2026-01-18 10:24:35 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<div class="ai-help-demo">
|
|
|
|
|
|
<div class="desktop-container">
|
|
|
|
|
|
<!-- 1. VS Code 窗口 (全功能模拟) -->
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div
|
|
|
|
|
|
class="window vscode"
|
|
|
|
|
|
:class="getWindowClass('vscode')"
|
|
|
|
|
|
>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
<!-- 标题栏 -->
|
|
|
|
|
|
<div class="title-bar">
|
|
|
|
|
|
<div class="controls">
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<span class="dot red" />
|
|
|
|
|
|
<span class="dot yellow" />
|
|
|
|
|
|
<span class="dot green" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="title-text">
|
|
|
|
|
|
App.vue - easy-vibe - Visual Studio Code
|
2026-01-18 10:24:35 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="main-layout">
|
|
|
|
|
|
<!-- 侧边栏 (Activity Bar) -->
|
|
|
|
|
|
<div class="activity-bar">
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div class="icon active">
|
|
|
|
|
|
📁
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="icon">
|
|
|
|
|
|
🔍
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="icon">
|
|
|
|
|
|
🌿
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="icon">
|
|
|
|
|
|
🐛
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="icon">
|
|
|
|
|
|
🧩
|
|
|
|
|
|
</div>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
</div>
|
2026-01-18 12:21:49 +08:00
|
|
|
|
|
2026-01-18 10:24:35 +08:00
|
|
|
|
<!-- 资源管理器 (Sidebar) -->
|
|
|
|
|
|
<div class="sidebar">
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div class="sidebar-title">
|
|
|
|
|
|
EXPLORER
|
|
|
|
|
|
</div>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
<div class="file-tree">
|
|
|
|
|
|
<div class="tree-item expanded">
|
|
|
|
|
|
<span class="arrow">▼</span> src
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="tree-item indent">
|
|
|
|
|
|
<span class="icon">📄</span> main.js
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="tree-item indent active">
|
|
|
|
|
|
<span class="icon">V</span> App.vue
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="tree-item indent">
|
|
|
|
|
|
<span class="icon">🎨</span> style.css
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 编辑器区域 -->
|
|
|
|
|
|
<div class="editor-area">
|
|
|
|
|
|
<div class="tab-bar">
|
|
|
|
|
|
<div class="tab active">
|
|
|
|
|
|
<span class="icon">V</span> App.vue <span class="close">×</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="code-content">
|
|
|
|
|
|
<div class="line-numbers">
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div
|
|
|
|
|
|
v-for="n in 15"
|
|
|
|
|
|
:key="n"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ n }}
|
|
|
|
|
|
</div>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="code-lines">
|
2026-01-18 12:21:49 +08:00
|
|
|
|
<div class="line">
|
|
|
|
|
|
<span class="kwd">import</span> {
|
|
|
|
|
|
<span class="var">ref</span>,
|
|
|
|
|
|
<span class="var">onMounted</span>,
|
|
|
|
|
|
<span class="var">nextTick</span> }
|
|
|
|
|
|
<span class="kwd">from</span> <span class="str">'vue'</span>
|
|
|
|
|
|
</div>
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div class="line" />
|
2026-01-18 12:21:49 +08:00
|
|
|
|
<div class="line">
|
|
|
|
|
|
<span class="kwd">const</span>
|
|
|
|
|
|
<span class="var">chartRef</span> =
|
|
|
|
|
|
<span class="func">ref</span>(<span class="kwd">null</span>)
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="line">
|
|
|
|
|
|
<span class="kwd">const</span> <span class="var">data</span> =
|
|
|
|
|
|
<span class="func">ref</span>([])
|
|
|
|
|
|
</div>
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div class="line" />
|
2026-01-18 12:21:49 +08:00
|
|
|
|
<div class="line">
|
|
|
|
|
|
<span class="kwd">const</span>
|
|
|
|
|
|
<span class="func">initChart</span> =
|
|
|
|
|
|
<span class="kwd">async</span> () => {
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="line">
|
|
|
|
|
|
<span class="comment">// 等待数据加载完成</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="line">
|
|
|
|
|
|
<span class="kwd">await</span>
|
|
|
|
|
|
<span class="func">fetchData</span>()
|
|
|
|
|
|
</div>
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div class="line">
|
|
|
|
|
|
|
2026-01-18 10:24:35 +08:00
|
|
|
|
</div>
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div
|
|
|
|
|
|
ref="targetCode"
|
|
|
|
|
|
class="line"
|
|
|
|
|
|
>
|
|
|
|
|
|
<span class="comment">// 👈 等待 DOM 更新后再渲染图表</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div
|
|
|
|
|
|
ref="targetCode2"
|
|
|
|
|
|
class="line"
|
|
|
|
|
|
>
|
2026-01-18 12:21:49 +08:00
|
|
|
|
<span class="kwd">await</span>
|
|
|
|
|
|
<span class="func">nextTick</span>()
|
2026-01-18 10:24:35 +08:00
|
|
|
|
</div>
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div class="line">
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
2026-01-18 12:21:49 +08:00
|
|
|
|
<div class="line">
|
|
|
|
|
|
<span class="kwd">const</span>
|
|
|
|
|
|
<span class="var">chart</span> =
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<span class="var">echarts</span>.<span class="func">init</span>(<span class="var">chartRef</span>.<span class="var">value</span>)
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="line">
|
|
|
|
|
|
<span class="var">chart</span>.<span class="func">setOption</span>({ ... })
|
2026-01-18 12:21:49 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="line">
|
2026-02-18 17:38:10 +08:00
|
|
|
|
}
|
2026-01-18 12:21:49 +08:00
|
|
|
|
</div>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 截图选框 (Overlay) - Moved to main-layout level -->
|
2026-01-18 12:21:49 +08:00
|
|
|
|
<div
|
|
|
|
|
|
v-if="step === 'selecting' || step === 'captured'"
|
2026-02-18 17:38:10 +08:00
|
|
|
|
class="screenshot-overlay"
|
2026-01-18 12:21:49 +08:00
|
|
|
|
>
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="selection-box"
|
|
|
|
|
|
:class="{ flashed: step === 'captured' }"
|
|
|
|
|
|
>
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div class="selection-handle top-left" />
|
|
|
|
|
|
<div class="selection-handle top-right" />
|
|
|
|
|
|
<div class="selection-handle bottom-left" />
|
|
|
|
|
|
<div class="selection-handle bottom-right" />
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-if="step === 'selecting'"
|
|
|
|
|
|
class="cursor-crosshair"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-if="step === 'selecting'"
|
|
|
|
|
|
class="selection-size"
|
|
|
|
|
|
>
|
2026-01-18 12:21:49 +08:00
|
|
|
|
220 × 350
|
|
|
|
|
|
</div>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 模拟操作引导 -->
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div
|
|
|
|
|
|
v-if="step === 'idle'"
|
|
|
|
|
|
class="guide-overlay"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="start-btn"
|
|
|
|
|
|
@click="startDemo"
|
|
|
|
|
|
>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
<span>📸 演示:遇到代码不懂怎么问 AI?</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 2. ChatGPT 窗口 -->
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div
|
|
|
|
|
|
class="window chatgpt"
|
|
|
|
|
|
:class="getWindowClass('chatgpt')"
|
|
|
|
|
|
>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
<div class="chat-sidebar">
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div class="new-chat">
|
|
|
|
|
|
+ New chat
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="history-item">
|
|
|
|
|
|
Previous 7 Days
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="history-item active">
|
|
|
|
|
|
Vue nextTick explanation
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="history-item">
|
|
|
|
|
|
CSS Grid layout
|
|
|
|
|
|
</div>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="chat-main">
|
|
|
|
|
|
<div class="chat-model-selector">
|
|
|
|
|
|
<span>GPT-4o</span> <span class="arrow">▼</span>
|
|
|
|
|
|
</div>
|
2026-01-18 12:21:49 +08:00
|
|
|
|
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div
|
|
|
|
|
|
ref="messagesContainer"
|
|
|
|
|
|
class="messages-container"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-if="stepInt >= 5"
|
|
|
|
|
|
class="msg-row user"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="avatar">
|
|
|
|
|
|
U
|
|
|
|
|
|
</div>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
<div class="msg-bubble">
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div
|
|
|
|
|
|
v-if="stepInt >= 5"
|
|
|
|
|
|
class="pasted-image"
|
|
|
|
|
|
>
|
2026-01-18 12:21:49 +08:00
|
|
|
|
<div class="ui-snapshot">
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div class="snapshot-rect menu-rect" />
|
|
|
|
|
|
<div class="snapshot-text">
|
|
|
|
|
|
Menu Bar.png
|
|
|
|
|
|
</div>
|
2026-01-18 12:21:49 +08:00
|
|
|
|
</div>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
</div>
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div class="msg-text">
|
|
|
|
|
|
{{ typedText }}
|
|
|
|
|
|
</div>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div
|
|
|
|
|
|
v-if="stepInt >= 7"
|
|
|
|
|
|
class="msg-row ai"
|
|
|
|
|
|
>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
<div class="avatar gpt">
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<svg
|
|
|
|
|
|
viewBox="0 0 41 41"
|
|
|
|
|
|
class="gpt-logo"
|
|
|
|
|
|
>
|
2026-01-18 12:21:49 +08:00
|
|
|
|
<path
|
|
|
|
|
|
d="M37.532 16.87a9.963 9.963 0 00-.856-8.184c-3.15-5.49-10.25-7.38-15.738-4.23-.718.412-1.35.914-1.896 1.488a9.965 9.965 0 00-7.144-1.156 9.972 9.972 0 00-6.73 4.966c-3.15 5.49-1.26 12.59 4.23 15.738.412.237.854.43 1.306.586a9.963 9.963 0 00.856 8.184c3.15 5.49 10.25 7.38 15.738 4.23.718-.412 1.35-.914 1.896-1.488a9.965 9.965 0 007.144 1.156 9.972 9.972 0 006.73-4.966c3.15-5.49 1.26-12.59-4.23-15.738a9.953 9.953 0 00-1.306-.586zM20.5 29.5a9 9 0 110-18 9 9 0 010 18z"
|
|
|
|
|
|
fill="currentColor"
|
2026-02-18 17:38:10 +08:00
|
|
|
|
/>
|
2026-01-18 12:21:49 +08:00
|
|
|
|
</svg>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="msg-bubble ai-bubble">
|
2026-01-18 12:21:49 +08:00
|
|
|
|
<p>
|
|
|
|
|
|
这是 VS Code 的
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<strong>顶部菜单栏 (Menu Bar)</strong>,包含了软件的所有功能入口。
|
2026-01-18 12:21:49 +08:00
|
|
|
|
</p>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
<p><strong>常用菜单解释:</strong></p>
|
|
|
|
|
|
<ul>
|
2026-01-18 12:21:49 +08:00
|
|
|
|
<li>
|
|
|
|
|
|
<strong>File (文件)</strong>:新建、打开、保存文件或项目。
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li>
|
|
|
|
|
|
<strong>Edit (编辑)</strong>:复制粘贴、查找替换、撤销重做。
|
|
|
|
|
|
</li>
|
|
|
|
|
|
<li>
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<strong>View (视图)</strong>:控制界面显示,比如打开侧边栏、终端等。
|
2026-01-18 12:21:49 +08:00
|
|
|
|
</li>
|
|
|
|
|
|
<li>
|
|
|
|
|
|
<strong>Terminal (终端)</strong>:打开内置命令行工具。
|
|
|
|
|
|
</li>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
</ul>
|
2026-01-18 12:21:49 +08:00
|
|
|
|
<p>
|
|
|
|
|
|
💡 <strong>小技巧</strong>:如果不记得某个功能在哪,可以按
|
|
|
|
|
|
<code>F1</code> 或
|
|
|
|
|
|
<code>Ctrl+Shift+P</code> 打开命令面板直接搜索功能名字!
|
|
|
|
|
|
</p>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="chat-input-area">
|
|
|
|
|
|
<div class="input-wrapper">
|
2026-01-18 12:21:49 +08:00
|
|
|
|
<div
|
|
|
|
|
|
v-if="stepInt === 4 || (stepInt === 5 && isTyping)"
|
2026-02-18 17:38:10 +08:00
|
|
|
|
class="input-preview"
|
2026-01-18 12:21:49 +08:00
|
|
|
|
>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
<div class="mini-snapshot-ui">
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div class="mini-menu-rect" />
|
2026-01-18 10:24:35 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="fake-input">
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<span
|
|
|
|
|
|
v-if="stepInt < 5"
|
|
|
|
|
|
class="placeholder"
|
|
|
|
|
|
>Message ChatGPT...</span>
|
|
|
|
|
|
<span
|
|
|
|
|
|
v-else
|
|
|
|
|
|
class="typing-text"
|
|
|
|
|
|
>{{ typedText
|
|
|
|
|
|
}}<span
|
|
|
|
|
|
v-if="isTyping"
|
|
|
|
|
|
class="cursor"
|
|
|
|
|
|
>|</span></span>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
</div>
|
2026-01-18 12:21:49 +08:00
|
|
|
|
<button
|
|
|
|
|
|
class="send-btn"
|
|
|
|
|
|
:class="{ active: typedText.length > 5 }"
|
|
|
|
|
|
>
|
|
|
|
|
|
↑
|
|
|
|
|
|
</button>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-01-18 12:21:49 +08:00
|
|
|
|
|
2026-01-18 10:24:35 +08:00
|
|
|
|
<!-- 全局重置按钮 -->
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<button
|
|
|
|
|
|
v-if="step === 'finished'"
|
|
|
|
|
|
class="reset-btn"
|
|
|
|
|
|
@click="reset"
|
|
|
|
|
|
>
|
2026-01-18 10:24:35 +08:00
|
|
|
|
🔄 重播
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
|
import { ref, computed } from 'vue'
|
|
|
|
|
|
|
|
|
|
|
|
// 状态机
|
|
|
|
|
|
// idle: 初始状态
|
|
|
|
|
|
// selecting: 正在截图(选框出现)
|
|
|
|
|
|
// captured: 截图完成(闪烁)
|
|
|
|
|
|
// switching: 窗口切换中
|
|
|
|
|
|
// pasting: ChatGPT 界面,显示输入动作
|
|
|
|
|
|
// typing: 正在打字
|
|
|
|
|
|
// sending: 发送中
|
|
|
|
|
|
// responding: AI 回复中
|
|
|
|
|
|
// finished: 结束
|
|
|
|
|
|
const step = ref('idle')
|
|
|
|
|
|
const typedText = ref('')
|
|
|
|
|
|
const isTyping = ref(false)
|
|
|
|
|
|
|
|
|
|
|
|
const stepInt = computed(() => {
|
|
|
|
|
|
const map = {
|
|
|
|
|
|
idle: 0,
|
|
|
|
|
|
selecting: 1,
|
|
|
|
|
|
captured: 2,
|
|
|
|
|
|
switching: 3,
|
|
|
|
|
|
pasting: 4,
|
|
|
|
|
|
typing: 5,
|
|
|
|
|
|
sending: 6,
|
|
|
|
|
|
responding: 7,
|
|
|
|
|
|
finished: 8
|
|
|
|
|
|
}
|
|
|
|
|
|
return map[step.value] || 0
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const getWindowClass = (winName) => {
|
|
|
|
|
|
if (winName === 'vscode') {
|
|
|
|
|
|
if (stepInt.value < 3) return 'active'
|
|
|
|
|
|
if (stepInt.value === 3) return 'inactive zoom-out'
|
|
|
|
|
|
return 'inactive hidden'
|
|
|
|
|
|
}
|
|
|
|
|
|
if (winName === 'chatgpt') {
|
|
|
|
|
|
if (stepInt.value < 3) return 'inactive hidden'
|
|
|
|
|
|
if (stepInt.value === 3) return 'active zoom-in'
|
|
|
|
|
|
return 'active'
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const startDemo = async () => {
|
|
|
|
|
|
step.value = 'selecting'
|
2026-01-18 12:21:49 +08:00
|
|
|
|
|
2026-01-18 10:24:35 +08:00
|
|
|
|
// 1. 模拟截图过程 (1.5s)
|
|
|
|
|
|
await wait(1500)
|
|
|
|
|
|
step.value = 'captured'
|
2026-01-18 12:21:49 +08:00
|
|
|
|
|
2026-01-18 10:24:35 +08:00
|
|
|
|
// 2. 截图闪烁确认 (0.5s)
|
|
|
|
|
|
await wait(600)
|
2026-01-18 12:21:49 +08:00
|
|
|
|
|
2026-01-18 10:24:35 +08:00
|
|
|
|
// 3. 窗口切换 (0.8s)
|
|
|
|
|
|
step.value = 'switching'
|
|
|
|
|
|
await wait(800)
|
2026-01-18 12:21:49 +08:00
|
|
|
|
|
2026-01-18 10:24:35 +08:00
|
|
|
|
// 4. ChatGPT 界面准备 (粘贴动作)
|
|
|
|
|
|
step.value = 'pasting'
|
|
|
|
|
|
await wait(800)
|
2026-01-18 12:21:49 +08:00
|
|
|
|
|
2026-01-18 10:24:35 +08:00
|
|
|
|
// 5. 打字
|
|
|
|
|
|
step.value = 'typing'
|
|
|
|
|
|
isTyping.value = true
|
2026-01-18 12:21:49 +08:00
|
|
|
|
const question = '帮我看下这张图,左边红框里那一块是干嘛用的?'
|
2026-01-18 10:24:35 +08:00
|
|
|
|
for (let i = 0; i < question.length; i++) {
|
|
|
|
|
|
typedText.value += question[i]
|
|
|
|
|
|
await wait(50)
|
|
|
|
|
|
}
|
|
|
|
|
|
isTyping.value = false
|
|
|
|
|
|
await wait(300)
|
2026-01-18 12:21:49 +08:00
|
|
|
|
|
2026-01-18 10:24:35 +08:00
|
|
|
|
// 6. 发送
|
|
|
|
|
|
step.value = 'sending'
|
|
|
|
|
|
await wait(500)
|
2026-01-18 12:21:49 +08:00
|
|
|
|
|
2026-01-18 10:24:35 +08:00
|
|
|
|
// 7. AI 回复
|
|
|
|
|
|
step.value = 'responding'
|
|
|
|
|
|
await wait(2500) // 模拟阅读时间
|
2026-01-18 12:21:49 +08:00
|
|
|
|
|
2026-01-18 10:24:35 +08:00
|
|
|
|
step.value = 'finished'
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const reset = () => {
|
|
|
|
|
|
step.value = 'idle'
|
|
|
|
|
|
typedText.value = ''
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-18 12:21:49 +08:00
|
|
|
|
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
|
2026-01-18 10:24:35 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
.ai-help-demo {
|
|
|
|
|
|
margin: 40px 0;
|
|
|
|
|
|
perspective: 1000px;
|
2026-01-18 12:21:49 +08:00
|
|
|
|
font-family:
|
|
|
|
|
|
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
|
|
|
|
|
|
Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
2026-01-18 10:24:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.desktop-container {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 400px; /* 增加高度以容纳更多内容 */
|
|
|
|
|
|
background: #333; /* 桌面背景 */
|
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
overflow: hidden;
|
2026-01-18 12:21:49 +08:00
|
|
|
|
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.3);
|
2026-01-18 10:24:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 通用窗口样式 */
|
|
|
|
|
|
.window {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 5%;
|
|
|
|
|
|
left: 5%;
|
|
|
|
|
|
width: 90%;
|
|
|
|
|
|
height: 90%;
|
2026-02-14 20:23:34 +08:00
|
|
|
|
border-radius: 6px;
|
2026-01-18 12:21:49 +08:00
|
|
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
2026-01-18 10:24:35 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1);
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 窗口状态动画 */
|
|
|
|
|
|
.window.active {
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
transform: scale(1);
|
|
|
|
|
|
z-index: 2;
|
|
|
|
|
|
filter: blur(0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.window.inactive {
|
|
|
|
|
|
opacity: 0;
|
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
|
z-index: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.window.zoom-out {
|
|
|
|
|
|
transform: scale(0.9);
|
|
|
|
|
|
opacity: 0;
|
|
|
|
|
|
filter: blur(2px);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.window.zoom-in {
|
|
|
|
|
|
animation: zoomIn 0.5s forwards;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@keyframes zoomIn {
|
2026-01-18 12:21:49 +08:00
|
|
|
|
from {
|
|
|
|
|
|
transform: scale(1.1);
|
|
|
|
|
|
opacity: 0;
|
|
|
|
|
|
filter: blur(4px);
|
|
|
|
|
|
}
|
|
|
|
|
|
to {
|
|
|
|
|
|
transform: scale(1);
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
filter: blur(0);
|
|
|
|
|
|
}
|
2026-01-18 10:24:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ================= VS Code 样式 ================= */
|
|
|
|
|
|
.vscode {
|
|
|
|
|
|
background: #1e1e1e;
|
|
|
|
|
|
color: #ccc;
|
|
|
|
|
|
font-family: 'Consolas', 'Monaco', monospace;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.title-bar {
|
|
|
|
|
|
height: 30px;
|
|
|
|
|
|
background: #252526;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 0 10px;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: #999;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-18 12:21:49 +08:00
|
|
|
|
.controls {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 6px;
|
|
|
|
|
|
margin-right: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.dot {
|
|
|
|
|
|
width: 10px;
|
|
|
|
|
|
height: 10px;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
}
|
|
|
|
|
|
.red {
|
|
|
|
|
|
background: #ff5f56;
|
|
|
|
|
|
}
|
|
|
|
|
|
.yellow {
|
|
|
|
|
|
background: #ffbd2e;
|
|
|
|
|
|
}
|
|
|
|
|
|
.green {
|
|
|
|
|
|
background: #27c93f;
|
|
|
|
|
|
}
|
2026-01-18 10:24:35 +08:00
|
|
|
|
|
2026-01-18 12:21:49 +08:00
|
|
|
|
.main-layout {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
2026-01-18 10:24:35 +08:00
|
|
|
|
|
|
|
|
|
|
.activity-bar {
|
|
|
|
|
|
width: 40px;
|
|
|
|
|
|
background: #333;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding-top: 10px;
|
|
|
|
|
|
gap: 15px;
|
|
|
|
|
|
}
|
2026-01-18 12:21:49 +08:00
|
|
|
|
.activity-bar .icon {
|
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
opacity: 0.5;
|
|
|
|
|
|
filter: grayscale(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
.activity-bar .icon.active {
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
border-left: 2px solid white;
|
|
|
|
|
|
filter: grayscale(0);
|
|
|
|
|
|
}
|
2026-01-18 10:24:35 +08:00
|
|
|
|
|
|
|
|
|
|
.sidebar {
|
|
|
|
|
|
width: 180px;
|
|
|
|
|
|
background: #252526;
|
|
|
|
|
|
border-right: 1px solid #1e1e1e;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: #ccc;
|
|
|
|
|
|
}
|
2026-01-18 12:21:49 +08:00
|
|
|
|
.sidebar-title {
|
|
|
|
|
|
padding: 10px;
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.tree-item {
|
|
|
|
|
|
padding: 4px 10px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 6px;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
.tree-item.active {
|
|
|
|
|
|
background: #37373d;
|
|
|
|
|
|
}
|
|
|
|
|
|
.tree-item.indent {
|
|
|
|
|
|
padding-left: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.tree-item .arrow {
|
|
|
|
|
|
font-size: 10px;
|
|
|
|
|
|
color: #999;
|
|
|
|
|
|
}
|
2026-01-18 10:24:35 +08:00
|
|
|
|
|
2026-01-18 12:21:49 +08:00
|
|
|
|
.editor-area {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
background: #1e1e1e;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
}
|
|
|
|
|
|
.tab-bar {
|
|
|
|
|
|
height: 35px;
|
|
|
|
|
|
background: #252526;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
}
|
2026-01-18 10:24:35 +08:00
|
|
|
|
.tab {
|
|
|
|
|
|
background: #1e1e1e;
|
|
|
|
|
|
padding: 0 15px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
border-top: 1px solid #007acc;
|
|
|
|
|
|
}
|
2026-01-18 12:21:49 +08:00
|
|
|
|
.tab .close {
|
|
|
|
|
|
margin-left: 8px;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
}
|
2026-01-18 10:24:35 +08:00
|
|
|
|
|
|
|
|
|
|
.code-content {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
padding: 10px 0;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
line-height: 20px;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
}
|
|
|
|
|
|
.line-numbers {
|
|
|
|
|
|
width: 40px;
|
|
|
|
|
|
text-align: right;
|
|
|
|
|
|
padding-right: 15px;
|
|
|
|
|
|
color: #6e7681;
|
|
|
|
|
|
user-select: none;
|
|
|
|
|
|
}
|
2026-01-18 12:21:49 +08:00
|
|
|
|
.code-lines {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
padding-left: 5px;
|
|
|
|
|
|
}
|
2026-01-18 10:24:35 +08:00
|
|
|
|
|
|
|
|
|
|
/* 语法高亮 */
|
2026-01-18 12:21:49 +08:00
|
|
|
|
.kwd {
|
|
|
|
|
|
color: #569cd6;
|
|
|
|
|
|
}
|
|
|
|
|
|
.var {
|
|
|
|
|
|
color: #9cdcfe;
|
|
|
|
|
|
}
|
|
|
|
|
|
.func {
|
|
|
|
|
|
color: #dcdcaa;
|
|
|
|
|
|
}
|
|
|
|
|
|
.str {
|
|
|
|
|
|
color: #ce9178;
|
|
|
|
|
|
}
|
|
|
|
|
|
.comment {
|
|
|
|
|
|
color: #6a9955;
|
|
|
|
|
|
}
|
2026-01-18 10:24:35 +08:00
|
|
|
|
|
|
|
|
|
|
/* 截图覆盖层 */
|
|
|
|
|
|
.screenshot-overlay {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
2026-01-18 12:21:49 +08:00
|
|
|
|
background: rgba(0, 0, 0, 0.3);
|
2026-01-18 10:24:35 +08:00
|
|
|
|
z-index: 10;
|
|
|
|
|
|
cursor: crosshair;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.selection-box {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 40px; /* 覆盖左侧 Sidebar */
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
width: 280px;
|
|
|
|
|
|
height: 320px;
|
|
|
|
|
|
border: 3px solid #ff5f56; /* 醒目的红框 */
|
|
|
|
|
|
background: rgba(255, 95, 86, 0.1);
|
2026-01-18 12:21:49 +08:00
|
|
|
|
box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.5); /* 遮罩效果 */
|
2026-01-18 10:24:35 +08:00
|
|
|
|
animation: selectAnim 0.5s ease-out;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.selection-box.flashed {
|
|
|
|
|
|
animation: flash 0.3s;
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.3);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@keyframes selectAnim {
|
2026-01-18 12:21:49 +08:00
|
|
|
|
from {
|
|
|
|
|
|
width: 0;
|
|
|
|
|
|
height: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
to {
|
|
|
|
|
|
width: 280px;
|
|
|
|
|
|
height: 320px;
|
|
|
|
|
|
}
|
2026-01-18 10:24:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@keyframes flash {
|
2026-01-18 12:21:49 +08:00
|
|
|
|
0% {
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.8);
|
|
|
|
|
|
}
|
|
|
|
|
|
100% {
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.1);
|
|
|
|
|
|
}
|
2026-01-18 10:24:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.selection-size {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
bottom: -20px;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
background: #ff5f56;
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
font-size: 10px;
|
|
|
|
|
|
padding: 2px 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* UI Snapshot Styling */
|
|
|
|
|
|
.ui-snapshot {
|
|
|
|
|
|
background: #252526;
|
|
|
|
|
|
padding: 8px;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.snapshot-rect {
|
|
|
|
|
|
width: 30px;
|
|
|
|
|
|
height: 20px;
|
|
|
|
|
|
border: 2px solid #ff5f56;
|
|
|
|
|
|
background: rgba(255, 95, 86, 0.2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.snapshot-text {
|
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
|
color: #ccc;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.mini-snapshot-ui {
|
|
|
|
|
|
width: 40px;
|
|
|
|
|
|
height: 30px;
|
|
|
|
|
|
background: #252526;
|
|
|
|
|
|
border: 1px solid #565869;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
.mini-rect {
|
|
|
|
|
|
width: 20px;
|
|
|
|
|
|
height: 14px;
|
|
|
|
|
|
border: 1px solid #ff5f56;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ================= ChatGPT 样式 ================= */
|
|
|
|
|
|
.chatgpt {
|
|
|
|
|
|
background: #343541;
|
|
|
|
|
|
color: #ececf1;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.chat-sidebar {
|
|
|
|
|
|
width: 200px;
|
|
|
|
|
|
background: #202123;
|
|
|
|
|
|
padding: 10px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.new-chat {
|
|
|
|
|
|
border: 1px solid #565869;
|
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
|
padding: 10px;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
text-align: left;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
.history-item {
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
color: #ececf1;
|
|
|
|
|
|
padding: 8px;
|
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
}
|
2026-01-18 12:21:49 +08:00
|
|
|
|
.history-item.active {
|
|
|
|
|
|
background: #343541;
|
|
|
|
|
|
}
|
2026-01-18 10:24:35 +08:00
|
|
|
|
|
|
|
|
|
|
.chat-main {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
background: #343541;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.chat-model-selector {
|
|
|
|
|
|
height: 40px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 0 20px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #d2d6db;
|
2026-01-18 12:21:49 +08:00
|
|
|
|
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
2026-01-18 10:24:35 +08:00
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.messages-container {
|
|
|
|
|
|
flex: 1;
|
2026-02-14 20:23:34 +08:00
|
|
|
|
|
2026-01-18 10:24:35 +08:00
|
|
|
|
padding: 20px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.msg-row {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 15px;
|
|
|
|
|
|
max-width: 80%;
|
|
|
|
|
|
}
|
2026-01-18 12:21:49 +08:00
|
|
|
|
.msg-row.user {
|
|
|
|
|
|
align-self: flex-end;
|
|
|
|
|
|
flex-direction: row-reverse;
|
|
|
|
|
|
}
|
|
|
|
|
|
.msg-row.ai {
|
|
|
|
|
|
align-self: flex-start;
|
|
|
|
|
|
}
|
2026-01-18 10:24:35 +08:00
|
|
|
|
|
|
|
|
|
|
.avatar {
|
|
|
|
|
|
width: 30px;
|
|
|
|
|
|
height: 30px;
|
|
|
|
|
|
border-radius: 2px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
}
|
2026-01-18 12:21:49 +08:00
|
|
|
|
.user .avatar {
|
|
|
|
|
|
background: #5436da;
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
}
|
|
|
|
|
|
.ai .avatar {
|
|
|
|
|
|
background: #19c37d;
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
}
|
|
|
|
|
|
.gpt-logo {
|
|
|
|
|
|
width: 20px;
|
|
|
|
|
|
height: 20px;
|
|
|
|
|
|
}
|
2026-01-18 10:24:35 +08:00
|
|
|
|
|
|
|
|
|
|
.msg-bubble {
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
|
}
|
2026-01-18 12:21:49 +08:00
|
|
|
|
.user .msg-bubble {
|
|
|
|
|
|
text-align: right;
|
|
|
|
|
|
}
|
2026-01-18 10:24:35 +08:00
|
|
|
|
.ai-bubble {
|
|
|
|
|
|
background: #444654;
|
|
|
|
|
|
padding: 15px;
|
2026-02-14 20:23:34 +08:00
|
|
|
|
border-radius: 6px;
|
2026-01-18 12:21:49 +08:00
|
|
|
|
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
2026-01-18 10:24:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.pasted-image {
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
border: 1px solid #565869;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
.code-snapshot {
|
|
|
|
|
|
background: #1e1e1e;
|
|
|
|
|
|
padding: 8px;
|
|
|
|
|
|
font-family: monospace;
|
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.chat-input-area {
|
|
|
|
|
|
padding: 20px;
|
2026-01-18 12:21:49 +08:00
|
|
|
|
background-image: linear-gradient(180deg, rgba(53, 55, 64, 0), #353740 50%);
|
2026-01-18 10:24:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.input-wrapper {
|
|
|
|
|
|
background: #40414f;
|
2026-01-18 12:21:49 +08:00
|
|
|
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
2026-01-18 10:24:35 +08:00
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
padding: 10px 12px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2026-01-18 12:21:49 +08:00
|
|
|
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
2026-01-18 10:24:35 +08:00
|
|
|
|
position: relative;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.input-preview {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
bottom: 100%;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
background: #40414f;
|
|
|
|
|
|
padding: 4px;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
border: 1px solid #565869;
|
|
|
|
|
|
animation: slideUp 0.3s;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.fake-input {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
min-height: 24px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
}
|
2026-01-18 12:21:49 +08:00
|
|
|
|
.placeholder {
|
|
|
|
|
|
color: #8e8ea0;
|
|
|
|
|
|
}
|
2026-01-18 10:24:35 +08:00
|
|
|
|
|
|
|
|
|
|
.send-btn {
|
|
|
|
|
|
background: #19c37d;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
width: 28px;
|
|
|
|
|
|
height: 28px;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
opacity: 0.5;
|
|
|
|
|
|
transition: opacity 0.2s;
|
|
|
|
|
|
}
|
2026-01-18 12:21:49 +08:00
|
|
|
|
.send-btn.active {
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
}
|
2026-01-18 10:24:35 +08:00
|
|
|
|
|
|
|
|
|
|
/* 引导层 */
|
|
|
|
|
|
.guide-overlay {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
2026-01-18 12:21:49 +08:00
|
|
|
|
background: rgba(0, 0, 0, 0.4);
|
2026-01-18 10:24:35 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
backdrop-filter: blur(2px);
|
|
|
|
|
|
z-index: 100;
|
|
|
|
|
|
}
|
|
|
|
|
|
.start-btn {
|
|
|
|
|
|
background: white;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
padding: 12px 24px;
|
|
|
|
|
|
border-radius: 30px;
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
cursor: pointer;
|
2026-01-18 12:21:49 +08:00
|
|
|
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
2026-01-18 10:24:35 +08:00
|
|
|
|
transition: transform 0.2s;
|
|
|
|
|
|
}
|
2026-01-18 12:21:49 +08:00
|
|
|
|
.start-btn:hover {
|
|
|
|
|
|
transform: scale(1.05);
|
|
|
|
|
|
}
|
2026-01-18 10:24:35 +08:00
|
|
|
|
|
|
|
|
|
|
.reset-btn {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 10px;
|
|
|
|
|
|
right: 10px;
|
|
|
|
|
|
z-index: 1000;
|
|
|
|
|
|
background: white;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
padding: 6px 12px;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
cursor: pointer;
|
2026-01-18 12:21:49 +08:00
|
|
|
|
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
|
2026-01-18 10:24:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@keyframes slideUp {
|
2026-01-18 12:21:49 +08:00
|
|
|
|
from {
|
|
|
|
|
|
opacity: 0;
|
|
|
|
|
|
transform: translateY(10px);
|
|
|
|
|
|
}
|
|
|
|
|
|
to {
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
transform: translateY(0);
|
|
|
|
|
|
}
|
2026-01-18 10:24:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
</style>
|