《我养的修仙 AI 会渡劫》:我用 Trae 把它“说”出来了

我不是前端高手,也不是什么游戏开发大拿。可最近,我却亲手"整出来"了一款轻松搞笑的修仙养成类网页游戏,还被几个朋友夸"有点创意"。其实这事要搁以前,我是想都不敢想的。

关键的转折点,是我遇到了一个叫 Trae DE 的工具。简单说,它就是个"听你说话就能写代码"的开发平台。你把想法用人话说出来,它就能给你变成 HTML+JS 页面,甚至还能懂上下文、记得你前面说了什么,不用反复教,像个"全栈实习生"一样,听你指挥,靠谱干活。

这工具对我来说,简直是开启新世界的大门。

灵感起点:一个沙雕修仙 AI 的幻想

灵感来源其实很简单。前阵子看了一些"我养的 AI 会xxx"的段子,忽然灵光一闪:要不,我来做个我养的修仙 AI 会吐槽、会渡劫、会和别的 AI 打架的小游戏

你负责"发号施令",AI 就像个带主角光环的小沙雕修士一样,努力修炼、谈恋爱、被雷劈、被踢出门派,还边修炼边碎碎念你这个"幕后操盘手"......是不是有点意思?

我不懂 Vue,也懒得开 React 项目。我打开了 Trae,把我的想法往上一输,说了这么几句话:

请创建一个基于 HTML 和原生 JavaScript 的项目,名字叫做《我养的修仙 AI 会渡劫》。这个项目的核心玩法是:用户通过输入自然语言的"修仙指令"来操控一个 AI 修士的养成过程,包括闭关修炼、加入门派、渡劫突破、恋爱遇奇等情节发展。

Trae 读完后只回了句:

好的,用户想要创建一个基于HTML和原生JavaScript的项目,名字叫做《我养的修仙 AI 会渡劫》。核心玩法是用户通过输入自然语言的指令来操控AI修士的养成过程,包括修炼、加入门派、渡劫和恋爱等情节。首先,我需要确定项目的基本结构和所需文件。

我就这么看着它,真就自己开始搭框架了。

零代码搭建页面:我只负责开口,它全搞定

🧩 项目启动与基础页面搭建

💬「请创建一个基于 HTML 和原生 JavaScript 的项目,名字叫做《我养的修仙 AI 会渡劫》。这个项目的核心玩法是:用户通过输入自然语言的"修仙指令"来操控一个 AI 修士的养成过程,包括闭关修炼、加入门派、渡劫突破、恋爱遇奇等情节发展。」

💬「请搭建一个基础网页结构,分为三块区域:左边显示 AI 修士的基本信息,中间展示修炼日志与吐槽,右边是输入框和指令按钮,用于玩家发出指令。」

💬「页面整体风格保持简洁修真风,可使用淡色背景,字体使用'宋体'或无衬线字体,颜色偏古典柔和,像仙侠游戏那种。」

🧠 AI 修士人物数据初始化

💬「请为 AI 修士设定初始属性,包括:名字叫'莫问天',当前境界是'练气三层',心情为'有点紧张',当前状态为'闲着'。把这些数据渲染到左侧面板中。」

💬「增加一个 AI 修士的记忆数组,用来记录玩家输入过的每一条指令。之后玩家发出的每条操作都应被记录,并在必要时影响 AI 行为。」

🗣️ 自然语言指令处理逻辑

💬「实现一个基础的指令解析器,支持识别以下关键词:

  • 含有'闭关':状态改为'闭关修炼',心情改为'专注';
  • 含有'奇遇':状态改为'外出遇奇',心情改为'忐忑';
  • 含有'加入'和'门派':状态改为'新入门弟子',心情改为'兴奋';
  • 含有'渡劫':状态改为'天劫降临',心情为'紧张又期待'。」

💬「玩家每次输入指令后,AI 修士要在日志区回复一句'修真吐槽',内容结合当前行为。例如闭关时可以说:'又要闭关?这次至少别打断我三天。'」

