diff --git a/admin/src/views/config/center/CredsPane.vue b/admin/src/views/config/center/CredsPane.vue index cdb6704..17e51b6 100644 --- a/admin/src/views/config/center/CredsPane.vue +++ b/admin/src/views/config/center/CredsPane.vue @@ -7,38 +7,30 @@ - AI(ai 组):provider / API Key / base_url / model - 密钥哨兵交互(mask.ts):GET 密钥为 '__SET__' → 输入框留空 + 占位符 「已设置,输入新值覆盖」;不动保存回传哨兵保持库值;「清除」按钮 = - 显式清空意图(提交空串),可再点「恢复保持」撤销 + 显式清空意图(提交空串),可再点「恢复保持」撤销——交互由 SecretField + 四件套组件承载(Task 5 起),提交值仍由父层 build*Payload 计算 - SMTP 测试邮件:收件人 + 按钮 → POST email/test——用**已保存**配置真发 一封(先保存再测试);未配置 400 / 发送失败 sent=false 均内联展示 - 推送连通性探测:POST push/test(后端发空 messages 批量,零线索数据) ——三态展示:不可达(dns/timeout/connect 原因分类)/ 可达但鉴权失败 (401·403)/ 正常(2xx);其余状态码 = 可达但鉴权不定 - - 重置出厂(Task 7d):三卡头部危险色小按钮 → 确认框 → POST + - 重置出厂(Task 7d):卡底危险行小按钮 → 确认框 → POST config/{group}/reset → 表单/密钥态回档案值 + emit saved;push 出厂 前缀被其他租户占用的 400 detail 内联展示 + - Task 5 视觉基线:三卡套 ConfigCard(图标/副标题/信息条/footer/danger + 行);footer-left「出问题?回滚 →」emit navigate('versions')(父层 + 接线在后续任务);表单区双列 grid --> @@ -413,8 +378,9 @@ type PushCredsForm } from './model' import { putConfigGroup, testEmail, testPush, type PushTestResponse } from '@/api/config' - import { MASKED_SENTINEL, secretPlaceholder } from '@/api/mask' import { confirmAndResetGroup } from './reset' + import ConfigCard from './ConfigCard.vue' + import SecretField from './SecretField.vue' defineOptions({ name: 'CredsPane' }) @@ -439,6 +405,8 @@ config: Record } ): void + /** footer 回滚入口:请求父层切到对应组('versions' = 版本历史) */ + (e: 'navigate', group: string): void }>() // ---- 编辑态(组引用变化 = 保存回写/租户切换/重载 → 重置表单与密钥态) ---------------- @@ -513,20 +481,6 @@ { immediate: true } ) - const emailPasswordPlaceholder = computed(() => - emailPasswordCleared.value - ? secretPlaceholder('') - : secretPlaceholder(emailPasswordMasked.value) - ) - const pushApiKeyPlaceholder = computed(() => - pushApiKeyCleared.value - ? secretPlaceholder('') - : secretPlaceholder(pushApiKeyMasked.value) - ) - const aiApiKeyPlaceholder = computed(() => - aiApiKeyCleared.value ? secretPlaceholder('') : secretPlaceholder(aiApiKeyMasked.value) - ) - // ---- 保存(前端预检 → 整组 PUT;密钥不动回哨兵保持库值) ------------------------------ async function onSaveEmail(): Promise { @@ -698,7 +652,8 @@ } } } catch (error) { - // 400「SMTP 未配置」等后端预检拒绝(ApiError.message = detail) + // 400「SMTP 未配置」/ 429「测试端点调用过于频繁」等后端预检拒绝 + // (ApiError.message = detail,白话文案直接内联展示) emailTestResult.value = { type: 'error', text: error instanceof Error ? error.message : '测试发送失败' @@ -724,7 +679,7 @@ try { pushProbe.value = await testPush(props.slug, { showErrorMessage: false }) } catch (error) { - // 400「推送 URL 未配置」等后端预检拒绝 + // 400「推送 URL 未配置」/ 429「测试端点调用过于频繁」等后端预检拒绝 pushProbeError.value = error instanceof Error ? error.message : '探测失败' } finally { pushProbing.value = false @@ -742,52 +697,21 @@ width: 100%; } - .card-header { - display: flex; - align-items: baseline; - justify-content: space-between; - gap: 12px; - - .card-title { - font-weight: 600; - } - - .card-sub { - font-size: 12px; - color: var(--art-gray-400); - } - - // 头部右列:副标题 + 重置出厂小按钮(Task 7d) - .header-side { - display: flex; - align-items: center; - gap: 10px; - flex-shrink: 0; - } - } - .pane-error { margin-bottom: 12px; } - .secret-row { - display: flex; - gap: 8px; - align-items: center; - width: 100%; + // 表单区双列 grid(span-2 = 独占整行:密钥/长控件/开关) + .form-grid { + display: grid; + grid-template-columns: 1fr 1fr; + column-gap: 16px; - .secret-input { - flex: 1; - min-width: 0; + .span-2 { + grid-column: span 2; } } - .field-warn { - margin: 4px 0 0; - font-size: 12px; - color: var(--el-color-danger); - } - .switch-hint { margin-left: 10px; font-size: 12px; @@ -798,10 +722,8 @@ width: 100%; } - .save-bar { - display: flex; - justify-content: flex-end; - margin-top: 8px; + .comment-input { + width: 220px; } .test-divider { diff --git a/admin/src/views/config/center/SecretField.vue b/admin/src/views/config/center/SecretField.vue index aac5091..1d4b450 100644 --- a/admin/src/views/config/center/SecretField.vue +++ b/admin/src/views/config/center/SecretField.vue @@ -29,7 +29,7 @@ {{ cleared ? '恢复保持' : '清除' }} -

+

保存后将清除已存密钥(空槽回退平台默认)

@@ -67,6 +67,10 @@ align-items: center; gap: 8px; + :deep(.el-button) { + flex-shrink: 0; + } + .secret-input { flex: 1; min-width: 0;