#set($needDict = $dicts != '') #set($needImagePreview = false) #set($needImageUpload = false) #set($needFileUpload = false) #set($needEditor = false) #set($needCheckbox = false) #set($needSelect = false) #set($needTextArea = false) #set($needDigit = false) #set($needDateField = false) #set($needSwitchField = false) #foreach($column in $columns) #if($column.list && $column.htmlType == "imageUpload") #set($needImagePreview = true) #end #if(($column.insert || $column.edit) && $column.htmlType == "imageUpload") #set($needImageUpload = true) #end #if(($column.insert || $column.edit) && $column.htmlType == "fileUpload") #set($needFileUpload = true) #end #if(($column.insert || $column.edit) && $column.htmlType == "editor") #set($needEditor = true) #end #if(($column.insert || $column.edit) && $column.htmlType == "checkbox") #set($needCheckbox = true) #end #if(($column.insert || $column.edit || $column.query) && ($column.htmlType == "select" || $column.htmlType == "radio" || $column.htmlType == "switch")) #set($needSelect = true) #end #if(($column.insert || $column.edit) && $column.htmlType == "textarea") #set($needTextArea = true) #end #if(($column.insert || $column.edit) && $column.htmlType == "inputNumber") #set($needDigit = true) #end #if(($column.insert || $column.edit) && $column.htmlType == "datetime") #set($needDateField = true) #end #if(($column.insert || $column.edit || $column.list) && $column.htmlType == "switch") #set($needSwitchField = true) #end #end #macro(comment $column)#set($idx=$column.columnComment.indexOf("("))#if($idx != -1)$column.columnComment.substring(0, $idx)#else$column.columnComment#end#end import { DeleteOutlined#if($enableExport), DownloadOutlined#end, EditOutlined, PlusOutlined, SortAscendingOutlined } from '@ant-design/icons'; import { ModalForm, PageContainer, #if($needCheckbox) ProFormCheckbox, #end #if($needDateField) ProFormDateTimePicker, #end #if($needDigit) ProFormDigit, #end #if($needSelect) ProFormSelect, #end #if($needTextArea) ProFormTextArea, #end ProFormText, ProFormTreeSelect, ProTable, type ActionType, type ProColumns } from '@ant-design/pro-components'; import { useBoolean } from 'ahooks'; import { Button, Form, message#if($enableStatus || $needSwitchField), Switch#end#if($enableSort), InputNumber#end } 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, #end del${BusinessName}, get${BusinessName}, list${BusinessName}, #if($enableSort) update${BusinessName}Sort, #end update${BusinessName} } from '@/api/${moduleName}/${businessName}'; #if($needDict) import DictTag from '@/components/common/DictTag'; #end #if($needFileUpload) import FileUpload from '@/components/common/FileUpload'; #end #if($needImagePreview) import ImagePreview from '@/components/common/ImagePreview'; #end #if($needImageUpload) import ImageUpload from '@/components/common/ImageUpload'; #end #if($needEditor) import RichTextEditor from '@/components/common/RichTextEditor'; #end import RowActions from '@/components/common/RowActions'; #if($needDict) import { useDict } from '@/hooks/useDict'; #end #if($enableExport) import { useTableExport } from '@/hooks/useTableExport'; #end import { useTreeTableExpand } from '@/hooks/useTreeTableExpand'; import { useUserStore } from '@/stores/userStore'; #if($needDict) import { dictOptions } from '@/utils/dict'; #end #if($enableStatus) import { confirmAction } from '@/utils/modal'; #end import { hasPermi } from '@/utils/permission'; import { filterTree#if($needDateField), formatDateTimeFields#end, handleTree#if($needDateField), toDayjsFields#end } from '@/utils/ruoyi'; const default${BusinessName}Form: ${BusinessName}Form = { ${treeParentCode}: ${treeRootValueTsLiteral}, #foreach($column in $columns) #if(($column.insert || $column.edit) && !$column.pk && $column.htmlType == "checkbox") ${column.javaField}: [], #end #end }; 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 })); } #macro(switchActiveValue $column)#if($column.javaType == "Boolean")true#elseif($column.javaType == "Integer" || $column.javaType == "Long")0#else'0'#end#end #macro(switchInactiveValue $column)#if($column.javaType == "Boolean")false#elseif($column.javaType == "Integer" || $column.javaType == "Long")1#else'1'#end#end #if($enableStatus) const ${statusField}ActiveValue = #if($statusColumn.javaType == "Boolean")true#elseif($statusColumn.javaType == "Integer" || $statusColumn.javaType == "Long")0#else'0'#end; const ${statusField}InactiveValue = #if($statusColumn.javaType == "Boolean")false#elseif($statusColumn.javaType == "Integer" || $statusColumn.javaType == "Long")1#else'1'#end; #end export default function ${BusinessName}Page() { const actionRef = useRef(undefined); const [form] = Form.useForm<${BusinessName}Form>(); const userInfo = useUserStore(state => state.userInfo); #if($needDict) const dicts = useDict(${dicts}); #end 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(); #end 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']); #end 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 }, [ #foreach($column in $columns) #if(($column.insert || $column.edit) && $column.htmlType == "datetime") '${column.javaField}', #end #end ])#else{ ...res.data }#end; #foreach($column in $columns) #if(($column.insert || $column.edit) && $column.htmlType == "checkbox") if (typeof data.${column.javaField} === 'string') { data.${column.javaField} = data.${column.javaField}.split(','); } #end #end form.resetFields(); form.setFieldsValue(data); setModalTitle('修改${functionName}'); openModal(); }; const submitForm = async (values: ${BusinessName}Form) => { const submitValues = #if($needDateField)formatDateTimeFields({ ...values }, [ #foreach($column in $columns) #if(($column.insert || $column.edit) && $column.htmlType == "datetime") '${column.javaField}', #end #end ])#else{ ...values }#end; #foreach($column in $columns) #if(($column.insert || $column.edit) && $column.htmlType == "checkbox") if (Array.isArray(submitValues.${column.javaField})) { submitValues.${column.javaField} = submitValues.${column.javaField}.join(','); } #end #end 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(`确认要"${text}"吗?`); await change${BusinessName}Status(row.${pkColumn.javaField}, status); message.success(`${text}成功`); actionRef.current?.reload(); } catch { row.${statusField} = previousStatus; actionRef.current?.reload(); } }; #end #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(); }; #end const columns: ProColumns<${BusinessName}VO>[] = [ #foreach($column in $columns) #set($javaField=$column.javaField) #set($dictType=$column.dictType) #if($column.list && !$column.pk) #if($enableStatus && $statusField == $javaField) { title: '#comment($column)', dataIndex: '${javaField}', valueType: 'select', width: 100, #if("" != $dictType) fieldProps: { options: dictOptions(dicts.${dictType}) }, #end render: (_, row) => ( handleStatusChange(row, checked)} /> ) }, #elseif($enableSort && $sortField == $javaField) { title: '#comment($column)', dataIndex: '${javaField}', search: false, width: 130, render: (_, row) => handleSortChange(row, value)} /> }, #elseif($column.htmlType == "datetime") { title: '#comment($column)', dataIndex: '${javaField}', valueType: 'dateTime', search: #if($column.query)true#else false#end, width: 170 }, #elseif($column.htmlType == "imageUpload") { title: '#comment($column)', dataIndex: '${javaField}Url', search: false, width: 100, render: (_, row) => }, #elseif($column.dictColumn) { title: '#comment($column)', dataIndex: '${javaField}', valueType: 'select', fieldProps: { options: dictOptions(dicts.${dictType}) }, render: (_, row) => }, #elseif($column.htmlType == "switch") { title: '#comment($column)', dataIndex: '${javaField}', valueType: 'select', width: 100, render: (_, row) => }, #else { title: '#comment($column)', dataIndex: '${javaField}'#if(!$column.query), search: false#end }, #end #end #end { 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}编号为"#[[${row.]]#${pkColumn.javaField}#[[}]]#"的数据项?`, onClick: () => remove(row) } ]} /> ) } ]; return ( actionRef={actionRef} rowKey="${treeCode}" columns={columns} scroll={{ x: 1000 }} 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); #end return { data: rows, total: rows.length, success: true }; }} toolbar={{ title: '${functionName}列表' }} toolBarRender={() => [ canAdd && ( ), #if($enableExport), canExport && ( )#end ]} /> 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} > ); }