@leevan/jtui 2.0.52 → 2.0.54-beta.1

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.52",
3
+ "version": "2.0.54-beta.1",
4
4
  "scripts": {
5
5
  "serve": "vue-cli-service serve",
6
6
  "build": "vue-cli-service build",
@@ -0,0 +1,211 @@
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
+ row: {
122
+ type: Object,
123
+ default: null
124
+ },
125
+ prop: {
126
+ type: String,
127
+ default: ''
128
+ }
129
+ },
130
+ data() {
131
+ return {
132
+ currentValue: this.value
133
+ };
134
+ },
135
+ computed: {
136
+ inputType() {
137
+ return this.type || 'text';
138
+ }
139
+ },
140
+ watch: {
141
+ value(newVal) {
142
+ this.currentValue = newVal;
143
+ }
144
+ },
145
+ mounted() {
146
+ this.$nextTick(() => {
147
+ if (this.$refs.inputRef) {
148
+ const input = this.$refs.inputRef.$el ? this.$refs.inputRef.$el.querySelector('input') : this.$refs.inputRef;
149
+ if (input && input.focus) {
150
+ input.focus();
151
+ }
152
+ }
153
+ });
154
+ },
155
+ methods: {
156
+ handleBlur(e) {
157
+ this.doComplete();
158
+ },
159
+ handleChange(val) {
160
+ this.doComplete();
161
+ },
162
+ doComplete() {
163
+ if (this.row && this.prop) {
164
+ if (!(this.prop in this.row)) {
165
+ this.$set(this.row, this.prop, this.currentValue);
166
+ } else {
167
+ this.row[this.prop] = this.currentValue;
168
+ }
169
+ }
170
+ this.$emit('input', this.currentValue);
171
+ this.closeEdit();
172
+ },
173
+ closeEdit() {
174
+ try {
175
+ let vm = this.$parent;
176
+ let count = 0;
177
+ while (vm && count < 30) {
178
+ const componentName = vm.$options && vm.$options.name;
179
+ if (componentName === 'VxeTable' || componentName === 'VxeTable') {
180
+ if (vm.$xegrid) {
181
+ if (typeof vm.$xegrid._clearActived === 'function') {
182
+ vm.$xegrid._clearActived();
183
+ return;
184
+ }
185
+ }
186
+ if (typeof vm._clearActived === 'function') {
187
+ vm._clearActived();
188
+ return;
189
+ }
190
+ }
191
+ vm = vm.$parent;
192
+ count++;
193
+ }
194
+ } catch (e) {
195
+ console.error('closeEdit error', e);
196
+ }
197
+ }
198
+ }
199
+ };
200
+ </script>
201
+
202
+ <style lang="scss">
203
+ .edit-input-wrapper {
204
+ width: 100%;
205
+ ::v-deep .el-input,
206
+ ::v-deep .el-input-number,
207
+ ::v-deep .el-date-editor {
208
+ width: 100%;
209
+ }
210
+ }
211
+ </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,13 @@
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
+ :row="row"
65
+ :prop="subSubItem.prop"
66
+ />
60
67
  </template>
61
68
  </vxe-table-column>
62
69
  </vxe-colgroup>
@@ -78,8 +85,8 @@
78
85
  :formatter="formatEnum"
79
86
  :cell-render="cellRenderData(subItem.cellRender)"
80
87
  >
81
- <template v-slot:edit="{ row }" v-if="item && item.edit && item.edit.name == '$select'">
82
- <div class="custom-select-wrapper" ref="selectWrapper">
88
+ <template v-slot:edit="{ row }">
89
+ <div v-if="item && item.edit && item.edit.name == '$select'" class="custom-select-wrapper" ref="selectWrapper">
83
90
  <div
84
91
  class="custom-select-input"
85
92
  @click="toggleDropdown"
@@ -103,6 +110,13 @@
103
110
  </ul>
104
111
  </div>
105
112
  </div>
113
+ <EditInput
114
+ v-else-if="item && item.edit && item.edit.name == '$input'"
115
+ v-model="row[subItem.prop]"
116
+ :type="(item.edit.props && item.edit.props.type) || 'text'"
117
+ :row="row"
118
+ :prop="subItem.prop"
119
+ />
106
120
  </template>
107
121
  </vxe-table-column>
108
122
  </template>
@@ -125,8 +139,8 @@
125
139
  :formatter="formatEnum"
126
140
  :cell-render="cellRenderData(item.cellRender)"
127
141
  >
128
- <template v-slot:edit="{ row }" v-if="item && item.edit && item.edit.name == '$select'">
129
- <div class="custom-select-wrapper" ref="selectWrapper">
142
+ <template v-slot:edit="{ row }">
143
+ <div v-if="item && item.edit && item.edit.name == '$select'" class="custom-select-wrapper" ref="selectWrapper">
130
144
  <div
