178 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
		
			
		
	
	
			178 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
|  | 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<Array>} 表格数据,使用 Vue 的 ref 包裹的数组 | |||
|  |  *  - [pagination] {Ref<{currentPage:number,pageSize:number,total:number}>} 分页信息对象,包含 currentPage、pageSize、total 字段,使用 ref 包裹 | |||
|  |  *  - [searchForm] {Ref<Object>} 搜索表单数据对象,使用 Vue 的 ref 包裹 | |||
|  |  *  - [tableRef] {Ref<ElTable|null>} 表格实例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(), | |||
|  |   }; | |||
|  | } |