feat(主题): 实现动态主题颜色配置功能
This commit is contained in:
@@ -3,9 +3,21 @@ import axios from 'axios';
|
||||
|
||||
const ConfigContext = createContext();
|
||||
|
||||
const applyThemeColors = (primaryColor, secondaryColor) => {
|
||||
const root = document.documentElement;
|
||||
if (primaryColor) {
|
||||
root.style.setProperty('--primary-color', primaryColor);
|
||||
root.style.setProperty('--primary-light', `${primaryColor}20`);
|
||||
root.style.setProperty('--primary-gradient', `linear-gradient(135deg, ${primaryColor} 0%, ${secondaryColor || '#764ba2'} 100%)`);
|
||||
}
|
||||
if (secondaryColor) {
|
||||
root.style.setProperty('--secondary-color', secondaryColor);
|
||||
root.style.setProperty('--secondary-light', `${secondaryColor}20`);
|
||||
}
|
||||
};
|
||||
|
||||
export const ConfigProvider = ({ children }) => {
|
||||
const [config, setConfig] = useState({
|
||||
// 默认配置
|
||||
site_name: '机柜管理系统',
|
||||
primary_color: '#667eea',
|
||||
secondary_color: '#764ba2',
|
||||
@@ -21,14 +33,12 @@ export const ConfigProvider = ({ children }) => {
|
||||
});
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
// 加载系统配置
|
||||
const loadConfig = async () => {
|
||||
try {
|
||||
const response = await axios.get('/api/system-settings');
|
||||
const settings = response.data;
|
||||
const configValues = {};
|
||||
|
||||
// 将配置转换为扁平结构
|
||||
Object.entries(settings).forEach(([key, value]) => {
|
||||
configValues[key] = value.value;
|
||||
});
|
||||
@@ -37,6 +47,10 @@ export const ConfigProvider = ({ children }) => {
|
||||
...prev,
|
||||
...configValues,
|
||||
}));
|
||||
|
||||
if (configValues.primary_color || configValues.secondary_color) {
|
||||
applyThemeColors(configValues.primary_color, configValues.secondary_color);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载系统配置失败:', error);
|
||||
} finally {
|
||||
@@ -44,12 +58,16 @@ export const ConfigProvider = ({ children }) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化加载配置
|
||||
useEffect(() => {
|
||||
loadConfig();
|
||||
}, []);
|
||||
|
||||
// 更新配置
|
||||
useEffect(() => {
|
||||
if (config.primary_color || config.secondary_color) {
|
||||
applyThemeColors(config.primary_color, config.secondary_color);
|
||||
}
|
||||
}, [config.primary_color, config.secondary_color]);
|
||||
|
||||
const updateConfig = newConfig => {
|
||||
setConfig(prev => ({
|
||||
...prev,
|
||||
@@ -57,7 +75,6 @@ export const ConfigProvider = ({ children }) => {
|
||||
}));
|
||||
};
|
||||
|
||||
// 重新加载配置
|
||||
const reloadConfig = async () => {
|
||||
await loadConfig();
|
||||
};
|
||||
@@ -69,7 +86,6 @@ export const ConfigProvider = ({ children }) => {
|
||||
);
|
||||
};
|
||||
|
||||
// 自定义钩子,方便组件使用配置
|
||||
export const useConfig = () => {
|
||||
const context = useContext(ConfigContext);
|
||||
if (!context) {
|
||||
|
||||
+12
-4
@@ -1,3 +1,11 @@
|
||||
:root {
|
||||
--primary-color: #667eea;
|
||||
--primary-light: rgba(102, 126, 234, 0.125);
|
||||
--primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
--secondary-color: #764ba2;
|
||||
--secondary-light: rgba(118, 75, 162, 0.125);
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
@@ -349,19 +357,19 @@ body {
|
||||
}
|
||||
|
||||
.ant-btn-primary {
|
||||
background: linear-gradient(135deg, #1890ff 0%, #096dd9 100%) !important;
|
||||
background: var(--primary-gradient) !important;
|
||||
border: none !important;
|
||||
box-shadow: 0 2px 6px rgba(24, 144, 255, 0.35) !important;
|
||||
}
|
||||
|
||||
.ant-btn-primary:hover {
|
||||
background: linear-gradient(135deg, #40a9ff 0%, #1890ff 100%) !important;
|
||||
background: var(--primary-gradient) !important;
|
||||
box-shadow: 0 4px 12px rgba(24, 144, 255, 0.45) !important;
|
||||
transform: translateY(-2px) !important;
|
||||
}
|
||||
|
||||
.ant-btn-primary:active {
|
||||
background: linear-gradient(135deg, #096dd9 0%, #0050b3 100%) !important;
|
||||
background: var(--primary-gradient) !important;
|
||||
box-shadow: 0 2px 6px rgba(24, 144, 255, 0.35) !important;
|
||||
transform: translateY(0) !important;
|
||||
}
|
||||
@@ -871,7 +879,7 @@ body {
|
||||
}
|
||||
|
||||
.welcome-banner {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
background: var(--primary-gradient);
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
color: #fff;
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
ScanOutlined,
|
||||
CheckOutlined,
|
||||
CloseOutlined,
|
||||
PlusOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import axios from 'axios';
|
||||
import dayjs from 'dayjs';
|
||||
@@ -67,6 +68,12 @@ const InventoryTaskExecution = () => {
|
||||
const [scanResult, setScanResult] = useState(null);
|
||||
const [scanModalVisible, setScanModalVisible] = useState(false);
|
||||
const [recordPagination, setRecordPagination] = useState({ current: 1, pageSize: 20, total: 0 });
|
||||
const [quickAddModalVisible, setQuickAddModalVisible] = useState(false);
|
||||
const [quickAddForm] = Form.useForm();
|
||||
const [quickAddLoading, setQuickAddLoading] = useState(false);
|
||||
const [rooms, setRooms] = useState([]);
|
||||
const [racks, setRacks] = useState([]);
|
||||
const [selectedRoomId, setSelectedRoomId] = useState(null);
|
||||
|
||||
const planId = searchParams.get('planId');
|
||||
|
||||
@@ -245,6 +252,84 @@ const InventoryTaskExecution = () => {
|
||||
fetchPlan();
|
||||
}, [fetchPlan]);
|
||||
|
||||
const fetchRooms = async () => {
|
||||
try {
|
||||
const res = await api.get('/rooms');
|
||||
setRooms(res.data.rooms || res.data || []);
|
||||
} catch (error) {
|
||||
console.error('获取机房列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
const fetchRacks = async () => {
|
||||
try {
|
||||
const res = await api.get('/racks');
|
||||
setRacks(res.data.racks || res.data || []);
|
||||
} catch (error) {
|
||||
console.error('获取机柜列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchRooms();
|
||||
fetchRacks();
|
||||
}, []);
|
||||
|
||||
const filteredRacks = selectedRoomId
|
||||
? racks.filter(rack => rack.roomId === selectedRoomId)
|
||||
: racks;
|
||||
|
||||
const handleQuickAddDevice = async (values) => {
|
||||
if (!currentTask || !plan) {
|
||||
message.error('请先选择盘点任务');
|
||||
return;
|
||||
}
|
||||
setQuickAddLoading(true);
|
||||
try {
|
||||
const res = await api.post('/inventory/quick-add-device', {
|
||||
taskId: currentTask.taskId,
|
||||
planId: plan.planId,
|
||||
serialNumber: scanResult?.sn || values.serialNumber,
|
||||
deviceName: values.deviceName,
|
||||
deviceType: values.deviceType,
|
||||
rackId: values.rackId,
|
||||
position: values.position,
|
||||
remark: values.remark
|
||||
});
|
||||
message.success('设备添加成功!');
|
||||
setQuickAddModalVisible(false);
|
||||
quickAddForm.resetFields();
|
||||
setScanResult({
|
||||
success: true,
|
||||
message: `新设备 "${res.data.device.name}" 已添加并完成盘点!`,
|
||||
record: res.data.record,
|
||||
sn: res.data.device.serialNumber
|
||||
});
|
||||
if (currentTask) {
|
||||
fetchTaskRecords(currentTask.taskId);
|
||||
}
|
||||
fetchPlan();
|
||||
} catch (error) {
|
||||
message.error(error.response?.data?.error || '添加设备失败');
|
||||
} finally {
|
||||
setQuickAddLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const openQuickAddModal = () => {
|
||||
setSelectedRoomId(null);
|
||||
quickAddForm.setFieldsValue({
|
||||
serialNumber: scanResult?.sn || '',
|
||||
deviceName: '',
|
||||
deviceType: 'other',
|
||||
roomId: undefined,
|
||||
rackId: undefined,
|
||||
position: undefined,
|
||||
remark: undefined,
|
||||
});
|
||||
setQuickAddModalVisible(true);
|
||||
};
|
||||
|
||||
const handleCheck = (record) => {
|
||||
setCurrentRecord(record);
|
||||
form.setFieldsValue({
|
||||
@@ -912,6 +997,18 @@ const InventoryTaskExecution = () => {
|
||||
</Row>
|
||||
</div>
|
||||
)}
|
||||
{!scanResult.success && scanResult.sn && (
|
||||
<div style={{ textAlign: 'center', marginTop: 16 }}>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<PlusOutlined />}
|
||||
onClick={openQuickAddModal}
|
||||
style={{ borderRadius: 8 }}
|
||||
>
|
||||
快速添加此设备
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1037,6 +1134,130 @@ const InventoryTaskExecution = () => {
|
||||
</Form>
|
||||
)}
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
title={
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||
<PlusOutlined style={{ fontSize: 18, color: '#1890ff' }} />
|
||||
<span>快速添加设备</span>
|
||||
</div>
|
||||
}
|
||||
open={quickAddModalVisible}
|
||||
onCancel={() => {
|
||||
setQuickAddModalVisible(false);
|
||||
setSelectedRoomId(null);
|
||||
}}
|
||||
footer={null}
|
||||
width={500}
|
||||
centered
|
||||
>
|
||||
<Form
|
||||
form={quickAddForm}
|
||||
layout="vertical"
|
||||
onFinish={handleQuickAddDevice}
|
||||
>
|
||||
<Form.Item
|
||||
name="serialNumber"
|
||||
label="序列号"
|
||||
rules={[{ required: true, message: '请输入序列号' }]}
|
||||
>
|
||||
<Input placeholder="请输入设备序列号" disabled />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="deviceName"
|
||||
label="设备名称"
|
||||
>
|
||||
<Input placeholder="请输入设备名称(可选)" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="deviceType"
|
||||
label="设备类型"
|
||||
initialValue="other"
|
||||
>
|
||||
<Select placeholder="请选择设备类型">
|
||||
<Select.Option value="server">服务器</Select.Option>
|
||||
<Select.Option value="switch">交换机</Select.Option>
|
||||
<Select.Option value="router">路由器</Select.Option>
|
||||
<Select.Option value="storage">存储设备</Select.Option>
|
||||
<Select.Option value="other">其他</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="roomId"
|
||||
label="所属机房"
|
||||
>
|
||||
<Select
|
||||
placeholder="请选择机房"
|
||||
allowClear
|
||||
showSearch
|
||||
optionFilterProp="children"
|
||||
onChange={(value) => {
|
||||
setSelectedRoomId(value);
|
||||
quickAddForm.setFieldsValue({ rackId: undefined });
|
||||
}}
|
||||
>
|
||||
{rooms.map(room => (
|
||||
<Select.Option key={room.roomId} value={room.roomId}>
|
||||
{room.name}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="rackId"
|
||||
label="所属机柜"
|
||||
>
|
||||
<Select
|
||||
placeholder={selectedRoomId ? "请选择机柜" : "请先选择机房"}
|
||||
allowClear
|
||||
showSearch
|
||||
optionFilterProp="children"
|
||||
disabled={!selectedRoomId}
|
||||
>
|
||||
{filteredRacks.map(rack => (
|
||||
<Select.Option key={rack.rackId} value={rack.rackId}>
|
||||
{rack.name}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Form.Item
|
||||
name="position"
|
||||
label="U位"
|
||||
>
|
||||
<Input type="number" placeholder="请输入U位(可选)" min={1} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="remark"
|
||||
label="备注"
|
||||
>
|
||||
<Input.TextArea rows={2} placeholder="请输入备注(可选)" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item style={{ marginBottom: 0, textAlign: 'right' }}>
|
||||
<Space>
|
||||
<Button onClick={() => {
|
||||
setQuickAddModalVisible(false);
|
||||
setSelectedRoomId(null);
|
||||
}}>取消</Button>
|
||||
<Button type="primary" htmlType="submit" loading={quickAddLoading}>
|
||||
添加设备
|
||||
</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
Badge,
|
||||
Tooltip,
|
||||
Avatar,
|
||||
ColorPicker,
|
||||
} from 'antd';
|
||||
import {
|
||||
SettingOutlined,
|
||||
@@ -668,18 +669,360 @@ const SystemSettings = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const presetColors = [
|
||||
'#667eea',
|
||||
'#764ba2',
|
||||
'#f093fb',
|
||||
'#4facfe',
|
||||
'#43e97b',
|
||||
'#fa709a',
|
||||
'#fee140',
|
||||
'#00b4db',
|
||||
'#0083b0',
|
||||
'#fcb045',
|
||||
'#1890ff',
|
||||
'#52c41a',
|
||||
'#eb2f96',
|
||||
'#722ed1',
|
||||
'#13c2c2',
|
||||
'#fa8c16',
|
||||
];
|
||||
|
||||
const handleColorChange = (color, key) => {
|
||||
const hexColor = typeof color === 'string' ? color : color.toHexString();
|
||||
form.setFieldValue(key, hexColor);
|
||||
|
||||
const root = document.documentElement;
|
||||
if (key === 'primary_color') {
|
||||
root.style.setProperty('--primary-color', hexColor);
|
||||
root.style.setProperty('--primary-light', `${hexColor}20`);
|
||||
} else if (key === 'secondary_color') {
|
||||
root.style.setProperty('--secondary-color', hexColor);
|
||||
root.style.setProperty('--secondary-light', `${hexColor}20`);
|
||||
}
|
||||
};
|
||||
|
||||
const renderColorFormItem = (key, data) => {
|
||||
const currentValue = form.getFieldValue(key) || settings[key]?.value || '#667eea';
|
||||
|
||||
return (
|
||||
<Form.Item
|
||||
key={key}
|
||||
label={
|
||||
<Space>
|
||||
<span style={{ fontSize: 14, color: '#262626', fontWeight: 500 }}>
|
||||
{data.description || key}
|
||||
</span>
|
||||
<div
|
||||
style={{
|
||||
width: 20,
|
||||
height: 20,
|
||||
borderRadius: 4,
|
||||
backgroundColor: currentValue,
|
||||
border: '1px solid #d9d9d9',
|
||||
boxShadow: '0 1px 2px rgba(0,0,0,0.1)'
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
}
|
||||
name={key}
|
||||
style={{ marginBottom: 0 }}
|
||||
>
|
||||
<Input type="hidden" />
|
||||
</Form.Item>
|
||||
);
|
||||
};
|
||||
|
||||
const renderAppearanceSettings = () => {
|
||||
const primaryColor = form.getFieldValue('primary_color') || settings.primary_color?.value || '#667eea';
|
||||
const secondaryColor = form.getFieldValue('secondary_color') || settings.secondary_color?.value || '#764ba2';
|
||||
|
||||
return (
|
||||
<Form form={form} layout="vertical" onFinish={handleSaveSettings}>
|
||||
<div style={{ paddingBottom: 80 }}>
|
||||
<Alert
|
||||
message="主题颜色设置"
|
||||
description="修改主题颜色后需要刷新页面才能生效。建议选择对比度适中的颜色组合。"
|
||||
description="选择颜色后可实时预览效果,保存设置后永久生效。建议选择对比度适中的颜色组合。"
|
||||
type="info"
|
||||
showIcon
|
||||
style={{ marginBottom: 24, borderRadius: 12 }}
|
||||
/>
|
||||
{settingGroups.appearance.map(group => renderSettingGroup(group))}
|
||||
|
||||
<Card
|
||||
style={{
|
||||
marginBottom: 24,
|
||||
borderRadius: 12,
|
||||
border: '1px solid #e8e8e8',
|
||||
boxShadow: '0 2px 8px rgba(0,0,0,0.04)',
|
||||
}}
|
||||
bodyStyle={{ padding: '24px' }}
|
||||
>
|
||||
<div style={{ textAlign: 'center', marginBottom: 24 }}>
|
||||
<div style={{
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: '50%',
|
||||
background: `linear-gradient(135deg, ${primaryColor} 0%, ${secondaryColor} 100%)`,
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginBottom: 12,
|
||||
}}>
|
||||
<BgColorsOutlined style={{ color: '#fff', fontSize: 24 }} />
|
||||
</div>
|
||||
<div style={{ fontSize: 18, fontWeight: 600, color: '#262626', marginBottom: 6 }}>
|
||||
主题颜色
|
||||
</div>
|
||||
<div style={{ fontSize: 14, color: '#666' }}>
|
||||
自定义系统主题配色方案
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Divider style={{ margin: '0 0 24px 0' }} />
|
||||
|
||||
<Row gutter={[32, 24]}>
|
||||
<Col xs={24} md={12}>
|
||||
<div style={{ marginBottom: 8 }}>
|
||||
<Text strong style={{ fontSize: 14, color: '#262626' }}>主色调</Text>
|
||||
<Text type="secondary" style={{ fontSize: 12, marginLeft: 8 }}>
|
||||
用于按钮、链接等主要交互元素
|
||||
</Text>
|
||||
</div>
|
||||
<Space direction="vertical" style={{ width: '100%' }}>
|
||||
<ColorPicker
|
||||
value={primaryColor}
|
||||
onChange={(color) => handleColorChange(color, 'primary_color')}
|
||||
format="hex"
|
||||
showText
|
||||
presets={[
|
||||
{
|
||||
label: '推荐配色',
|
||||
colors: presetColors,
|
||||
},
|
||||
]}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
<Input
|
||||
value={primaryColor}
|
||||
onChange={(e) => handleColorChange(e.target.value, 'primary_color')}
|
||||
placeholder="#667eea"
|
||||
style={{ borderRadius: 8 }}
|
||||
prefix={<BgColorsOutlined style={{ color: '#bfbfbf' }} />}
|
||||
/>
|
||||
</Space>
|
||||
</Col>
|
||||
<Col xs={24} md={12}>
|
||||
<div style={{ marginBottom: 8 }}>
|
||||
<Text strong style={{ fontSize: 14, color: '#262626' }}>次色调</Text>
|
||||
<Text type="secondary" style={{ fontSize: 12, marginLeft: 8 }}>
|
||||
用于渐变、悬停效果等辅助元素
|
||||
</Text>
|
||||
</div>
|
||||
<Space direction="vertical" style={{ width: '100%' }}>
|
||||
<ColorPicker
|
||||
value={secondaryColor}
|
||||
onChange={(color) => handleColorChange(color, 'secondary_color')}
|
||||
format="hex"
|
||||
showText
|
||||
presets={[
|
||||
{
|
||||
label: '推荐配色',
|
||||
colors: presetColors,
|
||||
},
|
||||
]}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
<Input
|
||||
value={secondaryColor}
|
||||
onChange={(e) => handleColorChange(e.target.value, 'secondary_color')}
|
||||
placeholder="#764ba2"
|
||||
style={{ borderRadius: 8 }}
|
||||
prefix={<BgColorsOutlined style={{ color: '#bfbfbf' }} />}
|
||||
/>
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Divider style={{ margin: '24px 0' }} />
|
||||
|
||||
<div style={{
|
||||
padding: 16,
|
||||
background: '#fafafa',
|
||||
borderRadius: 8,
|
||||
border: '1px solid #f0f0f0'
|
||||
}}>
|
||||
<Text strong style={{ fontSize: 13, color: '#595959', marginBottom: 12, display: 'block' }}>
|
||||
实时预览
|
||||
</Text>
|
||||
<Space size="middle" wrap>
|
||||
<Button
|
||||
type="primary"
|
||||
style={{
|
||||
background: `linear-gradient(135deg, ${primaryColor} 0%, ${secondaryColor} 100%)`,
|
||||
border: 'none'
|
||||
}}
|
||||
>
|
||||
主要按钮
|
||||
</Button>
|
||||
<Button
|
||||
style={{
|
||||
borderColor: primaryColor,
|
||||
color: primaryColor
|
||||
}}
|
||||
>
|
||||
次要按钮
|
||||
</Button>
|
||||
<Tag
|
||||
color={primaryColor}
|
||||
style={{ borderRadius: 4 }}
|
||||
>
|
||||
标签样式
|
||||
</Tag>
|
||||
<div
|
||||
style={{
|
||||
width: 60,
|
||||
height: 24,
|
||||
borderRadius: 4,
|
||||
background: `linear-gradient(135deg, ${primaryColor} 0%, ${secondaryColor} 100%)`,
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
style={{
|
||||
marginBottom: 24,
|
||||
borderRadius: 12,
|
||||
border: '1px solid #e8e8e8',
|
||||
boxShadow: '0 2px 8px rgba(0,0,0,0.04)',
|
||||
}}
|
||||
bodyStyle={{ padding: '24px' }}
|
||||
>
|
||||
<div style={{ textAlign: 'center', marginBottom: 24 }}>
|
||||
<div style={{
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: '50%',
|
||||
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginBottom: 12,
|
||||
}}>
|
||||
<DesktopOutlined style={{ color: '#fff', fontSize: 24 }} />
|
||||
</div>
|
||||
<div style={{ fontSize: 18, fontWeight: 600, color: '#262626', marginBottom: 6 }}>
|
||||
界面布局
|
||||
</div>
|
||||
<div style={{ fontSize: 14, color: '#666' }}>
|
||||
调整界面显示密度和布局方式
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Divider style={{ margin: '0 0 24px 0' }} />
|
||||
|
||||
<Row gutter={[32, 16]}>
|
||||
<Col xs={24} md={8}>
|
||||
<Form.Item
|
||||
label={<span style={{ fontSize: 14, color: '#262626', fontWeight: 500 }}>紧凑模式</span>}
|
||||
name="compact_mode"
|
||||
valuePropName="checked"
|
||||
style={{ marginBottom: 0 }}
|
||||
>
|
||||
<Tooltip title="开启后界面元素间距缩小,显示更多内容">
|
||||
<Switch
|
||||
checkedChildren="开启"
|
||||
unCheckedChildren="关闭"
|
||||
/>
|
||||
</Tooltip>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col xs={24} md={8}>
|
||||
<Form.Item
|
||||
label={<span style={{ fontSize: 14, color: '#262626', fontWeight: 500 }}>侧边栏折叠</span>}
|
||||
name="sidebar_collapsed"
|
||||
valuePropName="checked"
|
||||
style={{ marginBottom: 0 }}
|
||||
>
|
||||
<Tooltip title="开启后侧边栏默认折叠为图标模式">
|
||||
<Switch
|
||||
checkedChildren="开启"
|
||||
unCheckedChildren="关闭"
|
||||
/>
|
||||
</Tooltip>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col xs={24} md={8}>
|
||||
<Form.Item
|
||||
label={<span style={{ fontSize: 14, color: '#262626', fontWeight: 500 }}>表格行高度</span>}
|
||||
name="table_row_height"
|
||||
style={{ marginBottom: 0 }}
|
||||
>
|
||||
<Select
|
||||
placeholder="请选择"
|
||||
style={{ width: '100%', height: 40 }}
|
||||
dropdownStyle={{ borderRadius: 8 }}
|
||||
>
|
||||
{getSelectOptions('table_row_height').map(opt => (
|
||||
<Option key={opt.value} value={opt.value}>{opt.label}</Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
style={{
|
||||
marginBottom: 24,
|
||||
borderRadius: 12,
|
||||
border: '1px solid #e8e8e8',
|
||||
boxShadow: '0 2px 8px rgba(0,0,0,0.04)',
|
||||
}}
|
||||
bodyStyle={{ padding: '24px' }}
|
||||
>
|
||||
<div style={{ textAlign: 'center', marginBottom: 24 }}>
|
||||
<div style={{
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: '50%',
|
||||
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginBottom: 12,
|
||||
}}>
|
||||
<ThunderboltOutlined style={{ color: '#fff', fontSize: 24 }} />
|
||||
</div>
|
||||
<div style={{ fontSize: 18, fontWeight: 600, color: '#262626', marginBottom: 6 }}>
|
||||
动画效果
|
||||
</div>
|
||||
<div style={{ fontSize: 14, color: '#666' }}>
|
||||
控制界面动画和过渡效果
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Divider style={{ margin: '0 0 24px 0' }} />
|
||||
|
||||
<Row gutter={[32, 16]}>
|
||||
<Col xs={24} md={12}>
|
||||
<Form.Item
|
||||
label={<span style={{ fontSize: 14, color: '#262626', fontWeight: 500 }}>启用动画</span>}
|
||||
name="animation_enabled"
|
||||
valuePropName="checked"
|
||||
style={{ marginBottom: 0 }}
|
||||
>
|
||||
<Tooltip title="关闭后可提升低配设备性能">
|
||||
<Switch
|
||||
checkedChildren="开启"
|
||||
unCheckedChildren="关闭"
|
||||
/>
|
||||
</Tooltip>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
</div>
|
||||
{renderFixedFooter()}
|
||||
</Form>
|
||||
|
||||
Reference in New Issue
Block a user