131
145
  class="custom-select-input"
132
146
  @click="toggleDropdown"
@@ -150,18 +164,31 @@
150
164
  </ul>
151
165
  </div>
152
166
  </div>
167
+ <EditInput
168
+ v-else-if="item && item.edit && item.edit.name == '$input'"
169
+ v-model="row[item.prop]"
170
+ :type="(item.edit.props && item.edit.props.type) || 'text'"
171
+ :row="row"
172
+ :prop="item.prop"
173
+ />
153
174
  </template>
154
175
  </vxe-table-column>
155
176
  </template>
156
177
 
157
178
 
158
179
  <script>
180
+ import EditInput from './edit-components/EditInput.vue';
181
+
159
182
  export default {
160
183
  name: "tableColumn",
184
+ components: {
185
+ EditInput
186
+ },
161
187
 
162
188
  data() {
163
189
  return {
164
- isOpen: false
190
+ isOpen: false,
191
+ vxeTableInstance: null
165
192
  };
166
193
  },
167
194
  mounted() {
@@ -171,6 +198,8 @@ export default {
171
198
  this.$nextTick(() => {
172
199
  this.isOpen = true;
173
200
  });
201
+ // 查找并保存vxe-table实例
202
+ this.findVxeTable();
174
203
  },
175
204
  beforeDestroy() {
176
205
  document.removeEventListener('click', this.handleClickOutside);
@@ -202,6 +231,34 @@ export default {
202
231
  },
203
232
 
204
233
  methods: {
234
+ findVxeTable() {
235
+ // 向上查找vxe-table实例
236
+ let parent = this.$parent;
237
+ let count = 0;
238
+ while (parent && count < 30) {
239
+ const componentName = parent.$options && parent.$options.name;
240
+ if (componentName === 'VxeTable' || componentName === 'VxeTable') {
241
+ if (parent.clearEdit && typeof parent.clearEdit === 'function') {
242
+ this.vxeTableInstance = parent;
243
+ return;
244
+ }
245
+ if (parent.$vxe && parent.$vxe.table) {
246
+ this.vxeTableInstance = parent.$vxe.table;
247
+ return;
248
+ }
249
+ if (parent.xetable) {
250
+ this.vxeTableInstance = parent.xetable;
251
+ return;
252
+ }
253
+ }
254
+ if (parent.clearEdit && typeof parent.clearEdit === 'function') {
255
+ this.vxeTableInstance = parent;
256
+ return;
257
+ }
258
+ parent = parent.$parent;
259
+ count++;
260
+ }
261
+ },
205
262
  getLabel(value) {
206
263
  if (!this.item || !this.item.edit || !this.item.edit.options) return value;
207
264
  const findItem = this.item.edit.options.find(op => op.value === value);
@@ -213,6 +270,37 @@ export default {
213
270
  selectOption(op, row) {
214
271
  row[this.item.prop] = op.value;
215
272
  this.isOpen = false;
273
+ this.closeEdit();
274
+ },
275
+ closeEdit() {
276
+ try {
277
+ let vm = this.$parent;
278
+ let count = 0;
279
+ while (vm && count < 30) {
280
+ const componentName = vm.$options && vm.$options.name;
281
+
282
+ if (componentName === 'VxeTable' || componentName === 'VxeTable') {
283
+ if (vm.$xegrid) {
284
+ if (typeof vm.$xegrid._clearActived === 'function') {
285
+ vm.$xegrid._clearActived();
286
+ return;
287
+ }
288
+ if (typeof vm.$xegrid.clearEdit === 'function') {
289
+ vm.$xegrid.clearEdit();
290
+ return;
291
+ }
292
+ }
293
+ if (typeof vm._clearActived === 'function') {
294
+ vm._clearActived();
295
+ return;
296
+ }
297
+ }
298
+ vm = vm.$parent;
299
+ count++;
300
+ }
301
+ } catch (e) {
302
+ console.error('closeEdit error', e);
303
+ }
216
304
  },
217
305
  handleClickOutside(e) {
218
306
  if (this.$refs.selectWrapper && !this.$refs.selectWrapper.contains(e.target)) {
@@ -316,4 +404,13 @@ export default {
316
404
  }
317
405
  }
318
406
  }
407
+
408
+ .edit-input-wrapper {
409
+ width: 100%;
410
+ ::v-deep .el-input,
411
+ ::v-deep .el-input-number,
412
+ ::v-deep .el-date-editor {
413
+ width: 100%;
414
+ }
415
+ }
319
416
  </style>