From 5638bdcf1c4a0f19ea74ae0c5c1f600d7729cd67 Mon Sep 17 00:00:00 2001 From: Dallas98 <40557804+Dallas98@users.noreply.github.com> Date: Fri, 14 Nov 2025 18:05:40 +0800 Subject: [PATCH] feat: add file copying functionality to dataset directory and update base path configuration --- .../interfaces/rest/TagController.java | 2 +- .../SysParamApplicationService.java | 5 +- .../interfaces/rest/SysParamController.java | 10 +- .../interfaces/rest/dto/ParamRequest.java | 4 + .../src/pages/SettingsPage/ModelAccess.tsx | 2 +- .../src/pages/SettingsPage/SettingsPage.tsx | 20 +- .../src/pages/SettingsPage/SystemConfig.tsx | 360 ++++++++++-------- .../src/pages/SettingsPage/settings.apis.ts | 10 + scripts/db/setting-management-init.sql | 20 +- 9 files changed, 248 insertions(+), 185 deletions(-) create mode 100644 backend/shared/domain-common/src/main/java/com/datamate/common/setting/interfaces/rest/dto/ParamRequest.java diff --git a/backend/services/data-management-service/src/main/java/com/datamate/datamanagement/interfaces/rest/TagController.java b/backend/services/data-management-service/src/main/java/com/datamate/datamanagement/interfaces/rest/TagController.java index 476caeb..2e10606 100644 --- a/backend/services/data-management-service/src/main/java/com/datamate/datamanagement/interfaces/rest/TagController.java +++ b/backend/services/data-management-service/src/main/java/com/datamate/datamanagement/interfaces/rest/TagController.java @@ -74,7 +74,7 @@ public class TagController { } @DeleteMapping - public ResponseEntity> deleteTag(@RequestParam(value = "ids") @Valid @Size(max = 10) List ids) { + public ResponseEntity> deleteTag(@RequestParam(value = "ids") @Valid @Size(max = 10) List ids) { try { tagApplicationService.deleteTag(ids.stream().filter(StringUtils::isNoneBlank).distinct().toList()); return ResponseEntity.ok(Response.ok(null)); diff --git a/backend/shared/domain-common/src/main/java/com/datamate/common/setting/application/SysParamApplicationService.java b/backend/shared/domain-common/src/main/java/com/datamate/common/setting/application/SysParamApplicationService.java index 9e6404c..d83a9bb 100644 --- a/backend/shared/domain-common/src/main/java/com/datamate/common/setting/application/SysParamApplicationService.java +++ b/backend/shared/domain-common/src/main/java/com/datamate/common/setting/application/SysParamApplicationService.java @@ -10,6 +10,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; +import java.util.Comparator; import java.util.List; /** @@ -31,7 +32,9 @@ public class SysParamApplicationService { * @return 系统参数列表 */ public List list() { - return sysParamRepository.list(); + List sysParams = sysParamRepository.list(); + sysParams.sort(Comparator.comparing(SysParam::getParamType)); + return sysParams; } /** diff --git a/backend/shared/domain-common/src/main/java/com/datamate/common/setting/interfaces/rest/SysParamController.java b/backend/shared/domain-common/src/main/java/com/datamate/common/setting/interfaces/rest/SysParamController.java index f3904e5..b5d08cd 100644 --- a/backend/shared/domain-common/src/main/java/com/datamate/common/setting/interfaces/rest/SysParamController.java +++ b/backend/shared/domain-common/src/main/java/com/datamate/common/setting/interfaces/rest/SysParamController.java @@ -1,6 +1,7 @@ package com.datamate.common.setting.interfaces.rest; import com.datamate.common.setting.application.SysParamApplicationService; +import com.datamate.common.setting.interfaces.rest.dto.ParamRequest; import com.datamate.common.setting.domain.entity.SysParam; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; @@ -29,15 +30,15 @@ public class SysParamController { return sysParamApplicationService.list(); } - /** + /** * 根据参数id修改系统参数值 * * @param paramId 参数id - * @param paramValue 参数值 + * @param paramRequest 参数值请求体 */ @PutMapping("/{paramId}") - public void updateParamValueById(@PathVariable("paramId") String paramId, @RequestBody String paramValue) { - sysParamApplicationService.updateParamValueById(paramId, paramValue); + public void updateParamValueById(@PathVariable("paramId") String paramId, @RequestBody ParamRequest paramRequest) { + sysParamApplicationService.updateParamValueById(paramId, paramRequest.paramValue()); } /** @@ -50,3 +51,4 @@ public class SysParamController { sysParamApplicationService.deleteParamById(paramId); } } + diff --git a/backend/shared/domain-common/src/main/java/com/datamate/common/setting/interfaces/rest/dto/ParamRequest.java b/backend/shared/domain-common/src/main/java/com/datamate/common/setting/interfaces/rest/dto/ParamRequest.java new file mode 100644 index 0000000..70e8a26 --- /dev/null +++ b/backend/shared/domain-common/src/main/java/com/datamate/common/setting/interfaces/rest/dto/ParamRequest.java @@ -0,0 +1,4 @@ +package com.datamate.common.setting.interfaces.rest.dto; + +public record ParamRequest(String paramValue, boolean isEnabled) { +} diff --git a/frontend/src/pages/SettingsPage/ModelAccess.tsx b/frontend/src/pages/SettingsPage/ModelAccess.tsx index ab848f0..da60908 100644 --- a/frontend/src/pages/SettingsPage/ModelAccess.tsx +++ b/frontend/src/pages/SettingsPage/ModelAccess.tsx @@ -53,7 +53,7 @@ interface ProviderI { isEnabled: boolean; } -export default function EnvironmentAccess() { +export default function ModelAccess() { const [form] = Form.useForm(); const [showModelDialog, setShowModelDialog] = useState(false); const [isEditMode, setIsEditMode] = useState(false); diff --git a/frontend/src/pages/SettingsPage/SettingsPage.tsx b/frontend/src/pages/SettingsPage/SettingsPage.tsx index aac949d..4be1004 100644 --- a/frontend/src/pages/SettingsPage/SettingsPage.tsx +++ b/frontend/src/pages/SettingsPage/SettingsPage.tsx @@ -27,16 +27,16 @@ export default function SettingsPage() { icon: , label: "模型接入", }, - // { - // key: "system-config", - // icon: , - // label: "参数配置", - // }, - // { - // key: "webhook-config", - // icon: , - // label: "Webhook", - // }, + { + key: "system-config", + icon: , + label: "参数配置", + }, + { + key: "webhook-config", + icon: , + label: "Webhook", + }, ]} selectedKeys={[activeTab]} onClick={({ key }) => { diff --git a/frontend/src/pages/SettingsPage/SystemConfig.tsx b/frontend/src/pages/SettingsPage/SystemConfig.tsx index c43ec4e..7e3f1fa 100644 --- a/frontend/src/pages/SettingsPage/SystemConfig.tsx +++ b/frontend/src/pages/SettingsPage/SystemConfig.tsx @@ -1,107 +1,205 @@ -import { Divider, Input, Select, Switch, Button, Form, App, Table } from "antd"; -import { PlusOutlined } from "@ant-design/icons"; -import { useState } from "react"; +import { Divider, Input, Select, Switch, Button, Table, Spin } from "antd"; +import { useEffect, useState } from "react"; +import { getSysParamList, updateSysParamValue } from './settings.apis'; + +interface SystemParam { + id: string; + paramKey: string; + paramValue: string; + description: string; + isEnabled: boolean; + paramType?: string; + optionList?: string; + isBuiltIn?: boolean; + canModify?: boolean; +} export default function SystemConfig() { - const { message } = App.useApp(); - // System Settings State - const [systemConfig, setSystemConfig] = useState({ - siteName: "DataMate", - maxFileSize: "100", - autoBackup: true, - logLevel: "info", - sessionTimeout: "30", - enableNotifications: true, - }); - const configData = [ - { - key: "1", - parameter: "站点名称", - value: systemConfig.siteName, - description: "系统的显示名称", - }, - { - key: "2", - parameter: "最大文件大小 (MB)", - value: systemConfig.maxFileSize, - description: "允许上传的最大文件大小", - }, - { - key: "3", - parameter: "自动备份", - value: systemConfig.autoBackup ? "启用" : "禁用", - description: "定期自动备份系统数据", - }, - { - key: "4", - parameter: "日志级别", - value: systemConfig.logLevel, - description: "系统日志的详细程度", - }, - { - key: "5", - parameter: "会话超时 (分钟)", - value: systemConfig.sessionTimeout, - description: "用户会话的超时时间", - }, - ]; + const [sysParams, setSysParams] = useState([]); + const [loading, setLoading] = useState(true); + const [editingParams, setEditingParams] = useState>({}); + const [tempEditingValues, setTempEditingValues] = useState>({}); - const logLevelOptions = [ - { value: "debug", label: "Debug" }, - { value: "info", label: "Info" }, - { value: "warn", label: "Warning" }, - { value: "error", label: "Error" }, - ]; - - const handleSaveSystemSettings = () => { - // Save system settings logic - console.log("Saving system settings:", systemConfig); - message.success("系统设置已保存"); + // 获取系统参数列表 + const fetchSysParams = async () => { + try { + setLoading(true); + const response = await getSysParamList(); + setSysParams(response.data || []); + // 初始化编辑状态 + const initialEditState: Record = {}; + response.data?.forEach((param: SystemParam) => { + initialEditState[param.id] = param.paramValue; + }); + setEditingParams(initialEditState); + } catch (error) { + console.error('获取系统参数失败:', error); + } finally { + setLoading(false); + } }; + // 组件加载时获取数据 + useEffect(() => { + fetchSysParams(); + }, []); + + // 处理参数值更新 - 立即更新(用于开关和下拉框) + const handleImmediateUpdate = async (param: SystemParam, newValue: string | boolean) => { + try { + const stringValue = typeof newValue === 'boolean' ? newValue.toString() : newValue; + // 更新本地临时状态 + setTempEditingValues(prev => ({ ...prev, [param.id]: stringValue })); + setEditingParams(prev => ({ ...prev, [param.id]: stringValue })); + + // 调用后端更新接口 - 修改为适应新的接口格式 + await updateSysParamValue({ + id: param.id, + paramValue: stringValue + }); + + // 更新本地状态 + setSysParams(prev => prev.map(p => + p.id === param.id ? { ...p, paramValue: stringValue } : p + )); + } catch (error) { + console.error('更新参数失败:', error); + // 恢复原始值 + setEditingParams(prev => ({ ...prev, [param.id]: param.paramValue })); + setTempEditingValues(prev => ({ ...prev, [param.id]: param.paramValue })); + } + }; + + // 处理输入框值变化 - 仅更新临时状态 + const handleInputChange = (param: SystemParam, newValue: string) => { + setTempEditingValues(prev => ({ ...prev, [param.id]: newValue })); + }; + + // 处理输入框失焦 - 发起后端请求 + const handleInputBlur = async (param: SystemParam) => { + const newValue = tempEditingValues[param.id]; + if (newValue !== undefined && newValue !== param.paramValue) { + try { + // 调用后端更新接口 + await updateSysParamValue({ + id: param.id, + paramValue: newValue + }); + + // 更新本地状态 + setSysParams(prev => prev.map(p => + p.id === param.id ? { ...p, paramValue: newValue } : p + )); + setEditingParams(prev => ({ ...prev, [param.id]: newValue })); + } catch (error) { + console.error('更新参数失败:', error); + // 恢复原始值 + setTempEditingValues(prev => ({ ...prev, [param.id]: param.paramValue })); + setEditingParams(prev => ({ ...prev, [param.id]: param.paramValue })); + } + } + }; + + + // 获取选项列表 - 解析逗号分隔的字符串 + const getOptionList = (optionListStr?: string) => { + if (!optionListStr) return []; + try { + // 按逗号分割字符串并去除首尾空格 + return optionListStr.split(',').map(option => ({ + value: option.trim(), + label: option.trim() + })); + } catch (error) { + console.error('解析选项列表失败:', error); + return []; + } + }; + + // 表格列定义 const columns = [ { - title: "参数", - dataIndex: "parameter", - key: "parameter", + title: "参数名", + dataIndex: "paramKey", + key: "paramKey", + width: 180, + }, { - title: "值", - dataIndex: "value", - key: "value", + title: "参数值", + dataIndex: "paramValue", + key: "paramValue", + width: 200, + render: (value: string, record: SystemParam) => { + // 使用临时编辑值或当前值 + const displayValue = tempEditingValues[record.id] ?? editingParams[record.id] ?? value; + + // 对于boolean类型,使用开关按钮 + if (record.paramType === 'boolean') { + const isChecked = displayValue.toLowerCase() === 'true'; + return ( + handleImmediateUpdate(record, checked)} + disabled={!record.canModify} + /> + ); + } + + // 对于有选项列表的参数,强制使用下拉框 + if (record.optionList && record.optionList.trim()) { + const options = getOptionList(record.optionList); + return ( + handleInputChange(record, e.target.value)} + onBlur={() => handleInputBlur(record)} + disabled={!record.canModify} + style={{ width: '150px' }} + /> + ); + } + + // 默认为文本输入 + return ( + handleInputChange(record, e.target.value)} + onBlur={() => handleInputBlur(record)} + disabled={!record.canModify} + style={{ width: '150px' }} + /> + ); + }, }, { title: "描述", dataIndex: "description", key: "description", + width: 300, }, { title: "是否启用", - dataIndex: "enabled", - key: "enabled", - render: (_: any, record: any) => ( - { - if (record.key === "3") { - setSystemConfig((prevConfig) => ({ - ...prevConfig, - autoBackup: checked, - })); - } else if (record.key === "5") { - setSystemConfig((prevConfig) => ({ - ...prevConfig, - enableNotifications: checked, - })); - } - }} - /> + dataIndex: "isEnabled", + key: "isEnabled", + width: 100, + render: (isEnabled: boolean) => ( + ), } ]; @@ -109,82 +207,24 @@ export default function SystemConfig() { return (
-

参数配置

- +

系统参数配置

+
- - { - setSystemConfig((prevConfig) => ({ - ...prevConfig, - ...changedValues, - })); - }} - layout="vertical" - > -
- - - - - - - - - - - - + {loading ? ( +
+
- -
-

功能开关

-
-
-
- 自动备份 -

定期自动备份系统数据

-
- - - -
-
-
- 启用通知 -

接收系统通知和提醒

-
- - - -
-
-
-
- -
- + ) : ( +
+ )} ); -} +} \ No newline at end of file diff --git a/frontend/src/pages/SettingsPage/settings.apis.ts b/frontend/src/pages/SettingsPage/settings.apis.ts index 3efbc2d..d7bdd80 100644 --- a/frontend/src/pages/SettingsPage/settings.apis.ts +++ b/frontend/src/pages/SettingsPage/settings.apis.ts @@ -28,3 +28,13 @@ export function deleteModelByIdUsingDelete(id: string | number) { return del(`/api/models/${id}`); } + +// 获取系统参数列表 +export function getSysParamList() { + return get('/api/sys-param/list'); +} + +// 更新系统参数值 +export const updateSysParamValue = async (params: { id: string; paramValue: string }) => { + return put(`/api/sys-param/${params.id}`, params); +}; \ No newline at end of file diff --git a/scripts/db/setting-management-init.sql b/scripts/db/setting-management-init.sql index f33e4f0..cf440c0 100644 --- a/scripts/db/setting-management-init.sql +++ b/scripts/db/setting-management-init.sql @@ -23,8 +23,8 @@ CREATE TABLE IF NOT EXISTS t_sys_param id VARCHAR(36) PRIMARY KEY COMMENT '主键ID', param_key VARCHAR(100) NOT NULL COMMENT '设置项键', param_value TEXT NOT NULL COMMENT '设置项值', - param_type VARCHAR(50) DEFAULT 'string' COMMENT '设置项类型(如 string、integer、boolean)', - option_list TEXT COMMENT '选项列表(如 JSON 格式,仅对 enum 类型有效)', + param_type VARCHAR(50) DEFAULT 'string' COMMENT '设置项类型(仅 string、number、boolean 三种类型)', + option_list TEXT COMMENT '选项列表(逗号分隔,仅对 enum 类型有效)', description VARCHAR(255) DEFAULT '' COMMENT '设置项描述', is_built_in TINYINT DEFAULT 0 COMMENT '是否内置:1-是,0-否', can_modify TINYINT DEFAULT 1 COMMENT '是否可修改:1-可修改,0-不可修改', @@ -37,10 +37,14 @@ CREATE TABLE IF NOT EXISTS t_sys_param ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT ='设置管理表'; -insert ignore into t_sys_param (id, param_key, param_value, param_type, option_list, description, is_built_in, can_modify, - is_enabled, created_by, updated_by) -values ('1', 'sys.knowledge.base.count', '200', 'integer', '', '知识库最大数量', 1, 1, 1, 'system', 'system'), +insert ignore into t_sys_param (id, param_key, param_value, param_type, option_list, description, is_built_in, + can_modify, + is_enabled, created_by, updated_by) +values ('1', 'sys.knowledge.base.count', '200', 'number', '10,200,500', '知识库最大数量', 1, 1, 1, 'system', 'system'), ('2', 'SEARCH_API', 'tavily', 'string', '', 'deer-flow使用的搜索引擎', 1, 1, 1, 'system', 'system'), - ('3', 'TAVILY_API_KEY', 'tvly-dev-xxx', 'string', '', 'deer-flow使用的搜索引擎所需的apiKey', 1, 1, 1, 'system', 'system'), - ('4', 'BRAVE_SEARCH_API_KEY', 'api-xxx', 'string', '', 'deer-flow使用的搜索引擎所需的apiKey', 1, 1, 1, 'system', 'system'), - ('5', 'JINA_API_KEY', '', 'string', '', 'deer-flow使用的JINA搜索引擎所需的apiKey', 1, 1, 1, 'system', 'system'); + ('3', 'TAVILY_API_KEY', 'tvly-dev-xxx', 'string', '', 'deer-flow使用的搜索引擎所需的apiKey', 1, 1, 1, 'system', + 'system'), + ('4', 'BRAVE_SEARCH_API_KEY', 'api-xxx', 'string', '', 'deer-flow使用的搜索引擎所需的apiKey', 1, 1, 1, 'system', + 'system'), + ('5', 'JINA_API_KEY', '', 'string', '', 'deer-flow使用的JINA搜索引擎所需的apiKey', 1, 1, 1, 'system', 'system'), + ('6', 'test_bool', 'true', 'boolean', '', '测试布尔值', 1, 1, 1, 'system', 'system');