📜 修炼日记与吐槽系统

💬「创建一个函数,每次玩家发出指令,AI 修士会自动生成一句日记内容和一句吐槽内容,按时间顺序显示在中间面板中。日记记录行为,吐槽可以带点个性,比如调侃玩家、自恋、摆烂、立志等。」

💬「吐槽内容风格偏轻松搞笑,比如遇奇时可以说'我是不是主角啊?怎么走路都能捡秘籍。'闭关时可以说'这次绝不出来,除非你安排个红颜知己来敲门。'」

⚔️ 门派大战与

💬「请设计一个简单机制,允许玩家输入指令如'发起门派大战',系统会随机生成一个敌对 AI 修士,与当前 AI 对战,并生成一段战斗剧情,比如嘴炮对骂+灵技对决。」

💬「战斗剧情支持段落式自动生成,比如:

  • 开场:'你竟然是魔道奸细!'
  • 中场:'他施展出《天魔指》,你急忙以《紫阳剑诀》抗衡......'
  • 结局:胜利或失败,伴随一段吐槽。」

利用 JueJin MCP 部署

通过 Trae 或其他支持 MCP 的 AI IDE 配置 MCP,并将前端项目(HTML/CSS/JS)一键发布到掘金的步骤。

访问链接:aicoding.juejin.cn/pens/751013...

用 Trae 开发的体验总结一句话:

我在写小说,它在写代码。

整个过程我几乎没动手写 HTML 和 JS,甚至连 div 和 span 都没想结构,Trae 都给我搭好了。我要的只是灵感、想法、剧本,而 Trae 做到了剩下的全部。

我说"加点吐槽",它吐槽;

我说"记仇",它真就记仇;

我说"给我一场感天动地的渡劫",它直接打雷劈我。

我从没想过,未来某天开发一款游戏,居然像在和一个懂我想法的"神仙实习生"聊天。而 Trae 就是这个"神仙实习生"。

写在最后

《我养的修仙 AI 会渡劫》可能只是个小型沙雕项目,但它让我第一次感受到:只靠人类语言,也可以"写出"一个完整的产品原型。 Trae AI 的底层机制,结合自然语言解析、MCP 上下文记忆和实时代码生成,正在改变整个创作逻辑。而我这个前端菜鸟,也终于能靠"开口"开发自己的游戏。修仙世界浩瀚如海,下一款作品------说不定是"我被 AI 带飞飞升了"。

如果你也想试试用"嘴"开发游戏,不妨来和 Trae 说两句。谁知道,下一位渡劫成功的修士,会不会就是你嘴里说出来的那个?😉

喜欢点赞哦:aicoding.juejin.cn/aicoding/wo...

源码分享

HTML

