import { DeleteOutlined<#if enableExport>, DownloadOutlined, EditOutlined, PlusOutlined, SortAscendingOutlined } from '@ant-design/icons'; import { ModalForm, PageContainer, <#if needCheckbox> ProFormCheckbox, <#if needDateField> ProFormDateTimePicker, <#if needDigit> ProFormDigit, <#if needSelect> ProFormSelect, <#if needTextArea> ProFormTextArea, ProFormText, ProFormTreeSelect, ProTable, type ActionType, type ProColumns } from '@ant-design/pro-components'; import { useBoolean } from 'ahooks'; import { Button, Form, message<#if enableStatus || needSwitchField>, Switch<#if enableSort>, InputNumber } from 'antd'; import { useMemo, useRef, useState } from 'react'; import type { ${BusinessName}Form, ${BusinessName}Query, ${BusinessName}VO } from '@/api/${moduleName}/${businessName}/types'; import { add${BusinessName}, <#if enableStatus> change${BusinessName}Status, del${BusinessName}, get${BusinessName}, list${BusinessName}, <#if enableSort> update${BusinessName}Sort, update${BusinessName} } from '@/api/${moduleName}/${businessName}'; <#if needDict> import DictTag from '@/components/common/DictTag'; <#if needFileUpload> import FileUpload from '@/components/common/FileUpload'; <#if needImagePreview> import ImagePreview from '@/components/common/ImagePreview'; <#if needImageUpload> import ImageUpload from '@/components/common/ImageUpload'; <#if needEditor> import RichTextEditor from '@/components/common/RichTextEditor'; import RowActions from '@/components/common/RowActions'; <#if needDict> import { useDict } from '@/hooks/useDict'; <#if enableExport> import { useTableExport } from '@/hooks/useTableExport'; import { useTableScroll } from '@/hooks/useTableScroll'; import { useTreeTableExpand } from '@/hooks/useTreeTableExpand'; import { useUserStore } from '@/stores/userStore'; <#if needDict> import { dictOptions } from '@/utils/dict'; <#if enableStatus> import { confirmAction } from '@/utils/modal'; import { hasPermi } from '@/utils/permission'; import { filterTree<#if needDateField>, formatDateTimeFields, handleTree<#if needDateField>, toDayjsFields } from '@/utils/ruoyi'; const default${BusinessName}Form: ${BusinessName}Form = { ${treeParentCode}: ${treeRootValueTsLiteral}, <#list columns as column> <#if (column.insert || column.edit) && !column.pk && column.htmlType == "checkbox"> ${column.javaField}: [], }; interface ${BusinessName}SelectNode { title: string; value: string | number; children?: ${BusinessName}SelectNode[]; } function toTreeSelectData(nodes: ${BusinessName}VO[]): ${BusinessName}SelectNode[] { return nodes.map(node => ({ title: String(node.${treeName} || ''), value: node.${treeCode}, children: node.children ? toTreeSelectData(node.children) : undefined })); } <#if enableStatus> const ${statusField}ActiveValue = <#if statusColumn.javaType == "Boolean">true<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">0<#else>'0'; const ${statusField}InactiveValue = <#if statusColumn.javaType == "Boolean">false<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">1<#else>'1'; export default function ${BusinessName}Page() { const actionRef = useRef(undefined); const { tableScroll } = useTableScroll(1000); const [form] = Form.useForm<${BusinessName}Form>(); const userInfo = useUserStore(state => state.userInfo); <#if needDict> const dicts = useDict(${dicts}); const [treeOptions, setTreeOptions] = useState<${BusinessName}VO[]>([]); const [tableRows, setTableRows] = useState<${BusinessName}VO[]>([]); const { expandAll, expandedRowKeys, onExpandedRowsChange, syncExpandedRows, toggleExpandAll } = useTreeTableExpand<${BusinessName}VO>(row => row.${treeCode}); const [modalOpen, { setTrue: openModal, setFalse: closeModal }] = useBoolean(false); const [modalTitle, setModalTitle] = useState(''); <#if enableExport> const { updateExportParams, exportFile } = useTableExport(); const canAdd = hasPermi(userInfo, ['${permissionPrefix}:add']); const canEdit = hasPermi(userInfo, ['${permissionPrefix}:edit']); const canRemove = hasPermi(userInfo, ['${permissionPrefix}:remove']); <#if enableExport> const canExport = hasPermi(userInfo, ['${permissionPrefix}:export']); const treeSelectData = useMemo( () => [{ title: '顶级节点', value: ${treeRootValueTsLiteral}, children: toTreeSelectData(treeOptions) }], [treeOptions] ); const loadTreeOptions = async (excludeId?: string | number) => { const res = await list${BusinessName}(); const rows = handleTree<${BusinessName}VO>(res.data || [], '${treeCode}', '${treeParentCode}'); setTreeOptions(excludeId ? filterTree(rows, node => node.${treeCode} !== excludeId) : rows); }; const openAdd = async (row?: ${BusinessName}VO) => { await loadTreeOptions(); form.resetFields(); form.setFieldsValue({ ...default${BusinessName}Form, ${treeParentCode}: row?.${treeCode} || treeRootValueTsLiteral }); setModalTitle('添加${functionName}'); openModal(); }; const openEdit = async (row: ${BusinessName}VO) => { await loadTreeOptions(row.${treeCode}); const res = await get${BusinessName}(row.${pkColumn.javaField}); const data = <#if needDateField>toDayjsFields({ ...res.data }, [ <#list columns as column> <#if (column.insert || column.edit) && column.htmlType == "datetime"> '${column.javaField}', ])<#else>{ ...res.data }; <#list columns as column> <#if (column.insert || column.edit) && column.htmlType == "checkbox"> if (typeof data.${column.javaField} === 'string') { data.${column.javaField} = data.${column.javaField}.split(','); } form.resetFields(); form.setFieldsValue(data); setModalTitle('修改${functionName}'); openModal(); }; const submitForm = async (values: ${BusinessName}Form) => { const submitValues = <#if needDateField>formatDateTimeFields({ ...values }, [ <#list columns as column> <#if (column.insert || column.edit) && column.htmlType == "datetime"> '${column.javaField}', ])<#else>{ ...values }; <#list columns as column> <#if (column.insert || column.edit) && column.htmlType == "checkbox"> if (Array.isArray(submitValues.${column.javaField})) { submitValues.${column.javaField} = submitValues.${column.javaField}.join(','); } submitValues.${pkColumn.javaField} ? await update${BusinessName}(submitValues) : await add${BusinessName}(submitValues); message.success('操作成功'); form.resetFields(); actionRef.current?.reload(); return true; }; const remove = async (row: ${BusinessName}VO) => { await del${BusinessName}(row.${pkColumn.javaField}); message.success('删除成功'); actionRef.current?.reload(); }; <#if enableStatus> const handleStatusChange = async (row: ${BusinessName}VO, checked: boolean) => { const previousStatus = row.${statusField}; const status = checked ? ${statusField}ActiveValue : ${statusField}InactiveValue; const text = checked ? '启用' : '停用'; try { await confirmAction(`确认要"${r'${text}'}"吗?`); await change${BusinessName}Status(row.${pkColumn.javaField}, status); message.success(`${r'${text}'}成功`); actionRef.current?.reload(); } catch { row.${statusField} = previousStatus; actionRef.current?.reload(); } }; <#if enableSort> const handleSortChange = async (row: ${BusinessName}VO, value?: number | null) => { await update${BusinessName}Sort(row.${pkColumn.javaField}, value || 0); message.success('排序更新成功'); actionRef.current?.reload(); }; const columns: ProColumns<${BusinessName}VO>[] = [ <#list columns as column> <#if column.list && !column.pk> <#if enableStatus && statusField == column.javaField> { title: '${column.columnLabel}', dataIndex: '${column.javaField}', valueType: 'select', width: 100, <#if column.dictType?has_content> fieldProps: { options: dictOptions(dicts.${column.dictType}) }, render: (_, row) => ( handleStatusChange(row, checked)} /> ) }, <#elseif enableSort && sortField == column.javaField> { title: '${column.columnLabel}', dataIndex: '${column.javaField}', search: false, width: 130, render: (_, row) => handleSortChange(row, value)} /> }, <#elseif column.htmlType == "datetime"> { title: '${column.columnLabel}', dataIndex: '${column.javaField}', valueType: 'dateTime', search: <#if column.query>true<#else> false, width: 170 }, <#elseif column.htmlType == "imageUpload"> { title: '${column.columnLabel}', dataIndex: '${column.javaField}Url', search: false, width: 100, render: (_, row) => }, <#elseif column.dictColumn> { title: '${column.columnLabel}', dataIndex: '${column.javaField}', valueType: 'select', fieldProps: { options: dictOptions(dicts.${column.dictType}) }, render: (_, row) => }, <#elseif column.htmlType == "switch"> { title: '${column.columnLabel}', dataIndex: '${column.javaField}', valueType: 'select', width: 100, render: (_, row) => }, <#else> { title: '${column.columnLabel}', dataIndex: '${column.javaField}'<#if !column.query>, search: false }, { title: '操作', valueType: 'option', width: 130, fixed: 'right', render: (_, row) => ( , onClick: () => openEdit(row) }, canAdd && { key: 'add', label: '新增', icon: , onClick: () => openAdd(row) }, canRemove && { key: 'delete', label: '删除', icon: , danger: true, confirm: `是否确认删除${functionName}编号为"${r'${row.'}${pkColumn.javaField}${r'}'}"的数据项?`, onClick: () => remove(row) } ]} /> ) } ]; return ( actionRef={actionRef} rowKey="${treeCode}" columns={columns} scroll={tableScroll} pagination={false} search={{ labelWidth: 90 }} expandable={{ expandedRowKeys, onExpandedRowsChange }} request={async params => { const res = await list${BusinessName}(params); const rows = handleTree<${BusinessName}VO>(res.data || [], '${treeCode}', '${treeParentCode}'); setTableRows(rows); syncExpandedRows(rows, expandAll); <#if enableExport> updateExportParams(params); return { data: rows, total: rows.length, success: true }; }} toolbar={{ title: '${functionName}列表' }} toolBarRender={() => [ canAdd && ( ), <#if enableExport>, canExport && ( ) ]} /> title={modalTitle} open={modalOpen} width={560} form={form} layout="vertical" initialValues={default${BusinessName}Form} modalProps={{ destroyOnHidden: true, onCancel: closeModal }} onOpenChange={open => !open && closeModal()} onFinish={submitForm} > ); }