feat(admin): SecretField 密钥四件套组件
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
<!--
|
||||
密钥字段四件套(视觉基线 §4.2):状态徽章(secretFieldState 四态)+
|
||||
密码输入(show-password)+ 清除/恢复保持 + 清除警告文案。
|
||||
提交值计算不在本组件——父层沿用 build*Payload(form, cleared ? '' : masked)
|
||||
(mask.ts secretToSubmit 契约)。
|
||||
-->
|
||||
<template>
|
||||
<div class="secret-field">
|
||||
<div class="secret-row">
|
||||
<ElInput
|
||||
:model-value="modelValue"
|
||||
type="password"
|
||||
show-password
|
||||
autocomplete="new-password"
|
||||
:placeholder="state.placeholder"
|
||||
class="secret-input"
|
||||
@update:model-value="$emit('update:modelValue', $event)"
|
||||
/>
|
||||
<ElTag :type="state.badgeType" size="small" effect="light" class="secret-badge">
|
||||
{{ state.badgeLabel }}
|
||||
</ElTag>
|
||||
<ElButton
|
||||
v-if="masked === MASKED_SENTINEL"
|
||||
size="small"
|
||||
:type="cleared ? 'default' : 'danger'"
|
||||
plain
|
||||
@click="$emit('update:cleared', !cleared)"
|
||||
>
|
||||
{{ cleared ? '恢复保持' : '清除' }}
|
||||
</ElButton>
|
||||
</div>
|
||||
<p v-if="state.badge === 'pending-clear'" class="field-warn">
|
||||
保存后将清除已存密钥(空槽回退平台默认)
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { MASKED_SENTINEL } from '@/api/mask'
|
||||
import { secretFieldState } from './model'
|
||||
|
||||
defineOptions({ name: 'SecretField' })
|
||||
|
||||
const props = defineProps<{
|
||||
/** 用户输入(空串 = 未输入) */
|
||||
modelValue: string
|
||||
/** GET 掩码态('__SET__' = 库中已有值;'' = 未设置) */
|
||||
masked: string
|
||||
/** 清除开关(true = 提交空串显式清空) */
|
||||
cleared: boolean
|
||||
}>()
|
||||
|
||||
defineEmits<{
|
||||
(e: 'update:modelValue', value: string): void
|
||||
(e: 'update:cleared', value: boolean): void
|
||||
}>()
|
||||
|
||||
const state = computed(() => secretFieldState(props.modelValue, props.masked, props.cleared))
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.secret-field {
|
||||
width: 100%;
|
||||
|
||||
.secret-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
.secret-input {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.secret-badge {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.field-warn {
|
||||
margin: 4px 0 0;
|
||||
font-size: 12px;
|
||||
color: var(--el-color-danger);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user