- Run cargo fmt on all Rust crates for consistent formatting - Update CLAUDE.md with WASM plugin commands and dev.ps1 instructions - Update wiki: add WASM plugin architecture, rewrite dev environment docs - Minor frontend cleanup (unused imports)
99 lines
2.7 KiB
TypeScript
99 lines
2.7 KiB
TypeScript
import { useEffect, useState, useCallback } from 'react';
|
|
import { Form, Input, Select, Button, ColorPicker, message, Typography } from 'antd';
|
|
import {
|
|
getTheme,
|
|
updateTheme,
|
|
} from '../../api/themes';
|
|
|
|
// --- Component ---
|
|
|
|
export default function ThemeSettings() {
|
|
const [form] = Form.useForm();
|
|
const [, setLoading] = useState(false);
|
|
const [saving, setSaving] = useState(false);
|
|
|
|
const fetchTheme = useCallback(async () => {
|
|
setLoading(true);
|
|
try {
|
|
const theme = await getTheme();
|
|
form.setFieldsValue({
|
|
primary_color: theme.primary_color || '#1677ff',
|
|
logo_url: theme.logo_url || '',
|
|
sidebar_style: theme.sidebar_style || 'light',
|
|
});
|
|
} catch {
|
|
// Theme may not exist yet; use defaults
|
|
form.setFieldsValue({
|
|
primary_color: '#1677ff',
|
|
logo_url: '',
|
|
sidebar_style: 'light',
|
|
});
|
|
}
|
|
setLoading(false);
|
|
}, [form]);
|
|
|
|
useEffect(() => {
|
|
fetchTheme();
|
|
}, [fetchTheme]);
|
|
|
|
const handleSave = async (values: {
|
|
primary_color: string;
|
|
logo_url: string;
|
|
sidebar_style: 'light' | 'dark';
|
|
}) => {
|
|
setSaving(true);
|
|
try {
|
|
await updateTheme({
|
|
primary_color:
|
|
typeof values.primary_color === 'string'
|
|
? values.primary_color
|
|
: (values.primary_color as { toHexString?: () => string }).toHexString?.() ?? String(values.primary_color),
|
|
logo_url: values.logo_url,
|
|
sidebar_style: values.sidebar_style,
|
|
});
|
|
message.success('主题设置已保存');
|
|
} catch (err: unknown) {
|
|
const errorMsg =
|
|
(err as { response?: { data?: { message?: string } } })?.response?.data
|
|
?.message || '保存失败';
|
|
message.error(errorMsg);
|
|
}
|
|
setSaving(false);
|
|
};
|
|
|
|
return (
|
|
<div>
|
|
<Typography.Title level={5} style={{ marginBottom: 16 }}>
|
|
主题设置
|
|
</Typography.Title>
|
|
|
|
<Form
|
|
form={form}
|
|
onFinish={handleSave}
|
|
layout="vertical"
|
|
style={{ maxWidth: 480 }}
|
|
>
|
|
<Form.Item name="primary_color" label="主色调">
|
|
<ColorPicker format="hex" />
|
|
</Form.Item>
|
|
<Form.Item name="logo_url" label="Logo URL">
|
|
<Input placeholder="https://example.com/logo.png" />
|
|
</Form.Item>
|
|
<Form.Item name="sidebar_style" label="侧边栏风格">
|
|
<Select
|
|
options={[
|
|
{ label: '亮色', value: 'light' },
|
|
{ label: '暗色', value: 'dark' },
|
|
]}
|
|
/>
|
|
</Form.Item>
|
|
<Form.Item>
|
|
<Button type="primary" htmlType="submit" loading={saving}>
|
|
保存
|
|
</Button>
|
|
</Form.Item>
|
|
</Form>
|
|
</div>
|
|
);
|
|
}
|