@fe6/water-pro
Version:
An enterprise-class UI design language and Vue-based implementation
291 lines (256 loc) • 7.66 kB
text/typescript
/** @format */
import type { TableProProps, FetchParams, SorterResult } from '../types/table';
import type { PaginationProps } from '../types/pagination';
import {
ref,
unref,
ComputedRef,
computed,
onMounted,
watch,
reactive,
Ref,
watchEffect,
} from 'vue';
import { isArray, isFunction, isBoolean, uuid } from '@fe6/shared';
import { get, cloneDeep } from 'lodash-es';
import { useTimeoutFn } from '../../../_util/hooks/use-timeout';
import { FETCH_SETTING, ROW_KEY, PAGE_SIZE } from '../const';
interface ActionType {
getPaginationInfo: ComputedRef<boolean | PaginationProps>;
setPagination: (info: Partial<PaginationProps>) => void;
setLoading: (loading: boolean) => void;
getFieldsValue: () => Recordable;
clearSelectedRowKeys: () => void;
tableData: Ref<Recordable[]>;
}
interface SearchState {
sortInfo: Recordable;
filterInfo: Record<string, string[]>;
}
export function useDataSource(
propsRef: ComputedRef<TableProProps>,
{
getPaginationInfo,
setPagination,
setLoading,
getFieldsValue,
clearSelectedRowKeys,
tableData,
}: ActionType,
emit: EmitType,
) {
const searchState = reactive<SearchState>({
sortInfo: {},
filterInfo: {},
});
const dataSourceRef = ref<Recordable[]>([]);
// watchEffect(() => {
// const { dataSource, api } = unref(propsRef);
// !api && dataSource && (dataSourceRef.value = dataSource);
// });
watchEffect(() => {
tableData.value = unref(dataSourceRef);
});
watch(
() => unref(propsRef).dataSource,
() => {
const { dataSource, api } = unref(propsRef);
!api && dataSource && (dataSourceRef.value = dataSource);
},
{
immediate: true,
},
);
function handleTableChange(
pagination: PaginationProps,
filters: Partial<Recordable<string[]>>,
sorter: SorterResult,
) {
const { clearSelectOnPageChange, sortFn, filterFn } = unref(propsRef);
if (clearSelectOnPageChange) {
clearSelectedRowKeys();
}
setPagination(pagination);
const params: Recordable = {};
if (sorter && isFunction(sortFn)) {
const sortInfo = (sortFn as Function)(sorter);
searchState.sortInfo = sortInfo;
params.sortInfo = sortInfo;
}
if (filters && isFunction(filterFn)) {
const filterInfo = (filterFn as Function)(filters);
searchState.filterInfo = filterInfo;
params.filterInfo = filterInfo;
}
fetch({
params,
});
}
function setTableKey(items: any[]) {
if (!items || !isArray(items)) {
return;
}
items.forEach((item) => {
if (!item[ROW_KEY]) {
item[ROW_KEY] = uuid();
}
if (item.children && item.children.length) {
setTableKey(item.children);
}
});
}
const getAutoCreateKey = computed(() => {
return unref(propsRef).autoCreateKey && !unref(propsRef).rowKey;
});
const getRowKey = computed(() => {
const { rowKey } = unref(propsRef);
return unref(getAutoCreateKey) ? ROW_KEY : rowKey;
});
const getDataSourceRef = computed(() => {
const dataSource = unref(dataSourceRef);
if (!dataSource || dataSource.length === 0) {
return [];
}
if (unref(getAutoCreateKey)) {
const firstItem = dataSource[0];
const lastItem = dataSource[dataSource.length - 1];
if (firstItem && lastItem) {
if (!firstItem[ROW_KEY] || !lastItem[ROW_KEY]) {
const data = cloneDeep(unref(dataSourceRef));
data.forEach((item) => {
if (!item[ROW_KEY]) {
item[ROW_KEY] = uuid();
}
if (item.children && item.children.length) {
setTableKey(item.children);
}
});
dataSourceRef.value = data;
}
}
}
return unref(dataSourceRef);
});
async function updateTableData(index: number, key: string, value: any) {
const record = dataSourceRef.value[index];
if (record) {
dataSourceRef.value[index][key] = value;
}
return dataSourceRef.value[index];
}
function fetch(opt?: FetchParams) {
const { api, searchInfo, fetchSetting, beforeFetch, afterFetch, useSearchForm, pagination } =
unref(propsRef);
if (!api || !isFunction(api)) {
return;
}
try {
setLoading(true);
const { pageField, sizeField, listField, totalField } = fetchSetting || FETCH_SETTING;
let pageParams: Recordable = {};
const { current = 1, pageSize = PAGE_SIZE } = unref(getPaginationInfo) as PaginationProps;
if ((isBoolean(pagination) && !pagination) || isBoolean(getPaginationInfo)) {
pageParams = {};
} else {
pageParams[pageField] = (opt && opt.page) || current;
pageParams[sizeField] = pageSize;
}
const { sortInfo = {}, filterInfo } = searchState;
let params: Recordable = {
...pageParams,
...(useSearchForm ? getFieldsValue() : {}),
...searchInfo,
...(opt?.searchInfo ?? {}),
...sortInfo,
...filterInfo,
...(opt?.sortInfo ?? {}),
...(opt?.filterInfo ?? {}),
};
if (beforeFetch && isFunction(beforeFetch)) {
params = beforeFetch(params) || params;
}
const fetchApi = opt?.api || api;
fetchApi({
params,
success: (res) => {
const isArrayResult = isArray(res);
setLoading(false);
let resultItems: Recordable[] = isArrayResult ? res : get(res, listField);
const resultTotal: number = isArrayResult ? 0 : get(res, totalField);
// 假如数据变少,导致总页数变少并小于当前选中页码,通过getPaginationRef获取到的页码是不正确的,需获取正确的页码再次执行
if (resultTotal) {
const currentTotalPage = Math.ceil(resultTotal / pageSize);
if (current > currentTotalPage) {
setPagination({
current: currentTotalPage,
});
fetch(opt);
}
}
if (afterFetch && isFunction(afterFetch)) {
resultItems = afterFetch(resultItems, res) || resultItems;
}
dataSourceRef.value = resultItems;
setPagination({
total: resultTotal || 0,
});
if (opt && opt.page) {
setPagination({
current: opt.page || 1,
});
}
emit('fetch-success', {
items: unref(resultItems),
total: resultTotal,
params,
}, res);
},
error: (error) => {
setLoading(false);
emit('fetch-error', error);
dataSourceRef.value = [];
setPagination({
total: 0,
});
},
});
} catch (error) {
emit('fetch-error', error);
dataSourceRef.value = [];
setLoading(false);
setPagination({
total: 0,
});
} finally {
// fix table 加载数据的时候没有loading
// setLoading(false);
emit('fetch-finally');
}
}
function setTableData<T = Recordable>(values: T[]) {
dataSourceRef.value = values;
}
function getDataSource<T = Recordable>() {
return getDataSourceRef.value as T[];
}
async function reload(opt?: FetchParams) {
await fetch(opt);
}
onMounted(() => {
useTimeoutFn(() => {
unref(propsRef).immediate && fetch();
}, 16);
});
return {
getDataSourceRef,
getDataSource,
getRowKey,
setTableData,
getAutoCreateKey,
fetch,
reload,
updateTableData,
handleTableChange,
};
}