diff --git a/src/components/Table/src/BasicTable.vue b/src/components/Table/src/BasicTable.vue index 8f2f3ed..9c86a52 100644 --- a/src/components/Table/src/BasicTable.vue +++ b/src/components/Table/src/BasicTable.vue @@ -1,671 +1,644 @@ diff --git a/src/components/Table/src/hooks/useDataSource.ts b/src/components/Table/src/hooks/useDataSource.ts index 54d0776..ec2b23a 100644 --- a/src/components/Table/src/hooks/useDataSource.ts +++ b/src/components/Table/src/hooks/useDataSource.ts @@ -1,377 +1,383 @@ -import type { BasicTableProps, FetchParams, SorterResult } from '../types/table'; -import type { PaginationProps } from '../types/pagination'; +import type { BasicTableProps, FetchParams, SorterResult } from "../types/table"; +import type { PaginationProps } from "../types/pagination"; import { - ref, - unref, - ComputedRef, - computed, - onMounted, - watch, - reactive, - Ref, - watchEffect, -} from 'vue'; -import { useTimeoutFn } from '/@/hooks/core/useTimeout'; -import { buildUUID } from '/@/utils/uuid'; -import { isFunction, isBoolean } from '/@/utils/is'; -import { get, cloneDeep, merge } from 'lodash-es'; -import { FETCH_SETTING, ROW_KEY, PAGE_SIZE } from '../const'; + ref, + unref, + ComputedRef, + computed, + onMounted, + watch, + reactive, + Ref, + watchEffect +} from "vue"; +import { useTimeoutFn } from "/@/hooks/core/useTimeout"; +import { buildUUID } from "/@/utils/uuid"; +import { isFunction, isBoolean } from "/@/utils/is"; +import { get, cloneDeep, merge } from "lodash-es"; +import { FETCH_SETTING, ROW_KEY, PAGE_SIZE } from "../const"; interface ActionType { - getPaginationInfo: ComputedRef; - setPagination: (info: Partial) => void; - setLoading: (loading: boolean) => void; - getFieldsValue: () => Recordable; - clearSelectedRowKeys: () => void; - tableData: Ref; + getPaginationInfo: ComputedRef; + setPagination: (info: Partial) => void; + setLoading: (loading: boolean) => void; + getFieldsValue: () => Recordable; + clearSelectedRowKeys: () => void; + tableData: Ref; } interface SearchState { - sortInfo: Recordable; - filterInfo: Record; + sortInfo: Recordable; + filterInfo: Record; } + export function useDataSource( - propsRef: ComputedRef, - { - getPaginationInfo, - setPagination, - setLoading, - getFieldsValue, - clearSelectedRowKeys, - tableData, - }: ActionType, - emit: EmitType, -) { - const searchState = reactive({ - sortInfo: {}, - filterInfo: {}, - }); - const dataSourceRef = ref([]); - const rawDataSourceRef = ref({}); - - watchEffect(() => { - tableData.value = unref(dataSourceRef); - }); - - watch( - () => unref(propsRef).dataSource, - () => { - const { dataSource, api } = unref(propsRef); - !api && dataSource && (dataSourceRef.value = dataSource); - }, + propsRef: ComputedRef, { - immediate: true, - }, - ); - - function handleTableChange( - isPaginateByDataSource = false, - pagination: PaginationProps, - filters: Partial>, - sorter: SorterResult, - ) { - const { clearSelectOnPageChange, sortFn, filterFn } = unref(propsRef); - if (clearSelectOnPageChange) { - clearSelectedRowKeys(); - } - setPagination(pagination); - - const params: Recordable = {}; - if (sorter && isFunction(sortFn)) { - const sortInfo = sortFn(sorter); - searchState.sortInfo = sortInfo; - params.sortInfo = sortInfo; - } - - if (filters && isFunction(filterFn)) { - const filterInfo = filterFn(filters); - searchState.filterInfo = filterInfo; - params.filterInfo = filterInfo; - } - if (!isPaginateByDataSource) { - fetch(params); - } - } - - function setTableKey(items: any[]) { - if (!items || !Array.isArray(items)) return; - items.forEach((item) => { - if (!item[ROW_KEY]) { - item[ROW_KEY] = buildUUID(); - } - if (item.children && item.children.length) { - setTableKey(item.children); - } + getPaginationInfo, + setPagination, + setLoading, + getFieldsValue, + clearSelectedRowKeys, + tableData + }: ActionType, + emit: EmitType +) { + const searchState = reactive({ + sortInfo: {}, + filterInfo: {} }); - } + const dataSourceRef = ref([]); + const rawDataSourceRef = ref({}); + const searchFormData = ref({}); - const getAutoCreateKey = computed(() => { - return unref(propsRef).autoCreateKey && !unref(propsRef).rowKey; - }); + watchEffect(() => { + tableData.value = unref(dataSourceRef); + }); - const getRowKey = computed(() => { - const { rowKey } = unref(propsRef); - return unref(getAutoCreateKey) ? ROW_KEY : rowKey; - }); + watch( + () => unref(propsRef).dataSource, + () => { + const { dataSource, api } = unref(propsRef); + !api && dataSource && (dataSourceRef.value = dataSource); + }, + { + immediate: true + } + ); - const getDataSourceRef = computed(() => { - const dataSource = unref(dataSourceRef); - if (!dataSource || dataSource.length === 0) { - return unref(dataSourceRef); + function handleTableChange( + isPaginateByDataSource = false, + pagination: PaginationProps, + filters: Partial>, + sorter: SorterResult + ) { + const { clearSelectOnPageChange, sortFn, filterFn } = unref(propsRef); + if (clearSelectOnPageChange) { + clearSelectedRowKeys(); + } + setPagination(pagination); + + const params: Recordable = {}; + if (sorter && isFunction(sortFn)) { + const sortInfo = sortFn(sorter); + searchState.sortInfo = sortInfo; + params.sortInfo = sortInfo; + } + + if (filters && isFunction(filterFn)) { + const filterInfo = filterFn(filters); + searchState.filterInfo = filterInfo; + params.filterInfo = filterInfo; + } + if (!isPaginateByDataSource) { + fetch(params); + } } - 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) => { + function setTableKey(items: any[]) { + if (!items || !Array.isArray(items)) return; + items.forEach((item) => { if (!item[ROW_KEY]) { - item[ROW_KEY] = buildUUID(); + item[ROW_KEY] = buildUUID(); } if (item.children && item.children.length) { - setTableKey(item.children); + 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 updateTableDataRecord( - rowKey: string | number, - record: Recordable, - ): Recordable | undefined { - const row = findTableDataRecord(rowKey); - - if (row) { - for (const field in row) { - if (Reflect.has(record, field)) row[field] = record[field]; - } - return row; - } - } - - function deleteTableDataRecord(rowKey: string | number | string[] | number[]) { - if (!dataSourceRef.value || dataSourceRef.value.length == 0) return; - const rowKeyName = unref(getRowKey); - if (!rowKeyName) return; - const rowKeys = !Array.isArray(rowKey) ? [rowKey] : rowKey; - for (const key of rowKeys) { - let index: number | undefined = dataSourceRef.value.findIndex((row) => { - let targetKeyName: string; - if (typeof rowKeyName === 'function') { - targetKeyName = rowKeyName(row); - } else { - targetKeyName = rowKeyName as string; - } - return row[targetKeyName] === key; - }); - if (index >= 0) { - dataSourceRef.value.splice(index, 1); - } - index = unref(propsRef).dataSource?.findIndex((row) => { - let targetKeyName: string; - if (typeof rowKeyName === 'function') { - targetKeyName = rowKeyName(row); - } else { - targetKeyName = rowKeyName as string; - } - return row[targetKeyName] === key; - }); - if (typeof index !== 'undefined' && index !== -1) - unref(propsRef).dataSource?.splice(index, 1); - } - setPagination({ - total: unref(propsRef).dataSource?.length, - }); - } - - function insertTableDataRecord(record: Recordable, index: number): Recordable | undefined { - // if (!dataSourceRef.value || dataSourceRef.value.length == 0) return; - index = index ?? dataSourceRef.value?.length; - unref(dataSourceRef).splice(index, 0, record); - return unref(dataSourceRef); - } - - function findTableDataRecord(rowKey: string | number) { - if (!dataSourceRef.value || dataSourceRef.value.length == 0) return; - - const rowKeyName = unref(getRowKey); - if (!rowKeyName) return; - - const { childrenColumnName = 'children' } = unref(propsRef); - - const findRow = (array: any[]) => { - let ret; - array.some(function iter(r) { - if (typeof rowKeyName === 'function') { - if ((rowKeyName(r) as string) === rowKey) { - ret = r; - return true; - } - } else { - if (Reflect.has(r, rowKeyName) && r[rowKeyName] === rowKey) { - ret = r; - return true; - } - } - return r[childrenColumnName] && r[childrenColumnName].some(iter); - }); - return ret; - }; - - // const row = dataSourceRef.value.find(r => { - // if (typeof rowKeyName === 'function') { - // return (rowKeyName(r) as string) === rowKey - // } else { - // return Reflect.has(r, rowKeyName) && r[rowKeyName] === rowKey - // } - // }) - return findRow(dataSourceRef.value); - } - - async function fetch(opt?: FetchParams) { - const { - api, - searchInfo, - defSort, - fetchSetting, - beforeFetch, - afterFetch, - useSearchForm, - pagination, - } = unref(propsRef); - if (!api || !isFunction(api)) return; - try { - setLoading(true); - const { pageField, sizeField, listField, totalField } = Object.assign( - {}, - FETCH_SETTING, - fetchSetting, - ); - 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 = merge( - pageParams, - useSearchForm ? getFieldsValue() : {}, - searchInfo, - opt?.searchInfo ?? {}, - defSort, - sortInfo, - filterInfo, - opt?.sortInfo ?? {}, - opt?.filterInfo ?? {}, - ); - if (beforeFetch && isFunction(beforeFetch)) { - params = (await beforeFetch(params)) || params; - } - - const res = await api(params); - rawDataSourceRef.value = res; - - const isArrayResult = Array.isArray(res); - - let resultItems: Recordable[] = isArrayResult ? res : get(res, listField); - const resultTotal: number = isArrayResult ? res.length : get(res, totalField); - - // 假如数据变少,导致总页数变少并小于当前选中页码,通过getPaginationRef获取到的页码是不正确的,需获取正确的页码再次执行 - if (resultTotal) { - const currentTotalPage = Math.ceil(resultTotal / pageSize); - if (current > currentTotalPage) { - setPagination({ - current: currentTotalPage, - }); - return await fetch(opt); - } - } - - if (afterFetch && isFunction(afterFetch)) { - resultItems = (await afterFetch(resultItems)) || 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, - }); - return resultItems; - } catch (error) { - emit('fetch-error', error); - dataSourceRef.value = []; - setPagination({ - total: 0, - }); - } finally { - setLoading(false); } - } - function setTableData(values: T[]) { - dataSourceRef.value = values; - } + const getAutoCreateKey = computed(() => { + return unref(propsRef).autoCreateKey && !unref(propsRef).rowKey; + }); - function getDataSource() { - return getDataSourceRef.value as T[]; - } + const getRowKey = computed(() => { + const { rowKey } = unref(propsRef); + return unref(getAutoCreateKey) ? ROW_KEY : rowKey; + }); - function getRawDataSource() { - return rawDataSourceRef.value as T; - } + const getDataSourceRef = computed(() => { + const dataSource = unref(dataSourceRef); + if (!dataSource || dataSource.length === 0) { + return unref(dataSourceRef); + } + if (unref(getAutoCreateKey)) { + const firstItem = dataSource[0]; + const lastItem = dataSource[dataSource.length - 1]; - async function reload(opt?: FetchParams) { - return await fetch(opt); - } + 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] = buildUUID(); + } + if (item.children && item.children.length) { + setTableKey(item.children); + } + }); + dataSourceRef.value = data; + } + } + } + return unref(dataSourceRef); + }); - onMounted(() => { - useTimeoutFn(() => { - unref(propsRef).immediate && fetch(); - }, 16); - }); + 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]; + } - return { - getDataSourceRef, - getDataSource, - getRawDataSource, - getRowKey, - setTableData, - getAutoCreateKey, - fetch, - reload, - updateTableData, - updateTableDataRecord, - deleteTableDataRecord, - insertTableDataRecord, - findTableDataRecord, - handleTableChange, - }; + function updateTableDataRecord( + rowKey: string | number, + record: Recordable + ): Recordable | undefined { + const row = findTableDataRecord(rowKey); + + if (row) { + for (const field in row) { + if (Reflect.has(record, field)) row[field] = record[field]; + } + return row; + } + } + + function deleteTableDataRecord(rowKey: string | number | string[] | number[]) { + if (!dataSourceRef.value || dataSourceRef.value.length == 0) return; + const rowKeyName = unref(getRowKey); + if (!rowKeyName) return; + const rowKeys = !Array.isArray(rowKey) ? [rowKey] : rowKey; + for (const key of rowKeys) { + let index: number | undefined = dataSourceRef.value.findIndex((row) => { + let targetKeyName: string; + if (typeof rowKeyName === "function") { + targetKeyName = rowKeyName(row); + } else { + targetKeyName = rowKeyName as string; + } + return row[targetKeyName] === key; + }); + if (index >= 0) { + dataSourceRef.value.splice(index, 1); + } + index = unref(propsRef).dataSource?.findIndex((row) => { + let targetKeyName: string; + if (typeof rowKeyName === "function") { + targetKeyName = rowKeyName(row); + } else { + targetKeyName = rowKeyName as string; + } + return row[targetKeyName] === key; + }); + if (typeof index !== "undefined" && index !== -1) + unref(propsRef).dataSource?.splice(index, 1); + } + setPagination({ + total: unref(propsRef).dataSource?.length + }); + } + + function insertTableDataRecord(record: Recordable, index: number): Recordable | undefined { + // if (!dataSourceRef.value || dataSourceRef.value.length == 0) return; + index = index ?? dataSourceRef.value?.length; + unref(dataSourceRef).splice(index, 0, record); + return unref(dataSourceRef); + } + + function findTableDataRecord(rowKey: string | number) { + if (!dataSourceRef.value || dataSourceRef.value.length == 0) return; + + const rowKeyName = unref(getRowKey); + if (!rowKeyName) return; + + const { childrenColumnName = "children" } = unref(propsRef); + + const findRow = (array: any[]) => { + let ret; + array.some(function iter(r) { + if (typeof rowKeyName === "function") { + if ((rowKeyName(r) as string) === rowKey) { + ret = r; + return true; + } + } else { + if (Reflect.has(r, rowKeyName) && r[rowKeyName] === rowKey) { + ret = r; + return true; + } + } + return r[childrenColumnName] && r[childrenColumnName].some(iter); + }); + return ret; + }; + + // const row = dataSourceRef.value.find(r => { + // if (typeof rowKeyName === 'function') { + // return (rowKeyName(r) as string) === rowKey + // } else { + // return Reflect.has(r, rowKeyName) && r[rowKeyName] === rowKey + // } + // }) + return findRow(dataSourceRef.value); + } + + async function fetch(opt?: FetchParams) { + const { + api, + searchInfo, + defSort, + fetchSetting, + beforeFetch, + afterFetch, + useSearchForm, + pagination + } = unref(propsRef); + if (!api || !isFunction(api)) return; + try { + setLoading(true); + const { pageField, sizeField, listField, totalField } = Object.assign( + {}, + FETCH_SETTING, + fetchSetting + ); + 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 = merge( + pageParams, + useSearchForm ? getFieldsValue() : {}, + searchInfo, + opt?.searchInfo || searchFormData.value || {}, + defSort, + sortInfo, + filterInfo, + opt?.sortInfo ?? {}, + opt?.filterInfo ?? {} + ); + if (beforeFetch && isFunction(beforeFetch)) { + params = (await beforeFetch(params)) || params; + } + + const res = await api(params); + rawDataSourceRef.value = res; + + const isArrayResult = Array.isArray(res); + + let resultItems: Recordable[] = isArrayResult ? res : get(res, listField); + const resultTotal: number = isArrayResult ? res.length : get(res, totalField); + + // 假如数据变少,导致总页数变少并小于当前选中页码,通过getPaginationRef获取到的页码是不正确的,需获取正确的页码再次执行 + if (resultTotal) { + const currentTotalPage = Math.ceil(resultTotal / pageSize); + if (current > currentTotalPage) { + setPagination({ + current: currentTotalPage + }); + return await fetch(opt); + } + } + + if (afterFetch && isFunction(afterFetch)) { + resultItems = (await afterFetch(resultItems)) || 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 + }); + return resultItems; + } catch (error) { + emit("fetch-error", error); + dataSourceRef.value = []; + setPagination({ + total: 0 + }); + } finally { + setLoading(false); + } + } + + function setTableData(values: T[]) { + dataSourceRef.value = values; + } + + function getDataSource() { + return getDataSourceRef.value as T[]; + } + + function getRawDataSource() { + return rawDataSourceRef.value as T; + } + + async function reload(opt?: FetchParams) { + return await fetch(opt); + } + + function setSearchFormData(data) { + searchFormData.value = data; + } + + onMounted(() => { + useTimeoutFn(() => { + unref(propsRef).immediate && fetch(); + }, 16); + }); + + return { + getDataSourceRef, + getDataSource, + getRawDataSource, + getRowKey, + setTableData, + getAutoCreateKey, + fetch, + reload, + updateTableData, + updateTableDataRecord, + deleteTableDataRecord, + insertTableDataRecord, + findTableDataRecord, + handleTableChange, + setSearchFormData + }; }