xml 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>我养的修仙 AI 会渡劫</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="main-layout">
        <div class="left-panel">
            <h2>AI 修士信息</h2>
            <ul>
                <li>名字:<span id="name">莫问天</span></li>
                <li>境界:<span id="realm">练气三层</span></li>
                <li>经验:<span id="exp">0</span></li>
                <li>心情:<span id="mood">有点紧张</span></li>
                <li>门派:<span id="sect">无</span></li>
                <li>情缘:<span id="love">无</span></li>
                <li>当前状态:<span id="state">闲着</span></li>
            </ul>
        </div>
        <div class="center-panel">
            <h2>修炼日志 & 吐槽</h2>
            <div id="messages" class="messages"></div>
        </div>
        <div class="right-panel">
            <h2>修仙指令</h2>
            <div class="command-buttons" style="display:flex;flex-wrap:wrap;gap:8px 8px;margin-bottom:16px;">
                <button class="cmd-btn" data-cmd="闭关修炼">闭关修炼</button>
                <button class="cmd-btn" data-cmd="外出奇遇">外出奇遇</button>
                <button class="cmd-btn" data-cmd="加入门派">加入门派</button>
                <button class="cmd-btn" data-cmd="渡劫突破">渡劫突破</button>
                <button class="cmd-btn" data-cmd="谈恋爱">谈恋爱</button>
                <button class="cmd-btn" data-cmd="发起门派大战">发起门派大战</button>
                <button class="cmd-btn" data-cmd="随便说点什么">随便说点什么</button>
            </div>
            <div class="input-area">
                <input type="text" id="user-input" placeholder="请输入修仙指令...">
                <button id="send-btn">发送</button>
            </div>
            <div class="command-tips">
                <div style="margin-top:18px;color:#b89b5e;font-size:15px;">指令示例:</div>
                <ul style="margin:8px 0 0 18px;padding:0;color:#7c6a4a;font-size:14px;line-height:1.8;">
                    <li>闭关修炼</li>
                    <li>外出奇遇</li>
                    <li>加入门派</li>
                    <li>渡劫突破</li>
                    <li>谈恋爱</li>
                    <li>随便说点什么</li>
                </ul>
            </div>
        </div>
    </div>
    <script src="game.js"></script>
</body>
</html> 

JS

ini 复制代码
// AI 修士初始状态
const aiState = {
  name: '莫问天',
  realm: '练气三层',
  exp: 0,
  mood: '有点紧张',
  sect: '无',
  love: '无',
  state: '闲着',
  memory: [],
};

const realms = ['练气三层', '筑基', '结丹', '元婴', '化神', '合体', '大乘', '渡劫', '飞升'];
const expThreshold = [100, 300, 800, 2000, 5000, 12000, 30000, 99999];

const messages = document.getElementById('messages');
const nameSpan = document.getElementById('name');
const realmSpan = document.getElementById('realm');
const expSpan = document.getElementById('exp');
const moodSpan = document.getElementById('mood');
const sectSpan = document.getElementById('sect');
const loveSpan = document.getElementById('love');
const stateSpan = document.getElementById('state');

function updateStatus() {
  nameSpan.textContent = aiState.name;
  realmSpan.textContent = aiState.realm;
  expSpan.textContent = aiState.exp;
  moodSpan.textContent = aiState.mood;
  sectSpan.textContent = aiState.sect;
  loveSpan.textContent = aiState.love;
  stateSpan.textContent = aiState.state;
}

function addMessage(text, isUser = false) {
  const div = document.createElement('div');
  div.textContent = (isUser ? '你:' : 'AI 修士:') + text;
  div.style.marginBottom = '8px';
  div.style.color = isUser ? '#6a4cff' : '#333';
  messages.appendChild(div);
  messages.scrollTop = messages.scrollHeight;
}

