import { reactive, ref, Ref } from 'vue' import { merge } from 'lodash-es' import { DynamicProps } from '/#/utils' import { BasicTableProps, TableActionType, useTable } from '/@/components/Table' import { ColEx } from '/@/components/Form/src/types' import { FormActionType } from '/@/components/Form' import { useMessage } from '/@/hooks/web/useMessage' import { useMethods } from '/@/hooks/system/useMethods' import { useDesign } from '/@/hooks/web/useDesign' import { filterObj } from '/@/utils/common/compUtils' const { handleExportXls, handleImportXls } = useMethods() // 定义 useListPage 方法所需参数 interface ListPageOptions { // 样式作用域范围 designScope?: string, // 【必填】表格参数配置 tableProps: TableProps, // 分页 pagination?: boolean, // 导出配置 exportConfig?: { url: string, // 导出文件名 name?: string | (() => string), } // 导入配置 importConfig?: { url: string, // 导出成功后的回调 success?: (fileInfo?: any) => void } } interface IDoRequestOptions { // 是否显示确认对话框,默认 true confirm?: boolean, // 是否自动刷新表格,默认 true reload?: boolean, // 是否自动清空选择,默认 true clearSelection?: boolean, } /** * listPage页面公共方法 * * @param options */ export function useListPage(options: ListPageOptions) { const $message = useMessage() let $design = {} as ReturnType if (options.designScope) { $design = useDesign(options.designScope) } const tableContext = useListTable(options.tableProps) const [, { getForm, reload, setLoading }, { selectedRowKeys }] = tableContext // 导出 excel async function onExportXls() { let { url, name } = options?.exportConfig ?? {} if (url) { let title = typeof name === 'function' ? name() : name const params = await getForm().validate() if(selectedRowKeys.value && selectedRowKeys.value.length>0){ params['selections'] = selectedRowKeys.value.join(",") } return handleExportXls(title as string, url,filterObj(params)) } else { $message.createMessage.warn('没有传递 exportConfig.url 参数') return Promise.reject() } } // 导入 excel function onImportXls(file) { let { url,success } = options?.importConfig ?? {} if (url) { return handleImportXls(file, url, success||reload) } else { $message.createMessage.warn('没有传递 importConfig.url 参数') return Promise.reject() } } /** * 通用请求处理方法,可自动刷新表格,自动清空选择 * @param api 请求api * @param options 是否显示确认框 */ function doRequest(api: () => Promise, options?: IDoRequestOptions) { return new Promise((resolve, reject) => { const execute = async () => { try { setLoading(true) const res = await api() if (options?.reload ?? true) { reload() } if (options?.clearSelection ?? true) { selectedRowKeys.value = [] } resolve(res) } catch (e) { reject(e) } finally { setLoading(false) } } if (options?.confirm ?? true) { $message.createConfirm({ iconType: 'warning', title: '删除', content: '确定要删除吗?', onOk: () => execute(), onCancel: () => reject(), }) } else { execute() } }) } /** 执行单个删除操作 */ function doDeleteRecord(api: () => Promise) { return doRequest(api, { confirm: false, clearSelection: false }) } return { ...$design, ...$message, onExportXls, onImportXls, doRequest, doDeleteRecord, tableContext, } } // 定义表格所需参数 type TableProps = Partial>; type UseTableMethod = TableActionType & { getForm: () => FormActionType; }; /** * useListTable 列表页面标准表格参数 * * @param tableProps 表格参数 */ export function useListTable(tableProps: TableProps): [ (instance: TableActionType, formInstance: UseTableMethod) => void, TableActionType & { getForm: () => FormActionType; }, { rowSelection: any, selectedRows: Ref selectedRowKeys: Ref } ] { // 自适应列配置 const adaptiveColProps: Partial = { xs: 24, // <576px sm: 12, // ≥576px md: 12, // ≥768px lg: 8, // ≥992px xl: 8, // ≥1200px xxl: 6, // ≥1600px } const defaultTableProps: TableProps = { rowKey: 'id', // 使用查询条件区域 useSearchForm: true, // 查询条件区域配置 formConfig: { // 紧凑模式 compact: true, // label默认宽度 labelWidth: 120, // 按下回车后自动提交 autoSubmitOnEnter: true, // 默认 row 配置 rowProps: { gutter: 8 }, // 默认 col 配置 baseColProps: { ...adaptiveColProps, }, labelCol: { xs: 24, sm: 8, md: 6, lg: 8, xl: 6, xxl: 6, }, wrapperCol: {}, // 是否显示 展开/收起 按钮 showAdvancedButton: true, // 超过指定列数默认折叠 autoAdvancedCol: 3, // 操作按钮配置 actionColOptions: { ...adaptiveColProps, style: { textAlign: 'left' }, }, }, // 斑马纹 striped: true, // 是否可以自适应高度 canResize: true, // 表格最小高度 minHeight: 500, // 点击行选中 clickToRowSelect: false, // 是否显示边框 bordered: true, // 是否显示序号列 showIndexColumn: false, // 显示表格设置 showTableSetting: true, // 表格设置 tableSetting: { fullScreen: true, }, // 是否显示操作列 showActionColumn: true, // 操作列 actionColumn: { width: 120, title: '操作', //是否锁定操作列取值 right ,left,false fixed: false, dataIndex: 'action', slots: { customRender: 'action' }, }, } // 合并用户个性化配置 if (tableProps) { // merge 方法可深度合并对象 merge(defaultTableProps, tableProps) } // 发送请求之前调用的方法 function beforeFetch(params) { // 默认以 createTime 降序排序 return Object.assign({ column: 'createTime', order: 'desc' }, params) } // 合并方法 Object.assign(defaultTableProps, { beforeFetch }) if (typeof tableProps.beforeFetch === 'function') { defaultTableProps.beforeFetch = function (params) { params = beforeFetch(params) // @ts-ignore tableProps.beforeFetch(params) return params } } // 当前选择的行 const selectedRowKeys = ref([]) // 选择的行记录 const selectedRows = ref([]) // 表格选择列配置 const rowSelection: any = tableProps?.rowSelection ?? {} const defaultRowSelection = reactive({ ...rowSelection, type: rowSelection.type ?? 'checkbox', // 选择列宽度,默认 50 columnWidth: rowSelection.columnWidth ?? 50, selectedRows: selectedRows, selectedRowKeys: selectedRowKeys, onChange(...args) { selectedRowKeys.value = args[0] selectedRows.value = args[1] if (typeof rowSelection.onChange === 'function') { rowSelection.onChange(...args) } }, }) delete defaultTableProps.rowSelection return [ ...useTable(defaultTableProps), { selectedRows, selectedRowKeys, rowSelection: defaultRowSelection, }, ] }