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,6 +1,6 @@
1
1
  {
2
2
  "name": "n20-common-lib",
3
- "version": "2.22.77",
3
+ "version": "2.22.78",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -174,7 +174,10 @@ export default {
174
174
  provide() {
175
175
  let bigData = this.bigData
176
176
  return {
177
- bigData
177
+ bigData,
178
+ n20TableContext: {
179
+ getData: () => this.data || []
180
+ }
178
181
  }
179
182
  },
180
183
  watch: {
@@ -1,8 +1,8 @@
1
1
  <template>
2
- <el-table-column v-if="!bigData" v-bind="$attrs">
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="$attrs">
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: { bigData: { default: false } },
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>