Commit 3549043f372e8d80a2aa7cc747bd58a8308d4f52

Authored by vben
1 parent a305e591

wip(table): perf table

CHANGELOG.zh_CN.md
@@ -12,10 +12,13 @@ @@ -12,10 +12,13 @@
12 - form: 新增远程下拉`ApiSelect`及示例 12 - form: 新增远程下拉`ApiSelect`及示例
13 - form: 新增`autoFocusFirstItem`配置。用于配置是否聚焦表单第一个输入框 13 - form: 新增`autoFocusFirstItem`配置。用于配置是否聚焦表单第一个输入框
14 - useForm: 支持动态改变参数。可以传入`Ref`类型与`Computed`类型进行动态更改 14 - useForm: 支持动态改变参数。可以传入`Ref`类型与`Computed`类型进行动态更改
  15 +- table: 新增`clickToRowSelect`属性。用于控制点击行是否选中勾选狂
  16 +- table: 监听行点击事件
15 17
16 ### ⚡ Performance Improvements 18 ### ⚡ Performance Improvements
17 19
18 - 优化`modal`与`drawer`滚动条组件 20 - 优化`modal`与`drawer`滚动条组件
  21 +- table: 移除 `isTreeTable`属性
19 22
20 ### 🎫 Chores 23 ### 🎫 Chores
21 24
src/components/Drawer/src/BasicDrawer.vue
@@ -225,6 +225,10 @@ @@ -225,6 +225,10 @@
225 padding: 16px !important; 225 padding: 16px !important;
226 margin-bottom: 0 !important; 226 margin-bottom: 0 !important;
227 } 227 }
  228 +
  229 + > .scrollbar > .scrollbar__bar.is-horizontal {
  230 + display: none;
  231 + }
