Skip to content

Commit f6dd012

Browse files
committed
refactor(ui): migrate provider settings buttons
1 parent 1a7762b commit f6dd012

5 files changed

Lines changed: 40 additions & 33 deletions

File tree

‎app/src/components/AiProviderSettings.tsx‎

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import { useEffect, useState } from "react";
1414
import { invoke } from "@tauri-apps/api/core";
1515
import type { AiProviderInput, AiProviderView } from "../types";
16-
import { ConfirmDialog } from "../ui/primitives";
16+
import { ConfirmDialog, Button } from "../ui/primitives";
1717

1818
const btn: React.CSSProperties = {
1919
padding: "5px 10px",
@@ -169,14 +169,14 @@ export default function AiProviderSettings() {
169169
{p.baseUrl} · {p.defaultModel}
170170
</div>
171171
<div style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
172-
<button style={btn} onClick={() => setEditing(p)} disabled={busy}>编辑</button>
173-
<button style={btn} onClick={() => void testProvider(p.id)} disabled={busy}>测试连接</button>
174-
{!p.isDefault && <button style={btn} onClick={() => void setDefault(p.id)} disabled={busy}>设为默认</button>}
175-
<button style={btn} onClick={() => void toggleEnabled(p)} disabled={busy}>{p.enabled ? "禁用" : "启用"}</button>
172+
<Button variant="secondary" size="md" disabled={busy} onClick={() => setEditing(p)}>编辑</Button>
173+
<Button variant="secondary" size="md" disabled={busy} onClick={() => void testProvider(p.id)}>测试连接</Button>
174+
{!p.isDefault && <Button variant="secondary" size="md" disabled={busy} onClick={() => void setDefault(p.id)}>设为默认</Button>}
175+
<Button variant="secondary" size="md" disabled={busy} onClick={() => void toggleEnabled(p)}>{p.enabled ? "禁用" : "启用"}</Button>
176176
{p.hasKey ? (
177-
<button style={btn} onClick={() => clearKey(p.id)} disabled={busy}>清除密钥</button>
177+
<Button variant="secondary" size="md" disabled={busy} onClick={() => clearKey(p.id)}>清除密钥</Button>
178178
) : (
179-
<button style={btn} onClick={() => { setKeyInputId(p.id); setKeyInput(""); }} disabled={busy}>配置密钥</button>
179+
<Button variant="secondary" size="md" disabled={busy} onClick={() => { setKeyInputId(p.id); setKeyInput(""); }}>配置密钥</Button>
180180
)}
181181
{!p.isDefault && (
182182
<button style={{ ...btn, color: "#dc2626" }} onClick={() => removeProvider(p.id)} disabled={busy}>删除</button>
@@ -204,15 +204,16 @@ export default function AiProviderSettings() {
204204
>
205205
保存
206206
</button>
207-
<button
208-
style={btn}
207+
<Button
208+
variant="secondary"
209+
size="md"
209210
onClick={() => {
210211
setKeyInputId(null);
211212
setKeyInput("");
212213
}}
213214
>
214215
取消
215-
</button>
216+
</Button>
216217
</div>
217218
)}
218219
</div>
@@ -381,9 +382,9 @@ function ProviderForm({
381382
<button style={{ ...btn, background: "#0d9488", color: "#fff", border: "none" }} onClick={() => void submit()} disabled={busy}>
382383
保存
383384
</button>
384-
<button style={btn} onClick={onCancel} disabled={busy}>
385+
<Button variant="secondary" size="md" disabled={busy} onClick={onCancel}>
385386
取消
386-
</button>
387+
</Button>
387388
</div>
388389
</div>
389390
);

‎app/src/ui/primitives/buttonMigration.test.ts‎

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,23 @@ const T1_SECTION_B_37: readonly string[] = [
7373

7474
/** 登记例外:**点名 + 理由**(缺口必须可见;不许从账本消失) */
7575
const EXCLUDED: Readonly<Record<string, string>> = {
76-
"components/AiProviderSettings.tsx": "与 T11 并行撞车(同一文件同时被两个任务点名)",
77-
"components/GroupRowContextMenu.tsx": "T8 的 dialogMigration.e.test.ts:240-244 禁止 NON_MIGRATED_14 import 原语(B1)",
78-
"components/RichEditorView.tsx": "同上(B1 锚定菜单)",
76+
"components/GroupRowContextMenu.tsx": "B1:T8 的 dialogMigration.e.test.ts:240-244 禁止 NON_MIGRATED_14 import 原语",
77+
"components/RichEditorView.tsx": "B1:同上(锚定菜单)",
7978
};
8079
const MIGRATED = T1_SECTION_B_37.filter((f) => EXCLUDED[f] === undefined);
8180

8281
/** 缺口:这些文件**还剩几处** `style={xxxBtn}`(实测值;补做时这里先红) */
8382
const GAP_SITES: Readonly<Record<string, number>> = {
84-
"components/AiProviderSettings.tsx": 8,
8583
"components/GroupRowContextMenu.tsx": 2,
8684
"components/RichEditorView.tsx": 3,
8785
};
8886

87+
/** 已补齐的历史缺口(T11 落库后由 T12 补做)—— 留档,防止"缺口从账本消失" */
88+
const FILLED_GAP = { file: "components/AiProviderSettings.tsx", sites: 8, why: "曾与 T11 并行撞车;T11 落库后补做" } as const;
89+
8990
/** 仍被引用的 `const *Btn*` 白名单(`文件|常量名`)—— **只有 spread 消费者**的常量按兵不动 */
9091
const STILL_REFERENCED: readonly string[] = [
92+
"components/AiProviderSettings.tsx|btn",
9193
"components/AiRefineCard.tsx|btn",
9294
"components/AiServicePanel.tsx|btn",
9395
"components/AiTaskPanel.tsx|btn",
@@ -126,6 +128,7 @@ const STILL_REFERENCED: readonly string[] = [
126128

127129
/** 换出来的 `Button` 形状表:`文件 → (variant,size) 形状 → 计数`(迁移后实测) */
128130
const BUTTON_SHAPES: Readonly<Record<string, Readonly<Record<string, number>>>> = {
131+
"components/AiProviderSettings.tsx": { "variant=secondary size=md": 8 },
129132
"components/AiRefineCard.tsx": { "variant=secondary size=md": 1 },
130133
"components/AiServicePanel.tsx": { "variant=secondary size=md": 1 },
131134
"components/AiTaskPanel.tsx": { "variant=secondary size=sm": 3 },
@@ -162,7 +165,7 @@ const BUTTON_SHAPES: Readonly<Record<string, Readonly<Record<string, number>>>>
162165
"pages/GoalsPage.tsx": { "variant=primary size=md": 1, "variant=secondary size=md": 1 },
163166
};
164167
/** 形状表覆盖的 `Button` 总数(= 迁移处数;棘轮的 Δ 必须与它逐字相等) */
165-
const MIGRATED_SITES = 91;
168+
const MIGRATED_SITES = 99;
166169
/** 迁移前读数(`dev@bde807dc` 导出树,同一仪器实测):棘轮基线**只许在这条线以下** */
167170
const PRE_T12_NATIVE_BUTTONS = 493;
168171

@@ -199,11 +202,13 @@ describe("T12 · 仪器自证(正/负对照 · 剥注释 · 空真排查)",
199202
expect(MIGRATED.length + Object.keys(EXCLUDED).length).toBe(37);
200203
for (const rel of T1_SECTION_B_37) expect(read(rel).length, `读不到 ${rel}`).toBeGreaterThan(0);
201204
expect(Object.keys(GAP_SITES).sort(), "缺口表与例外表不是同一组文件").toEqual(Object.keys(EXCLUDED).sort());
202-
expect(MIGRATED.length, "已迁文件数不像话(清单读错会在这里显形)").toBe(34);
205+
expect(MIGRATED.length, "已迁文件数不像话(清单读错会在这里显形)").toBe(35);
206+
expect(MIGRATED, "曾登记的历史缺口已补齐(它必须回到已迁清单里)").toContain(FILLED_GAP.file);
207+
expect(directHits(read(FILLED_GAP.file)), `补做过的 ${FILLED_GAP.file} 又冒出直接形态命中`).toBe(0);
203208
});
204209
});
205210

206-
describe("① 直接形态 style={xxxBtn} 在 34 个已迁文件里归零", () => {
211+
describe("① 直接形态 style={xxxBtn} 在 35 个已迁文件里归零", () => {
207212
it("逐文件 directHits === 0;缺口文件的实测处数 == 登记值(仪器在缺口上有非零读数 ⇒ 不是看不见)", () => {
208213
const bad = MIGRATED.filter((rel) => directHits(read(rel)) !== 0)
209214
.map((rel) => `${rel}: ${directHits(read(rel))}`);
@@ -234,7 +239,7 @@ describe("② 常量族台账:孤立常量 = 0,仍被引用者 == 白名单"
234239
});
235240

236241
describe("③ Button 形状表:换出来的原语必须与冻结的 (variant,size) 逐文件一致", () => {
237-
it("逐文件形状计数相等,且总数 == 91(把 primary 写成 secondary 这里必红)", () => {
242+
it("逐文件形状计数相等,且总数 == 99(把 primary 写成 secondary 这里必红)", () => {
238243
const diffs: string[] = [];
239244
let total = 0;
240245
for (const rel of MIGRATED) {

‎app/src/ui/primitives/nativeButton.ratchet.test.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
* 已知边界(有意保留、并有用例钉住):字符串字面量里的 `<button` 会被计入 —— 实测本仓 0 例。
2121
*
2222
* 副作用:只读磁盘(递归遍历 `app/src`),不修改任何文件。
23-
* 边界:**批 4 T12 迁的是 `*Btn*` 常量族的直接消费者 91 处 / 34 文件**(两个登记例外见
23+
* 边界:**批 4 T12 迁的是 `*Btn*` 常量族的直接消费者 99 处 / 35 文件**(两个登记例外见
2424
* `nativeButtonBaseline.ts` 头注);其余余量登记给批 5/7。基线随迁移**只降不升**
25-
* (T1 冻结 510/121 → T5–T10 后 493/121 → T12 后 402/114)。
25+
* (T1 冻结 510/121 → T5–T10 后 493/121 → T12 后 394/114)。
2626
*/
2727
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
2828
import { dirname, join, relative, sep } from "node:path";
@@ -179,7 +179,7 @@ const SCAN = scan();
179179
const BASELINE = FROZEN_NATIVE_BUTTON_BY_FILE;
180180
const SPLIT_TARGETS = new Set(SPLIT_MOVES.map((m) => m.split("|")[0]));
181181

182-
describe("原生按钮棘轮(B4):基线随迁移只降不升(T12 后 402 处 / 114 文件)", () => {
182+
describe("原生按钮棘轮(B4):基线随迁移只降不升(T12 后 394 处 / 114 文件)", () => {
183183
it("仪器自证:能命中已知存在的串 · 对无意义串报 0 · 且剥注释生效(末条是**已知边界**)", () => {
184184
expect(countOf("const a = <button onClick={f}>x</button>;", RE_BUTTON)).toBe(1);
185185
expect(countOf("const a = <butto n />;", RE_BUTTON)).toBe(0);

‎app/src/ui/primitives/nativeButtonBaseline.ts‎

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,33 @@
2020
*
2121
* ★ 批 4 T12 的迁移与**基线收紧**(2026-09-12;T12 实施者实测,仪器 = 与守卫同源探针)
2222
* 迁移前(`dev@bde807dc` 导出树)**493 处 / 121 文件** · `const *Btn*` **79 行 / 55 文件**;
23-
* 迁移后(T12 工作树)**402 处 / 114 文件** · `const *Btn*` **56 行 / 44 文件**。
24-
* Δ = **−91 处**(逐文件 Δ 之和逐字等于迁过的处数 ⇒ 机理对拍通过;T5–T10 已先降 510→493)。
23+
* 迁移后(T12 三次提交后)**394 处 / 114 文件** · `const *Btn*` **56 行 / 44 文件**。
24+
* Δ = **−99 处**(逐文件 Δ 之和逐字等于迁过的处数 ⇒ 机理对拍通过;T5–T10 已先降 510→493)。
2525
*
2626
* ★ 余量去向(B4 的"口径变化 + 余量去向",**不许把 §5.1 的 107/63 悄悄改成 80/55**)
2727
* 规格 §5.1 的「Button | 107 处 / 63 文件」**口径不可考**(`btnStyle` 标识符全仓 0 命中)⇒
2828
* 实测三口径:原生 `<button>`(本文件冻结)· `const *Btn*` 常量族 · `style={xxxBtn}` 消费者。
29-
* **T12 只迁直接形态 91 处 / 34 文件**(T1 §B 的 37 文件减去 3 个登记例外,见下),
30-
* 余量(402 处 − 后续批次已迁)登记给**批 5/7**,由本棘轮冻结。**两个登记例外**:
31-
* ① `components/AiProviderSettings.tsx`(8 处,与 T11 并行撞车,见 T12 报告 §7 缺口表);
32-
* ② `components/GroupRowContextMenu.tsx`(2 处)+ `components/RichEditorView.tsx`(3 处)——
29+
* **T12 迁的是直接形态 99 处 / 35 文件**(T1 §B 的 37 文件减去 **2 个登记例外**,见下),
30+
* 余量(394 处 − 后续批次已迁)登记给**批 5/7**,由本棘轮冻结。**两个登记例外**(B1 优先于 B4):
31+
* ① `components/GroupRowContextMenu.tsx`(2 处)· ② `components/RichEditorView.tsx`(3 处)——
3332
* 二者在 T8 的 `NON_MIGRATED_14`(B1 锚定菜单)里,而 `dialogMigration.e.test.ts:240-244`
3433
* 断言这 14 个文件**不得 import 原语层** ⇒ 迁按钮会绕过 B1,**既有断言不改**,故不迁。
34+
* **已补齐的历史缺口**:`components/AiProviderSettings.tsx`(8 处)曾因与 T11 并行撞车暂缓,
35+
* T11 落库(`1a7762bd`)后由 T12 的补做提交补齐(13 → 5 处)。
3536
*/
36-
export const FROZEN_NATIVE_BUTTON_TOTAL = 402;
37+
export const FROZEN_NATIVE_BUTTON_TOTAL = 394;
3738

3839
/** `const *Btn*` 样式常量族的冻结**行数**(T12 迁移后实测 56;迁移前 79)。 */
3940
export const FROZEN_BTN_STYLE_CONST_LINES = 56;
4041

4142
/** `const *Btn*` 样式常量族的冻结**文件数**(T12 迁移后实测 44;迁移前 55)。 */
4243
export const FROZEN_BTN_STYLE_CONST_FILES = 44;
4344

44-
/** 相对 `app/src` 的路径 → 基线计数(T12 迁移后实测:402 处 / 114 文件) */
45+
/** 相对 `app/src` 的路径 → 基线计数(T12 迁移后实测:394 处 / 114 文件) */
4546
export const FROZEN_NATIVE_BUTTON_BY_FILE: Readonly<Record<string, number>> = {
4647
"components/action-center/ActionCenterPanel.tsx": 11,
4748
"components/AiConversationDock.tsx": 9,
48-
"components/AiProviderSettings.tsx": 13,
49+
"components/AiProviderSettings.tsx": 5,
4950
"components/AiRefineCard.tsx": 3,
5051
"components/AiServicePanel.tsx": 3,
5152
"components/AiTaskPanel.tsx": 1,

‎docs/standards/line-limit-exemptions.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
| app/src-tauri/src/live_session.rs | 394 | 会话装配/状态(LiveSessionParams 聚合 + run_session_after_engine 骨架 + ProfileOverride 细目字段);v0.13.6 +2 | 若再增长:ProfileOverride 与参数分拆至 live_session_params.rs |
7777
| app/src-tauri/src/fusion_tests.rs | 392 | 融合测试域(ADR-005 四规则 + REQ-062 概率加权 + REQ-103 音量透传 + REQ-111 切分对齐)单模块 #[path] 挂载 | 若再增长:REQ-111 切分对齐组拆至 fusion_split_tests.rs |
7878
| app/src-tauri/src/db_fragments.rs | 391 | REQ-316(批 7):delete_fragment/update_fragment_group/promote 同事务空组自动清理接线(登记值 309 过期快照,实测纠偏) | 若再增长:promote_fragment_to_note 事务拆至 db_fragments_promote.rs(既有登记计划兑现) |
79-
| app/src/components/AiProviderSettings.tsx | 390 | v0.11.6 M1 code-review 修复(2026-08-22):删除/清钥加 window.confirm、window.prompt 改卡片内联 password 输入(+2 state + 内联表单)、模型列表 input 改 textarea、fallbackOrder 透传 initial、run 置"处理中"反馈、预设双源 presetOptions 后端拉取——修复净增约 13 行越线(实测 329,含 4 行豁免头注释) | 若再增长:内联密钥表单拆至 AiProviderKeyInput.tsx |
79+
| app/src/components/AiProviderSettings.tsx | 391 | v0.11.6 M1 code-review 修复(2026-08-22):删除/清钥加 window.confirm、window.prompt 改卡片内联 password 输入(+2 state + 内联表单)、模型列表 input 改 textarea、fallbackOrder 透传 initial、run 置"处理中"反馈、预设双源 presetOptions 后端拉取——修复净增约 13 行越线(实测 329,含 4 行豁免头注释) | 若再增长:内联密钥表单拆至 AiProviderKeyInput.tsx |
8080
| app/src-tauri/src/import.rs | 385 | 导入域编排(音视频/图片导入流程 + 帧提取调度)内聚;与 import_frame/import_transcribe 分层 | 若再增长:导入参数校验拆至 import_validate.rs |
8181
| app/src-tauri/src/commands_proofread.rs | 383 | v0.20.2(REQ-270)LLM 校对命令域(预估/门控/分块请求/裁决源列表/失败记账)内聚;2026-09-06 实测登记(TD-2026-09-06-G) | 若再增长:record_proofread_failure 与载荷回写拆至 proofread_apply.rs |
8282
| app/src-tauri/src/capture/resample.rs | 381 | 音频重采样域(采样率转换/缓冲对齐/帧切分)内聚于捕获子模块,纯函数与捕获缓冲格式共享上下文 | 若再增长:帧切分拆至 resample_frames.rs |

0 commit comments

Comments
 (0)