| | |
| | | <template> |
| | | <div |
| | | ref="wrapRef" |
| | | :class="[ |
| | | prefixCls, |
| | | { |
| | | [`${prefixCls}-form-container`]: getBindValues.useSearchForm, |
| | | [`${prefixCls}--inset`]: getBindValues.inset, |
| | | }, |
| | | ]" |
| | | > |
| | | <div ref="wrapRef" :class="getWrapperClass"> |
| | | <BasicForm |
| | | submitOnReset |
| | | v-bind="getFormProps" |
| | | v-if="getBindValues.useSearchForm" |
| | | :submitButtonOptions="{ loading: getLoading }" |
| | | :tableAction="tableAction" |
| | | @register="registerForm" |
| | | @submit="handleSearchInfoChange" |
| | | @advanced-change="redoHeight" |
| | | > |
| | | <template #[replaceFormSlotKey(item)]="data" v-for="item in getFormSlotKeys"> |
| | | <slot :name="item" v-bind="data" /> |
| | | <slot :name="item" v-bind="data || {}"></slot> |
| | | </template> |
| | | </BasicForm> |
| | | |
| | |
| | | v-show="getEmptyDataIsShowTable" |
| | | @change="handleTableChange" |
| | | > |
| | | <template #[item]="data" v-for="item in Object.keys($slots)"> |
| | | <slot :name="item" v-bind="data" /> |
| | | <template #[item]="data" v-for="item in Object.keys($slots)" :key="item"> |
| | | <slot :name="item" v-bind="data || {}"></slot> |
| | | </template> |
| | | |
| | | <template #[`header-${column.dataIndex}`] v-for="column in columns" :key="column.dataIndex"> |
| | | <HeaderCell :column="column" /> |
| | | </template> |
| | |
| | | </div> |
| | | </template> |
| | | <script lang="ts"> |
| | | import type { BasicTableProps, TableActionType, SizeType } from './types/table'; |
| | | import type { |
| | | BasicTableProps, |
| | | TableActionType, |
| | | SizeType, |
| | | ColumnChangeParam, |
| | | } from './types/table'; |
| | | |
| | | import { defineComponent, ref, computed, unref } from 'vue'; |
| | | import { defineComponent, ref, computed, unref, toRaw, inject, watchEffect } from 'vue'; |
| | | import { Table } from 'ant-design-vue'; |
| | | import { BasicForm, useForm } from '/@/components/Form/index'; |
| | | |
| | | import { omit } from 'lodash-es'; |
| | | import { PageWrapperFixedHeightKey } from '/@/components/Page'; |
| | | import expandIcon from './components/ExpandIcon'; |
| | | import HeaderCell from './components/HeaderCell.vue'; |
| | | import { InnerHandlers } from './types/table'; |
| | | |
| | | import { usePagination } from './hooks/usePagination'; |
| | | import { useColumns } from './hooks/useColumns'; |
| | |
| | | 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 { useExpose } from '/@/hooks/core/useExpose'; |
| | | import { useDesign } from '/@/hooks/web/useDesign'; |
| | | |
| | | import { omit } from 'lodash-es'; |
| | | import { basicProps } from './props'; |
| | | import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; |
| | | import { isFunction } from '/@/utils/is'; |
| | | import { warn } from '/@/utils/log'; |
| | | |
| | | import './style/index.less'; |
| | | export default defineComponent({ |
| | | props: basicProps, |
| | | components: { |
| | | Table, |
| | | BasicForm, |
| | | HeaderCell: createAsyncComponent(() => import('./components/HeaderCell.vue')), |
| | | HeaderCell, |
| | | }, |
| | | props: basicProps, |
| | | emits: [ |
| | | 'fetch-success', |
| | | 'fetch-error', |
| | |
| | | 'row-mouseleave', |
| | | 'edit-end', |
| | | 'edit-cancel', |
| | | 'edit-row-end', |
| | | 'edit-change', |
| | | 'expanded-rows-change', |
| | | 'change', |
| | | 'columns-change', |
| | | ], |
| | | setup(props, { attrs, emit, slots }) { |
| | | const tableElRef = ref<ComponentRef>(null); |
| | | setup(props, { attrs, emit, slots, expose }) { |
| | | const tableElRef = ref(null); |
| | | const tableData = ref<Recordable[]>([]); |
| | | |
| | | const wrapRef = ref<Nullable<HTMLDivElement>>(null); |
| | | const wrapRef = ref(null); |
| | | const innerPropsRef = ref<Partial<BasicTableProps>>(); |
| | | |
| | | const { prefixCls } = useDesign('basic-table'); |
| | |
| | | |
| | | 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); |
| | |
| | | getSelectRowKeys, |
| | | deleteSelectRowByKey, |
| | | setSelectedRowKeys, |
| | | } = useRowSelection(getProps, emit); |
| | | } = useRowSelection(getProps, tableData, emit); |
| | | |
| | | const { |
| | | handleTableChange, |
| | | handleTableChange: onTableChange, |
| | | getDataSourceRef, |
| | | getDataSource, |
| | | getRawDataSource, |
| | | setTableData, |
| | | updateTableDataRecord, |
| | | deleteTableDataRecord, |
| | | insertTableDataRecord, |
| | | findTableDataRecord, |
| | | fetch, |
| | | getRowKey, |
| | | reload, |
| | |
| | | } = useDataSource( |
| | | getProps, |
| | | { |
| | | tableData, |
| | | getPaginationInfo, |
| | | setLoading, |
| | | setPagination, |
| | | getFieldsValue: formActions.getFieldsValue, |
| | | clearSelectedRowKeys, |
| | | }, |
| | | emit |
| | | emit, |
| | | ); |
| | | |
| | | const { getViewColumns, getColumns, setColumns, getColumnsRef, getCacheColumns } = useColumns( |
| | | getProps, |
| | | getPaginationInfo |
| | | ); |
| | | 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, |
| | | setColumns, |
| | | getColumnsRef, |
| | | getCacheColumns, |
| | | } = useColumns(getProps, getPaginationInfo); |
| | | |
| | | const { getScrollRef, redoHeight } = useTableScroll( |
| | | getProps, |
| | | tableElRef, |
| | | getColumnsRef, |
| | | getRowSelectionRef |
| | | getRowSelectionRef, |
| | | getDataSourceRef, |
| | | ); |
| | | |
| | | const { customRow } = useCustomRow(getProps, { |
| | |
| | | |
| | | const { getRowClassName } = useTableStyle(getProps, prefixCls); |
| | | |
| | | const { getHeaderProps } = useTableHeader(getProps, slots); |
| | | const { getExpandOption, expandAll, collapseAll } = useTableExpand(getProps, tableData, emit); |
| | | |
| | | const handlers: InnerHandlers = { |
| | | onColumnsChange: (data: ColumnChangeParam[]) => { |
| | | emit('columns-change', data); |
| | | // support useTable |
| | | unref(getProps).onColumnsChange?.(data); |
| | | }, |
| | | }; |
| | | |
| | | const { getHeaderProps } = useTableHeader(getProps, slots, handlers); |
| | | |
| | | const { getFooterProps } = useTableFooter( |
| | | getProps, |
| | | getScrollRef, |
| | | tableElRef, |
| | | getDataSourceRef |
| | | getDataSourceRef, |
| | | ); |
| | | |
| | | const { |
| | | getFormProps, |
| | | replaceFormSlotKey, |
| | | getFormSlotKeys, |
| | | handleSearchInfoChange, |
| | | } = useTableForm(getProps, slots, fetch); |
| | | const { getFormProps, replaceFormSlotKey, getFormSlotKeys, handleSearchInfoChange } = |
| | | useTableForm(getProps, slots, fetch, getLoading); |
| | | |
| | | const getBindValues = computed(() => { |
| | | const dataSource = unref(getDataSourceRef); |
| | | let propsData: Recordable = { |
| | | size: 'middle', |
| | | // ...(dataSource.length === 0 ? { getPopupContainer: () => document.body } : {}), |
| | | ...attrs, |
| | | customRow, |
| | | expandIcon: slots.expandIcon ? null : expandIcon(), |
| | | ...unref(getProps), |
| | | ...unref(getHeaderProps), |
| | | scroll: unref(getScrollRef), |
| | |
| | | tableLayout: 'fixed', |
| | | rowSelection: unref(getRowSelectionRef), |
| | | rowKey: unref(getRowKey), |
| | | columns: unref(getViewColumns), |
| | | pagination: unref(getPaginationInfo), |
| | | dataSource: unref(getDataSourceRef), |
| | | columns: toRaw(unref(getViewColumns)), |
| | | pagination: toRaw(unref(getPaginationInfo)), |
| | | dataSource, |
| | | footer: unref(getFooterProps), |
| | | ...unref(getExpandOption), |
| | | }; |
| | | if (slots.expandedRowRender) { |
| | | propsData = omit(propsData, 'scroll'); |
| | | } |
| | | |
| | | 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(() => { |
| | |
| | | deleteSelectRowByKey, |
| | | setPagination, |
| | | setTableData, |
| | | updateTableDataRecord, |
| | | deleteTableDataRecord, |
| | | insertTableDataRecord, |
| | | findTableDataRecord, |
| | | redoHeight, |
| | | setSelectedRowKeys, |
| | | setColumns, |
| | | setLoading, |
| | | getDataSource, |
| | | getRawDataSource, |
| | | setProps, |
| | | getRowSelection, |
| | | getPaginationRef: getPagination, |
| | |
| | | updateTableData, |
| | | setShowPagination, |
| | | getShowPagination, |
| | | setCacheColumnsByField, |
| | | expandAll, |
| | | collapseAll, |
| | | getSize: () => { |
| | | return unref(getBindValues).size as SizeType; |
| | | }, |
| | | }; |
| | | createTableContext({ ...tableAction, wrapRef, getBindValues }); |
| | | |
| | | useExpose<TableActionType>(tableAction); |
| | | expose(tableAction); |
| | | |
| | | emit('register', tableAction, formActions); |
| | | |
| | |
| | | wrapRef, |
| | | tableAction, |
| | | redoHeight, |
| | | getFormProps, |
| | | getFormProps: getFormProps as any, |
| | | replaceFormSlotKey, |
| | | getFormSlotKeys, |
| | | prefixCls, |
| | | getWrapperClass, |
| | | columns: getViewColumns, |
| | | }; |
| | | }, |
| | | }); |
| | | </script> |
| | | <style lang="less"> |
| | | @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%; |
| | | |
| | | &-row__striped { |
| | | td { |
| | | background-color: @app-content-background; |
| | | } |
| | | } |
| | | |
| | | &-form-container { |
| | | padding: 16px; |
| | | |
| | | .ant-form { |
| | | padding: 12px 10px 6px 10px; |
| | | margin-bottom: 16px; |
| | | background-color: @component-background; |
| | | border-radius: 2px; |
| | | } |
| | | } |
| | | |
| | | &--inset { |
| | | .ant-table-wrapper { |
| | | padding: 0; |
| | | } |
| | | } |
| | | |
| | | .ant-tag { |
| | | margin-right: 0; |
| | | } |
| | | |
| | | .ant-table-wrapper { |
| | | padding: 6px; |
| | | background-color: @component-background; |
| | | border-radius: 2px; |
| | | |
| | | .ant-table-title { |
| | | min-height: 40px; |
| | | padding: 0 0 8px 0 !important; |
| | | } |
| | | |
| | | .ant-table.ant-table-bordered .ant-table-title { |
| | | border: none !important; |
| | | } |
| | | } |
| | | |
| | | .ant-table { |
| | | width: 100%; |
| | | overflow-x: hidden; |
| | | |
| | | &-title { |
| | | display: flex; |
| | | padding: 8px 6px; |
| | | border-bottom: none; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | //.ant-table-tbody > tr.ant-table-row-selected td { |
| | | //background-color: fade(@primary-color, 8%) !important; |
| | | //} |
| | | } |
| | | |
| | | .ant-pagination { |
| | | margin: 10px 0 0 0; |
| | | } |
| | | |
| | | .ant-table-footer { |
| | | padding: 0; |
| | | |
| | | .ant-table-wrapper { |
| | | padding: 0; |
| | | } |
| | | |
| | | table { |
| | | border: none !important; |
| | | } |
| | | |
| | | .ant-table-body { |
| | | overflow-x: hidden !important; |
| | | // overflow-y: scroll !important; |
| | | } |
| | | |
| | | td { |
| | | padding: 12px 8px; |
| | | } |
| | | } |
| | | } |
| | | </style> |