From f0af965412d80a3601a91a95763e188edf4447f7 Mon Sep 17 00:00:00 2001 From: molong Date: Thu, 19 Feb 2026 12:06:13 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=85=8D=E7=BD=AE=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../setting/components/SaveConfigDialog.vue | 34 +-- .../admin/src/pages/system/setting/index.vue | 195 +++++++++--------- 2 files changed, 112 insertions(+), 117 deletions(-) diff --git a/resources/admin/src/pages/system/setting/components/SaveConfigDialog.vue b/resources/admin/src/pages/system/setting/components/SaveConfigDialog.vue index 9a89744..0ab50d3 100644 --- a/resources/admin/src/pages/system/setting/components/SaveConfigDialog.vue +++ b/resources/admin/src/pages/system/setting/components/SaveConfigDialog.vue @@ -2,24 +2,24 @@ - + - - + + -
建议使用小写字母、下划线命名
+
建议使用小写字母、下划线命名
- - + + - - + + 字符串 文本 数字 @@ -32,7 +32,7 @@ - +
@@ -60,26 +60,26 @@ {{ getDisplayValue(formData.default_value) }} - - -
可选,使用 Laravel 验证规则语法
+ + +
可选,使用 Laravel 验证规则语法
- + -
数字越小排序越靠前
+
数字越小排序越靠前
- - + + - 系统配置项 + 系统配置项 - 仅可修改配置值 diff --git a/resources/admin/src/pages/system/setting/index.vue b/resources/admin/src/pages/system/setting/index.vue index 3bdb72f..96072e9 100644 --- a/resources/admin/src/pages/system/setting/index.vue +++ b/resources/admin/src/pages/system/setting/index.vue @@ -7,9 +7,9 @@ 新增配置项 - + -
+
@@ -51,7 +51,7 @@
- + 编辑 @@ -95,7 +95,6 @@ const configs = ref({}) const formData = reactive({}) const jsonStrings = reactive({}) const jsonErrors = reactive({}) -const visibleEditIcon = ref(null) // 是否可以编辑系统配置 const canEditSystem = ref(false) @@ -122,16 +121,6 @@ const getColumnSpan = (type) => { return 8 } -// ===== 显示编辑图标 ===== -const showEditIcon = (id) => { - visibleEditIcon.value = id -} - -// ===== 隐藏编辑图标 ===== -const hideEditIcon = () => { - visibleEditIcon.value = null -} - // ===== 加载配置分组 ===== const loadGroups = async () => { try { @@ -262,35 +251,40 @@ const handleSave = async () => { return } + // 检查是否有需要保存的配置 + const configList = Object.values(configs.value).flat() + if (configList.length === 0) { + message.warning('暂无配置项可保存') + return + } + // 构建更新数据 - const updates = {} + const updates = [] Object.keys(formData).forEach((key) => { - const config = Object.values(configs.value) - .flat() - .find((c) => c.key === key) + const config = configList.find((c) => c.key === key) if (config) { let value = formData[key] // 转换 checkbox 类型为数组字符串 if (config.type === 'checkbox') { value = JSON.stringify(value) } - updates[key] = value + // 转换 file 类型为 JSON 字符串 + else if (config.type === 'file' && Array.isArray(value) && value.length > 0) { + value = JSON.stringify(value) + } + updates.push({ id: config.id, value }) } }) + if (updates.length === 0) { + message.warning('暂无配置项需要保存') + return + } + // 批量更新 try { saving.value = true - const promises = Object.entries(updates).map(([key, value]) => { - const config = Object.values(configs.value) - .flat() - .find((c) => c.key === key) - if (!config || (config.is_system && !canEditSystem.value)) { - return Promise.resolve() - } - return systemApi.config.edit.put(config.id, { value }) - }) - + const promises = updates.map((update) => systemApi.config.edit.put(update.id, { value: update.value })) await Promise.all(promises) message.success('保存成功') // 重新加载配置 @@ -320,7 +314,7 @@ const handleReset = () => { // ===== 编辑配置项 ===== const handleEditConfig = (config) => { - currentConfig.value = { ...config } + currentConfig.value = config dialog.save = true } @@ -356,6 +350,7 @@ onMounted(async () => { flex-direction: column; height: 100%; padding: 0; + background: #f5f5f5; .content-wrapper { flex: 1; @@ -363,23 +358,63 @@ onMounted(async () => { display: flex; background: #fff; margin: 16px; - padding: 10px; + border-radius: 8px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03); .config-tabs { width: 100%; display: flex; - :deep(.ant-tabs-content-holder) { - flex: 1; - overflow-y: auto; + flex-direction: column; + + :deep(.ant-tabs-nav) { + margin-bottom: 0; + padding: 0 8px; + background: #fafafa; + border-bottom: 1px solid #f0f0f0; + border-radius: 8px 8px 0 0; } :deep(.ant-tabs-tab) { - text-align: left; - padding: 12px 16px; + padding: 12px 20px; + font-size: 14px; + font-weight: 500; + transition: all 0.3s; + + &:hover { + color: #1890ff; + } + + &.ant-tabs-tab-active { + color: #1890ff; + background: #fff; + border-top: 2px solid #1890ff; + } } - :deep(.ant-tabs-left > .ant-tabs-nav .ant-tabs-tab-active) { - background-color: #e6f7ff; + :deep(.ant-tabs-ink-bar) { + display: none; + } + + :deep(.ant-tabs-content) { + flex: 1; + overflow: hidden; + display: flex; + } + + :deep(.ant-tabs-tabpane) { + height: 100%; + overflow: hidden; + display: flex; + } + + :deep(.ant-tabs-content-holder) { + flex: 1; + overflow-y: auto; + padding: 16px; + } + + :deep(.ant-form) { + width: 100%; } } @@ -389,74 +424,34 @@ onMounted(async () => { } .footer-bar { - padding: 12px 24px; + padding: 16px 24px; border-top: 1px solid #f0f0f0; - background: #fafafa; + background: #fff; display: flex; justify-content: flex-end; - } + align-items: center; + box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.04); + z-index: 10; - .config-item { - margin-bottom: 16px; - - .config-item-wrapper { - padding: 16px; - border: 1px solid #f0f0f0; + .ant-btn { border-radius: 6px; - transition: all 0.2s; - - &:hover { - border-color: #d9d9d9; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); - } - - .config-label { - margin-bottom: 8px; - - .label-text { - display: block; - font-size: 14px; - font-weight: 500; - color: #262626; - margin-bottom: 4px; - } - - .label-desc { - display: block; - font-size: 12px; - color: #8c8c8c; - } - } - - .config-input-wrapper { - position: relative; - - .edit-btn { - position: absolute; - right: 8px; - top: 50%; - transform: translateY(-50%); - padding: 4px 8px; - font-size: 12px; - } - - .config-upload { - :deep(.ant-upload-list) { - margin-top: 8px; - } - } - - .json-editor-wrapper { - position: relative; - - .json-error { - margin-top: 4px; - color: #ff4d4f; - font-size: 12px; - } - } - } + height: 36px; + padding: 0 24px; + font-weight: 500; } } } + +.config-input-wrapper { + display: flex; + align-items: center; + justify-items: center; + + .edit-btn { + padding: 4px 8px; + font-size: 12px; + background: rgba(255, 255, 255, 0.95); + border-radius: 4px; + } +}