228 } 232 }
229 } 233 }
230 234
src/components/Icon/src/index.vue
@@ -43,7 +43,7 @@ @@ -43,7 +43,7 @@
43 if (el) { 43 if (el) {
44 await nextTick(); 44 await nextTick();
45 const icon = unref(getIconRef); 45 const icon = unref(getIconRef);
46 - 46 + if (!icon) return;
47 const svg = Iconify.renderSVG(icon, {}); 47 const svg = Iconify.renderSVG(icon, {});
48 48
49 if (svg) { 49 if (svg) {
@@ -74,7 +74,7 @@ @@ -74,7 +74,7 @@
74 } 74 }
75 ); 75 );
76 76
77 - watch(() => props.icon, update, { flush: 'post' }); 77 + // watch(() => props.icon, update, { flush: 'post' });
78 78
79 onMounted(update); 79 onMounted(update);
80 80
src/components/Modal/src/index.less
@@ -40,6 +40,10 @@ @@ -40,6 +40,10 @@
40 40
41 .ant-modal-body { 41 .ant-modal-body {
42 padding: 0; 42 padding: 0;
  43 +
  44 + > .scrollbar > .scrollbar__bar.is-horizontal {
  45 + display: none;
  46 + }
43 } 47 }
44 48
45 &-large { 49 &-large {
src/components/Table/src/BasicTable.vue
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 :submitOnReset="true" 11 :submitOnReset="true"
12 v-bind="getFormProps" 12 v-bind="getFormProps"
13 v-if="getBindValues.useSearchForm" 13 v-if="getBindValues.useSearchForm"
14 - :submitButtonOptions="{ loading }" 14 + :submitButtonOptions="{ loading: getLoading }"
15 :tableAction="tableAction" 15 :tableAction="tableAction"
16 @register="registerForm" 16 @register="registerForm"
17 @submit="handleSearchInfoChange" 17 @submit="handleSearchInfoChange"
@@ -35,18 +35,10 @@ @@ -35,18 +35,10 @@
35 </div> 35 </div>
36 </template> 36 </template>
37 <script lang="ts"> 37 <script lang="ts">
38 - import type {  
39 - BasicTableProps,  
40 - FetchParams,  
41 - GetColumnsParams,  
42 - TableActionType,  
43 - SizeType,  
44 - SorterResult,  
45 - TableCustomRecord,  
46 - } from './types/table'; 38 + import type { BasicTableProps, TableActionType, SizeType, SorterResult } from './types/table';
47 import { PaginationProps } from './types/pagination'; 39 import { PaginationProps } from './types/pagination';
48 40
49 - import { defineComponent, ref, computed, unref, watch, nextTick, toRaw } from 'vue'; 41 + import { defineComponent, ref, computed, unref, watch, nextTick } from 'vue';
50 import { Table } from 'ant-design-vue'; 42 import { Table } from 'ant-design-vue';
51 import renderTitle from './components/renderTitle'; 43 import renderTitle from './components/renderTitle';
52 import renderFooter from './components/renderFooter'; 44 import renderFooter from './components/renderFooter';
@@ -64,51 +56,64 @@ @@ -64,51 +56,64 @@
64 import { useRowSelection } from './hooks/useRowSelection'; 56 import { useRowSelection } from './hooks/useRowSelection';
65 import { useTableScroll } from './hooks/useTableScroll'; 57 import { useTableScroll } from './hooks/useTableScroll';
66 import { provideTable } from './hooks/useProvinceTable'; 58 import { provideTable } from './hooks/useProvinceTable';
  59 + import { useCustomRow } from './hooks/useCustomRow';
  60 + import { useTableStyle } from './hooks/useTableStyle';
67 61
68 import { useEventListener } from '/@/hooks/event/useEventListener'; 62 import { useEventListener } from '/@/hooks/event/useEventListener';
69 import { basicProps } from './props'; 63 import { basicProps } from './props';
70 - import { ROW_KEY } from './const';  
71 import { useExpose } from '/@/hooks/core/useExpose'; 64 import { useExpose } from '/@/hooks/core/useExpose';
72 65
73 import './style/index.less'; 66 import './style/index.less';
74 export default defineComponent({ 67 export default defineComponent({
75 props: basicProps, 68 props: basicProps,
76 components: { Table, BasicForm }, 69 components: { Table, BasicForm },
77 - emits: ['fetch-success', 'fetch-error', 'selection-change', 'register'], 70 + emits: [
  71 + 'fetch-success',
  72 + 'fetch-error',
  73 + 'selection-change',
  74 + 'register',
  75 + 'row-click',
  76 + 'row-dbClick',
  77 + 'row-contextmenu',
  78 + 'row-mouseenter',
  79 + 'row-mouseleave',
  80 + ],
78 setup(props, { attrs, emit, slots }) { 81 setup(props, { attrs, emit, slots }) {
79 const tableElRef = ref<ComponentRef>(null); 82 const tableElRef = ref<ComponentRef>(null);
  83 +
80 const wrapRef = ref<Nullable<HTMLDivElement>>(null); 84 const wrapRef = ref<Nullable<HTMLDivElement>>(null);
81 const innerPropsRef = ref<Partial<BasicTableProps>>(); 85 const innerPropsRef = ref<Partial<BasicTableProps>>();
  86 +
82 const [registerForm, { getFieldsValue }] = useForm(); 87 const [registerForm, { getFieldsValue }] = useForm();
83 88
84 - const getMergeProps = computed(() => {  
85 - return {  
86 - ...props,  
87 - ...unref(innerPropsRef),  
88 - } as BasicTableProps; 89 + const getProps = computed(() => {
  90 + return { ...props, ...unref(innerPropsRef) } as BasicTableProps;
89 }); 91 });
90 92
91 - // const getProps = computed(  
92 - // (): FormProps => {  
93 - // return deepMerge(toRaw(props), unref(innerPropsRef));  
94 - // }  
95 - // );  
96 -  
97 - const { loadingRef } = useLoading(getMergeProps);  
98 - const { getPaginationRef, setPagination } = usePagination(getMergeProps);  
99 - const { getColumnsRef, setColumns } = useColumns(getMergeProps, getPaginationRef);  
100 - const { getDataSourceRef, setTableData, fetch, getAutoCreateKey } = useDataSource(  
101 - getMergeProps, 93 + const { getLoading, setLoading } = useLoading(getProps);
  94 + const { getPaginationInfo, getPagination, setPagination } = usePagination(getProps);
  95 + const { getColumnsRef, getColumns, setColumns } = useColumns(getProps, getPaginationInfo);
  96 + const {
  97 + getDataSourceRef,
  98 + getDataSource,
  99 + setTableData,
  100 + fetch,
  101 + getRowKey,
  102 + reload,
  103 + getAutoCreateKey,
  104 + } = useDataSource(
  105 + getProps,
102 { 106 {
103 - getPaginationRef,  
104 - loadingRef, 107 + getPaginationInfo,
  108 + setLoading,
105 setPagination, 109 setPagination,
106 getFieldsValue, 110 getFieldsValue,
107 }, 111 },
108 emit 112 emit
109 ); 113 );
110 114
111 - const { getScrollRef, redoHeight } = useTableScroll(getMergeProps, tableElRef); 115 + const { getScrollRef, redoHeight } = useTableScroll(getProps, tableElRef);
  116 +
112 const { 117 const {
113 getRowSelectionRef, 118 getRowSelectionRef,
114 getSelectRows, 119 getSelectRows,
@@ -116,55 +121,58 @@ @@ -116,55 +121,58 @@
116 getSelectRowKeys, 121 getSelectRowKeys,
117 deleteSelectRowByKey, 122 deleteSelectRowByKey,
118 setSelectedRowKeys, 123 setSelectedRowKeys,
119 - } = useRowSelection(getMergeProps, emit);  
120 -  
121 - const getRowKey = computed(() => {  
122 - const { rowKey } = unref(getMergeProps); 124 + } = useRowSelection(getProps, emit);
123 125
124 - return unref(getAutoCreateKey) ? ROW_KEY : rowKey; 126 + const { customRow } = useCustomRow(getProps, {
  127 + setSelectedRowKeys,
  128 + getSelectRowKeys,
  129 + clearSelectedRowKeys,
  130 + getAutoCreateKey,
  131 + emit,
125 }); 132 });
126 133
  134 + const { getRowClassName } = useTableStyle(getProps);
  135 +
  136 + const getTitleProps = computed(
  137 + (): Recordable => {
  138 + const { title, showTableSetting, titleHelpMessage, tableSetting } = unref(getProps);
  139 + const hideTitle = !slots.tableTitle && !title && !slots.toolbar && !showTableSetting;
  140 + if (hideTitle && !isString(title)) {
  141 + return {};
  142 + }
  143 + return {
  144 + title: hideTitle
  145 + ? null
  146 + : renderTitle.bind(
  147 + null,
  148 + title,
  149 + titleHelpMessage,
  150 + slots,
  151 + showTableSetting,
  152 + tableSetting
  153 + ),
  154 + };
  155 + }
  156 + );
  157 +
127 const getBindValues = computed(() => { 158 const getBindValues = computed(() => {
128 - const { title, titleHelpMessage, showSummary, showTableSetting, tableSetting } = unref(  
129 - getMergeProps  
130 - );  
131 - const hideTitle = !slots.tableTitle && !title && !slots.toolbar && !showTableSetting;  
132 - const titleData: Recordable =  
133 - hideTitle && !isString(title)  
134 - ? {}  
135 - : {  
136 - title: hideTitle  
137 - ? null  
138 - : renderTitle.bind(  
139 - null,  
140 - title,  
141 - titleHelpMessage,  
142 - slots,  
143 - showTableSetting,  
144 - tableSetting  
145 - ),  
146 - };  
147 - const pagination = unref(getPaginationRef);  
148 - const rowSelection = unref(getRowSelectionRef);  
149 - const scroll = unref(getScrollRef);  
150 - const loading = unref(loadingRef);  
151 - const rowKey = unref(getRowKey);  
152 - const columns = unref(getColumnsRef);  
153 - const dataSource = unref(getDataSourceRef);  
154 - let propsData = { 159 + const { showSummary } = unref(getProps);
  160 +
  161 + let propsData: Recordable = {
155 size: 'middle', 162 size: 'middle',
156 ...(slots.expandedRowRender ? { expandIcon: renderExpandIcon() } : {}), 163 ...(slots.expandedRowRender ? { expandIcon: renderExpandIcon() } : {}),
157 ...attrs, 164 ...attrs,
158 - ...unref(getMergeProps),  
159 - ...titleData,  
160 - scroll,  
161 - loading, 165 + customRow,
  166 + ...unref(getProps),
  167 + ...unref(getTitleProps),
  168 + scroll: unref(getScrollRef),
  169 + loading: unref(getLoading),
162 tableLayout: 'fixed', 170 tableLayout: 'fixed',
163 - rowSelection,  
164 - rowKey,  
165 - columns,  
166 - pagination,  
167 - dataSource, 171 + rowSelection: unref(getRowSelectionRef),
  172 + rowKey: unref(getRowKey),
  173 + columns: unref(getColumnsRef),
  174 + pagination: unref(getPaginationInfo),
  175 + dataSource: unref(getDataSourceRef),
168 }; 176 };
169 if (slots.expandedRowRender) { 177 if (slots.expandedRowRender) {
170 propsData = omit(propsData, 'scroll'); 178 propsData = omit(propsData, 'scroll');
@@ -173,7 +181,7 @@ @@ -173,7 +181,7 @@
173 propsData.footer = renderFooter.bind(null, { 181 propsData.footer = renderFooter.bind(null, {
174 scroll: scroll as any, 182 scroll: scroll as any,
175 columnsRef: getColumnsRef, 183 columnsRef: getColumnsRef,
176 - summaryFunc: unref(getMergeProps).summaryFunc, 184 + summaryFunc: unref(getProps).summaryFunc,
177 dataSourceRef: getDataSourceRef, 185 dataSourceRef: getDataSourceRef,
178 rowSelectionRef: getRowSelectionRef, 186 rowSelectionRef: getRowSelectionRef,
179 }); 187 });
@@ -182,17 +190,17 @@ @@ -182,17 +190,17 @@
182 }); 190 });
183 191
184 const getFormProps = computed(() => { 192 const getFormProps = computed(() => {
185 - const { formConfig } = unref(getBindValues);  
186 - const formProps: FormProps = { 193 + const { formConfig } = unref(getProps);
  194 + const formProps: Partial<FormProps> = {
187 showAdvancedButton: true, 195 showAdvancedButton: true,
188 - ...(formConfig as FormProps), 196 + ...formConfig,
189 compact: true, 197 compact: true,
190 }; 198 };
191 return formProps; 199 return formProps;
192 }); 200 });
193 201
194 const getEmptyDataIsShowTable = computed(() => { 202 const getEmptyDataIsShowTable = computed(() => {
195 - const { emptyDataIsShowTable, useSearchForm } = unref(getMergeProps); 203 + const { emptyDataIsShowTable, useSearchForm } = unref(getProps);
196 if (emptyDataIsShowTable || !useSearchForm) { 204 if (emptyDataIsShowTable || !useSearchForm) {
197 return true; 205 return true;
198 } 206 }
@@ -207,17 +215,8 @@ @@ -207,17 +215,8 @@
207 { immediate: true } 215 { immediate: true }
208 ); 216 );
209 217
210 - function getRowClassName(record: TableCustomRecord, index: number) {  
211 - const { striped, rowClassName } = unref(getMergeProps);  
212 - if (!striped) return;  
213 - if (rowClassName && isFunction(rowClassName)) {  
214 - return rowClassName(record);  
215 - }  
216 - return (index || 0) % 2 === 1 ? 'basic-table-row__striped' : '';  
217 - }  
218 -  
219 function handleSearchInfoChange(info: any) { 218 function handleSearchInfoChange(info: any) {
220 - const { handleSearchInfoFn } = unref(getMergeProps); 219 + const { handleSearchInfoFn } = unref(getProps);
221 if (handleSearchInfoFn && isFunction(handleSearchInfoFn)) { 220 if (handleSearchInfoFn && isFunction(handleSearchInfoFn)) {
222 info = handleSearchInfoFn(info) || info; 221 info = handleSearchInfoFn(info) || info;
223 } 222 }
@@ -230,7 +229,7 @@ @@ -230,7 +229,7 @@
230 filters: Partial<Recordable<string[]>>, 229 filters: Partial<Recordable<string[]>>,
231 sorter: SorterResult 230 sorter: SorterResult
232 ) { 231 ) {
233 - const { clearSelectOnPageChange, sortFn } = unref(getMergeProps); 232 + const { clearSelectOnPageChange, sortFn } = unref(getProps);
234 if (clearSelectOnPageChange) { 233 if (clearSelectOnPageChange) {
235 clearSelectedRowKeys(); 234 clearSelectedRowKeys();
236 } 235 }
@@ -245,7 +244,7 @@ @@ -245,7 +244,7 @@
245 } 244 }
246 245
247 function handleSummary() { 246 function handleSummary() {
248 - if (unref(getMergeProps).showSummary) { 247 + if (unref(getProps).showSummary) {
249 nextTick(() => { 248 nextTick(() => {
250 const tableEl = unref(tableElRef); 249 const tableEl = unref(tableElRef);
251 if (!tableEl) return; 250 if (!tableEl) return;
@@ -273,9 +272,7 @@ @@ -273,9 +272,7 @@
273 } 272 }
274 273
275 const tableAction: TableActionType = { 274 const tableAction: TableActionType = {
276 - reload: async (opt?: FetchParams) => {  
277 - await fetch(opt);  
278 - }, 275 + reload,
279 getSelectRows, 276 getSelectRows,
280 clearSelectedRowKeys, 277 clearSelectedRowKeys,
281 getSelectRowKeys, 278 getSelectRowKeys,
@@ -285,27 +282,11 @@ @@ -285,27 +282,11 @@
285 redoHeight, 282 redoHeight,
286 setSelectedRowKeys, 283 setSelectedRowKeys,
287 setColumns, 284 setColumns,
288 - getPaginationRef: () => {  
289 - return unref(getPaginationRef);  
290 - },  
291 - getColumns: (opt?: GetColumnsParams) => {  
292 - const { ignoreIndex, ignoreAction } = opt || {};  
293 - let columns = toRaw(unref(getColumnsRef));  
294 - if (ignoreIndex) {  
295 - columns = columns.filter((item) => item.flag !== 'INDEX');  
296 - }  
297 - if (ignoreAction) {  
298 - columns = columns.filter((item) => item.flag !== 'ACTION');  
299 - }  
300 - return columns;  
301 - },  
302 - getDataSource: () => {  
303 - return unref(getDataSourceRef);  
304 - },  
305 - setLoading: (loading: boolean) => {  
306 - loadingRef.value = loading;  
307 - }, 285 + setLoading,
  286 + getDataSource,
308 setProps, 287 setProps,
  288 + getPaginationRef: getPagination,
  289 + getColumns,
309 getSize: () => { 290 getSize: () => {
310 return unref(getBindValues).size as SizeType; 291 return unref(getBindValues).size as SizeType;
311 }, 292 },
@@ -323,7 +304,7 @@ @@ -323,7 +304,7 @@
323 return { 304 return {
324 tableElRef, 305 tableElRef,
325 getBindValues, 306 getBindValues,
326 - loading: loadingRef, 307 + getLoading,
327 registerForm, 308 registerForm,
328 handleSearchInfoChange, 309 handleSearchInfoChange,
329 getFormProps, 310 getFormProps,
src/components/Table/src/const.ts
@@ -31,3 +31,9 @@ export function DEFAULT_SORT_FN(sortInfo: SorterResult) { @@ -31,3 +31,9 @@ export function DEFAULT_SORT_FN(sortInfo: SorterResult) {
31 order, 31 order,
32 }; 32 };
33 } 33 }
  34 +
  35 +// 表格单元格默认布局
  36 +export const DEFAULT_ALIGN = 'center';
  37 +
  38 +export const INDEX_COLUMN_FLAG = 'INDEX';
  39 +export const ACTION_COLUMN_FLAG = 'ACTION';
src/components/Table/src/hooks/useColumns.ts
1 -import { BasicColumn, BasicTableProps } from '../types/table'; 1 +import { BasicColumn, BasicTableProps, GetColumnsParams } from '../types/table';
2 import { PaginationProps } from '../types/pagination'; 2 import { PaginationProps } from '../types/pagination';
3 import { unref, ComputedRef, Ref, computed, watchEffect, ref, toRaw } from 'vue'; 3 import { unref, ComputedRef, Ref, computed, watchEffect, ref, toRaw } from 'vue';
4 import { isBoolean, isArray, isObject } from '/@/utils/is'; 4 import { isBoolean, isArray, isObject } from '/@/utils/is';
5 -import { PAGE_SIZE } from '../const';  
6 -import { useProps } from './useProps'; 5 +import { DEFAULT_ALIGN, PAGE_SIZE, INDEX_COLUMN_FLAG, ACTION_COLUMN_FLAG } from '../const';
7 import { useI18n } from '/@/hooks/web/useI18n'; 6 import { useI18n } from '/@/hooks/web/useI18n';
8 7
9 const { t } = useI18n(); 8 const { t } = useI18n();
  9 +
  10 +function handleItem(item: BasicColumn, ellipsis: boolean) {
  11 + const { key, dataIndex, children } = item;
  12 + item.align = item.align || DEFAULT_ALIGN;
  13 + if (ellipsis) {
  14 + if (!key) {
  15 + item.key = dataIndex;
  16 + }
  17 + if (!isBoolean(item.ellipsis)) {
  18 + Object.assign(item, {
  19 + ellipsis,
  20 + });
  21 + }
  22 + }
  23 + if (children && children.length) {
  24 + handleChildren(children, !!ellipsis);
  25 + }
  26 +}
  27 +
  28 +function handleChildren(children: BasicColumn[] | undefined, ellipsis: boolean) {
  29 + if (!children) return;
  30 + children.forEach((item) => {
  31 + const { children } = item;
  32 + handleItem(item, ellipsis);
  33 + handleChildren(children, ellipsis);
  34 + });
  35 +}
  36 +
  37 +function handleIndexColumn(
  38 + propsRef: ComputedRef<BasicTableProps>,
  39 + getPaginationRef: ComputedRef<boolean | PaginationProps>,
  40 + columns: BasicColumn[]
  41 +) {
  42 + const { showIndexColumn, indexColumnProps, ellipsis } = unref(propsRef);
  43 +
  44 + let pushIndexColumns = false;
  45 + columns.forEach((item) => {
  46 + const { children } = item;
  47 + handleItem(item, !!ellipsis);
  48 + const isTreeTable = children && children.length;
  49 +
  50 + const indIndex = columns.findIndex((column) => column.flag === INDEX_COLUMN_FLAG);
  51 +
  52 + if (showIndexColumn && !isTreeTable) {
  53 + pushIndexColumns = indIndex === -1;
  54 + } else if (!showIndexColumn && !isTreeTable && indIndex !== -1) {
  55 + columns.splice(indIndex, 1);
  56 + }
  57 + });
  58 +
  59 + if (!pushIndexColumns) return;
  60 +
  61 + const isFixedLeft = columns.some((item) => item.fixed === 'left');
  62 +
  63 + columns.unshift({
  64 + flag: INDEX_COLUMN_FLAG,
  65 + width: 50,
  66 + title: t('component.table.index'),
  67 + align: 'center',
  68 + customRender: ({ index }) => {
  69 + const getPagination = unref(getPaginationRef);
  70 + if (isBoolean(getPagination)) {
  71 + return `${index + 1}`;
  72 + }
  73 + const { current = 1, pageSize = PAGE_SIZE } = getPagination;
  74 + const currentIndex = (current - 1) * pageSize + index + 1;
  75 + return currentIndex;
  76 + },
  77 + ...(isFixedLeft
  78 + ? {
  79 + fixed: 'left',
  80 + }
  81 + : {}),
  82 + ...indexColumnProps,
  83 + });
  84 +}
  85 +
  86 +function handleActionColumn(propsRef: ComputedRef<BasicTableProps>, columns: BasicColumn[]) {
  87 + const { actionColumn } = unref(propsRef);
  88 + if (!actionColumn) return;
  89 +
  90 + const hasIndex = columns.findIndex((column) => column.flag === ACTION_COLUMN_FLAG);
  91 + if (hasIndex === -1) {
  92 + columns.push({
  93 + ...columns[hasIndex],
  94 + fixed: 'right',
  95 + ...actionColumn,
  96 + flag: ACTION_COLUMN_FLAG,
  97 + });
  98 + }
  99 +}
  100 +
10 export function useColumns( 101 export function useColumns(
11 - refProps: ComputedRef<BasicTableProps>,  
12 - getPaginationRef: ComputedRef<false | PaginationProps> 102 + propsRef: ComputedRef<BasicTableProps>,
  103 + getPaginationRef: ComputedRef<boolean | PaginationProps>
13 ) { 104 ) {
14 - const { propsRef } = useProps(refProps);  
15 const columnsRef = (ref(unref(propsRef).columns) as unknown) as Ref<BasicColumn[]>; 105 const columnsRef = (ref(unref(propsRef).columns) as unknown) as Ref<BasicColumn[]>;
16 - const cacheColumnsRef = (ref(unref(propsRef).columns) as unknown) as Ref<BasicColumn[]>; 106 + let cacheColumns = unref(propsRef).columns;
17 107
18 const getColumnsRef = computed(() => { 108 const getColumnsRef = computed(() => {
19 - const props = unref(propsRef);  
20 - const { showIndexColumn, indexColumnProps, ellipsis, actionColumn, isTreeTable } = props;  
21 -  
22 const columns = unref(columnsRef); 109 const columns = unref(columnsRef);
23 if (!columns) { 110 if (!columns) {
24 return []; 111 return [];
25 } 112 }
26 - let pushIndexColumns = false;  
27 - columns.forEach((item) => {  
28 - const { children } = item;  
29 - handleItem(item, !!ellipsis);  
30 -  
31 - handleChildren(children, !!ellipsis);  
32 -  
33 - const indIndex = columns.findIndex((column) => column.flag === 'INDEX');  
34 - if (showIndexColumn && !isTreeTable) {  
35 - pushIndexColumns = indIndex === -1;  
36 - } else if (!showIndexColumn && !isTreeTable && indIndex !== -1) {  
37 - columns.splice(indIndex, 1);  
38 - }  
39 - });  
40 113
41 - if (pushIndexColumns) {  
42 - const isFixedLeft = columns.some((item) => item.fixed === 'left');  
43 -  
44 - columns.unshift({  
45 - flag: 'INDEX',  
46 - width: 50,  
47 - title: t('component.table.index'),  
48 - align: 'center',  
49 - customRender: ({ index }) => {  
50 - const getPagination = unref(getPaginationRef);  
51 - if (isBoolean(getPagination)) {  
52 - return `${index + 1}`;  
53 - }  
54 - const { current = 1, pageSize = PAGE_SIZE } = getPagination;  
55 - const currentIndex = (current - 1) * pageSize + index + 1;  
56 - return currentIndex;  
57 - },  
58 - ...(isFixedLeft  
59 - ? {  
60 - fixed: 'left',  
61 - }  
62 - : {}),  
63 - ...indexColumnProps,  
64 - });  
65 - }  
66 - if (actionColumn) {  
67 - const hasIndex = columns.findIndex((column) => column.flag === 'ACTION');  
68 - if (hasIndex === -1) {  
69 - columns.push({  
70 - ...columns[hasIndex],  
71 - fixed: 'right',  
72 - ...actionColumn,  
73 - flag: 'ACTION',  
74 - });  
75 - }  
76 - } 114 + handleIndexColumn(propsRef, getPaginationRef, columns);
  115 + handleActionColumn(propsRef, columns);
  116 +
77 return columns; 117 return columns;
78 }); 118 });
79 119
80 watchEffect(() => { 120 watchEffect(() => {
81 const columns = toRaw(unref(propsRef).columns); 121 const columns = toRaw(unref(propsRef).columns);
82 columnsRef.value = columns; 122 columnsRef.value = columns;
83 - cacheColumnsRef.value = columns; 123 + cacheColumns = columns;
84 }); 124 });
85 125
86 - function handleItem(item: BasicColumn, ellipsis: boolean) {  
87 - const { key, dataIndex } = item;  
88 - item.align = item.align || 'center';  
89 - if (ellipsis) {  
90 - if (!key) {  
91 - item.key = dataIndex;  
92 - }  
93 - if (!isBoolean(item.ellipsis)) {  
94 - Object.assign(item, {  
95 - ellipsis,  
96 - });  
97 - }  
98 - }  
99 - }  
100 -  
101 - function handleChildren(children: BasicColumn[] | undefined, ellipsis: boolean) {  
102 - if (!children) return;  
103 - children.forEach((item) => {  
104 - const { children } = item;  
105 - handleItem(item, ellipsis);  
106 - handleChildren(children, ellipsis);  
107 - });  
108 - }  
109 -  
110 - function setColumns(columns: BasicColumn[] | string[]) { 126 + /**
  127 + * set columns
  128 + * @param columns key|column
  129 + */
  130 + function setColumns(columns: Partial<BasicColumn>[] | string[]) {
111 if (!isArray(columns)) return; 131 if (!isArray(columns)) return;
112 132
113 if (columns.length <= 0) { 133 if (columns.length <= 0) {
@@ -116,15 +136,30 @@ export function useColumns( @@ -116,15 +136,30 @@ export function useColumns(
116 } 136 }
117 137
118 const firstColumn = columns[0]; 138 const firstColumn = columns[0];
  139 +
119 if (isObject(firstColumn)) { 140 if (isObject(firstColumn)) {
120 - columnsRef.value = columns as any; 141 + columnsRef.value = columns as BasicColumn[];
121 } else { 142 } else {
122 - const newColumns = unref(cacheColumnsRef).filter((item) =>  
123 - (columns as string[]).includes(`${item.key}`! || item.dataIndex!) 143 + const newColumns = cacheColumns.filter(
  144 + (item) =>
  145 + (item.dataIndex || `${item.key}`) &&
  146 + (columns as string[]).includes(`${item.key}`! || item.dataIndex!)
124 ); 147 );
125 columnsRef.value = newColumns; 148 columnsRef.value = newColumns;
126 } 149 }
127 } 150 }
128 151
129 - return { getColumnsRef, setColumns }; 152 + function getColumns(opt?: GetColumnsParams) {
  153 + const { ignoreIndex, ignoreAction } = opt || {};
  154 + let columns = toRaw(unref(getColumnsRef));
  155 + if (ignoreIndex) {
  156 + columns = columns.filter((item) => item.flag !== INDEX_COLUMN_FLAG);
  157 + }
  158 + if (ignoreAction) {
  159 + columns = columns.filter((item) => item.flag !== ACTION_COLUMN_FLAG);
  160 + }
  161 + return columns;
  162 + }
  163 +
  164 + return { getColumnsRef, getColumns, setColumns };
130 } 165 }
src/components/Table/src/hooks/useCustomRow.ts 0 → 100644
  1 +import type { ComputedRef } from 'vue';
  2 +import type { BasicTableProps } from '../types/table';
  3 +import { unref } from 'vue';
  4 +import { ROW_KEY } from '../const';
  5 +import { isString, isFunction } from '/@/utils/is';
  6 +
  7 +interface Options {
  8 + setSelectedRowKeys: (keys: string[]) => void;
  9 + getSelectRowKeys: () => string[];
  10 + clearSelectedRowKeys: () => void;
  11 + emit: EmitType;
  12 + getAutoCreateKey: ComputedRef<boolean | undefined>;
  13 +}
  14 +
  15 +function getKey(
  16 + record: Recordable,
  17 + rowKey: string | ((record: Record<string, any>) => string) | undefined,
  18 + autoCreateKey?: boolean
  19 +) {
  20 + if (!rowKey || autoCreateKey) {
  21 + return record[ROW_KEY];
  22 + }
  23 + if (isString(rowKey)) {
  24 + return record[rowKey];
  25 + }
  26 + if (isFunction(rowKey)) {
  27 + return record[rowKey(record)];
  28 + }
  29 + return null;
  30 +}
  31 +
  32 +export function useCustomRow(
  33 + propsRef: ComputedRef<BasicTableProps>,
  34 + { setSelectedRowKeys, getSelectRowKeys, getAutoCreateKey, clearSelectedRowKeys, emit }: Options
  35 +) {
  36 + const customRow = (record: Recordable, index: number) => {
  37 + return {
  38 + onClick: (e: Event) => {
  39 + emit('row-click', record, index, e);
  40 + e?.stopPropagation();
  41 + const { rowSelection, rowKey, clickToRowSelect } = unref(propsRef);
  42 + if (!rowSelection || !clickToRowSelect) return;
  43 + const keys = getSelectRowKeys();
  44 + const key = getKey(record, rowKey, unref(getAutoCreateKey));
  45 + if (!key) return;
  46 +
  47 + const isCheckbox = rowSelection.type === 'checkbox';
  48 +
  49 + if (isCheckbox) {
  50 + if (!keys.includes(key)) {
  51 + setSelectedRowKeys([...keys, key]);
  52 + return;
  53 + }
  54 + const keyIndex = keys.findIndex((item) => item === key);
  55 + keys.splice(keyIndex, 1);
  56 + setSelectedRowKeys(keys);
  57 + return;
  58 + }
  59 +
  60 + const isRadio = rowSelection.type === 'radio';
  61 + if (isRadio) {
  62 + if (!keys.includes(key)) {
  63 + if (keys.length) {
  64 + clearSelectedRowKeys();
  65 + }
  66 + setSelectedRowKeys([key]);
  67 + return;
  68 + }
  69 + clearSelectedRowKeys();
  70 + }
  71 + },
  72 + onDblclick: (event: Event) => {
  73 + emit('row-dbClick', record, index, event);
  74 + },
  75 + onContextmenu: (event: Event) => {
  76 + emit('row-contextmenu', record, index, event);
  77 + },
  78 + onMouseenter: (event: Event) => {
  79 + emit('row-mouseenter', record, index, event);
  80 + },
  81 + onMouseleave: (event: Event) => {
  82 + emit('row-mouseleave', record, index, event);
  83 + },
  84 + };
  85 + };
  86 +
  87 + return {
  88 + customRow,
  89 + };
  90 +}
src/components/Table/src/hooks/useDataSource.ts
1 import type { BasicTableProps, FetchParams } from '../types/table'; 1 import type { BasicTableProps, FetchParams } from '../types/table';
2 import type { PaginationProps } from '../types/pagination'; 2 import type { PaginationProps } from '../types/pagination';
3 3
4 -import { watch, ref, unref, ComputedRef, computed, onMounted, Ref } from 'vue'; 4 +import { ref, unref, ComputedRef, computed, onMounted, watchEffect } from 'vue';
5 5
6 import { useTimeoutFn } from '/@/hooks/core/useTimeout'; 6 import { useTimeoutFn } from '/@/hooks/core/useTimeout';
7 7
@@ -9,39 +9,28 @@ import { buildUUID } from &#39;/@/utils/uuid&#39;; @@ -9,39 +9,28 @@ import { buildUUID } from &#39;/@/utils/uuid&#39;;
9 import { isFunction, isBoolean } from '/@/utils/is'; 9 import { isFunction, isBoolean } from '/@/utils/is';
10 import { get } from 'lodash-es'; 10 import { get } from 'lodash-es';
11 11
12 -import { useProps } from './useProps'; 12 +import { FETCH_SETTING, ROW_KEY, PAGE_SIZE } from '../const';
13 13
14 -import { FETCH_SETTING, ROW_KEY } from '../const';  
15 interface ActionType { 14 interface ActionType {
16 - getPaginationRef: ComputedRef<false | PaginationProps>; 15 + getPaginationInfo: ComputedRef<boolean | PaginationProps>;
17 setPagination: (info: Partial<PaginationProps>) => void; 16 setPagination: (info: Partial<PaginationProps>) => void;
18 - loadingRef: Ref<boolean | undefined>;  
19 - getFieldsValue: () => {  
20 - [field: string]: any;  
21 - }; 17 + setLoading: (loading: boolean) => void;
  18 + getFieldsValue: () => Recordable;
22 } 19 }
23 export function useDataSource( 20 export function useDataSource(
24 - refProps: ComputedRef<BasicTableProps>,  
25 - { getPaginationRef, setPagination, loadingRef, getFieldsValue }: ActionType, 21 + propsRef: ComputedRef<BasicTableProps>,
  22 + { getPaginationInfo, setPagination, setLoading, getFieldsValue }: ActionType,
26 emit: EmitType 23 emit: EmitType
27 ) { 24 ) {
28 - const { propsRef } = useProps(refProps);  
29 -  
30 - const dataSourceRef = ref<any[]>([]); 25 + const dataSourceRef = ref<Recordable[]>([]);
31 26
32 - watch(  
33 - () => unref(propsRef).dataSource,  
34 - (data: any[]) => {  
35 - const { api } = unref(propsRef);  
36 - !api && (dataSourceRef.value = data);  
37 - },  
38 - { immediate: true }  
39 - ); 27 + watchEffect(() => {
  28 + const { dataSource, api } = unref(propsRef);
  29 + !api && dataSource && (dataSourceRef.value = dataSource);
  30 + });
40 31
41 function setTableKey(items: any[]) { 32 function setTableKey(items: any[]) {
42 - if (!items || !Array.isArray(items)) {  
43 - return;  
44 - } 33 + if (!items || !Array.isArray(items)) return;
45 items.forEach((item) => { 34 items.forEach((item) => {
46 if (!item[ROW_KEY]) { 35 if (!item[ROW_KEY]) {
47 item[ROW_KEY] = buildUUID(); 36 item[ROW_KEY] = buildUUID();
@@ -51,10 +40,16 @@ export function useDataSource( @@ -51,10 +40,16 @@ export function useDataSource(
51 } 40 }
52 }); 41 });
53 } 42 }
  43 +
54 const getAutoCreateKey = computed(() => { 44 const getAutoCreateKey = computed(() => {
55 return unref(propsRef).autoCreateKey && !unref(propsRef).rowKey; 45 return unref(propsRef).autoCreateKey && !unref(propsRef).rowKey;
56 }); 46 });
57 47
  48 + const getRowKey = computed(() => {
  49 + const { rowKey } = unref(propsRef);
  50 + return unref(getAutoCreateKey) ? ROW_KEY : rowKey;
  51 + });
  52 +
58 const getDataSourceRef = computed(() => { 53 const getDataSourceRef = computed(() => {
59 const dataSource = unref(dataSourceRef); 54 const dataSource = unref(dataSourceRef);
60 if (!dataSource || dataSource.length === 0) { 55 if (!dataSource || dataSource.length === 0) {
@@ -86,20 +81,20 @@ export function useDataSource( @@ -86,20 +81,20 @@ export function useDataSource(
86 ); 81 );
87 if (!api || !isFunction(api)) return; 82 if (!api || !isFunction(api)) return;
88 try { 83 try {
89 - loadingRef.value = true; 84 + setLoading(true);
90 const { pageField, sizeField, listField, totalField } = fetchSetting || FETCH_SETTING; 85 const { pageField, sizeField, listField, totalField } = fetchSetting || FETCH_SETTING;
91 - let pageParams: any = {};  
92 -  
93 - const { current, pageSize } = unref(getPaginationRef) as PaginationProps;  
94 -  
95 - if (isBoolean(getPaginationRef)) { 86 + let pageParams: Recordable = {};
  87 +
  88 + const { current = 1, pageSize = PAGE_SIZE } = unref(getPaginationInfo) as PaginationProps;
  89 +
  90 + if (isBoolean(getPaginationInfo)) {
96 pageParams = {}; 91 pageParams = {};
97 } else { 92 } else {
98 pageParams[pageField] = (opt && opt.page) || current; 93 pageParams[pageField] = (opt && opt.page) || current;
99 pageParams[sizeField] = pageSize; 94 pageParams[sizeField] = pageSize;
100 } 95 }
101 96
102 - let params: any = { 97 + let params: Recordable = {
103 ...pageParams, 98 ...pageParams,
104 ...(useSearchForm ? getFieldsValue() : {}), 99 ...(useSearchForm ? getFieldsValue() : {}),
105 ...searchInfo, 100 ...searchInfo,
@@ -112,18 +107,21 @@ export function useDataSource( @@ -112,18 +107,21 @@ export function useDataSource(
112 } 107 }
113 108
114 const res = await api(params); 109 const res = await api(params);
115 - let resultItems: any[] = get(res, listField);  
116 - const resultTotal: number = get(res, totalField);  
117 - 110 +
  111 + const isArrayResult = Array.isArray(res);
  112 +
  113 + let resultItems: Recordable[] = isArrayResult ? res : get(res, listField);
  114 + const resultTotal: number = isArrayResult ? 0 : get(res, totalField);
  115 +
118 // 假如数据变少,导致总页数变少并小于当前选中页码,通过getPaginationRef获取到的页码是不正确的,需获取正确的页码再次执行 116 // 假如数据变少,导致总页数变少并小于当前选中页码,通过getPaginationRef获取到的页码是不正确的,需获取正确的页码再次执行
119 - var currentTotalPage = Math.ceil(resultTotal / pageSize); 117 + const currentTotalPage = Math.ceil(resultTotal / pageSize);
120 if (current > currentTotalPage) { 118 if (current > currentTotalPage) {
121 - setPagination({  
122 - current: currentTotalPage,  
123 - });  
124 - fetch(opt); 119 + setPagination({
  120 + current: currentTotalPage,
  121 + });
  122 + fetch(opt);
125 } 123 }
126 - 124 +
127 if (afterFetch && isFunction(afterFetch)) { 125 if (afterFetch && isFunction(afterFetch)) {
128 resultItems = afterFetch(resultItems) || resultItems; 126 resultItems = afterFetch(resultItems) || resultItems;
129 } 127 }
@@ -147,20 +145,35 @@ export function useDataSource( @@ -147,20 +145,35 @@ export function useDataSource(
147 total: 0, 145 total: 0,
148 }); 146 });
149 } finally { 147 } finally {
150 - loadingRef.value = false;  
151 - // setSearchFormLoading(false); 148 + setLoading(false);
152 } 149 }
153 } 150 }
154 151
155 - function setTableData(values: any[]) { 152 + function setTableData<T = Recordable>(values: T[]) {
156 dataSourceRef.value = values; 153 dataSourceRef.value = values;
157 } 154 }
  155 +
  156 + function getDataSource<T = Recordable>() {
  157 + return getDataSourceRef.value as T[];
  158 + }
  159 +
  160 + async function reload(opt?: FetchParams) {
  161 + await fetch(opt);
  162 + }
  163 +
158 onMounted(() => { 164 onMounted(() => {
159 - // 转异步任务  
160 useTimeoutFn(() => { 165 useTimeoutFn(() => {
161 unref(propsRef).immediate && fetch(); 166 unref(propsRef).immediate && fetch();
162 }, 0); 167 }, 0);
163 }); 168 });
164 169
165 - return { getDataSourceRef, setTableData, getAutoCreateKey, fetch: fetch }; 170 + return {
  171 + getDataSourceRef,
  172 + getDataSource,
  173 + getRowKey,
  174 + setTableData,
  175 + getAutoCreateKey,
  176 + fetch,
  177 + reload,
  178 + };
166 } 179 }
src/components/Table/src/hooks/useLoading.ts
1 -import { watch, ref, ComputedRef, unref } from 'vue';  
2 -import { BasicTableProps } from '../types/table';  
3 -import { useProps } from './useProps';  
4 -export function useLoading(refProps: ComputedRef<BasicTableProps>) {  
5 - const { propsRef } = useProps(refProps);  
6 -  
7 - const loadingRef = ref(unref(propsRef).loading);  
8 - watch(  
9 - () => unref(propsRef).loading,  
10 - (v: boolean) => {  
11 - loadingRef.value = v;  
12 - }  
13 - );  
14 - return { loadingRef }; 1 +import { ref, ComputedRef, unref, computed, watchEffect } from 'vue';
  2 +import type { BasicTableProps } from '../types/table';
  3 +
  4 +export function useLoading(props: ComputedRef<BasicTableProps>) {
  5 + const loadingRef = ref(unref(props).loading);
  6 +
  7 + watchEffect(() => {
  8 + loadingRef.value = unref(props).loading;
  9 + });
  10 +
  11 + const getLoading = computed(() => {
  12 + return unref(loadingRef);
  13 + });
  14 +
  15 + function setLoading(loading: boolean) {
  16 + loadingRef.value = loading;
  17 + }
  18 +
  19 + return { getLoading, setLoading };
15 } 20 }
src/components/Table/src/hooks/usePagination.tsx
@@ -7,16 +7,30 @@ import { LeftOutlined, RightOutlined } from &#39;@ant-design/icons-vue&#39;; @@ -7,16 +7,30 @@ import { LeftOutlined, RightOutlined } from &#39;@ant-design/icons-vue&#39;;
7 import { isBoolean } from '/@/utils/is'; 7 import { isBoolean } from '/@/utils/is';
8 8
9 import { PAGE_SIZE, PAGE_SIZE_OPTIONS } from '../const'; 9 import { PAGE_SIZE, PAGE_SIZE_OPTIONS } from '../const';
10 -import { useProps } from './useProps';  
11 import { useI18n } from '/@/hooks/web/useI18n'; 10 import { useI18n } from '/@/hooks/web/useI18n';
12 11
13 -const { t } = useI18n(); 12 +interface ItemRender {
  13 + page: number;
  14 + type: 'page' | 'prev' | 'next';
  15 + originalElement: any;
  16 +}
  17 +
  18 +function itemRender({ page, type, originalElement }: ItemRender) {
  19 + if (type === 'prev') {
  20 + return page === 0 ? null : <LeftOutlined />;
  21 + } else if (type === 'next') {
  22 + return page === 1 ? null : <RightOutlined />;
  23 + }
  24 + return originalElement;
  25 +}
  26 +
14 export function usePagination(refProps: ComputedRef<BasicTableProps>) { 27 export function usePagination(refProps: ComputedRef<BasicTableProps>) {
15 const configRef = ref<PaginationProps>({}); 28 const configRef = ref<PaginationProps>({});
16 - const { propsRef } = useProps(refProps);  
17 29
18 - const getPaginationRef = computed((): PaginationProps | false => {  
19 - const { pagination } = unref(propsRef); 30 + const { t } = useI18n();
  31 + const getPaginationInfo = computed((): PaginationProps | boolean => {
  32 + const { pagination } = unref(refProps);
  33 +
20 if (isBoolean(pagination) && !pagination) { 34 if (isBoolean(pagination) && !pagination) {
21 return false; 35 return false;
22 } 36 }
@@ -28,20 +42,7 @@ export function usePagination(refProps: ComputedRef&lt;BasicTableProps&gt;) { @@ -28,20 +42,7 @@ export function usePagination(refProps: ComputedRef&lt;BasicTableProps&gt;) {
28 showTotal: (total) => t('component.table.total', { total }), 42 showTotal: (total) => t('component.table.total', { total }),
29 showSizeChanger: true, 43 showSizeChanger: true,
30 pageSizeOptions: PAGE_SIZE_OPTIONS, 44 pageSizeOptions: PAGE_SIZE_OPTIONS,
31 - itemRender: ({ page, type, originalElement }) => {  
32 - if (type === 'prev') {  
33 - if (page === 0) {  
34 - return null;  
35 - }  
36 - return <LeftOutlined />;  
37 - } else if (type === 'next') {  
38 - if (page === 1) {  
39 - return null;  
40 - }  
41 - return <RightOutlined />;  
42 - }  
43 - return originalElement;  
44 - }, 45 + itemRender: itemRender,
45 showQuickJumper: true, 46 showQuickJumper: true,
46 ...(isBoolean(pagination) ? {} : pagination), 47 ...(isBoolean(pagination) ? {} : pagination),
47 ...unref(configRef), 48 ...unref(configRef),
@@ -49,10 +50,15 @@ export function usePagination(refProps: ComputedRef&lt;BasicTableProps&gt;) { @@ -49,10 +50,15 @@ export function usePagination(refProps: ComputedRef&lt;BasicTableProps&gt;) {
49 }); 50 });
50 51
51 function setPagination(info: Partial<PaginationProps>) { 52 function setPagination(info: Partial<PaginationProps>) {
  53 + const paginationInfo = unref(getPaginationInfo);
52 configRef.value = { 54 configRef.value = {
53 - ...unref(getPaginationRef), 55 + ...(!isBoolean(paginationInfo) ? paginationInfo : {}),
54 ...info, 56 ...info,
55 }; 57 };
56 } 58 }
57 - return { getPaginationRef, setPagination }; 59 +
  60 + function getPagination() {
  61 + return unref(getPaginationInfo);
  62 + }
  63 + return { getPagination, getPaginationInfo, setPagination };
58 } 64 }
src/components/Table/src/hooks/useProps.ts deleted 100644 → 0
1 -import { Ref, ref, watch, unref } from 'vue';  
2 -  
3 -import type { BasicTableProps } from '../types/table';  
4 -  
5 -/**  
6 - * @description:  
7 - * @Date: 2020-05-12 13:20:37  
8 - */  
9 -export function useProps(props: Readonly<Ref<BasicTableProps>>) {  
10 - const propsRef = (ref<BasicTableProps>(unref(props)) as unknown) as Ref<BasicTableProps>;  
11 - watch(  
12 - () => props.value,  
13 - (v) => {  
14 - propsRef.value = unref(v);  
15 - },  
16 - {  
17 - immediate: false,  
18 - }  
19 - );  
20 - return { propsRef };  
21 -}  
src/components/Table/src/hooks/useRowSelection.ts
1 import type { BasicTableProps, TableRowSelection } from '../types/table'; 1 import type { BasicTableProps, TableRowSelection } from '../types/table';
2 2
3 import { computed, ref, unref, ComputedRef } from 'vue'; 3 import { computed, ref, unref, ComputedRef } from 'vue';
4 -import { useProps } from './useProps';  
5 4
6 /* eslint-disable */ 5 /* eslint-disable */
7 -export function useRowSelection(refProps: ComputedRef<BasicTableProps>, emit: EmitType) {  
8 - const { propsRef } = useProps(refProps);  
9 - 6 +export function useRowSelection(propsRef: ComputedRef<BasicTableProps>, emit: EmitType) {
10 const selectedRowKeysRef = ref<string[]>([]); 7 const selectedRowKeysRef = ref<string[]>([]);
11 - const selectedRowRef = ref<any[]>([]); 8 + const selectedRowRef = ref<Recordable[]>([]);
12 9
13 const getRowSelectionRef = computed((): TableRowSelection | null => { 10 const getRowSelectionRef = computed((): TableRowSelection | null => {
14 - const rowSelection = unref(propsRef).rowSelection; 11 + const { rowSelection } = unref(propsRef);
15 if (!rowSelection) { 12 if (!rowSelection) {
16 return null; 13 return null;
17 } 14 }
@@ -46,11 +43,14 @@ export function useRowSelection(refProps: ComputedRef&lt;BasicTableProps&gt;, emit: Em @@ -46,11 +43,14 @@ export function useRowSelection(refProps: ComputedRef&lt;BasicTableProps&gt;, emit: Em
46 unref(selectedRowKeysRef).splice(index, 1); 43 unref(selectedRowKeysRef).splice(index, 1);
47 } 44 }
48 } 45 }
  46 +
49 function getSelectRowKeys() { 47 function getSelectRowKeys() {
50 return unref(selectedRowKeysRef); 48 return unref(selectedRowKeysRef);
51 } 49 }
52 - function getSelectRows() {  
53 - return unref(selectedRowRef); 50 +
  51 + function getSelectRows<T = Recordable>() {
  52 + // const ret = toRaw(unref(selectedRowRef)).map((item) => toRaw(item));
  53 + return unref(selectedRowRef) as T[];
54 } 54 }
55 55
56 return { 56 return {
src/components/Table/src/hooks/useTable.ts
@@ -14,10 +14,11 @@ export function useTable( @@ -14,10 +14,11 @@ export function useTable(
14 const loadedRef = ref<Nullable<boolean>>(false); 14 const loadedRef = ref<Nullable<boolean>>(false);
15 15
16 function register(instance: TableActionType) { 16 function register(instance: TableActionType) {
17 - onUnmounted(() => {  
18 - tableRef.value = null;  
19 - loadedRef.value = null;  
20 - }); 17 + isProdMode() &&
  18 + onUnmounted(() => {
  19 + tableRef.value = null;
  20 + loadedRef.value = null;
  21 + });
21 22
22 if (unref(loadedRef) && isProdMode() && instance === unref(tableRef)) { 23 if (unref(loadedRef) && isProdMode() && instance === unref(tableRef)) {
23 return; 24 return;
src/components/Table/src/hooks/useTableScroll.ts
1 import type { BasicTableProps } from '../types/table'; 1 import type { BasicTableProps } from '../types/table';
2 -import { computed, Ref, onMounted, unref, ref, nextTick, ComputedRef, watch } from 'vue'; 2 +import type { Ref, ComputedRef } from 'vue';
  3 +import { computed, unref, ref, nextTick, watchEffect } from 'vue';
3 4
4 import { getViewportOffset } from '/@/utils/domUtils'; 5 import { getViewportOffset } from '/@/utils/domUtils';
5 import { isBoolean } from '/@/utils/is'; 6 import { isBoolean } from '/@/utils/is';
6 7
7 import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn'; 8 import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
8 -import { useProps } from './useProps';  
9 import { useModalContext } from '/@/components/Modal'; 9 import { useModalContext } from '/@/components/Modal';
10 10
11 -export function useTableScroll(refProps: ComputedRef<BasicTableProps>, tableElRef: Ref<any>) {  
12 - const { propsRef } = useProps(refProps);  
13 -  
14 - const tableHeightRef: Ref<number | null> = ref(null); 11 +export function useTableScroll(
  12 + propsRef: ComputedRef<BasicTableProps>,
  13 + tableElRef: Ref<ComponentRef>
  14 +) {
  15 + const tableHeightRef: Ref<Nullable<number>> = ref(null);
15 16
16 const modalFn = useModalContext(); 17 const modalFn = useModalContext();
17 18
18 - watch(  
19 - () => unref(propsRef).canResize,  
20 - () => {  
21 - redoHeight();  
22 - }  
23 - ); 19 + const getCanResize = computed(() => {
  20 + const { canResize, scroll } = unref(propsRef);
  21 + return canResize && !(scroll || {}).y;
  22 + });
24 23
25 - function redoHeight() {  
26 - const { canResize } = unref(propsRef); 24 + watchEffect(() => {
  25 + redoHeight();
  26 + });
27 27
28 - if (!canResize) return;  
29 - calcTableHeight(); 28 + function redoHeight() {
  29 + if (unref(getCanResize)) {
  30 + nextTick(() => {
  31 + calcTableHeight();
  32 + });
  33 + }
30 } 34 }
31 35
  36 + // No need to repeat queries
32 let paginationEl: HTMLElement | null; 37 let paginationEl: HTMLElement | null;
33 let footerEl: HTMLElement | null; 38 let footerEl: HTMLElement | null;
  39 +
34 async function calcTableHeight() { 40 async function calcTableHeight() {
35 - const { canResize, resizeHeightOffset, pagination, maxHeight } = unref(propsRef);  
36 - if (!canResize) return; 41 + const { resizeHeightOffset, pagination, maxHeight } = unref(propsRef);
  42 + if (!unref(getCanResize)) return;
37 43
38 await nextTick(); 44 await nextTick();
39 - const table = unref(tableElRef) as any; 45 + const table = unref(tableElRef);
40 if (!table) return; 46 if (!table) return;
41 47
42 const tableEl: Element = table.$el; 48 const tableEl: Element = table.$el;
43 if (!tableEl) return; 49 if (!tableEl) return;
  50 +
44 const headEl = tableEl.querySelector('.ant-table-thead '); 51 const headEl = tableEl.querySelector('.ant-table-thead ');
45 if (!headEl) return; 52 if (!headEl) return;
46 53
47 - // 表格距离底部高度 54 + // Table height from bottom
48 const { bottomIncludeBody } = getViewportOffset(headEl); 55 const { bottomIncludeBody } = getViewportOffset(headEl);
49 - // 表格高度+距离底部高度-自定义偏移量 56 + // Table height from bottom height-custom offset
50 57
51 const paddingHeight = 32; 58 const paddingHeight = 32;
52 const borderHeight = 2 * 2; 59 const borderHeight = 2 * 2;
53 - // 分页器高度  
54 - 60 + // Pager height
55 let paginationHeight = 2; 61 let paginationHeight = 2;
56 if (!isBoolean(pagination)) { 62 if (!isBoolean(pagination)) {
57 if (!paginationEl) { 63 if (!paginationEl) {
@@ -61,7 +67,7 @@ export function useTableScroll(refProps: ComputedRef&lt;BasicTableProps&gt;, tableElRe @@ -61,7 +67,7 @@ export function useTableScroll(refProps: ComputedRef&lt;BasicTableProps&gt;, tableElRe
61 const offsetHeight = paginationEl.offsetHeight; 67 const offsetHeight = paginationEl.offsetHeight;
62 paginationHeight += offsetHeight || 0; 68 paginationHeight += offsetHeight || 0;
63 } else { 69 } else {
64 - // TODO 先固定24 70 + // TODO First fix 24
65 paginationHeight += 24; 71 paginationHeight += 24;
66 } 72 }
67 } 73 }
@@ -75,11 +81,13 @@ export function useTableScroll(refProps: ComputedRef&lt;BasicTableProps&gt;, tableElRe @@ -75,11 +81,13 @@ export function useTableScroll(refProps: ComputedRef&lt;BasicTableProps&gt;, tableElRe
75 footerHeight += offsetHeight || 0; 81 footerHeight += offsetHeight || 0;
76 } 82 }
77 } 83 }
  84 +
78 let headerHeight = 0; 85 let headerHeight = 0;
79 if (headEl) { 86 if (headEl) {
80 headerHeight = (headEl as HTMLElement).offsetHeight; 87 headerHeight = (headEl as HTMLElement).offsetHeight;
81 } 88 }
82 - tableHeightRef.value = 89 +
  90 + const height =
83 bottomIncludeBody - 91 bottomIncludeBody -
84 (resizeHeightOffset || 0) - 92 (resizeHeightOffset || 0) -
85 paddingHeight - 93 paddingHeight -
@@ -89,27 +97,14 @@ export function useTableScroll(refProps: ComputedRef&lt;BasicTableProps&gt;, tableElRe @@ -89,27 +97,14 @@ export function useTableScroll(refProps: ComputedRef&lt;BasicTableProps&gt;, tableElRe
89 headerHeight; 97 headerHeight;
90 98
91 setTimeout(() => { 99 setTimeout(() => {
92 - tableHeightRef.value =  
93 - tableHeightRef.value! > maxHeight! ? (maxHeight as number) : tableHeightRef.value;  
94 - // 解决表格放modal内的时候,modal自适应高度计算问题 100 + tableHeightRef.value = (height > maxHeight! ? (maxHeight as number) : height) ?? height;
  101 + // Solve the problem of modal adaptive height calculation when the form is placed in the modal
95 modalFn?.redoModalHeight?.(); 102 modalFn?.redoModalHeight?.();
96 - }, 16); 103 + }, 0);
97 } 104 }
98 105
99 - const getCanResize = computed(() => {  
100 - const { canResize, scroll } = unref(propsRef);  
101 - return canResize && !(scroll || {}).y;  
102 - });  
103 -  
104 useWindowSizeFn(calcTableHeight, 100); 106 useWindowSizeFn(calcTableHeight, 100);
105 107
106 - onMounted(() => {  
107 - if (unref(getCanResize)) {  
108 - nextTick(() => {  
109 - calcTableHeight();  
110 - });  
111 - }  
112 - });  
113 const getScrollRef = computed(() => { 108 const getScrollRef = computed(() => {
114 const tableHeight = unref(tableHeightRef); 109 const tableHeight = unref(tableHeightRef);
115 const { canResize, scroll } = unref(propsRef); 110 const { canResize, scroll } = unref(propsRef);
@@ -121,5 +116,6 @@ export function useTableScroll(refProps: ComputedRef&lt;BasicTableProps&gt;, tableElRe @@ -121,5 +116,6 @@ export function useTableScroll(refProps: ComputedRef&lt;BasicTableProps&gt;, tableElRe
121 ...scroll, 116 ...scroll,
122 }; 117 };
123 }); 118 });
  119 +
124 return { getScrollRef, redoHeight }; 120 return { getScrollRef, redoHeight };
125 } 121 }
src/components/Table/src/hooks/useTableStyle.ts 0 → 100644
  1 +import type { ComputedRef } from 'vue';
  2 +import type { BasicTableProps, TableCustomRecord } from '../types/table';
  3 +import { unref } from 'vue';
  4 +import { isFunction } from '/@/utils/is';
  5 +export function useTableStyle(propsRef: ComputedRef<BasicTableProps>) {
  6 + function getRowClassName(record: TableCustomRecord, index: number) {
  7 + const { striped, rowClassName } = unref(propsRef);
  8 + if (!striped) return;
  9 + if (rowClassName && isFunction(rowClassName)) {
  10 + return rowClassName(record);
  11 + }
  12 + return (index || 0) % 2 === 1 ? 'basic-table-row__striped' : '';
  13 + }
  14 +
  15 + return {
  16 + getRowClassName,
  17 + };
  18 +}
src/components/Table/src/props.ts
@@ -14,6 +14,7 @@ import { propTypes } from &#39;/@/utils/propTypes&#39;; @@ -14,6 +14,7 @@ import { propTypes } from &#39;/@/utils/propTypes&#39;;
14 14
15 // 注释看 types/table 15 // 注释看 types/table
16 export const basicProps = { 16 export const basicProps = {
  17 + clickToRowSelect: propTypes.bool.def(true),
17 tableSetting: { 18 tableSetting: {
18 type: Object as PropType<TableSetting>, 19 type: Object as PropType<TableSetting>,
19 }, 20 },
@@ -34,7 +35,6 @@ export const basicProps = { @@ -34,7 +35,6 @@ export const basicProps = {
34 }, 35 },
35 36
36 canColDrag: propTypes.bool.def(true), 37 canColDrag: propTypes.bool.def(true),
37 - isTreeTable: propTypes.bool,  
38 api: { 38 api: {
39 type: Function as PropType<(...arg: any[]) => Promise<any>>, 39 type: Function as PropType<(...arg: any[]) => Promise<any>>,
40 default: null, 40 default: null,
src/components/Table/src/style/index.less
@@ -167,20 +167,6 @@ @@ -167,20 +167,6 @@
167 } 167 }
168 } 168 }
169 169
170 - .ant-radio {  
171 - &-inner {  
172 - border-color: @text-color-base;  
173 - }  
174 - }  
175 -  
176 - .ant-checkbox {  
177 - &:not(.ant-checkbox-checked) {  
178 - .ant-checkbox-inner {  
179 - border-color: @text-color-base;  
180 - }  
181 - }  
182 - }  
183 -  
184 .ant-table-bordered .ant-table-thead > tr:not(:last-child) > th, 170 .ant-table-bordered .ant-table-thead > tr:not(:last-child) > th,
185 .ant-table-tbody > tr > td { 171 .ant-table-tbody > tr > td {
186 word-break: break-word; 172 word-break: break-word;
src/components/Table/src/types/table.ts
@@ -124,6 +124,8 @@ export interface TableSetting { @@ -124,6 +124,8 @@ export interface TableSetting {
124 } 124 }
125 125
126 export interface BasicTableProps<T = any> { 126 export interface BasicTableProps<T = any> {
  127 + // 点击行选中
  128 + clickToRowSelect?: boolean;
127 // 自定义排序方法 129 // 自定义排序方法
128 sortFn?: (sortInfo: SorterResult) => any; 130 sortFn?: (sortInfo: SorterResult) => any;
129 // 取消表格的默认padding 131 // 取消表格的默认padding
@@ -141,8 +143,6 @@ export interface BasicTableProps&lt;T = any&gt; { @@ -141,8 +143,6 @@ export interface BasicTableProps&lt;T = any&gt; {
141 showSummary?: boolean; 143 showSummary?: boolean;
142 // 是否可拖拽列 144 // 是否可拖拽列
143 canColDrag?: boolean; 145 canColDrag?: boolean;
144 - // 是否树表  
145 - isTreeTable?: boolean;  
146 // 接口请求对象 146 // 接口请求对象
147 api?: (...arg: any) => Promise<any>; 147 api?: (...arg: any) => Promise<any>;
148 // 请求之前处理参数 148 // 请求之前处理参数
@@ -158,7 +158,7 @@ export interface BasicTableProps&lt;T = any&gt; { @@ -158,7 +158,7 @@ export interface BasicTableProps&lt;T = any&gt; {
158 // 在开起搜索表单的时候,如果没有数据是否显示表格 158 // 在开起搜索表单的时候,如果没有数据是否显示表格
159 emptyDataIsShowTable?: boolean; 159 emptyDataIsShowTable?: boolean;
160 // 额外的请求参数 160 // 额外的请求参数
161 - searchInfo?: any; 161 + searchInfo?: Recordable;
162 // 使用搜索表单 162 // 使用搜索表单
163 useSearchForm?: boolean; 163 useSearchForm?: boolean;
164 // 表单配置 164 // 表单配置
@@ -180,9 +180,9 @@ export interface BasicTableProps&lt;T = any&gt; { @@ -180,9 +180,9 @@ export interface BasicTableProps&lt;T = any&gt; {
180 // 在分页改变的时候清空选项 180 // 在分页改变的时候清空选项
181 clearSelectOnPageChange?: boolean; 181 clearSelectOnPageChange?: boolean;
182 // 182 //
183 - rowKey?: string | ((record: any) => string); 183 + rowKey?: string | ((record: Recordable) => string);
184 // 数据 184 // 数据
185 - dataSource?: any[]; 185 + dataSource?: Recordable[];
186 // 标题右侧提示 186 // 标题右侧提示
187 titleHelpMessage?: string | string[]; 187 titleHelpMessage?: string | string[];
188 // 表格滚动最大高度 188 // 表格滚动最大高度
src/views/demo/table/Basic.vue
@@ -9,7 +9,8 @@ @@ -9,7 +9,8 @@
9 :loading="loading" 9 :loading="loading"
10 :striped="striped" 10 :striped="striped"
11 :bordered="border" 11 :bordered="border"
12 - :pagination="{ pageSize: 20 }" 12 + showTableSetting
  13 + :pagination="pagination"
13 > 14 >
14 <template #toolbar> 15 <template #toolbar>
15 <a-button type="primary" @click="toggleCanResize"> 16 <a-button type="primary" @click="toggleCanResize">
@@ -38,6 +39,7 @@ @@ -38,6 +39,7 @@
38 const loading = ref(false); 39 const loading = ref(false);
39 const striped = ref(true); 40 const striped = ref(true);
40 const border = ref(true); 41 const border = ref(true);
  42 + const pagination = ref<any>(false);
41 function toggleCanResize() { 43 function toggleCanResize() {
42 canResize.value = !canResize.value; 44 canResize.value = !canResize.value;
43 } 45 }
@@ -48,6 +50,7 @@ @@ -48,6 +50,7 @@
48 loading.value = true; 50 loading.value = true;
49 setTimeout(() => { 51 setTimeout(() => {
50 loading.value = false; 52 loading.value = false;
  53 + pagination.value = { pageSize: 20 };
51 }, 3000); 54 }, 3000);
52 } 55 }
53 function toggleBorder() { 56 function toggleBorder() {
@@ -64,6 +67,7 @@ @@ -64,6 +67,7 @@
64 toggleCanResize, 67 toggleCanResize,
65 toggleLoading, 68 toggleLoading,
66 toggleBorder, 69 toggleBorder,
  70 + pagination,
67 }; 71 };
68 }, 72 },
69 }); 73 });
src/views/demo/table/FixedColumn.vue
@@ -74,10 +74,10 @@ @@ -74,10 +74,10 @@
74 slots: { customRender: 'action' }, 74 slots: { customRender: 'action' },
75 }, 75 },
76 }); 76 });
77 - function handleDelete(record: any) { 77 + function handleDelete(record: Recordable) {
78 console.log('点击了删除', record); 78 console.log('点击了删除', record);
79 } 79 }
80 - function handleOpen(record: any) { 80 + function handleOpen(record: Recordable) {
81 console.log('点击了启用', record); 81 console.log('点击了启用', record);
82 } 82 }
83 return { 83 return {
src/views/demo/table/TreeTable.vue
@@ -2,7 +2,6 @@ @@ -2,7 +2,6 @@
2 <div class="p-4"> 2 <div class="p-4">
3 <BasicTable 3 <BasicTable
4 :rowSelection="{ type: 'checkbox' }" 4 :rowSelection="{ type: 'checkbox' }"
5 - :isTreeTable="true"  
6 title="树形表格" 5 title="树形表格"
7 titleHelpMessage="树形组件不能和序列号列同时存在" 6 titleHelpMessage="树形组件不能和序列号列同时存在"
8 :columns="columns" 7 :columns="columns"
src/views/demo/table/UseTable.vue
@@ -44,12 +44,13 @@ @@ -44,12 +44,13 @@
44 clearSelectedRowKeys, 44 clearSelectedRowKeys,
45 }, 45 },
46 ] = useTable({ 46 ] = useTable({
47 - canResize: false, 47 + canResize: true,
48 title: 'useTable示例', 48 title: 'useTable示例',
49 titleHelpMessage: '使用useTable调用表格内方法', 49 titleHelpMessage: '使用useTable调用表格内方法',
50 api: demoListApi, 50 api: demoListApi,
51 columns: getBasicColumns(), 51 columns: getBasicColumns(),
52 rowKey: 'id', 52 rowKey: 'id',
  53 + showTableSetting: true,
53 rowSelection: { 54 rowSelection: {
54 type: 'checkbox', 55 type: 'checkbox',
55 }, 56 },
src/views/demo/table/tableData.tsx
@@ -5,13 +5,13 @@ export function getBasicColumns(): BasicColumn[] { @@ -5,13 +5,13 @@ export function getBasicColumns(): BasicColumn[] {
5 return [ 5 return [
6 { 6 {
7 title: 'ID', 7 title: 'ID',
8 - width: 150,  
9 dataIndex: 'id', 8 dataIndex: 'id',
  9 + width: 150,
10 }, 10 },
11 { 11 {
12 title: '姓名', 12 title: '姓名',
13 dataIndex: 'name', 13 dataIndex: 'name',
14 - width: 120, 14 + width: 150,
15 }, 15 },
16 { 16 {
17 title: '地址', 17 title: '地址',
@@ -20,14 +20,16 @@ export function getBasicColumns(): BasicColumn[] { @@ -20,14 +20,16 @@ export function getBasicColumns(): BasicColumn[] {
20 { 20 {
21 title: '编号', 21 title: '编号',
22 dataIndex: 'no', 22 dataIndex: 'no',
23 - width: 80, 23 + width: 150,
24 }, 24 },
25 { 25 {
26 title: '开始时间', 26 title: '开始时间',
  27 + width: 120,
27 dataIndex: 'beginTime', 28 dataIndex: 'beginTime',
28 }, 29 },
29 { 30 {
30 title: '结束时间', 31 title: '结束时间',
  32 + width: 120,
31 sorter: true, 33 sorter: true,
32 dataIndex: 'endTime', 34 dataIndex: 'endTime',
33 }, 35 },