<template>
<div ref="wrapRef" :class="getWrapperClass">
<BasicForm
ref="formRef"
submitOnReset
v-bind="getFormProps"
v-if="getBindValues.useSearchForm"
:tableAction="tableAction"
@register="registerForm"
@submit="handleSearchInfoChange"
@advanced-change="redoHeight"
@field-value-change="useDebounceFn(redoHeight, 300)()"
class="search-form">
<template #[replaceFormSlotKey(item)]="data" v-for="item in getFormSlotKeys">
<slot :name="item" v-bind="data || {}"></slot>
</template>
</BasicForm>
<button @click="getFrom">123123</button>
<Table
ref="tableElRef"
v-bind="getBindValues"
class="ant-table-striped"
:rowClassName="getCellStyle"
v-show="getEmptyDataIsShowTable"
@change="handleTableChange"
@resizeColumn="handleResizeColumn">
<template #[item]="data" v-for="item in Object.keys($slots)" :key="item">
<slot :name="item" v-bind="data || {}"></slot>
</template>
<template #headerCell="{ column }">
<HeaderCell :column="getcolumn(column)" />
</template>
<template #bodyCell="data">
<slot name="bodyCell" v-bind="data || {}"></slot>
</template>
</Table>
</div>
</template>
<script lang="ts">
import type { BasicTableProps, TableActionType, SizeType, ColumnChangeParam } from './types/table';
import { BasicForm, useForm } from '@/components/Form';
import { PageWrapperFixedHeightKey } from '@/enums/pageEnum';
import { InnerHandlers } from './types/table';
import { defineComponent, ref, computed, unref, toRaw, inject, watchEffect, onMounted, reactive, watch } from 'vue';
import { Table } from 'ant-design-vue';
import HeaderCell from './components/HeaderCell.vue';
import { usePagination } from './hooks/usePagination';
import { useColumns } from './hooks/useColumns';
import { useDataSource } from './hooks/useDataSource';
import { useLoading } from './hooks/useLoading';
import { useRowSelection } from './hooks/useRowSelection';
import { useTableScroll } from './hooks/useTableScroll';
import { useTableScrollTo } from './hooks/useScrollTo';
import { useCustomRow } from './hooks/useCustomRow';
import { useTableStyle } from './hooks/useTableStyle';
import { useTableHeader } from './hooks/useTableHeader';
import { useTableExpand } from './hooks/useTableExpand';
import { createTableContext } from './hooks/useTableContext';
import { useTableFooter } from './hooks/useTableFooter';
import { useTableForm } from './hooks/useTableForm';
import { useDesign } from '@/hooks/web/useDesign';
import { useDebounceFn } from '@vueuse/core';
import { omit } from 'lodash-es';
import { basicProps } from './props';
import { isFunction } from '@/utils/is';
import { warn } from '@/utils/log';
export default defineComponent({
name: 'BasicTable',
components: {
Table,
BasicForm,
HeaderCell,
},
props: {
...basicProps,
loading: {
type: Boolean,
default: false, // 默认值
},
dataSource: {
type: Array,
default: () => [], // 允许外部传入数据源,默认为空数组
},
pagination: {
type: Object,
default: () => ({}), // 默认值
},
},
emits: [
'fetch-success',
'fetch-error',
'selection-change',
'register',
'row-click',
'row-dbClick',
'row-contextmenu',
'row-mouseenter',
'row-mouseleave',
'edit-end',
'edit-cancel',
'edit-row-end',
'edit-change',
'expanded-rows-change',
'change',
'columns-change',
'changeMenu',
],
setup(props, { attrs, emit, slots, expose }) {
const tableElRef = ref(null);
const tableData = ref<Recordable[]>([]);
const wrapRef = ref(null);
const formRef = ref(null);
const innerPropsRef = ref<Partial<BasicTableProps>>();
const { prefixCls } = useDesign('basic-table');
const [registerForm, formActions] = useForm();
const getProps = computed(() => {
return { ...props, ...unref(innerPropsRef) } as BasicTableProps;
});
const isFixedHeightPage = inject(PageWrapperFixedHeightKey, false);
watchEffect(() => {
unref(isFixedHeightPage) &&
props.canResize &&
warn("'canResize' of BasicTable may not work in PageWrapper with 'fixedHeight' (especially in hot updates)");
});
const { getLoading, setLoading } = useLoading(getProps);
const { getPaginationInfo, getPagination, setPagination, setShowPagination, getShowPagination } = usePagination(getProps);
const {
getRowSelection,
getRowSelectionRef,
getSelectRows,
setSelectedRows,
clearSelectedRowKeys,
getSelectRowKeys,
deleteSelectRowByKey,
setSelectedRowKeys,
} = useRowSelection(getProps, tableData, emit);
const { getExpandOption, expandAll, expandRows, collapseAll, getIsExpanded } = useTableExpand(getProps, tableData, emit);
const {
handleTableChange: onTableChange,
getDataSourceRef,
getDataSource,
getRawDataSource,
getFetchParams,
setTableData,
updateTableDataRecord,
deleteTableDataRecord,
insertTableDataRecord,
findTableDataRecord,
fetch,
getRowKey,
reload,
getAutoCreateKey,
updateTableData,
} = useDataSource(
getProps,
{
tableData,
getPaginationInfo,
setLoading,
setPagination,
getFieldsValue: formActions.getFieldsValue,
clearSelectedRowKeys,
expandAll,
},
emit,
);
const addFakeData = () => {
if (props.dataSource.length === 0) {
tableData.value = [];
} else {
tableData.value = props.dataSource; // 使用传入的数据源
}
};
function handleTableChange(...args) {
onTableChange.call(undefined, ...args);
emit('change', ...args);
// 解决通过useTable注册onChange时不起作用的问题
const { onChange } = unref(getProps);
onChange && isFunction(onChange) && onChange.call(undefined, ...args);
}
const { getViewColumns, getColumns, setCacheColumnsByField, setCacheColumns, setColumns, getColumnsRef, getCacheColumns } = useColumns(
getProps,
getPaginationInfo,
);
const { getScrollRef, redoHeight } = useTableScroll(getProps, tableElRef, getColumnsRef, getRowSelectionRef, getDataSourceRef, wrapRef, formRef);
const { scrollTo } = useTableScrollTo(tableElRef, getDataSourceRef);
const { customRow } = useCustomRow(getProps, {
setSelectedRowKeys,
getSelectRowKeys,
clearSelectedRowKeys,
getAutoCreateKey,
emit,
});
const { getRowClassName } = useTableStyle(getProps, prefixCls);
const handlers: InnerHandlers = {
onColumnsChange: (data: ColumnChangeParam[]) => {
emit('columns-change', data);
unref(getProps).onColumnsChange?.(data);
},
};
const { getHeaderProps } = useTableHeader(getProps, slots, handlers);
const { getFooterProps } = useTableFooter(getProps, getScrollRef, tableElRef, getDataSourceRef);
const { getFormProps, replaceFormSlotKey, getFormSlotKeys, handleSearchInfoChange } = useTableForm(getProps, slots, fetch, getLoading);
const getBindValues = computed(() => {
const dataSource = unref(getDataSourceRef);
let propsData: Recordable = {
...attrs,
...unref(getProps),
customRow: unref(getProps).customRow || customRow,
...unref(getHeaderProps),
scroll: unref(getScrollRef),
loading: unref(getLoading),
tableLayout: 'fixed',
rowSelection: unref(getRowSelectionRef),
rowKey: unref(getRowKey),
columns: toRaw(unref(getViewColumns)),
pagination: toRaw(unref(getPaginationInfo)),
dataSource,
footer: unref(getFooterProps),
...unref(getExpandOption),
};
propsData = omit(propsData, ['class', 'onChange']);
return propsData;
});
const getWrapperClass = computed(() => {
const values = unref(getBindValues);
return [
prefixCls,
attrs.class,
{
[`${prefixCls}-form-container`]: values.useSearchForm,
[`${prefixCls}--inset`]: values.inset,
},
];
});
const getEmptyDataIsShowTable = computed(() => {
const { emptyDataIsShowTable, useSearchForm } = unref(getProps);
if (emptyDataIsShowTable || !useSearchForm) {
return true;
}
return !!unref(getDataSourceRef).length;
});
function getcolumn(column: any) {
// console.log(column);
if (!column.hasOwnProperty('fixed') && column.hasOwnProperty('width') && (column.key != undefined || column.key != null)) {
column.resizable = true;
}
return column;
}
function handleResizeColumn(w, col) {
col.width = w;
}
function setProps(props: Partial<BasicTableProps>) {
innerPropsRef.value = { ...unref(innerPropsRef), ...props };
}
const tableAction: TableActionType = {
reload,
getSelectRows,
setSelectedRows,
clearSelectedRowKeys,
getSelectRowKeys,
deleteSelectRowByKey,
setPagination,
setTableData,
updateTableDataRecord,
deleteTableDataRecord,
insertTableDataRecord,
findTableDataRecord,
redoHeight,
setSelectedRowKeys,
setColumns,
setLoading,
getDataSource,
getRawDataSource,
getFetchParams,
setProps,
getRowSelection,
getPaginationRef: getPagination,
getColumns,
getCacheColumns,
emit,
updateTableData,
setShowPagination,
getShowPagination,
setCacheColumnsByField,
expandAll,
expandRows,
collapseAll,
getIsExpanded,
scrollTo,
getSize: () => {
return unref(getBindValues).size as SizeType;
},
setCacheColumns,
};
createTableContext({ ...tableAction, wrapRef, getBindValues });
expose(tableAction);
emit('register', tableAction, formActions);
onMounted(() => {
addFakeData(); // 添加假数据
});
function getCellStyle(record, index) {
return index % 2 === 0 ? 'ant-table-row-even' : 'ant-table-row-odd'; // 根据索引返回不同的类名
}
function getFrom() {
console.log(formActions.submit,useForm(),formRef)
}
return {
getCellStyle,
formRef,
tableElRef,
getBindValues,
getLoading,
registerForm,
handleSearchInfoChange,
getEmptyDataIsShowTable,
handleTableChange,
getRowClassName,
wrapRef,
tableAction,
redoHeight,
getFormProps: getFormProps as any,
replaceFormSlotKey,
getFormSlotKeys,
getWrapperClass,
columns: getViewColumns,
useDebounceFn,
getcolumn,
handleResizeColumn,
getFrom
};
},
});
</script>
<style lang="less">
.ant-table-tbody > tr.ant-table-row-even > td {
background-color: #fafafa;
}
.ant-table-resize-handle {
border-left: 1px solid #fafafa !important;
// width: 1px !important;
}
.ant-table-tbody > tr.ant-table-row-odd > td {
background-color: #fff;
}
@border-color: #cecece4d;
@prefix-cls: ~'@{namespace}-basic-table';
[data-theme='dark'] {
.ant-table-tbody > tr:hover.ant-table-row-selected > td,
.ant-table-tbody > tr.ant-table-row-selected td {
background-color: #262626;
}
}
.@{prefix-cls} {
max-width: 100%;
height: 100%;
&-row__striped {
td {
background-color: @app-content-background;
}
}
&-form-container {
.ant-form {
width: 100%;
padding: 10px 10px 0;
margin-bottom: 10px;
background-color: @component-background;
}
}
.ant-table-cell {
.ant-tag {
margin-right: 0;
}
}
.ant-table-wrapper {
height: 100%;
background-color: @component-background;
border-radius: 2px;
.ant-table-title {
min-height: 40px;
padding: 0 !important;
}
.ant-table.ant-table-bordered .ant-table-title {
border: none !important;
}
}
.ant-table {
width: 100%;
overflow-x: hidden;
&-title {
display: flex;
border-bottom: none;
justify-content: space-between;
align-items: center;
}
}
.ant-table-pagination.ant-pagination {
margin: 10px 0 0;
padding: 0 10px 10px;
}
.ant-table-footer {
padding: 0;
.ant-table-wrapper {
padding: 0;
}
table {
border: none !important;
}
.ant-table-body {
overflow-x: hidden !important;
}
td {
padding: 12px 8px;
}
}
&--inset {
.ant-table-wrapper {
padding: 0;
}
}
}
</style>
获取formRef.value为null
最新发布