11import { ref , Ref , reactive } from '@vue/composition-api' ;
2- import isNumber from 'lodash/isNumber' ;
32import { RecalculateColumnWidthFunc } from '../interface' ;
43import { BaseTableCol , TableRowData } from '../type' ;
4+ import setThWidthListByColumnDrag from '../../_common/js/table/set-column-width-by-drag' ;
5+ import recalculateColumnWidth from '../../_common/js/table/recalculate-column-width' ;
56
67const DEFAULT_MIN_WIDTH = 80 ;
78const DEFAULT_MAX_WIDTH = 600 ;
@@ -14,6 +15,23 @@ export default function useColumnResize(
1415) {
1516 const resizeLineRef = ref < HTMLDivElement > ( ) ;
1617 const notCalculateWidthCols = ref < string [ ] > ( [ ] ) ;
18+ const effectColMap = ref < { [ colKey : string ] : any } > ( { } ) ;
19+
20+ // 递归查找列宽度变化后,受影响的相关列
21+ const setEffectColMap = ( nodes : BaseTableCol < TableRowData > [ ] , parent : BaseTableCol < TableRowData > | null ) => {
22+ if ( ! nodes ) return ;
23+ nodes . forEach ( ( n , index ) => {
24+ const parentPrevCol = parent ? effectColMap . value [ parent . colKey ] . prev : nodes [ index + 1 ] ;
25+ const parentNextCol = parent ? effectColMap . value [ parent . colKey ] . next : nodes [ index - 1 ] ;
26+ const prev = index === 0 ? parentPrevCol : nodes [ index - 1 ] ;
27+ const next = index === nodes . length - 1 ? parentNextCol : nodes [ index + 1 ] ;
28+ effectColMap . value [ n . colKey ] = {
29+ prev,
30+ next,
31+ } ;
32+ setEffectColMap ( n . children , n ) ;
33+ } ) ;
34+ } ;
1735
1836 const resizeLineParams = {
1937 isDragging : false ,
@@ -67,12 +85,7 @@ export default function useColumnResize(
6785 } ;
6886
6987 // 调整表格列宽
70- const onColumnMousedown = (
71- e : MouseEvent ,
72- col : BaseTableCol < TableRowData > ,
73- effectNextCol : BaseTableCol < TableRowData > ,
74- effectPrevCol : BaseTableCol < TableRowData > ,
75- ) => {
88+ const onColumnMousedown = ( e : MouseEvent , col : BaseTableCol < TableRowData > ) => {
7689 // 非 resize 的点击,不做处理
7790 if ( ! resizeLineParams . draggingCol ) return ;
7891
@@ -86,6 +99,9 @@ export default function useColumnResize(
8699 const minResizeLineLeft = colLeft + minColWidth ;
87100 const maxResizeLineLeft = colLeft + maxColWidth ;
88101
102+ const effectNextCol = effectColMap . value [ col . colKey ] . next ;
103+ const effectPrevCol = effectColMap . value [ col . colKey ] . prev ;
104+
89105 // 开始拖拽,记录下鼠标起始位置
90106 resizeLineParams . isDragging = true ;
91107 resizeLineParams . draggingStart = e . x ;
@@ -99,26 +115,6 @@ export default function useColumnResize(
99115 resizeLineStyle . bottom = `${ parent . bottom - tableBoundRect . bottom } px` ;
100116 }
101117
102- const setThWidthListByColumnDrag = (
103- dragCol : BaseTableCol < TableRowData > ,
104- dragWidth : number ,
105- nearCol : BaseTableCol < TableRowData > ,
106- ) => {
107- const thWidthList = getThWidthList ( ) ;
108-
109- const propColWidth = isNumber ( dragCol . width ) ? dragCol . width : parseFloat ( dragCol . width ) ;
110- const propNearColWidth = isNumber ( nearCol . width ) ? nearCol . width : parseFloat ( nearCol . width ) ;
111- const oldWidth = thWidthList [ dragCol . colKey ] || propColWidth ;
112- const oldNearWidth = thWidthList [ nearCol . colKey ] || propNearColWidth ;
113-
114- updateThWidthList ( {
115- [ dragCol . colKey ] : dragWidth ,
116- [ nearCol . colKey ] : Math . max ( nearCol . resize ?. minWidth || DEFAULT_MIN_WIDTH , oldWidth + oldNearWidth - dragWidth ) ,
117- } ) ;
118-
119- setNotCalculateWidthCols ( [ dragCol . colKey , nearCol . colKey ] ) ;
120- } ;
121-
122118 // 拖拽时鼠标可能会超出 table 范围,需要给 document 绑定拖拽相关事件
123119 const onDragEnd = ( ) => {
124120 if ( resizeLineParams . isDragging ) {
@@ -132,9 +128,27 @@ export default function useColumnResize(
132128 }
133129 // 更新列宽
134130 if ( resizeLineParams . effectCol === 'next' ) {
135- setThWidthListByColumnDrag ( col , width , effectNextCol ) ;
131+ setThWidthListByColumnDrag < BaseTableCol < TableRowData > > (
132+ col ,
133+ width ,
134+ effectNextCol ,
135+ { getThWidthList, DEFAULT_MIN_WIDTH } ,
136+ ( updateMap , notCalculateCols ) => {
137+ updateThWidthList ( updateMap ) ;
138+ setNotCalculateWidthCols ( notCalculateCols ) ;
139+ } ,
140+ ) ;
136141 } else if ( resizeLineParams . effectCol === 'prev' ) {
137- setThWidthListByColumnDrag ( effectPrevCol , width , col ) ;
142+ setThWidthListByColumnDrag < BaseTableCol < TableRowData > > (
143+ effectPrevCol ,
144+ width ,
145+ col ,
146+ { getThWidthList, DEFAULT_MIN_WIDTH } ,
147+ ( updateMap , notCalculateCols ) => {
148+ updateThWidthList ( updateMap ) ;
149+ setNotCalculateWidthCols ( notCalculateCols ) ;
150+ } ,
151+ ) ;
138152 }
139153
140154 // 恢复设置
@@ -175,108 +189,19 @@ export default function useColumnResize(
175189 tableLayout : string ,
176190 tableElmWidth : number ,
177191 ) : void => {
178- let actualWidth = 0 ;
179- const missingWidthCols : BaseTableCol < TableRowData > [ ] = [ ] ;
180- const thMap : { [ colKey : string ] : number } = { } ;
181-
182- // 计算现有列的列宽总和
183- columns . forEach ( ( col ) => {
184- if ( ! thWidthList [ col . colKey ] ) {
185- thMap [ col . colKey ] = isNumber ( col . width ) ? col . width : parseFloat ( col . width ) ;
186- } else {
187- thMap [ col . colKey ] = thWidthList [ col . colKey ] ;
188- }
189- const originWidth = thMap [ col . colKey ] ;
190- if ( originWidth ) {
191- actualWidth += originWidth ;
192- } else {
193- missingWidthCols . push ( col ) ;
194- }
195- } ) ;
196-
197- let tableWidth = tableElmWidth ;
198- let needUpdate = false ;
199- // 表宽没有初始化时,默认给没有指定列宽的列指定宽度为100px
200- if ( tableWidth > 0 ) {
201- // 存在没有指定列宽的列
202- if ( missingWidthCols . length ) {
203- // 当前列宽总宽度小于表宽,将剩余宽度平均分配给未指定宽度的列
204- if ( actualWidth < tableWidth ) {
205- const widthDiff = tableWidth - actualWidth ;
206- const avgWidth = widthDiff / missingWidthCols . length ;
207- missingWidthCols . forEach ( ( col ) => {
208- thMap [ col . colKey ] = avgWidth ;
209- } ) ;
210- } else if ( tableLayout === 'fixed' ) {
211- // 当前列表总宽度大于等于表宽,且当前排版模式为fixed,默认填充100px
212- missingWidthCols . forEach ( ( col ) => {
213- const originWidth = thMap [ col . colKey ] || 100 ;
214- thMap [ col . colKey ] = isNumber ( originWidth ) ? originWidth : parseFloat ( originWidth ) ;
215- } ) ;
216- } else {
217- // 当前列表总宽度大于等于表宽,且当前排版模式为auto,默认填充100px,然后按比例重新分配各列宽度
218- const extraWidth = missingWidthCols . length * 100 ;
219- const totalWidth = extraWidth + actualWidth ;
220- columns . forEach ( ( col ) => {
221- if ( ! thMap [ col . colKey ] ) {
222- thMap [ col . colKey ] = ( 100 / totalWidth ) * tableWidth ;
223- } else {
224- thMap [ col . colKey ] = ( thMap [ col . colKey ] / totalWidth ) * tableWidth ;
225- }
226- } ) ;
227- }
228- needUpdate = true ;
229- } else {
230- // 所有列都已经指定宽度
192+ recalculateColumnWidth < BaseTableCol < TableRowData > > (
193+ columns ,
194+ thWidthList ,
195+ tableLayout ,
196+ tableElmWidth ,
197+ notCalculateWidthCols . value ,
198+ ( widthMap ) => {
199+ updateThWidthList ( widthMap ) ;
231200 if ( notCalculateWidthCols . value . length ) {
232- // 存在不允许重新计算宽度的列(一般是resize后的两列),这些列不参与后续计算
233- let sum = 0 ;
234- notCalculateWidthCols . value . forEach ( ( colKey ) => {
235- sum += thMap [ colKey ] ;
236- } ) ;
237- actualWidth -= sum ;
238- tableWidth -= sum ;
239- }
240- // 重新计算其他列的宽度,按表格剩余宽度进行按比例分配
241- if ( actualWidth !== tableWidth || notCalculateWidthCols . value . length ) {
242- columns . forEach ( ( col ) => {
243- if ( notCalculateWidthCols . value . includes ( col . colKey ) ) return ;
244- thMap [ col . colKey ] = ( thMap [ col . colKey ] / actualWidth ) * tableWidth ;
245- } ) ;
246- needUpdate = true ;
247- }
248- }
249- } else {
250- // 表格宽度未初始化,默认填充100px
251- missingWidthCols . forEach ( ( col ) => {
252- const originWidth = thMap [ col . colKey ] || 100 ;
253- thMap [ col . colKey ] = isNumber ( originWidth ) ? originWidth : parseFloat ( originWidth ) ;
254- } ) ;
255-
256- needUpdate = true ;
257- }
258-
259- // 列宽转为整数
260- if ( needUpdate ) {
261- let addon = 0 ;
262- Object . keys ( thMap ) . forEach ( ( key ) => {
263- const width = thMap [ key ] ;
264- addon += width - Math . floor ( width ) ;
265- thMap [ key ] = Math . floor ( width ) + ( addon > 1 ? 1 : 0 ) ;
266- if ( addon > 1 ) {
267- addon -= 1 ;
201+ notCalculateWidthCols . value = [ ] ;
268202 }
269- } ) ;
270- if ( addon > 0.5 ) {
271- thMap [ columns [ 0 ] . colKey ] += 1 ;
272- }
273- }
274-
275- updateThWidthList ( thMap ) ;
276-
277- if ( notCalculateWidthCols . value . length ) {
278- notCalculateWidthCols . value = [ ] ;
279- }
203+ } ,
204+ ) ;
280205 } ;
281206
282207 return {
@@ -285,5 +210,6 @@ export default function useColumnResize(
285210 onColumnMouseover,
286211 onColumnMousedown,
287212 recalculateColWidth,
213+ setEffectColMap,
288214 } ;
289215}
0 commit comments