function handleCommand(cmd) {
  const lower = cmd.trim();
  // 记录玩家指令到记忆
  aiState.memory.push(lower);

  let actionType = '';
  let diary = '';
  // 门派大战机制
  if (lower.includes('门派大战')) {
      handleSectBattle();
      return;
  }
  // 基础指令解析器
  if (lower.includes('闭关')) {
      aiState.state = '闭关修炼';
      aiState.mood = '专注';
      const gain = Math.floor(Math.random() * 60) + 40;
      aiState.exp += gain;
      diary = `今日再次闭关修炼,获得${gain}点经验。`;
      checkBreakthrough();
      actionType = '闭关';
  } else if (lower.includes('奇遇')) {
      aiState.state = '外出遇奇';
      aiState.mood = '忐忑';
      diary = '今日外出,期待能有奇遇降临。';
      actionType = '奇遇';
  } else if (lower.includes('加入') && lower.includes('门派')) {
      aiState.state = '新入门弟子';
      aiState.mood = '兴奋';
      if (aiState.sect !== '无') {
          diary = '试图加入新门派,但我已经有门派了。';
      } else {
          const sects = ['青云宗', '天剑门', '丹霞谷', '魔音殿'];
          const chosen = sects[Math.floor(Math.random() * sects.length)];
          aiState.sect = chosen;
          diary = `今日加入${chosen},成为新入门弟子。`;
      }
      actionType = '门派';
  } else if (lower.includes('渡劫')) {
      aiState.state = '天劫降临';
      aiState.mood = '紧张又期待';
      if (aiState.realm === '渡劫') {
          const success = Math.random() < 0.7;
          if (success) {
              aiState.realm = '飞升';
              aiState.mood = '超脱';
              aiState.state = '飞升仙界';
              diary = '今日天劫降临,成功飞升仙界!';
          } else {
              aiState.mood = '虚弱';
              aiState.state = '渡劫失败';
              diary = '今日天劫降临,可惜失败了,只能休养生息。';
          }
      } else {
          diary = '尝试渡劫,但境界不够,失败。';
      }
      actionType = '渡劫';
  } else if (lower.includes('恋爱') || lower.includes('遇奇')) {
      if (aiState.love !== '无') {
          diary = '又遇情缘?可我已有心上人。';
      } else {
          const loves = ['神秘女修', '温柔师姐', '冷酷剑仙', '妖族公主'];
          const chosen = loves[Math.floor(Math.random() * loves.length)];
          aiState.love = chosen;
          aiState.mood = '欣喜';
          diary = `今日邂逅${chosen},心生情愫。`;
      }
      actionType = '恋爱';
  } else {
      diary = '收到一条不明指令,暂时无法理解。';
      actionType = '未知';
  }
  updateStatus();
  addDiaryAndTucao(diary, actionType);
}

function checkBreakthrough() {
  let idx = realms.indexOf(aiState.realm);
  if (idx < expThreshold.length && aiState.exp >= expThreshold[idx]) {
      aiState.exp = 0;
      aiState.realm = realms[idx + 1];
      aiState.mood = '突破喜悦';
      addMessage(`AI修士突破至${aiState.realm}!`);
  }
}

function addDiaryAndTucao(diary, type) {
  // 日记
  const now = new Date();
  const timeStr = now.toLocaleTimeString('zh-CN', { hour12: false });
  const diaryDiv = document.createElement('div');
  diaryDiv.textContent = `【${timeStr}】日记:${diary}`;
  diaryDiv.style.color = '#7c6a4a';
  messages.appendChild(diaryDiv);

  // 轻松搞笑吐槽
  let tucao = '';
  const tucaoList = {
      '闭关': [
          '这次绝不出来,除非你安排个红颜知己来敲门。',
          '闭关修炼,别来打扰我追剧!',
          '又闭关?我怀疑你是想让我变成老宅男。',
          '修炼千日,饿了怎么办?能点外卖吗?',
          '你是不是想让我一闭关就错过宗门大比?'
      ],
      '奇遇': [
          '我是不是主角啊?怎么走路都能捡秘籍。',
          '奇遇?上次差点踩到狗屎运,这次能不能来点真的?',
          '主角光环已上线,快给我安排个天降宝物!',
          '又遇奇遇?我怀疑你在开挂。',
          '走路遇奇遇,修仙界的路是不是太窄了?'
      ],
      '门派': [
          '新门派的规矩真多,能不能先发点入门礼包?',
          '拜师学艺,结果被安排去打杂,修仙界也内卷。',
          '我会不会成为宗门团宠?',
          '你选的门派不会太穷吧?要不换一个?',
          '入门第一天,师兄就让我请客吃饭。'
      ],
      '渡劫': [
          '天劫又来了,紧张得我都想请假。',
          '这次一定要挺过去,飞升后请你喝灵茶!',
          '要是有主角剧本就好了,直接无伤渡劫。',
          '你说我能不能靠卖萌混过天劫?',
          '天劫降临,在线等,挺急的。'
      ],
      '恋爱': [
          '修仙路上还能遇到情缘,难道我长得帅?',
          '谈恋爱会不会耽误修炼?还是修炼会耽误谈恋爱?',
          '你是不是想让我分心?我可不背锅。',
          '情劫难渡,能不能直接跳过?',
          '恋爱?我更想要一只灵宠。'
      ],
      '未知': [
          '修仙也有迷茫的时候,你到底想让我干啥?',
          '你这指令有点玄学,下次能不能详细点?',
          '我怀疑你在为难我,不过我不说。',
          '能不能说点我听得懂的?要不你来修仙?',
          '你是不是在考验我的悟性?'
      ]
  };
  const arr = tucaoList[type] || tucaoList['未知'];
  tucao = arr[Math.floor(Math.random() * arr.length)];
  const tucaoDiv = document.createElement('div');
  tucaoDiv.textContent = `【${timeStr}】吐槽:${tucao}`;
  tucaoDiv.style.color = '#b89b5e';
  tucaoDiv.style.marginBottom = '12px';
  messages.appendChild(tucaoDiv);
  messages.scrollTop = messages.scrollHeight;
}

