feat(admin): secretFieldState 密钥四态展示纯函数
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -52,6 +52,7 @@ import {
|
||||
rowsToEntries,
|
||||
rowToSingleEntry,
|
||||
scopedConfigJson,
|
||||
secretFieldState,
|
||||
snapshotGroupKeys,
|
||||
touchstoneSentences,
|
||||
utf8Bytes,
|
||||
@@ -745,3 +746,24 @@ describe('通用 JSON 组编辑(终审 I-1:contact/engine/misc)', () => {
|
||||
expect(JSON_GROUP_FIELDS.misc.map((f) => f.key)).toEqual(['name_to_region_extras'])
|
||||
})
|
||||
})
|
||||
|
||||
describe('secretFieldState(密钥四件套展示态)', () => {
|
||||
it('未配置:input 空 + 无掩码', () => {
|
||||
const s = secretFieldState('', '', false)
|
||||
expect(s).toMatchObject({ badge: 'unset', badgeType: 'info', badgeLabel: '未配置' })
|
||||
expect(s.placeholder).toContain('未设置')
|
||||
})
|
||||
it('已配置:掩码哨兵且未动', () => {
|
||||
const s = secretFieldState('', '__SET__', false)
|
||||
expect(s).toMatchObject({ badge: 'configured', badgeType: 'success', badgeLabel: '已配置' })
|
||||
expect(s.placeholder).toContain('留空保持不变')
|
||||
})
|
||||
it('pending-new:输入了新值(优先级最高)', () => {
|
||||
const s = secretFieldState('new-secret', '__SET__', true)
|
||||
expect(s).toMatchObject({ badge: 'pending-new', badgeType: 'warning', badgeLabel: '已输入新值 · 未保存' })
|
||||
})
|
||||
it('pending-clear:清除了已配置值', () => {
|
||||
const s = secretFieldState('', '__SET__', true)
|
||||
expect(s).toMatchObject({ badge: 'pending-clear', badgeType: 'warning', badgeLabel: '将清除 · 未保存' })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
* 密钥哨兵交互见 src/api/mask.ts(GET '__SET__' → 空输入 + 占位符;
|
||||
* 不动保存回传哨兵保持库值;「清除」= 提交空串)。
|
||||
*/
|
||||
import { MASKED_SENTINEL, secretToSubmit } from '@/api/mask'
|
||||
import { MASKED_SENTINEL, isMaskedSentinel, secretToSubmit } from '@/api/mask'
|
||||
import type { ConfigGroupKey } from '@/api/config'
|
||||
// ---- 提示词四件套 -----------------------------------------------------------------
|
||||
|
||||
@@ -569,6 +569,44 @@ export function normalizeAiCredsGroup(
|
||||
}
|
||||
}
|
||||
|
||||
// ---- SecretField 展示态(视觉基线 §4.2;提交值仍走 secretToSubmit) -----------------
|
||||
|
||||
/** 密钥字段徽章四态:已配置 / 未配置 / 已输入新值(未保存) / 将清除(未保存) */
|
||||
export type SecretFieldBadge = 'configured' | 'unset' | 'pending-new' | 'pending-clear'
|
||||
|
||||
export interface SecretFieldState {
|
||||
badge: SecretFieldBadge
|
||||
/** ElTag type 映射(configured=success / unset=info / pending-*=warning) */
|
||||
badgeType: 'success' | 'info' | 'warning'
|
||||
badgeLabel: string
|
||||
placeholder: string
|
||||
}
|
||||
|
||||
/** 输入值 + GET 掩码态 + 清除开关 → 徽章/占位文案(纯展示;优先级 新值 > 清除 > 已配置 > 未配置) */
|
||||
export function secretFieldState(
|
||||
input: string,
|
||||
masked: string,
|
||||
cleared: boolean
|
||||
): SecretFieldState {
|
||||
if (input !== '') {
|
||||
return {
|
||||
badge: 'pending-new', badgeType: 'warning', badgeLabel: '已输入新值 · 未保存', placeholder: ''
|
||||
}
|
||||
}
|
||||
if (cleared) {
|
||||
return {
|
||||
badge: 'pending-clear', badgeType: 'warning', badgeLabel: '将清除 · 未保存', placeholder: ''
|
||||
}
|
||||
}
|
||||
if (isMaskedSentinel(masked)) {
|
||||
return {
|
||||
badge: 'configured', badgeType: 'success', badgeLabel: '已配置',
|
||||
placeholder: '已设置,输入新值可更换(留空保持不变)'
|
||||
}
|
||||
}
|
||||
return { badge: 'unset', badgeType: 'info', badgeLabel: '未配置', placeholder: '未设置,输入新值' }
|
||||
}
|
||||
|
||||
/**
|
||||
* 邮件表单 → PUT config/email 整组载荷。密钥走 secretToSubmit(未动 →
|
||||
* 哨兵保持库值;「清除」按钮已把 maskedState 置 '',提交空串 = 显式清空)。
|
||||
|
||||
Reference in New Issue
Block a user