diff --git a/ai_knowledge_base_v2/apps/admin-web/src/App.vue b/ai_knowledge_base_v2/apps/admin-web/src/App.vue index 6d17764..4c7f68b 100644 --- a/ai_knowledge_base_v2/apps/admin-web/src/App.vue +++ b/ai_knowledge_base_v2/apps/admin-web/src/App.vue @@ -6,7 +6,6 @@ import AdminLoginView from "./components/AdminLoginView.vue"; import TableRowActions from "./components/TableRowActions.vue"; import { systemSettingDefinitions, - systemSettingSections, type SystemSettingValue, } from "./config/systemSettings"; import { api, clearToken, getToken, saveToken } from "./services/api"; @@ -47,6 +46,9 @@ const UserManagementView = defineAsyncComponent( const SsoIntegrationView = defineAsyncComponent( () => import("./components/SsoIntegrationView.vue"), ); +const SystemConfigView = defineAsyncComponent( + () => import("./components/SystemConfigView.vue"), +); const admin = ref(null); const activeMenu = ref("dashboard"); @@ -55,6 +57,8 @@ const loading = ref(false); const entitlementPlans = ref([]); const models = ref([]); const configs = ref([]); +const savingSystemSettings = ref(false); +const systemSettingsBaseline = ref>({}); const previewKnowledgeId = ref(null); const editingModelId = ref(null); @@ -174,6 +178,13 @@ const systemSettingValues = reactive>({}); systemSettingDefinitions.forEach((setting) => { systemSettingValues[setting.key] = setting.defaultValue; }); +const systemSettingsDirty = computed(() => + systemSettingDefinitions.some( + (setting) => + serializeSystemSettingValue(systemSettingValues[setting.key]) !== + systemSettingsBaseline.value[setting.key], + ), +); onMounted(async () => { if (!getToken()) return; @@ -490,20 +501,30 @@ function validateModelForm() { } async function saveSystemSettings() { - await Promise.all( - systemSettingDefinitions.map((setting) => - api.saveConfig({ - configKey: setting.key, - configValue: serializeSystemSettingValue( - systemSettingValues[setting.key], - ), - description: setting.description, - }), - ), - ); - ElMessage.success("系统配置已保存"); - configs.value = await api.configs(); - hydrateSystemSettings(); + if (savingSystemSettings.value || !systemSettingsDirty.value) return; + savingSystemSettings.value = true; + try { + await Promise.all( + systemSettingDefinitions.map((setting) => + api.saveConfig({ + configKey: setting.key, + configValue: serializeSystemSettingValue( + systemSettingValues[setting.key], + ), + description: setting.description, + }), + ), + ); + configs.value = await api.configs(); + hydrateSystemSettings(); + ElMessage.success("系统配置已保存"); + } catch (error) { + ElMessage.error( + error instanceof Error ? error.message : "系统配置保存失败,请重试", + ); + } finally { + savingSystemSettings.value = false; + } } function hydrateSystemSettings() { @@ -516,6 +537,17 @@ function hydrateSystemSettings() { configMap.get(setting.key), ); }); + systemSettingsBaseline.value = Object.fromEntries( + systemSettingDefinitions.map((setting) => [ + setting.key, + serializeSystemSettingValue(systemSettingValues[setting.key]), + ]), + ); +} + +function updateSystemSetting(key: string, value: SystemSettingValue) { + if (systemSettingValues[key] === value) return; + systemSettingValues[key] = value; } function normalizeSystemSettingValue( @@ -1014,81 +1046,14 @@ async function clearFeishuCache() { - + diff --git a/ai_knowledge_base_v2/apps/admin-web/src/components/SystemConfigView.vue b/ai_knowledge_base_v2/apps/admin-web/src/components/SystemConfigView.vue new file mode 100644 index 0000000..a969464 --- /dev/null +++ b/ai_knowledge_base_v2/apps/admin-web/src/components/SystemConfigView.vue @@ -0,0 +1,797 @@ + + + + + diff --git a/ai_knowledge_base_v2/apps/admin-web/src/styles.css b/ai_knowledge_base_v2/apps/admin-web/src/styles.css index 056ddf5..b397616 100644 --- a/ai_knowledge_base_v2/apps/admin-web/src/styles.css +++ b/ai_knowledge_base_v2/apps/admin-web/src/styles.css @@ -1678,67 +1678,6 @@ textarea { margin-top: 12px; } -.settings-grid { - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: 14px; - margin-bottom: 16px; -} - -.settings-section { - padding: 18px; - border: 1px solid #dfe8e5; - border-radius: 8px; - background: #ffffff; -} - -.settings-section-head h3 { - margin: 0; - font-size: 17px; -} - -.settings-section-head p { - margin: 6px 0 0; - color: #667a73; - font-size: 13px; - line-height: 1.6; -} - -.settings-fields { - display: grid; - gap: 14px; - margin-top: 16px; -} - -.setting-field { - display: grid; - gap: 7px; -} - -.setting-field > span { - color: #223631; - font-weight: 600; -} - -.setting-field > small { - color: #667a73; - line-height: 1.5; -} - -.setting-field > .setting-value-hint { - padding: 9px 11px; - border: 1px solid #cde6dc; - border-radius: 8px; - background: #f3faf7; - color: #246b52; -} - -.setting-field .el-input-number, -.setting-field .el-input, -.setting-field .el-select { - width: 100%; -} - .el-drawer .el-date-editor.el-input { width: 100%; } @@ -2343,8 +2282,7 @@ textarea { @media (max-width: 1120px) { .student-tools, .user-list-toolbar, - .agent-workbench, - .settings-grid { + .agent-workbench { grid-template-columns: 1fr; } diff --git a/ai_knowledge_base_v2/design-qa.md b/ai_knowledge_base_v2/design-qa.md index 0de1d0b..0311131 100644 --- a/ai_knowledge_base_v2/design-qa.md +++ b/ai_knowledge_base_v2/design-qa.md @@ -51,6 +51,54 @@ final result: passed --- +# 系统配置页面重构验收(2026-08-04) + +- 源页面截图:`development_records/ui-evidence/system-config-2026-08-04/before.png` +- 实现页面截图:`development_records/ui-evidence/system-config-2026-08-04/after.png` +- 同屏对比图:`development_records/ui-evidence/system-config-2026-08-04/comparison.jpg` +- 验收地址:`http://localhost:5174/` +- 状态:管理员已登录 / 系统配置 / 用户与登录 +- 视口:1280 × 720 CSS px,设备像素密度 1 +- 源页面完整截图:1280 × 1998 px;实现页面完整截图:1280 × 1572 px +- 归一化方式:两张截图均保持 1280 px 原始宽度和相同像素密度,不缩放;对比图仅在实现图底部补白至相同高度 + +## 完整视图与重点区域证据 + +- 修复前同时铺开 29 项配置,分散在三列高度不一的卡片中,阅读路径长、首屏没有重点,底部留白失衡。 +- 修复后增加运行摘要、左侧分类导航和右侧聚焦编辑区;一次只展示一个顶级分类,并在分类内按业务语义分组。 +- “用户与登录、AI 问答、外部服务、系统开关”四个分类均已逐项打开验证,29 项现有配置全部保留。 +- 首屏摘要展示短信模式、AI 模式、上下文消息数和最大并发数,管理员无需进入字段即可了解关键运行状态。 + +## 必查视觉面 + +- 字体与排版:标题、摘要值、分组标题、字段标签和说明形成稳定层级;长说明自然换行,不与控件挤压。 +- 间距与布局:左侧导航吸附,右侧表单采用统一双列网格;开关类配置使用整行设置项,控件垂直居中。 +- 颜色与设计令牌:沿用后台现有深墨绿、浅雾绿和蓝色主操作色,没有新增图片或大面积装饰色块。 +- 图片与资源:页面完全使用现有组件与 CSS,不依赖新增图片资产。 +- 文案:保留原配置名称和说明;新增“配置已同步 / 有未保存修改”状态,敏感字段增加提示标识。 + +## 交互与工程检查 + +- 已验证四个分类导航均可切换,并显示对应分组和配置数量。 +- 已验证 AI 超时从 60 改为 61 后出现“有未保存修改”且保存按钮启用;恢复为 60 后状态回到“配置已同步”且按钮禁用。 +- 本次验收未实际保存配置,未修改现有运行参数。 +- 保存流程已补充重复提交保护、保存中状态和失败提示,接口与原有配置读写逻辑保持不变。 +- 1280 px 视口下文档、页面容器和配置工作区 `scrollWidth` 均等于 `clientWidth`,无横向滚动。 +- 浏览器控制台错误和警告:0。 +- `npm run build`:通过。 + +## 对比历史 + +1. [P1] 初始问题:全部配置同时展示,三列信息密度过高,管理员难以定位配置且页面高度失控。 +2. 修复:按任务域拆成四个分类和十个业务分组,增加关键状态摘要与聚焦编辑工作区。 +3. [P2] 初始问题:保存按钮始终可点击,缺少未保存状态、保存中反馈和错误处理。 +4. 修复:增加基线对比、脏状态提示、按钮禁用规则、重复提交保护与真实失败提示。 +5. 复验:完整视图信息层级清晰,分类切换、状态恢复、响应式宽度和构建均通过;未发现剩余 P0、P1、P2 问题。 + +final result: passed + +--- + # Markdown 长回答排版修复验收(2026-07-17) ## 对照范围 diff --git a/ai_knowledge_base_v2/development_records/ui-evidence/system-config-2026-08-04/after.png b/ai_knowledge_base_v2/development_records/ui-evidence/system-config-2026-08-04/after.png new file mode 100644 index 0000000..e7f7e52 Binary files /dev/null and b/ai_knowledge_base_v2/development_records/ui-evidence/system-config-2026-08-04/after.png differ diff --git a/ai_knowledge_base_v2/development_records/ui-evidence/system-config-2026-08-04/ai-settings.png b/ai_knowledge_base_v2/development_records/ui-evidence/system-config-2026-08-04/ai-settings.png new file mode 100644 index 0000000..b305f93 Binary files /dev/null and b/ai_knowledge_base_v2/development_records/ui-evidence/system-config-2026-08-04/ai-settings.png differ diff --git a/ai_knowledge_base_v2/development_records/ui-evidence/system-config-2026-08-04/before.png b/ai_knowledge_base_v2/development_records/ui-evidence/system-config-2026-08-04/before.png new file mode 100644 index 0000000..8a044b4 Binary files /dev/null and b/ai_knowledge_base_v2/development_records/ui-evidence/system-config-2026-08-04/before.png differ diff --git a/ai_knowledge_base_v2/development_records/ui-evidence/system-config-2026-08-04/comparison.jpg b/ai_knowledge_base_v2/development_records/ui-evidence/system-config-2026-08-04/comparison.jpg new file mode 100644 index 0000000..e4d21ba Binary files /dev/null and b/ai_knowledge_base_v2/development_records/ui-evidence/system-config-2026-08-04/comparison.jpg differ