function handleSectBattle() {
  const now = new Date();
  const timeStr = now.toLocaleTimeString('zh-CN', { hour12: false });
  // 随机生成敌对AI修士
  const enemyNames = ['李天霸', '赵无极', '苏小邪', '欧阳狂刀', '花满楼', '冷月心'];
  const enemySects = ['血影门', '黑风寨', '魔音殿', '天煞宗', '赤焰谷'];
  const enemySkills = ['天魔斩', '黑风指', '血影步', '赤焰掌', '魔音穿魂', '狂刀诀', '天魔指'];
  const mySkills = ['紫阳剑诀', '九天雷法', '青云步', '玄冰掌', '烈焰刀', '乾坤印'];
  const enemy = {
      name: enemyNames[Math.floor(Math.random() * enemyNames.length)],
      sect: enemySects[Math.floor(Math.random() * enemySects.length)],
      skill: enemySkills[Math.floor(Math.random() * enemySkills.length)]
  };
  const mySkill = mySkills[Math.floor(Math.random() * mySkills.length)];
  // 开场对白
  const openers = [
      `你竟然是${enemy.sect}的魔道奸细!`,
      `${enemy.name}冷笑道:"今日让你有来无回!"`,
      `场面剑拔弩张,空气中弥漫着火药味。`
  ];
  // 中场技能对决
  const midScenes = [
      `他施展出《${enemy.skill}》,你急忙以《${mySkill}》抗衡......`,
      `灵力激荡,天地变色,双方招式不断碰撞。`,
      `观战弟子屏息凝神,生怕错过任何一个细节。`
  ];
  // 随机胜负
  const win = Math.random() > 0.5;
  const winTucao = [
      '赢了!果然主角光环还是在我身上。',
      '哈哈,这波操作我给满分!',
      '对面是不是太菜了?',
      '扬名立万,今晚请自己喝奶茶!'
  ];
  const loseTucao = [
      '输了......下次一定要带外挂!',
      '对面开挂了吧?',
      '我怀疑你在故意整我。',
      '修仙路漫漫,今天先摆烂。'
  ];
  const result = win
      ? `最终,${aiState.name}技高一筹,击败了${enemy.name},扬名立万!`
      : `激战后,${aiState.name}惜败于${enemy.name},只能卧薪尝胆,来日再战。`;
  const tucao = win
      ? winTucao[Math.floor(Math.random() * winTucao.length)]
      : loseTucao[Math.floor(Math.random() * loseTucao.length)];
  // 日志输出
  const diary = `今日发起门派大战,对战${enemy.sect}修士${enemy.name}。`;
  const diaryDiv = document.createElement('div');
  diaryDiv.textContent = `【${timeStr}】日记:${diary}`;
  diaryDiv.style.color = '#7c6a4a';
  messages.appendChild(diaryDiv);
  // 剧情段落
  openers.forEach(line => {
      const lineDiv = document.createElement('div');
      lineDiv.textContent = `【${timeStr}】剧情:${line}`;
      lineDiv.style.color = '#b89b5e';
      messages.appendChild(lineDiv);
  });
  midScenes.forEach(line => {
      const lineDiv = document.createElement('div');
      lineDiv.textContent = `【${timeStr}】剧情:${line}`;
      lineDiv.style.color = '#b89b5e';
      messages.appendChild(lineDiv);
  });
  // 结局
  const resultDiv = document.createElement('div');
  resultDiv.textContent = `【${timeStr}】结果:${result}`;
  resultDiv.style.color = win ? '#4caf50' : '#f44336';
  messages.appendChild(resultDiv);
  // 搞笑吐槽
  const tucaoDiv = document.createElement('div');
  tucaoDiv.textContent = `【${timeStr}】吐槽:${tucao}`;
  tucaoDiv.style.color = '#b89b5e';
  tucaoDiv.style.marginBottom = '12px';
  messages.appendChild(tucaoDiv);
  messages.scrollTop = messages.scrollHeight;
}

