ui(css): dev.html 圆角降一档 + 抽 token + modal 基类化 (style -11%)
抽 5 组 CSS token(语义色组 / 圆角分档 / mono / transition / shadow),顶栏按钮 hover + dd-item + badge 全切到 token(同色 selector 合并:export ≈ sp-copy 蓝、abandon ≈ sp-move 橙);4 个 modal 抽 .modal 基类(fixed/inset/bg/.show 五属性合并);.msg .body 与 file-preview .md-render 合并 markdown 渲染规则。圆角主流档 6px → 4px,modal card 8~12px → 6~8px,art-chip 999px 保留(胶囊语言)。功能 0 改动,JS 一行没动。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
fa6cb72103
commit
6f9391dee3
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
> 配合 `DESIGN.md`。本文件只记 phase 状态、决策偏差、文件量、下一步。每条 1-2 句:做了啥 + 关键判断;细节查 `git log` / `git diff` / `DESIGN §7.9`。
|
> 配合 `DESIGN.md`。本文件只记 phase 状态、决策偏差、文件量、下一步。每条 1-2 句:做了啥 + 关键判断;细节查 `git log` / `git diff` / `DESIGN §7.9`。
|
||||||
|
|
||||||
最后更新:2026-05-21(system prompt 注入 task 预选 skill 提示)
|
最后更新:2026-05-21(dev.html CSS 精简 + 圆角降档 + modal 基类化)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
### 2026-05-21
|
### 2026-05-21
|
||||||
|
|
||||||
|
- **dev.html CSS 精简 + 圆角降档 + modal 基类化(style 块 589 → 522 行,-11%)**:为了"没那么圆润"统一调整。引入 CSS tokens:① 语义色组 `--c-green/blue/purple/orange/red` + 同色 `-bg/-bd` 三件套,顶栏 5 个按钮 hover + dd-item + badge.completed + sp-copy/sp-move 全切到 token(同色 selector 合并:export ≈ sp-copy 蓝、abandon ≈ sp-move 橙,各省 1 条规则);② 圆角分档 `--r-sm/md/lg/xl` = 3/4/6/8px,主流 button/input/msg/menu 从 6px 降到 4px,modal card 从 8~12px 降到 6~8px,art-chip 999px 保留(胶囊语言);③ `--mono`/`--t`/`--shadow-card` 收敛重复 font-family/transition/box-shadow。④ 4 个 modal(`#admin-modal/#src-picker-modal/#new-task-modal/#file-preview-modal`)抽 `.modal` 基类(fixed/inset/bg/display/.show 五属性合并),id 选择器只留 z-index + 宽高差异;HTML 同步加 `class="modal"`(JS `classList.add("show")` 不动)。⑤ `.msg .body` 与 file-preview `.md-render` 合并 markdown 渲染规则(`.msg .body x, .md-render x { ... }`,从两套 17 条缩到一套 17 条多 selector)。⑥ `button:disabled` 全局兜底,删散落 2 处单独写;`#login input:focus` 与 `#admin-modal input:focus` 合并(规则一字不差)。`.dev-item.act-export/rename` 同色合并到一行。功能 0 改动,JS 完全不动;`.dd-item` 颜色微变(原 #2e7d32 → #27ae60 等,因为统一到 5 组色 token)是可接受的副作用。
|
||||||
- **工作目录回到原生 `<select>` + sentinel + 二级 input(modal + 顶部 filter)**:combobox 方案推翻 —— 即使 show 时不过滤,modal 里 wd 因联动有值之后用户的直觉仍然是"我得点开下拉看选项",自己实现的 panel 总不如浏览器原生 select 稳。改回 select 范式:① modal `nt-wd-sel` 第一项 sentinel `+ 新建「<name>」`(label 由 `updateSentinelLabel` 跟 name 实时刷)+ 其后已有目录列表;sentinel 选中时显示二级 `nt-wd-new` 输入框默认值跟随 name,选已有目录时隐藏。`wdManuallyEdited` 锚到二级 input 上(用户改它就脱钩,清空恢复跟随)。② 顶部 `filter-wd` 也改成 `<select>`,首项 `(全部目录)`,onchange → `loadTaskList`;原 input 的 debounce listener 删,搜索 `filter-q` 的 debounce 保留独立写。③ `loadFolderSuggestions` 拉数据 + 新增 `populateFolderSelects` 灌两个 select(保留当前选中值);`enterApp` 启动时 fire-and-forget 预拉一次让左 pane 一打开就有选项。④ hint 在"输入新名恰好命中已有"时提示"将复用而非新建"。combobox 工厂 + .combo CSS + datalist 残留全删。
|
- **工作目录回到原生 `<select>` + sentinel + 二级 input(modal + 顶部 filter)**:combobox 方案推翻 —— 即使 show 时不过滤,modal 里 wd 因联动有值之后用户的直觉仍然是"我得点开下拉看选项",自己实现的 panel 总不如浏览器原生 select 稳。改回 select 范式:① modal `nt-wd-sel` 第一项 sentinel `+ 新建「<name>」`(label 由 `updateSentinelLabel` 跟 name 实时刷)+ 其后已有目录列表;sentinel 选中时显示二级 `nt-wd-new` 输入框默认值跟随 name,选已有目录时隐藏。`wdManuallyEdited` 锚到二级 input 上(用户改它就脱钩,清空恢复跟随)。② 顶部 `filter-wd` 也改成 `<select>`,首项 `(全部目录)`,onchange → `loadTaskList`;原 input 的 debounce listener 删,搜索 `filter-q` 的 debounce 保留独立写。③ `loadFolderSuggestions` 拉数据 + 新增 `populateFolderSelects` 灌两个 select(保留当前选中值);`enterApp` 启动时 fire-and-forget 预拉一次让左 pane 一打开就有选项。④ hint 在"输入新名恰好命中已有"时提示"将复用而非新建"。combobox 工厂 + .combo CSS + datalist 残留全删。
|
||||||
- **新建任务弹窗工作目录改 combobox + name 联动**:`web/static/dev.html` modal 里 `nt-wd-sel` 从 `<select>` 改成 `<input list="folders-datalist">`,删 `+ 新建目录…` sentinel + 二级 `nt-wd-new` 输入框;加 `wdManuallyEdited` flag —— name 输入时若 flag=false 自动同步到 wd(programmatic 改 value 不触发 wd input 事件不会假阳性),wd 非空输入置 flag=true 脱钩,wd 清空重置 flag=false 但保持空(避免 backspace 想换名字时被立刻填回打断);submit 保留 `working_dir || name` fallback 兜底空值。`loadFolderSuggestions` 不再渲染 select options,只灌共享 datalist + 缓存到 `state.folders` 供 hint 比对"命中已有/新建"。label 文案 `(可选,留空 → 用任务名...)` → `(默认跟随任务名;可输入新名或选已有目录复用)`,更直观。
|
- **新建任务弹窗工作目录改 combobox + name 联动**:`web/static/dev.html` modal 里 `nt-wd-sel` 从 `<select>` 改成 `<input list="folders-datalist">`,删 `+ 新建目录…` sentinel + 二级 `nt-wd-new` 输入框;加 `wdManuallyEdited` flag —— name 输入时若 flag=false 自动同步到 wd(programmatic 改 value 不触发 wd input 事件不会假阳性),wd 非空输入置 flag=true 脱钩,wd 清空重置 flag=false 但保持空(避免 backspace 想换名字时被立刻填回打断);submit 保留 `working_dir || name` fallback 兜底空值。`loadFolderSuggestions` 不再渲染 select options,只灌共享 datalist + 缓存到 `state.folders` 供 hint 比对"命中已有/新建"。label 文案 `(可选,留空 → 用任务名...)` → `(默认跟随任务名;可输入新名或选已有目录复用)`,更直观。
|
||||||
- **system prompt 注入 task 预选 skill 提示**:`core/agent_builder.py::_build_system_prompt` 加 `task_skill` 参数,非空时在"工作目录与 task 上下文"段加一行 `- **task 预选 skill**: \`<name>\` — 用户创建时声明的主 skill`;空字符串走老路径,prompt 字节级一致。LLM 拿到这条事实 + `general_v1.md:17-23` 已有的"对应 skill 领域先 load_skill" 规则自然组合 → 主动 load。否决"直接把完整 SKILL.md 预注入 prompt"方案 —— 那会把 `tasks.skill` 从 metadata 升格成 binding,需要同步改 DESIGN.md / 想清楚 PATCH 改 skill 的语义,投入产出比不划算;轻量提示保渐进披露三层架构不动。
|
- **system prompt 注入 task 预选 skill 提示**:`core/agent_builder.py::_build_system_prompt` 加 `task_skill` 参数,非空时在"工作目录与 task 上下文"段加一行 `- **task 预选 skill**: \`<name>\` — 用户创建时声明的主 skill`;空字符串走老路径,prompt 字节级一致。LLM 拿到这条事实 + `general_v1.md:17-23` 已有的"对应 skill 领域先 load_skill" 规则自然组合 → 主动 load。否决"直接把完整 SKILL.md 预注入 prompt"方案 —— 那会把 `tasks.skill` 从 metadata 升格成 binding,需要同步改 DESIGN.md / 想清楚 PATCH 改 skill 的语义,投入产出比不划算;轻量提示保渐进披露三层架构不动。
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,21 @@
|
||||||
--code-bg: #f4f4f4;
|
--code-bg: #f4f4f4;
|
||||||
--user-bg: #eef4fb;
|
--user-bg: #eef4fb;
|
||||||
--asst-bg: #ffffff;
|
--asst-bg: #ffffff;
|
||||||
|
/* 语义色组:done/export/clear/abandon/delete 按钮 + dd-item + badge 共用 */
|
||||||
|
--c-green: #27ae60; --c-green-bg: #e9f7ef; --c-green-bd: #a9dfbf;
|
||||||
|
--c-blue: #2980b9; --c-blue-bg: #ebf5fb; --c-blue-bd: #aed6f1;
|
||||||
|
--c-purple: #8e44ad; --c-purple-bg: #f5eef8; --c-purple-bd: #d2b4de;
|
||||||
|
--c-orange: #e67e22; --c-orange-bg: #fef5e7; --c-orange-bd: #f5cba7;
|
||||||
|
--c-red: #c0392b; --c-red-bg: #fdedec; --c-red-bd: #f5b7b1;
|
||||||
|
/* 圆角:各档下调一档(没那么圆润) */
|
||||||
|
--r-sm: 3px; /* code / 小标签 */
|
||||||
|
--r-md: 4px; /* button / input / 消息气泡 / 卡片元素 */
|
||||||
|
--r-lg: 6px; /* modal card / 中型容器 */
|
||||||
|
--r-xl: 8px; /* 大 modal card(登录卡) */
|
||||||
|
--shadow-card: 0 12px 32px rgba(0,0,0,.18);
|
||||||
|
--shadow-card-lg: 0 20px 60px rgba(0,0,0,.12), 0 2px 6px rgba(0,0,0,.04);
|
||||||
|
--mono: ui-monospace, "Cascadia Code", "SF Mono", Consolas, monospace;
|
||||||
|
--t: all .15s;
|
||||||
}
|
}
|
||||||
* { box-sizing: border-box; }
|
* { box-sizing: border-box; }
|
||||||
html, body { height: 100%; margin: 0; }
|
html, body { height: 100%; margin: 0; }
|
||||||
|
|
@ -33,27 +48,36 @@
|
||||||
color: var(--text); background: var(--bg);
|
color: var(--text); background: var(--bg);
|
||||||
overflow: hidden; /* 视窗锁死,所有滚动在 pane 内 */
|
overflow: hidden; /* 视窗锁死,所有滚动在 pane 内 */
|
||||||
}
|
}
|
||||||
button, input, textarea, select {
|
button, input, textarea, select { font: inherit; color: inherit; }
|
||||||
font: inherit; color: inherit;
|
|
||||||
}
|
|
||||||
button {
|
button {
|
||||||
background: #fff; border: 1px solid var(--border);
|
background: #fff; border: 1px solid var(--border);
|
||||||
padding: 4px 10px; border-radius: 6px; cursor: pointer;
|
padding: 4px 10px; border-radius: var(--r-md); cursor: pointer;
|
||||||
transition: color .15s, border-color .15s, background .15s, box-shadow .15s;
|
transition: var(--t);
|
||||||
}
|
}
|
||||||
button:hover { background: var(--hover); }
|
button:hover:not(:disabled) { background: var(--hover); }
|
||||||
|
button:disabled { opacity: 0.4; cursor: not-allowed; }
|
||||||
button.primary { background: var(--accent); color: #fff; border-color: var(--accent); }
|
button.primary { background: var(--accent); color: #fff; border-color: var(--accent); }
|
||||||
button.primary:hover { filter: brightness(1.08); }
|
button.primary:hover { filter: brightness(1.08); }
|
||||||
button.danger:hover { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
|
button.danger:hover { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
|
||||||
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
|
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
|
||||||
textarea, select {
|
textarea, select {
|
||||||
background: #fff; border: 1px solid var(--border);
|
background: #fff; border: 1px solid var(--border);
|
||||||
padding: 5px 8px; border-radius: 6px; width: 100%;
|
padding: 5px 8px; border-radius: var(--r-md); width: 100%;
|
||||||
}
|
}
|
||||||
input[type="checkbox"], input[type="radio"] { cursor: pointer; }
|
input[type="checkbox"], input[type="radio"] { cursor: pointer; }
|
||||||
textarea { resize: vertical; min-height: 60px; }
|
textarea { resize: vertical; min-height: 60px; }
|
||||||
a { color: var(--accent); text-decoration: none; }
|
a { color: var(--accent); text-decoration: none; }
|
||||||
a:hover { text-decoration: underline; }
|
a:hover { text-decoration: underline; }
|
||||||
|
/* 4 个 modal 共用骨架(admin / src-picker / new-task / file-preview) */
|
||||||
|
.modal {
|
||||||
|
position: fixed; inset: 0; background: rgba(0,0,0,0.4);
|
||||||
|
display: none; align-items: center; justify-content: center;
|
||||||
|
}
|
||||||
|
.modal.show { display: flex; }
|
||||||
|
.modal > .card {
|
||||||
|
background: var(--panel); border-radius: var(--r-lg);
|
||||||
|
box-shadow: var(--shadow-card);
|
||||||
|
}
|
||||||
|
|
||||||
/* ───── login overlay ───── */
|
/* ───── login overlay ───── */
|
||||||
#login {
|
#login {
|
||||||
|
|
@ -67,9 +91,9 @@
|
||||||
#login .card {
|
#login .card {
|
||||||
background: var(--panel);
|
background: var(--panel);
|
||||||
padding: 32px 36px 28px;
|
padding: 32px 36px 28px;
|
||||||
border-radius: 12px;
|
border-radius: var(--r-xl);
|
||||||
width: 380px;
|
width: 380px;
|
||||||
box-shadow: 0 20px 60px rgba(0,0,0,.12), 0 2px 6px rgba(0,0,0,.04);
|
box-shadow: var(--shadow-card-lg);
|
||||||
border: 1px solid rgba(0,0,0,.04);
|
border: 1px solid rgba(0,0,0,.04);
|
||||||
animation: login-in .35s cubic-bezier(.2,.7,.2,1);
|
animation: login-in .35s cubic-bezier(.2,.7,.2,1);
|
||||||
}
|
}
|
||||||
|
|
@ -77,11 +101,9 @@
|
||||||
from { opacity: 0; transform: translateY(8px); }
|
from { opacity: 0; transform: translateY(8px); }
|
||||||
to { opacity: 1; transform: translateY(0); }
|
to { opacity: 1; transform: translateY(0); }
|
||||||
}
|
}
|
||||||
#login .brand {
|
#login .brand { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
|
||||||
display: flex; align-items: center; gap: 10px; margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
#login .brand .logo {
|
#login .brand .logo {
|
||||||
width: 32px; height: 32px; border-radius: 8px;
|
width: 32px; height: 32px; border-radius: var(--r-md);
|
||||||
background: linear-gradient(135deg, var(--accent), #8e2a20);
|
background: linear-gradient(135deg, var(--accent), #8e2a20);
|
||||||
color: #fff; font-weight: 700; font-size: 16px;
|
color: #fff; font-weight: 700; font-size: 16px;
|
||||||
display: flex; align-items: center; justify-content: center;
|
display: flex; align-items: center; justify-content: center;
|
||||||
|
|
@ -94,23 +116,20 @@
|
||||||
font-size: 12px; color: var(--muted); letter-spacing: .2px;
|
font-size: 12px; color: var(--muted); letter-spacing: .2px;
|
||||||
}
|
}
|
||||||
#login input {
|
#login input {
|
||||||
padding: 9px 12px; border-radius: 6px;
|
padding: 9px 12px; border-radius: var(--r-md);
|
||||||
border: 1px solid var(--border); background: #fafafa;
|
border: 1px solid var(--border); background: #fafafa;
|
||||||
transition: border-color .15s, background .15s, box-shadow .15s;
|
transition: var(--t);
|
||||||
}
|
}
|
||||||
#login input:hover { background: #fff; }
|
#login input:hover { background: #fff; }
|
||||||
#login input:focus {
|
#login input:focus, #admin-modal input:focus {
|
||||||
outline: none; background: #fff; border-color: var(--accent);
|
outline: none; background: #fff; border-color: var(--accent);
|
||||||
box-shadow: 0 0 0 3px rgba(192,57,43,.12);
|
box-shadow: 0 0 0 3px rgba(192,57,43,.12);
|
||||||
}
|
}
|
||||||
#login .err {
|
#login .err { color: var(--accent); font-size: 12px; margin-top: 12px; min-height: 1em; }
|
||||||
color: var(--accent); font-size: 12px; margin-top: 12px;
|
|
||||||
min-height: 1em; transition: opacity .15s;
|
|
||||||
}
|
|
||||||
#login .actions { margin-top: 18px; display: flex; gap: 8px; }
|
#login .actions { margin-top: 18px; display: flex; gap: 8px; }
|
||||||
#login .actions .primary {
|
#login .actions .primary {
|
||||||
flex: 1; padding: 9px 14px; font-size: 14px; font-weight: 500;
|
flex: 1; padding: 9px 14px; font-size: 14px; font-weight: 500;
|
||||||
border-radius: 6px; transition: filter .15s, transform .05s, box-shadow .15s;
|
border-radius: var(--r-md); transition: var(--t);
|
||||||
box-shadow: 0 2px 6px rgba(192,57,43,.25);
|
box-shadow: 0 2px 6px rgba(192,57,43,.25);
|
||||||
}
|
}
|
||||||
#login .actions .primary:hover { box-shadow: 0 4px 12px rgba(192,57,43,.35); }
|
#login .actions .primary:hover { box-shadow: 0 4px 12px rgba(192,57,43,.35); }
|
||||||
|
|
@ -122,8 +141,7 @@
|
||||||
#login .tabs button {
|
#login .tabs button {
|
||||||
background: none; border: none; border-bottom: 2px solid transparent;
|
background: none; border: none; border-bottom: 2px solid transparent;
|
||||||
padding: 8px 4px; margin-right: 16px; font-size: 13px;
|
padding: 8px 4px; margin-right: 16px; font-size: 13px;
|
||||||
color: var(--muted); cursor: pointer;
|
color: var(--muted); cursor: pointer; transition: var(--t);
|
||||||
transition: color .15s, border-color .15s;
|
|
||||||
}
|
}
|
||||||
#login .tabs button:hover { color: var(--text); background: none; }
|
#login .tabs button:hover { color: var(--text); background: none; }
|
||||||
#login .tabs button.active { color: var(--accent); border-bottom-color: var(--accent); }
|
#login .tabs button.active { color: var(--accent); border-bottom-color: var(--accent); }
|
||||||
|
|
@ -133,48 +151,28 @@
|
||||||
from { opacity: 0; transform: translateY(2px); }
|
from { opacity: 0; transform: translateY(2px); }
|
||||||
to { opacity: 1; transform: translateY(0); }
|
to { opacity: 1; transform: translateY(0); }
|
||||||
}
|
}
|
||||||
#login code {
|
#login code { background: var(--code-bg); padding: 1px 5px; border-radius: var(--r-sm); font-size: 11.5px; }
|
||||||
background: var(--code-bg); padding: 1px 5px; border-radius: 3px;
|
#login .card-footer { margin-top: 10px; display: flex; justify-content: flex-end; }
|
||||||
font-size: 11.5px;
|
|
||||||
}
|
|
||||||
#login .card-footer {
|
|
||||||
margin-top: 10px; display: flex; justify-content: flex-end;
|
|
||||||
}
|
|
||||||
#login .ghost-link {
|
#login .ghost-link {
|
||||||
color: var(--muted); font-size: 12px; text-decoration: none;
|
color: var(--muted); font-size: 12px; text-decoration: none;
|
||||||
padding: 2px 4px; border-radius: 4px; transition: color .15s, background .15s;
|
padding: 2px 4px; border-radius: var(--r-md); transition: var(--t);
|
||||||
}
|
}
|
||||||
#login .ghost-link:hover { color: var(--accent); background: var(--accent-soft); }
|
#login .ghost-link:hover { color: var(--accent); background: var(--accent-soft); }
|
||||||
|
|
||||||
/* ───── admin add-user modal ───── */
|
/* ───── admin add-user modal ───── */
|
||||||
#admin-modal {
|
#admin-modal { z-index: 110; }
|
||||||
position: fixed; inset: 0; background: rgba(0,0,0,0.4);
|
#admin-modal .card { padding: 20px 24px; width: 360px; }
|
||||||
display: none; align-items: center; justify-content: center; z-index: 110;
|
|
||||||
}
|
|
||||||
#admin-modal.show { display: flex; }
|
|
||||||
#admin-modal .card {
|
|
||||||
background: var(--panel); padding: 20px 24px; border-radius: 10px;
|
|
||||||
width: 360px; box-shadow: 0 16px 40px rgba(0,0,0,.18);
|
|
||||||
}
|
|
||||||
#admin-modal h3 { margin: 0 0 12px; font-size: 15px; }
|
#admin-modal h3 { margin: 0 0 12px; font-size: 15px; }
|
||||||
#admin-modal label {
|
#admin-modal label {
|
||||||
display: block; margin-top: 10px; margin-bottom: 4px;
|
display: block; margin-top: 10px; margin-bottom: 4px;
|
||||||
font-size: 12px; color: var(--muted);
|
font-size: 12px; color: var(--muted);
|
||||||
}
|
}
|
||||||
#admin-modal input {
|
#admin-modal input {
|
||||||
width: 100%; padding: 8px 10px; border-radius: 6px;
|
width: 100%; padding: 8px 10px; border-radius: var(--r-md);
|
||||||
border: 1px solid var(--border); background: #fafafa;
|
border: 1px solid var(--border); background: #fafafa;
|
||||||
}
|
}
|
||||||
#admin-modal input:focus {
|
#admin-modal .err { color: var(--accent); font-size: 12px; margin-top: 10px; min-height: 1em; }
|
||||||
outline: none; background: #fff; border-color: var(--accent);
|
#admin-modal .actions { margin-top: 14px; display: flex; gap: 8px; justify-content: flex-end; }
|
||||||
box-shadow: 0 0 0 3px rgba(192,57,43,.12);
|
|
||||||
}
|
|
||||||
#admin-modal .err {
|
|
||||||
color: var(--accent); font-size: 12px; margin-top: 10px; min-height: 1em;
|
|
||||||
}
|
|
||||||
#admin-modal .actions {
|
|
||||||
margin-top: 14px; display: flex; gap: 8px; justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ───── 3-pane layout ───── */
|
/* ───── 3-pane layout ───── */
|
||||||
#app { display: none; height: 100vh; }
|
#app { display: none; height: 100vh; }
|
||||||
|
|
@ -197,14 +195,14 @@
|
||||||
}
|
}
|
||||||
header .brand { display: flex; align-items: center; gap: 8px; }
|
header .brand { display: flex; align-items: center; gap: 8px; }
|
||||||
header .brand .logo {
|
header .brand .logo {
|
||||||
width: 24px; height: 24px; border-radius: 6px;
|
width: 24px; height: 24px; border-radius: var(--r-md);
|
||||||
background: linear-gradient(135deg, var(--accent), #8e2a20);
|
background: linear-gradient(135deg, var(--accent), #8e2a20);
|
||||||
color: #fff; font-weight: 700; font-size: 13px;
|
color: #fff; font-weight: 700; font-size: 13px;
|
||||||
display: flex; align-items: center; justify-content: center;
|
display: flex; align-items: center; justify-content: center;
|
||||||
box-shadow: 0 2px 6px rgba(192,57,43,.28);
|
box-shadow: 0 2px 6px rgba(192,57,43,.28);
|
||||||
}
|
}
|
||||||
header .title { font-weight: 600; font-size: 15px; letter-spacing: .2px; }
|
header .title { font-weight: 600; font-size: 15px; letter-spacing: .2px; }
|
||||||
header .who { color: var(--muted); font-size: 12px; font-family: monospace; }
|
header .who { color: var(--muted); font-size: 12px; font-family: var(--mono); }
|
||||||
header .spacer { flex: 1; }
|
header .spacer { flex: 1; }
|
||||||
|
|
||||||
.pane { border-right: 1px solid var(--border); background: var(--panel); overflow: auto; min-height: 0; }
|
.pane { border-right: 1px solid var(--border); background: var(--panel); overflow: auto; min-height: 0; }
|
||||||
|
|
@ -225,26 +223,28 @@
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-bottom: 1px solid var(--border-soft);
|
border-bottom: 1px solid var(--border-soft);
|
||||||
}
|
}
|
||||||
/* 对话顶栏按钮:常态中性 + hover 上语义色 — 完成 绿/导出 蓝/清空 紫/废弃 橙/删除 红 */
|
/* 对话顶栏按钮:常态中性 + hover 上语义色 — 完成 绿/导出 蓝/清空 紫/废弃 橙/删除 红
|
||||||
#btn-done:hover:not(:disabled) { color: #27ae60; border-color: #a9dfbf; background: #e9f7ef; }
|
同色组合并 selector(export ≈ sp-copy 蓝, abandon ≈ sp-move 橙) */
|
||||||
#btn-export:hover:not(:disabled) { color: #2980b9; border-color: #aed6f1; background: #ebf5fb; }
|
#btn-done:hover:not(:disabled) { color: var(--c-green); border-color: var(--c-green-bd); background: var(--c-green-bg); }
|
||||||
#btn-clear-msgs:hover:not(:disabled) { color: #8e44ad; border-color: #d2b4de; background: #f5eef8; }
|
#btn-export:hover:not(:disabled),
|
||||||
#btn-abandon:hover:not(:disabled) { color: #e67e22; border-color: #f5cba7; background: #fef5e7; }
|
#sp-copy:hover:not(:disabled) { color: var(--c-blue); border-color: var(--c-blue-bd); background: var(--c-blue-bg); }
|
||||||
#btn-delete-task:hover:not(:disabled) { color: #c0392b; border-color: #f5b7b1; background: #fdedec; }
|
#btn-clear-msgs:hover:not(:disabled) { color: var(--c-purple); border-color: var(--c-purple-bd); background: var(--c-purple-bg); }
|
||||||
#pane-mid > .pane-head > button.small:disabled { opacity: 0.4; cursor: not-allowed; }
|
#btn-abandon:hover:not(:disabled),
|
||||||
|
#sp-move:hover:not(:disabled) { color: var(--c-orange); border-color: var(--c-orange-bd); background: var(--c-orange-bg); }
|
||||||
|
#btn-delete-task:hover:not(:disabled) { color: var(--c-red); border-color: var(--c-red-bd); background: var(--c-red-bg); }
|
||||||
|
|
||||||
/* ───── floating dropdown menu ───── */
|
/* ───── floating dropdown menu ───── */
|
||||||
/* 单例:position: fixed 逃出 pane overflow 裁剪;右上角触发,向下展开 */
|
/* 单例:position: fixed 逃出 pane overflow 裁剪;右上角触发,向下展开 */
|
||||||
.dd-toggle {
|
.dd-toggle {
|
||||||
padding: 2px 6px; font-size: 14px; line-height: 1;
|
padding: 2px 6px; font-size: 14px; line-height: 1;
|
||||||
background: transparent; border: 1px solid transparent;
|
background: transparent; border: 1px solid transparent;
|
||||||
color: var(--muted); border-radius: 3px; cursor: pointer;
|
color: var(--muted); border-radius: var(--r-sm); cursor: pointer;
|
||||||
}
|
}
|
||||||
.dd-toggle:hover { background: var(--hover); color: var(--text); border-color: var(--border); }
|
.dd-toggle:hover { background: var(--hover); color: var(--text); border-color: var(--border); }
|
||||||
#floating-menu {
|
#floating-menu {
|
||||||
display: none; position: fixed;
|
display: none; position: fixed;
|
||||||
min-width: 132px; background: #fff;
|
min-width: 132px; background: #fff;
|
||||||
border: 1px solid var(--border); border-radius: 6px;
|
border: 1px solid var(--border); border-radius: var(--r-md);
|
||||||
box-shadow: 0 4px 14px rgba(0,0,0,0.12);
|
box-shadow: 0 4px 14px rgba(0,0,0,0.12);
|
||||||
z-index: 60; padding: 4px 0;
|
z-index: 60; padding: 4px 0;
|
||||||
}
|
}
|
||||||
|
|
@ -258,11 +258,9 @@
|
||||||
.dd-item:hover { background: var(--hover); }
|
.dd-item:hover { background: var(--hover); }
|
||||||
.dd-item:disabled { color: var(--muted); cursor: not-allowed; opacity: 0.55; }
|
.dd-item:disabled { color: var(--muted); cursor: not-allowed; opacity: 0.55; }
|
||||||
.dd-item:disabled:hover { background: transparent; }
|
.dd-item:disabled:hover { background: transparent; }
|
||||||
.dd-item.act-complete { color: #2e7d32; }
|
.dd-item.act-complete, .dd-item.act-download { color: var(--c-green); }
|
||||||
.dd-item.act-abandon { color: #c77800; }
|
.dd-item.act-abandon { color: var(--c-orange); }
|
||||||
.dd-item.act-export { color: #1565c0; }
|
.dd-item.act-export, .dd-item.act-rename { color: var(--c-blue); }
|
||||||
.dd-item.act-rename { color: #1565c0; }
|
|
||||||
.dd-item.act-download { color: #2e7d32; }
|
|
||||||
.dd-item.act-delete { color: var(--accent); }
|
.dd-item.act-delete { color: var(--accent); }
|
||||||
|
|
||||||
/* ───── task list ───── */
|
/* ───── task list ───── */
|
||||||
|
|
@ -284,92 +282,82 @@
|
||||||
.task-row .meta .num.right-group { margin-left: auto; } /* 把数字+时间整组挤到右侧 */
|
.task-row .meta .num.right-group { margin-left: auto; } /* 把数字+时间整组挤到右侧 */
|
||||||
.task-row .meta .time-ago { flex-shrink: 0; text-align: right; min-width: 64px; }
|
.task-row .meta .time-ago { flex-shrink: 0; text-align: right; min-width: 64px; }
|
||||||
.task-row .badge {
|
.task-row .badge {
|
||||||
display: inline-block; padding: 0 6px; border-radius: 8px; font-size: 11px;
|
display: inline-block; padding: 0 6px; border-radius: var(--r-md); font-size: 11px;
|
||||||
background: #eef; color: #336;
|
background: #eef; color: #336;
|
||||||
}
|
}
|
||||||
.badge.completed { background: #e8f5e9; color: #2e7d32; }
|
.badge.completed { background: var(--c-green-bg); color: var(--c-green); }
|
||||||
.badge.abandoned { background: #fde9e7; color: var(--accent); }
|
.badge.abandoned { background: var(--accent-soft); color: var(--accent); }
|
||||||
.badge.active { background: #eef; color: #336; }
|
.badge.active { background: #eef; color: #336; }
|
||||||
.empty { padding: 24px; color: var(--muted); text-align: center; font-size: 13px; }
|
.empty { padding: 24px; color: var(--muted); text-align: center; font-size: 13px; }
|
||||||
|
|
||||||
/* ───── chat ───── */
|
/* ───── chat ───── */
|
||||||
#chat-meta { padding: 8px 12px; border-bottom: 1px solid var(--border); background: #fafafa;
|
#chat-meta { padding: 8px 12px; border-bottom: 1px solid var(--border); background: #fafafa;
|
||||||
font-size: 12px; color: var(--muted); display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
|
font-size: 12px; color: var(--muted); display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
|
||||||
#chat-meta .tid { font-family: monospace; color: var(--text); }
|
#chat-meta .tid { font-family: var(--mono); color: var(--text); }
|
||||||
#chat-meta .spacer { flex: 1; }
|
#chat-meta .spacer { flex: 1; }
|
||||||
/* 同 wd 并发软警告 banner — 非阻塞,只提示中间产物互覆风险 */
|
/* 同 wd 并发软警告 banner — 非阻塞,只提示中间产物互覆风险 */
|
||||||
#wd-concurrent-warn { padding: 6px 12px; border-bottom: 1px solid #f0c36d;
|
#wd-concurrent-warn { padding: 6px 12px; border-bottom: 1px solid #f0c36d;
|
||||||
background: #fff8e1; color: #6a4500; font-size: 12px; }
|
background: #fff8e1; color: #6a4500; font-size: 12px; }
|
||||||
#wd-concurrent-warn .tname { font-weight: 600; }
|
#wd-concurrent-warn .tname { font-weight: 600; }
|
||||||
#wd-concurrent-warn .rs { font-family: monospace; opacity: 0.7; }
|
#wd-concurrent-warn .rs { font-family: var(--mono); opacity: 0.7; }
|
||||||
#chat-stream {
|
#chat-stream {
|
||||||
flex: 1; overflow-y: auto; overflow-x: hidden; padding: 12px;
|
flex: 1; overflow-y: auto; overflow-x: hidden; padding: 12px;
|
||||||
display: flex; flex-direction: column; gap: 8px;
|
display: flex; flex-direction: column; gap: 8px;
|
||||||
min-height: 0; /* 同上,允许在 flex 容器里收缩 + 触发自身滚动 */
|
min-height: 0; /* 允许在 flex 容器里收缩 + 触发自身滚动 */
|
||||||
}
|
|
||||||
.msg {
|
|
||||||
border: 1px solid var(--border); border-radius: 6px; padding: 8px 12px;
|
|
||||||
max-width: 92%;
|
|
||||||
}
|
}
|
||||||
|
.msg { border: 1px solid var(--border); border-radius: var(--r-md); padding: 8px 12px; max-width: 92%; }
|
||||||
.msg.user { background: var(--user-bg); align-self: flex-end; }
|
.msg.user { background: var(--user-bg); align-self: flex-end; }
|
||||||
.msg.assistant, .msg.system, .msg.tool, .msg.error { background: var(--asst-bg); align-self: flex-start; }
|
.msg.assistant, .msg.system, .msg.tool, .msg.error { background: var(--asst-bg); align-self: flex-start; }
|
||||||
.msg.error { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
|
.msg.error { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
|
||||||
.cancelled-badge { margin-top: 8px; padding: 4px 10px; font-size: 12px; color: var(--accent); background: var(--accent-soft); border: 1px dashed var(--accent); border-radius: 4px; display: inline-block; }
|
.cancelled-badge { margin-top: 8px; padding: 4px 10px; font-size: 12px; color: var(--accent); background: var(--accent-soft); border: 1px dashed var(--accent); border-radius: var(--r-md); display: inline-block; }
|
||||||
.msg .role { font-size: 11px; color: var(--muted); margin-bottom: 2px; font-family: monospace; }
|
.msg .role { font-size: 11px; color: var(--muted); margin-bottom: 2px; font-family: var(--mono); }
|
||||||
.msg .body { word-wrap: break-word; font-size: 14px; line-height: 1.55; }
|
.msg .body { word-wrap: break-word; font-size: 14px; line-height: 1.55; }
|
||||||
.msg .body.streaming::after { content: "▌"; color: var(--accent); animation: blink 1s infinite; }
|
.msg .body.streaming::after { content: "▌"; color: var(--accent); animation: blink 1s infinite; }
|
||||||
@keyframes blink { 0%,49% { opacity: 1; } 50%,100% { opacity: 0; } }
|
@keyframes blink { 0%,49% { opacity: 1; } 50%,100% { opacity: 0; } }
|
||||||
/* markdown 输出元素紧凑化 */
|
/* markdown 输出:.msg .body 与 file-preview .md-render 共用一组规则 */
|
||||||
.msg .body > :first-child { margin-top: 0; }
|
.msg .body > :first-child, .md-render > :first-child { margin-top: 0; }
|
||||||
.msg .body > :last-child { margin-bottom: 0; }
|
.msg .body > :last-child, .md-render > :last-child { margin-bottom: 0; }
|
||||||
.msg .body p { margin: 0.4em 0; }
|
.msg .body p, .md-render p { margin: 0.4em 0; }
|
||||||
.msg .body h1, .msg .body h2, .msg .body h3, .msg .body h4 {
|
.msg .body h1, .msg .body h2, .msg .body h3, .msg .body h4,
|
||||||
|
.md-render h1, .md-render h2, .md-render h3, .md-render h4 {
|
||||||
margin: 0.8em 0 0.3em; line-height: 1.3;
|
margin: 0.8em 0 0.3em; line-height: 1.3;
|
||||||
}
|
}
|
||||||
.msg .body h1 { font-size: 1.4em; }
|
.msg .body h1, .md-render h1 { font-size: 1.4em; }
|
||||||
.msg .body h2 { font-size: 1.25em; }
|
.msg .body h2, .md-render h2 { font-size: 1.25em; }
|
||||||
.msg .body h3 { font-size: 1.1em; }
|
.msg .body h3, .md-render h3 { font-size: 1.1em; }
|
||||||
.msg .body h4 { font-size: 1em; font-weight: 600; }
|
.msg .body h4, .md-render h4 { font-size: 1em; font-weight: 600; }
|
||||||
.msg .body ul, .msg .body ol { margin: 0.4em 0; padding-left: 1.6em; }
|
.msg .body ul, .msg .body ol, .md-render ul, .md-render ol { margin: 0.4em 0; padding-left: 1.6em; }
|
||||||
.msg .body li { margin: 0.15em 0; }
|
.msg .body li, .md-render li { margin: 0.15em 0; }
|
||||||
.msg .body li > p { margin: 0.15em 0; }
|
.msg .body li > p, .md-render li > p { margin: 0.15em 0; }
|
||||||
.msg .body blockquote {
|
.msg .body blockquote, .md-render blockquote {
|
||||||
margin: 0.4em 0; padding: 4px 12px; border-left: 3px solid var(--accent);
|
margin: 0.4em 0; padding: 4px 12px; border-left: 3px solid var(--accent);
|
||||||
background: var(--accent-soft); color: #555;
|
background: var(--accent-soft); color: #555;
|
||||||
}
|
}
|
||||||
.msg .body code:not(pre code) {
|
.msg .body code:not(pre code), .md-render code:not(pre code) {
|
||||||
background: var(--code-bg); padding: 1px 5px; border-radius: 3px;
|
background: var(--code-bg); padding: 1px 5px; border-radius: var(--r-sm);
|
||||||
font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
|
font-family: var(--mono); font-size: 0.92em;
|
||||||
font-size: 0.92em;
|
|
||||||
}
|
}
|
||||||
.msg .body pre {
|
.msg .body pre, .md-render pre {
|
||||||
margin: 0.5em 0; padding: 10px; background: #f6f8fa; border-radius: 4px;
|
margin: 0.5em 0; padding: 10px; background: #f6f8fa; border-radius: var(--r-md);
|
||||||
overflow-x: auto; font-size: 12.5px; line-height: 1.4;
|
overflow-x: auto; font-size: 12.5px; line-height: 1.4;
|
||||||
}
|
}
|
||||||
.msg .body pre code {
|
.msg .body pre code, .md-render pre code { font-family: var(--mono); background: transparent; padding: 0; }
|
||||||
font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
|
.msg .body table, .md-render table { border-collapse: collapse; margin: 0.5em 0; font-size: 13px; }
|
||||||
background: transparent; padding: 0;
|
.msg .body th, .msg .body td, .md-render th, .md-render td {
|
||||||
}
|
|
||||||
.msg .body table {
|
|
||||||
border-collapse: collapse; margin: 0.5em 0; font-size: 13px;
|
|
||||||
}
|
|
||||||
.msg .body th, .msg .body td {
|
|
||||||
border: 1px solid var(--border); padding: 4px 8px;
|
border: 1px solid var(--border); padding: 4px 8px;
|
||||||
}
|
}
|
||||||
.msg .body th { background: #fafafa; font-weight: 600; }
|
.msg .body th, .md-render th { background: #fafafa; font-weight: 600; }
|
||||||
.msg .body a { color: var(--accent); }
|
.msg .body a, .md-render a { color: var(--accent); }
|
||||||
.msg .body img { max-width: 100%; }
|
.msg .body img, .md-render img { max-width: 100%; }
|
||||||
.msg .body hr { border: none; border-top: 1px solid var(--border); margin: 0.8em 0; }
|
.msg .body hr, .md-render hr { border: none; border-top: 1px solid var(--border); margin: 0.8em 0; }
|
||||||
.tool-call {
|
.tool-call { margin-top: 6px; font-family: var(--mono); font-size: 12px; }
|
||||||
margin-top: 6px; font-family: ui-monospace, Consolas, monospace; font-size: 12px;
|
|
||||||
}
|
|
||||||
.tool-call summary {
|
.tool-call summary {
|
||||||
cursor: pointer; padding: 4px 6px; background: var(--code-bg); border-radius: 3px;
|
cursor: pointer; padding: 4px 6px; background: var(--code-bg); border-radius: var(--r-sm);
|
||||||
color: #555;
|
color: #555;
|
||||||
}
|
}
|
||||||
.tool-call summary:hover { background: #ebebeb; }
|
.tool-call summary:hover { background: #ebebeb; }
|
||||||
.tool-call pre {
|
.tool-call pre {
|
||||||
margin: 4px 0 0; padding: 8px; background: var(--code-bg); border-radius: 3px;
|
margin: 4px 0 0; padding: 8px; background: var(--code-bg); border-radius: var(--r-sm);
|
||||||
overflow-x: auto; max-height: 300px; white-space: pre-wrap;
|
overflow-x: auto; max-height: 300px; white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
/* media tool 摘要 banner(model / size / cost / elapsed,折叠态也可见) */
|
/* media tool 摘要 banner(model / size / cost / elapsed,折叠态也可见) */
|
||||||
|
|
@ -378,36 +366,31 @@
|
||||||
margin-left: 8px; font-size: 11px; vertical-align: middle;
|
margin-left: 8px; font-size: 11px; vertical-align: middle;
|
||||||
}
|
}
|
||||||
.tool-banner .kv {
|
.tool-banner .kv {
|
||||||
padding: 1px 6px; border-radius: 3px; background: #fff;
|
padding: 1px 6px; border-radius: var(--r-sm); background: #fff;
|
||||||
border: 1px solid var(--border); color: #555;
|
border: 1px solid var(--border); color: #555;
|
||||||
}
|
}
|
||||||
.tool-banner .kv.cost { color: #b34a4a; border-color: #e0c4c4; }
|
.tool-banner .kv.cost { color: #b34a4a; border-color: #e0c4c4; }
|
||||||
.tool-banner .kv.model { color: var(--accent); border-color: #e0c4c4; }
|
.tool-banner .kv.model { color: var(--accent); border-color: #e0c4c4; }
|
||||||
/* ───── artifact chips(对话内点产物预览/下载) ───── */
|
/* ───── artifact chips(对话内点产物预览/下载) ───── */
|
||||||
.artifact-bar {
|
.artifact-bar { margin-top: 4px; display: flex; flex-wrap: wrap; gap: 4px; font-family: var(--mono); }
|
||||||
margin-top: 4px; display: flex; flex-wrap: wrap; gap: 4px;
|
|
||||||
font-family: ui-monospace, Consolas, monospace;
|
|
||||||
}
|
|
||||||
.art-chip {
|
.art-chip {
|
||||||
font: inherit; font-size: 11px; line-height: 1.4;
|
font: inherit; font-size: 11px; line-height: 1.4;
|
||||||
padding: 2px 8px 2px 6px; border: 1px solid var(--border);
|
padding: 2px 8px 2px 6px; border: 1px solid var(--border);
|
||||||
background: #fff; color: #555; border-radius: 999px; cursor: pointer;
|
background: #fff; color: #555; border-radius: 999px; cursor: pointer;
|
||||||
max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||||||
display: inline-flex; align-items: center; gap: 4px;
|
display: inline-flex; align-items: center; gap: 4px;
|
||||||
transition: color .12s, border-color .12s, background .12s;
|
transition: var(--t);
|
||||||
}
|
}
|
||||||
.art-chip::before { content: "📄"; font-size: 11px; }
|
.art-chip::before { content: "📄"; font-size: 11px; }
|
||||||
.art-chip:hover {
|
.art-chip:hover { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
|
||||||
background: var(--accent-soft); border-color: var(--accent); color: var(--accent);
|
|
||||||
}
|
|
||||||
/* 内联图片/视频:产物 chip 替代,fetch 完直接展示 */
|
/* 内联图片/视频:产物 chip 替代,fetch 完直接展示 */
|
||||||
.art-media {
|
.art-media {
|
||||||
border: 1px solid var(--border); border-radius: 6px; overflow: hidden;
|
border: 1px solid var(--border); border-radius: var(--r-md); overflow: hidden;
|
||||||
background: #fff; display: inline-block; line-height: 0;
|
background: #fff; display: inline-block; line-height: 0;
|
||||||
}
|
}
|
||||||
.art-media .art-media-loading, .art-media .art-media-error {
|
.art-media .art-media-loading, .art-media .art-media-error {
|
||||||
display: inline-block; padding: 6px 10px; font-size: 11px;
|
display: inline-block; padding: 6px 10px; font-size: 11px;
|
||||||
color: var(--muted); line-height: 1.4; font-family: ui-monospace, Consolas, monospace;
|
color: var(--muted); line-height: 1.4; font-family: var(--mono);
|
||||||
}
|
}
|
||||||
.art-media .art-media-error { color: #b34a4a; }
|
.art-media .art-media-error { color: #b34a4a; }
|
||||||
.art-media img {
|
.art-media img {
|
||||||
|
|
@ -437,7 +420,7 @@
|
||||||
}
|
}
|
||||||
.file-row:hover { background: var(--hover); }
|
.file-row:hover { background: var(--hover); }
|
||||||
.file-row .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
.file-row .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||||
.file-row .size { font-size: 11px; color: var(--muted); font-family: monospace; }
|
.file-row .size { font-size: 11px; color: var(--muted); font-family: var(--mono); }
|
||||||
.ico-dir::before { content: "▸ "; color: var(--accent); }
|
.ico-dir::before { content: "▸ "; color: var(--accent); }
|
||||||
.ico-file::before { content: "· "; color: var(--muted); }
|
.ico-file::before { content: "· "; color: var(--muted); }
|
||||||
|
|
||||||
|
|
@ -453,16 +436,10 @@
|
||||||
#file-droparea.show { display: flex; }
|
#file-droparea.show { display: flex; }
|
||||||
|
|
||||||
/* ───── source picker modal(选入文件:勾源 + 复制/移动到主区当前目录) ───── */
|
/* ───── source picker modal(选入文件:勾源 + 复制/移动到主区当前目录) ───── */
|
||||||
#src-picker-modal {
|
#src-picker-modal { z-index: 95; }
|
||||||
position: fixed; inset: 0; background: rgba(0,0,0,0.4);
|
|
||||||
display: none; align-items: center; justify-content: center; z-index: 95;
|
|
||||||
}
|
|
||||||
#src-picker-modal.show { display: flex; }
|
|
||||||
#src-picker-modal .card {
|
#src-picker-modal .card {
|
||||||
background: var(--panel); border-radius: 8px;
|
|
||||||
width: 560px; max-height: 82vh;
|
width: 560px; max-height: 82vh;
|
||||||
display: flex; flex-direction: column;
|
display: flex; flex-direction: column;
|
||||||
box-shadow: 0 12px 32px rgba(0,0,0,.18);
|
|
||||||
}
|
}
|
||||||
#src-picker-modal h3 {
|
#src-picker-modal h3 {
|
||||||
margin: 0; padding: 14px 18px; font-size: 16px;
|
margin: 0; padding: 14px 18px; font-size: 16px;
|
||||||
|
|
@ -477,19 +454,12 @@
|
||||||
padding: 8px 18px; font-size: 12px; color: var(--muted);
|
padding: 8px 18px; font-size: 12px; color: var(--muted);
|
||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
}
|
}
|
||||||
#sp-crumbs {
|
#sp-crumbs { padding: 8px 14px; border-bottom: 1px solid var(--border); font-size: 12px; background: #fafafa; }
|
||||||
padding: 8px 14px; border-bottom: 1px solid var(--border);
|
|
||||||
font-size: 12px; background: #fafafa;
|
|
||||||
}
|
|
||||||
#sp-crumbs a { margin-right: 4px; }
|
#sp-crumbs a { margin-right: 4px; }
|
||||||
#sp-list {
|
#sp-list { flex: 1; overflow: auto; min-height: 240px; max-height: 50vh; }
|
||||||
flex: 1; overflow: auto;
|
|
||||||
min-height: 240px; max-height: 50vh;
|
|
||||||
}
|
|
||||||
#sp-list .sp-row {
|
#sp-list .sp-row {
|
||||||
padding: 6px 14px; border-bottom: 1px solid var(--border);
|
padding: 6px 14px; border-bottom: 1px solid var(--border);
|
||||||
display: flex; align-items: center; gap: 8px;
|
display: flex; align-items: center; gap: 8px; font-size: 13px;
|
||||||
font-size: 13px;
|
|
||||||
}
|
}
|
||||||
#sp-list .sp-row:hover { background: var(--hover); }
|
#sp-list .sp-row:hover { background: var(--hover); }
|
||||||
#sp-list .sp-row .sp-cb { flex-shrink: 0; margin: 0; }
|
#sp-list .sp-row .sp-cb { flex-shrink: 0; margin: 0; }
|
||||||
|
|
@ -498,42 +468,24 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
#sp-list .sp-row.disabled .sp-name { color: var(--muted); cursor: not-allowed; }
|
#sp-list .sp-row.disabled .sp-name { color: var(--muted); cursor: not-allowed; }
|
||||||
#sp-list .sp-row .sp-size { font-size: 11px; color: var(--muted); font-family: monospace; }
|
#sp-list .sp-row .sp-size { font-size: 11px; color: var(--muted); font-family: var(--mono); }
|
||||||
#sp-list .empty { padding: 18px; color: var(--muted); text-align: center; font-size: 12px; }
|
|
||||||
#src-picker-modal .actions {
|
#src-picker-modal .actions {
|
||||||
padding: 12px 18px; border-top: 1px solid var(--border);
|
padding: 12px 18px; border-top: 1px solid var(--border);
|
||||||
display: flex; gap: 8px; align-items: center;
|
display: flex; gap: 8px; align-items: center;
|
||||||
}
|
}
|
||||||
#src-picker-modal .actions .count {
|
#src-picker-modal .actions .count { flex: 1; font-size: 12px; color: var(--muted); }
|
||||||
flex: 1; font-size: 12px; color: var(--muted);
|
|
||||||
}
|
|
||||||
#sp-copy:hover:not(:disabled) { color: #1565c0; border-color: #aed6f1; background: #ebf5fb; }
|
|
||||||
#sp-move:hover:not(:disabled) { color: #c77800; border-color: #f5cba7; background: #fef5e7; }
|
|
||||||
#sp-copy:disabled, #sp-move:disabled { opacity: 0.4; cursor: not-allowed; }
|
|
||||||
|
|
||||||
/* ───── new task modal ───── */
|
/* ───── new task modal ───── */
|
||||||
#new-task-modal {
|
#new-task-modal { z-index: 80; }
|
||||||
position: fixed; inset: 0; background: rgba(0,0,0,0.4);
|
#new-task-modal .card { padding: 20px; width: 420px; }
|
||||||
display: none; align-items: center; justify-content: center; z-index: 80;
|
|
||||||
}
|
|
||||||
#new-task-modal.show { display: flex; }
|
|
||||||
#new-task-modal .card {
|
|
||||||
background: var(--panel); padding: 20px; border-radius: 8px;
|
|
||||||
width: 420px; box-shadow: 0 12px 32px rgba(0,0,0,.18);
|
|
||||||
}
|
|
||||||
#new-task-modal h3 { margin: 0 0 12px; font-size: 16px; }
|
#new-task-modal h3 { margin: 0 0 12px; font-size: 16px; }
|
||||||
#new-task-modal label { display: block; margin-top: 8px; font-size: 12px; color: var(--muted); }
|
#new-task-modal label { display: block; margin-top: 8px; font-size: 12px; color: var(--muted); }
|
||||||
#new-task-modal .err { color: var(--accent); font-size: 12px; margin-top: 8px; min-height: 1em; }
|
#new-task-modal .err { color: var(--accent); font-size: 12px; margin-top: 8px; min-height: 1em; }
|
||||||
#new-task-modal .actions { margin-top: 14px; display: flex; gap: 8px; justify-content: flex-end; }
|
#new-task-modal .actions { margin-top: 14px; display: flex; gap: 8px; justify-content: flex-end; }
|
||||||
|
|
||||||
/* ───── file preview modal ───── */
|
/* ───── file preview modal(略深的遮罩 0.5 + 更重阴影) ───── */
|
||||||
#file-preview-modal {
|
#file-preview-modal { background: rgba(0,0,0,0.5); z-index: 90; }
|
||||||
position: fixed; inset: 0; background: rgba(0,0,0,0.5);
|
|
||||||
display: none; align-items: center; justify-content: center; z-index: 90;
|
|
||||||
}
|
|
||||||
#file-preview-modal.show { display: flex; }
|
|
||||||
#file-preview-modal .card {
|
#file-preview-modal .card {
|
||||||
background: var(--panel); border-radius: 8px;
|
|
||||||
width: 90vw; height: 90vh; max-width: 1200px;
|
width: 90vw; height: 90vh; max-width: 1200px;
|
||||||
display: flex; flex-direction: column;
|
display: flex; flex-direction: column;
|
||||||
box-shadow: 0 12px 32px rgba(0,0,0,.22);
|
box-shadow: 0 12px 32px rgba(0,0,0,.22);
|
||||||
|
|
@ -546,15 +498,9 @@
|
||||||
flex: 1; font-weight: 500; overflow: hidden;
|
flex: 1; font-weight: 500; overflow: hidden;
|
||||||
text-overflow: ellipsis; white-space: nowrap;
|
text-overflow: ellipsis; white-space: nowrap;
|
||||||
}
|
}
|
||||||
#file-preview-modal .body {
|
#file-preview-modal .body { flex: 1; overflow: auto; padding: 12px; position: relative; }
|
||||||
flex: 1; overflow: auto; padding: 12px; position: relative;
|
#file-preview-modal .body.center { display: flex; align-items: center; justify-content: center; }
|
||||||
}
|
#file-preview-modal .body .ph { color: var(--muted); font-size: 13px; text-align: center; }
|
||||||
#file-preview-modal .body.center {
|
|
||||||
display: flex; align-items: center; justify-content: center;
|
|
||||||
}
|
|
||||||
#file-preview-modal .body .ph {
|
|
||||||
color: var(--muted); font-size: 13px; text-align: center;
|
|
||||||
}
|
|
||||||
#file-preview-modal .body img.preview-img {
|
#file-preview-modal .body img.preview-img {
|
||||||
max-width: 100%; max-height: 100%; object-fit: contain;
|
max-width: 100%; max-height: 100%; object-fit: contain;
|
||||||
display: block; margin: 0 auto;
|
display: block; margin: 0 auto;
|
||||||
|
|
@ -562,23 +508,14 @@
|
||||||
#file-preview-modal .body video.preview-video {
|
#file-preview-modal .body video.preview-video {
|
||||||
max-width: 100%; max-height: 100%; display: block; margin: 0 auto; outline: none;
|
max-width: 100%; max-height: 100%; display: block; margin: 0 auto; outline: none;
|
||||||
}
|
}
|
||||||
#file-preview-modal .body iframe.preview-frame {
|
#file-preview-modal .body iframe.preview-frame { width: 100%; height: 100%; border: 0; }
|
||||||
width: 100%; height: 100%; border: 0;
|
|
||||||
}
|
|
||||||
#file-preview-modal .body pre.preview-text {
|
#file-preview-modal .body pre.preview-text {
|
||||||
margin: 0; padding: 8px; background: var(--code-bg);
|
margin: 0; padding: 8px; background: var(--code-bg);
|
||||||
border-radius: 4px; white-space: pre-wrap; word-break: break-word;
|
border-radius: var(--r-md); white-space: pre-wrap; word-break: break-word;
|
||||||
font-family: ui-monospace, "SF Mono", Consolas, monospace;
|
font-family: var(--mono); font-size: 12px; line-height: 1.5;
|
||||||
font-size: 12px; line-height: 1.5;
|
|
||||||
}
|
}
|
||||||
#file-preview-modal .body .md-render {
|
/* .md-render 通用样式已与 .msg .body 合并到上方 chat 段;这里只保留 file-preview 专属 */
|
||||||
max-width: 860px; margin: 0 auto; line-height: 1.7;
|
#file-preview-modal .body .md-render { max-width: 860px; margin: 0 auto; line-height: 1.7; }
|
||||||
}
|
|
||||||
#file-preview-modal .body .md-render pre {
|
|
||||||
background: var(--code-bg); padding: 10px; border-radius: 4px; overflow: auto;
|
|
||||||
}
|
|
||||||
#file-preview-modal .body .md-render code { background: var(--code-bg); padding: 1px 4px; border-radius: 3px; }
|
|
||||||
#file-preview-modal .body .md-render pre code { background: transparent; padding: 0; }
|
|
||||||
#file-preview-modal .body .docx-host { background: #fff; }
|
#file-preview-modal .body .docx-host { background: #fff; }
|
||||||
#file-preview-modal .body .xlsx-tabs {
|
#file-preview-modal .body .xlsx-tabs {
|
||||||
display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 8px;
|
display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 8px;
|
||||||
|
|
@ -587,12 +524,8 @@
|
||||||
#file-preview-modal .body .xlsx-tabs button.active {
|
#file-preview-modal .body .xlsx-tabs button.active {
|
||||||
background: var(--accent-soft); border-color: var(--accent); color: var(--accent);
|
background: var(--accent-soft); border-color: var(--accent); color: var(--accent);
|
||||||
}
|
}
|
||||||
#file-preview-modal .body .xlsx-sheet {
|
#file-preview-modal .body .xlsx-sheet { overflow: auto; }
|
||||||
overflow: auto;
|
#file-preview-modal .body .xlsx-sheet table { border-collapse: collapse; font-size: 12px; }
|
||||||
}
|
|
||||||
#file-preview-modal .body .xlsx-sheet table {
|
|
||||||
border-collapse: collapse; font-size: 12px;
|
|
||||||
}
|
|
||||||
#file-preview-modal .body .xlsx-sheet td, #file-preview-modal .body .xlsx-sheet th {
|
#file-preview-modal .body .xlsx-sheet td, #file-preview-modal .body .xlsx-sheet th {
|
||||||
border: 1px solid var(--border); padding: 4px 8px; white-space: nowrap;
|
border: 1px solid var(--border); padding: 4px 8px; white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
@ -649,7 +582,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ───── admin add-user modal ───── -->
|
<!-- ───── admin add-user modal ───── -->
|
||||||
<div id="admin-modal">
|
<div id="admin-modal" class="modal">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h3>添加用户</h3>
|
<h3>添加用户</h3>
|
||||||
<label for="ad-email">邮箱</label>
|
<label for="ad-email">邮箱</label>
|
||||||
|
|
@ -759,7 +692,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ───── source picker modal(选入文件:勾源 → 复制/移动到主区当前目录) ───── -->
|
<!-- ───── source picker modal(选入文件:勾源 → 复制/移动到主区当前目录) ───── -->
|
||||||
<div id="src-picker-modal">
|
<div id="src-picker-modal" class="modal">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h3>
|
<h3>
|
||||||
<span>选入到</span>
|
<span>选入到</span>
|
||||||
|
|
@ -781,7 +714,7 @@
|
||||||
<div id="floating-menu"></div>
|
<div id="floating-menu"></div>
|
||||||
|
|
||||||
<!-- ───── new task modal ───── -->
|
<!-- ───── new task modal ───── -->
|
||||||
<div id="new-task-modal">
|
<div id="new-task-modal" class="modal">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h3>新建任务</h3>
|
<h3>新建任务</h3>
|
||||||
<label for="nt-name">任务名(必填)</label>
|
<label for="nt-name">任务名(必填)</label>
|
||||||
|
|
@ -809,7 +742,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ───── file preview modal ───── -->
|
<!-- ───── file preview modal ───── -->
|
||||||
<div id="file-preview-modal">
|
<div id="file-preview-modal" class="modal">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="hdr">
|
<div class="hdr">
|
||||||
<span class="name" id="fp-name"></span>
|
<span class="name" id="fp-name"></span>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue