import { TableColumnData as BaseColumn, TableData as BaseData, Table as BaseTable, Message, } from "@arco-design/web-vue"; import { merge } from "lodash-es"; import { PropType, computed, defineComponent, reactive, ref, watch } from "vue"; import { Form, FormInstance, FormModal, FormModalInstance, FormModalProps, FormProps } from "../form"; import { config } from "./table.config"; type DataFn = (search: Record, paging: { page: number; size: number }) => Promise; /** * 表格组件 * @see src/components/table/table.tsx */ export const Table = defineComponent({ name: "Table", props: { /** * 表格数据 * @description 可以是数组或者函数,函数返回值为`{ data: BaseData[], total: number }`类型 */ data: { type: [Array, Function] as PropType, }, /** * 表格列设置 */ columns: { type: Array as PropType, default: () => [], }, /** * 分页参数配置 */ pagination: { type: Object as PropType, default: () => reactive(config.pagination), }, /** * 搜索表单配置 */ search: { type: Object as PropType, }, /** * 新建弹窗配置 */ create: { type: Object as PropType, }, /** * 修改弹窗配置 */ modify: { type: Object as PropType, }, /** * 详情弹窗配置 */ detail: { type: Object as PropType, }, /** * 传递给 Table 组件的属性 */ tableProps: { type: Object as PropType["$props"]>, }, }, setup(props) { const loading = ref(false); const searchRef = ref(); const createRef = ref(); const modifyRef = ref(); const renderData = ref([]); const inlined = computed(() => (props.search?.items?.length ?? 0) <= config.searchInlineCount); const reloadData = () => loadData({ current: 1, pageSize: 10 }); const openModifyModal = (data: any) => modifyRef.value?.open(data); const loadData = async (pagination: Partial = {}) => { const merged = { ...props.pagination, ...pagination }; const paging = { page: merged.current, size: merged.pageSize }; const model = searchRef.value?.getModel() ?? {}; if (Array.isArray(props.data)) { const filters = Object.entries(model); const data = props.data.filter((item) => { return filters.every(([key, value]) => { if (typeof value === "string") { return item[key].includes(value); } return item[key] === value; }); }); renderData.value = data; props.pagination.total = renderData.value.length; props.pagination.current = 1; } if (typeof props.data === "function") { try { loading.value = true; const resData = await props.data(model, paging); const { data = [], total = 0 } = resData?.data || {}; renderData.value = data; props.pagination.total = total; props.pagination.current = paging.page; } catch (error) { const message = config.getApiErrorMessage(error); if (message) { Message.error(`提示:${message}`); } } finally { loading.value = false; } } }; watch( () => props.data, (data) => { if (Array.isArray(data)) { renderData.value = data; props.pagination.total = data.length; props.pagination.current = 1; } }, { immediate: true, } ); onMounted(() => { loadData(); }); if (props.search) { merge(props.search, { formProps: { layout: "inline" } }); } const state = { loading, inlined, searchRef, createRef, modifyRef, renderData, loadData, reloadData, openModifyModal, }; provide("ref:table", { ...state, ...props }); return state; }, render() { (this.columns as any).instance = this; return (
{!this.inlined && (
)}
{this.create && ( )} {this.modify && ( )} {this.$slots.action?.()}
{this.inlined &&
}
this.loadData({ current })} >
); }, }); export type TableInstance = InstanceType; export type TableProps = TableInstance["$props"];