forked from yoone/WEB
1
0
Fork 0
WEB/src/pages/Template/index.tsx

442 lines
12 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.

import {
templatecontrollerCreatetemplate,
templatecontrollerDeletetemplate,
templatecontrollerGettemplatelist,
templatecontrollerRendertemplate,
templatecontrollerRendertemplatedirect,
templatecontrollerUpdatetemplate,
} from '@/servers/api/template';
import { EditOutlined, PlusOutlined, ReloadOutlined } from '@ant-design/icons';
import {
ActionType,
DrawerForm,
PageContainer,
ProColumns,
ProForm,
ProFormText,
ProTable,
} from '@ant-design/pro-components';
import Editor from '@monaco-editor/react';
import { App, Button, Card, Popconfirm, Space, Typography } from 'antd';
import { useEffect, useRef, useState } from 'react';
// 自定义hook用于处理模板预览逻辑
const useTemplatePreview = () => {
const [renderedResult, setRenderedResult] = useState<string>('');
const [previewData, setPreviewData] = useState<any>(null);
// 防抖的预览效果
useEffect(() => {
if (!previewData || !previewData.value) {
setRenderedResult('请输入模板内容');
return;
}
const timer = setTimeout(async () => {
let testData = {};
try {
if (previewData.testData) {
testData = JSON.parse(previewData.testData);
}
} catch (e) {
testData = {};
}
try {
// 使用新的直接渲染API传入模板内容和测试数据
const res = await templatecontrollerRendertemplatedirect({
template: previewData.value,
data: testData,
});
if (res.success) {
setRenderedResult(res.data as unknown as string);
} else {
setRenderedResult(`错误: ${res.message}`);
}
} catch (error: any) {
setRenderedResult(`错误: ${error.message}`);
}
}, 500); // 防抖 500ms
return () => clearTimeout(timer);
}, [previewData]);
// 处理实时预览逻辑
const handlePreview = (_changedValues: any, allValues: any) => {
setPreviewData(allValues);
};
// 手动刷新预览
const refreshPreview = (formValues: any) => {
setPreviewData(formValues);
};
return {
renderedResult,
handlePreview,
refreshPreview,
setPreviewData
};
};
const List: React.FC = () => {
const actionRef = useRef<ActionType>();
const { message } = App.useApp();
const columns: ProColumns<API.Template>[] = [
{
title: '名称',
dataIndex: 'name',
tip: '名称是唯一的 key',
formItemProps: {
rules: [
{
required: true,
message: '名称为必填项',
},
],
},
},
{
title: '标题',
dataIndex: 'title',
},
{
title: '值',
dataIndex: 'value',
},
{
title: '更新时间',
dataIndex: 'updatedAt',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '创建时间',
dataIndex: 'createdAt',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '操作',
dataIndex: 'option',
valueType: 'option',
render: (_, record) => (
<Space>
<UpdateForm tableRef={actionRef} values={record} />
<Popconfirm
title="删除"
description="确认删除?"
onConfirm={async () => {
if (!record.id) return;
try {
await templatecontrollerDeletetemplate({ id: record.id });
actionRef.current?.reload();
} catch (error: any) {
message.error(error.message);
}
}}
>
<Button type="primary" danger>
</Button>
</Popconfirm>
</Space>
),
},
];
return (
<PageContainer header={{ title: '模板列表' }}>
<ProTable<API.Template>
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
toolBarRender={() => [<CreateForm tableRef={actionRef} />]}
request={async (params) => {
const response = (await templatecontrollerGettemplatelist(
params as any,
)) as any;
return {
data: response.items || [],
total: response.total || 0,
success: true,
};
}}
columns={columns}
/>
</PageContainer>
);
};
const CreateForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
}> = ({ tableRef }) => {
const { message } = App.useApp();
const [form] = ProForm.useForm();
const { renderedResult, handlePreview, refreshPreview } = useTemplatePreview();
return (
<DrawerForm<API.CreateTemplateDTO>
title="新建"
form={form}
trigger={
<Button type="primary">
<PlusOutlined />
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnHidden: true,
width: 1200, // 增加抽屉宽度以容纳调试面板
}}
onValuesChange={handlePreview}
onFinish={async (values) => {
try {
await templatecontrollerCreatetemplate(values);
tableRef.current?.reload();
message.success('提交成功');
return true;
} catch (error: any) {
message.error(error.message);
return false;
}
}}
>
<div style={{ display: 'flex', gap: '20px' }}>
<div style={{ flex: 1 }}>
<ProFormText
name="name"
label="模板名称"
placeholder="请输入名称"
rules={[{ required: true, message: '请输入名称' }]}
/>
<ProForm.Item
name="value"
label="模板内容"
rules={[{ required: true, message: '请输入模板内容' }]}
>
<Editor
height="400px"
defaultLanguage="html"
options={{
minimap: { enabled: false },
lineNumbers: 'on',
scrollBeyondLastLine: false,
automaticLayout: true,
}}
/>
</ProForm.Item>
<ProForm.Item
name="testData"
label="测试数据 (JSON)"
rules={[
{
validator: (_: any, value: any) => {
if (!value) return Promise.resolve();
try {
JSON.parse(value);
return Promise.resolve();
} catch (e) {
return Promise.reject(new Error('请输入有效的JSON格式'));
}
},
},
]}
>
<Editor
height="200px"
defaultLanguage="json"
options={{
minimap: { enabled: false },
lineNumbers: 'on',
scrollBeyondLastLine: false,
automaticLayout: true,
formatOnPaste: true,
formatOnType: true,
}}
/>
</ProForm.Item>
</div>
<div style={{ flex: 1 }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '8px' }}>
<Typography.Title level={5} style={{ margin: 0 }}></Typography.Title>
<Button
type="text"
icon={<ReloadOutlined />}
onClick={() => {
// 获取当前表单数据并触发预览
const currentValues = form.getFieldsValue();
refreshPreview(currentValues);
}}
title="手动刷新预览"
/>
</div>
<Card
styles={{
body: {
padding: '16px',
height: '600px',
overflow: 'auto',
backgroundColor: '#f5f5f5',
}
}}
>
<pre style={{ whiteSpace: 'pre-wrap', margin: 0 }}>
{renderedResult || '修改模板或测试数据后将自动预览结果...'}
</pre>
</Card>
</div>
</div>
</DrawerForm>
);
};
const UpdateForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
values: API.Template;
}> = ({ tableRef, values: initialValues }) => {
const { message } = App.useApp();
const [form] = ProForm.useForm();
const { renderedResult, handlePreview, refreshPreview, setPreviewData } = useTemplatePreview();
// 组件挂载时初始化预览数据
useEffect(() => {
if (initialValues) {
setPreviewData({
name: initialValues.name,
value: initialValues.value,
testData: initialValues.testData
});
}
}, [initialValues, setPreviewData]);
return (
<DrawerForm<API.UpdateTemplateDTO>
title="编辑"
form={form}
initialValues={initialValues}
trigger={
<Button type="primary">
<EditOutlined />
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnHidden: true,
width: 1200, // 增加抽屉宽度以容纳调试面板
}}
onValuesChange={handlePreview}
onFinish={async (values) => {
if (!initialValues.id) return false;
try {
await templatecontrollerUpdatetemplate(
{ id: initialValues.id },
values,
);
message.success('提交成功');
tableRef.current?.reload();
return true;
} catch (error: any) {
message.error(error.message);
return false;
}
}}
>
<div style={{ display: 'flex', gap: '20px' }}>
<div style={{ flex: 1 }}>
<ProFormText
name="name"
label="模板名称"
placeholder="请输入名称"
rules={[{ required: true, message: '请输入名称' }]}
/>
<ProForm.Item
name="value"
label="模板内容"
rules={[{ required: true, message: '请输入模板内容' }]}
>
<Editor
height="400px"
defaultLanguage="html"
options={{
minimap: { enabled: false },
lineNumbers: 'on',
scrollBeyondLastLine: false,
automaticLayout: true,
}}
/>
</ProForm.Item>
<ProForm.Item
name="testData"
label="测试数据 (JSON)"
rules={[
{
validator: (_: any, value: any) => {
if (!value) return Promise.resolve();
try {
JSON.parse(value);
return Promise.resolve();
} catch (e) {
return Promise.reject(new Error('请输入有效的JSON格式'));
}
},
},
]}
>
<Editor
height="200px"
defaultLanguage="json"
options={{
minimap: { enabled: false },
lineNumbers: 'on',
scrollBeyondLastLine: false,
automaticLayout: true,
formatOnPaste: true,
formatOnType: true,
}}
/>
</ProForm.Item>
</div>
<div style={{ flex: 1 }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '8px' }}>
<Typography.Title level={5} style={{ margin: 0 }}></Typography.Title>
<Button
type="text"
icon={<ReloadOutlined />}
onClick={() => {
// 获取当前表单数据并触发预览
const currentValues = form.getFieldsValue();
refreshPreview(currentValues);
}}
title="手动刷新预览"
/>
</div>
<Card
styles={{
body: {
padding: '16px',
height: '600px',
overflow: 'auto',
backgroundColor: '#f5f5f5',
}
}}
>
<pre style={{ whiteSpace: 'pre-wrap', margin: 0 }}>
{renderedResult || '修改模板或测试数据后将自动预览结果...'}
</pre>
</Card>
</div>
</div>
</DrawerForm>
);
};
export default List;