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(),
 | ||
|   };
 | ||
| }
 |