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:
@@ -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 消费)'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user