import { reactive, ref, Ref, unref } 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';
import { isFunction } from '@/utils/is';
const { handleExportXls, handleImportXls } = useMethods();
// 定义 useListPage 方法所需参数
interface ListPageOptions {
// 样式作用域范围
designScope?: string;
// 【必填】表格参数配置
tableProps: TableProps & {
// 添加 defSort 类型定义
defSort?: DefSort;
};
// 是否分页
pagination?: boolean;
// 导出配置
exportConfig?: {
url: string | (() => string);
// 导出文件名
name?: string | (() => string);
//导出参数
params?: object | (() => object);
};
// 导入配置
importConfig?: {
//update-begin-author:taoyan date:20220507 for: erp代码生成 子表 导入地址是动态的
url: string | (() => string);
//update-end-author:taoyan date:20220507 for: erp代码生成 子表 导入地址是动态的
// 导出成功后的回调
success?: (fileInfo?: any) => void;
};
}
interface IDoRequestOptions {
// 是否显示确认对话框,默认 true
confirm?: boolean;
// 是否自动刷新表格,默认 true
reload?: boolean;
// 是否自动清空选择,默认 true
clearSelection?: boolean;
}
interface DefSort {
column: string;
order: 'asc' | 'desc';
}
/**
* listPage页面公共方法
*
* @param options
*/
export function useListPage(options: ListPageOptions) {
const $message = useMessage();
let $design = {} as ReturnType<typeof useDesign>;
if (options.designScope) {
$design = useDesign(options.designScope);
}
const tableContext = useListTable(options.tableProps);
const [, { getForm, reload, setLoading }, { selectedRowKeys }] = tableContext;
// 导出 excel
async function onExportXls() {
//update-begin---author:wangshuai ---date:20220411 for:导出新增自定义参数------------
let { url, name, params } = options?.exportConfig ?? {};
let realUrl = typeof url === 'function' ? url() : url;
if (realUrl) {
let title = typeof name === 'function' ? name() : name;
//update-begin-author:taoyan date:20220507 for: erp代码生成 子表 导出报错,原因未知-
let paramsForm:any = {};
try {
//update-begin-author:liusq---date:2025-03-20--for: [QQYUN-11627]代码生成原生表单,数据导出,前端报错,并且范围参数没有转换 #7962
//当useSearchFor不等于false的时候,才去触发validate
if (options?.tableProps?.useSearchForm !== false) {
paramsForm = await getForm().validate();
console.log('paramsForm', paramsForm);
}
//update-end-author:liusq---date:2025-03-20--for:[QQYUN-11627]代码生成原生表单,数据导出,前端报错,并且范围参数没有转换 #7962
} catch (e) {
console.warn(e);
}
//update-end-author:taoyan date:20220507 for: erp代码生成 子表 导出报错,原因未知-
//update-begin-author:liusq date:20230410 for:[/issues/409]导出功能没有按排序结果导出,设置导出默认排序,创建时间倒序
// 获取表格的默认排序
const { defSort } = options?.tableProps ?? {};
if (defSort && !paramsForm?.column) {
// 使用类型断言确保 defSort 类型正确
Object.assign(paramsForm, {
column: (defSort as DefSort).column,
order: (defSort as DefSort).order,
});
} else if (!paramsForm?.column) {
// 如果没有默认排序,则使用创建时间倒序
Object.assign(paramsForm, { column: 'createTime', order: 'desc' });
}
//update-begin-author:liusq date:20230410 for: [/issues/409]导出功能没有按排序结果导出,设置导出默认排序,创建时间倒序
//如果参数不为空,则整合到一起
//update-begin-author:taoyan date:20220507 for: erp代码生成 子表 导出动态设置mainId
if (params) {
//update-begin-author:liusq---date:2025-03-20--for: [QQYUN-11627]代码生成原生表单,数据导出,前端报错,并且范围参数没有转换 #7962
const realParams = isFunction(params) ? await params() : { ...(params || {}) };
//update-end-author:liusq---date:2025-03-20--for:[QQYUN-11627]代码生成原生表单,数据导出,前端报错,并且范围参数没有转换 #7962
Object.keys(realParams).map((k) => {
let temp = (realParams as object)[k];
if (temp) {
paramsForm[k] = unref(temp);
}
});
}
//update-end-author:taoyan date:20220507 for: erp代码生成 子表 导出动态设置mainId
if (selectedRowKeys.value && selectedRowKeys.value.length > 0) {
paramsForm['selections'] = selectedRowKeys.value.join(',');
}
console.log()
return handleExportXls(title as string, realUrl, filterObj(paramsForm));
//update-end---author:wangshuai ---date:20220411 for:导出新增自定义参数--------------
} else {
$message.createMessage.warn('没有传递 exportConfig.url 参数');
return Promise.reject();
}
}
// 导入 excel
function onImportXls(file) {
let { url, success } = options?.importConfig ?? {};
//update-begin-author:taoyan date:20220507 for: erp代码生成 子表 导入地址是动态的
let realUrl = typeof url === 'function' ? url() : url;
if (realUrl) {
return handleImportXls(file, realUrl, success || reload);
//update-end-author:taoyan date:20220507 for: erp代码生成 子表 导入地址是动态的
} else {
$message.createMessage.warn('没有传递 importConfig.url 参数');
return Promise.reject();
}
}
/**
* 通用请求处理方法,可自动刷新表格,自动清空选择
* @param api 请求api
* @param options 是否显示确认框
*/
function doRequest(api: () => Promise<any>, 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<any>) {
return doRequest(api, { confirm: false, clearSelection: false });
}
return {
...$design,
...$message,
onExportXls,
onImportXls,
doRequest,
doDeleteRecord,
tableContext,
};
}
// 定义表格所需参数
type TableProps = Partial<DynamicProps<BasicTableProps>>;
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<Recordable[]>;
selectedRowKeys: Ref<any[]>;
}
] {
// 自适应列配置
const adaptiveColProps: Partial<ColEx> = {
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: false,
// 是否可以自适应高度
canResize: true,
// 表格最小高度
// update-begin--author:liaozhiyang---date:20240603---for【TV360X-861】列表查询区域不可往上滚动
minHeight: 300,
// update-end--author:liaozhiyang---date:20240603---for【TV360X-861】列表查询区域不可往上滚动
// 点击行选中
clickToRowSelect: false,
// 是否显示边框
bordered: true,
// 是否显示序号列
showIndexColumn: false,
// 显示表格设置
showTableSetting: true,
// 表格全屏设置
tableSetting: {
fullScreen: false,
},
// 是否显示操作列
showActionColumn: true,
// 操作列
actionColumn: {
width: 120,
title: '操作',
//是否锁定操作列取值 right ,left,false
fixed: false,
dataIndex: 'action',
slots: { customRender: 'action' },
},
};
// 合并用户个性化配置
if (tableProps) {
//update-begin---author:wangshuai---date:2024-04-28---for:【issues/6180】前端代码配置表变查询条件显示列不生效---
if(tableProps.formConfig){
setTableProps(tableProps.formConfig);
}
//update-end---author:wangshuai---date:2024-04-28---for:【issues/6180】前端代码配置表变查询条件显示列不生效---
// 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<any[]>([]);
// 选择的行记录
const selectedRows = ref<Recordable[]>([]);
// 表格选择列配置
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;
/**
* 设置表格参数
*
* @param formConfig
*/
function setTableProps(formConfig: any) {
const replaceAttributeArray: string[] = ['baseColProps','labelCol'];
for (let item of replaceAttributeArray) {
if(formConfig && formConfig[item]){
if(defaultTableProps.formConfig){
let defaultFormConfig:any = defaultTableProps.formConfig;
defaultFormConfig[item] = formConfig[item];
}
formConfig[item] = {};
}
}
}
return [
...useTable(defaultTableProps),
{
selectedRows,
selectedRowKeys,
rowSelection: defaultRowSelection,
},
];
}