fix: 低优先级收尾 — 图片上传/语言编辑/插件恢复/URL 编码
- P3-2: ArticleEditor 图片上传接入 /upload 端点 + 封面图上传按钮 - P4-3: recover_plugins 添加 tenant 日志 + 同 ID 去重保护 - P4-4: LanguageManager 编辑弹窗改为真实表单 (name 字段) + 后端 name 持久化 - P4-6: Settings API getSetting/updateSetting 添加 encodeURIComponent
This commit is contained in:
@@ -8,6 +8,8 @@ import {
|
||||
Typography,
|
||||
message,
|
||||
Card,
|
||||
Form,
|
||||
Input,
|
||||
} from 'antd';
|
||||
import { EditOutlined } from '@ant-design/icons';
|
||||
import {
|
||||
@@ -16,13 +18,12 @@ import {
|
||||
type LanguageInfo,
|
||||
} from '../../api/languages';
|
||||
|
||||
// --- Component ---
|
||||
|
||||
export default function LanguageManager() {
|
||||
const [languages, setLanguages] = useState<LanguageInfo[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [editModalOpen, setEditModalOpen] = useState(false);
|
||||
const [editingLang, setEditingLang] = useState<LanguageInfo | null>(null);
|
||||
const [form] = Form.useForm<{ name: string }>();
|
||||
|
||||
const fetchLanguages = useCallback(async () => {
|
||||
setLoading(true);
|
||||
@@ -39,8 +40,6 @@ export default function LanguageManager() {
|
||||
fetchLanguages();
|
||||
}, [fetchLanguages]);
|
||||
|
||||
// --- Enable / Disable Toggle ---
|
||||
|
||||
const handleToggle = async (record: LanguageInfo, checked: boolean) => {
|
||||
try {
|
||||
await updateLanguage(record.code, { is_active: checked });
|
||||
@@ -55,24 +54,25 @@ export default function LanguageManager() {
|
||||
}
|
||||
};
|
||||
|
||||
// --- Edit Modal ---
|
||||
|
||||
const openEdit = (lang: LanguageInfo) => {
|
||||
setEditingLang(lang);
|
||||
form.setFieldsValue({ name: lang.name });
|
||||
setEditModalOpen(true);
|
||||
};
|
||||
|
||||
const closeEdit = () => {
|
||||
setEditModalOpen(false);
|
||||
setEditingLang(null);
|
||||
form.resetFields();
|
||||
};
|
||||
|
||||
const handleEditSubmit = async () => {
|
||||
if (!editingLang) return;
|
||||
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
const updated = await updateLanguage(editingLang.code, {
|
||||
is_active: editingLang.is_active,
|
||||
name: values.name,
|
||||
});
|
||||
setLanguages((prev) =>
|
||||
prev.map((lang) =>
|
||||
@@ -82,6 +82,7 @@ export default function LanguageManager() {
|
||||
message.success('语言更新成功');
|
||||
closeEdit();
|
||||
} catch (err: unknown) {
|
||||
if (err && typeof err === 'object' && 'errorFields' in err) return;
|
||||
const errorMsg =
|
||||
(err as { response?: { data?: { message?: string } } })?.response?.data
|
||||
?.message || '更新失败';
|
||||
@@ -89,8 +90,6 @@ export default function LanguageManager() {
|
||||
}
|
||||
};
|
||||
|
||||
// --- Columns ---
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '语言代码',
|
||||
@@ -113,13 +112,6 @@ export default function LanguageManager() {
|
||||
<Switch checked={is_active} onChange={(checked) => handleToggle(record, checked)} />
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '状态标签',
|
||||
key: 'statusLabel',
|
||||
width: 140,
|
||||
render: (_: unknown, record: LanguageInfo) =>
|
||||
record.is_active ? '已启用' : '已禁用',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'actions',
|
||||
@@ -153,22 +145,25 @@ export default function LanguageManager() {
|
||||
/>
|
||||
</Card>
|
||||
|
||||
{/* Edit Modal */}
|
||||
<Modal
|
||||
title={`语言详情 - ${editingLang?.name ?? ''}`}
|
||||
title={`编辑语言 - ${editingLang?.code ?? ''}`}
|
||||
open={editModalOpen}
|
||||
onCancel={closeEdit}
|
||||
onOk={() => handleEditSubmit()}
|
||||
onOk={handleEditSubmit}
|
||||
okText="保存"
|
||||
>
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<strong>语言代码:</strong>{editingLang?.code}
|
||||
</div>
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<strong>语言名称:</strong>{editingLang?.name}
|
||||
</div>
|
||||
<div>
|
||||
<strong>状态:</strong>{editingLang?.is_active ? '已启用' : '已禁用'}
|
||||
</div>
|
||||
<Form form={form} layout="vertical" style={{ marginTop: 16 }}>
|
||||
<Form.Item label="语言代码">
|
||||
<Input value={editingLang?.code} disabled />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="语言名称"
|
||||
name="name"
|
||||
rules={[{ required: true, message: '请输入语言名称' }]}
|
||||
>
|
||||
<Input placeholder="例如:简体中文" maxLength={100} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user