n20-common-lib 2.22.77 → 2.22.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<el-table-column v-if="!bigData" v-bind="
|
|
2
|
+
<el-table-column v-if="!bigData" v-bind="resolvedColumnAttrs">
|
|
3
3
|
<OperateBtns slot-scope="{ row, $index }" :btn-list="btnList" :row="row" @command="(c) => $emit(c, row, $index)" />
|
|
4
4
|
</el-table-column>
|
|
5
|
-
<ux-table-column v-else :field="$attrs.prop" :title="$attrs.label" v-bind="
|
|
5
|
+
<ux-table-column v-else :field="$attrs.prop" :title="$attrs.label" v-bind="resolvedColumnAttrs">
|
|
6
6
|
<OperateBtns slot-scope="{ row, $index }" :btn-list="btnList" :row="row" @command="(c) => $emit(c, row, $index)" />
|
|
7
7
|
</ux-table-column>
|
|
8
8
|
</template>
|
|
@@ -10,17 +10,143 @@
|
|
|
10
10
|
<script>
|
|
11
11
|
// import { $lc } from '../../utils/i18n/index'
|
|
12
12
|
import OperateBtns from './OperateBtns.vue'
|
|
13
|
+
|
|
14
|
+
const DEFAULT_OPERATE_COLUMN_MIN_WIDTH = 80
|
|
15
|
+
|
|
13
16
|
export default {
|
|
14
17
|
name: 'TableOperateColumn',
|
|
15
18
|
components: {
|
|
16
19
|
OperateBtns
|
|
17
20
|
},
|
|
18
|
-
inject: {
|
|
21
|
+
inject: {
|
|
22
|
+
bigData: { default: false },
|
|
23
|
+
n20TableContext: { default: null }
|
|
24
|
+
},
|
|
19
25
|
props: {
|
|
20
26
|
btnList: {
|
|
21
27
|
type: Array,
|
|
22
28
|
default: () => []
|
|
23
29
|
}
|
|
30
|
+
},
|
|
31
|
+
computed: {
|
|
32
|
+
resolvedColumnAttrs() {
|
|
33
|
+
const attrs = { ...this.$attrs }
|
|
34
|
+
const hasWidth =
|
|
35
|
+
Object.prototype.hasOwnProperty.call(attrs, 'width') &&
|
|
36
|
+
attrs.width !== null &&
|
|
37
|
+
attrs.width !== undefined &&
|
|
38
|
+
attrs.width !== ''
|
|
39
|
+
if (hasWidth) {
|
|
40
|
+
return attrs
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const minWidthKey = ['minWidth', 'min-width'].find((key) => {
|
|
44
|
+
const value = attrs[key]
|
|
45
|
+
return Object.prototype.hasOwnProperty.call(attrs, key) && value !== null && value !== undefined && value !== ''
|
|
46
|
+
})
|
|
47
|
+
const calculatedWidth = this.calcOperateColumnWidth()
|
|
48
|
+
if (minWidthKey) {
|
|
49
|
+
const minWidth = this.parsePixelWidth(attrs[minWidthKey])
|
|
50
|
+
if (minWidth !== null) {
|
|
51
|
+
attrs[minWidthKey] = Math.max(calculatedWidth, minWidth)
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
// 避免 Element/UX Table 将大量剩余空间分配给操作列。
|
|
55
|
+
attrs.width = calculatedWidth
|
|
56
|
+
}
|
|
57
|
+
return attrs
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
methods: {
|
|
61
|
+
measureOperateText(text) {
|
|
62
|
+
const normalizedText = text === undefined || text === null ? '' : String(text)
|
|
63
|
+
if (!normalizedText) return 0
|
|
64
|
+
|
|
65
|
+
const fallbackWidth = Array.from(normalizedText).reduce(
|
|
66
|
+
(width, char) => width + (/[⺀-鿿]/.test(char) ? 14 : 8),
|
|
67
|
+
0
|
|
68
|
+
)
|
|
69
|
+
if (typeof document === 'undefined') return fallbackWidth
|
|
70
|
+
|
|
71
|
+
const canvas = document.createElement('canvas')
|
|
72
|
+
const context = canvas.getContext('2d')
|
|
73
|
+
if (!context) return fallbackWidth
|
|
74
|
+
|
|
75
|
+
context.font = '14px PingFang SC, Microsoft YaHei, sans-serif'
|
|
76
|
+
return Math.max(context.measureText(normalizedText).width, fallbackWidth)
|
|
77
|
+
},
|
|
78
|
+
parsePixelWidth(value) {
|
|
79
|
+
if (typeof value === 'number') {
|
|
80
|
+
return Number.isFinite(value) && value >= 0 ? value : null
|
|
81
|
+
}
|
|
82
|
+
if (typeof value !== 'string') return null
|
|
83
|
+
|
|
84
|
+
const normalizedValue = value.trim()
|
|
85
|
+
if (!/^\d+(\.\d+)?(px)?$/.test(normalizedValue)) return null
|
|
86
|
+
const parsedValue = Number.parseFloat(normalizedValue)
|
|
87
|
+
return Number.isFinite(parsedValue) ? parsedValue : null
|
|
88
|
+
},
|
|
89
|
+
calcOperateColumnWidth() {
|
|
90
|
+
const CELL_HORIZONTAL_PADDING = this.bigData ? 20 : 16
|
|
91
|
+
// OperateBtns 使用行内元素,除 6px margin 外还会产生约 4px 的模板空白。
|
|
92
|
+
const BUTTON_GAP = 10
|
|
93
|
+
const CHILDREN_ARROW_WIDTH = 20
|
|
94
|
+
const MORE_BUTTON_WIDTH = 16
|
|
95
|
+
const buttons = (this.btnList || []).filter((button) => button && button.isHas !== false)
|
|
96
|
+
const getButtonWidth = (button) => {
|
|
97
|
+
let width = this.measureOperateText(button.label)
|
|
98
|
+
if (button.children && button.children.length > 0) {
|
|
99
|
+
width += CHILDREN_ARROW_WIDTH
|
|
100
|
+
}
|
|
101
|
+
return width
|
|
102
|
+
}
|
|
103
|
+
const buttonWidths = buttons.map(getButtonWidth)
|
|
104
|
+
|
|
105
|
+
if (buttonWidths.length === 0) {
|
|
106
|
+
return DEFAULT_OPERATE_COLUMN_MIN_WIDTH
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const calcLayoutWidth = (inlineWidths, hasMoreButton = false) => {
|
|
110
|
+
const itemCount = inlineWidths.length + (hasMoreButton ? 1 : 0)
|
|
111
|
+
const contentWidth = inlineWidths.reduce((total, width) => total + width, 0)
|
|
112
|
+
const moreButtonWidth = hasMoreButton ? MORE_BUTTON_WIDTH : 0
|
|
113
|
+
const gapWidth = Math.max(itemCount - 1, 0) * BUTTON_GAP
|
|
114
|
+
return contentWidth + moreButtonWidth + gapWidth + CELL_HORIZONTAL_PADDING
|
|
115
|
+
}
|
|
116
|
+
const rows = this.n20TableContext?.getData?.() || []
|
|
117
|
+
if (rows.length > 0) {
|
|
118
|
+
const maxRowWidth = rows.reduce((maxWidth, row) => {
|
|
119
|
+
const visibleButtonWidths = buttons
|
|
120
|
+
.filter((button) => this.hasButton(button.isHas, row))
|
|
121
|
+
.map(getButtonWidth)
|
|
122
|
+
const rowWidth = visibleButtonWidths.length > 3
|
|
123
|
+
? calcLayoutWidth(visibleButtonWidths.slice(0, 2), true)
|
|
124
|
+
: calcLayoutWidth(visibleButtonWidths)
|
|
125
|
+
return Math.max(maxWidth, rowWidth)
|
|
126
|
+
}, 0)
|
|
127
|
+
return Math.max(DEFAULT_OPERATE_COLUMN_MIN_WIDTH, Math.ceil(maxRowWidth))
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const sortedButtonWidths = [...buttonWidths].sort((a, b) => b - a)
|
|
131
|
+
const directButtonsWidth = calcLayoutWidth(sortedButtonWidths.slice(0, 3))
|
|
132
|
+
const collapsedButtonsWidth =
|
|
133
|
+
sortedButtonWidths.length > 3 ? calcLayoutWidth(sortedButtonWidths.slice(0, 2), true) : 0
|
|
134
|
+
|
|
135
|
+
return Math.max(
|
|
136
|
+
DEFAULT_OPERATE_COLUMN_MIN_WIDTH,
|
|
137
|
+
Math.ceil(directButtonsWidth),
|
|
138
|
+
Math.ceil(collapsedButtonsWidth)
|
|
139
|
+
)
|
|
140
|
+
},
|
|
141
|
+
hasButton(isHas, row) {
|
|
142
|
+
if (isHas === undefined || isHas === null) return true
|
|
143
|
+
if (typeof isHas === 'boolean') return isHas
|
|
144
|
+
if (typeof isHas === 'function') return isHas(row)
|
|
145
|
+
if (typeof isHas === 'string' || Array.isArray(isHas)) {
|
|
146
|
+
return typeof this.$has === 'function' ? this.$has(isHas) : true
|
|
147
|
+
}
|
|
148
|
+
return false
|
|
149
|
+
}
|
|
24
150
|
}
|
|
25
151
|
}
|
|
26
152
|
</script>
|