fix: Phase3 终审修复(env入库/通用配置组面板/锁屏通知摘除/记档修正)

- I-2: admin/.env(被根 .gitignore 误伤)删除,内容并入入库的
  .env.development/.env.production(公共块两份都写,PORT 仅 dev)
- I-1: 配置中心补 contact/engine/misc 三组通用 JSON 编辑面板
  (JsonGroupPane:等宽 textarea 整组编辑 + JSON.parse 预检 +
  PUT 整组 + 重置出厂 + 顶部字段说明;挂进 GROUP_NAV 三入口);
  修组键缺失租户的禁存 bug(父层快照加载后挂载,空组可建组)
- I-3: config_routes.py docstring 改「接线归 Phase 4」;
  CLAUDE.md Phase 4 清理单补 resolver 回退链与 email/push test 限流
- M-1: 锁屏摘除入口(用户菜单项删 + 全局组件 enabled:false)
- M-2: 顶栏通知铃铛隐藏(headerBar notification.enabled:false)
- M-5/M-8: admin/README 换三行指针(删模板 README.zh-CN.md);
  quickLinks 删「登录」项
- M-3/M-4 不做记档入 Phase 4 清理单
- 测试基线:后端 pytest 595 / 前端 vitest 156(+3 通用 JSON 组)

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-10-14 00:05:40 +08:00
parent 65aad53e12
commit 6af8c186d8
15 changed files with 464 additions and 236 deletions
+62
View File
@@ -737,3 +737,65 @@ export function scopedConfigJson(
scope === COMPARE_SCOPE_ALL ? config : { [scope]: config[scope] }
return JSON.stringify(view, null, 2)
}
// ---- 通用 JSON 组编辑(Phase 3 终审 I-1:contact / engine / misc) -------------------
/** 走通用 JSON pane 的组(无密钥字段、结构低频变更——表单化收益低) */
export type JsonGroupKey = 'contact' | 'engine' | 'misc'
/** 组取值 → 编辑器初稿(null 组 = 空对象;2 空格缩进等宽展示) */
export function jsonGroupDraft(
group: Record<string, unknown> | null | undefined
): string {
return JSON.stringify(group ?? {}, null, 2)
}
/** 编辑器解析结果:ok=false 时 error 带可直接展示的中文原因 */
export type JsonDraftParse =
| { ok: true; value: Record<string, unknown> }
| { ok: false; error: string }
/** 编辑稿预检:JSON 语法 + 顶层须为对象(后端 _check_* 类型校验兜底) */
export function parseJsonGroupDraft(text: string): JsonDraftParse {
let value: unknown
try {
value = JSON.parse(text)
} catch (error) {
const detail = error instanceof Error ? error.message : String(error)
return { ok: false, error: `JSON 语法错误——${detail}` }
}
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
return { ok: false, error: '顶层须为 JSON 对象({ ... })——整组替换语义' }
}
// typeof 收窄只到 object(无索引签名)——JSON.parse 产物必为普通对象,断言收形
return { ok: true, value: value as Record<string, unknown> }
}
/** 三组的字段说明(pane 顶部展示;事实源 app/platform/defaults.py) */
export const JSON_GROUP_FIELDS: Record<
JsonGroupKey,
Array<{ key: string; desc: string }>
> = {
contact: [
{ key: 'cc_completion', desc: 'bool——cc 区号补全判定树开关' },
{ key: 'email_light_ask', desc: 'bool——dual-contact 分步双要的邮箱轻补' },
{
key: 'template_languages',
desc: 'string[]——邮件模板语言清单(运行期接线归 Phase 4,清理单 #8)'
}
],
engine: [
{ key: 'rate_limit_per_hour', desc: '正整数——聊天限流(次/小时/IP)' },
{ key: 'ws_conn_limit', desc: '正整数——每 IP WebSocket 连接上限' },
{
key: 'context_seed_keys',
desc: '映射——产品字段 → 会话上下文种子键(如 product_name → app_product_name)'
}
],
misc: [
{
key: 'name_to_region_extras',
desc: '映射——国名 → ISO 区域码扩展(resolve_region_code 消费)'
}
]
}