Files
MYXY_Web/src/pages/tabs/BasicConfigTab.tsx
2025-12-12 20:01:39 +08:00

294 lines
9.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 基本配置标签页组件
* @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;