feat(ops): kb doc edit, validation auto-tickets, support batch ops
Add knowledge document GET/PUT and admin edit UI; auto-create support tickets on client 400 validation errors across user/shop/partner apps; batch create tasks and publish from support tickets; restore mini-user store env single-column layout. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -18,6 +18,7 @@ import type { ColumnsType } from 'antd/es/table';
|
||||
import { UploadOutlined } from '@ant-design/icons';
|
||||
import type {
|
||||
KnowledgeBaseDto,
|
||||
KnowledgeDocumentDetailDto,
|
||||
KnowledgeDocumentDto,
|
||||
} from '@dukang/shared-types';
|
||||
import { request } from '../lib/api';
|
||||
@@ -49,6 +50,10 @@ export default function KnowledgeBasesPage() {
|
||||
const [docsLoading, setDocsLoading] = useState(false);
|
||||
const [docModalOpen, setDocModalOpen] = useState(false);
|
||||
const [docSaving, setDocSaving] = useState(false);
|
||||
const [editingDoc, setEditingDoc] = useState<KnowledgeDocumentDto | null>(null);
|
||||
const [editDocModalOpen, setEditDocModalOpen] = useState(false);
|
||||
const [editDocSaving, setEditDocSaving] = useState(false);
|
||||
const [editDocForm] = Form.useForm<DocForm>();
|
||||
|
||||
const { data, loading, page, pageSize, setPage, setPageSize, reload } =
|
||||
useAdminList<KnowledgeBaseDto>(
|
||||
@@ -195,28 +200,52 @@ export default function KnowledgeBasesPage() {
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
width: 80,
|
||||
width: 140,
|
||||
render: (_, row) =>
|
||||
drawerKb?.canEditFull ? (
|
||||
<Popconfirm
|
||||
title="删除文档?"
|
||||
onConfirm={async () => {
|
||||
try {
|
||||
await request(`/admin/knowledge-bases/${drawerKb.id}/documents/${row.id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
message.success('已删除');
|
||||
void loadDocs(drawerKb);
|
||||
reload();
|
||||
} catch (e) {
|
||||
message.error(e instanceof Error ? e.message : String(e));
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Button type="link" size="small" danger>
|
||||
删除
|
||||
<Space>
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
onClick={async () => {
|
||||
if (!drawerKb) return;
|
||||
try {
|
||||
const detail = await request<KnowledgeDocumentDetailDto>(
|
||||
`/admin/knowledge-bases/${drawerKb.id}/documents/${row.id}`,
|
||||
);
|
||||
setEditingDoc(row);
|
||||
editDocForm.setFieldsValue({
|
||||
title: detail.title,
|
||||
contentText: detail.contentText || '',
|
||||
});
|
||||
setEditDocModalOpen(true);
|
||||
} catch (e) {
|
||||
message.error(e instanceof Error ? e.message : String(e));
|
||||
}
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
<Popconfirm
|
||||
title="删除文档?"
|
||||
onConfirm={async () => {
|
||||
try {
|
||||
await request(`/admin/knowledge-bases/${drawerKb.id}/documents/${row.id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
message.success('已删除');
|
||||
void loadDocs(drawerKb);
|
||||
reload();
|
||||
} catch (e) {
|
||||
message.error(e instanceof Error ? e.message : String(e));
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Button type="link" size="small" danger>
|
||||
删除
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
) : null,
|
||||
},
|
||||
];
|
||||
@@ -398,6 +427,50 @@ export default function KnowledgeBasesPage() {
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
title="编辑知识文档"
|
||||
open={editDocModalOpen}
|
||||
onCancel={() => {
|
||||
setEditDocModalOpen(false);
|
||||
setEditingDoc(null);
|
||||
}}
|
||||
confirmLoading={editDocSaving}
|
||||
onOk={async () => {
|
||||
if (!drawerKb || !editingDoc) return;
|
||||
const values = await editDocForm.validateFields();
|
||||
setEditDocSaving(true);
|
||||
try {
|
||||
await request(`/admin/knowledge-bases/${drawerKb.id}/documents/${editingDoc.id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({
|
||||
title: values.title,
|
||||
contentText: values.contentText || null,
|
||||
}),
|
||||
});
|
||||
message.success('已保存');
|
||||
setEditDocModalOpen(false);
|
||||
setEditingDoc(null);
|
||||
void loadDocs(drawerKb);
|
||||
reload();
|
||||
} catch (e) {
|
||||
message.error(e instanceof Error ? e.message : String(e));
|
||||
} finally {
|
||||
setEditDocSaving(false);
|
||||
}
|
||||
}}
|
||||
destroyOnClose
|
||||
width={640}
|
||||
>
|
||||
<Form form={editDocForm} layout="vertical">
|
||||
<Form.Item name="title" label="标题" rules={[{ required: true }]}>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item name="contentText" label="正文(可粘贴)">
|
||||
<Input.TextArea rows={8} placeholder="支持 Markdown / 纯文本" />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user