import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { Alert, App, Button, Drawer, Form, Input, Popconfirm, Select, Space, Switch, Table, Tag, Tooltip, Typography } from 'antd'; import { DeleteOutlined, EditOutlined, PlusOutlined, ReloadOutlined, SaveOutlined, SettingOutlined } from '@ant-design/icons'; import httpService from '../../services/httpService'; import { API_ENDPOINTS, buildApiUrl } from '../../config/api'; import AdminModuleShell from '../../components/AdminModuleShell'; import ActionButton from '../../components/ActionButton'; import StatusTag from '../../components/StatusTag'; import configService from '../../utils/configService'; import useSystemPageSize from '../../hooks/useSystemPageSize'; const { Text } = Typography; const CATEGORY_OPTIONS = [ { label: 'public', value: 'public' }, { label: 'system', value: 'system' }, ]; const VALUE_TYPE_OPTIONS = [ { label: 'string', value: 'string' }, { label: 'number', value: 'number' }, { label: 'json', value: 'json' }, ]; const PUBLIC_PARAM_KEYS = new Set([ 'app_name', 'page_size', 'max_audio_size', 'preview_title', 'login_welcome', 'footer_text', 'console_subtitle', ]); const ParameterManagement = () => { const { message } = App.useApp(); const [items, setItems] = useState([]); const [loading, setLoading] = useState(false); const [drawerOpen, setDrawerOpen] = useState(false); const [editing, setEditing] = useState(null); const [submitting, setSubmitting] = useState(false); const [form] = Form.useForm(); const pageSize = useSystemPageSize(10); const currentParamKey = Form.useWatch('param_key', form); const categorySuggestion = useMemo(() => { const normalizedKey = String(currentParamKey || '').trim(); if (!normalizedKey) { return '前端需要读取并缓存的参数请选择 public,仅后端内部使用的参数请选择 system。'; } if (PUBLIC_PARAM_KEYS.has(normalizedKey)) { return `检测到参数键 ${normalizedKey} 更适合作为 public 参数,前端会统一初始化并缓存本地。`; } return `参数键 ${normalizedKey} 暂未命中公开参数白名单,如仅后端使用,建议归类为 system。`; }, [currentParamKey]); const fetchItems = useCallback(async () => { setLoading(true); try { const res = await httpService.get(buildApiUrl(API_ENDPOINTS.ADMIN.PARAMETERS)); setItems(res.data.items || []); } catch { message.error('获取参数列表失败'); } finally { setLoading(false); } }, [message]); useEffect(() => { fetchItems(); }, [fetchItems]); const openCreate = () => { setEditing(null); form.setFieldsValue({ param_key: '', param_name: '', param_value: '', value_type: 'string', category: 'system', description: '', is_active: true, }); setDrawerOpen(true); }; const openEdit = (row) => { setEditing(row); form.setFieldsValue({ ...row, is_active: Boolean(row.is_active), }); setDrawerOpen(true); }; const submit = async () => { const values = await form.validateFields(); setSubmitting(true); try { if (editing) { await httpService.put(buildApiUrl(API_ENDPOINTS.ADMIN.PARAMETER_DETAIL(editing.param_key)), values); message.success('参数更新成功'); } else { await httpService.post(buildApiUrl(API_ENDPOINTS.ADMIN.PARAMETERS), values); message.success('参数创建成功'); } configService.clearCache(); setDrawerOpen(false); fetchItems(); } catch (error) { message.error(error?.response?.data?.message || '参数保存失败'); } finally { setSubmitting(false); } }; const columns = [ { title: '参数键', dataIndex: 'param_key', key: 'param_key', width: 220 }, { title: '参数名', dataIndex: 'param_name', key: 'param_name', width: 180 }, { title: '值', dataIndex: 'param_value', key: 'param_value' }, { title: '类型', dataIndex: 'value_type', key: 'value_type', width: 100, render: (v) => {v} }, { title: '分类', dataIndex: 'category', key: 'category', width: 120, render: (value) => ( {value || 'system'} ), }, { title: '状态', dataIndex: 'is_active', key: 'is_active', width: 90, render: (v) => , }, { title: '操作', key: 'action', width: 90, render: (_, row) => ( } onClick={() => openEdit(row)} /> { try { await httpService.delete(buildApiUrl(API_ENDPOINTS.ADMIN.PARAMETER_DELETE(row.param_key))); configService.clearCache(); message.success('参数删除成功'); fetchItems(); } catch (error) { message.error(error?.response?.data?.message || '参数删除失败'); } }} > } /> ), }, ]; return (
} title="参数管理" subtitle="系统参数已从字典 system_config 迁移到专用参数表。" rightActions={( )} stats={[ { label: '参数总数', value: items.length }, { label: '启用参数', value: items.filter((item) => item.is_active).length }, ]} >
`共 ${count} 条` }} scroll={{ x: 1100 }} /> setDrawerOpen(false)} extra={( )} >
`public`:前端可读取,适合页面交互参数。 `system`:仅后端内部使用,不对前端公开。 )} />
); }; export default ParameterManagement;