feat(settings): 设置弹窗改为全局设置页面(全局/高级/关于三 Tab)+ 体检账单缺口与更新下载修复 — bump to v0.8.5
Release / Version consistency (push) Canceled after 0s
Release / Build (macos-latest) (push) Canceled after 0s
Release / Build (ubuntu-latest) (push) Canceled after 0s
Release / Build (windows-latest) (push) Canceled after 0s
Release / Attach macOS install script (push) Canceled after 0s
Release / Version consistency (push) Canceled after 0s
Release / Build (macos-latest) (push) Canceled after 0s
Release / Build (ubuntu-latest) (push) Canceled after 0s
Release / Build (windows-latest) (push) Canceled after 0s
Release / Attach macOS install script (push) Canceled after 0s
This commit is contained in:
1 parent
e00f6b6591
commit
38dbb5527a
50 files changed
+3904
-2571
No files matched your search
@@ -0,0 +1,186 @@
|
||||
# 提案:设置改为全局页面(设置 + 高级功能 合一)
|
||||
|
||||
状态:**待评审**(本文档为主代理自查 + 交叉审核用,未开始实现)
|
||||
日期:2026-10-15
|
||||
|
||||
---
|
||||
|
||||
## 1. 目标
|
||||
|
||||
取消「设置」弹窗,改为带返回按钮的全局页面;三个 Tab 从同一入口打开同一页面(顺序 **全局设置 | 高级设置 | 关于**):
|
||||
|
||||
- **全局设置 Tab**:全局默认模型 / 供应商级别的默认项
|
||||
- **高级设置 Tab**(原「高级设置」页内容 + 代理设置):代理设置(thinking/循环控制/权限规则/hooks 等)、Kimi Code WebUI 快速打开、models.dev 模型数据、子代理副模型/模型池、实验开关
|
||||
- **关于 Tab**(id 仍为 `general`,原 `SettingsModal` 内容):外观(主题/语言)、更新(版本/检查/下载/安装)、Kimi Code CLI 版本与兼容性、关于
|
||||
|
||||
已确认的三个决策点:
|
||||
|
||||
| 决策 | 选择 | 含义 |
|
||||
| --- | --- | --- |
|
||||
| A | 1 | `AgentSettingsPanel` 从供应商编辑页(`ProviderEdit.tsx`)**移除**,只保留在设置页高级 Tab —— 单一入口 |
|
||||
| B | 2 | **保留**旧 `view === "subagent"` 渲染分支作为兼容外壳,不删除 |
|
||||
| C | 1 | 所有 section **抽成独立可复用组件**,不复制内容,避免两处分叉 |
|
||||
|
||||
## 2. 现状核实(已完成调研,行号为当前 main 上的位置)
|
||||
|
||||
| 文件 | 关键事实 |
|
||||
| --- | --- |
|
||||
| `src/App.tsx:83-85` | `view` 类型:`"list" \| "edit" \| "subagent" \| "dashboard" \| "sessions" \| "plugins"`,需新增 `"settings"` |
|
||||
| `src/App.tsx:89` | `showSettings` state(改造后删除) |
|
||||
| `src/App.tsx:600-638` | 顶部导航(供应商/数据看板/会话),**无 dirty 拦截**,直接 `setView` |
|
||||
| `src/App.tsx:652-665` | 齿轮按钮 → `setShowSettings(true)`;含「有更新」绿点徽标(保留) |
|
||||
| `src/App.tsx:682-696` | 渲染分支:`subagent` → `<SubagentSettingsPage>`(保留,即决策 B) |
|
||||
| `src/App.tsx:697-724` | `ProviderEdit` 入参含 `rawOther` / `onRawOtherChange` / `defaultModel` |
|
||||
| `src/App.tsx:906-914` | footer「高级设置」按钮(仅 `view === "list"` 显示)→ `setView("subagent")`,改为打开设置页高级 Tab |
|
||||
| `src/App.tsx:919-926` | `<SettingsModal>` 挂载(改造后删除) |
|
||||
| `src/components/SettingsModal.tsx`(589 行) | 4 个 section:外观 `:257`、更新 `:302`、Kimi Code `:434`、关于 `:500`;弹窗专属:`createPortal`、`fixed inset-0` 蒙层、Esc 关闭、`body.overflow` 锁定;`handleDownload`(`:103-130`)含「无安装包 → 打开 release 页」回退(**近期 bug 修复,必须逐字保留**);全仓库仅 `App.tsx` 引用 |
|
||||
| `src/components/SubagentSettingsPage.tsx`(710 行) | props `{ rawOther, models, onChange, onBack }`;返回头 `:402-414`,内容区 `:416-707`(masterOn 提示条 + WebUI Card + models.dev Card + 副模型/模型池 Card + 实验开关 Card);仅 `App.tsx` 引用 |
|
||||
| `src/components/AgentSettingsPanel.tsx`(451 行) | props `{ rawOther, onChange, models?, defaultModel? }`;读写全局 `config.raw_other`;自带 `mt-6` 外壳和 `agentSettings` 小标题,页面内可直接复用,**该文件本身不改**;目前唯一挂载点 `ProviderEdit.tsx:478-484`(`agent === "kimi_code"` 时) |
|
||||
| `src/i18n/zh.ts` / `en.ts` | 已有:`settings`、`settingsTitle`、`settingsAppearance`、`settingsUpdates`、`settingsAbout`、`subagentSettings`、`back`;三个 Tab 直接复用 `settingsTabGlobal` / `subagentSettings` / `settingsAbout` |
|
||||
|
||||
数据流结论(合并无数据层改动):`AgentSettingsPanel`、`SubagentSettingsPage` 都只读写全局 `config.raw_other`,`App.tsx` 已有现成回调 `onRawOtherChange={(next) => updateConfig((cfg) => ({ ...cfg, raw_other: next }))}`(`App.tsx:722-724`)。
|
||||
|
||||
## 3. 目标结构
|
||||
|
||||
```
|
||||
src/components/settings/
|
||||
├── SettingsPage.tsx 新增:返回头 + Tab 切换 + 内容容器(本次唯一的"页面")
|
||||
├── SettingsGeneralTab.tsx 新增:SettingsModal 的 4 个 section,去掉弹窗外壳
|
||||
└── SettingsAdvancedTab.tsx 新增:AgentSettingsPanel + SubagentSettingsPage 内容区,去掉返回头
|
||||
|
||||
src/components/
|
||||
├── SettingsModal.tsx 删除(仅 App.tsx 引用,一并摘除)
|
||||
└── SubagentSettingsPage.tsx 改为薄壳:返回头 + <SettingsAdvancedTab>(决策 B 的兼容入口)
|
||||
```
|
||||
|
||||
### 3.1 组件接口契约
|
||||
|
||||
```tsx
|
||||
// SettingsGeneralTab.tsx —— 自包含(主题/语言/版本/下载状态都内置)
|
||||
interface SettingsGeneralTabProps {
|
||||
updateInfo: UpdateInfo | null;
|
||||
checking: boolean;
|
||||
onCheckUpdate: () => void;
|
||||
lastChecked: number | null;
|
||||
}
|
||||
|
||||
// SettingsAdvancedTab.tsx —— 纯内容,无返回头
|
||||
interface SettingsAdvancedTabProps {
|
||||
rawOther: unknown;
|
||||
models: Record<string, Model>;
|
||||
defaultModel: string | null; // 供 AgentSettingsPanel 判断 effort 支持
|
||||
onChange: (nextRawOther: unknown) => void;
|
||||
}
|
||||
|
||||
// SettingsPage.tsx
|
||||
// 返回头与 SubagentSettingsPage 同款:`← {t("back")}` + 标题 `t("settingsTitle")`("设置")
|
||||
interface SettingsPageProps {
|
||||
// Tab 受控(不用 initialTab + 内部 state)——齿轮按钮在 header 常驻,
|
||||
// 停留在设置页时再点齿轮,必须能切回第一个 Tab(全局设置);非受控则 prop 变化不生效。
|
||||
activeTab: "global" | "advanced" | "general";
|
||||
onTabChange: (tab: "global" | "advanced" | "general") => void;
|
||||
onBack: () => void;
|
||||
// 透传给三个 Tab:
|
||||
updateInfo / checking / onCheckUpdate / lastChecked
|
||||
rawOther / models / defaultModel / onRawOtherChange
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 Tab 挂载策略(审核补充的关键点)
|
||||
|
||||
原 `SettingsModal` **常驻挂载**(`open=false` 时返回 null 但 hooks 仍在跑),下载进度监听、`downloadedPath` 状态在弹窗开关间不丢失。改造后若用条件渲染 `{tab === "general" && ...}`,下载进行中切到高级 Tab(或按返回离开页面)会丢失 `downloadedPath`,「安装」按钮消失——这是行为回归。
|
||||
|
||||
**方案:三个 Tab 面板都常驻挂载,非激活 Tab 用 `className="hidden"` 隐藏。** 代价仅是高级 Tab 提前挂载(一次 `getAgentSettings` IPC 读,无副作用),换来下载状态与滚动位置不丢。
|
||||
|
||||
## 4. App.tsx 接线
|
||||
|
||||
1. `view` 类型加 `"settings"`;删除 `showSettings` state 与 `<SettingsModal>` 挂载、import;删除 `SettingsModal.tsx`。
|
||||
2. 新增 `settingsTab` state(`"global" | "advanced" | "general"`)。
|
||||
3. 齿轮按钮(`App.tsx:670`)→ `setSettingsTab("global"); setView("settings")`(第一个 Tab 即全局设置);绿点徽标保留。
|
||||
4. header「高级设置」按钮 → `setSettingsTab("advanced"); setView("settings")`,文案键不变。
|
||||
5. 渲染分支加(Tab 受控,state 放 App):
|
||||
```tsx
|
||||
) : view === "settings" ? (
|
||||
<SettingsPage
|
||||
activeTab={settingsTab}
|
||||
onTabChange={setSettingsTab}
|
||||
onBack={() => setView("list")}
|
||||
updateInfo={updateInfo} checking={checking} onCheckUpdate={checkNow} lastChecked={lastChecked}
|
||||
rawOther={config.raw_other} models={config.models} defaultModel={config.default_model}
|
||||
onRawOtherChange={(next) => updateConfig((cfg) => ({ ...cfg, raw_other: next }))}
|
||||
/>
|
||||
```
|
||||
6. 兼容分支(决策 B):`view === "subagent"` 保留,仅多传 `defaultModel={config.default_model}`(`SubagentSettingsPage` 新增可选 prop)。此后 UI 上无入口指向它,代码保留。
|
||||
|
||||
## 5. ProviderEdit.tsx 摘除(决策 A)
|
||||
|
||||
- 删除 `AgentSettingsPanel` 挂载块(`:477-484`)与 import(`:16`)。
|
||||
- 连锁清理(`noUnusedLocals` / `noUnusedParameters` 开启,tsc 会逼出来):`rawOther` / `onRawOtherChange` 两个 props 若无其他使用则从 `ProviderEditProps`(`:93` 附近)和 `App.tsx:721-724` 调用处一并删除;`modelsByAlias` 等仅为其存在的中间变量同步清理。以 `npx tsc --noEmit` 零错误为准。
|
||||
|
||||
## 6. i18n
|
||||
|
||||
三个 Tab 文案键(zh / en):
|
||||
|
||||
| key | zh | en |
|
||||
| --- | --- | --- |
|
||||
| `settingsTabGlobal` | 全局设置 | Global Settings |
|
||||
| `subagentSettings` | 高级设置 | Advanced Settings |
|
||||
| `settingsAbout` | 关于 | About |
|
||||
|
||||
不新增其他 key;`SubagentSettingsPage` 薄壳继续复用 `subagentSettings` / `back`。
|
||||
|
||||
## 7. 行为差异清单(有意为之,评审确认)
|
||||
|
||||
| # | 差异 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| 1 | Esc 不再关闭设置 | 弹窗行为;页面用「← 返回」。如需保留可加,默认不加 |
|
||||
| 2 | 设置不再遮挡底层界面 | 弹窗 → 页面,符合本次需求本意 |
|
||||
| 3 | footer 出现在设置页 | footer 显示条件不含 `settings`,保存/重载按钮仍可用(高级 Tab 改 `raw_other` 会标 dirty,**能在页内直接保存**,是改善而非回归) |
|
||||
| 4 | 顶部导航「供应商」高亮条件 | `list/edit/subagent` 高亮(`App.tsx:604`),`settings` 不加入高亮,返回后仍正确 |
|
||||
| 5 | 齿轮/高级按钮进入设置页**不做 dirty 拦截** | 与现有 header 导航(数据看板/会话)一致;配置在内存中不丢失 |
|
||||
| 6 | 停留在设置页时再点齿轮 | 切回第一个 Tab(全局设置),受控 Tab 保证 prop 变化生效,见 3.1 |
|
||||
| 7 | footer 按钮文案 | 与高级设置 Tab 共用 `subagentSettings`(高级设置),文案一致 |
|
||||
|
||||
## 8. 不做的事(边界)
|
||||
|
||||
- 不动 dashboard / sessions / plugins 页面,不动 Rust 侧任何代码。
|
||||
- 不改 `AgentSettingsPanel.tsx` 内部(含 `mt-6` 外壳与「代理设置」小标题,在高级 Tab 中观感正常);高级 Tab 不再按 `agent === "kimi_code"` 判断——当前仅支持 kimi_code(`getInitialAgent` 恒返回 `"kimi_code"`),判断无意义。
|
||||
- Tab 选择不持久化到 localStorage:每次进入按入口决定初始 Tab(齿轮 → 全局设置,header「高级设置」→ 高级设置)。
|
||||
- 不新增组件测试:项目测试先例仅覆盖 `src/lib` / `src/hooks`,无组件测试;本次跟随先例。
|
||||
- `SettingsGeneralTab` 只在设置页打开时挂载(原弹窗常驻挂载)——下载监听只能由设置页内的按钮发起,无实际影响。
|
||||
- 工作区里已有的未提交改动(更新下载修复、OpenTerminal 链接、models-dev 数据)与本提案无关,实现时**不混入**,分开提交。
|
||||
|
||||
## 9. 实施步骤(依赖顺序)
|
||||
|
||||
1. **并行抽取**(两个子代理,文件不相交):
|
||||
a. `SettingsGeneralTab.tsx`(含下载回退修复逐字保留)
|
||||
b. `SettingsAdvancedTab.tsx` + `SubagentSettingsPage.tsx` 改薄壳
|
||||
2. **接线**(主代理):`SettingsPage.tsx` + `App.tsx` + `ProviderEdit.tsx` + i18n 两键 + 删除 `SettingsModal.tsx`。
|
||||
3. **验证**:`npx tsc --noEmit` 零错误 → `npm test`(150 例基线)→ `cargo test`(应无影响,跑一遍确认 208 例基线)。
|
||||
4. **dev 实测**(注意先 `taskkill` 关正式版,单实例锁冲突):见 10。
|
||||
|
||||
## 10. 验收标准
|
||||
|
||||
**自动化**:`npx tsc --noEmit` 零错误;`npm test` 全绿;`cargo test` 全绿。
|
||||
|
||||
**手动清单**(`npm run tauri-dev`):
|
||||
|
||||
- [ ] 齿轮 → 打开设置页,初始停在「全局设置」Tab,四个 section(外观/更新/KimiCode/关于)在「关于」Tab 中原弹窗内容一致(含 OpenTerminal 链接)
|
||||
- [ ] header「高级设置」→ 同一页面,初始停在「高级设置」Tab,含代理设置 + 原 4 个 Card
|
||||
- [ ] 「← 返回」回到供应商列表
|
||||
- [ ] 供应商编辑页模型 Tab **不再出现**代理设置区块
|
||||
- [ ] 高级 Tab 改动(如实验开关)→ footer 出现未保存标记 → 可在页内保存 → 配置文件落盘正确
|
||||
- [ ] 检查更新 / 下载 / 安装流程可用;下载中切到高级 Tab 再切回,进度与「安装」按钮不丢
|
||||
- [ ] 主题、语言切换即时生效
|
||||
- [ ] 有新版本时齿轮绿点徽标仍显示
|
||||
- [ ] 停留在设置页时再点齿轮 → 切回第一个 Tab(全局设置)
|
||||
- [ ] header「高级设置」按钮文案与高级设置 Tab 名一致
|
||||
|
||||
## 11. 风险与回退
|
||||
|
||||
| 风险 | 缓解 |
|
||||
| --- | --- |
|
||||
| 抽取时漏搬/改错下载回退逻辑 | 验收清单专项覆盖;diff 逐行 review |
|
||||
| 高级 Tab 提前挂载引发意外 IPC | 仅一次只读 `getAgentSettings`,无写操作 |
|
||||
| `ProviderEdit` props 清理波及其他用法 | 已核实 `rawOther` 仅 `AgentSettingsPanel` 消费,tsc 兜底 |
|
||||
| 回退 | 单独 commit,`git revert` 即可整体回退,不碰数据格式 |
|
||||
@@ -0,0 +1,37 @@
|
||||
# KimiSwitch v0.8.5
|
||||
|
||||
设置界面重构版:原来那个塞满所有选项的「设置」弹窗变成了一整页带返回头的全局设置页面,按「全局设置 / 高级设置 / 关于」分页;同时修掉两处体检与更新下载的哑火问题。
|
||||
|
||||
## 设置弹窗改为全局设置页面(重构)
|
||||
|
||||
- **弹窗改成页面**:原 `SettingsModal` 只能在弹窗那一小块区域里滚动,选项一多就要反复上下翻。现在从右上角齿轮或顶部导航进入的是一整页设置,与「供应商 / 仪表盘 / 会话」平级、由顶部导航直接切换,宽度与上下文都充裕
|
||||
- **三个 Tab 各管一摊**:
|
||||
- **全局设置**——写回 `config.toml` 的代理设置,思考开关与五档思考等级、循环控制(单步最大尝试次数、上下文预留、压缩重试上限)、权限规则、钩子
|
||||
- **高级设置**——KimiWebUI、models.dev 参考数据同步/回滚、子代理模型池、实验功能开关
|
||||
- **关于**——外观三态(浅色 / 深色 / 跟随系统)、语言、更新检查、kimi-code CLI 版本核验、关于信息
|
||||
- **「高级设置」入口移入顶部导航组**:此前要从页面底部 footer 的按钮进;现在和「供应商 / 仪表盘 / 会话」并排,位置固定好找
|
||||
- **代理设置单一入口**:供应商编辑页里内嵌的那份代理设置已移除,全局设置页是唯一入口,不会出现两处各写一半的困惑
|
||||
- **旧 `view=subagent` 路由保留**:作为兼容外壳继续存在,书签或内部跳转不会失效
|
||||
- **Tab 切换不丢状态**:非活动面板只是隐藏而非卸载,更新下载的进度与安装包路径在切 Tab 之间保持不丢
|
||||
|
||||
## 一键体检:账单缺口修复
|
||||
|
||||
- **配了 NewAPI / Sub2API 查询模板但没勾 usageKinds 的供应商不再被静默跳过**:这两条模板路径直接查网关自己的用量端点,本来就不走 `usageKinds`,此前体检却因为它为空而判定「不需要查账单」,把这一行整个漏掉
|
||||
- **用户在配置面板里主动关掉用量查询时仍然不查**:关掉是明确意图,不该被记成失败项
|
||||
- 其余情况(无配置、`auto` 模板 + 空 kinds)行为不变,仍不发起账单请求
|
||||
|
||||
## 更新下载修复
|
||||
|
||||
- **release 没有当前平台安装包资产时,「下载」按钮回退为打开 release 页面**:此前 `downloadUrl` 缺失就静默返回,点了没反应像是按钮坏了;现在直接跳 release 页,用户可自行选资产。连 release 页地址都没有时才提示原因
|
||||
- **自动更新过滤 draft 与 prerelease**:两个托管站都按「最新在前」返回,此前直接取数组第一个;若最新一条是 draft,或正式版之后又发了一个 rc,就会被当成更新推给用户。现在显式跳过未发布与预发布,取最新的正式版,全被过滤掉时按「无已发布版本」处理而不是 panic
|
||||
|
||||
## 其他
|
||||
|
||||
- **启动瞬间的色差修复**:CSS 变量默认深色,而 Tailwind 的 `dark:` 变体要等 React 挂载后才生效,启动瞬间激活的供应商卡片会先闪一下浅色;现在 `index.html` 首帧前内联脚本即按 localStorage + 系统偏好设置主题 class,不再闪
|
||||
- **关于区新增 OpenTerminal 推荐链接**(`billowliu2.github.io/OpenTerminal`),与 KimiSwitch 官网、Kimi Eyes 插件站并列
|
||||
- models.dev 快照同步至 2026-10-15(8,873 模型 / 230 供应商),本次含 14 条模型价格调整与 3 条已下线模型清理
|
||||
|
||||
## 测试
|
||||
|
||||
- 前端 150 项
|
||||
- Rust 212 项(新增 7 项:网关模板应查 / 面板关闭不查 / 空 kinds 不查、draft 与 prerelease 过滤、全稳定取最新、空与非数组不 panic)
|
||||
Reference in new issue
Block a user