feat: 新增系统配置页面

This commit is contained in:
Stev_Wang
2025-12-12 20:01:39 +08:00
parent 5a3d3918ba
commit fb51d51215
15 changed files with 4633 additions and 93 deletions

View File

@@ -0,0 +1,294 @@
/**
* 基本配置标签页组件
* @author MHXY Development Team
* @version 1.0.0
*/
import React, { useState, useEffect } from 'react';
import { Form, Input, Switch, Select, Card, Button, Space, Row, Col, Tooltip } from 'antd';
import {
InfoCircleOutlined,
SaveOutlined,
ReloadOutlined,
HistoryOutlined,
SettingOutlined
} from '@ant-design/icons';
import { SystemConfig, SaveConfigRequest } from '../../types/systemConfig';
const { Option } = Select;
const { TextArea } = Input;
interface BasicConfigTabProps {
configs: SystemConfig[];
loading: boolean;
saving: boolean;
onSave: (requests: SaveConfigRequest[]) => void;
onReset: (configKey: string) => void;
onShowHistory: (configKey: string) => void;
onConfigChange: () => void;
}
const BasicConfigTab: React.FC<BasicConfigTabProps> = ({
configs,
loading,
saving,
onSave,
onReset,
onShowHistory,
onConfigChange
}) => {
const [form] = Form.useForm();
const [formData, setFormData] = useState<Record<string, any>>({});
// 初始化表单数据
useEffect(() => {
const initialData: Record<string, any> = {};
configs.forEach(config => {
initialData[config.config_key] = config.config_value;
});
setFormData(initialData);
form.setFieldsValue(initialData);
}, [configs, form]);
// 处理表单值变化
const handleValuesChange = (changedValues: any, allValues: any) => {
setFormData(allValues);
onConfigChange();
};
// 保存配置
const handleSave = () => {
form.validateFields().then(() => {
const saveRequests: SaveConfigRequest[] = configs.map(config => ({
config_key: config.config_key,
config_value: formData[config.config_key] || '',
config_label: config.config_label,
config_group: config.config_group
}));
onSave(saveRequests);
}).catch(() => {
// 表单验证失败
});
};
// 重置为默认值
const handleReset = (configKey: string) => {
onReset(configKey);
};
// 显示配置历史
const handleShowHistory = (configKey: string) => {
onShowHistory(configKey);
};
// 语言选项
const languageOptions = [
{ value: 'zh-CN', label: '简体中文' },
{ value: 'zh-TW', label: '繁体中文' },
{ value: 'en-US', label: 'English' },
{ value: 'ja-JP', label: '日本語' }
];
// 版本选项
const versionOptions = [
{ value: '1.0.0', label: 'v1.0.0' },
{ value: '1.1.0', label: 'v1.1.0' },
{ value: '2.0.0', label: 'v2.0.0' }
];
const configItems = [
{
key: 'site_name',
title: '网站名称',
description: '系统显示名称,将在页面标题和系统信息中显示',
type: 'input',
placeholder: '请输入网站名称',
required: true
},
{
key: 'site_version',
title: '系统版本',
description: '当前系统版本号,用于显示和版本管理',
type: 'select',
options: versionOptions,
required: true
},
{
key: 'site_description',
title: '系统描述',
description: '系统描述信息,简要介绍系统功能和用途',
type: 'textarea',
placeholder: '请输入系统描述',
rows: 3
},
{
key: 'admin_email',
title: '管理员邮箱',
description: '系统管理员联系邮箱,用于接收系统通知',
type: 'input',
placeholder: '请输入管理员邮箱',
required: true
},
{
key: 'maintenance_mode',
title: '维护模式',
description: '开启后用户无法正常访问系统,仅管理员可以登录',
type: 'switch'
},
{
key: 'default_language',
title: '默认语言',
description: '系统默认语言设置,影响界面显示语言',
type: 'select',
options: languageOptions,
required: true
}
];
return (
<div className="basic-config-tab" style={{ padding: '0' }}>
{/* 配置表单 */}
<Form
form={form}
layout="vertical"
onValuesChange={handleValuesChange}
style={{ marginBottom: '24px' }}
>
<Row gutter={[24, 0]}>
{configItems.map((item, index) => {
const config = configs.find(c => c.config_key === item.key);
if (!config) return null;
return (
<Col span={12} key={item.key}>
<Card
size="small"
style={{ marginBottom: '16px' }}
title={
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<SettingOutlined />
{item.title}
{config.config_type === 'boolean' && (
<Switch
size="small"
checked={formData[item.key] === '1' || formData[item.key] === true}
onChange={(checked) => {
const newValue = checked ? '1' : '0';
form.setFieldValue(item.key, newValue);
onConfigChange();
}}
style={{ marginLeft: '8px' }}
/>
)}
</div>
}
extra={
<Space>
<Tooltip title="查看历史记录">
<Button
type="text"
size="small"
icon={<HistoryOutlined />}
onClick={() => handleShowHistory(item.key)}
/>
</Tooltip>
<Tooltip title="重置为默认值">
<Button
type="text"
size="small"
icon={<ReloadOutlined />}
onClick={() => handleReset(item.key)}
/>
</Tooltip>
</Space>
}
>
<div style={{ marginBottom: '8px' }}>
<div style={{
fontSize: '12px',
color: '#666',
display: 'flex',
alignItems: 'center',
gap: '4px'
}}>
<InfoCircleOutlined />
{item.description}
</div>
</div>
{/* 输入控件 */}
<Form.Item
name={item.key}
rules={[
{ required: item.required, message: `请输入${item.title}` },
...(item.key === 'admin_email' ? [
{ type: 'email', message: '请输入有效的邮箱地址' }
] : [])
]}
>
{item.type === 'input' && (
<Input
placeholder={item.placeholder}
disabled={config.config_type === 'boolean'}
/>
)}
{item.type === 'textarea' && (
<TextArea
placeholder={item.placeholder}
rows={item.rows || 2}
/>
)}
{item.type === 'select' && (
<Select placeholder={item.placeholder}>
{item.options?.map(option => (
<Option key={option.value} value={option.value}>
{option.label}
</Option>
))}
</Select>
)}
</Form.Item>
</Card>
</Col>
);
})}
</Row>
</Form>
{/* 保存按钮 */}
<div style={{
display: 'flex',
justifyContent: 'center',
padding: '24px 0',
borderTop: '1px solid #f0f0f0'
}}>
<Button
type="primary"
size="large"
icon={<SaveOutlined />}
loading={saving}
onClick={handleSave}
style={{ minWidth: '120px' }}
>
</Button>
</div>
{/* 配置信息 */}
<Card size="small" style={{ background: '#fafafa' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '8px' }}>
<InfoCircleOutlined style={{ color: '#1890ff' }} />
<strong></strong>
</div>
<ul style={{ margin: 0, paddingLeft: '20px', fontSize: '12px', color: '#666' }}>
<li></li>
<li>访</li>
<li></li>
<li></li>
</ul>
</Card>
</div>
);
};
export default BasicConfigTab;