Refine mobile conversation layout

This commit is contained in:
caoqianming 2026-07-29 15:13:51 +08:00
parent 369c74483c
commit 02b278b175
6 changed files with 94 additions and 65 deletions

View File

@ -5,6 +5,10 @@
> 所以不是每个版本号都有条目。条目格式 `## <版本> — <日期>`,新条目加在最上面。
> 工程口径的完整记录见 `PROGRESS.md` / git log。
## 0.60.10 — 2026-07-29
- 网页工作台恢复清爽的中性白色配色,助手回复回到左侧阅读轴;手机端进一步缩小顶部页签、操作按钮和输入区,并移除默认的文件保存位置提示,为对话正文留出更多空间。
## 0.60.9 — 2026-07-29
- 网页工作台改用更温和的暖白配色,任务与文件列表的分隔更加清楚;助手回复按完整轮次形成统一阅读块,手机端输入区也改为更紧凑的图标操作布局。

View File

@ -2,7 +2,7 @@
> 配合 `DESIGN.md`。本文件只记 phase 状态、决策偏差、文件量、下一步。每条 1-2 句:做了啥 + 关键判断;细节查 `git log` / `git diff` / `DESIGN §7.9`
最后更新:2026-07-29(Web 工作台视觉复核修正,bump 0.60.9)
最后更新:2026-07-29(Web 工作台移动端空间优化,bump 0.60.10)
---
@ -23,6 +23,7 @@
### 2026-07-29
- **07-29 / 0.60.10 / Web 工作台移动端空间优化**:根据第二轮手机实图反馈把暖白/浅米灰改回中性白色桌面助手回答、工具卡与任务进度恢复左侧阅读轴手机端压缩顶栏、Tab、任务操作区、模型区、消息间距和 composer高频操作键由 44px 收至 40px、输入框最低高度由 64px 收至 52px并隐藏空闲态“请选择文件保存位置/就绪”占位行,运行、上传与错误等有效状态提示继续按需显示。相关 Python 21 项 + Node 5 项及 JS 语法、diff 格式检查通过;无 API、schema、migration 或依赖变化。
- **07-29 / 0.60.9 / Web 工作台视觉复核修正(桌面 + 手机实图)**:据上线截图把冷蓝灰改为暖白/浅米灰;任务与文件行恢复明确分隔,助手消息收进居中 52rem 文档型回答块,工具与进度对齐同一阅读轨道;同时修掉 `task_progress`-only assistant 被过滤工具后仍留下空“助手”壳。手机端 composer 改为独立状态行 + 3 个 44px SVG 图标键 + 发送键,缩短 placeholder、加入安全区并压缩操作/模型区;录音与润色状态改只更新 label/ARIA不再覆盖 SVG DOM。相关 Python 21 项 + Node 5 项及 JS 语法、HTML/SVG 结构、CSS 括号检查通过;无 API、schema、migration 或依赖变化。
- **07-29 / 0.60.8 / Web 工作台 Visual Polish v1**:新增零构建 `web/static/ui.css` 作为内部轻量视觉基础层,集中颜色、间距、圆角、阴影与 focus/disabled 等控件状态;收敛三栏层级、任务/资源导航、对话正文与工具过程块、输入区、文件栏、modal/toast 及 ≤640px 触控尺寸,不改 DOM 契约、API 或业务交互。新增 CSS 文件接入、MIME 与 `no-cache` 回归测试;相关 Python 20 项 + Node 5 项通过,浏览器连接不可用故截图级视觉验收留真实页面复核。
- **07-29 / 0.60.7 / 组合框内直接新建工作目录**:新对话目录 combobox 增加 allow-create 语义:输入时继续过滤已有目录,无完全同名项时在同一下拉内提供“创建工作目录「名称」”,明确选择后才进入新建状态,失焦搜索词不会误提交;删除外部新建按钮与二级输入框。纯前端改动,无 API、schema、migration 或目录绑定语义变化;全量 387 测试通过17 项按环境跳过)。

View File

@ -1,3 +1,3 @@
# zcbot 版本号单一事实源:web/app.py 的 FastAPI version、/healthz 返回、前端展示都引这里。
# 改版本只动这一行。
__version__ = "0.60.9"
__version__ = "0.60.10"

View File

@ -66,6 +66,8 @@ class StaticVendorTests(unittest.TestCase):
self.assertIn('aria-label="润色提示词"', html)
self.assertIn("hasVisibleAssistantContent", frontend)
self.assertIn('input.placeholder = mqPhone.matches', frontend)
self.assertIn("#chat-hint:empty", css)
self.assertNotIn("请选择文件保存位置", frontend)
def test_frontend_surfaces_context_and_cache_stats(self) -> None:
src = _frontend_source()

