zy-vue-library/hooks/useListData/index.js

178 lines
7.2 KiB
JavaScript
Raw Normal View History

2025-10-22 11:19:51 +08:00
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}>} 分页信息对象包含 currentPagepageSizetotal 字段使用 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(),
};
}