@leevan/jtui 2.0.46 → 2.0.47

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": "@leevan/jtui",
3
- "version": "2.0.46",
3
+ "version": "2.0.47",
4
4
  "scripts": {
5
5
  "serve": "vue-cli-service serve",
6
6
  "build": "vue-cli-service build",
@@ -32,6 +32,32 @@
32
32
  :formatter="formatEnum"
33
33
  :cell-render="cellRenderData(subSubItem.cellRender)"
34
34
  >
35
+ <template v-slot:edit="{ row }" v-if="item && item.edit && item.edit.name == '$select'">
36
+ <div class="custom-select-wrapper" ref="selectWrapper">
37
+ <div
38
+ class="custom-select-input"
39
+ @click="toggleDropdown"
40
+ ref="inputRef"
41
+ >
42
+ <span class="custom-select-value">
43
+ {{ getLabel(row[item.prop]) }}
44
+ </span>
45
+ <i class="custom-select-arrow" :class="{'is-open': isOpen}"></i>
46
+ </div>
47
+ <div class="custom-select-dropdown" v-show="isOpen" ref="dropdownRef">
48
+ <ul>
49
+ <li
50
+ v-for="op in item.edit.options"
51
+ :key="op.value"
52
+ :class="{'is-selected': row[item.prop] === op.value}"
53
+ @mousedown.prevent="selectOption(op, row)"
54
+ >
55
+ {{ op.label }}
56
+ </li>
57
+ </ul>
58
+ </div>
59
+ </div>
60
+ </template>
35
61
  </vxe-table-column>
36
62
  </vxe-colgroup>
37
63
  <vxe-table-column
@@ -52,12 +78,38 @@
52
78
  :formatter="formatEnum"
53
79
  :cell-render="cellRenderData(subItem.cellRender)"
54
80
  >
81
+ <template v-slot:edit="{ row }" v-if="item && item.edit && item.edit.name == '$select'">
82
+ <div class="custom-select-wrapper" ref="selectWrapper">
83
+ <div
84
+ class="custom-select-input"
85
+ @click="toggleDropdown"
86
+ ref="inputRef"
87
+ >
88
+ <span class="custom-select-value">
89
+ {{ getLabel(row[item.prop]) }}
90
+ </span>
91
+ <i class="custom-select-arrow" :class="{'is-open': isOpen}"></i>
92
+ </div>
93
+ <div class="custom-select-dropdown" v-show="isOpen" ref="dropdownRef">
94
+ <ul>
95
+ <li
96
+ v-for="op in item.edit.options"
97
+ :key="op.value"
98
+ :class="{'is-selected': row[item.prop] === op.value}"
99
+ @mousedown.prevent="selectOption(op, row)"
100
+ >
101
+ {{ op.label }}
102
+ </li>
103
+ </ul>
104
+ </div>
105
+ </div>
106
+ </template>
55
107
  </vxe-table-column>
56
108
  </template>
57
109
  </vxe-colgroup>
58
110
  <vxe-table-column
59
111
  v-else
60
- :edit-render="item.edit"
112
+ :edit-render="item.edit && item.edit.name == '$select' ? {autofocus: '.vxe-input--inner'} : item.edit"
61
113
  :key="index"
62
114
  show-overflow
63
115
  :field="item.prop"
@@ -73,6 +125,32 @@
73
125
  :formatter="formatEnum"
74
126
  :cell-render="cellRenderData(item.cellRender)"
75
127
  >
128
+ <template v-slot:edit="{ row }" v-if="item && item.edit && item.edit.name == '$select'">
129
+ <div class="custom-select-wrapper" ref="selectWrapper">
130
+ <div
131
+ class="custom-select-input"
132
+ @click="toggleDropdown"
133
+ ref="inputRef"
134
+ >
135
+ <span class="custom-select-value">
136
+ {{ getLabel(row[item.prop]) }}
137
+ </span>
138
+ <i class="custom-select-arrow" :class="{'is-open': isOpen}"></i>
139
+ </div>
140
+ <div class="custom-select-dropdown" v-show="isOpen" ref="dropdownRef">
141
+ <ul>
142
+ <li
143
+ v-for="op in item.edit.options"
144
+ :key="op.value"
145
+ :class="{'is-selected': row[item.prop] === op.value}"
146
+ @mousedown.prevent="selectOption(op, row)"
147
+ >
148
+ {{ op.label }}
149
+ </li>
150
+ </ul>
151
+ </div>
152
+ </div>
153
+ </template>
76
154
  </vxe-table-column>
77
155
  </template>
78
156
 
@@ -83,9 +161,20 @@ export default {
83
161
 
84
162
  data() {
85
163
  return {
86
-
164
+ isOpen: false
87
165
  };
88
166
  },
167
+ mounted() {
168
+ // 点击外部关闭下拉框
169
+ document.addEventListener('click', this.handleClickOutside);
170
+ // 编辑激活时自动打开
171
+ this.$nextTick(() => {
172
+ this.isOpen = true;
173
+ });
174
+ },
175
+ beforeDestroy() {
176
+ document.removeEventListener('click', this.handleClickOutside);
177
+ },
89
178
  props: {
90
179
  item: Object,
91
180
  filterData: {
@@ -113,9 +202,118 @@ export default {
113
202
  },
114
203
 
115
204
  methods: {
205
+ getLabel(value) {
206
+ if (!this.item || !this.item.edit || !this.item.edit.options) return value;
207
+ const findItem = this.item.edit.options.find(op => op.value === value);
208
+ return findItem ? findItem.label : (value || '请选择');
209
+ },
210
+ toggleDropdown() {
211
+ this.isOpen = !this.isOpen;
212
+ },
213
+ selectOption(op, row) {
214
+ row[this.item.prop] = op.value;
215
+ this.isOpen = false;
216
+ },
217
+ handleClickOutside(e) {
218
+ if (this.$refs.selectWrapper && !this.$refs.selectWrapper.contains(e.target)) {
219
+ this.isOpen = false;
220
+ }
221
+ }
116
222
  },
117
223
  };
118
224
  </script>
119
225
 
120
- <style lang="scss" scoped>
226
+ <style lang="scss">
227
+ .custom-select-wrapper {
228
+ position: relative;
229
+ width: 100%;
230
+ }
231
+
232
+ .custom-select-input {
233
+ display: flex;
234
+ align-items: center;
235
+ justify-content: space-between;
236
+ box-sizing: border-box;
237
+ width: 100%;
238
+ height: 30px;
239
+ padding: 0 5px;
240
+ font-size: 14px;
241
+ color: #606266;
242
+ background-color: #fff;
243
+ border: 1px solid #dcdfe6;
244
+ border-radius: 4px;
245
+ cursor: pointer;
246
+ transition: border-color 0.2s;
247
+
248
+ &:hover {
249
+ border-color: #c0c4cc;
250
+ }
251
+ }
252
+
253
+ .custom-select-value {
254
+ flex: 1;
255
+ overflow: hidden;
256
+ text-overflow: ellipsis;
257
+ white-space: nowrap;
258
+ }
259
+
260
+ .custom-select-arrow {
261
+ position: relative;
262
+ width: 0;
263
+ height: 0;
264
+ margin-left: 3px;
265
+ border-left: 5px solid transparent;
266
+ border-right: 5px solid transparent;
267
+ border-top: 6px solid #c0c4cc;
268
+ transition: transform 0.3s;
269
+
270
+ &.is-open {
271
+ transform: rotate(180deg);
272
+ }
273
+ }
274
+
275
+ .custom-select-dropdown {
276
+ position: absolute;
277
+ top: 100%;
278
+ left: 0;
279
+ z-index: 2000;
280
+ min-width: fit-content;
281
+ width: auto;
282
+ margin-top: 4px;
283
+ padding: 6px 0;
284
+ background-color: #fff;
285
+ border: 1px solid #e4e7ed;
286
+ border-radius: 4px;
287
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
288
+ max-height: 274px;
289
+ overflow-y: auto;
290
+
291
+ ul {
292
+ margin: 0;
293
+ padding: 0;
294
+ list-style: none;
295
+ }
296
+
297
+ li {
298
+ padding: 0 20px;
299
+ height: 34px;
300
+ line-height: 34px;
301
+ font-size: 14px;
302
+ color: #606266;
303
+ cursor: pointer;
304
+ white-space: nowrap;
305
+ overflow: hidden;
306
+ text-overflow: ellipsis;
307
+
308
+ &:hover {
309
+ background-color: #f5f7fa;
310
+ }
311
+
312
+ &.is-selected {
313
+ color: #409eff;
314
+ font-weight: 700;
315
+ background-color: #f5f7fa;
316
+ }
317
+ }
318
+ }
121
319
  </style>