View File

@ -403,7 +403,7 @@ let _draftFolderActiveIndex = -1;
function syncDraftAction() {
const ready = !!draftWorkingDir();
setActionMode(ready ? "idle" : "loading");
$("chat-hint").textContent = ready ? "输入消息开始对话" : "请选择文件保存位置";
$("chat-hint").textContent = "";
const note = $("new-chat-dir-note");
if (note) {
note.textContent = ready
@ -685,6 +685,7 @@ export async function selectTask(tid) {
renderMessages(state.loadedMessages); // 内部含 renderPersistedRunTerminal(须在 taskMeta 赋值后)
renderChatMeta();
applyChannelComposerLock(meta);
$("chat-hint").textContent = "";
if (meta.run_status === "running" || meta.run_status === "cancelling") {
ensureRunningTaskSubscribed(tid, `/v1/tasks/${tid}/events`, meta);
} else {
@ -2457,7 +2458,7 @@ async function sendMessage(overrideText) {
: e.message;
appendErrorCard(msg);
setActionMode("idle");
$("chat-hint").textContent = "就绪";
$("chat-hint").textContent = "";
}
}
@ -2556,7 +2557,7 @@ async function fetchSse(url, run) {
state.streaming = state.liveRuns.size > 0;
syncTaskRowRunIndicator(ctx.taskId); // 先按本地态即时清标识,loadTaskList 随后带回服务端真相(如 error)
if (state.taskId === ctx.taskId) {
hint.textContent = ctx.lastUsageHint || "就绪";
hint.textContent = ctx.lastUsageHint || "";
setActionMode("idle");
}
}

View File

@ -11,16 +11,16 @@
color-scheme: light;
/* Neutral workspace palette */
--bg: #f6f4f1;
--bg: #f7f7f7;
--panel: #ffffff;
--panel-subtle: #fbfaf8;
--panel-muted: #f7f4f0;
--border: #e2ddd7;
--border-soft: #ede8e2;
--list-divider: #ddd7d0;
--text: #292623;
--text-strong: #1c1a18;
--muted: #756f69;
--panel-subtle: #fafafa;
--panel-muted: #f5f5f5;
--border: #e1e3e5;
--border-soft: #eceeef;
--list-divider: #d9dde0;
--text: #242424;
--text-strong: #171717;
--muted: #73777c;
/* Institute red is deliberately reserved for primary emphasis. */
--accent: #b83a31;
@ -28,9 +28,9 @@
--accent-soft: #fbecea;
--accent-ring: rgba(184, 58, 49, 0.16);
--hover: #f5f1ed;
--code-bg: #f6f3ef;
--user-bg: #f5f1eb;
--hover: #f2f3f4;
--code-bg: #f5f5f5;
--user-bg: #f2f6fa;
--asst-bg: #ffffff;
--c-green: #238653;
@ -98,7 +98,7 @@ button.small {
}
button:hover:not(:disabled) {
border-color: #cdc5bd;
border-color: #cbd1d6;
}
button.primary {
@ -137,7 +137,7 @@ select {
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):hover,
textarea:hover,
select:hover {
border-color: #c9c1b9;
border-color: #c7cdd2;
}
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):focus,
@ -149,7 +149,7 @@ select:focus {
}
::placeholder {
color: #9b958f;
color: #999fa5;
}
/* Application shell */
@ -203,7 +203,7 @@ header .who {
}
.splitter::before {
background: #d9d3cc;
background: #d7dce0;
}
.pane-head {
@ -225,7 +225,7 @@ header .who {
#task-scroll,
#file-list {
scrollbar-color: #cec7bf transparent;
scrollbar-color: #cbd1d6 transparent;
scrollbar-width: thin;
}
@ -337,8 +337,8 @@ header .who {
line-height: 1.7;
}
/* Conversation: one centred reading rail, with each assistant turn grouped as
a document block rather than a floating chat label. */
/* Conversation: one left-anchored reading rail, with each assistant turn grouped
as a document block rather than a floating chat label. */
#chat-meta {
min-height: 40px;
@ -369,12 +369,12 @@ header .who {
.msg.assistant {
width: min(100%, 52rem);
max-width: min(100%, 52rem);
align-self: center;
align-self: flex-start;
padding: 16px 18px;
border: 1px solid var(--border-soft);
border-left: 3px solid #cbc3bb;
border-left: 3px solid #cbd0d4;
border-radius: var(--r-lg);
background: #fffdfa;
background: #ffffff;
}
.msg.assistant.live-run {
@ -401,7 +401,7 @@ header .who {
display: flex;
align-items: center;
gap: 7px;
color: #6d665f;
color: #656b70;
}
.msg.assistant > .role::before {
@ -417,7 +417,7 @@ header .who {
.msg.tool {
width: min(100%, 52rem);
max-width: min(100%, 52rem);
align-self: center;
align-self: flex-start;
padding: 0 18px;
border: 0;
background: transparent;
@ -430,7 +430,7 @@ header .who {
#task-progress-dock .task-progress {
width: min(100%, 52rem);
max-width: 52rem;
margin: 0 auto;
margin: 0;
}
.msg .body {
@ -456,7 +456,7 @@ header .who {
.tool-call,
.reasoning {
color: #5f5851;
color: #555b60;
}
.tool-call summary,
@ -490,13 +490,17 @@ header .who {
padding: 10px 12px;
line-height: 1.6;
border-radius: var(--r-lg);
background: #fffdfa;
background: #ffffff;
}
#chat-form .row {
align-items: center;
}
#chat-hint:empty {
display: none;
}
.composer-spacer {
flex: 1;
}
@ -538,7 +542,7 @@ header .who {
}
.file-row .name {
color: #332f2b;
color: #303438;
}
.storage-foot {
@ -549,7 +553,7 @@ header .who {
.storage-foot .bar {
height: 5px;
background: #e8e3de;
background: #e5e8ea;
}
/* Dialogs and notifications */
@ -612,37 +616,45 @@ header .who {
@media (max-width: 640px) {
header {
min-height: 46px;
padding: 7px 10px;
min-height: 42px;
padding: 5px 9px;
}
.pane-head {
min-height: 42px;
min-height: 36px;
}
.mobile-tabs {
gap: 6px;
gap: 5px;
}
.mobile-tabs button {
min-height: 38px;
padding: 6px 8px;
min-height: 34px;
padding: 4px 7px;
font-size: 11.5px;
}
#hd-admin {
padding: 4px 8px;
font-size: 11px;
}
#pane-mid > .pane-head {
min-height: 38px;
padding: 5px 10px;
min-height: 34px;
padding: 4px 8px;
}
#pane-mid > .pane-head > button {
min-height: 30px;
min-height: 28px;
padding: 3px 8px;
font-size: 11.5px;
}
#chat-meta {
min-height: auto;
padding: 7px 10px;
column-gap: 7px;
row-gap: 7px;
padding: 5px 8px;
column-gap: 5px;
row-gap: 5px;
}
#chat-meta > .spacer {
@ -658,15 +670,24 @@ header .who {
#chat-meta select {
width: 100% !important;
max-width: none;
min-height: 30px;
padding: 2px 6px;
font-size: 12px;
}
#chat-meta button {
min-height: 30px;
padding: 2px 7px;
font-size: 11.5px;
}
#task-progress-dock {
padding: 6px 10px;
padding: 5px 8px;
}
#chat-stream {
gap: 14px;
padding: 14px 12px 18px;
gap: 11px;
padding: 10px 10px 12px;
}
.msg {
@ -676,7 +697,7 @@ header .who {
.msg.assistant {
width: 100%;
max-width: 100%;
padding: 13px 14px;
padding: 10px 12px;
}
.msg.tool {
@ -691,24 +712,23 @@ header .who {
}
#chat-form {
padding: 10px;
padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
padding: 8px 9px;
padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
}
#chat-input {
min-height: 64px;
min-height: 52px;
}
#chat-form .row {
flex-wrap: wrap;
justify-content: flex-end;
gap: 8px;
gap: 6px;
}
#chat-hint {
order: -1;
flex: 1 0 100%;
min-height: 18px;
line-height: 18px;
}
@ -717,16 +737,16 @@ header .who {
}
#chat-form .row .composer-tool {
width: 44px;
min-width: 44px;
height: 44px;
min-height: 44px;
width: 40px;
min-width: 40px;
height: 40px;
min-height: 40px;
padding: 0;
}
.composer-tool svg {
width: 19px;
height: 19px;
width: 18px;
height: 18px;
}
.composer-tool .composer-label {
@ -742,10 +762,11 @@ header .who {
}
#chat-action {
width: 72px;
min-width: 72px;
height: 44px;
min-height: 44px;
width: 68px;
min-width: 68px;
height: 40px;
min-height: 40px;
padding: 5px 12px;
}
.modal {