@turingflow/agent-kit 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +592 -2
- package/dist/agent.d.ts +27 -0
- package/dist/agent.js +31 -0
- package/dist/cli.d.ts +5 -0
- package/dist/cli.js +105 -0
- package/dist/handlers.d.ts +92 -0
- package/dist/handlers.js +211 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +10 -0
- package/dist/sdk.d.ts +106 -0
- package/dist/sdk.js +309 -0
- package/dist/server/agent.d.ts +27 -0
- package/dist/server/agent.js +31 -0
- package/dist/server/artifact-hooks.d.ts +6 -0
- package/dist/server/artifact-hooks.js +37 -0
- package/dist/server/artifact-tool-tracker.d.ts +24 -0
- package/dist/server/artifact-tool-tracker.js +347 -0
- package/dist/server/artifacts.d.ts +227 -0
- package/dist/server/artifacts.js +1061 -0
- package/dist/server/auth/config.d.ts +34 -0
- package/dist/server/auth/config.js +82 -0
- package/dist/server/auth/db.d.ts +159 -0
- package/dist/server/auth/db.js +680 -0
- package/dist/server/auth/handlers.d.ts +27 -0
- package/dist/server/auth/handlers.js +297 -0
- package/dist/server/auth/index.d.ts +15 -0
- package/dist/server/auth/index.js +14 -0
- package/dist/server/auth/login-options.d.ts +14 -0
- package/dist/server/auth/login-options.js +50 -0
- package/dist/server/auth/providers/dingtalk.d.ts +16 -0
- package/dist/server/auth/providers/dingtalk.js +177 -0
- package/dist/server/auth/providers/feishu.d.ts +15 -0
- package/dist/server/auth/providers/feishu.js +100 -0
- package/dist/server/auth/providers/index.d.ts +13 -0
- package/dist/server/auth/providers/index.js +24 -0
- package/dist/server/auth/session.d.ts +48 -0
- package/dist/server/auth/session.js +108 -0
- package/dist/server/auth/types.d.ts +118 -0
- package/dist/server/auth/types.js +7 -0
- package/dist/server/browser-agent-mcp.d.ts +67 -0
- package/dist/server/browser-agent-mcp.js +608 -0
- package/dist/server/cli.d.ts +6 -0
- package/dist/server/cli.js +112 -0
- package/dist/server/debug-log.d.ts +25 -0
- package/dist/server/debug-log.js +86 -0
- package/dist/server/handlers.d.ts +141 -0
- package/dist/server/handlers.js +523 -0
- package/dist/server/index.d.ts +30 -0
- package/dist/server/index.js +28 -0
- package/dist/server/kit-api.d.ts +23 -0
- package/dist/server/kit-api.js +153 -0
- package/dist/server/model-sources.d.ts +32 -0
- package/dist/server/model-sources.js +58 -0
- package/dist/server/oa.d.ts +87 -0
- package/dist/server/oa.js +397 -0
- package/dist/server/providers/openrouter.d.ts +51 -0
- package/dist/server/providers/openrouter.js +283 -0
- package/dist/server/render-markdown.d.ts +2 -0
- package/dist/server/render-markdown.js +50 -0
- package/dist/server/sdk.d.ts +269 -0
- package/dist/server/sdk.js +2025 -0
- package/dist/server/session-access.d.ts +5 -0
- package/dist/server/session-access.js +68 -0
- package/dist/server/session-fork.d.ts +10 -0
- package/dist/server/session-fork.js +142 -0
- package/dist/server/session-store.d.ts +56 -0
- package/dist/server/session-store.js +148 -0
- package/dist/server/sessions.d.ts +24 -0
- package/dist/server/sessions.js +541 -0
- package/dist/server/share.d.ts +15 -0
- package/dist/server/share.js +433 -0
- package/dist/server/tool-activity.d.ts +2 -0
- package/dist/server/tool-activity.js +26 -0
- package/dist/server/transcription/xiaomi-mimo.d.ts +8 -0
- package/dist/server/transcription/xiaomi-mimo.js +86 -0
- package/dist/server/upload.d.ts +13 -0
- package/dist/server/upload.js +81 -0
- package/dist/server/user-files.d.ts +28 -0
- package/dist/server/user-files.js +311 -0
- package/dist/server/voice.d.ts +25 -0
- package/dist/server/voice.js +61 -0
- package/dist/server/web-fetch.d.ts +71 -0
- package/dist/server/web-fetch.js +330 -0
- package/dist/styles.css +3354 -0
- package/dist/transcription/xiaomi-mimo.d.ts +8 -0
- package/dist/transcription/xiaomi-mimo.js +86 -0
- package/dist/ui/index.d.ts +358 -0
- package/dist/ui/index.js +7730 -0
- package/dist/upload.d.ts +13 -0
- package/dist/upload.js +81 -0
- package/dist/voice.d.ts +25 -0
- package/dist/voice.js +61 -0
- package/package.json +74 -4
package/dist/styles.css
ADDED
|
@@ -0,0 +1,3354 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--bg: #f4f6fb;
|
|
3
|
+
--panel: #ffffff;
|
|
4
|
+
--ink: #1f2733;
|
|
5
|
+
--ink-soft: #5b6573;
|
|
6
|
+
/* Shimmer 扫光:亮色模式用「骨架式」——静止文字=浅灰(--shine-base),扫过高光(--shine)=深墨,
|
|
7
|
+
高对比、一眼可见;深色调见下方 [data-theme=dark] 仍用白光。 */
|
|
8
|
+
--shine-base: #c2c9d4;
|
|
9
|
+
--shine: #1f2733;
|
|
10
|
+
--line: #e3e8f0;
|
|
11
|
+
--brand: #2f6bff;
|
|
12
|
+
--brand-dark: #1f4fd6;
|
|
13
|
+
--brand-soft: #eaf1ff;
|
|
14
|
+
--user-bubble: #2f6bff;
|
|
15
|
+
--bot-bubble: #f1f4fa;
|
|
16
|
+
--danger: #e5484d;
|
|
17
|
+
--ok: #1f9d55;
|
|
18
|
+
--radius: 14px;
|
|
19
|
+
--shadow: 0 10px 30px rgba(31, 39, 51, 0.08);
|
|
20
|
+
/* 中栏(聊天消息区)最小宽度:移动端视口小于该值时中栏不再压缩(保持此宽度,超出部分
|
|
21
|
+
被壳层裁切 = 放弃适配,不显示提示页)。改这里即可整体调宽/调窄 */
|
|
22
|
+
--chat-min-w: 360px;
|
|
23
|
+
/* 输入框(单行态)卡片高度:textarea 最小高 60px(见 ChatWindow MIN_TEXTAREA_HEIGHT)
|
|
24
|
+
+ composer 上下内边距 24px。思考直播小窗最大高度 = 该值 ×2,超出在框内滚动。 */
|
|
25
|
+
--chat-input-h: 84px;
|
|
26
|
+
--chat-thinking-max-h: calc(var(--chat-input-h) * 2);
|
|
27
|
+
/* 语义化扩展色(浅色默认值 = 原硬编码色,深色主题在下方 :root[data-theme="dark"] 整体换肤) */
|
|
28
|
+
--shell-bg: #ffffff;
|
|
29
|
+
--sidebar-bg: #f7f8fa;
|
|
30
|
+
--right-bg: #ffffff;
|
|
31
|
+
--hover: rgba(0,0,0,.05);
|
|
32
|
+
--hover-strong: #f0f1f4;
|
|
33
|
+
--active: #e8eaee;
|
|
34
|
+
--field-bg: #ffffff;
|
|
35
|
+
--field-soft: #fafbfc;
|
|
36
|
+
--overlay-bg: #ffffff;
|
|
37
|
+
--toast-bg: #ffffff;
|
|
38
|
+
--modal-mask: rgba(20, 28, 40, .45);
|
|
39
|
+
--fade-stop: rgba(255,255,255,.94);
|
|
40
|
+
--danger-soft: #fff0f0;
|
|
41
|
+
--ok-soft: #e9f8f0;
|
|
42
|
+
--warn-soft: #fef3e2;
|
|
43
|
+
--mark-bg: rgba(0, 0, 0, .1);
|
|
44
|
+
--user-bubble-soft: #f0f0f0;
|
|
45
|
+
--send-bg: #1f2733;
|
|
46
|
+
--send-bg-hover: #2f3b4a;
|
|
47
|
+
--send-ink: #ffffff;
|
|
48
|
+
--quote-bg: #f0f0f0;
|
|
49
|
+
--quote-line: #e0e0e0;
|
|
50
|
+
--brand-line: #cfe0ff;
|
|
51
|
+
--brand-line-strong: #b7d2ff;
|
|
52
|
+
--table-stripe: rgba(0,0,0,.02);
|
|
53
|
+
--scrollbar: rgba(31,39,51,.18);
|
|
54
|
+
--scrollbar-hover: rgba(31,39,51,.32);
|
|
55
|
+
--copied-bg: #e6f4ea;
|
|
56
|
+
--copied-ink: #1a7f37;
|
|
57
|
+
--drawer-shadow: -12px 0 40px rgba(31, 39, 51, .18);
|
|
58
|
+
--mobile-drawer-shadow: 0 8px 40px rgba(31, 39, 51, .22);
|
|
59
|
+
--spin-edge: rgba(0,0,0,.12);
|
|
60
|
+
--spin-top: rgba(0,0,0,.42);
|
|
61
|
+
/* 侧边消息滑块:亮色主题 —— 视口内可见=深墨(亮),滚出视口=浅灰 */
|
|
62
|
+
--slider-on: rgba(31, 39, 51, .52);
|
|
63
|
+
--slider-off: rgba(31, 39, 51, .16);
|
|
64
|
+
--slider-hover: #1f2733;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* ============ 深色主题(参考 WorkBuddy 桌面端深色配色) ============
|
|
68
|
+
通过 <html data-theme="dark"> 切换(用户菜单「外观」segment / 系统偏好)。
|
|
69
|
+
核心语义变量换肤:炭黑底 + 白字 + 灰阶边框 + 品牌蓝点缀;组件硬编码色已收敛到上方变量。 */
|
|
70
|
+
:root[data-theme="dark"] {
|
|
71
|
+
/* 中性灰阶对齐 WorkBuddy 桌面端深色(去蓝绿偏色):页面 #1a1a1a / 主面 #1f1f1f / 卡片 #252525 / 描边 #333(白低透) */
|
|
72
|
+
--bg: #1a1a1a;
|
|
73
|
+
--panel: #252525;
|
|
74
|
+
--ink: #ededed;
|
|
75
|
+
--ink-soft: #9a9a9a;
|
|
76
|
+
/* Shimmer 扫光:暗色模式静止文字=浅灰(--shine-base),高光=白(深底上亮闪)。 */
|
|
77
|
+
--shine-base: #9a9a9a;
|
|
78
|
+
--shine: #ffffff;
|
|
79
|
+
--line: #333333;
|
|
80
|
+
--brand: #2f6bff;
|
|
81
|
+
--brand-dark: #7fa5ff;
|
|
82
|
+
--brand-soft: rgba(47, 107, 255, .16);
|
|
83
|
+
--user-bubble: #2f6bff;
|
|
84
|
+
--bot-bubble: #252525;
|
|
85
|
+
--danger: #f0616d;
|
|
86
|
+
--ok: #34b36b;
|
|
87
|
+
--radius: 14px;
|
|
88
|
+
--shadow: 0 10px 30px rgba(0, 0, 0, .45);
|
|
89
|
+
--chat-min-w: 360px;
|
|
90
|
+
--shell-bg: #1a1a1a;
|
|
91
|
+
--sidebar-bg: #1f1f1f;
|
|
92
|
+
--right-bg: #252525;
|
|
93
|
+
--hover: rgba(255,255,255,.07);
|
|
94
|
+
--hover-strong: #2a2a2a;
|
|
95
|
+
--active: #333333;
|
|
96
|
+
--field-bg: #1f1f1f;
|
|
97
|
+
--field-soft: #262626;
|
|
98
|
+
--overlay-bg: #252525;
|
|
99
|
+
--toast-bg: #252525;
|
|
100
|
+
--modal-mask: rgba(0, 0, 0, .55);
|
|
101
|
+
--fade-stop: rgba(26, 26, 26, .94);
|
|
102
|
+
--danger-soft: rgba(240, 97, 109, .14);
|
|
103
|
+
--ok-soft: rgba(52, 179, 107, .14);
|
|
104
|
+
--warn-soft: rgba(245, 166, 35, .16);
|
|
105
|
+
--user-bubble-soft: #2e2e2e;
|
|
106
|
+
--send-bg: #ededed;
|
|
107
|
+
--send-bg-hover: #ffffff;
|
|
108
|
+
--send-ink: #1a1a1a;
|
|
109
|
+
--quote-bg: #1f1f1f;
|
|
110
|
+
--quote-line: #333333;
|
|
111
|
+
--mark-bg: rgba(255, 255, 255, .18);
|
|
112
|
+
--brand-line: rgba(47, 107, 255, .4);
|
|
113
|
+
--brand-line-strong: rgba(47, 107, 255, .55);
|
|
114
|
+
--table-stripe: rgba(255,255,255,.03);
|
|
115
|
+
--scrollbar: rgba(255,255,255,.16);
|
|
116
|
+
--scrollbar-hover: rgba(255,255,255,.3);
|
|
117
|
+
--copied-bg: rgba(52, 179, 107, .16);
|
|
118
|
+
--copied-ink: #5fd693;
|
|
119
|
+
--drawer-shadow: -12px 0 40px rgba(0, 0, 0, .5);
|
|
120
|
+
--mobile-drawer-shadow: 0 8px 40px rgba(0, 0, 0, .55);
|
|
121
|
+
--spin-edge: rgba(255,255,255,.2);
|
|
122
|
+
--spin-top: rgba(255,255,255,.5);
|
|
123
|
+
/* 侧边消息滑块:暗色主题 —— 视口内可见=亮白,滚出视口=暗灰 */
|
|
124
|
+
--slider-on: rgba(255, 255, 255, .82);
|
|
125
|
+
--slider-off: rgba(255, 255, 255, .17);
|
|
126
|
+
--slider-hover: #ffffff;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
* { box-sizing: border-box; }
|
|
130
|
+
|
|
131
|
+
/* 细滚动条:与 WorkBuddy 一致(4px 圆角浅灰) */
|
|
132
|
+
* { scrollbar-width: thin; scrollbar-color: var(--scrollbar) transparent; }
|
|
133
|
+
*::-webkit-scrollbar { width: 4px; height: 4px; }
|
|
134
|
+
*::-webkit-scrollbar-thumb { background: var(--scrollbar); border-radius: 999px; }
|
|
135
|
+
*::-webkit-scrollbar-track { background: transparent; }
|
|
136
|
+
/* 聊天消息区 + 右栏滚动条:自动隐藏(平时透明,滚动/悬停时显现,1.5s 无操作渐隐)。
|
|
137
|
+
webkit 的 ::-webkit-scrollbar 伪元素不支持 CSS 动画,由 JS(.sb-active)切换显示;
|
|
138
|
+
Firefox 用 scrollbar-color 同样随 .sb-active 切换(默认透明,滚动时显现) */
|
|
139
|
+
.chat-body, .chat-right-section-body { scrollbar-width: thin; scrollbar-color: rgba(31,39,51,0) transparent; }
|
|
140
|
+
.chat-body.sb-active, .chat-right-section-body.sb-active { scrollbar-color: var(--scrollbar) transparent; }
|
|
141
|
+
.chat-body::-webkit-scrollbar-thumb,
|
|
142
|
+
.chat-right-section-body::-webkit-scrollbar-thumb { background: rgba(31,39,51,0); }
|
|
143
|
+
.chat-body.sb-active::-webkit-scrollbar-thumb,
|
|
144
|
+
.chat-right-section-body.sb-active::-webkit-scrollbar-thumb { background: var(--scrollbar); }
|
|
145
|
+
|
|
146
|
+
html, body {
|
|
147
|
+
margin: 0;
|
|
148
|
+
padding: 0;
|
|
149
|
+
height: 100%;
|
|
150
|
+
overflow-x: hidden;
|
|
151
|
+
background: var(--bg);
|
|
152
|
+
color: var(--ink);
|
|
153
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", Roboto, Helvetica, Arial, sans-serif;
|
|
154
|
+
-webkit-font-smoothing: antialiased;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
a { color: inherit; }
|
|
158
|
+
|
|
159
|
+
/* ============ 登录页(黑白灰色系) ============ */
|
|
160
|
+
.login-page {
|
|
161
|
+
min-height: 100vh;
|
|
162
|
+
display: flex;
|
|
163
|
+
flex-direction: column;
|
|
164
|
+
align-items: center;
|
|
165
|
+
justify-content: center;
|
|
166
|
+
background: radial-gradient(1200px 600px at 50% -10%, #eef0f4 0%, var(--bg) 55%);
|
|
167
|
+
padding: 24px;
|
|
168
|
+
}
|
|
169
|
+
.login-shell { width: 100%; max-width: 420px; }
|
|
170
|
+
.login-brand { display: flex; align-items: center; gap: 14px; margin-bottom: 22px; }
|
|
171
|
+
.login-brand-logo { height: 32px; width: auto; display: block; }
|
|
172
|
+
.login-brand-title h1 { margin: 0; font-size: 20px; letter-spacing: .3px; }
|
|
173
|
+
.login-brand-title span { font-size: 13px; color: var(--ink-soft); }
|
|
174
|
+
|
|
175
|
+
.login-card {
|
|
176
|
+
background: var(--panel);
|
|
177
|
+
border: 1px solid var(--line);
|
|
178
|
+
border-radius: var(--radius);
|
|
179
|
+
padding: 28px 26px 24px;
|
|
180
|
+
box-shadow: var(--shadow);
|
|
181
|
+
position: relative;
|
|
182
|
+
overflow: hidden;
|
|
183
|
+
}
|
|
184
|
+
.login-card-line {
|
|
185
|
+
position: absolute; top: 0; left: 0; right: 0; height: 4px;
|
|
186
|
+
background: linear-gradient(90deg, #2a3140, #8b93a3);
|
|
187
|
+
}
|
|
188
|
+
.login-dingtalk-heading { display: flex; flex-direction: column; gap: 4px; margin-bottom: 22px; }
|
|
189
|
+
.login-dingtalk-heading strong { font-size: 17px; }
|
|
190
|
+
.login-dingtalk-heading span { font-size: 13px; color: var(--ink-soft); }
|
|
191
|
+
|
|
192
|
+
/* 登录方式选择器(AUTH_PROVIDER 多个时渲染):黑白灰 */
|
|
193
|
+
.login-provider-list { display: flex; flex-direction: column; gap: 10px; }
|
|
194
|
+
.login-provider-button {
|
|
195
|
+
display: flex; align-items: center; justify-content: center; gap: 10px;
|
|
196
|
+
width: 100%; padding: 13px 16px; border-radius: 10px;
|
|
197
|
+
background: var(--panel);
|
|
198
|
+
border: 1px solid var(--ink);
|
|
199
|
+
color: var(--ink); font-size: 15px; font-weight: 600; text-decoration: none;
|
|
200
|
+
transition: background .15s ease, color .15s ease;
|
|
201
|
+
}
|
|
202
|
+
.login-provider-button svg { width: 22px; height: 22px; fill: currentColor; }
|
|
203
|
+
|
|
204
|
+
/* 兼容旧用法:单个登录按钮(同样黑白灰) */
|
|
205
|
+
.login-dingtalk-button {
|
|
206
|
+
display: flex; align-items: center; justify-content: center; gap: 10px;
|
|
207
|
+
width: 100%; padding: 13px 16px; border-radius: 10px;
|
|
208
|
+
background: var(--panel);
|
|
209
|
+
border: 1px solid var(--ink);
|
|
210
|
+
color: var(--ink); font-size: 15px; font-weight: 600; text-decoration: none;
|
|
211
|
+
transition: background .15s ease, color .15s ease;
|
|
212
|
+
}
|
|
213
|
+
.login-dingtalk-button svg { width: 22px; height: 22px; fill: currentColor; }
|
|
214
|
+
|
|
215
|
+
.login-auto-status {
|
|
216
|
+
display: flex; align-items: center; gap: 8px;
|
|
217
|
+
font-size: 13px; color: var(--ink-soft); margin: 12px 0 14px;
|
|
218
|
+
}
|
|
219
|
+
.login-auto-status i {
|
|
220
|
+
width: 8px; height: 8px; border-radius: 50%; background: var(--ink-soft);
|
|
221
|
+
animation: pulse 1s infinite ease-in-out;
|
|
222
|
+
}
|
|
223
|
+
@keyframes pulse { 0%,100%{opacity:.3} 50%{opacity:1} }
|
|
224
|
+
|
|
225
|
+
.login-dev-wrap { margin-top: 16px; }
|
|
226
|
+
.login-divider { display: flex; align-items: center; gap: 10px; color: var(--ink-soft); font-size: 12px; margin: 8px 0; }
|
|
227
|
+
.login-divider::before, .login-divider::after { content: ""; flex: 1; height: 1px; background: var(--line); }
|
|
228
|
+
.login-dev-button {
|
|
229
|
+
width: 100%; padding: 11px 16px; border-radius: 10px;
|
|
230
|
+
border: 1px solid var(--line); background: var(--panel); color: var(--ink);
|
|
231
|
+
font-size: 14px; font-weight: 600; cursor: pointer;
|
|
232
|
+
text-decoration: none; display: block; text-align: center;
|
|
233
|
+
transition: background .15s ease, color .15s ease;
|
|
234
|
+
}
|
|
235
|
+
.login-dev-button:disabled { opacity: .6; cursor: default; }
|
|
236
|
+
|
|
237
|
+
.login-error { color: var(--danger); font-size: 13px; margin-top: 14px; min-height: 18px; }
|
|
238
|
+
.login-dots { display: flex; gap: 6px; justify-content: center; margin: 18px 0; }
|
|
239
|
+
.login-dots i { width: 6px; height: 6px; border-radius: 50%; background: var(--ink-soft); }
|
|
240
|
+
.login-copyright { color: var(--ink-soft); font-size: 12px; margin-top: 6px; }
|
|
241
|
+
|
|
242
|
+
/* ============ 聊天页 ============ */
|
|
243
|
+
/* 三栏布局壳:左栏 / 中栏 / 右栏 横向铺满;左右默认收起(flex-basis 0),中栏全屏。
|
|
244
|
+
应用窗口宽度由用户缩放控制:禁止窗口级水平滚动,右栏打开时压缩中栏而非横向溢出 */
|
|
245
|
+
.chat-shell { height: 100vh; display: flex; flex-direction: row; align-items: stretch; background: var(--shell-bg); overflow-x: hidden; overflow-y: hidden; }
|
|
246
|
+
.chat-topbar {
|
|
247
|
+
position: relative;
|
|
248
|
+
display: flex; align-items: center; gap: 12px;
|
|
249
|
+
flex: 0 0 auto;
|
|
250
|
+
height: 46px; padding: 0 16px;
|
|
251
|
+
border-bottom: 1px solid var(--line); background: var(--panel);
|
|
252
|
+
}
|
|
253
|
+
.chat-brand { display: flex; align-items: center; gap: 10px; }
|
|
254
|
+
.chat-logo { height: 26px; width: auto; display: block; flex: 0 0 auto; }
|
|
255
|
+
/* 顶栏左侧:侧边栏展开按钮 + 品牌 Logo + 会话标题。
|
|
256
|
+
flex:1 + min-width:0 → 空间不足时由它承担收缩(挤压标题),右侧按钮组始终完整。
|
|
257
|
+
overflow:hidden 防止长标题把 flex 项最小宽度撑死、把右侧按钮推出顶栏。 */
|
|
258
|
+
.chat-topbar-left { flex: 1 1 auto; min-width: 0; overflow: hidden; display: flex; align-items: center; gap: 6px; }
|
|
259
|
+
/* 按钮组固定不收缩:从右往左占据空间,空间不够时挤压左侧标题而不是被裁切 */
|
|
260
|
+
.chat-topbar-right { margin-left: auto; flex: 0 0 auto; display: flex; align-items: center; gap: 10px; }
|
|
261
|
+
.chat-sidebar-toggle {
|
|
262
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
263
|
+
width: 34px; height: 34px; border-radius: 8px;
|
|
264
|
+
border: none; background: transparent; color: var(--ink-soft); cursor: pointer;
|
|
265
|
+
transition: background .15s ease, color .15s ease;
|
|
266
|
+
}
|
|
267
|
+
.chat-sidebar-toggle svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
|
|
268
|
+
/* 中栏:全屏主体。真正的最小宽度 = 正常手机宽度(375px,与 JS 侧 CHAT_MIN_W 保持一致):
|
|
269
|
+
即使 PC 上拖宽右侧边栏、或窗口收窄,中间 chat 区域也不会被挤压到 375px 以下。
|
|
270
|
+
min(375px, 100%) 保证窗口比手机还窄(如 360px 小屏)时回退为全宽,不产生水平溢出。 */
|
|
271
|
+
.chat-main { flex: 1 1 auto; min-width: min(375px, 100%); display: flex; flex-direction: column; height: 100vh; position: relative; }
|
|
272
|
+
.chat-main-inner {
|
|
273
|
+
flex: 0 1 auto;
|
|
274
|
+
min-height: 0;
|
|
275
|
+
display: flex; flex-direction: column;
|
|
276
|
+
justify-content: flex-end;
|
|
277
|
+
/* 输入区宽度 = min(中栏可用宽度的 80%, 1200px) 居中:
|
|
278
|
+
- 中栏 < 1200px/0.8 = 1500px 时,按 80% 缩放(随窗口/右栏自适应,两侧留白 10%);
|
|
279
|
+
- 中栏 ≥ 1500px(超大屏)时封顶 1200px,不再随百分比继续变宽。
|
|
280
|
+
中栏 = 窗口 − 左栏 − 右栏;中栏最小宽度由 .chat-main 的 min-width 保证(375px)。 */
|
|
281
|
+
width: 100%; max-width: min(80%, 1200px); margin: 0 auto;
|
|
282
|
+
position: relative;
|
|
283
|
+
}
|
|
284
|
+
/* 新建任务空态(无消息):输入区与欢迎/提示一起垂直居中,参考 WB 新建任务界面;
|
|
285
|
+
用户输入第一条消息后 is-empty 移除,chat-main-inner 自动回到底部常规布局 */
|
|
286
|
+
.chat-main.is-empty .chat-main-inner {
|
|
287
|
+
position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
|
|
288
|
+
width: min(680px, calc(100% - 32px)); max-width: none; margin: 0;
|
|
289
|
+
gap: 14px;
|
|
290
|
+
justify-content: center;
|
|
291
|
+
}
|
|
292
|
+
.chat-main.is-empty .chat-empty { margin: 0 auto 4px; max-width: 520px; }
|
|
293
|
+
.chat-main.is-empty .chat-suggestions { flex-wrap: wrap; justify-content: center; gap: 8px; }
|
|
294
|
+
.chat-main.is-empty .chat-composer-stack { margin: 0; width: 100%; box-sizing: border-box; }
|
|
295
|
+
/* 离开底部时:消息区与输入区交界的浮层(锚定输入区容器顶部 bottom:100%,滚动时不动)。
|
|
296
|
+
overlay 自身高度 0,fade 向上延伸进消息区、按钮浮在其上 */
|
|
297
|
+
.chat-body-overlay {
|
|
298
|
+
position: absolute; left: 0; right: 0; bottom: 100%; height: 0;
|
|
299
|
+
pointer-events: none; z-index: 5;
|
|
300
|
+
}
|
|
301
|
+
/* 消息底部渐隐 + 毛玻璃模糊 */
|
|
302
|
+
.chat-body-fade {
|
|
303
|
+
position: absolute; left: 0; right: 0; bottom: 0; height: 72px;
|
|
304
|
+
pointer-events: none;
|
|
305
|
+
background: linear-gradient(180deg, rgba(255,255,255,0) 0%, var(--fade-stop) 100%);
|
|
306
|
+
backdrop-filter: blur(6px);
|
|
307
|
+
-webkit-backdrop-filter: blur(6px);
|
|
308
|
+
}
|
|
309
|
+
/* Electron:backdrop-filter 合成会把覆盖区文字一起糊掉,仅保留渐变渐隐(浏览器保持毛玻璃) */
|
|
310
|
+
.env-electron .chat-body-fade {
|
|
311
|
+
backdrop-filter: none;
|
|
312
|
+
-webkit-backdrop-filter: none;
|
|
313
|
+
}
|
|
314
|
+
/* 居中「回到底部」按钮:一直悬浮在输入框上方 */
|
|
315
|
+
.chat-bottom-btn {
|
|
316
|
+
position: absolute; left: 50%; transform: translateX(-50%); bottom: 14px;
|
|
317
|
+
width: 34px; height: 34px; border-radius: 50%; z-index: 6;
|
|
318
|
+
border: 1px solid var(--line); background: var(--field-bg); color: var(--ink-soft);
|
|
319
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
320
|
+
cursor: pointer; pointer-events: auto;
|
|
321
|
+
box-shadow: 0 2px 8px rgba(31,39,51,.14);
|
|
322
|
+
transition: background .15s ease, color .15s ease, border-color .15s ease;
|
|
323
|
+
}
|
|
324
|
+
.chat-bottom-btn svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
|
|
325
|
+
/* 大模型输出中(busy)且用户离开底部:按钮细环转圈动画(subtle)。
|
|
326
|
+
单段弧:起点最亮,沿圆周到尾端淡出为 0(conic 渐变),旋转产生流动感;
|
|
327
|
+
环形 mask 保留 1px 细环。颜色用主题变量 --spin-edge(深色下为柔和的亮灰、
|
|
328
|
+
浅色下为浅灰):对比足够但不过亮。 */
|
|
329
|
+
.chat-bottom-btn.is-live { border-color: transparent; }
|
|
330
|
+
.chat-bottom-btn.is-live::before {
|
|
331
|
+
content: ""; position: absolute; inset: 0; border-radius: 50%;
|
|
332
|
+
background: conic-gradient(from 0deg,
|
|
333
|
+
transparent 0deg,
|
|
334
|
+
var(--spin-edge) 60deg,
|
|
335
|
+
var(--spin-edge) 300deg,
|
|
336
|
+
transparent 360deg);
|
|
337
|
+
-webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 1px), #000 calc(100% - 1px));
|
|
338
|
+
mask: radial-gradient(farthest-side, transparent calc(100% - 1px), #000 calc(100% - 1px));
|
|
339
|
+
animation: chatBottomLive 1.1s linear infinite;
|
|
340
|
+
}
|
|
341
|
+
@keyframes chatBottomLive { to { transform: rotate(360deg); } }
|
|
342
|
+
/* 左栏:会话列表 + 底部用户信息;默认收起(flex-basis 0 + overflow hidden + 内容 visibility hidden) */
|
|
343
|
+
.chat-pane-left { flex: 0 0 0; overflow: hidden; transition: flex-basis .18s ease; border-right: 1px solid var(--line); }
|
|
344
|
+
.chat-pane-left.is-open { flex-basis: 280px; }
|
|
345
|
+
.chat-pane-left:not(.is-open) .chat-sidebar-inner { visibility: hidden; }
|
|
346
|
+
.chat-sidebar-inner {
|
|
347
|
+
width: 280px; height: 100%;
|
|
348
|
+
display: flex; flex-direction: column;
|
|
349
|
+
background: var(--sidebar-bg);
|
|
350
|
+
}
|
|
351
|
+
/* 右栏:上半输入文件 / 下半输出产物;默认收起。拖动改宽时用 --right-w 覆盖基础宽度。
|
|
352
|
+
展开默认与中间消息区平分剩余水平宽度(50%) */
|
|
353
|
+
.chat-pane-right { flex: 0 0 0; overflow: hidden; transition: flex-basis .18s ease; border-left: 1px solid var(--line); position: relative; }
|
|
354
|
+
/* 右栏宽上限 = 容器宽 − 左栏实际占用(var(--left-used):开 280px / 关 0px) − 中栏最小宽(375):
|
|
355
|
+
拖宽右栏可以把中间 chat 一直压到 375px 最小宽;与 JS 拖拽侧(LEFT_PANE_W / CHAT_MIN_W)同源,双保险。
|
|
356
|
+
窗口极窄时 calc 为负 → flex-basis 按 0 处理。 */
|
|
357
|
+
.chat-pane-right.is-open { flex-basis: min(var(--right-w, 50%), calc(100% - var(--left-used, 280px) - 375px)); }
|
|
358
|
+
.chat-pane-right.is-dragging { transition: none; }
|
|
359
|
+
.chat-pane-right:not(.is-open) .chat-right-inner { visibility: hidden; }
|
|
360
|
+
/* 产物预览全屏(toggle):右栏占满 app 整个宽度,左栏与中栏让位隐藏;再点还原。
|
|
361
|
+
仅在右栏可见时生效(chat-shell 的 has-preview-full 类已带 rightShown 条件)。 */
|
|
362
|
+
.chat-shell.has-preview-full .chat-pane-left,
|
|
363
|
+
.chat-shell.has-preview-full .chat-main { display: none; }
|
|
364
|
+
.chat-shell.has-preview-full .chat-pane-right {
|
|
365
|
+
flex: 1 1 100% !important; min-width: 0 !important; max-width: 100% !important;
|
|
366
|
+
}
|
|
367
|
+
.chat-shell.has-preview-full .chat-resizer { display: none; }
|
|
368
|
+
/* 中/右栏之间的拖拽 resizer:hover 时 2px 竖条 dim-in 渐显;拖动中常显 */
|
|
369
|
+
.chat-resizer {
|
|
370
|
+
position: absolute; left: -5px; top: 0; bottom: 0; width: 10px;
|
|
371
|
+
cursor: col-resize; z-index: 40;
|
|
372
|
+
}
|
|
373
|
+
.chat-resizer::after {
|
|
374
|
+
content: ""; position: absolute; left: 50%; top: 0; bottom: 0; width: 2px;
|
|
375
|
+
transform: translateX(-50%);
|
|
376
|
+
background: rgba(31,39,51,.28);
|
|
377
|
+
opacity: 0; transition: opacity .18s ease;
|
|
378
|
+
}
|
|
379
|
+
.chat-pane-right:not(.is-open) .chat-right-inner { visibility: hidden; }
|
|
380
|
+
.chat-right-inner {
|
|
381
|
+
width: 100%; height: 100%;
|
|
382
|
+
display: flex; flex-direction: column;
|
|
383
|
+
background: var(--right-bg);
|
|
384
|
+
}
|
|
385
|
+
.chat-right-section { display: flex; flex-direction: column; min-height: 0; }
|
|
386
|
+
/* 输入区:排在输出区下方(视觉顺序:输出在上 / 输入在下);高度自适应内容(不强制 50%),
|
|
387
|
+
上限 50%;文件项单列占满整行,长文件名允许换行,避免两列布局/省略号造成"被截断"的观感 */
|
|
388
|
+
.chat-right-section--inputs { flex: 0 1 auto; max-height: 50%; order: 2; border-top: 1px solid var(--line); }
|
|
389
|
+
.chat-right-section--inputs .chat-right-section-body { display: flex; flex-direction: column; gap: 4px; padding: 8px; overflow-y: auto; }
|
|
390
|
+
.chat-right-section--inputs .chat-right-file { flex: 0 0 auto; width: 100%; }
|
|
391
|
+
/* 输出区:排在输入区上方(视觉顺序:输出在上 / 输入在下);默认占满剩余高度(上限 50%);
|
|
392
|
+
无输入文件时 is-full 占满 100% */
|
|
393
|
+
.chat-right-section--outputs { flex: 1 1 auto; max-height: 50%; order: 1; }
|
|
394
|
+
.chat-right-section--outputs.is-full { flex: 1 1 auto; max-height: 100%; }
|
|
395
|
+
.chat-right-section-head {
|
|
396
|
+
flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between;
|
|
397
|
+
height: 46px; padding: 0 12px; border-bottom: 1px solid var(--line);
|
|
398
|
+
font-size: 13px; font-weight: 700; color: var(--ink);
|
|
399
|
+
}
|
|
400
|
+
.chat-right-count {
|
|
401
|
+
font-size: 11px; color: var(--ink-soft); background: var(--line);
|
|
402
|
+
border-radius: 999px; padding: 1px 7px; font-weight: 600;
|
|
403
|
+
}
|
|
404
|
+
/* 标题 + 计数紧贴一行(计数在"输出产物"文字右边);"打开文件夹"按钮仍靠右 */
|
|
405
|
+
.chat-right-section-title {
|
|
406
|
+
display: inline-flex; align-items: center; gap: 6px; min-width: 0;
|
|
407
|
+
}
|
|
408
|
+
/* 打开产物文件夹(本地 app):section-head 内的小按钮,图标+文字,hover 仅变色不位移、不变边框 */
|
|
409
|
+
.chat-right-folder-btn {
|
|
410
|
+
display: inline-flex; align-items: center; gap: 4px; margin-left: 8px;
|
|
411
|
+
height: 24px; padding: 0 8px; border: 1px solid var(--line); border-radius: 6px;
|
|
412
|
+
background: transparent; color: var(--ink-soft); font-size: 11.5px; font-weight: 600;
|
|
413
|
+
cursor: pointer; transition: color .15s ease, background .15s ease;
|
|
414
|
+
}
|
|
415
|
+
.chat-right-folder-btn svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
|
|
416
|
+
.chat-right-folder-btn:hover { color: var(--ink); background: color-mix(in srgb, var(--ink) 8%, transparent); }
|
|
417
|
+
.chat-right-folder-btn:active { color: var(--ink); }
|
|
418
|
+
.chat-right-section-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 6px; }
|
|
419
|
+
/* 输出区:列表项垂直排列并拉开间距 */
|
|
420
|
+
.chat-right-section--outputs .chat-right-section-body { display: flex; flex-direction: column; gap: 8px; padding: 8px; }
|
|
421
|
+
.chat-right-empty { padding: 18px 10px; font-size: 12.5px; color: var(--ink-soft); text-align: center; }
|
|
422
|
+
.chat-right-file {
|
|
423
|
+
display: flex; align-items: center; gap: 6px;
|
|
424
|
+
padding: 6px 8px; border-radius: 8px;
|
|
425
|
+
}
|
|
426
|
+
.chat-right-file-main {
|
|
427
|
+
flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 8px;
|
|
428
|
+
text-decoration: none; color: inherit;
|
|
429
|
+
}
|
|
430
|
+
.chat-right-file-info { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
|
|
431
|
+
.chat-right-file-name {
|
|
432
|
+
font-size: 12.5px; color: var(--ink);
|
|
433
|
+
white-space: normal; word-break: break-all; line-height: 1.35;
|
|
434
|
+
}
|
|
435
|
+
.chat-right-file-meta { font-size: 11px; color: var(--ink-soft); }
|
|
436
|
+
.chat-right-file-dl {
|
|
437
|
+
flex: none; width: 26px; height: 26px;
|
|
438
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
439
|
+
border-radius: 6px; color: var(--ink-soft); text-decoration: none;
|
|
440
|
+
transition: background .15s ease, color .15s ease;
|
|
441
|
+
}
|
|
442
|
+
.chat-right-file-dl svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
|
|
443
|
+
/* 左栏底部用户信息(WorkBuddy 风格):用户区域朴素无边框无背景、点击也不改变外观;
|
|
444
|
+
点击后用户菜单 popup(外观 segment + 退出登录)出现在 profile 上方;点菜单外任意处关闭 */
|
|
445
|
+
.chat-sidebar-user {
|
|
446
|
+
position: relative;
|
|
447
|
+
flex: 0 0 auto; padding: 10px 12px; border-top: 1px solid var(--line);
|
|
448
|
+
display: flex; flex-direction: column; gap: 8px;
|
|
449
|
+
}
|
|
450
|
+
.chat-sidebar-user-trigger {
|
|
451
|
+
display: block; width: 100%; border: none; background: none; padding: 6px 4px;
|
|
452
|
+
cursor: pointer; text-align: left; border-radius: 8px;
|
|
453
|
+
}
|
|
454
|
+
.chat-sidebar-user-row { display: flex; align-items: center; gap: 10px; }
|
|
455
|
+
.chat-sidebar-user-name {
|
|
456
|
+
font-size: 13.5px; font-weight: 600; color: var(--ink);
|
|
457
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
458
|
+
}
|
|
459
|
+
/* 用户菜单 popup:悬浮于用户块上方。不再使用全屏 backdrop(透明 fixed 层会拦截消息区滚轮,
|
|
460
|
+
造成"菜单开着时悬停消息区无法滚动");关闭改由 ChatWindow 的 document pointerdown 监听处理,
|
|
461
|
+
滚轮事件穿透到消息区,悬停即可滚动(WorkBuddy 同款行为)。 */
|
|
462
|
+
.chat-user-menu {
|
|
463
|
+
position: absolute; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%);
|
|
464
|
+
width: 232px; z-index: 60;
|
|
465
|
+
background: var(--overlay-bg); border: 1px solid var(--line);
|
|
466
|
+
border-radius: 12px; box-shadow: var(--shadow);
|
|
467
|
+
padding: 6px; display: flex; flex-direction: column; gap: 2px;
|
|
468
|
+
animation: chatUserMenuIn .14s ease;
|
|
469
|
+
}
|
|
470
|
+
@keyframes chatUserMenuIn {
|
|
471
|
+
from { opacity: 0; transform: translate(-50%, 4px); }
|
|
472
|
+
to { opacity: 1; transform: translate(-50%, 0); }
|
|
473
|
+
}
|
|
474
|
+
.chat-user-menu-row {
|
|
475
|
+
display: flex; align-items: center; justify-content: space-between; gap: 10px;
|
|
476
|
+
padding: 8px 10px;
|
|
477
|
+
}
|
|
478
|
+
.chat-user-menu-label { font-size: 13px; color: var(--ink); }
|
|
479
|
+
/* segment:浅色 / 深色(外观切换) */
|
|
480
|
+
.chat-user-menu-segment {
|
|
481
|
+
display: inline-flex; background: var(--hover-strong); border-radius: 8px; padding: 2px; gap: 2px;
|
|
482
|
+
}
|
|
483
|
+
.chat-user-menu-seg {
|
|
484
|
+
border: none; background: transparent; cursor: pointer;
|
|
485
|
+
padding: 4px 12px; border-radius: 6px;
|
|
486
|
+
font-size: 12.5px; color: var(--ink-soft);
|
|
487
|
+
transition: background .15s ease, color .15s ease, box-shadow .15s ease;
|
|
488
|
+
}
|
|
489
|
+
.chat-user-menu-seg.is-on {
|
|
490
|
+
background: var(--overlay-bg); color: var(--ink); font-weight: 600;
|
|
491
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, .14);
|
|
492
|
+
}
|
|
493
|
+
.chat-user-menu-sep { height: 1px; background: var(--line); margin: 2px 0; }
|
|
494
|
+
/* 开关(显示上下文使用量 / 显示模型):track + knob 的两态滑块 */
|
|
495
|
+
.chat-user-menu-switch {
|
|
496
|
+
flex: 0 0 auto; position: relative; cursor: pointer;
|
|
497
|
+
width: 34px; height: 20px; padding: 0;
|
|
498
|
+
border: none; border-radius: 999px;
|
|
499
|
+
background: var(--hover-strong);
|
|
500
|
+
transition: background .16s ease;
|
|
501
|
+
}
|
|
502
|
+
.chat-user-menu-switch.is-on { background: var(--brand); }
|
|
503
|
+
.chat-user-menu-switch-knob {
|
|
504
|
+
position: absolute; top: 2px; left: 2px;
|
|
505
|
+
width: 16px; height: 16px; border-radius: 50%;
|
|
506
|
+
background: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, .25);
|
|
507
|
+
transition: transform .16s ease;
|
|
508
|
+
}
|
|
509
|
+
.chat-user-menu-switch.is-on .chat-user-menu-switch-knob { transform: translateX(14px); }
|
|
510
|
+
.chat-user-menu-item {
|
|
511
|
+
display: block; width: 100%; text-align: left;
|
|
512
|
+
border: none; background: transparent; cursor: pointer;
|
|
513
|
+
padding: 9px 10px; border-radius: 8px; font-size: 13px; color: var(--ink);
|
|
514
|
+
transition: background .15s ease, color .15s ease;
|
|
515
|
+
}
|
|
516
|
+
.chat-user-menu-item--danger { color: var(--danger); }
|
|
517
|
+
.chat-sidebar-head {
|
|
518
|
+
display: flex; align-items: center; justify-content: space-between; gap: 8px;
|
|
519
|
+
flex: 0 0 auto;
|
|
520
|
+
height: 46px; padding: 0 14px;
|
|
521
|
+
}
|
|
522
|
+
/* 头部右上角应用名:logo 在左、应用名靠右(space-between 下 flex:1 推右) */
|
|
523
|
+
.chat-sidebar-appname {
|
|
524
|
+
margin-left: auto; flex: 0 1 auto; min-width: 0;
|
|
525
|
+
font-size: 12.5px; color: var(--ink-soft);
|
|
526
|
+
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
527
|
+
}
|
|
528
|
+
.chat-sidebar-title { font-weight: 700; font-size: 15px; color: var(--ink); }
|
|
529
|
+
/* 左栏顶部 Logo(宿主传入):固定高度、保持比例,与「+新对话」按钮同行 */
|
|
530
|
+
.chat-sidebar-logo { height: 24px; width: auto; display: block; }
|
|
531
|
+
/* 「新建任务」独立固定行(不随会话列表滚动):头部下方一行,⊕ 圆圈加号 + 文字;
|
|
532
|
+
与下方会话列表只留间距、不画分隔线 */
|
|
533
|
+
.chat-sidebar-newrow {
|
|
534
|
+
flex: 0 0 auto;
|
|
535
|
+
padding: 8px 8px 6px;
|
|
536
|
+
}
|
|
537
|
+
.chat-sidebar-new {
|
|
538
|
+
display: flex; align-items: center; gap: 7px; width: 100%;
|
|
539
|
+
border: none; background: transparent; color: var(--ink);
|
|
540
|
+
padding: 7px 10px; border-radius: 8px;
|
|
541
|
+
font-size: 13.5px; font-weight: 600; text-align: left; cursor: pointer;
|
|
542
|
+
transition: background .15s ease;
|
|
543
|
+
}
|
|
544
|
+
/* ⊕ 圆圈加号:整体外径约 14px,略小于 13.5px 文字高度(描边同步加粗以免缩小后发虚) */
|
|
545
|
+
.chat-sidebar-new-icon {
|
|
546
|
+
width: 8px; height: 8px; flex: 0 0 auto;
|
|
547
|
+
border: 1.2px solid currentColor; border-radius: 50%;
|
|
548
|
+
padding: 1.5px; box-sizing: content-box;
|
|
549
|
+
fill: none; stroke: currentColor; stroke-width: 3.2; stroke-linecap: round;
|
|
550
|
+
}
|
|
551
|
+
.chat-sidebar-list { flex: 1; overflow-y: auto; padding: 10px 8px 8px; }
|
|
552
|
+
.chat-sidebar-empty { padding: 24px 12px; font-size: 13px; color: var(--ink-soft); text-align: center; }
|
|
553
|
+
.chat-sidebar-item {
|
|
554
|
+
display: flex; align-items: center; gap: 8px;
|
|
555
|
+
padding: 6px 10px; border-radius: 9px; cursor: pointer;
|
|
556
|
+
transition: background .15s ease;
|
|
557
|
+
}
|
|
558
|
+
.chat-sidebar-item.is-active { background: var(--active); }
|
|
559
|
+
/* 会话项主体:标题 + 时间(hover 时时间隐藏、位置让给编辑/删除按钮)同行,标题单行。
|
|
560
|
+
main 固定 22px 行高、按钮与文字同高 → hover 前后 item 高度恒定、不抖动 */
|
|
561
|
+
.chat-sidebar-item-main {
|
|
562
|
+
flex: 1 1 auto; min-width: 0;
|
|
563
|
+
display: flex; flex-direction: row; align-items: center; gap: 6px;
|
|
564
|
+
height: 26px;
|
|
565
|
+
}
|
|
566
|
+
.chat-sidebar-item-title {
|
|
567
|
+
flex: 1 1 auto; min-width: 0; overflow: hidden; white-space: nowrap;
|
|
568
|
+
font-size: 13px; color: var(--ink);
|
|
569
|
+
}
|
|
570
|
+
.chat-sidebar-item-title:not(.is-marquee) .chat-sidebar-item-title-text {
|
|
571
|
+
display: block; width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
572
|
+
}
|
|
573
|
+
.chat-sidebar-item-title-text { display: inline-block; white-space: nowrap; width: max-content; min-width: 100%; line-height: 26px; }
|
|
574
|
+
/* 超长标题走马灯:默认不播放(transform 归零 = 标题开头),hover 播放;
|
|
575
|
+
鼠标移走后 animation 移除 → 立即回到标题开始处 */
|
|
576
|
+
.chat-sidebar-item-title.is-marquee .chat-sidebar-item-title-text {
|
|
577
|
+
animation: none;
|
|
578
|
+
display: block; width: 100%; overflow: hidden; text-overflow: ellipsis;
|
|
579
|
+
}
|
|
580
|
+
/* 非 hover:只显示单份 t1 并省略,避免双份文本在裁切窗口里拼接成重复 */
|
|
581
|
+
.chat-sidebar-item-title.is-marquee .chat-sidebar-item-title-t2 { display: none; }
|
|
582
|
+
.chat-sidebar-item-title-t1, .chat-sidebar-item-title-t2 { display: inline-block; }
|
|
583
|
+
@keyframes chatTitleMarquee {
|
|
584
|
+
0% { transform: translateX(0); }
|
|
585
|
+
100% { transform: translateX(-50%); }
|
|
586
|
+
}
|
|
587
|
+
.chat-sidebar-item-time { flex: 0 0 auto; font-size: 11px; color: #9aa1ab; line-height: 26px; }
|
|
588
|
+
/* 会话运行中:时间位显示黑白灰转圈动画(颜色随主题变量 --spin-edge/--spin-top 明暗变化) */
|
|
589
|
+
.chat-sidebar-item-spinner {
|
|
590
|
+
display: inline-block; width: 12px; height: 12px; box-sizing: border-box;
|
|
591
|
+
border: 2px solid var(--spin-edge); border-top-color: var(--spin-top);
|
|
592
|
+
border-radius: 50%; animation: chatSpin .7s linear infinite;
|
|
593
|
+
vertical-align: -2px;
|
|
594
|
+
}
|
|
595
|
+
/* 后台跑完、当前未查看的会话:时间位显示小绿圈(点进该会话即消失)。
|
|
596
|
+
实心绿点 + 轻微脉冲,在明暗主题下均醒目,但不喧宾夺主。 */
|
|
597
|
+
.chat-sidebar-item-done {
|
|
598
|
+
display: inline-block; width: 8px; height: 8px; box-sizing: border-box;
|
|
599
|
+
border-radius: 50%; background: #21b573; vertical-align: 0;
|
|
600
|
+
box-shadow: 0 0 0 0 rgba(33, 181, 115, .5);
|
|
601
|
+
animation: chatSidebarDonePulse 1.6s ease-out infinite;
|
|
602
|
+
}
|
|
603
|
+
@keyframes chatSidebarDonePulse {
|
|
604
|
+
0% { box-shadow: 0 0 0 0 rgba(33, 181, 115, .5); }
|
|
605
|
+
70% { box-shadow: 0 0 0 5px rgba(33, 181, 115, 0); }
|
|
606
|
+
100% { box-shadow: 0 0 0 0 rgba(33, 181, 115, 0); }
|
|
607
|
+
}
|
|
608
|
+
/* hover 时时间隐藏,⋯ 按钮原位出现(点开重命名/删除菜单)。actions 不被标题挤压 */
|
|
609
|
+
.chat-sidebar-item-actions { display: none; align-items: center; gap: 0; flex: 0 0 auto; }
|
|
610
|
+
.chat-sidebar-item-act {
|
|
611
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
612
|
+
width: 26px; height: 26px; border-radius: 50%;
|
|
613
|
+
border: none; background: transparent; color: var(--ink-soft); cursor: pointer;
|
|
614
|
+
transition: color .15s ease;
|
|
615
|
+
}
|
|
616
|
+
.chat-sidebar-item-act svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
|
|
617
|
+
/* 会话条目 ⋯ 按钮:复用 msg-footer「更多」图标——实心圆点(fill 当前色、无描边),菜单打开时高亮 */
|
|
618
|
+
.chat-sidebar-item-act.chat-sidebar-item-more svg { width: 17px; height: 17px; }
|
|
619
|
+
.chat-sidebar-item-act.chat-sidebar-item-more svg circle { fill: currentColor; stroke: none; }
|
|
620
|
+
.chat-sidebar-item-act.chat-sidebar-item-more.is-open { color: var(--ink); background: var(--line); }
|
|
621
|
+
/* 侧栏分组 ⋯ 与条目 ⋯ 视觉统一:同为实心圆点(与 msg-footer「更多」一致) */
|
|
622
|
+
.chat-sidebar-group-more svg circle,
|
|
623
|
+
.chat-sidebar-item-more svg circle { fill: currentColor; stroke: none; }
|
|
624
|
+
.chat-sidebar-rename-input {
|
|
625
|
+
flex: 1 1 auto; min-width: 0;
|
|
626
|
+
border: 1px solid var(--line); border-radius: 6px; padding: 5px 8px;
|
|
627
|
+
font-size: 13px; background: var(--field-bg); color: var(--ink); outline: none;
|
|
628
|
+
}
|
|
629
|
+
.chat-sidebar-rename-input:focus { border-color: var(--brand); }
|
|
630
|
+
/* 结构化提问卡片(AskUserQuestion):模型需要用户确认/选择时,正文下方渲染的交互卡片 */
|
|
631
|
+
.chat-question-area { display: flex; flex-direction: column; gap: 12px; margin-top: 12px; margin-bottom: 4px; }
|
|
632
|
+
.chat-question-wrap { display: flex; flex-direction: column; gap: 10px; }
|
|
633
|
+
.chat-question-card {
|
|
634
|
+
border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px;
|
|
635
|
+
background: var(--panel); display: flex; flex-direction: column; gap: 8px;
|
|
636
|
+
}
|
|
637
|
+
.chat-question-header {
|
|
638
|
+
align-self: flex-start; font-size: 11px; font-weight: 700; color: var(--ink-soft);
|
|
639
|
+
background: var(--hover); border-radius: 999px; padding: 2px 10px;
|
|
640
|
+
}
|
|
641
|
+
.chat-question-text { font-size: 15px; color: var(--ink); line-height: 1.5; }
|
|
642
|
+
.chat-question-options { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
643
|
+
.chat-question-opt {
|
|
644
|
+
display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
|
|
645
|
+
border: 1px solid var(--line); background: var(--field-bg); border-radius: 9px;
|
|
646
|
+
padding: 8px 12px; cursor: pointer; font-size: 12.5px; color: var(--ink);
|
|
647
|
+
transition: border-color .15s ease, background .15s ease;
|
|
648
|
+
}
|
|
649
|
+
.chat-question-opt-label { font-weight: 600; }
|
|
650
|
+
.chat-question-opt-desc { color: var(--ink-soft); font-size: 12px; }
|
|
651
|
+
.chat-question-opt.is-selected {
|
|
652
|
+
border-color: var(--ink); background: var(--hover);
|
|
653
|
+
box-shadow: 0 0 0 1px var(--ink) inset;
|
|
654
|
+
}
|
|
655
|
+
.chat-question-opt.is-selected .chat-question-opt-label::after {
|
|
656
|
+
content: " ✓"; color: var(--ink); font-weight: 700;
|
|
657
|
+
}
|
|
658
|
+
.chat-question-multi {
|
|
659
|
+
margin-left: 6px; font-size: 11px; color: var(--ink-soft); font-weight: 400;
|
|
660
|
+
}
|
|
661
|
+
.chat-question-other { display: flex; flex-direction: column; gap: 4px; margin-top: 4px; }
|
|
662
|
+
.chat-question-other-label { font-size: 11px; color: var(--ink-soft); }
|
|
663
|
+
.chat-question-other-input {
|
|
664
|
+
width: 100%; box-sizing: border-box;
|
|
665
|
+
border: 1px solid var(--line); border-radius: 8px;
|
|
666
|
+
background: var(--field-bg); color: var(--ink);
|
|
667
|
+
padding: 7px 10px; font-size: 13px;
|
|
668
|
+
}
|
|
669
|
+
.chat-question-other-input::placeholder { color: var(--ink-soft); opacity: .8; }
|
|
670
|
+
.chat-question-other-input:focus { outline: none; border-color: var(--ink); }
|
|
671
|
+
.chat-question-submit-row { display: flex; justify-content: flex-end; margin-top: 2px; }
|
|
672
|
+
.chat-question-submit {
|
|
673
|
+
border: none; border-radius: 999px; padding: 7px 18px; cursor: pointer;
|
|
674
|
+
font-size: 13px; font-weight: 600; color: var(--panel); background: var(--ink);
|
|
675
|
+
transition: opacity .15s ease, transform .1s ease;
|
|
676
|
+
}
|
|
677
|
+
.chat-question-submit:active:not(:disabled) { transform: scale(.98); }
|
|
678
|
+
.chat-question-submit:disabled {
|
|
679
|
+
background: var(--line); color: var(--ink-soft); cursor: not-allowed; font-weight: 500;
|
|
680
|
+
}
|
|
681
|
+
.chat-question-card--done { background: var(--hover); border-style: dashed; }
|
|
682
|
+
.chat-question-answered-badge {
|
|
683
|
+
align-self: flex-start; font-size: 12px; font-weight: 700; color: var(--ink);
|
|
684
|
+
}
|
|
685
|
+
.chat-question-answered-text {
|
|
686
|
+
font-size: 13px; color: var(--ink); line-height: 1.6; white-space: pre-wrap;
|
|
687
|
+
}
|
|
688
|
+
.chat-title { font-weight: 700; font-size: 15px; letter-spacing: .3px; }
|
|
689
|
+
.chat-title--center {
|
|
690
|
+
position: absolute; left: 50%; transform: translateX(-50%);
|
|
691
|
+
white-space: nowrap;
|
|
692
|
+
}
|
|
693
|
+
/* 顶栏左侧会话标题:单行省略,给右侧四个按钮让位。
|
|
694
|
+
上限用 min(100%, 420px) 相对父容器而非 vw——vw 以视口计,右侧面板打开
|
|
695
|
+
挤窄中栏时 32vw 仍按整窗计算,会把按钮组推出顶栏右缘(历史 bug)。 */
|
|
696
|
+
.chat-title--left {
|
|
697
|
+
flex: 0 1 auto; min-width: 0;
|
|
698
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
699
|
+
max-width: min(100%, 420px);
|
|
700
|
+
}
|
|
701
|
+
/* 顶栏图标按钮(search / 分享 / 历史):视觉与 .chat-sidebar-toggle 一致 */
|
|
702
|
+
.chat-topbar-btn {
|
|
703
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
704
|
+
width: 34px; height: 34px; border-radius: 8px;
|
|
705
|
+
border: none; background: transparent; color: var(--ink-soft); cursor: pointer;
|
|
706
|
+
transition: background .15s ease, color .15s ease;
|
|
707
|
+
}
|
|
708
|
+
.chat-topbar-btn.is-active { background: rgba(31,79,214,.10); color: var(--brand); }
|
|
709
|
+
.chat-topbar-btn svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
|
|
710
|
+
/* 分享图标:采用 Ionicons arrow-redo-outline(闭合轮廓的空心曲线箭头,箭头有身体、内部空心) */
|
|
711
|
+
/* 描边宽度跟随顶栏通用值 1.8,与 search/history 等图标保持一致(不再单独加粗) */
|
|
712
|
+
.chat-topbar-btn[aria-label="分享"] svg { stroke-width: 1.8; }
|
|
713
|
+
.chat-topbar-right { gap: 6px; }
|
|
714
|
+
|
|
715
|
+
/* 面板打开时顶栏保持在遮罩之上(点其它顶栏按钮可切换面板) */
|
|
716
|
+
.chat-topbar { z-index: 220; }
|
|
717
|
+
/* 面板点击关闭遮罩:盖住中栏内容区(顶栏 z 更高不受影响) */
|
|
718
|
+
.chat-panel-backdrop {
|
|
719
|
+
position: fixed; inset: 0; z-index: 200;
|
|
720
|
+
background: transparent;
|
|
721
|
+
}
|
|
722
|
+
/* ---- 对话内搜索条(顶栏下方) ---- */
|
|
723
|
+
.chat-search-bar {
|
|
724
|
+
flex: 0 0 auto;
|
|
725
|
+
display: flex; align-items: center; gap: 8px;
|
|
726
|
+
padding: 8px 16px;
|
|
727
|
+
border-bottom: 1px solid var(--line); background: var(--panel);
|
|
728
|
+
z-index: 210;
|
|
729
|
+
}
|
|
730
|
+
.chat-search-bar-icon { width: 16px; height: 16px; flex: 0 0 auto; fill: none; stroke: var(--ink-soft); stroke-width: 1.8; stroke-linecap: round; }
|
|
731
|
+
.chat-search-bar-input {
|
|
732
|
+
flex: 1 1 auto; min-width: 0; height: 30px;
|
|
733
|
+
border: 1px solid var(--line); border-radius: 8px; background: var(--field-bg);
|
|
734
|
+
padding: 0 10px; font-size: 13px; color: var(--ink); outline: none;
|
|
735
|
+
}
|
|
736
|
+
.chat-search-bar-input:focus { border-color: var(--brand); }
|
|
737
|
+
.chat-search-bar-count {
|
|
738
|
+
flex: 0 0 auto; font-size: 12px; color: var(--ink-soft);
|
|
739
|
+
font-variant-numeric: tabular-nums; min-width: 34px; text-align: center;
|
|
740
|
+
}
|
|
741
|
+
.chat-search-bar-btn {
|
|
742
|
+
flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
|
|
743
|
+
width: 30px; height: 30px; border-radius: 7px;
|
|
744
|
+
border: none; background: transparent; color: var(--ink-soft); cursor: pointer;
|
|
745
|
+
}
|
|
746
|
+
.chat-search-bar-btn svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
|
|
747
|
+
.chat-search-bar-close { color: var(--ink-soft); }
|
|
748
|
+
|
|
749
|
+
/* ---- 历史提问下拉 ---- */
|
|
750
|
+
.chat-history-pop,
|
|
751
|
+
.chat-share-pop {
|
|
752
|
+
position: absolute; top: 66px; right: 12px; z-index: 230;
|
|
753
|
+
width: min(360px, calc(100vw - 24px));
|
|
754
|
+
background: var(--overlay-bg); border: 1px solid var(--line); border-radius: 12px;
|
|
755
|
+
box-shadow: 0 12px 32px rgba(20, 27, 38, .16);
|
|
756
|
+
overflow: hidden;
|
|
757
|
+
}
|
|
758
|
+
.chat-history-head {
|
|
759
|
+
padding: 12px 14px; font-size: 13px; font-weight: 700; color: var(--ink);
|
|
760
|
+
border-bottom: 1px solid var(--line);
|
|
761
|
+
}
|
|
762
|
+
.chat-history-list { max-height: min(56vh, 420px); overflow-y: auto; padding: 6px; }
|
|
763
|
+
.chat-history-empty { padding: 22px 14px; text-align: center; font-size: 13px; color: var(--ink-soft); }
|
|
764
|
+
.chat-history-item {
|
|
765
|
+
display: flex; align-items: flex-start; width: 100%; text-align: left;
|
|
766
|
+
border: none; background: transparent; cursor: pointer;
|
|
767
|
+
padding: 9px 10px; border-radius: 8px; font-size: 13px; color: var(--ink);
|
|
768
|
+
line-height: 1.5;
|
|
769
|
+
}
|
|
770
|
+
.chat-history-item + .chat-history-item { margin-top: 2px; }
|
|
771
|
+
.chat-history-text {
|
|
772
|
+
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
773
|
+
overflow: hidden; word-break: break-word;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
/* ---- 分享面板:三选项(复制链接 / 浏览器打开 / 发送到 OA 聊天) ---- */
|
|
777
|
+
.chat-share-head {
|
|
778
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
779
|
+
padding: 12px 14px; font-size: 13px; font-weight: 700; color: var(--ink);
|
|
780
|
+
border-bottom: 1px solid var(--line);
|
|
781
|
+
}
|
|
782
|
+
.chat-share-close {
|
|
783
|
+
flex: 0 0 auto; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center;
|
|
784
|
+
border: none; background: transparent; border-radius: 6px; cursor: pointer; color: var(--ink-soft);
|
|
785
|
+
}
|
|
786
|
+
.chat-share-close svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
|
|
787
|
+
.chat-share-loading,
|
|
788
|
+
.chat-share-error { padding: 16px 14px; font-size: 13px; color: var(--ink-soft); }
|
|
789
|
+
.chat-share-error { color: var(--danger); }
|
|
790
|
+
.chat-share-opt {
|
|
791
|
+
display: flex; align-items: center; gap: 11px; width: 100%;
|
|
792
|
+
padding: 11px 14px; border: none; background: transparent; cursor: pointer; text-align: left;
|
|
793
|
+
}
|
|
794
|
+
.chat-share-opt + .chat-share-opt { border-top: 1px solid var(--line); }
|
|
795
|
+
.chat-share-opt:disabled { opacity: .55; cursor: default; }
|
|
796
|
+
.chat-share-opt-icon {
|
|
797
|
+
flex: 0 0 auto; width: 34px; height: 34px; display: flex; align-items: center; justify-content: center;
|
|
798
|
+
background: var(--field-soft); border-radius: 9px; color: var(--ink);
|
|
799
|
+
}
|
|
800
|
+
.chat-share-opt-icon svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
|
|
801
|
+
.chat-share-opt-body { display: flex; flex-direction: column; min-width: 0; }
|
|
802
|
+
.chat-share-opt-title { font-size: 13.5px; font-weight: 600; color: var(--ink); }
|
|
803
|
+
.chat-share-opt-desc { font-size: 12px; color: var(--ink-soft); margin-top: 2px; }
|
|
804
|
+
.chat-share-opt-state { flex: 0 0 auto; margin-left: auto; font-size: 12px; color: #1f9d55; font-weight: 600; }
|
|
805
|
+
.chat-share-oa-msg { margin: 4px 14px 12px; font-size: 12px; color: #1f9d55; }
|
|
806
|
+
.chat-share-oa-msg.is-error { color: var(--danger); }
|
|
807
|
+
/* 飞书分享成功后的轻提示条:与上方操作项区分,作为"已分享"反馈,整条可点击跳转会话 */
|
|
808
|
+
.chat-share-oa-link {
|
|
809
|
+
display: flex; align-items: center; gap: 6px;
|
|
810
|
+
margin: 2px 14px 12px; padding: 7px 10px;
|
|
811
|
+
width: calc(100% - 28px); box-sizing: border-box;
|
|
812
|
+
border: 1px solid var(--line); border-radius: 8px;
|
|
813
|
+
background: var(--hover); cursor: pointer;
|
|
814
|
+
font-size: 12px; color: #1f9d55; font-weight: 600;
|
|
815
|
+
text-align: left; transition: background 0.15s ease;
|
|
816
|
+
}
|
|
817
|
+
.chat-share-oa-link svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; flex: 0 0 auto; }
|
|
818
|
+
/* 分享直达发送(未打开面板)的结果反馈:顶部居中 toast,黑白灰系 */
|
|
819
|
+
.chat-share-toast {
|
|
820
|
+
position: fixed;
|
|
821
|
+
top: 14px;
|
|
822
|
+
left: 50%;
|
|
823
|
+
transform: translateX(-50%);
|
|
824
|
+
z-index: 1000;
|
|
825
|
+
padding: 7px 16px;
|
|
826
|
+
border: 1px solid var(--line);
|
|
827
|
+
border-radius: 10px;
|
|
828
|
+
background: var(--toast-bg);
|
|
829
|
+
color: var(--ink);
|
|
830
|
+
font-size: 13px;
|
|
831
|
+
box-shadow: 0 6px 24px rgba(31, 39, 51, 0.12);
|
|
832
|
+
animation: chatShareToastIn 0.18s ease-out;
|
|
833
|
+
}
|
|
834
|
+
.chat-share-toast.is-error { color: var(--danger); border-color: #f1d6d6; }
|
|
835
|
+
@keyframes chatShareToastIn {
|
|
836
|
+
from { opacity: 0; transform: translateX(-50%) translateY(-6px); }
|
|
837
|
+
to { opacity: 1; transform: translateX(-50%) translateY(0); }
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
/* 搜索命中高亮(黑白灰系,参考 wb):淡灰边框 + 内边距让边框与内容留出呼吸感;
|
|
841
|
+
命中关键字由正文里的 <mark> 背景高亮(见 Markdown.tsx / UserBubble 的 highlight) */
|
|
842
|
+
.msg.is-search-hit {
|
|
843
|
+
border: 1px solid var(--line);
|
|
844
|
+
border-radius: 12px;
|
|
845
|
+
padding: 8px 10px;
|
|
846
|
+
background: var(--field-soft);
|
|
847
|
+
}
|
|
848
|
+
/* 当前定位的命中:边框加深一档 + 背景更实 */
|
|
849
|
+
.msg.is-search-current {
|
|
850
|
+
border-color: var(--line);
|
|
851
|
+
background: var(--hover-strong);
|
|
852
|
+
}
|
|
853
|
+
mark {
|
|
854
|
+
background: var(--mark-bg);
|
|
855
|
+
color: inherit;
|
|
856
|
+
border-radius: 3px;
|
|
857
|
+
padding: 0 2px;
|
|
858
|
+
}
|
|
859
|
+
.chat-user-avatar {
|
|
860
|
+
width: 32px; height: 32px; border-radius: 50%; object-fit: cover;
|
|
861
|
+
border: 1px solid var(--line); display: block;
|
|
862
|
+
}
|
|
863
|
+
.chat-user-avatar--fallback {
|
|
864
|
+
background: linear-gradient(135deg, var(--brand), #6b8bff); color: #fff;
|
|
865
|
+
display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 13px;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
/* 聊天滚动容器:全宽(滚动条贴最右缘,与 wb/豆包 work 一致),
|
|
869
|
+
消息内容在内部 .chat-body-inner 限宽中栏 80% 居中。
|
|
870
|
+
scrollbar-gutter: stable:滚动条出现/消失(展开收起思考框导致溢出变化)时始终预留
|
|
871
|
+
等宽 gutter,内容区宽度恒定——否则滚动条出现瞬间消息列表会整体左移抖动。 */
|
|
872
|
+
.chat-body {
|
|
873
|
+
flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 0; display: block; scrollbar-gutter: stable;
|
|
874
|
+
/* 滚动容器全宽:滚动条贴聊天区最右缘(右栏打开时 = 右栏左侧),
|
|
875
|
+
消息内容限宽由 .chat-body-inner 承担(min(80%, 1200px) 居中) */
|
|
876
|
+
width: 100%; max-width: none; margin: 0;
|
|
877
|
+
}
|
|
878
|
+
.chat-body-inner {
|
|
879
|
+
width: 100%; max-width: min(80%, 1200px); margin: 0 auto;
|
|
880
|
+
box-sizing: border-box;
|
|
881
|
+
/* 底部留白(WorkBuddy 同款):消息区垂直高度略大于内容,滚动到底后还能再滚一段,
|
|
882
|
+
让最后一条回复上方的「更多」菜单向上弹出时有足够空间,不会顶出视口 */
|
|
883
|
+
padding: 20px 26px 120px 18px;
|
|
884
|
+
display: flex; flex-direction: column; gap: 14px;
|
|
885
|
+
}
|
|
886
|
+
/* 流式置顶 reserve:消息列表底部的动态 spacer(纯占位,无内容、无背景)。
|
|
887
|
+
高度由 useChatScroll 的 syncStreamScroll() 计算并实时写入:
|
|
888
|
+
reserve = max(0, 用户消息偏移 + 一屏 V − 真实内容高)
|
|
889
|
+
设历史消息高 x、新发消息高 h、回复高 r、视口高 V:
|
|
890
|
+
- 置顶:reserve 补足「把用户消息顶到视口顶部」所需的滚动范围(否则 scrollTop 被浏览器 clamp)。
|
|
891
|
+
- 回复未填满(h+r ≤ V):reserve = V − h − r,总高度 = x + V 恒定 → scrollTop 纹丝不动,
|
|
892
|
+
不抖动;此时「新消息下方到输入区之间的空白」= V − h,满足「空白 + h = 可见高度 V」。
|
|
893
|
+
- 回复写长:reserve 自动归零,内容自撑,一次性平滑切到底部跟随。
|
|
894
|
+
|
|
895
|
+
★ 实现硬约束(踩坑记录,勿改):测「真实内容高」绝不能把 spacer 临时置 0 再读 scrollHeight。
|
|
896
|
+
scrollHeight 瞬间变短 → 浏览器立即 clamp scrollTop → spacer 恢复后 scrollTop 不回来,
|
|
897
|
+
表现为「LLM 一开始输出,整条消息列表瞬间掉到下面」。必须用 scrollHeight − spacer 实际高度 反推。 */
|
|
898
|
+
.chat-stream-spacer { flex: 0 0 auto; width: 100%; }
|
|
899
|
+
.chat-empty { margin: auto; text-align: center; color: var(--ink-soft); max-width: 360px; }
|
|
900
|
+
.chat-empty h2 { color: var(--ink); font-size: 18px; margin: 0 0 8px; }
|
|
901
|
+
.chat-empty p { font-size: 14px; line-height: 1.6; }
|
|
902
|
+
.chat-loading-state { padding: 18px 12px; color: var(--ink-soft); font-size: 12.5px; }
|
|
903
|
+
.chat-loading-caption { display: flex; align-items: center; gap: 8px; justify-content: center; line-height: 20px; }
|
|
904
|
+
.chat-loading-spinner {
|
|
905
|
+
display: inline-block; flex: 0 0 16px; width: 16px; height: 16px; box-sizing: border-box;
|
|
906
|
+
border: 2px solid var(--spin-edge); border-top-color: var(--spin-top);
|
|
907
|
+
border-radius: 50%; animation: chatSpin .75s linear infinite;
|
|
908
|
+
}
|
|
909
|
+
.chat-loading-state--session { display: flex; align-items: center; justify-content: center; min-height: 160px; flex: 1; }
|
|
910
|
+
.chat-body.is-loading .chat-body-inner { min-height: 100%; padding-bottom: 20px; }
|
|
911
|
+
.chat-loading-state--sidebar { padding: 12px 8px; }
|
|
912
|
+
.chat-loading-state--sidebar .chat-loading-caption { justify-content: flex-start; padding: 0 4px 10px; }
|
|
913
|
+
.chat-loading-state--artifacts { padding: 16px 12px; }
|
|
914
|
+
.chat-loading-skeleton { display: flex; flex-direction: column; gap: 12px; margin-top: 14px; }
|
|
915
|
+
.chat-loading-skeleton-row { display: flex; align-items: center; gap: 10px; min-height: 25px; }
|
|
916
|
+
.chat-loading-state--artifacts .chat-loading-skeleton-row { min-height: 48px; padding: 8px; border: 1px solid var(--line); border-radius: 8px; }
|
|
917
|
+
.chat-loading-skeleton-lines { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
|
|
918
|
+
.chat-loading-skeleton-line, .chat-loading-skeleton-icon {
|
|
919
|
+
display: block; border-radius: 5px;
|
|
920
|
+
background: linear-gradient(90deg, var(--hover-strong) 20%, var(--line) 50%, var(--hover-strong) 80%);
|
|
921
|
+
background-size: 240% 100%; animation: chatSkeletonShine 1.6s ease-in-out infinite;
|
|
922
|
+
}
|
|
923
|
+
.chat-loading-skeleton-line { height: 11px; width: 86%; }
|
|
924
|
+
.chat-loading-skeleton-row:nth-child(2n) .chat-loading-skeleton-line { width: 67%; }
|
|
925
|
+
.chat-loading-skeleton-line.is-short { height: 8px; width: 36%; }
|
|
926
|
+
.chat-loading-skeleton-icon { flex: 0 0 28px; width: 28px; height: 32px; }
|
|
927
|
+
.chat-loading-error { display: flex; align-items: center; justify-content: center; gap: 8px; padding: 22px 12px; color: var(--ink-soft); font-size: 12.5px; }
|
|
928
|
+
.chat-loading-error button { border: 1px solid var(--line); border-radius: 6px; background: transparent; color: var(--ink); cursor: pointer; padding: 4px 9px; }
|
|
929
|
+
@keyframes chatSkeletonShine { from { background-position: 100% 0; } to { background-position: -100% 0; } }
|
|
930
|
+
@media (prefers-reduced-motion: reduce) {
|
|
931
|
+
.chat-loading-spinner, .chat-loading-skeleton-line, .chat-loading-skeleton-icon { animation: none; }
|
|
932
|
+
}
|
|
933
|
+
.chat-suggestions { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-top: 16px; }
|
|
934
|
+
.chat-suggestions button {
|
|
935
|
+
border: 1px solid var(--line); background: var(--hover-strong); color: var(--ink);
|
|
936
|
+
border-radius: 999px; padding: 7px 13px; font-size: 13px; cursor: pointer;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
.msg { display: flex; max-width: 100%; min-width: 0; }
|
|
940
|
+
/* 用户消息:整体右对齐(消息块靠右),气泡内部文字左对齐。
|
|
941
|
+
宽屏时限制 860px 最大宽度(对标豆包 Work 不占满、右侧留白);中栏被挤压变窄时
|
|
942
|
+
min(100%, 860px) 自动取小 → 逐渐占满全部宽度(连续无断点)。答复保持全宽左对齐。 */
|
|
943
|
+
.msg.user {
|
|
944
|
+
align-self: flex-end; flex-direction: column; align-items: flex-end;
|
|
945
|
+
max-width: min(100%, 860px);
|
|
946
|
+
}
|
|
947
|
+
.msg.bot { align-self: flex-start; flex-direction: column; width: 100%; }
|
|
948
|
+
.msg.user .bubble { text-align: left; }
|
|
949
|
+
.msg.bot .bubble { text-align: left; }
|
|
950
|
+
.msg .bubble {
|
|
951
|
+
padding: 11px 14px; border-radius: 14px; font-size: 15.5px; line-height: 1.65;
|
|
952
|
+
white-space: pre-wrap; word-break: break-word; overflow-wrap: anywhere; min-width: 0;
|
|
953
|
+
max-width: 100%;
|
|
954
|
+
}
|
|
955
|
+
/* 用户消息里的文件部分:带背景的圆角矩形条,与输入文字明确区分。
|
|
956
|
+
.msg-attachment = 有附件元数据的消息(气泡上方可点链接);
|
|
957
|
+
.msg-inline-file = 恢复的历史消息里残留 "[附件] 文件名" 文本时解析出的文件条 */
|
|
958
|
+
.msg-attachment,
|
|
959
|
+
.msg-inline-file {
|
|
960
|
+
display: inline-flex; align-items: center; gap: 5px;
|
|
961
|
+
max-width: 100%; overflow-wrap: anywhere;
|
|
962
|
+
background: var(--brand-soft); border: 1px solid var(--brand-line); border-radius: 8px;
|
|
963
|
+
padding: 2px 8px; font-size: 12.5px; color: var(--brand-dark);
|
|
964
|
+
}
|
|
965
|
+
/* vertical-align: middle:附件条与同行正文垂直居中(缺省基线对齐会因 flex 盒/小字号
|
|
966
|
+
文件名的合成基线不同而错位);上下对称 margin,避免不对称 margin 盒把居中点顶偏 */
|
|
967
|
+
.msg-attachment { text-decoration: none; margin: 2px 8px 2px 0; vertical-align: middle; }
|
|
968
|
+
.msg-inline-file { margin: 2px 8px 2px 0; vertical-align: middle; }
|
|
969
|
+
/* 附件条内图标:与文件名之间用 CSS gap 控制,替代 emoji 字符间距不可控的问题 */
|
|
970
|
+
.msg-attachment-icon,
|
|
971
|
+
.msg-inline-file-icon {
|
|
972
|
+
flex: none;
|
|
973
|
+
display: grid;
|
|
974
|
+
place-items: center;
|
|
975
|
+
width: 14px;
|
|
976
|
+
height: 14px;
|
|
977
|
+
color: currentColor;
|
|
978
|
+
}
|
|
979
|
+
.msg-attachment-icon svg,
|
|
980
|
+
.msg-inline-file-icon svg {
|
|
981
|
+
width: 14px;
|
|
982
|
+
height: 14px;
|
|
983
|
+
fill: none;
|
|
984
|
+
stroke: currentColor;
|
|
985
|
+
stroke-width: 2;
|
|
986
|
+
stroke-linecap: round;
|
|
987
|
+
stroke-linejoin: round;
|
|
988
|
+
}
|
|
989
|
+
.msg-attachment-name,
|
|
990
|
+
.msg-inline-file-name {
|
|
991
|
+
min-width: 0;
|
|
992
|
+
}
|
|
993
|
+
.msg.bot .bubble { align-self: flex-start; background: transparent; color: var(--ink); padding: 2px 0; border-bottom-left-radius: 4px; }
|
|
994
|
+
.msg.user .bubble { background: var(--user-bubble-soft); color: var(--ink); border-bottom-right-radius: 4px; }
|
|
995
|
+
.msg .typing { display: inline-flex; gap: 4px; align-items: center; }
|
|
996
|
+
.msg .typing i { width: 6px; height: 6px; border-radius: 50%; background: #9aa6b8; animation: blink 1.2s infinite; }
|
|
997
|
+
.msg .typing i:nth-child(2){ animation-delay: .2s } .msg .typing i:nth-child(3){ animation-delay: .4s }
|
|
998
|
+
@keyframes blink { 0%,80%,100%{opacity:.3} 40%{opacity:1} }
|
|
999
|
+
|
|
1000
|
+
/* ===== 负责人名片卡片(每条 AI 回答末尾,独占一行、左对齐)===== */
|
|
1001
|
+
.chat-owner-wrap { display: block; width: 100%; margin-top: 12px; clear: both; }
|
|
1002
|
+
/* 答案与「转人工」之间的过渡分隔:左线—文字—右线 */
|
|
1003
|
+
.chat-owner-divider {
|
|
1004
|
+
display: flex; align-items: center; gap: 10px;
|
|
1005
|
+
margin: 2px 0 10px;
|
|
1006
|
+
color: var(--ink-soft); font-size: 12px; letter-spacing: .3px; opacity: .85;
|
|
1007
|
+
}
|
|
1008
|
+
.chat-owner-divider::before,
|
|
1009
|
+
.chat-owner-divider::after {
|
|
1010
|
+
content: ""; flex: 1; height: 1px; background: var(--line);
|
|
1011
|
+
}
|
|
1012
|
+
.chat-owner-card {
|
|
1013
|
+
display: flex; align-items: center; gap: 10px;
|
|
1014
|
+
padding: 10px 12px 10px 8px;
|
|
1015
|
+
border: 1px solid var(--line); border-radius: 12px;
|
|
1016
|
+
background: var(--panel); cursor: pointer; text-align: left;
|
|
1017
|
+
box-shadow: 0 1px 4px rgba(31, 39, 51, .06);
|
|
1018
|
+
transition: border-color .15s, box-shadow .15s;
|
|
1019
|
+
flex: none;
|
|
1020
|
+
}
|
|
1021
|
+
/* 责任人卡片 + 评分卡片:同一行、两端对齐(责任人靠左 / 评分靠右);
|
|
1022
|
+
宽度不足时自动换行(小手机评分卡片落到下一行)。
|
|
1023
|
+
align-items: stretch 让两张卡片等高(以较高者为准),内容各自垂直居中。 */
|
|
1024
|
+
.chat-owner-cards {
|
|
1025
|
+
display: flex; align-items: stretch; justify-content: space-between;
|
|
1026
|
+
gap: 12px; flex-wrap: wrap;
|
|
1027
|
+
}
|
|
1028
|
+
.chat-owner-avatar {
|
|
1029
|
+
width: 36px; height: 36px; border-radius: 50%; flex: none;
|
|
1030
|
+
display: grid; place-items: center; overflow: hidden;
|
|
1031
|
+
background: linear-gradient(135deg, var(--brand), #6b8bff); color: #fff;
|
|
1032
|
+
font-weight: 700; font-size: 15px;
|
|
1033
|
+
}
|
|
1034
|
+
.chat-owner-avatar img { width: 100%; height: 100%; object-fit: cover; }
|
|
1035
|
+
.chat-owner-meta { display: flex; flex-direction: column; line-height: 1.25; }
|
|
1036
|
+
.chat-owner-name { font-weight: 600; font-size: 13.5px; color: var(--ink); }
|
|
1037
|
+
.chat-owner-dept { font-size: 12px; color: var(--ink-soft); }
|
|
1038
|
+
.chat-owner-action { margin-left: 6px; font-size: 12.5px; color: var(--brand); white-space: nowrap; }
|
|
1039
|
+
|
|
1040
|
+
/* ===== Markdown 渲染(react-markdown + remark-gfm + rehype-highlight)===== */
|
|
1041
|
+
/* ═══ 流式正文揭示:块级渐入(fade-in,对标 WorkBuddy)═══
|
|
1042
|
+
流式期间每个新到达的块级子元素(p / li / heading…)淡入一次,
|
|
1043
|
+
文字全程全实心可读;末尾保留闪烁光标 ▍ 作为"正在输出"信号。
|
|
1044
|
+
不再使用扫光(shimmer / mask-image),避免"前暗后亮"错位。 */
|
|
1045
|
+
|
|
1046
|
+
/* 流式「渐入」关键帧:每个新到达的文本块(p / li / heading…)淡入一次,
|
|
1047
|
+
对标 WorkBuddy 的流式渐入观感;文字全程全实心,不会出现扫光那种前暗后亮的错位。 */
|
|
1048
|
+
@keyframes mdFadeIn {
|
|
1049
|
+
from { opacity: 0; transform: translateY(3px); }
|
|
1050
|
+
to { opacity: 1; transform: translateY(0); }
|
|
1051
|
+
}
|
|
1052
|
+
@keyframes mdCaretBlink {
|
|
1053
|
+
50% { opacity: 0; }
|
|
1054
|
+
}
|
|
1055
|
+
/* 流式正文容器:定位上下文 + 逐块渐入。
|
|
1056
|
+
只作用于「块级子元素」,已稳定显示的块不会重播动画,只有流式中新追加的块会淡入。
|
|
1057
|
+
.md-table-wrap 豁免:表格在流式期间频繁更新,重播渐入会造成持续闪烁。 */
|
|
1058
|
+
.md--streaming { position: relative; }
|
|
1059
|
+
.md--streaming > *:not(.md-table-wrap) {
|
|
1060
|
+
animation: mdFadeIn .32s ease-out both;
|
|
1061
|
+
}
|
|
1062
|
+
/* 尾部光标:流式期间正文末尾闪烁 ▍,强化"正在输出" */
|
|
1063
|
+
.md--streaming::after {
|
|
1064
|
+
content: "▍";
|
|
1065
|
+
display: inline-block;
|
|
1066
|
+
margin-left: 2px;
|
|
1067
|
+
color: var(--ink-soft);
|
|
1068
|
+
animation: mdCaretBlink 1s steps(1) infinite;
|
|
1069
|
+
}
|
|
1070
|
+
/* 无障碍:减少动效时停掉渐入与光标闪烁(文字保持全实心,语义不丢) */
|
|
1071
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1072
|
+
.md--streaming > * { animation: none; transform: none; }
|
|
1073
|
+
.md--streaming::after { animation: none; opacity: 1; }
|
|
1074
|
+
}
|
|
1075
|
+
.bubble .md, .artifact-md .md{ font-size: 15.5px; line-height: 1.7; color: var(--ink); white-space: normal; overflow-wrap: anywhere; }
|
|
1076
|
+
.bubble .md > *:first-child, .artifact-md .md > *:first-child{ margin-top: 0; }
|
|
1077
|
+
.bubble .md > *:last-child, .artifact-md .md > *:last-child{ margin-bottom: 0; }
|
|
1078
|
+
.bubble .md p, .artifact-md .md p{ margin: 0 0 8px; }
|
|
1079
|
+
.bubble .md h1, .bubble .md h2, .bubble .md h3,
|
|
1080
|
+
.bubble .md h4, .bubble .md h5, .bubble .md h6, .artifact-md .md h1, .artifact-md .md h2, .artifact-md .md h3,
|
|
1081
|
+
.artifact-md .md h4, .artifact-md .md h5, .artifact-md .md h6{ margin: 12px 0 6px; line-height: 1.35; font-weight: 700; }
|
|
1082
|
+
.bubble .md h1, .artifact-md .md h1{ font-size: 20px; }
|
|
1083
|
+
.bubble .md h2, .artifact-md .md h2{ font-size: 18px; }
|
|
1084
|
+
.bubble .md h3, .artifact-md .md h3{ font-size: 16.5px; }
|
|
1085
|
+
.bubble .md h4, .bubble .md h5, .bubble .md h6, .artifact-md .md h4, .artifact-md .md h5, .artifact-md .md h6{ font-size: 15.5px; }
|
|
1086
|
+
.bubble .md ul, .bubble .md ol, .artifact-md .md ul, .artifact-md .md ol{ margin: 0 0 8px; padding-left: 22px; }
|
|
1087
|
+
.bubble .md li, .artifact-md .md li{ margin: 2px 0; }
|
|
1088
|
+
.bubble .md li.task-list-item, .artifact-md .md li.task-list-item{ list-style: none; margin-left: -22px; }
|
|
1089
|
+
.bubble .md li.task-list-item input[type="checkbox"], .artifact-md .md li.task-list-item input[type="checkbox"]{ margin-right: 6px; }
|
|
1090
|
+
.bubble .md a, .artifact-md .md a{ color: var(--brand); text-decoration: none; border-bottom: 1px solid rgba(47,107,255,.35); }
|
|
1091
|
+
.bubble .md strong, .artifact-md .md strong{ font-weight: 700; }
|
|
1092
|
+
.bubble .md em, .artifact-md .md em{ font-style: italic; }
|
|
1093
|
+
.bubble .md del, .artifact-md .md del{ color: var(--ink-soft); }
|
|
1094
|
+
/* 行内代码:非 pre 内 code */
|
|
1095
|
+
.bubble .md :not(pre) > code, .artifact-md .md :not(pre) > code{
|
|
1096
|
+
background: var(--quote-bg); border: 1px solid var(--quote-line); border-radius: 5px;
|
|
1097
|
+
padding: 1px 5px; font-size: 12.5px; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
1098
|
+
color: var(--ink);
|
|
1099
|
+
}
|
|
1100
|
+
/* 围栏代码块(react-markdown 输出 pre > code,rehype-highlight 加 hljs 类) */
|
|
1101
|
+
.bubble .md pre, .artifact-md .md pre{
|
|
1102
|
+
background: #0f172a; color: #e2e8f0; border-radius: 10px; padding: 12px 14px;
|
|
1103
|
+
overflow-x: auto; margin: 0 0 10px; font-size: 12.5px; line-height: 1.55;
|
|
1104
|
+
}
|
|
1105
|
+
.bubble .md pre code, .artifact-md .md pre code{ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; white-space: pre; background: none; border: none; padding: 0; color: inherit; }
|
|
1106
|
+
/* GFM 表格 */
|
|
1107
|
+
.bubble .md .md-table-wrap, .artifact-md .md .md-table-wrap{
|
|
1108
|
+
margin: 12px 0 16px; max-width: 100%; overflow-x: auto;
|
|
1109
|
+
border: 1px solid var(--line); border-radius: 10px;
|
|
1110
|
+
scrollbar-width: thin; scrollbar-color: var(--scrollbar) transparent;
|
|
1111
|
+
}
|
|
1112
|
+
.md-table-wrap:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }
|
|
1113
|
+
.bubble .md table, .artifact-md .md table{
|
|
1114
|
+
border-collapse: separate; border-spacing: 0; margin: 0; font-size: 14px; width: 100%;
|
|
1115
|
+
}
|
|
1116
|
+
.bubble .md th, .bubble .md td, .artifact-md .md th, .artifact-md .md td{
|
|
1117
|
+
border: 0; border-bottom: 1px solid var(--line); padding: 12px 16px;
|
|
1118
|
+
text-align: left; vertical-align: top; line-height: 1.6; min-width: 96px; max-width: 440px;
|
|
1119
|
+
overflow-wrap: break-word;
|
|
1120
|
+
}
|
|
1121
|
+
.bubble .md th, .artifact-md .md th{ background: var(--field-soft); font-weight: 600; }
|
|
1122
|
+
.bubble .md tbody tr:last-child td, .artifact-md .md tbody tr:last-child td{ border-bottom: 0; }
|
|
1123
|
+
.bubble .md td > :last-child, .artifact-md .md td > :last-child{ margin-bottom: 0; }
|
|
1124
|
+
@media (hover: hover) and (pointer: fine) {
|
|
1125
|
+
.bubble .md tbody tr:hover td, .artifact-md .md tbody tr:hover td{ background: var(--table-stripe); }
|
|
1126
|
+
}
|
|
1127
|
+
/* 引用 */
|
|
1128
|
+
.bubble .md blockquote, .artifact-md .md blockquote{
|
|
1129
|
+
margin: 0 0 10px; padding: 8px 12px; border-left: 3px solid var(--brand);
|
|
1130
|
+
background: var(--brand-soft); border-radius: 0 8px 8px 0; color: var(--ink-soft);
|
|
1131
|
+
}
|
|
1132
|
+
.bubble .md blockquote > *:last-child, .artifact-md .md blockquote > *:last-child{ margin-bottom: 0; }
|
|
1133
|
+
.bubble .md hr, .artifact-md .md hr{ border: none; border-top: 1px solid var(--line); margin: 12px 0; }
|
|
1134
|
+
.bubble .md img, .artifact-md .md img{ max-width: 100%; border-radius: 8px; }
|
|
1135
|
+
/* rehype-highlight(highlight.js)代码高亮配色:GitHub Dark 精简版 */
|
|
1136
|
+
.bubble .md .hljs-comment, .bubble .md .hljs-quote, .artifact-md .md .hljs-comment, .artifact-md .md .hljs-quote{ color: #8b949e; font-style: italic; }
|
|
1137
|
+
.bubble .md .hljs-keyword, .bubble .md .hljs-selector-tag, .bubble .md .hljs-literal,
|
|
1138
|
+
.bubble .md .hljs-doctag, .bubble .md .hljs-type, .artifact-md .md .hljs-keyword, .artifact-md .md .hljs-selector-tag, .artifact-md .md .hljs-literal,
|
|
1139
|
+
.artifact-md .md .hljs-doctag, .artifact-md .md .hljs-type{ color: #ff7b72; }
|
|
1140
|
+
.bubble .md .hljs-string, .bubble .md .hljs-regexp, .bubble .md .hljs-addition,
|
|
1141
|
+
.bubble .md .hljs-attribute, .bubble .md .hljs-meta .hljs-string, .artifact-md .md .hljs-string, .artifact-md .md .hljs-regexp, .artifact-md .md .hljs-addition,
|
|
1142
|
+
.artifact-md .md .hljs-attribute, .artifact-md .md .hljs-meta .hljs-string{ color: #a5d6ff; }
|
|
1143
|
+
.bubble .md .hljs-number, .bubble .md .hljs-symbol, .bubble .md .hljs-bullet,
|
|
1144
|
+
.bubble .md .hljs-variable, .bubble .md .hljs-template-variable, .artifact-md .md .hljs-number, .artifact-md .md .hljs-symbol, .artifact-md .md .hljs-bullet,
|
|
1145
|
+
.artifact-md .md .hljs-variable, .artifact-md .md .hljs-template-variable{ color: #79c0ff; }
|
|
1146
|
+
.bubble .md .hljs-title, .bubble .md .hljs-section, .bubble .md .hljs-name, .artifact-md .md .hljs-title, .artifact-md .md .hljs-section, .artifact-md .md .hljs-name{ color: #d2a8ff; }
|
|
1147
|
+
.bubble .md .hljs-built_in, .bubble .md .hljs-builtin-name, .bubble .md .hljs-params, .artifact-md .md .hljs-built_in, .artifact-md .md .hljs-builtin-name, .artifact-md .md .hljs-params{ color: #ffa657; }
|
|
1148
|
+
.bubble .md .hljs-function .hljs-title, .artifact-md .md .hljs-function .hljs-title{ color: #d2a8ff; }
|
|
1149
|
+
.bubble .md .hljs-emphasis, .artifact-md .md .hljs-emphasis{ font-style: italic; }
|
|
1150
|
+
.bubble .md .hljs-strong, .artifact-md .md .hljs-strong{ font-weight: 700; }
|
|
1151
|
+
|
|
1152
|
+
/* ===== 思考过程(thinking)区:思考中 = 小窗滚动直播;思考结束 = 收起为「已思考 X 秒」可再展开 ===== */
|
|
1153
|
+
.chat-thinking { margin: 0 0 8px; }
|
|
1154
|
+
.chat-thinking-head {
|
|
1155
|
+
display: inline-flex; align-items: center; gap: 7px;
|
|
1156
|
+
padding: 0;
|
|
1157
|
+
background: transparent; border: none;
|
|
1158
|
+
color: var(--ink-soft);
|
|
1159
|
+
}
|
|
1160
|
+
.chat-thinking-label { font-size: 12.5px; }
|
|
1161
|
+
/* 实时计时(活动步「已用时 X 秒」):与胶囊文字同字号同色,数字等宽避免每秒跳动宽度抖动 */
|
|
1162
|
+
.chat-thinking-timer {
|
|
1163
|
+
font-size: 12.5px; color: inherit;
|
|
1164
|
+
font-variant-numeric: tabular-nums;
|
|
1165
|
+
}
|
|
1166
|
+
.chat-thinking-spinner {
|
|
1167
|
+
width: 12px; height: 12px; border-radius: 50%;
|
|
1168
|
+
border: 2px solid var(--line); border-top-color: var(--brand);
|
|
1169
|
+
animation: chatVoiceSpin .7s linear infinite;
|
|
1170
|
+
}
|
|
1171
|
+
/* 思考直播(WorkBuddy 同款):无边框无背景,仅左侧一根竖条。
|
|
1172
|
+
最大高度 = 输入框高度 ×2(--chat-thinking-max-h);超出在框内滚动,不再无限撑高消息流。
|
|
1173
|
+
组件内 useEffect(ThinkingLiveBox)每次文本更新把 scrollTop 拉到底,持续显示最新思考。 */
|
|
1174
|
+
.chat-thinking-live {
|
|
1175
|
+
margin: 6px 0 0;
|
|
1176
|
+
padding: 2px 12px 2px 12px;
|
|
1177
|
+
background: transparent; border: none; border-radius: 0;
|
|
1178
|
+
border-left: 2px solid #c9cdd4;
|
|
1179
|
+
max-height: var(--chat-thinking-max-h);
|
|
1180
|
+
overflow-y: auto;
|
|
1181
|
+
font-size: 12.5px; line-height: 1.7; color: var(--ink-soft);
|
|
1182
|
+
white-space: pre-wrap; word-break: break-word;
|
|
1183
|
+
scrollbar-width: thin; scrollbar-color: #c9cdd4 transparent;
|
|
1184
|
+
}
|
|
1185
|
+
.chat-thinking-live::-webkit-scrollbar { width: 6px; }
|
|
1186
|
+
.chat-thinking-live::-webkit-scrollbar-track { background: transparent; }
|
|
1187
|
+
.chat-thinking-live::-webkit-scrollbar-thumb { background: #c9cdd4; border-radius: 3px; }
|
|
1188
|
+
/* 思考结束胶囊:无背景无边框纯文字,「思考 N · 用时 X 秒 · 工具名」,点击展开/收起完整思考过程 */
|
|
1189
|
+
.chat-thinking--done { margin: 0 0 8px; }
|
|
1190
|
+
.chat-thinking-done-toggle {
|
|
1191
|
+
display: inline-flex; align-items: center; gap: 7px;
|
|
1192
|
+
max-width: 100%; min-width: 0;
|
|
1193
|
+
padding: 2px 0;
|
|
1194
|
+
background: transparent; border: none;
|
|
1195
|
+
color: var(--ink-soft); font-size: 12.5px; cursor: pointer;
|
|
1196
|
+
transition: color .15s ease;
|
|
1197
|
+
}
|
|
1198
|
+
/* hover:仅字体颜色变化(含箭头,箭头颜色继承字体),边框不变 */
|
|
1199
|
+
/* 胶囊文字:继承按钮字体与颜色(与箭头一致,无 opacity 削弱);
|
|
1200
|
+
inline-flex + align-items:center 让工具 icon 与工具名垂直居中对齐(icon 复用 .chat-thinking-tool-icon) */
|
|
1201
|
+
.chat-thinking-done-label {
|
|
1202
|
+
display: inline-flex; align-items: center; gap: 6px;
|
|
1203
|
+
flex: 0 1 auto; min-width: 0; overflow: hidden; white-space: nowrap;
|
|
1204
|
+
font-size: 12.5px; color: inherit;
|
|
1205
|
+
}
|
|
1206
|
+
.chat-thinking-done-toggle .chat-thinking-tool-name,
|
|
1207
|
+
.chat-thinking-done-toggle .chat-thinking-browser-label {
|
|
1208
|
+
flex: 0 1 auto; min-width: 0;
|
|
1209
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
1210
|
+
}
|
|
1211
|
+
.chat-thinking-activity { display: block; }
|
|
1212
|
+
.chat-thinking-icon {
|
|
1213
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
1214
|
+
flex: 0 0 16px;
|
|
1215
|
+
width: 16px; height: 16px;
|
|
1216
|
+
background: transparent; color: inherit;
|
|
1217
|
+
}
|
|
1218
|
+
/* 展开/收起箭头:收起态向右(chevron-right)、展开态向下(chevron-down) */
|
|
1219
|
+
.chat-thinking-icon svg {
|
|
1220
|
+
width: 13px; height: 13px;
|
|
1221
|
+
fill: none; stroke: currentColor; stroke-width: 2.4;
|
|
1222
|
+
stroke-linecap: round; stroke-linejoin: round;
|
|
1223
|
+
}
|
|
1224
|
+
/* 展开后的完整思考正文(与直播小窗同款:左侧竖条、无边框、超高滚动) */
|
|
1225
|
+
.chat-thinking-body {
|
|
1226
|
+
margin: 6px 0 0; padding: 2px 12px 2px 12px;
|
|
1227
|
+
max-height: 320px; overflow-y: auto;
|
|
1228
|
+
background: transparent; border: none; border-radius: 0;
|
|
1229
|
+
border-left: 2px solid #c9cdd4;
|
|
1230
|
+
font-size: 13.5px; line-height: 1.7; color: var(--ink-soft);
|
|
1231
|
+
white-space: pre-wrap; word-break: break-word;
|
|
1232
|
+
scrollbar-width: thin; scrollbar-color: #c9cdd4 transparent;
|
|
1233
|
+
}
|
|
1234
|
+
.chat-thinking-body::-webkit-scrollbar { width: 6px; }
|
|
1235
|
+
.chat-thinking-body::-webkit-scrollbar-track { background: transparent; }
|
|
1236
|
+
.chat-thinking-body::-webkit-scrollbar-thumb { background: #c9cdd4; border-radius: 3px; }
|
|
1237
|
+
/* 展开详情顶部的该步用时(折叠胶囊不显示用时,展开后在此展示) */
|
|
1238
|
+
.chat-thinking-secs {
|
|
1239
|
+
margin: 0 0 6px;
|
|
1240
|
+
font-size: 14px; color: var(--ink-soft); line-height: 1.5;
|
|
1241
|
+
font-variant-numeric: tabular-nums;
|
|
1242
|
+
}
|
|
1243
|
+
/* WorkBuddy 式「动作 → 结果」:完成步胶囊下方常驻的结果摘要(2 行省略;展开时前端隐藏避免重复)。
|
|
1244
|
+
每一步都保留(含工具步):取思考末段,line-clamp 2 控制消息流长度,长任务多步时也不会堆满。
|
|
1245
|
+
颜色用正文色 --ink(而非灰 --ink-soft):摘要与过程白字同色,保持「一直可见」的连续性。
|
|
1246
|
+
字号层级:正式答复 15.5 > 结果摘要 14.5 > 动作胶囊 14 > 状态徽标 12.5 */
|
|
1247
|
+
.chat-thinking-summary {
|
|
1248
|
+
margin: 3px 0 0 0;
|
|
1249
|
+
font-size: 14.5px; line-height: 1.6; color: var(--ink);
|
|
1250
|
+
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
1251
|
+
overflow: hidden; overflow-wrap: anywhere;
|
|
1252
|
+
}
|
|
1253
|
+
/* 正文为空时的兜底回复(模型以 thinking/工具收尾、无最终 result):步骤折叠后
|
|
1254
|
+
用最后一步思考尾段顶上,避免「已完成」卡片下只剩空气泡。展示为正式答复样式
|
|
1255
|
+
(非摘要的 2 行省略),仅在折叠态渲染;步骤未折叠时由胶囊摘要承担,不重复出现 */
|
|
1256
|
+
.msg-fallback-result {
|
|
1257
|
+
margin: 0;
|
|
1258
|
+
font-size: 15.5px; line-height: 1.65; color: var(--ink);
|
|
1259
|
+
overflow-wrap: anywhere;
|
|
1260
|
+
}
|
|
1261
|
+
/* 思考步内的工具调用行(WorkBuddy 同款清爽风格):无卡片无背景,语义图标 + 中文短词 +
|
|
1262
|
+
入参摘要单行显示(超长省略),与左侧竖条形成统一的时间线观感 */
|
|
1263
|
+
.chat-thinking-tool {
|
|
1264
|
+
display: flex; align-items: baseline; gap: 6px; flex-wrap: nowrap;
|
|
1265
|
+
margin: 3px 0; padding: 0;
|
|
1266
|
+
background: transparent; border: none; border-radius: 0;
|
|
1267
|
+
max-width: 100%;
|
|
1268
|
+
}
|
|
1269
|
+
.chat-thinking-tool-icon {
|
|
1270
|
+
flex: 0 0 auto; align-self: center;
|
|
1271
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
1272
|
+
width: 14px; height: 14px;
|
|
1273
|
+
color: var(--ink-soft); opacity: .85;
|
|
1274
|
+
}
|
|
1275
|
+
.chat-thinking-tool-name {
|
|
1276
|
+
flex: 0 0 auto; color: var(--ink-soft);
|
|
1277
|
+
font-size: 14px; white-space: nowrap;
|
|
1278
|
+
}
|
|
1279
|
+
.chat-thinking-tool-input {
|
|
1280
|
+
flex: 1 1 auto; min-width: 0;
|
|
1281
|
+
font-size: 14px; color: var(--ink-soft);
|
|
1282
|
+
font-variant-numeric: tabular-nums;
|
|
1283
|
+
overflow-wrap: anywhere;
|
|
1284
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
1285
|
+
}
|
|
1286
|
+
/* 工具执行状态徽标(豆包 Work 式就地更新):✓ 成功 / ✗ 失败(保持全链最小层级) */
|
|
1287
|
+
.chat-thinking-tool-status {
|
|
1288
|
+
flex: 0 0 auto; font-size: 12.5px; font-weight: 500; color: var(--ok);
|
|
1289
|
+
}
|
|
1290
|
+
.chat-thinking-tool-status--error { color: var(--danger); }
|
|
1291
|
+
/* 工具结果预览(仅展开详情内显示,受限 3 行省略;超长完整内容放 title):
|
|
1292
|
+
成功=灰、失败=红。收起态不再展示工具执行结果(SDK 无工具摘要字段) */
|
|
1293
|
+
.chat-thinking-tool-result {
|
|
1294
|
+
flex-basis: 100%; min-width: 0;
|
|
1295
|
+
font-size: 14px; line-height: 1.5; color: var(--ink-soft);
|
|
1296
|
+
overflow-wrap: anywhere;
|
|
1297
|
+
display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
|
|
1298
|
+
overflow: hidden;
|
|
1299
|
+
}
|
|
1300
|
+
.chat-thinking-tool-result.is-error { color: var(--danger); }
|
|
1301
|
+
/* 失败工具胶囊:整行文字标红(is-error 与 is-running 互斥) */
|
|
1302
|
+
.chat-thinking-done-toggle.is-error .chat-thinking-tool-name,
|
|
1303
|
+
.chat-thinking-done-toggle.is-error .chat-thinking-tool-file,
|
|
1304
|
+
.chat-thinking-done-toggle.is-error .chat-thinking-tool-status { color: var(--danger); }
|
|
1305
|
+
/* 文件编辑增删徽标(Claude Code 风格「已编辑文件 xxx +N -M」):+N 绿 / -M 红,
|
|
1306
|
+
文件路径超长省略(完整路径放 title),徽标右对齐 */
|
|
1307
|
+
.chat-thinking-tool-file {
|
|
1308
|
+
flex: 0 1 auto; min-width: 0;
|
|
1309
|
+
font-size: 14px; color: var(--ink-soft);
|
|
1310
|
+
font-variant-numeric: tabular-nums;
|
|
1311
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
1312
|
+
}
|
|
1313
|
+
.chat-edit-badges {
|
|
1314
|
+
flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px;
|
|
1315
|
+
font-size: 14px; font-weight: 500; line-height: 1;
|
|
1316
|
+
font-variant-numeric: tabular-nums;
|
|
1317
|
+
}
|
|
1318
|
+
.chat-edit-add { color: var(--ok); }
|
|
1319
|
+
.chat-edit-del { color: #e5484d; }
|
|
1320
|
+
/* 思考步内的中间小结文本(工具调用前模型输出的该步小结):同样去掉卡片,纯文本行
|
|
1321
|
+
(内容层级,与结果摘要同级) */
|
|
1322
|
+
.chat-thinking-step-text {
|
|
1323
|
+
margin: 3px 0; padding: 0;
|
|
1324
|
+
background: transparent; border: none; border-radius: 0;
|
|
1325
|
+
font-size: 14.5px; color: var(--ink-soft); line-height: 1.6;
|
|
1326
|
+
overflow-wrap: anywhere;
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
/* control_browser 过程面板(动作/思考实时进 thinking;截图仅在右侧边栏预览,不再渲染进消息列表) */
|
|
1330
|
+
.chat-browser {
|
|
1331
|
+
margin: 0 0 8px; padding: 8px;
|
|
1332
|
+
background: var(--table-stripe); border: 1px solid var(--line); border-radius: 8px;
|
|
1333
|
+
}
|
|
1334
|
+
.chat-browser-head {
|
|
1335
|
+
display: flex; align-items: center; justify-content: flex-end;
|
|
1336
|
+
margin-bottom: 6px;
|
|
1337
|
+
}
|
|
1338
|
+
.chat-browser-status {
|
|
1339
|
+
padding: 2px 8px; border-radius: 999px;
|
|
1340
|
+
font-size: 12px; line-height: 1.5; color: #fff;
|
|
1341
|
+
background: rgba(31,39,51,.72);
|
|
1342
|
+
pointer-events: none;
|
|
1343
|
+
white-space: nowrap;
|
|
1344
|
+
}
|
|
1345
|
+
.chat-browser-status--running { background: rgba(31,39,51,.72); }
|
|
1346
|
+
.chat-browser-status--done { background: rgba(23,126,63,.85); }
|
|
1347
|
+
.chat-browser-status--error { background: rgba(172,43,43,.85); }
|
|
1348
|
+
.chat-browser-status--ask { background: rgba(176,108,15,.9); }
|
|
1349
|
+
/* 模型决策思考文本(browser thinking 事件;hy3 默认不输出,有则显示) */
|
|
1350
|
+
.chat-browser-think {
|
|
1351
|
+
margin: 0 0 8px; padding: 6px 9px;
|
|
1352
|
+
background: var(--field-bg); border: 1px solid var(--line); border-radius: 6px;
|
|
1353
|
+
font-size: 12px; color: var(--ink); line-height: 1.6;
|
|
1354
|
+
white-space: pre-wrap; overflow-wrap: anywhere;
|
|
1355
|
+
}
|
|
1356
|
+
.chat-browser-actions {
|
|
1357
|
+
display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 8px;
|
|
1358
|
+
}
|
|
1359
|
+
.chat-browser-action {
|
|
1360
|
+
padding: 1px 7px; border-radius: 4px;
|
|
1361
|
+
background: var(--field-soft); border: 1px solid var(--line);
|
|
1362
|
+
font-size: 12px; color: var(--ink-soft); font-variant-numeric: tabular-nums;
|
|
1363
|
+
}
|
|
1364
|
+
/* 运行中的实时动作流(活跃步直播,只列最近 4 条) */
|
|
1365
|
+
.chat-browser-live {
|
|
1366
|
+
display: flex; flex-direction: column; gap: 3px;
|
|
1367
|
+
}
|
|
1368
|
+
.chat-browser-live-item {
|
|
1369
|
+
display: flex; align-items: baseline; gap: 7px;
|
|
1370
|
+
font-size: 12px; line-height: 1.6; color: var(--ink);
|
|
1371
|
+
}
|
|
1372
|
+
.chat-browser-live-step {
|
|
1373
|
+
flex: 0 0 auto; min-width: 24px; text-align: right;
|
|
1374
|
+
font-variant-numeric: tabular-nums; color: var(--ink-soft);
|
|
1375
|
+
font-size: 12px;
|
|
1376
|
+
}
|
|
1377
|
+
.chat-browser-live-action { min-width: 0; overflow-wrap: anywhere; }
|
|
1378
|
+
.chat-browser-live-empty {
|
|
1379
|
+
padding: 6px 0; font-size: 12px; color: var(--ink-soft);
|
|
1380
|
+
}
|
|
1381
|
+
.chat-browser-ask {
|
|
1382
|
+
margin-bottom: 8px; padding: 8px;
|
|
1383
|
+
background: var(--field-bg); border: 1px solid var(--line); border-radius: 6px;
|
|
1384
|
+
}
|
|
1385
|
+
.chat-browser-ask-q {
|
|
1386
|
+
margin-bottom: 6px; font-size: 12px; color: var(--ink); line-height: 1.6;
|
|
1387
|
+
}
|
|
1388
|
+
.chat-browser-ask-row { display: flex; gap: 6px; }
|
|
1389
|
+
.chat-browser-ask-input {
|
|
1390
|
+
flex: 1 1 auto; min-width: 0;
|
|
1391
|
+
padding: 5px 9px; border: 1px solid var(--line); border-radius: 6px;
|
|
1392
|
+
font-size: 12px; color: var(--ink); background: var(--field-bg);
|
|
1393
|
+
outline: none;
|
|
1394
|
+
}
|
|
1395
|
+
.chat-browser-ask-input:focus { border-color: var(--line); }
|
|
1396
|
+
.chat-browser-ask-btn {
|
|
1397
|
+
flex: 0 0 auto; padding: 4px 12px; border-radius: 6px;
|
|
1398
|
+
background: var(--hover-strong); border: 1px solid var(--line);
|
|
1399
|
+
font-size: 12px; color: var(--ink); cursor: pointer;
|
|
1400
|
+
}
|
|
1401
|
+
.chat-browser-ask-btn:disabled { opacity: .45; cursor: default; }
|
|
1402
|
+
.chat-browser-summary {
|
|
1403
|
+
padding: 6px 9px; border-radius: 6px;
|
|
1404
|
+
background: var(--field-soft); border: 1px solid var(--line);
|
|
1405
|
+
font-size: 12px; color: var(--ink); line-height: 1.6;
|
|
1406
|
+
overflow-wrap: anywhere;
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
/* 底部输入区:与 WorkBuddy 一致的圆角卡片,和聊天内容用浅背景区分。
|
|
1410
|
+
外层 stack 统管背景/边框/圆角/阴影;内部 composer 与 queue 只负责内容排布。
|
|
1411
|
+
stack 自身可收缩,queue 超出时内部滚动;composer 永远贴底,不会被 queue 顶出视口。 */
|
|
1412
|
+
.chat-composer-stack {
|
|
1413
|
+
margin: 0 14px 14px;
|
|
1414
|
+
background: var(--panel);
|
|
1415
|
+
border: 1px solid var(--line);
|
|
1416
|
+
border-radius: 20px;
|
|
1417
|
+
box-shadow: 0 2px 12px rgba(31, 39, 51, .04);
|
|
1418
|
+
display: flex;
|
|
1419
|
+
flex-direction: column;
|
|
1420
|
+
flex: 0 1 auto;
|
|
1421
|
+
min-height: 0;
|
|
1422
|
+
/* 作为容器:工具条按输入卡片自身宽度自适应(中栏随拖拽/右栏开合实时变化,
|
|
1423
|
+
视口媒体查询感知不到,故用容器查询)。见下方 @container composer。 */
|
|
1424
|
+
container-type: inline-size;
|
|
1425
|
+
container-name: composer;
|
|
1426
|
+
}
|
|
1427
|
+
.chat-composer {
|
|
1428
|
+
flex: 0 0 auto;
|
|
1429
|
+
padding: 14px 16px 10px;
|
|
1430
|
+
}
|
|
1431
|
+
.chat-composer textarea {
|
|
1432
|
+
width: 100%; display: block; resize: none; border: 0; background: transparent;
|
|
1433
|
+
padding: 6px 2px; font-size: 15px; font-family: inherit; color: var(--ink);
|
|
1434
|
+
line-height: 1.55; overflow-y: hidden; min-height: 48px;
|
|
1435
|
+
}
|
|
1436
|
+
.chat-composer textarea:focus { outline: none; }
|
|
1437
|
+
.chat-composer textarea::placeholder { color: var(--ink-soft); opacity: .75; }
|
|
1438
|
+
|
|
1439
|
+
/* 输入区容器:内聚 composer + queue 的 stack,以及可选的 notify banner。
|
|
1440
|
+
整体锚定在 chat-main-inner 底部:queue 向上生长时输入框不会被顶出视口,
|
|
1441
|
+
消息列表(.chat-body)的可用高度会相应缩小。 */
|
|
1442
|
+
.chat-input-zone {
|
|
1443
|
+
position: relative;
|
|
1444
|
+
display: flex; flex-direction: column;
|
|
1445
|
+
justify-content: flex-end;
|
|
1446
|
+
flex: 0 1 auto;
|
|
1447
|
+
min-height: 0;
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
/* ---- 选择工作空间(WB 风格,仅新建任务空态显示;进入对话后隐藏)---- */
|
|
1451
|
+
/* 定位上下文:按钮 + 向上弹出的项目菜单 */
|
|
1452
|
+
.chat-ws-anchor { position: relative; display: inline-flex; flex: 0 0 auto; }
|
|
1453
|
+
/* 下拉按钮:文件图标 + 当前项目名/提示 + 下拉箭头(与 WB 输入区左下角工具一致) */
|
|
1454
|
+
.chat-ws-btn {
|
|
1455
|
+
display: inline-flex; align-items: center; gap: 6px;
|
|
1456
|
+
border: 1px solid var(--line); background: transparent;
|
|
1457
|
+
color: var(--ink-soft); border-radius: 8px;
|
|
1458
|
+
font-size: 12.5px; line-height: 1; padding: 6px 10px;
|
|
1459
|
+
cursor: pointer; transition: all .15s ease;
|
|
1460
|
+
}
|
|
1461
|
+
.chat-ws-btn:hover, .chat-ws-btn.is-open {
|
|
1462
|
+
color: var(--ink); background: var(--hover);
|
|
1463
|
+
}
|
|
1464
|
+
.chat-ws-btn:disabled { opacity: .55; cursor: default; }
|
|
1465
|
+
.chat-ws-btn-icon { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
|
|
1466
|
+
.chat-ws-btn-label {
|
|
1467
|
+
max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
1468
|
+
font-weight: 500;
|
|
1469
|
+
}
|
|
1470
|
+
.chat-ws-btn-caret { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; opacity: .7; }
|
|
1471
|
+
|
|
1472
|
+
/* 项目菜单 popup:从按钮向上弹出;backdrop 承接外部点击关闭 */
|
|
1473
|
+
.chat-ws-pop {
|
|
1474
|
+
position: absolute; left: 0; bottom: calc(100% + 8px);
|
|
1475
|
+
z-index: 80;
|
|
1476
|
+
}
|
|
1477
|
+
.chat-ws-pop-backdrop { position: fixed; inset: 0; z-index: -1; }
|
|
1478
|
+
.chat-ws-pop-inner {
|
|
1479
|
+
width: 300px;
|
|
1480
|
+
background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
|
|
1481
|
+
box-shadow: var(--shadow);
|
|
1482
|
+
padding: 8px; display: flex; flex-direction: column;
|
|
1483
|
+
}
|
|
1484
|
+
/* 当前项目(顶部):路径 + 移除 */
|
|
1485
|
+
.chat-ws-current {
|
|
1486
|
+
display: flex; align-items: center; gap: 8px;
|
|
1487
|
+
padding: 8px 10px; margin-bottom: 4px;
|
|
1488
|
+
border: 1px dashed var(--line); border-radius: 8px; background: var(--field-soft, transparent);
|
|
1489
|
+
}
|
|
1490
|
+
.chat-ws-current-path {
|
|
1491
|
+
flex: 1 1 auto; min-width: 0;
|
|
1492
|
+
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
1493
|
+
font-size: 12px; color: var(--ink);
|
|
1494
|
+
font-family: ui-monospace, Consolas, "Courier New", monospace;
|
|
1495
|
+
}
|
|
1496
|
+
.chat-ws-act {
|
|
1497
|
+
flex: 0 0 auto;
|
|
1498
|
+
border: 1px solid var(--line); background: transparent;
|
|
1499
|
+
color: var(--ink-soft); border-radius: 7px;
|
|
1500
|
+
font-size: 12px; padding: 3px 10px; cursor: pointer;
|
|
1501
|
+
transition: all .15s ease;
|
|
1502
|
+
}
|
|
1503
|
+
.chat-ws-act:hover { color: var(--ink); background: var(--hover); }
|
|
1504
|
+
.chat-ws-act:disabled { opacity: .55; cursor: default; }
|
|
1505
|
+
.chat-ws-act--clear:hover { color: #d23f4c; border-color: rgba(210, 63, 76, .4); background: rgba(210, 63, 76, .08); }
|
|
1506
|
+
/* 分组标题 */
|
|
1507
|
+
.chat-ws-pop-label {
|
|
1508
|
+
padding: 6px 10px 4px; font-size: 11px; font-weight: 600;
|
|
1509
|
+
color: var(--ink-soft); letter-spacing: .04em; text-transform: uppercase;
|
|
1510
|
+
}
|
|
1511
|
+
.chat-ws-pop-empty { padding: 10px; font-size: 12.5px; color: var(--ink-soft); }
|
|
1512
|
+
/* 已有项目条目 */
|
|
1513
|
+
.chat-ws-pop-item {
|
|
1514
|
+
display: flex; align-items: center; gap: 8px;
|
|
1515
|
+
width: 100%; border: none; background: transparent;
|
|
1516
|
+
color: var(--ink); font-size: 13px; text-align: left;
|
|
1517
|
+
padding: 8px 10px; border-radius: 8px; cursor: pointer;
|
|
1518
|
+
transition: background .12s ease;
|
|
1519
|
+
}
|
|
1520
|
+
.chat-ws-pop-item:hover { background: var(--hover); }
|
|
1521
|
+
.chat-ws-pop-item.is-active { background: var(--brand-soft); color: var(--brand-dark); }
|
|
1522
|
+
.chat-ws-pop-item-icon { width: 15px; height: 15px; flex: 0 0 auto; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; opacity: .75; }
|
|
1523
|
+
.chat-ws-pop-item-name {
|
|
1524
|
+
flex: 1 1 auto; min-width: 0;
|
|
1525
|
+
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
1526
|
+
}
|
|
1527
|
+
.chat-ws-pop-item-check { flex: 0 0 auto; color: var(--brand); font-size: 13px; font-weight: 700; }
|
|
1528
|
+
.chat-ws-pop-divider { height: 1px; background: var(--line); margin: 6px 2px; }
|
|
1529
|
+
/* 底部操作:新建项目 / 打开本地文件夹 */
|
|
1530
|
+
.chat-ws-pop-act {
|
|
1531
|
+
display: flex; align-items: center; gap: 9px;
|
|
1532
|
+
width: 100%; border: none; background: transparent;
|
|
1533
|
+
color: var(--ink); font-size: 13px; text-align: left;
|
|
1534
|
+
padding: 8px 10px; border-radius: 8px; cursor: pointer;
|
|
1535
|
+
transition: background .12s ease;
|
|
1536
|
+
}
|
|
1537
|
+
.chat-ws-pop-act:hover { background: var(--hover); }
|
|
1538
|
+
.chat-ws-pop-act:disabled { opacity: .55; cursor: default; }
|
|
1539
|
+
.chat-ws-pop-act-icon {
|
|
1540
|
+
width: 17px; flex: 0 0 auto;
|
|
1541
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
1542
|
+
color: var(--ink-soft);
|
|
1543
|
+
}
|
|
1544
|
+
.chat-ws-pop-act-icon svg {
|
|
1545
|
+
width: 15px; height: 15px;
|
|
1546
|
+
fill: none; stroke: currentColor; stroke-width: 1.7;
|
|
1547
|
+
stroke-linecap: round; stroke-linejoin: round;
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
/* ---- 侧边栏:会话按项目分组(WB 列表样式)---- */
|
|
1551
|
+
.chat-sidebar-group { margin-top: 2px; }
|
|
1552
|
+
.chat-sidebar-group + .chat-sidebar-group { margin-top: 10px; }
|
|
1553
|
+
/* 项目组标题:高度与会话 item 一致(padding 6px + 行高 26px + 6px = 38px),
|
|
1554
|
+
左侧可折叠箭头,hover 时右侧出现「+ 新建会话」「⋯ 项目菜单」 */
|
|
1555
|
+
.chat-sidebar-group-title {
|
|
1556
|
+
display: flex; align-items: center; gap: 6px;
|
|
1557
|
+
padding: 6px 10px; box-sizing: border-box; height: 38px;
|
|
1558
|
+
font-size: 13px; font-weight: 600; color: var(--ink-soft);
|
|
1559
|
+
letter-spacing: .03em;
|
|
1560
|
+
border-radius: 9px; cursor: context-menu; user-select: none;
|
|
1561
|
+
transition: background .15s ease, color .15s ease;
|
|
1562
|
+
}
|
|
1563
|
+
.chat-sidebar-group-title:hover { background: var(--hover); color: var(--ink); }
|
|
1564
|
+
/* 折叠箭头:展开默认 ▼(可收起),折叠 is-collapsed 旋转回 ▶(可展开) */
|
|
1565
|
+
.chat-sidebar-group-chevron {
|
|
1566
|
+
flex: 0 0 auto; width: 18px; height: 18px;
|
|
1567
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
1568
|
+
padding: 0; border: none; border-radius: 5px; cursor: pointer;
|
|
1569
|
+
background: transparent; color: var(--ink-soft);
|
|
1570
|
+
transition: transform .15s ease, color .15s ease;
|
|
1571
|
+
}
|
|
1572
|
+
.chat-sidebar-group-chevron svg {
|
|
1573
|
+
width: 13px; height: 13px;
|
|
1574
|
+
fill: none; stroke: currentColor; stroke-width: 2;
|
|
1575
|
+
stroke-linecap: round; stroke-linejoin: round;
|
|
1576
|
+
transform: rotate(90deg);
|
|
1577
|
+
}
|
|
1578
|
+
.chat-sidebar-group-title.is-collapsed .chat-sidebar-group-chevron svg { transform: rotate(0deg); }
|
|
1579
|
+
.chat-sidebar-group-title:hover .chat-sidebar-group-chevron { color: var(--ink); }
|
|
1580
|
+
.chat-sidebar-group-chevron:hover { color: var(--ink); }
|
|
1581
|
+
/* 目录分组前的文件夹图标(WorkBuddy 同款:描边线性图标,与组标题文字同色) */
|
|
1582
|
+
.chat-sidebar-group-icon {
|
|
1583
|
+
flex: 0 0 auto; width: 14px; height: 14px;
|
|
1584
|
+
fill: none; stroke: currentColor; stroke-width: 1.8;
|
|
1585
|
+
stroke-linecap: round; stroke-linejoin: round;
|
|
1586
|
+
}
|
|
1587
|
+
/* 组内会话缩进对齐图标右侧(图标 14px + gap 6px + 标题 padding-left 10px ≈ 26px) */
|
|
1588
|
+
.chat-sidebar-group .chat-sidebar-item { padding-left: 26px; }
|
|
1589
|
+
.chat-sidebar-group-name {
|
|
1590
|
+
min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
1591
|
+
}
|
|
1592
|
+
.chat-sidebar-group-count {
|
|
1593
|
+
flex: 0 0 auto;
|
|
1594
|
+
font-size: 10.5px; font-weight: 700; color: var(--ink-soft);
|
|
1595
|
+
background: var(--hover, rgba(128, 128, 128, .15));
|
|
1596
|
+
border-radius: 99px; padding: 1px 7px;
|
|
1597
|
+
}
|
|
1598
|
+
/* hover 时计数隐藏、位置让给右侧操作区(+ / ⋯),避免挤压标题 */
|
|
1599
|
+
.chat-sidebar-group-title:hover .chat-sidebar-group-count { display: none; }
|
|
1600
|
+
.chat-sidebar-group-actions { display: none; align-items: center; gap: 2px; flex: 0 0 auto; margin-left: auto; }
|
|
1601
|
+
.chat-sidebar-group-title:hover .chat-sidebar-group-actions { display: inline-flex; }
|
|
1602
|
+
.chat-sidebar-group-act {
|
|
1603
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
1604
|
+
width: 22px; height: 22px; border-radius: 50%;
|
|
1605
|
+
border: none; background: transparent; color: var(--ink-soft); cursor: pointer;
|
|
1606
|
+
transition: color .15s ease, background .15s ease;
|
|
1607
|
+
}
|
|
1608
|
+
.chat-sidebar-group-act svg {
|
|
1609
|
+
width: 15px; height: 15px;
|
|
1610
|
+
fill: none; stroke: currentColor; stroke-width: 1.8;
|
|
1611
|
+
stroke-linecap: round; stroke-linejoin: round;
|
|
1612
|
+
}
|
|
1613
|
+
.chat-sidebar-group-act:hover { color: var(--ink); }
|
|
1614
|
+
.chat-sidebar-group-act.chat-sidebar-group-add {
|
|
1615
|
+
width: 26px; height: 26px;
|
|
1616
|
+
}
|
|
1617
|
+
.chat-sidebar-group-act.chat-sidebar-group-add svg {
|
|
1618
|
+
width: 17px; height: 17px;
|
|
1619
|
+
}
|
|
1620
|
+
.chat-sidebar-group-more.is-open { color: var(--ink); background: var(--line); }
|
|
1621
|
+
/* 项目分组菜单:固定定位浮层,锚定右键位置或 ⋯ 按钮下方;浅/深色主题自适应 */
|
|
1622
|
+
.chat-sidebar-project-menu {
|
|
1623
|
+
position: fixed; z-index: 300;
|
|
1624
|
+
min-width: 150px; padding: 5px;
|
|
1625
|
+
border: 1px solid var(--line); border-radius: 10px;
|
|
1626
|
+
background: var(--panel, var(--bg)); box-shadow: 0 8px 24px rgba(0,0,0,.22);
|
|
1627
|
+
display: flex; flex-direction: column; gap: 2px;
|
|
1628
|
+
}
|
|
1629
|
+
.chat-sidebar-project-menu button {
|
|
1630
|
+
display: flex; align-items: center; gap: 9px; width: 100%;
|
|
1631
|
+
padding: 7px 9px; border: none; border-radius: 7px;
|
|
1632
|
+
background: transparent; color: var(--ink); font-size: 13px; cursor: pointer; text-align: left;
|
|
1633
|
+
}
|
|
1634
|
+
.chat-sidebar-project-menu button:hover { background: var(--hover); }
|
|
1635
|
+
.chat-sidebar-project-menu button svg {
|
|
1636
|
+
width: 15px; height: 15px; flex: 0 0 auto;
|
|
1637
|
+
fill: none; stroke: var(--ink-soft); stroke-width: 1.8;
|
|
1638
|
+
stroke-linecap: round; stroke-linejoin: round;
|
|
1639
|
+
}
|
|
1640
|
+
.chat-sidebar-project-menu button:hover svg { stroke: var(--ink); }
|
|
1641
|
+
/* 「删除全部会话」危险项:文字/图标转危险色 */
|
|
1642
|
+
.chat-sidebar-project-menu button.is-danger,
|
|
1643
|
+
.chat-sidebar-project-menu button.is-danger:hover { color: var(--danger, #e5484d); }
|
|
1644
|
+
.chat-sidebar-project-menu button.is-danger svg,
|
|
1645
|
+
.chat-sidebar-project-menu button.is-danger:hover svg { stroke: var(--danger, #e5484d); }
|
|
1646
|
+
|
|
1647
|
+
/* 会话条目长按/⋯ 菜单:portal 到 body 渲染(脱离侧栏抽屉 overflow/层叠上下文);
|
|
1648
|
+
z-index 抬到 1100+,确保盖住移动端抽屉(200)、遮罩(150)、topbar(220) 与各类浮层 */
|
|
1649
|
+
.chat-sidebar-session-menu { z-index: 1100; }
|
|
1650
|
+
|
|
1651
|
+
|
|
1652
|
+
|
|
1653
|
+
/* Shimmer 扫光:核心规则 = 最后一个展示给用户的提示持续播放,表明 Agent 仍在干活、没有卡死。
|
|
1654
|
+
命中两处(均由 ChatWindow 流式判定触发):
|
|
1655
|
+
① 活动步「正在思考…」文字(.chat-thinking-head .chat-thinking-label);
|
|
1656
|
+
② 正在运行的工具行:状态与命令在同一个文本元素中,共用一条扫光带,覆盖可见整行。
|
|
1657
|
+
一条高光带沿文字从左往右循环掠过;基础色=--shine-base、高光=--shine(见 :root 与 [data-theme=dark])。
|
|
1658
|
+
亮色模式:静止浅灰 → 扫过填深墨(高对比、明显);暗色模式:静止浅灰 → 扫过填白(深底亮闪)。 */
|
|
1659
|
+
/* 节奏对标 WorkBuddy:快速扫过 → 稍作停留 → 再重复(干脆利落、有顿挫)。
|
|
1660
|
+
高光带收窄(占文字~0.6倍宽) + background-size:300% + no-repeat,使扫描能「彻底扫出文字」。
|
|
1661
|
+
方向:左→右。0% 高光带在左侧外(文字零光);前 ~40% 线性匀速扫到右侧外(快速掠过整段文字);
|
|
1662
|
+
40%~100% 定格(高光已完全离开文字,只显示纯文字=停留);循环回 0% 时两端文字均零光,无缝衔接。 */
|
|
1663
|
+
@keyframes chatTextShine {
|
|
1664
|
+
0% { background-position: 90% 0; }
|
|
1665
|
+
40% { background-position: 10% 0; }
|
|
1666
|
+
100% { background-position: 10% 0; }
|
|
1667
|
+
}
|
|
1668
|
+
.chat-thinking-head .chat-thinking-label,
|
|
1669
|
+
.chat-thinking-done-toggle.is-running .chat-thinking-tool-name,
|
|
1670
|
+
.chat-thinking-done-toggle.is-running .chat-thinking-tool-file,
|
|
1671
|
+
.chat-thinking-done-toggle.is-running .chat-thinking-browser-label {
|
|
1672
|
+
position: relative;
|
|
1673
|
+
/* 收窄高光带(40%→60%,占文字~0.6倍宽),两侧留足余量,保证带子能完全扫出文字。
|
|
1674
|
+
基础色用 --shine-base(浅色=浅灰、深色=浅灰),高光用 --shine(浅色=深墨、深色=白)。 */
|
|
1675
|
+
background: linear-gradient(
|
|
1676
|
+
90deg,
|
|
1677
|
+
var(--shine-base) 0%,
|
|
1678
|
+
var(--shine-base) 40%,
|
|
1679
|
+
var(--shine) 50%,
|
|
1680
|
+
var(--shine-base) 60%,
|
|
1681
|
+
var(--shine-base) 100%
|
|
1682
|
+
);
|
|
1683
|
+
background-size: 300% 100%;
|
|
1684
|
+
background-repeat: no-repeat;
|
|
1685
|
+
background-position: 90% 0;
|
|
1686
|
+
-webkit-background-clip: text;
|
|
1687
|
+
background-clip: text;
|
|
1688
|
+
color: transparent;
|
|
1689
|
+
/* linear = 匀速干脆不拖泥带水;2.1s 内前 40%(~0.84s) 快速扫过、后 60%(~1.26s) 停留。
|
|
1690
|
+
停点时高光已完全离开文字(文字零光),解决「停留发生在半途、文字还带光」的怪感。 */
|
|
1691
|
+
animation: chatTextShine 2.1s linear infinite;
|
|
1692
|
+
}
|
|
1693
|
+
/* 工具调用/浏览器胶囊文字:基础色与思考提示统一 --shine-base(见 :root 与 [data-theme=dark])。
|
|
1694
|
+
注意:必须用 background-image(longhand)而非 background 简写——
|
|
1695
|
+
简写会把 background-clip 重置为 border-box,导致上方规则的 background-clip:text 失效,
|
|
1696
|
+
文字透明后渐变铺满元素矩形 → 变成「灰色渐变条」而非文字扫光。 */
|
|
1697
|
+
.chat-thinking-done-toggle.is-running .chat-thinking-tool-name,
|
|
1698
|
+
.chat-thinking-done-toggle.is-running .chat-thinking-tool-file,
|
|
1699
|
+
.chat-thinking-done-toggle.is-running .chat-thinking-browser-label {
|
|
1700
|
+
background-image: linear-gradient(
|
|
1701
|
+
90deg,
|
|
1702
|
+
var(--shine-base) 0%,
|
|
1703
|
+
var(--shine-base) 40%,
|
|
1704
|
+
var(--shine) 50%,
|
|
1705
|
+
var(--shine-base) 60%,
|
|
1706
|
+
var(--shine-base) 100%
|
|
1707
|
+
);
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
/* 通知权限引导条(仅 Web 且通知被浏览器拒绝时出现;悬浮于输入卡片上方) */
|
|
1711
|
+
.chat-notify-banner {
|
|
1712
|
+
position: absolute; left: 14px; right: 14px; bottom: calc(100% + 8px);
|
|
1713
|
+
display: flex; align-items: center; gap: 8px;
|
|
1714
|
+
padding: 8px 12px; border-radius: 10px;
|
|
1715
|
+
background: var(--panel); border: 1px solid var(--line);
|
|
1716
|
+
box-shadow: 0 4px 16px rgba(20, 27, 38, .10);
|
|
1717
|
+
z-index: 31;
|
|
1718
|
+
}
|
|
1719
|
+
.chat-notify-banner-icon { width: 15px; height: 15px; flex: 0 0 auto; fill: none; stroke: var(--brand); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
|
|
1720
|
+
.chat-notify-banner-text { flex: 1 1 auto; font-size: 12px; color: var(--ink); line-height: 1.5; }
|
|
1721
|
+
.chat-notify-banner-link {
|
|
1722
|
+
flex: 0 0 auto; font-size: 12px; font-weight: 600; color: var(--brand);
|
|
1723
|
+
text-decoration: none; white-space: nowrap;
|
|
1724
|
+
}
|
|
1725
|
+
.chat-notify-banner-close {
|
|
1726
|
+
flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
|
|
1727
|
+
width: 22px; height: 22px; border-radius: 6px;
|
|
1728
|
+
border: none; background: transparent; color: var(--ink-soft); cursor: pointer;
|
|
1729
|
+
}
|
|
1730
|
+
.chat-notify-banner-close svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
|
|
1731
|
+
|
|
1732
|
+
/* 待发消息队列(steer):与输入卡片共用 stack 面板,视觉上连成一体。
|
|
1733
|
+
队列只保留顶部圆角(与外层 stack 一致),内部条目之间用 1px 分隔线
|
|
1734
|
+
(最后一条无线),条目本身不再带独立背景/边框/圆角。
|
|
1735
|
+
overflow 用于裁剪 item hover 背景,避免超出 stack 圆角。 */
|
|
1736
|
+
.chat-queue {
|
|
1737
|
+
flex: 0 1 auto;
|
|
1738
|
+
min-height: 0;
|
|
1739
|
+
display: flex; flex-direction: column; gap: 0;
|
|
1740
|
+
max-height: 42vh; overflow: hidden auto;
|
|
1741
|
+
border-radius: 20px 20px 0 0;
|
|
1742
|
+
/* 与 composer 同处一个 stack 面板,但用极微弱的深色叠加让 queue 区可辨识,
|
|
1743
|
+
提示用户“上方是待插队消息,下方是主输入区”,对比度刻意保持克制 */
|
|
1744
|
+
background: rgba(0, 0, 0, 0.06);
|
|
1745
|
+
}
|
|
1746
|
+
.chat-queue-item {
|
|
1747
|
+
display: flex; align-items: center; gap: 8px;
|
|
1748
|
+
padding: 10px 12px; min-width: 0;
|
|
1749
|
+
border-bottom: 1px solid var(--line);
|
|
1750
|
+
cursor: grab;
|
|
1751
|
+
}
|
|
1752
|
+
.chat-queue-item:last-child { border-bottom: none; }
|
|
1753
|
+
.chat-queue-item:hover { background: var(--hover); }
|
|
1754
|
+
.chat-queue-item:active { cursor: grabbing; }
|
|
1755
|
+
.chat-queue-grip {
|
|
1756
|
+
flex: none; display: grid; place-items: center;
|
|
1757
|
+
width: 16px; height: 20px; color: var(--ink-soft);
|
|
1758
|
+
}
|
|
1759
|
+
.chat-queue-grip svg { width: 12px; height: 16px; fill: currentColor; }
|
|
1760
|
+
.chat-queue-text {
|
|
1761
|
+
flex: 1; min-width: 0; font-size: 13px; color: var(--ink);
|
|
1762
|
+
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
1763
|
+
}
|
|
1764
|
+
.chat-queue-act {
|
|
1765
|
+
flex: none; width: 26px; height: 26px; padding: 0; display: grid; place-items: center;
|
|
1766
|
+
border: none; border-radius: 7px; background: transparent; color: var(--ink-soft); cursor: pointer;
|
|
1767
|
+
}
|
|
1768
|
+
.chat-queue-act svg {
|
|
1769
|
+
width: 16px; height: 16px;
|
|
1770
|
+
fill: none; stroke: currentColor; stroke-width: 1.7;
|
|
1771
|
+
stroke-linecap: round; stroke-linejoin: round;
|
|
1772
|
+
}
|
|
1773
|
+
.chat-queue-notice { font-size: 12px; color: var(--ink-soft); padding: 7px 12px 9px; }
|
|
1774
|
+
|
|
1775
|
+
/* 有附件时:附件条在卡片内 textarea 上方;textarea 压缩为一行、卡片上内边距收窄,
|
|
1776
|
+
合计与无附件时的总高度一致,聊天区高度与页面均不抖动。 */
|
|
1777
|
+
.chat-composer.has-attachment { padding-top: 8px; }
|
|
1778
|
+
.chat-composer.has-attachment textarea { min-height: 20px; }
|
|
1779
|
+
.chat-composer.has-attachment .chat-attachment-wrap { margin-bottom: 4px; }
|
|
1780
|
+
|
|
1781
|
+
/* 场景分类选择按钮组:输入卡片外部的上一行,按场景路由到不同钉钉文档 */
|
|
1782
|
+
.chat-scene-bar { padding: 10px 14px 4px; }
|
|
1783
|
+
.chat-scenes { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
1784
|
+
.chat-scene {
|
|
1785
|
+
height: 30px; padding: 0 14px; border-radius: 999px;
|
|
1786
|
+
border: 1px solid var(--line); background: var(--field-bg); color: var(--ink-soft);
|
|
1787
|
+
font-size: 13px; cursor: pointer; line-height: 1; white-space: nowrap;
|
|
1788
|
+
transition: all .12s ease;
|
|
1789
|
+
}
|
|
1790
|
+
.chat-scene.is-active {
|
|
1791
|
+
border-color: var(--brand); background: var(--brand-soft); color: var(--brand-dark);
|
|
1792
|
+
font-weight: 600;
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1795
|
+
.chat-toolbar { display: flex; align-items: center; gap: 4px; padding-top: 4px; }
|
|
1796
|
+
|
|
1797
|
+
/* 上传附件:仅 + 图标。hover 背景为圆形 */
|
|
1798
|
+
.chat-tool {
|
|
1799
|
+
width: 36px; height: 36px; padding: 0;
|
|
1800
|
+
display: flex; align-items: center; justify-content: center;
|
|
1801
|
+
border: none; border-radius: 50%; background: transparent;
|
|
1802
|
+
color: var(--ink-soft); cursor: pointer;
|
|
1803
|
+
}
|
|
1804
|
+
.chat-tool:disabled { opacity: .45; cursor: default; }
|
|
1805
|
+
.chat-tool svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
|
|
1806
|
+
|
|
1807
|
+
/* AgentApp 首屏加载占位:全屏居中黑白灰 spinner */
|
|
1808
|
+
.agent-kit-loading {
|
|
1809
|
+
position: fixed; inset: 0;
|
|
1810
|
+
display: flex; align-items: center; justify-content: center;
|
|
1811
|
+
background: var(--bg);
|
|
1812
|
+
}
|
|
1813
|
+
.agent-kit-loading::after {
|
|
1814
|
+
content: "";
|
|
1815
|
+
width: 22px; height: 22px; border-radius: 50%;
|
|
1816
|
+
border: 2px solid var(--spin-edge); border-top-color: var(--spin-top);
|
|
1817
|
+
animation: agentKitLoadingSpin .7s linear infinite;
|
|
1818
|
+
}
|
|
1819
|
+
@keyframes agentKitLoadingSpin { to { transform: rotate(360deg); } }
|
|
1820
|
+
|
|
1821
|
+
/* 语音输入:图标按钮,放在发送按钮旁边;录音时仅变为红色停止图标。hover 背景为圆形 */
|
|
1822
|
+
.chat-voice {
|
|
1823
|
+
width: 36px; height: 36px; padding: 0;
|
|
1824
|
+
display: flex; align-items: center; justify-content: center;
|
|
1825
|
+
border: none; border-radius: 50%; background: transparent;
|
|
1826
|
+
color: var(--ink-soft); cursor: pointer;
|
|
1827
|
+
}
|
|
1828
|
+
.chat-voice-icon { width: 22px; height: 22px; display: grid; place-items: center; color: inherit; }
|
|
1829
|
+
.chat-voice-icon svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
|
|
1830
|
+
.chat-voice-icon--stop svg { fill: currentColor; stroke: none; }
|
|
1831
|
+
.chat-voice:disabled { opacity: .45; cursor: default; }
|
|
1832
|
+
/* 录音进行中:按钮变红(停止态),时长提示在按钮左边 */
|
|
1833
|
+
.chat-voice.recording { background: var(--danger-soft); color: var(--danger); }
|
|
1834
|
+
.chat-voice.connecting { justify-content: center; }
|
|
1835
|
+
.chat-voice-spinner { width: 17px; height: 17px; box-sizing: border-box; border: 2px solid #c7d7ea; border-top-color: #2563eb; border-radius: 50%; animation: chatVoiceSpin .75s linear infinite; }
|
|
1836
|
+
/* 录音时长 / 10 分钟上限提示:位于语音按钮左侧 */
|
|
1837
|
+
.chat-voice-hint {
|
|
1838
|
+
display: inline-flex; align-items: center; gap: 6px; height: 36px; padding: 0 6px;
|
|
1839
|
+
font-size: 12px; font-weight: 500; color: var(--ink-soft);
|
|
1840
|
+
font-variant-numeric: tabular-nums; letter-spacing: .3px;
|
|
1841
|
+
}
|
|
1842
|
+
.chat-voice-dot { width: 8px; height: 8px; border-radius: 50%; background: #dc2626; animation: chatVoicePulse 1s ease-in-out infinite; }
|
|
1843
|
+
@keyframes chatVoicePulse { 50% { opacity: .25; } }
|
|
1844
|
+
@keyframes chatVoiceSpin { to { transform: rotate(360deg); } }
|
|
1845
|
+
|
|
1846
|
+
.chat-tool-spacer { flex: 1; }
|
|
1847
|
+
/* 上下文容量环形指示(输入框右侧、模型名左侧,对标 WorkBuddy):圆环 + 百分比,三档状态色 */
|
|
1848
|
+
.ctx-meter {
|
|
1849
|
+
display: inline-flex; align-items: center; gap: 5px;
|
|
1850
|
+
flex: 0 0 auto; padding: 4px 8px;
|
|
1851
|
+
border-radius: 8px; cursor: default;
|
|
1852
|
+
font-size: 12px; line-height: 1; color: var(--ink-soft);
|
|
1853
|
+
position: relative;
|
|
1854
|
+
}
|
|
1855
|
+
.ctx-meter svg { width: 16px; height: 16px; display: block; }
|
|
1856
|
+
.ctx-meter-track { fill: none; stroke: color-mix(in srgb, var(--line) 40%, transparent); stroke-width: 1.5; }
|
|
1857
|
+
.ctx-meter-bar {
|
|
1858
|
+
fill: none; stroke-width: 1.5; stroke-linecap: round;
|
|
1859
|
+
transform: rotate(-90deg); transform-origin: 50% 50%;
|
|
1860
|
+
transition: stroke-dashoffset .3s ease, stroke .3s ease;
|
|
1861
|
+
}
|
|
1862
|
+
/* 圆环只作容量提示:未用部分浅、已用部分深,但整体刻意降饱和,不抢主线视线 */
|
|
1863
|
+
.ctx-meter--ok .ctx-meter-bar { stroke: color-mix(in srgb, var(--ink-soft) 40%, transparent); }
|
|
1864
|
+
.ctx-meter--warn .ctx-meter-bar { stroke: color-mix(in srgb, var(--ink-soft) 70%, transparent); }
|
|
1865
|
+
.ctx-meter--danger .ctx-meter-bar { stroke: var(--ink-soft); }
|
|
1866
|
+
.ctx-meter--neutral .ctx-meter-bar { stroke: color-mix(in srgb, var(--ink-soft) 45%, transparent); }
|
|
1867
|
+
.ctx-meter.is-compacting { animation: ctx-meter-pulse 1s ease infinite; }
|
|
1868
|
+
@keyframes ctx-meter-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .4; } }
|
|
1869
|
+
/* hover 详情浮层(对标 WorkBuddy):已用百分比 · 已用/上限 tokens;深色浮层向上弹出 */
|
|
1870
|
+
.ctx-meter::after {
|
|
1871
|
+
content: attr(data-tip);
|
|
1872
|
+
position: absolute;
|
|
1873
|
+
bottom: calc(100% + 10px);
|
|
1874
|
+
left: 50%;
|
|
1875
|
+
transform: translateX(-50%);
|
|
1876
|
+
white-space: nowrap;
|
|
1877
|
+
padding: 5px 9px;
|
|
1878
|
+
border-radius: 7px;
|
|
1879
|
+
background: var(--bg-float, #fdfdfd);
|
|
1880
|
+
color: var(--ink, #1a1a1a);
|
|
1881
|
+
border: 1px solid var(--line, #e3e8f0);
|
|
1882
|
+
font-size: 12px;
|
|
1883
|
+
line-height: 1.5;
|
|
1884
|
+
box-shadow: 0 4px 14px rgb(0 0 0 / .15);
|
|
1885
|
+
opacity: 0;
|
|
1886
|
+
pointer-events: none;
|
|
1887
|
+
transition: opacity .12s ease;
|
|
1888
|
+
z-index: 40;
|
|
1889
|
+
}
|
|
1890
|
+
:root[data-theme="dark"] .ctx-meter::after {
|
|
1891
|
+
background: var(--bg-float, #212121);
|
|
1892
|
+
color: #f0f0f0;
|
|
1893
|
+
border-color: #3a3a3a;
|
|
1894
|
+
}
|
|
1895
|
+
.ctx-meter:hover::after { opacity: 1; }
|
|
1896
|
+
/* 中栏很窄时(窗口收窄 / 右栏拖宽挤压中栏):工具条放不下模型选择按钮,
|
|
1897
|
+
隐藏它避免挤压导致输入卡片内容溢出、显示错乱。
|
|
1898
|
+
用容器查询(容器 = .chat-composer-stack)而非视口媒体查询:
|
|
1899
|
+
中栏宽度随右栏拖拽实时变化,视口宽度不变,媒体查询无法跟随。 */
|
|
1900
|
+
@container composer (max-width: 360px) {
|
|
1901
|
+
.chat-model-picker { display: none; }
|
|
1902
|
+
}
|
|
1903
|
+
/* 模型选择下拉(现代风格,向上弹出):触发按钮与 + 号/语音按钮一致——无背景无边框,
|
|
1904
|
+
hover 才出现浅灰胶囊圆角背景;菜单为圆角浮层,黑白灰系 */
|
|
1905
|
+
.chat-model-picker { position: relative; flex: 0 0 auto; }
|
|
1906
|
+
.chat-model-picker-btn {
|
|
1907
|
+
display: inline-flex; align-items: center; gap: 4px;
|
|
1908
|
+
height: 36px; padding: 0 12px;
|
|
1909
|
+
border: none; background: transparent; border-radius: 999px;
|
|
1910
|
+
color: var(--ink); font-size: 13px; font-family: inherit; cursor: pointer;
|
|
1911
|
+
transition: background .15s ease;
|
|
1912
|
+
}
|
|
1913
|
+
.chat-model-picker-btn.open { background: var(--hover); }
|
|
1914
|
+
.chat-model-picker-name {
|
|
1915
|
+
max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
1916
|
+
}
|
|
1917
|
+
.chat-model-picker-chev {
|
|
1918
|
+
width: 14px; height: 14px; flex: 0 0 auto;
|
|
1919
|
+
fill: none; stroke: var(--ink-soft); stroke-width: 1.6;
|
|
1920
|
+
stroke-linecap: round; stroke-linejoin: round;
|
|
1921
|
+
transition: transform .15s ease;
|
|
1922
|
+
}
|
|
1923
|
+
.chat-model-picker-btn.open .chat-model-picker-chev { transform: rotate(180deg); }
|
|
1924
|
+
.chat-model-picker-menu {
|
|
1925
|
+
position: absolute; right: 0; bottom: calc(100% + 6px);
|
|
1926
|
+
min-width: 200px; margin: 0; padding: 4px; list-style: none;
|
|
1927
|
+
background: var(--overlay-bg); border: 1px solid var(--line); border-radius: 12px;
|
|
1928
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, .08);
|
|
1929
|
+
z-index: 30;
|
|
1930
|
+
max-height: 240px; overflow-y: auto;
|
|
1931
|
+
}
|
|
1932
|
+
.chat-model-picker-item {
|
|
1933
|
+
display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
|
1934
|
+
padding: 9px 12px; border-radius: 8px;
|
|
1935
|
+
font-size: 13px; line-height: 1.3; color: var(--ink);
|
|
1936
|
+
cursor: pointer; white-space: nowrap;
|
|
1937
|
+
transition: background .12s ease;
|
|
1938
|
+
}
|
|
1939
|
+
.chat-model-picker-item.selected { color: var(--ink); font-weight: 600; }
|
|
1940
|
+
/* 下拉项:名称(主)+ id(副,models.json 自定义模型时附显示) */
|
|
1941
|
+
.chat-model-picker-item-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
|
1942
|
+
.chat-model-picker-item-name { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1943
|
+
.chat-model-picker-item-id {
|
|
1944
|
+
font-size: 11px; line-height: 1.2; color: var(--ink-soft);
|
|
1945
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
1946
|
+
max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
1947
|
+
}
|
|
1948
|
+
/* 悬停信息卡:展示当前模型详情(provider/上下文窗口/能力),不展示 apiKey */
|
|
1949
|
+
.chat-model-picker-detail {
|
|
1950
|
+
position: absolute; right: 0; bottom: calc(100% + 8px);
|
|
1951
|
+
min-width: 260px; max-width: 340px; padding: 12px 14px;
|
|
1952
|
+
background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
|
|
1953
|
+
box-shadow: 0 10px 30px rgba(0,0,0,.20);
|
|
1954
|
+
pointer-events: none; z-index: 30;
|
|
1955
|
+
font-size: 12.5px; line-height: 1.4; color: var(--ink);
|
|
1956
|
+
}
|
|
1957
|
+
.chat-model-picker-detail-head { display: flex; flex-direction: column; gap: 3px; margin-bottom: 10px; }
|
|
1958
|
+
.chat-model-picker-detail-name { font-weight: 600; font-size: 13.5px; }
|
|
1959
|
+
.chat-model-picker-detail-id {
|
|
1960
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
1961
|
+
font-size: 11px; color: var(--ink-soft); word-break: break-all;
|
|
1962
|
+
}
|
|
1963
|
+
.chat-model-picker-detail-rows { display: flex; flex-direction: column; gap: 7px; }
|
|
1964
|
+
.chat-model-picker-detail-row { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; }
|
|
1965
|
+
.chat-model-picker-detail-label { color: var(--ink-soft); flex: 0 0 auto; }
|
|
1966
|
+
.chat-model-picker-detail-value { text-align: right; word-break: break-all; }
|
|
1967
|
+
.chat-model-picker-check {
|
|
1968
|
+
width: 14px; height: 14px; flex: 0 0 auto;
|
|
1969
|
+
fill: none; stroke: currentColor; stroke-width: 2;
|
|
1970
|
+
stroke-linecap: round; stroke-linejoin: round;
|
|
1971
|
+
}
|
|
1972
|
+
/* 语音/附件报错:底部工具栏内、靠近右侧图标组 */
|
|
1973
|
+
.chat-hint--error {
|
|
1974
|
+
display: inline-flex; align-items: center;
|
|
1975
|
+
color: var(--danger); background: var(--danger-soft); border: 1px solid rgba(240, 97, 109, .35);
|
|
1976
|
+
border-radius: 8px; padding: 5px 8px; font-size: 11.5px; line-height: 1.3;
|
|
1977
|
+
max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
.chat-send {
|
|
1981
|
+
width: 36px; height: 36px; border: none; border-radius: 50%;
|
|
1982
|
+
background: var(--send-bg); color: var(--send-ink); cursor: pointer;
|
|
1983
|
+
display: flex; align-items: center; justify-content: center;
|
|
1984
|
+
box-shadow: 0 4px 10px rgba(0,0,0,.15);
|
|
1985
|
+
}
|
|
1986
|
+
/* 无输入时发送按钮禁用:禁止光标;hover 不改变外观(避免与可发送态混淆) */
|
|
1987
|
+
.chat-send:disabled { opacity: .45; cursor: not-allowed; transform: none; }
|
|
1988
|
+
.chat-send svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
|
|
1989
|
+
/* 图片附件 + 疑似不支持图片的模型:输入卡片内的黄色提醒条(仅提示,不拦截发送) */
|
|
1990
|
+
.chat-vision-warning {
|
|
1991
|
+
margin-top: 6px; font-size: 12px; line-height: 1.55; color: #92400e;
|
|
1992
|
+
background: #fef3c7; border: 1px solid #fde68a; border-radius: 8px;
|
|
1993
|
+
padding: 6px 10px; max-width: 100%;
|
|
1994
|
+
}
|
|
1995
|
+
/* 附件条(输入卡片内、textarea 上方):默认显示类型图标(图片/文件),
|
|
1996
|
+
hover 时移除按钮替换图标位(与 WorkBuddy 一致) */
|
|
1997
|
+
.chat-attachment-wrap { position: relative; display: inline-block; max-width: fit-content; }
|
|
1998
|
+
.chat-attachment {
|
|
1999
|
+
display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--ink);
|
|
2000
|
+
background: var(--brand-soft); border: 1px solid var(--brand-line); border-radius: 8px;
|
|
2001
|
+
padding: 4px 8px; max-width: fit-content;
|
|
2002
|
+
}
|
|
2003
|
+
/* 附件图标位:默认显示类型图标(图片/文件),hover 时被移除按钮替换(与 WorkBuddy 一致) */
|
|
2004
|
+
.chat-attachment-icon-wrap { position: relative; width: 18px; height: 18px; flex: none; display: grid; place-items: center; }
|
|
2005
|
+
.chat-attachment-icon { display: grid; place-items: center; width: 18px; height: 18px; color: var(--brand-dark); transition: opacity .12s ease; }
|
|
2006
|
+
.chat-attachment-icon svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
|
|
2007
|
+
.chat-attachment-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
2008
|
+
.chat-attachment-remove {
|
|
2009
|
+
position: absolute; inset: 0; display: grid; place-items: center;
|
|
2010
|
+
border: none; background: transparent; color: var(--danger); cursor: pointer;
|
|
2011
|
+
font-size: 17px; line-height: 1; padding: 0; border-radius: 50%;
|
|
2012
|
+
opacity: 0; transform: scale(.6); transition: opacity .12s ease, transform .12s ease;
|
|
2013
|
+
}
|
|
2014
|
+
/* 附件 hover 图片预览:浮层出现在附件条上方(仅图片附件渲染,纯 CSS 控制显隐) */
|
|
2015
|
+
.chat-attachment-preview {
|
|
2016
|
+
position: absolute; left: 0; bottom: calc(100% + 6px);
|
|
2017
|
+
padding: 8px; background: var(--overlay-bg); border: 1px solid var(--line); border-radius: 10px;
|
|
2018
|
+
box-shadow: 0 4px 16px rgba(15, 23, 42, .12);
|
|
2019
|
+
opacity: 0; visibility: hidden; transform: translateY(4px);
|
|
2020
|
+
transition: opacity .12s ease, transform .12s ease, visibility .12s;
|
|
2021
|
+
z-index: 30; pointer-events: none; max-width: 436px;
|
|
2022
|
+
}
|
|
2023
|
+
.chat-attachment-preview img {
|
|
2024
|
+
display: block; max-width: 420px; max-height: 320px;
|
|
2025
|
+
border-radius: 6px; object-fit: contain;
|
|
2026
|
+
}
|
|
2027
|
+
|
|
2028
|
+
/* 拖拽添加附件:文件拖入页面时的全屏蒙版(pointer-events 穿透,drop 仍落在 window 上)。
|
|
2029
|
+
不使用 backdrop-filter:渲染开销会在大面积拖拽时造成界面抖动。 */
|
|
2030
|
+
.chat-drop-overlay {
|
|
2031
|
+
position: fixed; inset: 0; z-index: 100;
|
|
2032
|
+
display: flex; align-items: center; justify-content: center;
|
|
2033
|
+
background: rgba(47, 107, 255, .10);
|
|
2034
|
+
pointer-events: none;
|
|
2035
|
+
}
|
|
2036
|
+
.chat-drop-box {
|
|
2037
|
+
padding: 18px 34px; border-radius: 14px;
|
|
2038
|
+
background: var(--fade-stop); border: 2px dashed var(--brand);
|
|
2039
|
+
color: var(--brand-dark); font-size: 16px; font-weight: 600;
|
|
2040
|
+
box-shadow: 0 8px 30px rgba(31, 39, 51, .14);
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
/* ============ 运营后台 admin ============ */
|
|
2044
|
+
.admin-page {
|
|
2045
|
+
min-height: 100vh;
|
|
2046
|
+
max-width: 1240px;
|
|
2047
|
+
margin: 0 auto;
|
|
2048
|
+
padding: 18px 22px 30px;
|
|
2049
|
+
display: flex;
|
|
2050
|
+
flex-direction: column;
|
|
2051
|
+
gap: 16px;
|
|
2052
|
+
}
|
|
2053
|
+
.admin-topbar {
|
|
2054
|
+
display: flex; align-items: center; gap: 12px;
|
|
2055
|
+
padding: 10px 2px 2px;
|
|
2056
|
+
}
|
|
2057
|
+
.admin-brand { display: flex; align-items: center; gap: 11px; }
|
|
2058
|
+
.admin-logo { height: 28px; width: auto; display: block; }
|
|
2059
|
+
.admin-title { margin: 0; font-size: 22px; font-weight: 800; letter-spacing: .3px; }
|
|
2060
|
+
.admin-range {
|
|
2061
|
+
display: flex; gap: 2px;
|
|
2062
|
+
margin-left: auto;
|
|
2063
|
+
background: var(--field-soft); border: 1px solid var(--line); border-radius: 10px;
|
|
2064
|
+
padding: 3px;
|
|
2065
|
+
}
|
|
2066
|
+
.admin-range button {
|
|
2067
|
+
border: none; background: transparent; padding: 5px 12px; border-radius: 8px;
|
|
2068
|
+
font-size: 12.5px; color: var(--ink-soft); cursor: pointer; white-space: nowrap;
|
|
2069
|
+
transition: all .12s ease;
|
|
2070
|
+
}
|
|
2071
|
+
.admin-range button.on {
|
|
2072
|
+
background: var(--overlay-bg); color: var(--brand-dark); font-weight: 600;
|
|
2073
|
+
box-shadow: 0 1px 4px rgba(31, 39, 51, .14);
|
|
2074
|
+
}
|
|
2075
|
+
.admin-clock {
|
|
2076
|
+
font-size: 13px; color: var(--ink-soft);
|
|
2077
|
+
font-variant-numeric: tabular-nums; letter-spacing: .4px;
|
|
2078
|
+
}
|
|
2079
|
+
|
|
2080
|
+
.admin-kpis {
|
|
2081
|
+
display: grid;
|
|
2082
|
+
grid-template-columns: repeat(6, 1fr);
|
|
2083
|
+
gap: 14px;
|
|
2084
|
+
}
|
|
2085
|
+
.admin-kpi {
|
|
2086
|
+
display: flex; align-items: flex-start; gap: 12px;
|
|
2087
|
+
background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
|
|
2088
|
+
padding: 16px 16px 14px; box-shadow: 0 2px 10px rgba(31, 39, 51, .04);
|
|
2089
|
+
}
|
|
2090
|
+
.admin-kpi-icon {
|
|
2091
|
+
flex: none; width: 40px; height: 40px; border-radius: 11px;
|
|
2092
|
+
display: grid; place-items: center; color: var(--brand); background: var(--brand-soft);
|
|
2093
|
+
}
|
|
2094
|
+
.admin-kpi--orange .admin-kpi-icon { color: #b45309; background: var(--warn-soft); }
|
|
2095
|
+
.admin-kpi--ok .admin-kpi-icon { color: var(--ok); background: var(--ok-soft); }
|
|
2096
|
+
.admin-kpi-body { min-width: 0; }
|
|
2097
|
+
.admin-kpi-label { font-size: 12.5px; color: var(--ink-soft); white-space: nowrap; }
|
|
2098
|
+
.admin-kpi-value {
|
|
2099
|
+
font-size: 25px; font-weight: 800; line-height: 1.25; margin: 2px 0 1px;
|
|
2100
|
+
font-variant-numeric: tabular-nums; white-space: nowrap;
|
|
2101
|
+
}
|
|
2102
|
+
.admin-kpi-unit { font-size: 13px; font-weight: 600; color: var(--ink-soft); margin-left: 2px; }
|
|
2103
|
+
.admin-kpi-sub {
|
|
2104
|
+
font-size: 11.5px; color: var(--ink-soft); line-height: 1.45;
|
|
2105
|
+
overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
2106
|
+
}
|
|
2107
|
+
|
|
2108
|
+
.admin-grid--pair { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
|
|
2109
|
+
.admin-card {
|
|
2110
|
+
background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
|
|
2111
|
+
padding: 16px 18px 12px; box-shadow: 0 2px 10px rgba(31, 39, 51, .04);
|
|
2112
|
+
min-width: 0;
|
|
2113
|
+
}
|
|
2114
|
+
.admin-card-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 6px; }
|
|
2115
|
+
.admin-card-head h3 { margin: 0; font-size: 14.5px; font-weight: 700; }
|
|
2116
|
+
.admin-card-hint { font-size: 11.5px; color: var(--ink-soft); }
|
|
2117
|
+
|
|
2118
|
+
.admin-chart-svg { width: 100%; height: auto; display: block; }
|
|
2119
|
+
.admin-gridline { stroke: var(--line); stroke-width: 1; }
|
|
2120
|
+
.admin-area { fill: rgba(47, 107, 255, .08); }
|
|
2121
|
+
.admin-line--ai { fill: none; stroke: var(--brand); stroke-width: 2.4; stroke-linejoin: round; }
|
|
2122
|
+
.admin-bar { fill: #c9dcff; }
|
|
2123
|
+
.admin-dot { fill: var(--panel); stroke: var(--brand); stroke-width: 2; }
|
|
2124
|
+
.admin-dot--today { fill: var(--brand); stroke: var(--panel); stroke-width: 2.4; }
|
|
2125
|
+
.admin-axis-x { font-size: 11px; fill: #8a94a6; }
|
|
2126
|
+
.admin-axis-y { font-size: 11px; fill: #8a94a6; }
|
|
2127
|
+
|
|
2128
|
+
.admin-pctbars { display: flex; flex-direction: column; gap: 9px; padding: 2px 0 6px; }
|
|
2129
|
+
.admin-pct-row { display: flex; align-items: center; gap: 10px; font-size: 12.5px; }
|
|
2130
|
+
.admin-pct-label { width: 64px; flex: none; color: var(--ink); }
|
|
2131
|
+
.admin-star { font-style: normal; color: #f5a623; }
|
|
2132
|
+
.admin-pct-track { flex: 1; height: 8px; border-radius: 999px; background: var(--field-soft); overflow: hidden; }
|
|
2133
|
+
.admin-pct-fill { display: block; height: 100%; border-radius: 999px; }
|
|
2134
|
+
.admin-pct-num { width: 40px; text-align: right; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
|
|
2135
|
+
|
|
2136
|
+
.admin-table-wrap { overflow-x: auto; }
|
|
2137
|
+
.admin-table { width: 100%; border-collapse: collapse; font-size: 13px; }
|
|
2138
|
+
.admin-table th {
|
|
2139
|
+
text-align: left; font-size: 12px; font-weight: 600; color: var(--ink-soft);
|
|
2140
|
+
padding: 8px 10px; border-bottom: 1px solid var(--line); white-space: nowrap;
|
|
2141
|
+
}
|
|
2142
|
+
.admin-table td { padding: 9px 10px; border-bottom: 1px solid var(--line); vertical-align: middle; }
|
|
2143
|
+
.admin-table tbody tr:last-child td { border-bottom: none; }
|
|
2144
|
+
.admin-name { font-weight: 600; }
|
|
2145
|
+
.admin-dept { margin-left: 8px; font-size: 11.5px; color: var(--ink-soft); }
|
|
2146
|
+
.admin-num { font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
2147
|
+
.admin-time { color: var(--ink-soft); }
|
|
2148
|
+
.admin-issue { max-width: 240px; }
|
|
2149
|
+
.admin-agent { font-size: 12.5px; color: var(--brand-dark); }
|
|
2150
|
+
|
|
2151
|
+
.admin-badge {
|
|
2152
|
+
display: inline-flex; align-items: center; gap: 5px;
|
|
2153
|
+
font-size: 12px; font-weight: 600; border-radius: 999px; padding: 3px 10px;
|
|
2154
|
+
white-space: nowrap;
|
|
2155
|
+
}
|
|
2156
|
+
.admin-badge i { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
|
|
2157
|
+
.admin-badge--ai { color: var(--brand-dark); background: var(--brand-soft); }
|
|
2158
|
+
.admin-badge--done { color: var(--ok); background: var(--ok-soft); }
|
|
2159
|
+
.admin-badge--active { color: var(--brand-dark); background: var(--brand-soft); }
|
|
2160
|
+
.admin-badge--escalated { color: #b45309; background: var(--warn-soft); }
|
|
2161
|
+
.admin-badge--queued { color: #a16207; background: var(--warn-soft); }
|
|
2162
|
+
|
|
2163
|
+
.admin-footer {
|
|
2164
|
+
text-align: center; font-size: 11.5px; color: var(--ink-soft);
|
|
2165
|
+
padding: 8px 0 2px;
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
@media (max-width: 1100px) {
|
|
2169
|
+
.admin-kpis { grid-template-columns: repeat(3, 1fr); }
|
|
2170
|
+
.admin-grid--pair { grid-template-columns: 1fr; }
|
|
2171
|
+
}
|
|
2172
|
+
@media (max-width: 720px) {
|
|
2173
|
+
.admin-kpis { grid-template-columns: repeat(2, 1fr); }
|
|
2174
|
+
.admin-topbar { flex-wrap: wrap; }
|
|
2175
|
+
.admin-range { margin-left: 0; flex-wrap: wrap; }
|
|
2176
|
+
.admin-clock { margin-left: auto; }
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2179
|
+
/* ============ 满意度评价(每条 AI 答复末尾) ============ */
|
|
2180
|
+
.chat-sat {
|
|
2181
|
+
display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 4px;
|
|
2182
|
+
flex: none;
|
|
2183
|
+
padding: 8px 12px;
|
|
2184
|
+
border: 1px solid var(--line);
|
|
2185
|
+
border-radius: 12px;
|
|
2186
|
+
background: var(--panel);
|
|
2187
|
+
}
|
|
2188
|
+
.chat-sat-title { font-size: 12px; font-weight: 600; line-height: 1.25; color: var(--ink); }
|
|
2189
|
+
.chat-sat-row { display: flex; align-items: center; gap: 10px; }
|
|
2190
|
+
.chat-sat-stars { display: inline-flex; gap: 2px; }
|
|
2191
|
+
.chat-sat-star {
|
|
2192
|
+
border: none; background: none; padding: 0; cursor: pointer;
|
|
2193
|
+
font-size: 18px; line-height: 1; color: var(--ink-soft);
|
|
2194
|
+
transition: transform .1s ease, color .1s ease;
|
|
2195
|
+
}
|
|
2196
|
+
.chat-sat-star.on { color: #f5a623; }
|
|
2197
|
+
.chat-sat-hint { font-size: 11.5px; color: var(--ink-soft); min-width: 68px; }
|
|
2198
|
+
.chat-sat-submit {
|
|
2199
|
+
margin-left: auto;
|
|
2200
|
+
border: none; border-radius: 8px; padding: 4px 14px;
|
|
2201
|
+
background: linear-gradient(135deg, var(--brand), var(--brand-dark)); color: #fff;
|
|
2202
|
+
font-size: 12px; font-weight: 600; cursor: pointer;
|
|
2203
|
+
}
|
|
2204
|
+
.chat-sat-submit:disabled { opacity: .45; cursor: default; }
|
|
2205
|
+
.chat-sat--done {
|
|
2206
|
+
flex-direction: row; align-items: center; gap: 8px;
|
|
2207
|
+
background: var(--ok-soft); border-color: rgba(52, 179, 107, .35);
|
|
2208
|
+
}
|
|
2209
|
+
.chat-sat--done .chat-sat-stars i { font-style: normal; font-size: 15px; color: var(--ink-soft); }
|
|
2210
|
+
.chat-sat--done .chat-sat-stars i.on { color: #f5a623; }
|
|
2211
|
+
.chat-sat-done-text { font-size: 12px; color: var(--ok); }
|
|
2212
|
+
|
|
2213
|
+
/* ============ 反馈操作条(点赞 / 点踩,描边图标按钮,仿 WorkBuddy 工具栏) ============ */
|
|
2214
|
+
.chat-fb {
|
|
2215
|
+
display: flex; align-items: center; gap: 4px;
|
|
2216
|
+
/* margin-top 由 .msg-footer 统一控制 */
|
|
2217
|
+
}
|
|
2218
|
+
.chat-fb-btn {
|
|
2219
|
+
width: 21px; height: 21px;
|
|
2220
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
2221
|
+
border: none; border-radius: 6px;
|
|
2222
|
+
background: transparent; cursor: pointer; padding: 0;
|
|
2223
|
+
color: var(--ink-soft);
|
|
2224
|
+
transition: color .15s, background .15s, transform .1s;
|
|
2225
|
+
}
|
|
2226
|
+
.chat-fb-btn:active { transform: scale(.92); }
|
|
2227
|
+
.chat-fb-btn svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
|
|
2228
|
+
.chat-fb-btn:hover, .chat-fb-vote.on { color: var(--ink); background: var(--hover); }
|
|
2229
|
+
.chat-fb-btn.is-copied { color: var(--ok); }
|
|
2230
|
+
.chat-fb-vote svg { width: 16px; height: 16px; }
|
|
2231
|
+
.chat-fb-menu-item svg { flex: 0 0 auto; width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
|
|
2232
|
+
.chat-fb-btn svg.chat-fb-icon-selected, .chat-fb-menu-item svg.chat-fb-icon-selected { fill: currentColor; stroke: none; }
|
|
2233
|
+
.chat-fb-menu-item:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
|
|
2234
|
+
.chat-fb-check { margin-left: auto; }
|
|
2235
|
+
.chat-fb-status { font-size: 11px; color: var(--ink-soft); }
|
|
2236
|
+
.chat-fb-status:empty { display: none; }
|
|
2237
|
+
.chat-fb-btn.on.up { color: var(--ok); border-color: var(--ok); background: rgba(35,162,111,.08); }
|
|
2238
|
+
.chat-fb-btn.on.down { color: #e5484d; border-color: #e5484d; background: rgba(229,72,77,.08); }
|
|
2239
|
+
/* 「更多」菜单(复制会话ID):WorkBuddy 风格悬浮小菜单,竖排选项;浮层用 CSS 变量随明暗主题 */
|
|
2240
|
+
.chat-fb-more-wrap { position: relative; display: inline-flex; }
|
|
2241
|
+
.chat-fb-more svg circle { fill: currentColor; stroke: none; }
|
|
2242
|
+
.chat-fb-more.on { color: var(--ink); border-color: var(--ink-soft); background: var(--line); }
|
|
2243
|
+
/* 「…」按钮作为菜单触发器,按下时不缩放,避免点击时的抖动;其 transform 过渡一并关闭 */
|
|
2244
|
+
.chat-fb-more:active { transform: none; }
|
|
2245
|
+
.chat-fb-more { transition: border-color .15s, color .15s, background .15s; }
|
|
2246
|
+
.chat-fb-menu-backdrop { position: fixed; inset: 0; z-index: 240; background: transparent; }
|
|
2247
|
+
.chat-fb-menu {
|
|
2248
|
+
/* z 高于聊天区所有浮层(输入区/待发队列 30、顶栏 220、历史/分享下拉 230):
|
|
2249
|
+
菜单即使弹到输入卡片上方,也始终在输入区之上,用户总能点到菜单项。
|
|
2250
|
+
定位由组件按按钮视口坐标 + 实测菜单高度计算(fixed,并在视口内 clamp):
|
|
2251
|
+
保证在屏幕任何位置点「…」菜单都不会被滚动容器裁剪或顶出屏幕 */
|
|
2252
|
+
z-index: 241;
|
|
2253
|
+
min-width: 158px; padding: 5px;
|
|
2254
|
+
background: var(--overlay-bg); border: 1px solid var(--line);
|
|
2255
|
+
border-radius: 10px; box-shadow: var(--shadow);
|
|
2256
|
+
}
|
|
2257
|
+
.chat-fb-menu-item {
|
|
2258
|
+
display: flex; align-items: center; gap: 8px;
|
|
2259
|
+
width: 100%; padding: 8px 10px; border: none; background: none; cursor: pointer;
|
|
2260
|
+
font-size: 13px; color: var(--ink); border-radius: 7px; text-align: left;
|
|
2261
|
+
white-space: nowrap;
|
|
2262
|
+
transition: background .15s ease, color .15s ease;
|
|
2263
|
+
}
|
|
2264
|
+
.chat-fb-menu-item.is-copied { color: var(--ok); }
|
|
2265
|
+
/* hover 仅对可悬停设备生效(移动端点击不会粘滞) */
|
|
2266
|
+
@media (hover: hover) and (pointer: fine) {
|
|
2267
|
+
.chat-fb-menu-item:hover { background: var(--line); }
|
|
2268
|
+
}
|
|
2269
|
+
|
|
2270
|
+
/* ============ 产物(Artifact)卡片 ============ */
|
|
2271
|
+
.artifact-grid {
|
|
2272
|
+
display: flex; flex-wrap: wrap; gap: 10px;
|
|
2273
|
+
margin: 10px 0 2px;
|
|
2274
|
+
}
|
|
2275
|
+
.artifact-card {
|
|
2276
|
+
display: inline-flex; align-items: center; gap: 12px;
|
|
2277
|
+
width: min(340px, 100%);
|
|
2278
|
+
padding: 11px 14px;
|
|
2279
|
+
border: 1px solid var(--line); border-radius: 12px;
|
|
2280
|
+
background: var(--panel); color: var(--ink);
|
|
2281
|
+
cursor: pointer; text-align: left;
|
|
2282
|
+
transition: border-color .15s, box-shadow .15s, transform .1s;
|
|
2283
|
+
}
|
|
2284
|
+
.artifact-card:active { transform: scale(.98); }
|
|
2285
|
+
.artifact-card-icon { flex: 0 0 auto; display: inline-flex; }
|
|
2286
|
+
.artifact-card-icon svg { width: 26px; height: 26px; fill: none; stroke: var(--ink-soft); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
|
|
2287
|
+
/* PDF 图标:SVG Repo 标准图标(白底文档页 + 粗体 PDF),填充灰(与其它文件 icon 颜色统一)、无描边 */
|
|
2288
|
+
.artifact-card-icon svg.artifact-icon-pdf { fill: var(--ink-soft); stroke: none; }
|
|
2289
|
+
.artifact-card-main {
|
|
2290
|
+
flex: 1 1 auto; min-width: 0;
|
|
2291
|
+
display: flex; flex-direction: column; gap: 3px;
|
|
2292
|
+
}
|
|
2293
|
+
.artifact-card-name {
|
|
2294
|
+
font-size: 14px; font-weight: 600; color: var(--ink);
|
|
2295
|
+
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
2296
|
+
}
|
|
2297
|
+
.artifact-card-meta {
|
|
2298
|
+
display: inline-flex; align-items: center; gap: 8px;
|
|
2299
|
+
min-height: 18px;
|
|
2300
|
+
}
|
|
2301
|
+
.artifact-card-size {
|
|
2302
|
+
flex: 0 0 auto; font-size: 11.5px; color: var(--ink-soft);
|
|
2303
|
+
font-variant-numeric: tabular-nums;
|
|
2304
|
+
}
|
|
2305
|
+
/* 右侧「打开预览」箭头:无背景,中性色,hover 不强调 */
|
|
2306
|
+
.artifact-card-open {
|
|
2307
|
+
flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
|
|
2308
|
+
width: 22px; height: 22px; background: transparent; color: var(--ink-soft);
|
|
2309
|
+
}
|
|
2310
|
+
.artifact-card-open svg {
|
|
2311
|
+
width: 14px; height: 14px;
|
|
2312
|
+
fill: none; stroke: currentColor; stroke-width: 2.2;
|
|
2313
|
+
stroke-linecap: round; stroke-linejoin: round;
|
|
2314
|
+
}
|
|
2315
|
+
|
|
2316
|
+
/* ============ 产物预览抽屉(右侧) ============ */
|
|
2317
|
+
.artifact-drawer-backdrop {
|
|
2318
|
+
position: fixed; inset: 0; z-index: 40;
|
|
2319
|
+
background: var(--modal-mask);
|
|
2320
|
+
}
|
|
2321
|
+
.artifact-drawer {
|
|
2322
|
+
position: fixed; top: 0; right: 0; bottom: 0; z-index: 50;
|
|
2323
|
+
width: min(64vw, 880px); max-width: 100vw;
|
|
2324
|
+
display: flex; flex-direction: column;
|
|
2325
|
+
background: var(--panel);
|
|
2326
|
+
box-shadow: var(--drawer-shadow);
|
|
2327
|
+
border-left: 1px solid var(--line);
|
|
2328
|
+
animation: artifact-drawer-in .18s ease-out;
|
|
2329
|
+
}
|
|
2330
|
+
@keyframes artifact-drawer-in { from { transform: translateX(24px); opacity: .6; } to { transform: none; opacity: 1; } }
|
|
2331
|
+
|
|
2332
|
+
/* ============ 非免费模型(积分)提示 ============ */
|
|
2333
|
+
/* 位于回复底部「点赞/点踩」上方:本次对话走了 fallback 积分模型时的提示。
|
|
2334
|
+
仅显示感叹号图标(黑白灰系),hover 出 tooltip 说明文字(data-tip,与 ctx-meter 同款)。 */
|
|
2335
|
+
.chat-model-hint {
|
|
2336
|
+
position: relative;
|
|
2337
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
2338
|
+
width: 20px; height: 20px; margin: 0;
|
|
2339
|
+
border-radius: 50%;
|
|
2340
|
+
color: var(--ink-soft);
|
|
2341
|
+
cursor: help;
|
|
2342
|
+
transition: background .15s ease, color .15s ease;
|
|
2343
|
+
}
|
|
2344
|
+
.chat-model-hint:hover { background: var(--hover); color: var(--ink); }
|
|
2345
|
+
.chat-model-hint-icon {
|
|
2346
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
2347
|
+
width: 13px; height: 13px;
|
|
2348
|
+
}
|
|
2349
|
+
.chat-model-hint-icon svg {
|
|
2350
|
+
width: 13px; height: 13px;
|
|
2351
|
+
fill: none; stroke: currentColor; stroke-width: 1.8;
|
|
2352
|
+
stroke-linecap: round; stroke-linejoin: round;
|
|
2353
|
+
}
|
|
2354
|
+
.chat-model-hint::after {
|
|
2355
|
+
content: attr(data-tip);
|
|
2356
|
+
position: absolute;
|
|
2357
|
+
bottom: calc(100% + 8px);
|
|
2358
|
+
left: 50%;
|
|
2359
|
+
transform: translateX(-50%);
|
|
2360
|
+
white-space: nowrap;
|
|
2361
|
+
padding: 5px 9px;
|
|
2362
|
+
border-radius: 7px;
|
|
2363
|
+
background: var(--bg-float, #fdfdfd);
|
|
2364
|
+
color: var(--ink, #1a1a1a);
|
|
2365
|
+
border: 1px solid var(--line, #e3e8f0);
|
|
2366
|
+
font-size: 12px; line-height: 1.5;
|
|
2367
|
+
box-shadow: 0 4px 14px rgb(0 0 0 / .15);
|
|
2368
|
+
opacity: 0;
|
|
2369
|
+
pointer-events: none;
|
|
2370
|
+
transition: opacity .12s ease;
|
|
2371
|
+
z-index: 40;
|
|
2372
|
+
}
|
|
2373
|
+
:root[data-theme="dark"] .chat-model-hint::after {
|
|
2374
|
+
background: var(--bg-float, #212121);
|
|
2375
|
+
color: #f0f0f0;
|
|
2376
|
+
border-color: #3a3a3a;
|
|
2377
|
+
}
|
|
2378
|
+
.chat-model-hint:hover::after { opacity: 1; }
|
|
2379
|
+
.artifact-drawer-head {
|
|
2380
|
+
flex: 0 0 auto;
|
|
2381
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
2382
|
+
gap: 12px; padding: 14px 18px;
|
|
2383
|
+
border-bottom: 1px solid var(--line);
|
|
2384
|
+
background: var(--panel);
|
|
2385
|
+
}
|
|
2386
|
+
/* 预览窗口顶部菜单栏:标题 + 右侧操作区(下载图标 / 关闭)同行 */
|
|
2387
|
+
.artifact-menu-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
|
|
2388
|
+
.artifact-menu-bar .artifact-drawer-title { flex: 1 1 auto; min-width: 0; }
|
|
2389
|
+
/* 预览菜单操作按钮容器:右侧两个按钮并排 */
|
|
2390
|
+
.artifact-menu-actions { flex: 0 0 auto; display: flex; align-items: center; gap: 4px; }
|
|
2391
|
+
/* 预览菜单操作按钮(下载 / 全屏 / 关闭):与输入区 +号、语音按钮一致——
|
|
2392
|
+
无边框圆形,hover 仅黑白灰背景,自身颜色不变(不出现蓝色) */
|
|
2393
|
+
.artifact-menu-dl, .artifact-drawer-close, .artifact-drawer-full {
|
|
2394
|
+
flex: 0 0 auto; width: 32px; height: 32px;
|
|
2395
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
2396
|
+
border: none; border-radius: 50%; background: transparent;
|
|
2397
|
+
color: var(--ink-soft); text-decoration: none; cursor: pointer;
|
|
2398
|
+
transition: background .15s ease;
|
|
2399
|
+
}
|
|
2400
|
+
.artifact-menu-dl svg, .artifact-drawer-close svg, .artifact-drawer-full svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
|
|
2401
|
+
.artifact-drawer-title { font-size: 14px; font-weight: 700; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
2402
|
+
.artifact-drawer-body { flex: 1 1 auto; min-height: 0; overflow: auto; background: var(--bg); }
|
|
2403
|
+
.artifact-frame { width: 100%; height: 100%; border: 0; background: var(--panel); display: block; }
|
|
2404
|
+
.artifact-img { display: block; max-width: 100%; margin: 0 auto; }
|
|
2405
|
+
.artifact-md { padding: 18px 22px; }
|
|
2406
|
+
.artifact-pre {
|
|
2407
|
+
margin: 0;
|
|
2408
|
+
font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, Consolas, "Courier New", monospace);
|
|
2409
|
+
font-size: 13px;
|
|
2410
|
+
line-height: 1.6;
|
|
2411
|
+
white-space: pre;
|
|
2412
|
+
overflow: auto;
|
|
2413
|
+
color: var(--ink-soft);
|
|
2414
|
+
}
|
|
2415
|
+
/* Word(.docx) 内嵌预览(mammoth 转换的 HTML):文档流样式,随主题变量 */
|
|
2416
|
+
.artifact-word {
|
|
2417
|
+
padding: 14px 18px;
|
|
2418
|
+
font-size: 14px;
|
|
2419
|
+
line-height: 1.7;
|
|
2420
|
+
color: var(--ink);
|
|
2421
|
+
overflow: auto;
|
|
2422
|
+
}
|
|
2423
|
+
.artifact-word h1, .artifact-word h2, .artifact-word h3, .artifact-word h4 {
|
|
2424
|
+
margin: .7em 0 .35em;
|
|
2425
|
+
line-height: 1.35;
|
|
2426
|
+
color: var(--ink);
|
|
2427
|
+
}
|
|
2428
|
+
.artifact-word h1 { font-size: 20px; }
|
|
2429
|
+
.artifact-word h2 { font-size: 17px; }
|
|
2430
|
+
.artifact-word h3 { font-size: 15px; }
|
|
2431
|
+
.artifact-word h4 { font-size: 14px; }
|
|
2432
|
+
.artifact-word p { margin: .45em 0; }
|
|
2433
|
+
.artifact-word ul, .artifact-word ol { margin: .4em 0; padding-left: 22px; }
|
|
2434
|
+
.artifact-word table { border-collapse: collapse; margin: .6em 0; }
|
|
2435
|
+
.artifact-word td, .artifact-word th { border: 1px solid var(--line); padding: 4px 9px; }
|
|
2436
|
+
.artifact-word img { max-width: 100%; }
|
|
2437
|
+
/* Prism 语法高亮 token 色(浅色默认 + 深色覆盖):柔和、不抢视线 */
|
|
2438
|
+
.artifact-pre {
|
|
2439
|
+
--syn-comment: #8a919c;
|
|
2440
|
+
--syn-keyword: #8250df;
|
|
2441
|
+
--syn-string: #1a7f37;
|
|
2442
|
+
--syn-number: #0550ae;
|
|
2443
|
+
--syn-function: #6639ba;
|
|
2444
|
+
--syn-class: #953800;
|
|
2445
|
+
--syn-operator: #57606a;
|
|
2446
|
+
--syn-property: #0a3069;
|
|
2447
|
+
--syn-tag: #116329;
|
|
2448
|
+
--syn-regex: #cf222e;
|
|
2449
|
+
}
|
|
2450
|
+
:root[data-theme="dark"] .artifact-pre {
|
|
2451
|
+
--syn-comment: #8b949e;
|
|
2452
|
+
--syn-keyword: #ff7b72;
|
|
2453
|
+
--syn-string: #a5d6ff;
|
|
2454
|
+
--syn-number: #79c0ff;
|
|
2455
|
+
--syn-function: #d2a8ff;
|
|
2456
|
+
--syn-class: #ffa657;
|
|
2457
|
+
--syn-operator: #c9d1d9;
|
|
2458
|
+
--syn-property: #79c0ff;
|
|
2459
|
+
--syn-tag: #7ee787;
|
|
2460
|
+
--syn-regex: #ffa198;
|
|
2461
|
+
}
|
|
2462
|
+
.artifact-pre .token.comment, .artifact-pre .token.prolog, .artifact-pre .token.doctype, .artifact-pre .token.cdata { color: var(--syn-comment); font-style: italic; }
|
|
2463
|
+
.artifact-pre .token.keyword, .artifact-pre .token.atrule, .artifact-pre .token.rule, .artifact-pre .token.important { color: var(--syn-keyword); }
|
|
2464
|
+
.artifact-pre .token.string, .artifact-pre .token.char, .artifact-pre .token.attr-value { color: var(--syn-string); }
|
|
2465
|
+
.artifact-pre .token.number, .artifact-pre .token.boolean, .artifact-pre .token.constant { color: var(--syn-number); }
|
|
2466
|
+
.artifact-pre .token.function, .artifact-pre .token.method { color: var(--syn-function); }
|
|
2467
|
+
.artifact-pre .token.class-name, .artifact-pre .token.builtin, .artifact-pre .token.type { color: var(--syn-class); }
|
|
2468
|
+
.artifact-pre .token.operator, .artifact-pre .token.punctuation { color: var(--syn-operator); }
|
|
2469
|
+
.artifact-pre .token.property, .artifact-pre .token.attr-name, .artifact-pre .token.parameter { color: var(--syn-property); }
|
|
2470
|
+
.artifact-pre .token.variable, .artifact-pre .token.selector, .artifact-pre .token.tag { color: var(--syn-tag); }
|
|
2471
|
+
.artifact-pre .token.regex, .artifact-pre .token.deleted { color: var(--syn-regex); }
|
|
2472
|
+
.artifact-pre .token.inserted { color: var(--syn-string); }
|
|
2473
|
+
.artifact-other-hint { padding: 18px 22px; font-size: 13px; color: var(--ink-soft); line-height: 1.6; }
|
|
2474
|
+
.artifact-loading {
|
|
2475
|
+
display: flex; align-items: center; justify-content: center;
|
|
2476
|
+
height: 100%; min-height: 120px;
|
|
2477
|
+
}
|
|
2478
|
+
.artifact-loading::after {
|
|
2479
|
+
content: "";
|
|
2480
|
+
width: 24px; height: 24px; border-radius: 50%;
|
|
2481
|
+
border: 2.5px solid var(--spin-edge); border-top-color: var(--spin-top);
|
|
2482
|
+
animation: chatSpin .7s linear infinite;
|
|
2483
|
+
}
|
|
2484
|
+
.artifact-err {
|
|
2485
|
+
margin: 18px 22px; padding: 14px 16px; border-radius: 10px; font-size: 13px; line-height: 1.6;
|
|
2486
|
+
color: var(--danger); background: var(--panel); border: 1px solid var(--line);
|
|
2487
|
+
}
|
|
2488
|
+
/* 右栏内嵌预览:菜单栏 + 内容区(替换产物列表显示,不再悬浮) */
|
|
2489
|
+
.chat-right-preview { display: flex; flex-direction: column; height: 100%; }
|
|
2490
|
+
.chat-right-preview-head { flex: 0 0 auto; padding: 6px 8px; border-bottom: 1px solid var(--line); background: var(--panel); }
|
|
2491
|
+
.chat-right-preview-head .artifact-drawer-title { font-size: 13px; }
|
|
2492
|
+
.chat-right-preview-frame { flex: 1 1 auto; min-height: 0; background: var(--panel); overflow: auto; }
|
|
2493
|
+
.chat-right-preview-frame .artifact-img { max-height: 100%; object-fit: contain; }
|
|
2494
|
+
.chat-right-preview-frame .artifact-frame { height: 100%; }
|
|
2495
|
+
.chat-right-preview-frame .artifact-md { height: 100%; overflow: auto; box-sizing: border-box; }
|
|
2496
|
+
.chat-right-preview-frame .artifact-other-hint { height: 100%; box-sizing: border-box; display: flex; align-items: center; justify-content: center; text-align: center; }
|
|
2497
|
+
/* 右侧浏览器实时预览:截图可点击(坐标转发 AI 操作的同一浏览器),底部提示条 */
|
|
2498
|
+
.artifact-browser-live {
|
|
2499
|
+
display: flex; flex-direction: column; height: 100%; box-sizing: border-box;
|
|
2500
|
+
}
|
|
2501
|
+
.artifact-img--clickable { cursor: crosshair; flex: 1 1 auto; min-height: 0; max-height: none; object-fit: contain; }
|
|
2502
|
+
.artifact-browser-tip {
|
|
2503
|
+
flex: 0 0 auto; padding: 4px 10px; text-align: center;
|
|
2504
|
+
font-size: 11.5px; color: var(--ink-soft); background: var(--field-soft);
|
|
2505
|
+
border-top: 1px solid var(--line);
|
|
2506
|
+
}
|
|
2507
|
+
|
|
2508
|
+
/* ============ 「查看所有产物」按钮 + 右侧产物列表面板(WorkBuddy 风格) ============ */
|
|
2509
|
+
.artifact-viewall-row { margin: 8px 0 2px; display: flex; gap: 8px; flex-wrap: wrap; }
|
|
2510
|
+
.artifact-viewall {
|
|
2511
|
+
display: inline-flex; align-items: center; gap: 6px;
|
|
2512
|
+
padding: 6px 12px;
|
|
2513
|
+
border: 1px solid var(--line); border-radius: 999px;
|
|
2514
|
+
background: var(--field-bg); color: var(--ink-soft);
|
|
2515
|
+
font-size: 12.5px; font-weight: 600; line-height: 1.5;
|
|
2516
|
+
cursor: pointer; text-align: left;
|
|
2517
|
+
transition: border-color .15s, background .15s, box-shadow .15s;
|
|
2518
|
+
}
|
|
2519
|
+
|
|
2520
|
+
/* ============ 变更 diff 视图(对标 WorkBuddy「查看所有变更」) ============
|
|
2521
|
+
右栏:顶部文件 tabs(+新增 / ~修改 / −删除),下方左右并排 diff(左=旧内容红底、右=新内容绿底) */
|
|
2522
|
+
.diff-panel {
|
|
2523
|
+
--diff-add-ink: #167346; --diff-del-ink: #b52b37; --diff-mod-ink: #2563c5;
|
|
2524
|
+
--diff-add-bg: rgba(40, 167, 92, .13); --diff-del-bg: rgba(220, 53, 69, .12);
|
|
2525
|
+
--diff-add-strong: rgba(40, 167, 92, .27); --diff-del-strong: rgba(220, 53, 69, .25);
|
|
2526
|
+
display: flex; flex-direction: column; height: 100%; min-height: 0;
|
|
2527
|
+
}
|
|
2528
|
+
:root[data-theme="dark"] .diff-panel {
|
|
2529
|
+
--diff-add-ink: #72dba0; --diff-del-ink: #ff959d; --diff-mod-ink: #89b8ff;
|
|
2530
|
+
--diff-add-bg: rgba(46, 160, 87, .19); --diff-del-bg: rgba(248, 81, 73, .17);
|
|
2531
|
+
--diff-add-strong: rgba(46, 160, 87, .37); --diff-del-strong: rgba(248, 81, 73, .34);
|
|
2532
|
+
}
|
|
2533
|
+
.diff-tabs {
|
|
2534
|
+
display: flex; align-items: center; gap: 4px;
|
|
2535
|
+
padding: 8px 10px 6px;
|
|
2536
|
+
border-bottom: 1px solid var(--line);
|
|
2537
|
+
flex-wrap: nowrap; overflow-x: auto; scrollbar-width: thin;
|
|
2538
|
+
}
|
|
2539
|
+
.diff-tab {
|
|
2540
|
+
display: inline-flex; align-items: center; gap: 5px;
|
|
2541
|
+
flex: 0 0 auto; max-width: 200px;
|
|
2542
|
+
padding: 4px 9px; border-radius: 8px;
|
|
2543
|
+
border: 1px solid transparent;
|
|
2544
|
+
background: transparent; color: var(--ink-soft);
|
|
2545
|
+
font-size: 12px; line-height: 1.4; cursor: pointer;
|
|
2546
|
+
transition: background .15s, border-color .15s;
|
|
2547
|
+
}
|
|
2548
|
+
.diff-tab:hover { background: var(--hover); }
|
|
2549
|
+
.diff-tab.is-active {
|
|
2550
|
+
background: var(--hover-strong); border-color: var(--line);
|
|
2551
|
+
color: var(--ink); font-weight: 600;
|
|
2552
|
+
}
|
|
2553
|
+
.diff-tab-mark { font-weight: 700; font-size: 12px; line-height: 1; }
|
|
2554
|
+
.diff-tab-mark--added { color: var(--diff-add-ink); }
|
|
2555
|
+
.diff-tab-mark--modified { color: var(--diff-mod-ink); }
|
|
2556
|
+
.diff-tab-mark--deleted { color: var(--diff-del-ink); }
|
|
2557
|
+
.diff-tab-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
2558
|
+
.diff-tabs-spacer { flex: 1; min-width: 6px; }
|
|
2559
|
+
.diff-close {
|
|
2560
|
+
flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
|
|
2561
|
+
width: 26px; height: 26px; padding: 0; border-radius: 8px;
|
|
2562
|
+
border: none; background: transparent; color: var(--ink-soft); cursor: pointer;
|
|
2563
|
+
transition: background .15s, color .15s;
|
|
2564
|
+
}
|
|
2565
|
+
.diff-close:hover { background: var(--hover); color: var(--ink); }
|
|
2566
|
+
.diff-close svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
|
|
2567
|
+
.diff-file-head {
|
|
2568
|
+
display: flex; align-items: center; gap: 8px;
|
|
2569
|
+
padding: 6px 12px;
|
|
2570
|
+
border-bottom: 1px solid var(--line);
|
|
2571
|
+
background: var(--field-bg);
|
|
2572
|
+
}
|
|
2573
|
+
.diff-file-name { font-size: 12.5px; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
2574
|
+
.diff-file-size { font-size: 11.5px; color: var(--ink-soft); }
|
|
2575
|
+
.diff-change-tag {
|
|
2576
|
+
flex: 0 0 auto; padding: 1px 7px; border-radius: 999px;
|
|
2577
|
+
font-size: 11px; font-weight: 600; line-height: 1.5;
|
|
2578
|
+
background: var(--hover-strong); color: var(--ink-soft);
|
|
2579
|
+
}
|
|
2580
|
+
.diff-change-tag--added { color: var(--diff-add-ink); }
|
|
2581
|
+
.diff-change-tag--modified { color: var(--diff-mod-ink); }
|
|
2582
|
+
.diff-change-tag--deleted { color: var(--diff-del-ink); }
|
|
2583
|
+
.diff-stat { margin-left: auto; font-size: 11.5px; color: var(--ink-soft); white-space: nowrap; }
|
|
2584
|
+
.diff-view-controls { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; padding: 6px 12px; border-bottom: 1px solid var(--line); }
|
|
2585
|
+
.diff-view-controls button { border: 1px solid var(--line); background: transparent; color: var(--ink-soft); border-radius: 5px; padding: 4px 8px; cursor: pointer; font-size: 12px; }
|
|
2586
|
+
.diff-view-controls button[aria-pressed="true"] { background: var(--brand-soft); color: var(--brand); border-color: var(--brand); }
|
|
2587
|
+
.diff-view-controls > span { font-size: 11px; color: var(--ink-soft); }
|
|
2588
|
+
.diff-gap td { padding: 0; text-align: center; background: var(--hover); }
|
|
2589
|
+
.diff-gap button { display: block; width: 100%; padding: 9px 12px; border: 0; background: transparent; color: var(--ink-soft); cursor: pointer; font-size: 12px; }
|
|
2590
|
+
.diff-gap button:hover { color: var(--brand); background: var(--brand-soft); }
|
|
2591
|
+
.diff-stat-add { color: var(--diff-add-ink); }
|
|
2592
|
+
.diff-stat-del { color: var(--diff-del-ink); }
|
|
2593
|
+
.diff-stat-modified { color: var(--diff-mod-ink); }
|
|
2594
|
+
.diff-legend { display: flex; flex-wrap: wrap; gap: 12px; padding: 6px 12px; font-size: 11px; border-bottom: 1px solid var(--line); }
|
|
2595
|
+
.diff-notice { padding: 8px 12px; color: var(--ink-soft); font-size: 12px; background: var(--field-bg); }
|
|
2596
|
+
.diff-body { flex: 1; min-height: 0; overflow: auto; font-size: 12.5px; line-height: 1.5; }
|
|
2597
|
+
.diff-table { width: 100%; border-collapse: collapse; table-layout: fixed; }
|
|
2598
|
+
.diff-lineno-col { width: 58px; }
|
|
2599
|
+
.diff-table th { position: sticky; top: 0; z-index: 1; padding: 7px 12px; text-align: left; font-weight: 600; font-size: 11px; color: var(--ink-soft); background: var(--field-bg); border-bottom: 1px solid var(--line); }
|
|
2600
|
+
.diff-table th + th, .diff-cell--left { border-right: 1px solid var(--line); }
|
|
2601
|
+
.diff-row td {
|
|
2602
|
+
padding: 0 8px; vertical-align: top;
|
|
2603
|
+
font-family: var(--mono, ui-monospace, "Cascadia Code", Consolas, monospace);
|
|
2604
|
+
font-size: 12px; white-space: pre-wrap; word-break: break-all;
|
|
2605
|
+
border-bottom: 1px solid color-mix(in srgb, var(--line) 50%, transparent);
|
|
2606
|
+
}
|
|
2607
|
+
.diff-lineno {
|
|
2608
|
+
width: 58px; min-width: 58px; text-align: right;
|
|
2609
|
+
color: var(--ink-soft);
|
|
2610
|
+
user-select: none; -webkit-user-select: none;
|
|
2611
|
+
background: color-mix(in srgb, var(--hover-strong) 40%, transparent);
|
|
2612
|
+
}
|
|
2613
|
+
.diff-cell { color: var(--ink); }
|
|
2614
|
+
.diff-cell--left.is-del, .diff-lineno.is-del { background: var(--diff-del-bg); }
|
|
2615
|
+
.diff-cell--right.is-add, .diff-lineno.is-add { background: var(--diff-add-bg); }
|
|
2616
|
+
.diff-lineno.is-del { color: var(--diff-del-ink); }
|
|
2617
|
+
.diff-lineno.is-add { color: var(--diff-add-ink); }
|
|
2618
|
+
.diff-line-mark { float: left; font-weight: 700; }
|
|
2619
|
+
.diff-row.is-modified .diff-line-mark { color: var(--diff-mod-ink); }
|
|
2620
|
+
.diff-row.is-modified .diff-lineno { box-shadow: inset 3px 0 0 var(--diff-mod-ink); }
|
|
2621
|
+
.diff-cell.is-empty { background: color-mix(in srgb, var(--hover-strong) 35%, transparent); }
|
|
2622
|
+
.diff-inline { color: inherit; border-radius: 2px; font-weight: 600; }
|
|
2623
|
+
.diff-inline--del { background: var(--diff-del-strong); }
|
|
2624
|
+
.diff-inline--add { background: var(--diff-add-strong); }
|
|
2625
|
+
.diff-no-newline { display: block; font: 10px/1.5 var(--mono, monospace); color: var(--ink-soft); user-select: none; }
|
|
2626
|
+
.diff-nocontent {
|
|
2627
|
+
display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
|
|
2628
|
+
padding: 24px 16px; color: var(--ink-soft); font-size: 12.5px;
|
|
2629
|
+
}
|
|
2630
|
+
.diff-nocontent-name { font-weight: 600; color: var(--ink); }
|
|
2631
|
+
|
|
2632
|
+
/* 右侧产物列表 */
|
|
2633
|
+
.artifact-list { padding: 10px 14px; display: flex; flex-direction: column; gap: 8px; }
|
|
2634
|
+
/* 每行是一个圆角边框容器;⋯ 菜单展开时菜单成为行内第三行,
|
|
2635
|
+
被行自身的圆角边框包住(不弹出到行外) */
|
|
2636
|
+
.artifact-list-item {
|
|
2637
|
+
display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
|
|
2638
|
+
width: 100%;
|
|
2639
|
+
position: relative;
|
|
2640
|
+
padding: 2px;
|
|
2641
|
+
border: 1px solid transparent; border-radius: 12px;
|
|
2642
|
+
background: transparent;
|
|
2643
|
+
transition: border-color .12s, background .12s;
|
|
2644
|
+
}
|
|
2645
|
+
.artifact-list-item.menu-open {
|
|
2646
|
+
border-color: var(--line);
|
|
2647
|
+
background: var(--panel);
|
|
2648
|
+
}
|
|
2649
|
+
.artifact-list-item-mainbtn {
|
|
2650
|
+
flex: 1 1 auto; min-width: 0;
|
|
2651
|
+
display: flex; align-items: center; gap: 12px;
|
|
2652
|
+
padding: 8px 10px;
|
|
2653
|
+
border: none; border-radius: 9px;
|
|
2654
|
+
background: transparent; color: var(--ink);
|
|
2655
|
+
cursor: pointer; text-align: left;
|
|
2656
|
+
transition: background .12s, transform .1s;
|
|
2657
|
+
}
|
|
2658
|
+
.artifact-list-item-mainbtn:active { transform: scale(.99); }
|
|
2659
|
+
/* 条目右侧「⋯」操作按钮(WorkBuddy 式菜单入口);点击在行内展开「打开所在文件夹 / 另存为」 */
|
|
2660
|
+
.artifact-list-actions { position: relative; flex: 0 0 auto; display: flex; align-items: center; }
|
|
2661
|
+
.artifact-list-more {
|
|
2662
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
2663
|
+
width: 30px; height: 30px; border: none; border-radius: 8px;
|
|
2664
|
+
background: transparent; color: var(--ink-soft); cursor: pointer; padding: 0;
|
|
2665
|
+
transition: background .12s, color .12s;
|
|
2666
|
+
}
|
|
2667
|
+
.artifact-list-more:hover, .artifact-list-more.is-open { background: var(--hover); color: var(--ink); }
|
|
2668
|
+
.artifact-list-more svg {
|
|
2669
|
+
width: 16px; height: 16px; fill: var(--ink-soft); stroke: none;
|
|
2670
|
+
}
|
|
2671
|
+
.artifact-list-more:hover svg, .artifact-list-more.is-open svg { fill: var(--ink); }
|
|
2672
|
+
/* 「⋯」菜单:行内展开(作为行容器的第三行,占满行宽,被行圆角边框包住) */
|
|
2673
|
+
.artifact-list-menu {
|
|
2674
|
+
flex: 1 1 100%; /* 换行到第二行,占满行宽 */
|
|
2675
|
+
display: flex; flex-direction: column; gap: 2px;
|
|
2676
|
+
padding: 4px 6px 6px;
|
|
2677
|
+
border: none; border-radius: 0; background: transparent; box-shadow: none;
|
|
2678
|
+
}
|
|
2679
|
+
.artifact-list-menu button {
|
|
2680
|
+
display: flex; align-items: center; gap: 9px; width: 100%;
|
|
2681
|
+
padding: 7px 9px; border: none; border-radius: 7px;
|
|
2682
|
+
background: transparent; color: var(--ink); font-size: 13px; cursor: pointer; text-align: left;
|
|
2683
|
+
}
|
|
2684
|
+
.artifact-list-menu button:hover { background: var(--hover); }
|
|
2685
|
+
.artifact-list-menu button svg {
|
|
2686
|
+
width: 15px; height: 15px; flex: 0 0 auto;
|
|
2687
|
+
fill: none; stroke: var(--ink-soft); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
|
|
2688
|
+
}
|
|
2689
|
+
.artifact-list-menu button:hover svg { stroke: var(--ink); }
|
|
2690
|
+
.artifact-list-item-main {
|
|
2691
|
+
flex: 1 1 auto; min-width: 0;
|
|
2692
|
+
display: flex; flex-direction: column; gap: 3px;
|
|
2693
|
+
}
|
|
2694
|
+
.artifact-list-item-name {
|
|
2695
|
+
font-size: 13.5px; font-weight: 600; color: var(--ink);
|
|
2696
|
+
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
2697
|
+
}
|
|
2698
|
+
.artifact-list-item-meta { font-size: 11.5px; color: var(--ink-soft); }
|
|
2699
|
+
|
|
2700
|
+
/* ============ 优雅提示与错误框 ============ */
|
|
2701
|
+
.chat-hint { margin: 6px auto 2px; max-width: 92%; padding: 8px 14px; border-radius: 10px; font-size: 12.5px; line-height: 1.5; }
|
|
2702
|
+
.chat-hint--slow {
|
|
2703
|
+
background: var(--brand-soft, rgba(31, 39, 51, .05));
|
|
2704
|
+
color: var(--ink-soft); border: 1px solid var(--line);
|
|
2705
|
+
}
|
|
2706
|
+
.chat-error {
|
|
2707
|
+
display: flex; align-items: center; gap: 10px; margin: 8px auto 2px; max-width: 92%;
|
|
2708
|
+
padding: 10px 14px; border-radius: 10px; font-size: 13px; line-height: 1.5;
|
|
2709
|
+
background: rgba(229, 72, 77, .08); border: 1px solid rgba(229, 72, 77, .35); color: var(--danger);
|
|
2710
|
+
}
|
|
2711
|
+
.chat-error-icon {
|
|
2712
|
+
flex: 0 0 auto; width: 18px; height: 18px; border-radius: 50%;
|
|
2713
|
+
background: var(--danger); color: #fff; font-weight: 700; font-size: 13px; line-height: 18px; text-align: center;
|
|
2714
|
+
}
|
|
2715
|
+
.chat-error-text { flex: 1 1 auto; word-break: break-word; }
|
|
2716
|
+
|
|
2717
|
+
/* 发送区:停止按钮(生成中显示)。灰色系。外部保持圆形(继承 .chat-send),
|
|
2718
|
+
仅阴影收敛(区别于发送按钮的大阴影);中间的方形图标比发送图标略大 */
|
|
2719
|
+
.chat-send--stop {
|
|
2720
|
+
/* 参考截图:白色圆形 + 内部黑色实心方块(深色背景上高亮;浅色主题靠细边框区分) */
|
|
2721
|
+
background: #fff;
|
|
2722
|
+
border: 1px solid rgba(0, 0, 0, .08);
|
|
2723
|
+
color: #111;
|
|
2724
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, .28);
|
|
2725
|
+
}
|
|
2726
|
+
.chat-send--stop svg {
|
|
2727
|
+
width: 20px; height: 20px;
|
|
2728
|
+
fill: currentColor; stroke: none; /* 实心方块(覆盖 .chat-send svg 的描边模式) */
|
|
2729
|
+
animation: chatStopBreathe 2.2s ease-in-out infinite;
|
|
2730
|
+
}
|
|
2731
|
+
@keyframes chatStopBreathe {
|
|
2732
|
+
0%, 100% { transform: scale(1); }
|
|
2733
|
+
50% { transform: scale(.88); }
|
|
2734
|
+
}
|
|
2735
|
+
|
|
2736
|
+
/* 助手消息最上方的共用时提示:从用户发送消息开始计时,到全部答复完成/用户停止 */
|
|
2737
|
+
.msg-elapsed {
|
|
2738
|
+
margin: 0 0 8px;
|
|
2739
|
+
font-size: 12px;
|
|
2740
|
+
line-height: 1.4;
|
|
2741
|
+
color: var(--ink-soft, #5b6573);
|
|
2742
|
+
opacity: .8;
|
|
2743
|
+
user-select: none;
|
|
2744
|
+
}
|
|
2745
|
+
|
|
2746
|
+
/* 豆包 Work 式「已完成」折叠卡:代替 msg-elapsed 纯文本。流式中不显示(过程由下方思考/工具步直播);
|
|
2747
|
+
完成后显示「已完成 X · ▸」,点击卡片展开/收起该消息的全部思考与工具调用。
|
|
2748
|
+
纯文本行样式:无背景无边框,与下方内容天然左对齐 */
|
|
2749
|
+
.msg-process-card {
|
|
2750
|
+
display: inline-flex; align-items: center; gap: 7px;
|
|
2751
|
+
margin: 0 0 8px; padding: 0;
|
|
2752
|
+
border: none; background: transparent;
|
|
2753
|
+
font-size: 14px; line-height: 1.4; color: var(--ink-soft);
|
|
2754
|
+
cursor: pointer; user-select: none;
|
|
2755
|
+
transition: color .15s ease;
|
|
2756
|
+
}
|
|
2757
|
+
.msg-process-card:hover { color: var(--ink); }
|
|
2758
|
+
.msg-process-label { font-variant-numeric: tabular-nums; }
|
|
2759
|
+
.msg-process-chevron {
|
|
2760
|
+
flex: 0 0 auto;
|
|
2761
|
+
transition: transform .15s ease;
|
|
2762
|
+
}
|
|
2763
|
+
/* 与 tools 胶囊同款 SVG 描边 chevron:收起向右、展开向下(rotate 90deg) */
|
|
2764
|
+
.msg-process-chevron svg {
|
|
2765
|
+
width: 12px; height: 12px;
|
|
2766
|
+
fill: none; stroke: currentColor; stroke-width: 2;
|
|
2767
|
+
stroke-linecap: round; stroke-linejoin: round;
|
|
2768
|
+
}
|
|
2769
|
+
.msg-process-card.is-open .msg-process-chevron { transform: rotate(90deg); }
|
|
2770
|
+
|
|
2771
|
+
/* 助手消息底部操作行 */
|
|
2772
|
+
.msg-footer {
|
|
2773
|
+
display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
|
|
2774
|
+
margin-top: 10px;
|
|
2775
|
+
}
|
|
2776
|
+
/* 非最后一条助手消息:footer 默认隐藏,hover 该消息时才显示(保留占位,避免布局抖动) */
|
|
2777
|
+
@media (hover: hover) and (pointer: fine) {
|
|
2778
|
+
.msg-footer:not(.msg-footer--last) {
|
|
2779
|
+
opacity: 0;
|
|
2780
|
+
pointer-events: none;
|
|
2781
|
+
transition: opacity .15s;
|
|
2782
|
+
}
|
|
2783
|
+
.msg:hover .msg-footer:not(.msg-footer--last) {
|
|
2784
|
+
opacity: 1;
|
|
2785
|
+
pointer-events: auto;
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2788
|
+
|
|
2789
|
+
/* 助手消息底部费用提示(与点赞点踩同一行) */
|
|
2790
|
+
.msg-cost {
|
|
2791
|
+
margin: 0;
|
|
2792
|
+
font-size: 11.5px;
|
|
2793
|
+
line-height: 1.4;
|
|
2794
|
+
color: var(--ink-soft, #5b6573);
|
|
2795
|
+
opacity: .75;
|
|
2796
|
+
user-select: none;
|
|
2797
|
+
}
|
|
2798
|
+
|
|
2799
|
+
/* 助手消息底部时间:最后一条始终显示,其他消息默认隐藏、hover 时显示 */
|
|
2800
|
+
.msg-footer-time {
|
|
2801
|
+
font-size: 11.5px;
|
|
2802
|
+
line-height: 1.4;
|
|
2803
|
+
color: var(--ink-soft);
|
|
2804
|
+
opacity: .75;
|
|
2805
|
+
user-select: none;
|
|
2806
|
+
}
|
|
2807
|
+
.msg-footer-time-hover {
|
|
2808
|
+
opacity: 0;
|
|
2809
|
+
transition: opacity 0.15s;
|
|
2810
|
+
}
|
|
2811
|
+
.msg-footer:hover .msg-footer-time-hover {
|
|
2812
|
+
opacity: .75;
|
|
2813
|
+
}
|
|
2814
|
+
|
|
2815
|
+
/* 删除确认对话框 + 全局 loading 遮罩 */
|
|
2816
|
+
.chat-modal-backdrop {
|
|
2817
|
+
position: fixed; inset: 0; background: var(--modal-mask);
|
|
2818
|
+
display: flex; align-items: center; justify-content: center; z-index: 1000;
|
|
2819
|
+
backdrop-filter: blur(2px);
|
|
2820
|
+
}
|
|
2821
|
+
/* Electron:关闭遮罩 blur(合成异常),保留半透明暗色 */
|
|
2822
|
+
.env-electron .chat-modal-backdrop { backdrop-filter: none; -webkit-backdrop-filter: none; }
|
|
2823
|
+
.chat-modal-backdrop--busy { pointer-events: none; }
|
|
2824
|
+
.chat-modal {
|
|
2825
|
+
background: var(--panel); border-radius: 14px; padding: 22px 24px; width: 320px;
|
|
2826
|
+
box-shadow: 0 12px 40px rgba(0,0,0,.18); text-align: center;
|
|
2827
|
+
}
|
|
2828
|
+
.chat-modal--loading { display: flex; flex-direction: column; align-items: center; gap: 12px; width: 200px; }
|
|
2829
|
+
.chat-modal-title { margin: 0 0 8px; font-size: 16px; font-weight: 700; }
|
|
2830
|
+
.chat-modal-desc { margin: 0 0 18px; font-size: 13px; color: var(--ink-soft); }
|
|
2831
|
+
.chat-modal-actions { display: flex; gap: 10px; justify-content: center; }
|
|
2832
|
+
.chat-modal-btn {
|
|
2833
|
+
padding: 8px 18px; border-radius: 8px; border: 1px solid var(--line); background: var(--field-bg);
|
|
2834
|
+
font-size: 13px; cursor: pointer; color: var(--ink);
|
|
2835
|
+
}
|
|
2836
|
+
.chat-modal-btn--danger { background: var(--danger); color: #fff; border-color: var(--danger); }
|
|
2837
|
+
.chat-spinner {
|
|
2838
|
+
width: 28px; height: 28px; border: 3px solid #e2e8f0; border-top-color: #2563eb;
|
|
2839
|
+
border-radius: 50%; animation: chatSpin .8s linear infinite;
|
|
2840
|
+
}
|
|
2841
|
+
@keyframes chatSpin { to { transform: rotate(360deg); } }
|
|
2842
|
+
|
|
2843
|
+
/* 输入图片全屏预览(应用大小浮层):点击右栏输入文件图片打开;深色底、顶栏文件名+下载/关闭,图片居中 contain */
|
|
2844
|
+
.chat-img-preview {
|
|
2845
|
+
position: fixed; inset: 0; z-index: 1100;
|
|
2846
|
+
background: rgba(12, 14, 18, .94);
|
|
2847
|
+
display: flex; flex-direction: column;
|
|
2848
|
+
}
|
|
2849
|
+
.chat-img-preview-head {
|
|
2850
|
+
flex: 0 0 auto; height: 52px; padding: 0 14px;
|
|
2851
|
+
display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
|
2852
|
+
background: var(--panel);
|
|
2853
|
+
border-bottom: 1px solid var(--line);
|
|
2854
|
+
}
|
|
2855
|
+
.chat-img-preview-name {
|
|
2856
|
+
font-size: 13px; font-weight: 600; color: var(--ink);
|
|
2857
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
|
|
2858
|
+
}
|
|
2859
|
+
.chat-img-preview-actions { display: flex; gap: 8px; flex: 0 0 auto; }
|
|
2860
|
+
.chat-img-preview-btn {
|
|
2861
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
2862
|
+
width: 32px; height: 32px; border-radius: 8px;
|
|
2863
|
+
border: 1px solid var(--line); background: var(--field-bg); color: var(--ink);
|
|
2864
|
+
cursor: pointer; text-decoration: none;
|
|
2865
|
+
}
|
|
2866
|
+
.chat-img-preview-btn:hover { background: var(--hover-strong); }
|
|
2867
|
+
.chat-img-preview-btn svg {
|
|
2868
|
+
width: 16px; height: 16px; fill: none; stroke: currentColor;
|
|
2869
|
+
stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
|
|
2870
|
+
}
|
|
2871
|
+
.chat-img-preview-body {
|
|
2872
|
+
flex: 1 1 auto; min-height: 0;
|
|
2873
|
+
display: flex; align-items: center; justify-content: center; padding: 16px;
|
|
2874
|
+
}
|
|
2875
|
+
.chat-img-preview-img {
|
|
2876
|
+
max-width: 100%; max-height: 100%; object-fit: contain;
|
|
2877
|
+
border-radius: 4px; box-shadow: 0 8px 32px rgba(0, 0, 0, .35);
|
|
2878
|
+
}
|
|
2879
|
+
|
|
2880
|
+
/* 用户长输入折叠:折叠尾部渐隐罩 + 居中的"展开全部"按钮,与消息同属一个气泡 */
|
|
2881
|
+
/* 渐隐罩:盖在被截断文字最后几行上,从透明渐变到气泡背景色,配合极轻 blur 形成小毛玻璃过渡 */
|
|
2882
|
+
.chat-expand-fade {
|
|
2883
|
+
height: 26px;
|
|
2884
|
+
margin: -26px -14px 0 -14px; /* 覆盖气泡左右 padding(11px 14px),让渐变横跨内容宽度 */
|
|
2885
|
+
background: linear-gradient(180deg, rgba(240, 240, 240, 0), rgba(240, 240, 240, .96));
|
|
2886
|
+
pointer-events: none;
|
|
2887
|
+
}
|
|
2888
|
+
@supports (backdrop-filter: blur(1px)) {
|
|
2889
|
+
.chat-expand-fade { backdrop-filter: blur(1.2px); }
|
|
2890
|
+
}
|
|
2891
|
+
/* Electron 内核的 backdrop-filter 合成会把下方内容一起糊掉(历史问题),仅保留渐变 */
|
|
2892
|
+
.env-electron .chat-expand-fade { backdrop-filter: none; }
|
|
2893
|
+
|
|
2894
|
+
.chat-expand-toggle {
|
|
2895
|
+
margin-top: 8px;
|
|
2896
|
+
font-size: 12.5px;
|
|
2897
|
+
line-height: 1.4;
|
|
2898
|
+
color: var(--ink-soft);
|
|
2899
|
+
text-align: center;
|
|
2900
|
+
cursor: pointer;
|
|
2901
|
+
user-select: none;
|
|
2902
|
+
transition: color .15s ease;
|
|
2903
|
+
}
|
|
2904
|
+
|
|
2905
|
+
/* hover 用户消息时显示操作栏(消息底部,图标) */
|
|
2906
|
+
.msg.user .msg-hover-actions {
|
|
2907
|
+
opacity: 0;
|
|
2908
|
+
transition: opacity .15s;
|
|
2909
|
+
margin-top: 4px;
|
|
2910
|
+
display: flex;
|
|
2911
|
+
gap: 6px;
|
|
2912
|
+
align-items: center;
|
|
2913
|
+
justify-content: flex-end;
|
|
2914
|
+
}
|
|
2915
|
+
.msg-hover-actions .msg-time {
|
|
2916
|
+
font-size: 12px;
|
|
2917
|
+
color: var(--ink-soft);
|
|
2918
|
+
margin-right: 4px;
|
|
2919
|
+
}
|
|
2920
|
+
.msg-hover-actions button {
|
|
2921
|
+
width: 26px; height: 26px;
|
|
2922
|
+
display: flex; align-items: center; justify-content: center;
|
|
2923
|
+
border: none; background: transparent;
|
|
2924
|
+
color: var(--ink-soft);
|
|
2925
|
+
cursor: pointer;
|
|
2926
|
+
border-radius: 6px;
|
|
2927
|
+
}
|
|
2928
|
+
/* 复制成功反馈:绿色对勾 + 浅绿底,1.8s 后由组件恢复为普通态 */
|
|
2929
|
+
.msg-hover-actions button.is-copied { background: var(--copied-bg); color: var(--copied-ink); }
|
|
2930
|
+
.msg-hover-actions svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
|
|
2931
|
+
|
|
2932
|
+
/* 原地编辑用户消息(workbuddy 浅色风格) */
|
|
2933
|
+
/* 编辑态:原地右对齐(与已发送用户消息一致)。宽度由组件在进入编辑时量取「原气泡宽度」后
|
|
2934
|
+
以行内样式写到 .msg.user 上——编辑框与编辑前的消息框同宽,而非撑满用户消息最大宽度。
|
|
2935
|
+
★ .msg.user 必须保留 align-self: flex-end(不能对整个消息行 stretch)——否则消息行占满整行、
|
|
2936
|
+
编辑框从最左起排,视觉上"闪到中间"。
|
|
2937
|
+
★★ min-width 是必需的兜底:短消息(如"Hi")的原气泡本身很窄,量出来的宽度装不下
|
|
2938
|
+
底部「提示语 + 取消/发送」按钮,flex-wrap 会把它们压成竖排一字一行(见 issue:编辑框被改坏)。
|
|
2939
|
+
因此宽度取 max(原气泡宽, EDIT_MIN_WIDTH)——长消息仍与原消息同宽,短消息至少能放下底部元素。*/
|
|
2940
|
+
.msg.user.is-editing { align-self: flex-end; width: max-content; min-width: min(100%, 420px); max-width: min(100%, 860px); }
|
|
2941
|
+
/* .msg.user 编辑态已带确定的量取宽度,气泡撑满它即可复用自身底色/圆角/内边距,
|
|
2942
|
+
使可见编辑框与已发送用户消息同宽同形,右缘原地不动、向左铺开(不换行、不跳位)。 */
|
|
2943
|
+
.msg.user.is-editing .bubble { width: 100%; max-width: 100%; }
|
|
2944
|
+
/* 编辑框仅作透明容器:底色/内边距由外层 .bubble 提供,避免双层背景与内边距叠加导致右缘内缩 */
|
|
2945
|
+
.msg-edit-box { width: 100%; box-sizing: border-box; }
|
|
2946
|
+
.msg-edit-textarea {
|
|
2947
|
+
width: 100%;
|
|
2948
|
+
background: transparent;
|
|
2949
|
+
border: none;
|
|
2950
|
+
outline: none;
|
|
2951
|
+
color: var(--ink);
|
|
2952
|
+
/* 与 .msg .bubble 完全一致:字号/行高随已发送用户消息,避免编辑时字体"变小" */
|
|
2953
|
+
font-size: 15.5px;
|
|
2954
|
+
line-height: 1.65;
|
|
2955
|
+
resize: none;
|
|
2956
|
+
max-height: 200px;
|
|
2957
|
+
overflow-y: auto;
|
|
2958
|
+
font-family: inherit;
|
|
2959
|
+
}
|
|
2960
|
+
.msg-edit-footer {
|
|
2961
|
+
margin-top: 10px;
|
|
2962
|
+
display: flex;
|
|
2963
|
+
align-items: center;
|
|
2964
|
+
justify-content: space-between;
|
|
2965
|
+
gap: 8px 12px;
|
|
2966
|
+
flex-wrap: wrap; /* 窄消息框内提示语与按钮换行,避免溢出编辑框 */
|
|
2967
|
+
}
|
|
2968
|
+
/* 提示语允许压缩并省略,优先保住「取消/发送」按钮不被压行 */
|
|
2969
|
+
.msg-edit-hint { font-size: 12px; color: var(--ink-soft); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
2970
|
+
/* 按钮组不参与收缩:任何宽度下都保持「取消」「发送」并排、不换行、不竖排 */
|
|
2971
|
+
.msg-edit-btns { display: flex; gap: 8px; flex: none; white-space: nowrap; }
|
|
2972
|
+
.msg-edit-btns .chat-modal-btn { background: transparent; color: var(--ink-soft); border: 1px solid var(--line); padding: 4px 12px; }
|
|
2973
|
+
.chat-modal-btn--primary { background: var(--send-bg) !important; border-color: var(--send-bg) !important; color: var(--send-ink) !important; }
|
|
2974
|
+
|
|
2975
|
+
/* ============ 移动端适配 ============
|
|
2976
|
+
断点策略:
|
|
2977
|
+
1. > 767.98px —— 桌面三栏(左右栏 flex 占位,挤压中栏),维持原布局;
|
|
2978
|
+
2. ≤ 767.98px —— 移动端:左右栏改为「悬浮抽屉」(fixed 覆盖在中栏之上,
|
|
2979
|
+
不再占 flex 空间、不挤压中栏),中栏占满整宽;
|
|
2980
|
+
3. 中栏最小宽度 --chat-min-w(360px):视口小于该值时中栏保持最小宽度不再压缩,
|
|
2981
|
+
超出部分被壳层裁切(放弃适配,不显示提示)。 */
|
|
2982
|
+
|
|
2983
|
+
/* 移动端抽屉遮罩:默认隐藏(桌面无此元素语义);JS 在左/右抽屉打开时渲染,
|
|
2984
|
+
点击关闭抽屉。仅在移动端媒体查询下可见 */
|
|
2985
|
+
.chat-mobile-backdrop { display: none; }
|
|
2986
|
+
|
|
2987
|
+
@media (max-width: 767.98px) {
|
|
2988
|
+
/* 移动端浏览器地址栏伸缩:用 dvh 兜底(不支持时回退 100vh) */
|
|
2989
|
+
.chat-shell, .chat-main { height: 100dvh; }
|
|
2990
|
+
/* 中栏最小宽度:视口 < --chat-min-w 时中栏保持最小宽度不再压缩,
|
|
2991
|
+
超出部分由 .chat-shell 的 overflow-x:hidden 裁切(放弃适配,无提示) */
|
|
2992
|
+
.chat-main { min-width: var(--chat-min-w); }
|
|
2993
|
+
|
|
2994
|
+
/* ---- 左/右栏 → 悬浮抽屉 ---- */
|
|
2995
|
+
.chat-pane-left, .chat-pane-right {
|
|
2996
|
+
position: fixed; top: 0; bottom: 0; z-index: 200;
|
|
2997
|
+
flex: none; overflow: hidden;
|
|
2998
|
+
transition: transform .2s ease;
|
|
2999
|
+
box-shadow: var(--mobile-drawer-shadow);
|
|
3000
|
+
}
|
|
3001
|
+
.chat-pane-left {
|
|
3002
|
+
left: 0; width: 280px;
|
|
3003
|
+
transform: translateX(-100%);
|
|
3004
|
+
}
|
|
3005
|
+
.chat-pane-left.is-open { transform: translateX(0); }
|
|
3006
|
+
.chat-pane-right {
|
|
3007
|
+
right: 0;
|
|
3008
|
+
/* 默认 340px,但不超过视口 88%:窄屏下避免抽屉占满整屏 */
|
|
3009
|
+
width: min(var(--right-w, 340px), 88vw);
|
|
3010
|
+
transform: translateX(100%);
|
|
3011
|
+
}
|
|
3012
|
+
.chat-pane-right.is-open { transform: translateX(0); }
|
|
3013
|
+
.chat-pane-right.is-dragging { transition: none; }
|
|
3014
|
+
|
|
3015
|
+
/* 移动端抽屉无拖拽改宽语义,隐藏 resizer */
|
|
3016
|
+
.chat-resizer { display: none; }
|
|
3017
|
+
|
|
3018
|
+
/* 抽屉遮罩:盖住中栏,点击(JS onClick)关闭抽屉 */
|
|
3019
|
+
.chat-mobile-backdrop {
|
|
3020
|
+
display: block;
|
|
3021
|
+
position: fixed; inset: 0; z-index: 150;
|
|
3022
|
+
background: rgba(20, 27, 38, .32);
|
|
3023
|
+
}
|
|
3024
|
+
|
|
3025
|
+
/* ---- 中栏细节 ---- */
|
|
3026
|
+
.chat-topbar { height: 48px; padding: 0 10px; gap: 8px; }
|
|
3027
|
+
.chat-sidebar-toggle { width: 32px; height: 32px; }
|
|
3028
|
+
.chat-topbar-btn { width: 32px; height: 32px; }
|
|
3029
|
+
.chat-topbar-right { gap: 2px; }
|
|
3030
|
+
.chat-title--center {
|
|
3031
|
+
max-width: 42vw; overflow: hidden; text-overflow: ellipsis;
|
|
3032
|
+
}
|
|
3033
|
+
.chat-title--left { max-width: 34vw; }
|
|
3034
|
+
.chat-search-bar { padding: 6px 10px; gap: 6px; }
|
|
3035
|
+
.chat-search-bar-count { min-width: 28px; }
|
|
3036
|
+
.chat-history-pop,
|
|
3037
|
+
.chat-share-pop { top: 62px; right: 8px; width: min(340px, calc(100vw - 16px)); }
|
|
3038
|
+
.chat-history-list { max-height: 48vh; }
|
|
3039
|
+
.chat-body-inner { max-width: 100%; margin: 0; padding: 14px 14px; gap: 12px; }
|
|
3040
|
+
/* 移动端取消桌面端「内容区按中栏 80% 居中」的约束(否则窄屏左右各留 10% 大留白)。
|
|
3041
|
+
空态 .is-empty .chat-main-inner 优先级更高,保持自身 32px 内边距不变。 */
|
|
3042
|
+
.chat-main-inner { max-width: 100%; margin: 0; }
|
|
3043
|
+
.msg { max-width: 100%; }
|
|
3044
|
+
.chat-scene-bar { padding: 8px 10px 2px; }
|
|
3045
|
+
.chat-composer-stack { margin: 0 10px 10px; border-radius: 16px; }
|
|
3046
|
+
.chat-composer { padding: 12px 12px 8px; }
|
|
3047
|
+
.chat-workspace { margin: 0 10px 10px; }
|
|
3048
|
+
/* ≥16px 防止 iOS Safari 聚焦输入框时自动放大页面 */
|
|
3049
|
+
.chat-composer textarea { font-size: 16px; }
|
|
3050
|
+
.chat-queue { border-radius: 16px 16px 0 0; }
|
|
3051
|
+
|
|
3052
|
+
/* ---- 右栏抽屉内部 ---- */
|
|
3053
|
+
.chat-right-section--inputs { max-height: 40%; }
|
|
3054
|
+
.chat-right-section--outputs { max-height: 60%; }
|
|
3055
|
+
.chat-right-section--outputs.is-full { max-height: 100%; }
|
|
3056
|
+
|
|
3057
|
+
/* 全局产物预览抽屉:窄屏下全屏铺开,便于阅读 */
|
|
3058
|
+
.artifact-drawer { width: 100vw; border-left: none; }
|
|
3059
|
+
}
|
|
3060
|
+
|
|
3061
|
+
/* ============ 深色主题定向覆盖(变量覆盖不到、需按 data-theme 单独写的几处) ============ */
|
|
3062
|
+
:root[data-theme="dark"] .login-page {
|
|
3063
|
+
background: radial-gradient(1200px 600px at 50% -10%, #2a2d34 0%, var(--bg) 55%);
|
|
3064
|
+
}
|
|
3065
|
+
/* 用户消息长输入折叠渐隐:深色下从气泡深灰渐变 */
|
|
3066
|
+
:root[data-theme="dark"] .chat-expand-fade {
|
|
3067
|
+
background: linear-gradient(180deg, rgba(58, 62, 70, 0), rgba(58, 62, 70, .96));
|
|
3068
|
+
}
|
|
3069
|
+
/* 移动端抽屉遮罩:深色下用更重的黑幕 */
|
|
3070
|
+
:root[data-theme="dark"] .chat-mobile-backdrop { background: rgba(0, 0, 0, .5); }
|
|
3071
|
+
/* 右栏拖拽分隔条:深色下黑条不可见,换白条 */
|
|
3072
|
+
:root[data-theme="dark"] .chat-resizer::after { background: rgba(255, 255, 255, .28); }
|
|
3073
|
+
/* 行内代码(暗色):对齐 WorkBuddy —— 灰色背景 + 近白文字,不用红色 */
|
|
3074
|
+
:root[data-theme="dark"] .bubble .md :not(pre) > code, :root[data-theme="dark"] .artifact-md .md :not(pre) > code{
|
|
3075
|
+
background: rgba(255, 255, 255, .08);
|
|
3076
|
+
border-color: rgba(255, 255, 255, .1);
|
|
3077
|
+
color: #e6e6e6;
|
|
3078
|
+
}
|
|
3079
|
+
/* 引用块文字:深色下浅色 #334155 看不清,提亮 */
|
|
3080
|
+
:root[data-theme="dark"] .bubble .md blockquote, :root[data-theme="dark"] .artifact-md .md blockquote{ color: #c3cfdf; }
|
|
3081
|
+
|
|
3082
|
+
|
|
3083
|
+
/* ============ 移动端 hover 粘滞修复 ============
|
|
3084
|
+
* 触摸设备(hover: none)点击后 :hover 状态会“粘住”,
|
|
3085
|
+
* 全部 :hover 视觉规则统一收敛到 (hover: hover) 设备才生效。
|
|
3086
|
+
* 注:移动端功能性 hover(如侧栏操作按钮、消息操作浮层)由 JS 以点击方式替代。 */
|
|
3087
|
+
@media (hover: hover) and (pointer: fine) {
|
|
3088
|
+
*::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-hover); }
|
|
3089
|
+
.chat-body.sb-active::-webkit-scrollbar-thumb:hover,
|
|
3090
|
+
.chat-right-section-body.sb-active::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-hover); }
|
|
3091
|
+
.login-provider-button:hover { background: var(--hover-strong); }
|
|
3092
|
+
.login-dingtalk-button:hover { background: var(--hover-strong); }
|
|
3093
|
+
.login-dev-button:hover { background: var(--hover-strong); }
|
|
3094
|
+
.chat-sidebar-toggle:hover { background: var(--hover); color: var(--ink); }
|
|
3095
|
+
.chat-bottom-btn:hover { background: var(--hover-strong); color: var(--ink); border-color: var(--line); }
|
|
3096
|
+
.chat-resizer:hover::after, .chat-resizer.is-dragging::after { opacity: 1; }
|
|
3097
|
+
.chat-right-file:hover { background: var(--hover); }
|
|
3098
|
+
.chat-right-file-dl:hover { background: var(--hover); color: var(--ink); }
|
|
3099
|
+
.chat-user-menu-item:hover { background: var(--hover); }
|
|
3100
|
+
.chat-user-menu-item--danger:hover { background: var(--danger-soft); color: var(--danger); }
|
|
3101
|
+
.chat-sidebar-new:hover { background: var(--hover-strong); }
|
|
3102
|
+
.chat-sidebar-item:hover { background: var(--hover-strong); }
|
|
3103
|
+
.chat-sidebar-item:hover .chat-sidebar-item-title.is-marquee .chat-sidebar-item-title-text,
|
|
3104
|
+
.chat-sidebar-item.is-active:hover .chat-sidebar-item-title.is-marquee .chat-sidebar-item-title-text {
|
|
3105
|
+
animation: chatTitleMarquee var(--marquee-dur, 4s) linear infinite;
|
|
3106
|
+
overflow: visible;
|
|
3107
|
+
}
|
|
3108
|
+
.chat-sidebar-item:hover .chat-sidebar-item-title.is-marquee .chat-sidebar-item-title-t2,
|
|
3109
|
+
.chat-sidebar-item.is-active:hover .chat-sidebar-item-title.is-marquee .chat-sidebar-item-title-t2 {
|
|
3110
|
+
display: inline-block;
|
|
3111
|
+
}
|
|
3112
|
+
.chat-sidebar-item:hover .chat-sidebar-item-actions { display: flex; }
|
|
3113
|
+
.chat-sidebar-item:hover .chat-sidebar-item-time { display: none; }
|
|
3114
|
+
.chat-sidebar-item-act:hover { color: var(--ink); }
|
|
3115
|
+
.chat-question-opt:hover { background: var(--hover); }
|
|
3116
|
+
.chat-question-submit:hover:not(:disabled) { opacity: .9; }
|
|
3117
|
+
.chat-topbar-btn:hover { background: var(--hover); color: var(--ink); }
|
|
3118
|
+
.chat-search-bar-btn:hover { background: var(--hover); color: var(--ink); }
|
|
3119
|
+
.chat-history-item:hover { background: var(--brand-soft); }
|
|
3120
|
+
.chat-share-close:hover { background: var(--hover-strong); color: var(--ink); }
|
|
3121
|
+
.chat-share-opt:hover:not(:disabled) { background: var(--hover-strong); }
|
|
3122
|
+
.chat-share-oa-link:hover { background: var(--hover-strong); }
|
|
3123
|
+
.chat-suggestions button:hover { background: var(--brand-soft); }
|
|
3124
|
+
.msg-attachment:hover { background: var(--brand-soft); border-color: var(--brand-line-strong); }
|
|
3125
|
+
.chat-owner-card:hover { border-color: #2563eb; box-shadow: 0 2px 10px rgba(47, 107, 255, .12); }
|
|
3126
|
+
.bubble .md a:hover, .artifact-md .md a:hover{ border-bottom-color: var(--brand); }
|
|
3127
|
+
.chat-thinking-done-toggle:hover { color: var(--ink); }
|
|
3128
|
+
.chat-browser-ask-btn:hover:not(:disabled) { background: var(--active); }
|
|
3129
|
+
.chat-notify-banner-link:hover { text-decoration: underline; }
|
|
3130
|
+
.chat-notify-banner-close:hover { background: var(--hover); color: var(--ink); }
|
|
3131
|
+
.chat-queue-act:hover { background: var(--hover); color: var(--ink); }
|
|
3132
|
+
.chat-queue-act--danger:hover { background: var(--danger-soft); color: var(--danger); }
|
|
3133
|
+
.chat-scene:hover { border-color: var(--brand); color: var(--brand-dark); }
|
|
3134
|
+
.chat-tool:hover { background: var(--hover); }
|
|
3135
|
+
.chat-voice:hover:not(:disabled) { background: var(--hover); }
|
|
3136
|
+
.chat-voice.recording:hover:not(:disabled) { background: var(--danger-soft); color: var(--danger); }
|
|
3137
|
+
.chat-model-picker-btn:hover { background: var(--hover); }
|
|
3138
|
+
.chat-model-picker-item:hover { background: var(--hover); }
|
|
3139
|
+
.chat-send:hover { background: var(--send-bg-hover); }
|
|
3140
|
+
.chat-send:disabled:hover { background: var(--send-bg); transform: none; }
|
|
3141
|
+
.chat-attachment:hover .chat-attachment-icon { opacity: 0; }
|
|
3142
|
+
.chat-attachment:hover .chat-attachment-remove { opacity: 1; transform: scale(1); }
|
|
3143
|
+
.chat-attachment-wrap:hover .chat-attachment-preview { opacity: 1; visibility: visible; transform: translateY(0); }
|
|
3144
|
+
.admin-range button:hover { color: var(--brand-dark); }
|
|
3145
|
+
.admin-table tbody tr:hover { background: var(--hover); }
|
|
3146
|
+
.chat-sat-star:hover { transform: scale(1.15); }
|
|
3147
|
+
.chat-fb-btn:hover { background: var(--hover); color: var(--ink); }
|
|
3148
|
+
.artifact-card:hover {
|
|
3149
|
+
border-color: var(--line);
|
|
3150
|
+
box-shadow: var(--shadow);
|
|
3151
|
+
background: var(--field-soft);
|
|
3152
|
+
}
|
|
3153
|
+
.artifact-menu-dl:hover, .artifact-drawer-close:hover { background: var(--hover); }
|
|
3154
|
+
.artifact-viewall:hover {
|
|
3155
|
+
border-color: var(--line); background: var(--hover);
|
|
3156
|
+
box-shadow: var(--shadow);
|
|
3157
|
+
}
|
|
3158
|
+
.artifact-list-item:hover .artifact-list-item-mainbtn {
|
|
3159
|
+
background: var(--hover);
|
|
3160
|
+
border-color: transparent;
|
|
3161
|
+
}
|
|
3162
|
+
.artifact-list-item:hover .artifact-list-item-name { color: var(--ink); }
|
|
3163
|
+
.artifact-list-item:hover .artifact-list-item-meta { color: var(--ink); }
|
|
3164
|
+
.chat-send--stop:hover { background: #f2f2f2; color: #111; transform: none; }
|
|
3165
|
+
.chat-modal-btn:hover { background: var(--hover-strong); }
|
|
3166
|
+
.chat-modal-btn--danger:hover { background: #d13438; }
|
|
3167
|
+
.chat-expand-toggle:hover { color: var(--ink); }
|
|
3168
|
+
.msg.user:hover .msg-hover-actions { opacity: 1; }
|
|
3169
|
+
.msg-hover-actions button:hover { background: var(--hover-strong); color: var(--ink); }
|
|
3170
|
+
.msg-hover-actions button.is-copied:hover { background: var(--copied-bg); color: var(--copied-ink); }
|
|
3171
|
+
.msg-edit-btns .chat-modal-btn:hover { background: var(--hover-strong); color: var(--ink); }
|
|
3172
|
+
.chat-modal-btn--primary:hover { background: var(--send-bg-hover) !important; }
|
|
3173
|
+
}
|
|
3174
|
+
|
|
3175
|
+
/* ============ 移动端交互体验补强 ============ */
|
|
3176
|
+
/* 触摸设备:点击闪动高亮去掉(黑白灰系) */
|
|
3177
|
+
* { -webkit-tap-highlight-color: transparent; }
|
|
3178
|
+
/* 按钮/链接:touch-action manipulation 消除双击缩放与点击延迟 */
|
|
3179
|
+
button, a, [role="button"], input, textarea, select {
|
|
3180
|
+
touch-action: manipulation;
|
|
3181
|
+
-webkit-touch-callout: none;
|
|
3182
|
+
}
|
|
3183
|
+
/* 滚动容器:overscroll contain 阻止移动端滚动链穿透(下拉刷新/回弹带动页面) */
|
|
3184
|
+
.chat-body, .chat-sidebar-list, .chat-history-list,
|
|
3185
|
+
.chat-right-section-body { overscroll-behavior: contain; }
|
|
3186
|
+
|
|
3187
|
+
/* 触摸设备(hover: none):会话条目不再常显操作按钮——改用长按/右键弹出操作菜单;
|
|
3188
|
+
时间位恢复正常显示,并禁用长按选中文本 */
|
|
3189
|
+
@media (hover: none) {
|
|
3190
|
+
.chat-sidebar-item .chat-sidebar-item-actions { display: none; }
|
|
3191
|
+
.chat-sidebar-item { user-select: none; -webkit-user-select: none; }
|
|
3192
|
+
/* 用户消息操作浮层(复制/编辑等)常显 */
|
|
3193
|
+
.msg.user .msg-hover-actions { opacity: 1; }
|
|
3194
|
+
/* 附件移除按钮常显(图标隐藏让位) */
|
|
3195
|
+
.chat-attachment .chat-attachment-icon { opacity: 0; }
|
|
3196
|
+
.chat-attachment .chat-attachment-remove { opacity: 1; transform: scale(1); }
|
|
3197
|
+
}
|
|
3198
|
+
/* 触屏(含混合设备,即便被系统识别为可悬停):会话 ⋯ 按钮同样隐藏,长按弹菜单 */
|
|
3199
|
+
@media (pointer: coarse) {
|
|
3200
|
+
.chat-sidebar-item .chat-sidebar-item-actions { display: none; }
|
|
3201
|
+
}
|
|
3202
|
+
|
|
3203
|
+
/* ============ Admin 用量分析页(黑白灰系,无依赖 SVG 图表) ============ */
|
|
3204
|
+
.au-page {
|
|
3205
|
+
min-height: 100vh;
|
|
3206
|
+
background: var(--bg);
|
|
3207
|
+
color: var(--ink);
|
|
3208
|
+
padding: 0 24px 48px;
|
|
3209
|
+
font-size: 13.5px;
|
|
3210
|
+
}
|
|
3211
|
+
.au-topbar {
|
|
3212
|
+
display: flex; align-items: center; gap: 14px;
|
|
3213
|
+
padding: 16px 0 14px; margin-bottom: 18px;
|
|
3214
|
+
border-bottom: 1px solid var(--line);
|
|
3215
|
+
}
|
|
3216
|
+
.au-back {
|
|
3217
|
+
display: inline-flex; align-items: center; gap: 4px;
|
|
3218
|
+
padding: 6px 12px; border-radius: 8px;
|
|
3219
|
+
border: 1px solid var(--line); background: var(--field-bg); color: var(--ink);
|
|
3220
|
+
cursor: pointer; font-size: 13px;
|
|
3221
|
+
}
|
|
3222
|
+
.au-back:hover { background: var(--hover-strong); }
|
|
3223
|
+
.au-back svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
|
|
3224
|
+
.au-title { margin: 0; font-size: 18px; font-weight: 700; }
|
|
3225
|
+
.au-topbar-note { color: var(--ink-soft); font-size: 12px; margin-left: auto; }
|
|
3226
|
+
.au-error {
|
|
3227
|
+
padding: 12px 16px; border-radius: 10px;
|
|
3228
|
+
background: rgba(229, 72, 77, .08); border: 1px solid rgba(229, 72, 77, .35);
|
|
3229
|
+
color: var(--danger); font-size: 13px;
|
|
3230
|
+
}
|
|
3231
|
+
.au-loading {
|
|
3232
|
+
display: flex; align-items: center; gap: 10px;
|
|
3233
|
+
color: var(--ink-soft); font-size: 14px; padding: 40px 0;
|
|
3234
|
+
}
|
|
3235
|
+
/* admin 登录表单(黑白灰系):仅管理员可访问用量页 */
|
|
3236
|
+
.au-login-wrap { display: flex; justify-content: center; padding: 64px 0; }
|
|
3237
|
+
.au-login-card {
|
|
3238
|
+
width: 100%; max-width: 340px;
|
|
3239
|
+
display: flex; flex-direction: column; gap: 12px;
|
|
3240
|
+
background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
|
|
3241
|
+
padding: 24px 22px;
|
|
3242
|
+
}
|
|
3243
|
+
.au-login-title { font-size: 17px; font-weight: 700; }
|
|
3244
|
+
.au-login-sub { font-size: 12.5px; color: var(--ink-soft); margin-bottom: 4px; }
|
|
3245
|
+
.au-login-field { display: flex; flex-direction: column; gap: 5px; font-size: 12.5px; color: var(--ink-soft); }
|
|
3246
|
+
.au-login-field input {
|
|
3247
|
+
border: 1px solid var(--line); border-radius: 8px; background: var(--field-bg);
|
|
3248
|
+
color: var(--ink); padding: 8px 10px; font-size: 13.5px;
|
|
3249
|
+
}
|
|
3250
|
+
.au-login-field input:focus { outline: none; border-color: var(--ink); }
|
|
3251
|
+
.au-login-err { font-size: 12.5px; color: var(--danger); }
|
|
3252
|
+
.au-login-submit {
|
|
3253
|
+
margin-top: 6px; border: none; border-radius: 999px; padding: 9px 0;
|
|
3254
|
+
cursor: pointer; font-size: 13.5px; font-weight: 600;
|
|
3255
|
+
color: var(--panel); background: var(--ink);
|
|
3256
|
+
transition: opacity .15s ease, transform .1s ease;
|
|
3257
|
+
}
|
|
3258
|
+
.au-login-submit:hover:not(:disabled) { opacity: .9; }
|
|
3259
|
+
.au-login-submit:active:not(:disabled) { transform: scale(.98); }
|
|
3260
|
+
.au-login-submit:disabled { background: var(--line); color: var(--ink-soft); cursor: not-allowed; }
|
|
3261
|
+
.au-logout { margin-left: 0; }
|
|
3262
|
+
/* 无 cost_info 数据的空态:整页展示「暂无用量数据」,不报错 */
|
|
3263
|
+
.au-empty-page {
|
|
3264
|
+
padding: 64px 24px; text-align: center;
|
|
3265
|
+
background: var(--panel); border: 1px dashed var(--line); border-radius: 12px;
|
|
3266
|
+
}
|
|
3267
|
+
.au-empty-page-title { font-size: 17px; font-weight: 700; color: var(--ink); margin-bottom: 8px; }
|
|
3268
|
+
.au-empty-page-sub { font-size: 13px; color: var(--ink-soft); line-height: 1.6; }
|
|
3269
|
+
.au-cards { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 26px; }
|
|
3270
|
+
.au-card {
|
|
3271
|
+
flex: 1 1 150px; min-width: 140px;
|
|
3272
|
+
background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
|
|
3273
|
+
padding: 16px 18px;
|
|
3274
|
+
}
|
|
3275
|
+
.au-card-num { font-size: 22px; font-weight: 700; color: var(--ink); margin-bottom: 4px; }
|
|
3276
|
+
.au-card-cap { font-size: 12px; color: var(--ink-soft); }
|
|
3277
|
+
.au-sec { margin-bottom: 28px; }
|
|
3278
|
+
.au-sec-title { margin: 0 0 12px; font-size: 15px; font-weight: 600; }
|
|
3279
|
+
.au-empty { color: var(--ink-soft); font-size: 13px; }
|
|
3280
|
+
.au-hbar { width: 100%; max-width: 720px; height: auto; display: block; }
|
|
3281
|
+
.au-bar-label { fill: var(--ink-soft); }
|
|
3282
|
+
.au-bar-rect { fill: var(--ink); opacity: .82; }
|
|
3283
|
+
.au-bar-val { fill: var(--ink); font-weight: 600; }
|
|
3284
|
+
.au-table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: 12px; background: var(--panel); }
|
|
3285
|
+
.au-table { border-collapse: collapse; width: 100%; min-width: 820px; font-size: 12.5px; }
|
|
3286
|
+
.au-table th, .au-table td {
|
|
3287
|
+
padding: 8px 12px; text-align: left;
|
|
3288
|
+
border-bottom: 1px solid var(--line);
|
|
3289
|
+
white-space: nowrap;
|
|
3290
|
+
}
|
|
3291
|
+
.au-table th { background: var(--hover-strong); color: var(--ink-soft); font-weight: 600; position: sticky; top: 0; }
|
|
3292
|
+
.au-table tbody tr:hover { background: var(--hover); }
|
|
3293
|
+
.au-num { text-align: right; font-variant-numeric: tabular-nums; }
|
|
3294
|
+
.au-strong { font-weight: 700; }
|
|
3295
|
+
.au-mono { font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: 12px; }
|
|
3296
|
+
.au-preview { max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink-soft); }
|
|
3297
|
+
/* 按会话分组合并单元格:第一列合并(Excel 合并样式),单元格内为会话名 + 该会话合计 */
|
|
3298
|
+
.au-col-session { min-width: 150px; }
|
|
3299
|
+
.au-group-cell {
|
|
3300
|
+
background: var(--hover); vertical-align: middle; min-width: 150px;
|
|
3301
|
+
border-top: 1px solid var(--line);
|
|
3302
|
+
}
|
|
3303
|
+
.au-group-title { font-weight: 700; color: var(--ink); font-size: 12.5px; line-height: 1.4; }
|
|
3304
|
+
.au-group-total { font-size: 11px; color: var(--ink-soft); margin-top: 3px; font-variant-numeric: tabular-nums; line-height: 1.4; }
|
|
3305
|
+
/* 会话组之间的分隔:组首行上方一条更明显的线 */
|
|
3306
|
+
.au-table tbody tr.au-row-first td { border-top: 1px solid var(--ink-soft); }
|
|
3307
|
+
.au-foot { color: var(--ink-soft); font-size: 12px; margin-top: 8px; }
|
|
3308
|
+
|
|
3309
|
+
/* ============ 侧边消息滑块(ChatGPT/豆包式 minimap,组件 MessageSlider.tsx) ============
|
|
3310
|
+
挂在 .chat-main(position:relative)内、聊天区右缘;显隐由 JS 控制(宽度/可滚动判定)。
|
|
3311
|
+
横线颜色:视口内=--slider-on(亮),滚出视口=--slider-off(灰);hover 加宽+高亮。 */
|
|
3312
|
+
.chat-slider {
|
|
3313
|
+
position: absolute; left: 10px; top: 90px; bottom: 190px; z-index: 30;
|
|
3314
|
+
display: flex; align-items: center;
|
|
3315
|
+
pointer-events: none; /* 容器不拦截,滚轮/点击穿透到聊天区;仅轨道可交互 */
|
|
3316
|
+
opacity: 0; visibility: hidden;
|
|
3317
|
+
transition: opacity .18s ease, visibility .18s;
|
|
3318
|
+
}
|
|
3319
|
+
.chat-slider.is-show { opacity: 1; visibility: visible; }
|
|
3320
|
+
.chat-slider-track { position: relative; width: 64px; pointer-events: auto; }
|
|
3321
|
+
/* 横线:宽度全部由 JS 经 --w 变量给出(非 hover 统一 10px;hover 时按与悬停横线的
|
|
3322
|
+
距离指数衰减渐变——hover 最宽、相邻次之、远处钳回 10px,友商同款「波峰」过渡)。
|
|
3323
|
+
3px 视觉高度 + 14px 命中区(background-clip: content-box 只画中间 3px) */
|
|
3324
|
+
.chat-slider-dash {
|
|
3325
|
+
position: absolute; left: 0; height: 14px; padding: 5.5px 0; box-sizing: border-box;
|
|
3326
|
+
border: none; border-radius: 2px; cursor: pointer;
|
|
3327
|
+
background: var(--slider-off); background-clip: content-box;
|
|
3328
|
+
width: var(--w, 10px);
|
|
3329
|
+
transition: width .14s ease, background-color .18s ease;
|
|
3330
|
+
}
|
|
3331
|
+
.chat-slider-dash.is-on { background-color: var(--slider-on); }
|
|
3332
|
+
.chat-slider-dash.is-hover { background-color: var(--slider-hover); }
|
|
3333
|
+
.chat-slider-dash:focus-visible { outline: 1px solid var(--brand); outline-offset: 1px; }
|
|
3334
|
+
/* 提问 tooltip:hover 横线右侧弹出,显示该消息所属轮次的用户提问(点击横线即跳到那个提问)。
|
|
3335
|
+
定位模型:position: fixed(包含块=视口),left/top 由 JS 从横线按钮 getBoundingClientRect 算出。
|
|
3336
|
+
这是竖条塌陷的根治方案——absolute + 64px track 包含块会把 shrink-to-fit 可用宽度压到 64px,
|
|
3337
|
+
中文逐字断行一字一行;fixed 下可用宽度=视口,width:max-content 自然取内容真实宽度,
|
|
3338
|
+
max-width:340px 只在超宽时折行 → 短文字窄气泡、长文字 340px 换行。
|
|
3339
|
+
最多 5 行:max-height 裁切 + JS 侧 120 字截断加「…」。 */
|
|
3340
|
+
.chat-slider-tip {
|
|
3341
|
+
position: fixed; transform: translateY(-50%);
|
|
3342
|
+
width: max-content; max-width: 340px;
|
|
3343
|
+
max-height: calc(5 * 1.5em + 16px); overflow: hidden;
|
|
3344
|
+
padding: 8px 12px; border-radius: 10px;
|
|
3345
|
+
background: var(--toast-bg); color: var(--ink);
|
|
3346
|
+
border: 1px solid var(--line); box-shadow: var(--shadow);
|
|
3347
|
+
font-size: 12.5px; line-height: 1.5;
|
|
3348
|
+
pointer-events: none; z-index: 31;
|
|
3349
|
+
}
|
|
3350
|
+
.chat-slider-tip-text {
|
|
3351
|
+
display: block;
|
|
3352
|
+
white-space: normal; word-break: break-word;
|
|
3353
|
+
max-width: 340px;
|
|
3354
|
+
}
|