diff --git a/CHANGELOG.md b/CHANGELOG.md index 336df0a..565dd40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ > 主题:**控制台「去命令行化」** —— 双击应用即用,启停/重启/更新/日志/托盘常驻/开机自启全部在界面里完成。 > 目标原文:「不再打开命令行窗口,运行应用之后,有启动、停止、重启、检查更新等功能, > 有日志功能,可以后台运行和开机自启等等功能」。 +> +> 末段另含两轮纯界面调整:**一律不使用图标**(emoji 在部分渲染器里退化成豆腐块)、 +> **配色收敛为「简约白 / 高级灰」两套中性灰阶主题**。 ### 新增 —— 本机被控端托管(`apps/console/src-tauri/src/agent.rs`,约 560 行) @@ -109,6 +112,28 @@ > 它们是**程序输出内容**,会原样出现在「服务日志」页里,但不是界面元素; > ③ 控件的结构性部件(下拉箭头、折叠箭头、输入框清除钮、表格排序箭头)。 +### 变更 —— 配色收敛为两套中性灰阶主题 + +- **两套可切换主题:`简约白`(浅)与 `高级灰`(深)**,侧栏底部一行切换,选择存 `localStorage`。 + 两套都**只用中性灰阶**:去掉原先的青色品牌字(`#63e2b7`)与 naive-ui 默认的绿色主色, + 主按钮 / 开关激活态 / 进度条 / 勾选框统一改吃「主色位 = 中性灰」这一个值。 + - 白主题的**页底刻意不是 `#ffffff`**(`#f4f4f5`):卡片本身是白的,两者同色就只能靠 1px 分线撑层次, + 整页发「糊」;压一档浅灰后层次为「页底 < 侧栏 < 卡片」,且仍是白为主。 +- **语义色不是去掉,而是降饱和**(灰绿 / 灰琥珀 / 灰红 / 灰蓝)。 + 这是运维工具,`运行中 / 出错` 必须一眼可辨,全部灰化会导致误读;故它们只出现在徽章与告警这类小面积上, + 底色观感仍是「白 + 灰」。严重程度在关闭图标后本就更依赖 `type` 的底色/边框。 +- **色值只有一份定义**(`src/theme/index.ts` 的 `Palette`):既生成 naive-ui 的 `themeOverrides`, + 又由 `App.vue` 在运行期注入成 `--na-*` CSS 变量供自定义样式使用。 + 原因是若「TS 调色板」与「CSS 写死的色值」各存一份,换主题时会**一半新一半旧且不报错、类型也抓不到** + —— 这正是本轮要消灭的失效模式。 +- **清掉 17 处写死的色值**(散在 8 个文件:日志三流着色、代码块/预览底色、节点选中边框、历史悬停等), + 全部改为 `var(--na-*)`。复扫后自定义样式里的硬编码色为 **0**。 +- **主题偏好只存 `localStorage`,不落 Rust 侧 settings**:那是给「仅服务模式」(无窗口、常驻托盘) + 也要生效的偏好用的,而主题是纯图形偏好 —— 没有窗口时毫无意义。为一件纯前端的事去动 Rust 命令面与契约守卫不划算。 +- **首帧防闪**:`index.html` 内联一段极小脚本,在 Vue 接管前先把上次主题的底色刷上, + 否则「高级灰」用户每次启动都会看到一帧刺眼的白。此处**刻意重复了 2 个底色值**(真值在 `theme/index.ts`), + 因为在此之前没有任何模块可依赖;已在两处都注明「改底色时同步」。 + ### 说明 —— 本轮**刻意不升版本号** 本轮新增的全部是**控制台**功能,**被控端能力集合未变**(未增删任何 `system.*` / `fs.*` / `app.*` 能力)。 diff --git a/apps/console/index.html b/apps/console/index.html index 1571290..74e813b 100644 --- a/apps/console/index.html +++ b/apps/console/index.html @@ -4,6 +4,21 @@ nodeagent 控制台 + diff --git a/apps/console/src/App.vue b/apps/console/src/App.vue index b358847..061bce6 100644 --- a/apps/console/src/App.vue +++ b/apps/console/src/App.vue @@ -1,17 +1,40 @@ diff --git a/apps/console/src/views/LogsView.vue b/apps/console/src/views/LogsView.vue index 687f86c..70706d9 100644 --- a/apps/console/src/views/LogsView.vue +++ b/apps/console/src/views/LogsView.vue @@ -137,7 +137,7 @@ function streamType(s: string) { height: calc(100vh - 300px); min-height: 320px; overflow: auto; - background: rgba(0, 0, 0, 0.18); + background: var(--na-sunken); border-radius: 6px; padding: 10px 12px; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; @@ -160,10 +160,10 @@ function streamType(s: string) { margin-top: 1px; } .txt.stderr { - color: #e88080; + color: var(--na-err); } .txt.system { - color: #63e2b7; + color: var(--na-info); } .empty { opacity: 0.5; diff --git a/apps/console/src/views/NodesView.vue b/apps/console/src/views/NodesView.vue index 0809569..b75375c 100644 --- a/apps/console/src/views/NodesView.vue +++ b/apps/console/src/views/NodesView.vue @@ -195,11 +195,11 @@ const capGroups = computed(() => { align-items: center; justify-content: space-between; padding: 8px 12px; - border: 1px solid rgba(255, 255, 255, 0.09); + border: 1px solid var(--na-border); border-radius: 8px; } .node.active { - border-color: #63e2b7; + border-color: var(--na-accent); } .node-name { font-size: 14px; @@ -219,7 +219,7 @@ const capGroups = computed(() => { font-size: 12px; padding: 2px 8px; border-radius: 4px; - background: rgba(255, 255, 255, 0.06); + background: var(--na-sunken); } .logs { font-family: ui-monospace, Menlo, monospace; diff --git a/apps/console/src/views/OverviewView.vue b/apps/console/src/views/OverviewView.vue index b55068b..f0fc0a9 100644 --- a/apps/console/src/views/OverviewView.vue +++ b/apps/console/src/views/OverviewView.vue @@ -102,7 +102,7 @@ onUnmounted(stop); type="line" :percentage="Math.round(status?.cpu_pct ?? 0)" :height="10" - :color="(status?.cpu_pct ?? 0) > 80 ? '#e88080' : '#63e2b7'" + :color="(status?.cpu_pct ?? 0) > 80 ? 'var(--na-err)' : 'var(--na-ok)'" />
@@ -113,7 +113,7 @@ onUnmounted(stop); type="line" :percentage="Math.round(status?.memory_pct ?? 0)" :height="10" - :color="(status?.memory_pct ?? 0) > 85 ? '#e88080' : '#63e2b7'" + :color="(status?.memory_pct ?? 0) > 85 ? 'var(--na-err)' : 'var(--na-ok)'" />
diff --git a/apps/console/src/views/SoftwareView.vue b/apps/console/src/views/SoftwareView.vue index 95277da..998c8e0 100644 --- a/apps/console/src/views/SoftwareView.vue +++ b/apps/console/src/views/SoftwareView.vue @@ -175,7 +175,7 @@ onMounted(() => { margin: 12px 0 0; padding: 10px; border-radius: 8px; - background: rgba(255, 255, 255, 0.05); + background: var(--na-sunken); font-size: 12px; max-height: 200px; overflow: auto; diff --git a/apps/console/src/views/TerminalView.vue b/apps/console/src/views/TerminalView.vue index 823bffc..38ee6e6 100644 --- a/apps/console/src/views/TerminalView.vue +++ b/apps/console/src/views/TerminalView.vue @@ -161,6 +161,6 @@ function reuse(c: string) { opacity: 0.85; } .hist:hover code { - color: #63e2b7; + color: var(--na-accent); } diff --git a/docs/console-plan.md b/docs/console-plan.md index c08ca56..fd15fd7 100644 --- a/docs/console-plan.md +++ b/docs/console-plan.md @@ -572,6 +572,56 @@ node 去跑打包内的 sidecar,并走一次真实 JSON-RPC 握手 —— 源 > 该测试**已注入故障实测会红**(改 `agent_start` → `agent_startX`、`na-agent-state` → `na-agent-statee` > 当场 2 条失败),非空转守卫。 +## 界面观感约定(2026-10-11) + +两轮纯界面调整,方向都是「少即是多」。理由记下来,免得日后被当成"没做完"再补回去。 + +### 一、一律不使用图标 + +触发原因是一次真实的渲染事故:侧栏的 emoji 图标在非系统字体栈的渲染器里退化成**豆腐块**。 +试过三法,分别无效或更糟 —— 给图标指定 `Apple Color Emoji`、全局字体栈加 `!important`、 +乃至 `font-variant-emoji: emoji`(最后一招把 ASCII 数字也拆成了 emoji 呈现)。 +「哪套字体栈一定带 emoji」跨平台并不成立 —— **与其赌字形,不如不用**。 + +去掉的范围比"看得见的图标"宽得多(下面这三类都算): + +| 类别 | 处数 | 关法 | +|---|---|---| +| 侧栏 emoji | 9 | 路由表 `meta.icon` 字段**整体删除**,`NavMeta` 接口同步收窄 | +| `n-empty` 空态**插画** | **16** | `:show-icon="false"` —— 插画比图标更「图形」,散在 9 个页面,**最易漏** | +| `n-alert` 类型图标 | 7 | naive-ui 的 `showIcon` **默认就是 `true`**,不显式关它就一直都在 | +| `n-popconfirm` 询问图标 | 3 | 同上 | +| 文案里的符号 | 1 | 终端页「⚠ 高权限操作,请谨慎」保留纯文字 | + +顺带清掉 `public/{vite,tauri}.svg` 与 `src/assets/vue.svg`:`public/` 下的文件会被**整体复制进产物**, +此前等于把 Vite / Tauri 的 logo 一并发了出去(且 `index.html` 的 favicon 正指向它)。 +`index.html` 的 `` 还是模板默认的「Tauri + Vue + Typescript App」,也一并改齐 +(原生窗口标题取自 `tauri.conf.json`,故此前只是 dev 态标签页不一致)。 + +**刻意未动**:① 托盘图标 —— 菜单栏没图标就点不到,关窗后应用无法寻回,属**功能必需**; +② 被控端 CLI 自己打印的文本标记(`⚠️`/`ℹ️`/`✅`)—— 是**程序输出内容**,会原样出现在「服务日志」页里, +但不是界面元素;③ 控件的结构性部件(下拉/折叠箭头、输入框清除钮、表格排序箭头)。 + +### 二、配色收敛为两套中性灰阶主题 + +`简约白`(浅)/`高级灰`(深),侧栏底部一行切换,选择存 `localStorage`。 + +| 决定 | 理由 | +|---|---| +| **主色位改中性灰** | naive-ui 默认主色是**绿色**、原设计的品牌字是**青绿 `#63e2b7`** —— 都是"颜色",与「简单些」相悖。主按钮/开关激活/进度条/勾选框统一吃这一个值 | +| 白主题**页底不是纯白**(`#f4f4f5`) | 卡片本身是白的,两者同色就只能靠 1px 分线撑层次,整页发「糊」。压一档浅灰后层次为「页底 < 侧栏 < 卡片」,且仍是白为主 | +| 语义色**降饱和**而非去掉 | 这是运维工具,「运行中 / 出错」必须一眼可辨,全部灰化会导致误读。故它们只出现在徽章与告警这类**小面积**上,底色观感仍是「白 + 灰」 | +| **色值只定义一份** | `src/theme/index.ts` 的 `Palette` 同时喂 naive-ui 的 `themeOverrides` 与 `--na-*` CSS 变量(`App.vue` 运行期注入)。两处各写一份,换主题时会**一半新一半旧且不报错、类型也抓不到** | +| 主题**只存 `localStorage`**,不落 Rust settings | Rust 那套 `Settings` 是给「仅服务模式」(无窗口、常驻托盘)也要生效的偏好用的;主题是纯图形偏好,**没有窗口时毫无意义**。为一件纯前端的事去动 Rust 命令面与契约守卫不划算 | + +清掉散在 **8 个文件**里的 **17 处写死色值**(日志三流着色、代码块/预览底色、节点选中边框、历史悬停…), +全部改为 `var(--na-*)`。复扫后自定义样式里的硬编码色为 **0**。 + +**首帧防闪**:`index.html` 内联一小段脚本,在 Vue 接管前先把上次主题的底色刷上 +(否则「高级灰」用户每次启动都会看到一帧刺眼的白)。 +此处**刻意重复了 2 个底色值**,已在 `index.html` 与 `theme/index.ts` 两处注明「改底色时同步」—— +因为在它执行之前没有任何模块可依赖。除此之外全应用再无第二份色值。 + ### 本轮验证记录 | 条目 | 结果 |