// 指令按钮点击事件
window.onload = function() {
  updateStatus();
  document.querySelectorAll('.cmd-btn').forEach(btn => {
      btn.onclick = function() {
          const cmd = btn.getAttribute('data-cmd');
          addMessage(cmd, true);
          handleCommand(cmd);
      };
  });
};

document.getElementById('user-input').addEventListener('keydown', function(e) {
  if (e.key === 'Enter') {
      document.getElementById('send-btn').click();
  }
});

updateStatus(); 

CSS

css 复制代码
body {
    background: linear-gradient(120deg, #f8f6f0 0%, #e6e3d3 100%);
    font-family: 'SimSun', '宋体', 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
    margin: 0;
    padding: 0;
}
.container {
    max-width: 500px;
    margin: 40px auto;
    background: rgba(255,255,255,0.95);
    border-radius: 16px;
    box-shadow: 0 4px 24px rgba(0,0,0,0.12);
    padding: 32px 24px 24px 24px;
}
h1 {
    text-align: center;
    color: #6a4cff;
    margin-bottom: 24px;
    letter-spacing: 2px;
}
.status {
    background: #f3f0ff;
    border-radius: 10px;
    padding: 16px;
    margin-bottom: 20px;
    box-shadow: 0 2px 8px rgba(106,76,255,0.06);
}
.status ul {
    list-style: none;
    padding: 0;
    margin: 0;
}
.status li {
    margin: 8px 0;
    font-size: 16px;
}
#messages {
    min-height: 120px;
    max-height: 200px;
    overflow-y: auto;
    background: #f8fafd;
    border-radius: 8px;
    padding: 12px;
    margin-bottom: 18px;
    font-size: 15px;
    color: #333;
}
.input-area {
    display: flex;
    gap: 8px;
}
#user-input {
    flex: 1;
    padding: 10px;
    border-radius: 6px;
    border: 1px solid #bdbdbd;
    font-size: 15px;
}
#send-btn {
    background: #6a4cff;
    color: #fff;
    border: none;
    border-radius: 6px;
    padding: 0 18px;
    font-size: 15px;
    cursor: pointer;
    transition: background 0.2s;
}
#send-btn:hover {
    background: #4b2fd6;
}
.main-layout {
    display: flex;
    height: 100vh;
    box-sizing: border-box;
}
.left-panel, .center-panel, .right-panel {
    background: rgba(255,255,245,0.96);
    border-radius: 18px;
    box-shadow: 0 4px 24px rgba(180,160,120,0.08);
    margin: 24px 8px;
    padding: 24px 16px;
    display: flex;
    flex-direction: column;
    border: 1.5px solid #e2d6c2;
}
.left-panel {
    min-width: 180px;
    max-width: 220px;
    flex: 0 0 200px;
}
.center-panel {
    flex: 1 1 0;
    margin-left: 0;
    margin-right: 0;
    min-width: 260px;
}
.right-panel {
    min-width: 180px;
    max-width: 240px;
    flex: 0 0 220px;
    align-items: flex-end;
    justify-content: flex-end;
}
.left-panel h2, .center-panel h2, .right-panel h2 {
    text-align: center;
    color: #b89b5e;
    margin-bottom: 18px;
    letter-spacing: 2px;
    font-weight: normal;
    font-family: 'SimSun', '宋体', 'Microsoft YaHei', Arial, sans-serif;
    border-bottom: 1px solid #e2d6c2;
    padding-bottom: 6px;
    background: linear-gradient(90deg, #f7ecd6 0%, #f3f0e6 100%);
    border-radius: 8px 8px 0 0;
}
.left-panel ul {
    list-style: none;
    padding: 0;
    margin: 0;
}
.left-panel li {
    margin: 10px 0;
    font-size: 16px;
    color: #7c6a4a;
    letter-spacing: 1px;
}
#messages {
    min-height: 200px;
    max-height: 60vh;
    overflow-y: auto;
    background: #f7f3e9;
    border-radius: 8px;
    padding: 12px;
    font-size: 15px;
    color: #5c4a2a;
    flex: 1 1 0;
    border: 1px solid #e2d6c2;
    font-family: 'SimSun', '宋体', 'Microsoft YaHei', Arial, sans-serif;
}
.input-area {
    display: flex;
    gap: 8px;
    margin-top: 20px;
}
#user-input {
    flex: 1;
    padding: 10px;
    border-radius: 6px;
    border: 1px solid #d6c7a6;
    font-size: 15px;
    background: #f9f7f2;
    color: #7c6a4a;
    font-family: 'SimSun', '宋体', 'Microsoft YaHei', Arial, sans-serif;
}
#send-btn {
    background: linear-gradient(90deg, #e2d6c2 0%, #cfc2a0 100%);
    color: #7c6a4a;
    border: none;
    border-radius: 6px;
    padding: 0 18px;
    font-size: 15px;
    cursor: pointer;
    transition: background 0.2s, color 0.2s;
    font-family: 'SimSun', '宋体', 'Microsoft YaHei', Arial, sans-serif;
    box-shadow: 0 2px 8px rgba(180,160,120,0.08);
}
#send-btn:hover {
    background: linear-gradient(90deg, #cfc2a0 0%, #e2d6c2 100%);
    color: #b89b5e;
}
@media (max-width: 900px) {
    .main-layout {
        flex-direction: column;
        height: auto;
    }
    .left-panel, .center-panel, .right-panel {
        max-width: 100%;
        margin: 12px 8px;
    }
    .right-panel {
        align-items: stretch;
        justify-content: flex-start;
    }
} 
相关推荐
BNTang8 小时前
AI编码焕新:用Context7
mcp
coder_pig8 小时前
Coze+Trae+掘金MCP = "✨掘金微热榜"
coze·mcp·trae
Captaincc9 小时前
探索“Vibe Coding”:AI驱动的编码新风潮
ai编程
ZHOU_WUYI11 小时前
吴恩达MCP课程(5):research_server_prompt_resource.py
agent·mcp
偶尔的鱼11 小时前
AI Agent 框架大盘点:Coze、Dify 到 LangChain,哪款是你的菜?
前端·github·ai编程
量子位12 小时前
00 后中国女孩 0 产品创业实现 3 亿估值:斯坦福数学博士的 AI 量化野心
ai编程
盏灯12 小时前
国产❓Trae ❓收费❓❗︎
trae
lecepin12 小时前
AI Coding 资讯 2025-06-04
ai编程
石小石Orz13 小时前
浏览器指纹-探究前端如何识别用户设备
trae
量子位13 小时前
ChatGPT 普通会员能用编程神器 Codex 了!支持联网,奥特曼:更多更新在路上
chatgpt·ai编程