import { nextTick, ref } from "vue"; import { getDataType } from "../../utils/index.js"; import { getQueryCriteria, setQueryCriteria, } from "../useQueryCriteria/index.js"; const verificationParameter = (api, options) => { if (getDataType(api) !== "Function") throw new Error("api必须是一个函数"); if (getDataType(options) !== "Object") throw new Error("options必须是一个对象"); if (options.immediate && getDataType(options.immediate) !== "Boolean") throw new Error("options.immediate必须是一个布尔值"); if (options.usePagination && getDataType(options.usePagination) !== "Boolean") throw new Error("options.usePagination必须是一个布尔值"); if (options.key && getDataType(options.key) !== "String") throw new Error("options.key必须是一个字符串"); if ( options.callback && getDataType(options.callback) !== "Function" && getDataType(options.callback) !== "AsyncFunction" ) throw new Error("options.callback必须是一个函数"); if ( options.before && getDataType(options.before) !== "Function" && getDataType(options.before) !== "AsyncFunction" ) throw new Error("options.before必须是一个函数"); if ( options.defaultSearchForm && getDataType(options.defaultSearchForm) !== "Object" ) throw new Error("options.defaultSearchForm必须是一个对象"); if ( options.clearSelection && getDataType(options.clearSelection) !== "Boolean" ) throw new Error("options.clearSelection必须是一个布尔值"); if ( options.params && getDataType(options.params) !== "Object" && getDataType(options.params) !== "Function" ) throw new Error("options.params必须是一个对象或者一个函数"); if ( options.isStorageQueryCriteria && getDataType(options.isStorageQueryCriteria) !== "Boolean" ) throw new Error("options.isStorageQueryCriteria必须是一个布尔值"); if ( options.tabsActiveName && getDataType(options.tabsActiveName) !== "String" ) throw new Error("options.tabsActiveName必须是一个字符串"); }; const getOptionParams = (params) => { if (params) { if (getDataType(params) === "Object") return params; const paramsValue = params(); if (getDataType(paramsValue) !== "Object") throw new Error("options.params为函数时必须存在返回值并且必须是一个对象"); else return paramsValue; } }; const getBeforeParams = (before, params) => { if (before) { const paramsValue = before(JSON.parse(JSON.stringify(params))); if (getDataType(paramsValue) !== "Object") throw new Error("options.before必须存在返回值并且必须是一个对象"); else return paramsValue; } }; /** * @param {Function} api - 接口请求函数,用于获取列表数据 * @param {Object} [options] - 配置项(可选) * @param {Function} [options.callback] - 数据获取完成后的回调函数,第一个参数为列表数据,第二个参数为接口返回数据 * @param {Function} [options.before] - 请求前执行的钩子函数,接收当前查询参数作为参数,必须返回一个对象 * @param {Object|Function} [options.params] - 额外的请求参数,可以是对象或返回对象的函数 * @param {Object} [options.defaultSearchForm] - 搜索表单默认值 * @param {boolean} [options.immediate=true] - 是否立即执行接口请求 * @param {boolean} [options.usePagination=true] - 是否使用分页功能 * @param {string} [options.key="list"] - 响应数据中存放列表数据的字段名 * @param {boolean} [options.clearSelection=true] - 调用 resetPagination 时是否清空表格选择项 * @param {boolean} [options.isStorageQueryCriteria=true] - 是否缓存当前查询条件 * @param {string} [options.tabsActiveName] - 当存在 Tabs 组件时,当前激活的 tab 名称,用于区分查询缓存 * @return {Object} 返回对象包含以下属性:list 表格数据,pagination 分页数据,searchForm 搜索表单数据,tableRef 表格实例,getData 获取数据函数,resetPagination 重置分页函数 * @returns {Object} 返回对象包含以下属性: * - [list] {Ref} 表格数据,使用 Vue 的 ref 包裹的数组 * - [pagination] {Ref<{currentPage:number,pageSize:number,total:number}>} 分页信息对象,包含 currentPage、pageSize、total 字段,使用 ref 包裹 * - [searchForm] {Ref} 搜索表单数据对象,使用 Vue 的 ref 包裹 * - [tableRef] {Ref} 表格实例ref,可用于调用表格方法 * - [getData] {Function} 获取或刷新列表数据的异步函数 * - [resetPagination] {Function} 重置分页并刷新数据的异步函数 */ export default function useListData(api, options = {}) { verificationParameter(api, options); const immediate = options.immediate ?? true; const usePagination = options.usePagination ?? true; const key = options.key ?? "list"; const defaultSearchForm = options.defaultSearchForm ?? {}; const clearSelection = options.clearSelection ?? true; const isStorageQueryCriteria = options.isStorageQueryCriteria ?? true; const defaultPagination = { currentPage: 1, pageSize: 20, total: 0 }; const list = ref([]); const queryCriteria = getQueryCriteria(options.tabsActiveName); const pagination = ref(queryCriteria.pagination || defaultPagination); const searchForm = ref(JSON.parse(JSON.stringify(defaultSearchForm))); const tableRef = ref(null); const getData = async () => { const resData = await api({ ...(usePagination ? { curPage: pagination.value.currentPage, limit: pagination.value.pageSize, } : {}), ...searchForm.value, ...(queryCriteria.searchForm || {}), ...(getBeforeParams( options.before, queryCriteria.searchForm || searchForm.value ) || {}), ...(getOptionParams(options.params) || {}), }); if (usePagination) { if (resData.page[key]) list.value = resData.page[key]; else list.value = resData[key] || resData.varList; } else list.value = resData[key] || resData.varList; if (usePagination) pagination.value.total = resData.page.totalCount || resData.page.totalResult; options.callback && options.callback(list.value, resData); !usePagination && clearSelection && tableRef.value && tableRef.value.clearSelection(); if (isStorageQueryCriteria) { setQueryCriteria( { searchForm: { ...searchForm.value, ...(queryCriteria.searchForm || {}), }, pagination: pagination.value, }, options.tabsActiveName ); await nextTick(); searchForm.value = queryCriteria.searchForm || searchForm.value; } }; immediate && getData().then(); const resetPagination = async () => { list.value = []; pagination.value = defaultPagination; await nextTick(); await getData(); clearSelection && tableRef.value && tableRef.value.clearSelection(); const cloneSearchForm = searchForm.value; searchForm.value = {}; await nextTick(); searchForm.value = cloneSearchForm; }; return { list, pagination, searchForm, tableRef, getData: async () => await getData(), resetPagination: async () => await resetPagination(), }; }