@leevan/jtui 2.0.51 → 2.0.53

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.51",
3
+ "version": "2.0.53",
4
4
  "scripts": {
5
5
  "serve": "vue-cli-service serve",
6
6
  "build": "vue-cli-service build",
@@ -0,0 +1,225 @@
1
+ <template>
2
+ <div class="edit-input-wrapper">
3
+ <el-input
4
+ v-if="inputType === 'text'"
5
+ v-model="currentValue"
6
+ type="text"
7
+ size="mini"
8
+ ref="inputRef"
9
+ @blur="handleBlur"
10
+ @change="handleChange"
11
+ @keyup.enter="handleBlur"
12
+ />
13
+ <el-input
14
+ v-else-if="inputType === 'password'"
15
+ v-model="currentValue"
16
+ type="password"
17
+ show-password
18
+ size="mini"
19
+ ref="inputRef"
20
+ @blur="handleBlur"
21
+ @change="handleChange"
22
+ @keyup.enter="handleBlur"
23
+ />
24
+ <el-input-number
25
+ v-else-if="inputType === 'number'"
26
+ v-model="currentValue"
27
+ :controls="true"
28
+ size="mini"
29
+ ref="inputRef"
30
+ @blur="handleBlur"
31
+ @change="handleChange"
32
+ />
33
+ <el-input-number
34
+ v-else-if="inputType === 'integer'"
35
+ v-model="currentValue"
36
+ :precision="0"
37
+ :step="1"
38
+ size="mini"
39
+ ref="inputRef"
40
+ @blur="handleBlur"
41
+ @change="handleChange"
42
+ />
43
+ <el-input-number
44
+ v-else-if="inputType === 'float'"
45
+ v-model="currentValue"
46
+ :precision="2"
47
+ :step="0.1"
48
+ size="mini"
49
+ ref="inputRef"
50
+ @blur="handleBlur"
51
+ @change="handleChange"
52
+ />
53
+ <el-date-picker
54
+ v-else-if="inputType === 'date'"
55
+ v-model="currentValue"
56
+ type="date"
57
+ value-format="yyyy-MM-dd"
58
+ size="mini"
59
+ ref="inputRef"
60
+ @change="handleChange"
61
+ />
62
+ <el-date-picker
63
+ v-else-if="inputType === 'datetime'"
64
+ v-model="currentValue"
65
+ type="datetime"
66
+ value-format="yyyy-MM-dd HH:mm:ss"
67
+ size="mini"
68
+ ref="inputRef"
69
+ @change="handleChange"
70
+ />
71
+ <el-date-picker
72
+ v-else-if="inputType === 'week'"
73
+ v-model="currentValue"
74
+ type="week"
75
+ format="yyyy 第 WW 周"
76
+ value-format="yyyy-Www"
77
+ size="mini"
78
+ ref="inputRef"
79
+ @change="handleChange"
80
+ />
81
+ <el-date-picker
82
+ v-else-if="inputType === 'month'"
83
+ v-model="currentValue"
84
+ type="month"
85
+ value-format="yyyy-MM"
86
+ size="mini"
87
+ ref="inputRef"
88
+ @change="handleChange"
89
+ />
90
+ <el-date-picker
91
+ v-else-if="inputType === 'year'"
92
+ v-model="currentValue"
93
+ type="year"
94
+ value-format="yyyy"
95
+ size="mini"
96
+ ref="inputRef"
97
+ @change="handleChange"
98
+ />
99
+ <el-input
100
+ v-else
101
+ v-model="currentValue"
102
+ type="text"
103
+ size="mini"
104
+ ref="inputRef"
105
+ @blur="handleBlur"
106
+ @change="handleChange"
107
+ @keyup.enter="handleBlur"
108
+ />
109
+ </div>
110
+ </template>
111
+
112
+ <script>
113
+ export default {
114
+ name: 'EditInput',
115
+ props: {
116
+ value: [String, Number],
117
+ type: {
118
+ type: String,
119
+ default: 'text'
120
+ }
121
+ },
122
+ data() {
123
+ return {
124
+ currentValue: this.value
125
+ };
126
+ },
127
+ computed: {
128
+ inputType() {
129
+ return this.type || 'text';
130
+ }
131
+ },
132
+ watch: {
133
+ value(newVal) {
134
+ this.currentValue = newVal;
135
+ }
136
+ },
137
+ mounted() {
138
+ this.$nextTick(() => {
139
+ if (this.$refs.inputRef) {
140
+ const input = this.$refs.inputRef.$el ? this.$refs.inputRef.$el.querySelector('input') : this.$refs.inputRef;
141
+ if (input && input.focus) {
142
+ input.focus();
143
+ }
144
+ }
145
+ });
146
+ },
147
+ methods: {
148
+ handleBlur(e) {
149
+ this.doComplete();
150
+ },
151
+ handleChange(val) {
152
+ this.doComplete();
153
+ },
154
+ doComplete() {
155
+ this.$emit('input', this.currentValue);
156
+ this.closeEdit();
157
+ },
158
+ closeEdit() {
159
+ try {
160
+ console.log('EditInput closeEdit, start finding VxeTable...');
161
+ let vm = this.$parent;
162
+ let count = 0;
163
+ while (vm && count < 30) {
164
+ const componentName = vm.$options && vm.$options.name;
165
+
166
+ if (componentName === 'VxeTable' || componentName === 'VxeTable') {
167
+ console.log('Found VxeTable component!');
168
+ console.log('vm.$xegrid:', vm.$xegrid);
169
+ if (vm.$xegrid) {
170
+ console.log('Methods on $xegrid:', Object.keys(vm.$xegrid));
171
+ if (typeof vm.$xegrid.clearEdit === 'function') {
172
+ vm.$xegrid.clearEdit();
173
+ return;
174
+ }
175
+ if (typeof vm.$xegrid._clearActived === 'function') {
176
+ vm.$xegrid._clearActived();
177
+ return;
178
+ }
179
+ if (typeof vm.$xegrid.closeEdit === 'function') {
180
+ vm.$xegrid.closeEdit();
181
+ return;
182
+ }
183
+ }
184
+ if (typeof vm._clearActived === 'function') {
185
+ vm._clearActived();
186
+ return;
187
+ }
188
+ if (typeof vm.$xegrid && typeof vm.$xegrid._clearActived === 'function') {
189
+ vm.$xegrid._clearActived();
190
+ return;
191
+ }
192
+ console.log('Trying all methods on VxeTable vm:', Object.keys(vm));
193
+ for (let key of Object.keys(vm)) {
194
+ if (typeof vm[key] === 'function' && (key.toLowerCase().includes('clear') || key.toLowerCase().includes('close') || key.toLowerCase().includes('edit'))) {
195
+ console.log('Found potential method:', key);
196
+ try {
197
+ vm[key]();
198
+ return;
199
+ } catch (e) {
200
+ console.log('Tried', key, 'but failed:', e);
201
+ }
202
+ }
203
+ }
204
+ }
205
+ vm = vm.$parent;
206
+ count++;
207
+ }
208
+ } catch (e) {
209
+ console.error('closeEdit error', e);
210
+ }
211
+ }
212
+ }
213
+ };
214
+ </script>
215
+
216
+ <style lang="scss">
217
+ .edit-input-wrapper {
218
+ width: 100%;
219
+ ::v-deep .el-input,
220
+ ::v-deep .el-input-number,
221
+ ::v-deep .el-date-editor {
222
+ width: 100%;
223
+ }
224
+ }
225
+ </style>
@@ -0,0 +1,178 @@
1
+ <template>
2
+ <div class="custom-select-wrapper" ref="selectWrapper">
3
+ <div
4
+ class="custom-select-input"
5
+ @click="toggleDropdown"
6
+ ref="inputRef"
7
+ >
8
+ <span class="custom-select-value">
9
+ {{ displayLabel }}
10
+ </span>
11
+ <i class="custom-select-arrow" :class="{'is-open': isOpen}"></i>
12
+ </div>
13
+ <div class="custom-select-dropdown" v-show="isOpen" ref="dropdownRef">
14
+ <ul>
15
+ <li
16
+ v-for="op in options"
17
+ :key="op.value"
18
+ :class="{'is-selected': value === op.value}"
19
+ @mousedown.prevent="selectOption(op)"
20
+ >
21
+ {{ op.label }}
22
+ </li>
23
+ </ul>
24
+ </div>
25
+ </div>
26
+ </template>
27
+
28
+ <script>
29
+ export default {
30
+ name: 'EditSelect',
31
+ props: {
32
+ value: [String, Number],
33
+ options: {
34
+ type: Array,
35
+ default: () => []
36
+ }
37
+ },
38
+ data() {
39
+ return {
40
+ isOpen: true
41
+ };
42
+ },
43
+ computed: {
44
+ displayLabel() {
45
+ const findItem = this.options.find(op => op.value === this.value);
46
+ return findItem ? findItem.label : (this.value || '请选择');
47
+ }
48
+ },
49
+ mounted() {
50
+ document.addEventListener('click', this.handleClickOutside);
51
+ },
52
+ beforeDestroy() {
53
+ document.removeEventListener('click', this.handleClickOutside);
54
+ },
55
+ methods: {
56
+ toggleDropdown() {
57
+ this.isOpen = !this.isOpen;
58
+ },
59
+ selectOption(op) {
60
+ this.$emit('input', op.value);
61
+ this.isOpen = false;
62
+ this.closeEdit();
63
+ },
64
+ handleClickOutside(e) {
65
+ if (this.$refs.selectWrapper && !this.$refs.selectWrapper.contains(e.target)) {
66
+ this.isOpen = false;
67
+ this.closeEdit();
68
+ }
69
+ },
70
+ closeEdit() {
71
+ // 向上查找vxe-table实例
72
+ let parent = this.$parent;
73
+ while (parent) {
74
+ if (parent.$vxe && parent.$vxe.table) {
75
+ parent.$vxe.table.clearEdit();
76
+ break;
77
+ }
78
+ parent = parent.$parent;
79
+ }
80
+ }
81
+ }
82
+ };
83
+ </script>
84
+
85
+ <style lang="scss">
86
+ .custom-select-wrapper {
87
+ position: relative;
88
+ width: 100%;
89
+ }
90
+
91
+ .custom-select-input {
92
+ display: flex;
93
+ align-items: center;
94
+ justify-content: space-between;
95
+ box-sizing: border-box;
96
+ width: 100%;
97
+ height: 30px;
98
+ padding: 0 5px;
99
+ font-size: 14px;
100
+ color: #606266;
101
+ background-color: #fff;
102
+ border: 1px solid #dcdfe6;
103
+ border-radius: 4px;
104
+ cursor: pointer;
105
+ transition: border-color 0.2s;
106
+
107
+ &:hover {
108
+ border-color: #c0c4cc;
109
+ }
110
+ }
111
+
112
+ .custom-select-value {
113
+ flex: 1;
114
+ overflow: hidden;
115
+ text-overflow: ellipsis;
116
+ white-space: nowrap;
117
+ }
118
+
119
+ .custom-select-arrow {
120
+ position: relative;
121
+ width: 0;
122
+ height: 0;
123
+ margin-left: 3px;
124
+ border-left: 5px solid transparent;
125
+ border-right: 5px solid transparent;
126
+ border-top: 6px solid #c0c4cc;
127
+ transition: transform 0.3s;
128
+
129
+ &.is-open {
130
+ transform: rotate(180deg);
131
+ }
132
+ }
133
+
134
+ .custom-select-dropdown {
135
+ position: absolute;
136
+ top: 100%;
137
+ left: 0;
138
+ z-index: 9999;
139
+ min-width: fit-content;
140
+ width: auto;
141
+ margin-top: 4px;
142
+ padding: 6px 0;
143
+ background-color: #fff;
144
+ border: 1px solid #e4e7ed;
145
+ border-radius: 4px;
146
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
147
+ max-height: 274px;
148
+ overflow-y: auto;
149
+
150
+ ul {
151
+ margin: 0;
152
+ padding: 0;
153
+ list-style: none;
154
+ }
155
+
156
+ li {
157
+ padding: 0 20px;
158
+ height: 34px;
159
+ line-height: 34px;
160
+ font-size: 14px;
161
+ color: #606266;
162
+ cursor: pointer;
163
+ white-space: nowrap;
164
+ overflow: hidden;
165
+ text-overflow: ellipsis;
166
+
167
+ &:hover {
168
+ background-color: #f5f7fa;
169
+ }
170
+
171
+ &.is-selected {
172
+ color: #409eff;
173
+ font-weight: 700;
174
+ background-color: #f5f7fa;
175
+ }
176
+ }
177
+ }
178
+ </style>
@@ -32,8 +32,8 @@
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">
35
+ <template v-slot:edit="{ row }">
36
+ <div v-if="item && item.edit && item.edit.name == '$select'" class="custom-select-wrapper" ref="selectWrapper">
37
37
  <div
38
38
  class="custom-select-input"
39
39
  @click="toggleDropdown"
@@ -57,6 +57,12 @@
57
57
  </ul>
58
58
  </div>
59
59
  </div>
60
+ <EditInput
61
+ v-else-if="item && item.edit && item.edit.name == '$input'"
62
+ v-model="row[subSubItem.prop]"
63
+ :type="(item.edit.props && item.edit.props.type) || 'text'"
64
+ :table-instance="vxeTableInstance"
65
+ />
60
66
  </template>
61
67
  </vxe-table-column>
62
68
  </vxe-colgroup>
@@ -78,8 +84,8 @@
78
84
  :formatter="formatEnum"
79
85
  :cell-render="cellRenderData(subItem.cellRender)"
80
86
  >
81
- <template v-slot:edit="{ row }" v-if="item && item.edit && item.edit.name == '$select'">
82
- <div class="custom-select-wrapper" ref="selectWrapper">
87
+ <template v-slot:edit="{ row }">
88
+ <div v-if="item && item.edit && item.edit.name == '$select'" class="custom-select-wrapper" ref="selectWrapper">
83
89
  <div
84
90
  class="custom-select-input"
85
91
  @click="toggleDropdown"
@@ -103,6 +109,12 @@
103
109
  </ul>
104
110
  </div>
105
111
  </div>
112
+ <EditInput
113
+ v-else-if="item && item.edit && item.edit.name == '$input'"
114
+ v-model="row[subItem.prop]"
115
+ :type="(item.edit.props && item.edit.props.type) || 'text'"
116
+ :table-instance="vxeTableInstance"
117
+ />
106
118
  </template>
107
119
  </vxe-table-column>
108
120
  </template>
@@ -125,8 +137,8 @@
125
137
  :formatter="formatEnum"
126
138
  :cell-render="cellRenderData(item.cellRender)"
127
139
  >
128
- <template v-slot:edit="{ row }" v-if="item && item.edit && item.edit.name == '$select'">
129
- <div class="custom-select-wrapper" ref="selectWrapper">
140
+ <template v-slot:edit="{ row }">
141
+ <div v-if="item && item.edit && item.edit.name == '$select'" class="custom-select-wrapper" ref="selectWrapper">
130
142
  <div
131
143
  class="custom-select-input"
132
144
  @click="toggleDropdown"
@@ -150,18 +162,30 @@
150
162
  </ul>
151
163
  </div>
152
164
  </div>
165
+ <EditInput
166
+ v-else-if="item && item.edit && item.edit.name == '$input'"
167
+ v-model="row[item.prop]"
168
+ :type="(item.edit.props && item.edit.props.type) || 'text'"
169
+ :table-instance="vxeTableInstance"
170
+ />
153
171
  </template>
154
172
  </vxe-table-column>
155
173
  </template>
156
174
 
157
175
 
158
176
  <script>
177
+ import EditInput from './edit-components/EditInput.vue';
178
+
159
179
  export default {
160
180
  name: "tableColumn",
181
+ components: {
182
+ EditInput
183
+ },
161
184
 
162
185
  data() {
163
186
  return {
164
- isOpen: false
187
+ isOpen: false,
188
+ vxeTableInstance: null
165
189
  };
166
190
  },
167
191
  mounted() {
@@ -171,6 +195,8 @@ export default {
171
195
  this.$nextTick(() => {
172
196
  this.isOpen = true;
173
197
  });
198
+ // 查找并保存vxe-table实例
199
+ this.findVxeTable();
174
200
  },
175
201
  beforeDestroy() {
176
202
  document.removeEventListener('click', this.handleClickOutside);
@@ -202,6 +228,34 @@ export default {
202
228
  },
203
229
 
204
230
  methods: {
231
+ findVxeTable() {
232
+ // 向上查找vxe-table实例
233
+ let parent = this.$parent;
234
+ let count = 0;
235
+ while (parent && count < 30) {
236
+ const componentName = parent.$options && parent.$options.name;
237
+ if (componentName === 'VxeTable' || componentName === 'VxeTable') {
238
+ if (parent.clearEdit && typeof parent.clearEdit === 'function') {
239
+ this.vxeTableInstance = parent;
240
+ return;
241
+ }
242
+ if (parent.$vxe && parent.$vxe.table) {
243
+ this.vxeTableInstance = parent.$vxe.table;
244
+ return;
245
+ }
246
+ if (parent.xetable) {
247
+ this.vxeTableInstance = parent.xetable;
248
+ return;
249
+ }
250
+ }
251
+ if (parent.clearEdit && typeof parent.clearEdit === 'function') {
252
+ this.vxeTableInstance = parent;
253
+ return;
254
+ }
255
+ parent = parent.$parent;
256
+ count++;
257
+ }
258
+ },
205
259
  getLabel(value) {
206
260
  if (!this.item || !this.item.edit || !this.item.edit.options) return value;
207
261
  const findItem = this.item.edit.options.find(op => op.value === value);
@@ -213,6 +267,37 @@ export default {
213
267
  selectOption(op, row) {
214
268
  row[this.item.prop] = op.value;
215
269
  this.isOpen = false;
270
+ this.closeEdit();
271
+ },
272
+ closeEdit() {
273
+ try {
274
+ let vm = this.$parent;
275
+ let count = 0;
276
+ while (vm && count < 30) {
277
+ const componentName = vm.$options && vm.$options.name;
278
+
279
+ if (componentName === 'VxeTable' || componentName === 'VxeTable') {
280
+ if (vm.$xegrid) {
281
+ if (typeof vm.$xegrid._clearActived === 'function') {
282
+ vm.$xegrid._clearActived();
283
+ return;
284
+ }
285
+ if (typeof vm.$xegrid.clearEdit === 'function') {
286
+ vm.$xegrid.clearEdit();
287
+ return;
288
+ }
289
+ }
290
+ if (typeof vm._clearActived === 'function') {
291
+ vm._clearActived();
292
+ return;
293
+ }
294
+ }
295
+ vm = vm.$parent;
296
+ count++;
297
+ }
298
+ } catch (e) {
299
+ console.error('closeEdit error', e);
300
+ }
216
301
  },
217
302
  handleClickOutside(e) {
218
303
  if (this.$refs.selectWrapper && !this.$refs.selectWrapper.contains(e.target)) {
@@ -316,4 +401,13 @@ export default {
316
401
  }
317
402
  }
318
403
  }
404
+
405
+ .edit-input-wrapper {
406
+ width: 100%;
407
+ ::v-deep .el-input,
408
+ ::v-deep .el-input-number,
409
+ ::v-deep .el-date-editor {
410
+ width: 100%;
411
+ }
412
+ }
319
413
  </style>
@@ -21,7 +21,7 @@
21
21
  </div>
22
22
  <!-- 普通表格 -->
23
23
  <vxe-table
24
- class="jt-table-class-only"
24
+ class="jt-table-class-only table-2-repair"
25
25
  height="auto"
26
26
  size="mini"
27
27
  show-overflow
@@ -203,7 +203,7 @@
203
203
  </vxe-table>
204
204
  <!-- 大数据 -->
205
205
  <vxe-table
206
- class="jt-table-class-only"
206
+ class="jt-table-class-only table-2-repair"
207
207
  height="auto"
208
208
  size="mini"
209
209
  show-overflow
@@ -373,7 +373,7 @@
373
373
  <!-- 分组表格 -->
374
374
  <vxe-table
375
375
  size="mini"
376
- class="jt-table-class-only"
376
+ class="jt-table-class-only table-2-repair"
377
377
  :id="id"
378
378
  :ref="id"
379
379
  empty-text=" "
@@ -514,7 +514,7 @@
514
514
  <!-- 树形表格 and 树 -->
515
515
  <vxe-table
516
516
  size="mini"
517
- class="jt-table-class-only"
517
+ class="jt-table-class-only table-2-repair"
518
518
  :id="id"
519
519
  :ref="id"
520
520
  :stripe="stripe"
@@ -1770,17 +1770,22 @@ export default {
1770
1770
  transform: translate(-50%,-50%);
1771
1771
  z-index:999;
1772
1772
  }
1773
- // .table-2-repair{
1774
- // .col--checkbox{
1775
- // .vxe-cell{
1776
- // overflow: visible !important;
1777
- // }
1778
- // .vxe-cell--checkbox{
1779
- // height:14px !important;
1780
- // }
1781
- // }
1782
- // .vxe-cell{
1783
- // display: inline-block !important;
1784
- // }
1785
- // }
1773
+ .table-2-repair{
1774
+ .col--checkbox{
1775
+ .vxe-cell{
1776
+ overflow: visible !important;
1777
+ }
1778
+ .vxe-cell--checkbox{
1779
+ height:14px !important;
1780
+ }
1781
+ }
1782
+ .col--edit{
1783
+ .vxe-cell{
1784
+ overflow: visible !important;
1785
+ }
1786
+ }
1787
+ .vxe-cell{
1788
+ display: inline-block !important;
1789
+ }
1790
+ }
1786
1791
  </style>
package/public/index.html CHANGED
@@ -6,6 +6,8 @@
6
6
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
7
7
  <link rel="icon" href="<%= BASE_URL %>favicon.ico">
8
8
  <title><%= htmlWebpackPlugin.options.title %></title>
9
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vxe-pc-ui@4.2.19/lib/style.css">
10
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vxe-table@4.7.87/lib/style.css">
9
11
  </head>
10
12
  <body>
11
13
  <noscript>