xt-element-ui 2.1.21 → 2.1.61

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.
Files changed (75) hide show
  1. package/docs/components/base/xt-badge.md +0 -2
  2. package/docs/components/base/xt-bar.md +0 -27
  3. package/docs/components/base/xt-button.md +0 -2
  4. package/docs/components/base/xt-card-item.md +0 -2
  5. package/docs/components/base/xt-card.md +17 -19
  6. package/docs/components/base/xt-chart.md +5 -31
  7. package/docs/components/base/xt-config-provider.md +0 -2
  8. package/docs/components/base/xt-date-picker.md +185 -28
  9. package/docs/components/base/xt-flex-box.md +25 -25
  10. package/docs/components/base/xt-form-schema.md +356 -0
  11. package/docs/components/base/xt-grid-box.md +4 -6
  12. package/docs/components/base/xt-icon.md +0 -2
  13. package/docs/components/base/xt-input.md +204 -44
  14. package/docs/components/base/xt-line.md +0 -26
  15. package/docs/components/base/xt-list.md +456 -458
  16. package/docs/components/base/xt-map-provider.md +0 -2
  17. package/docs/components/base/xt-map.md +0 -2
  18. package/docs/components/base/xt-multi.md +0 -39
  19. package/docs/components/base/xt-page.md +17 -6
  20. package/docs/components/base/xt-pie.md +0 -25
  21. package/docs/components/base/xt-progress.md +0 -2
  22. package/docs/components/base/xt-scroll-arrow.md +0 -2
  23. package/docs/components/base/xt-select-tree.md +0 -2
  24. package/docs/components/base/xt-step-price.md +3 -4
  25. package/docs/components/base/xt-table.md +2 -2
  26. package/docs/components/base/xt-tabs.md +0 -2
  27. package/docs/components/base/xt-text.md +1 -2
  28. package/docs/components/base/xt-time.md +0 -2
  29. package/docs/components/base/xt-transfer-tree.md +270 -0
  30. package/docs/components/base/xt-upload.md +11 -8
  31. package/docs/components/utils/config.md +285 -0
  32. package/docs/components/utils/format.md +445 -0
  33. package/lib/index.common.js +96183 -115717
  34. package/lib/index.css +1 -1
  35. package/lib/index.umd.js +96183 -115717
  36. package/lib/index.umd.min.js +1 -34
  37. package/package.json +7 -4
  38. package/src/components/xt-badge/style/index.scss +0 -22
  39. package/src/components/xt-button/index.vue +2 -1
  40. package/src/components/xt-button/style/index.scss +2 -2
  41. package/src/components/xt-card/style/index.scss +2 -2
  42. package/src/components/xt-card-item/style/index.scss +5 -40
  43. package/src/components/xt-chart/XtBar.vue +0 -3
  44. package/src/components/xt-date-picker/component/Picker.vue +196 -0
  45. package/src/components/xt-date-picker/component/RangeDate.vue +136 -0
  46. package/src/components/xt-date-picker/index.vue +220 -80
  47. package/src/components/xt-flex-box/index.vue +1 -1
  48. package/src/components/xt-form-schema/index.js +8 -0
  49. package/src/components/xt-form-schema/index.vue +328 -0
  50. package/src/components/xt-grid-item/index.vue +2 -2
  51. package/src/components/xt-input/index.vue +224 -28
  52. package/src/components/xt-input/style/index.scss +10 -0
  53. package/src/components/xt-layout/ExFieldset.vue +4 -4
  54. package/src/components/xt-list/index.js +7 -7
  55. package/src/components/xt-list/index.vue +885 -885
  56. package/src/components/xt-page/index.vue +148 -75
  57. package/src/components/xt-progress/style/index.scss +0 -14
  58. package/src/components/xt-step-price/style/index.scss +0 -4
  59. package/src/components/xt-step-price-item/index.vue +1 -1
  60. package/src/components/xt-table/XtTableCell.vue +2 -2
  61. package/src/components/xt-table/index.vue +17 -10
  62. package/src/components/xt-tabs/style/index.scss +0 -40
  63. package/src/components/xt-text/index.vue +16 -4
  64. package/src/components/xt-text/style/index.scss +0 -15
  65. package/src/components/xt-transfer-tree/index.js +8 -0
  66. package/src/components/xt-transfer-tree/index.vue +494 -0
  67. package/src/components/xt-upload/index.vue +12 -6
  68. package/src/index.js +8 -2
  69. package/src/styles/theme/colors.scss +0 -44
  70. package/src/styles/theme/dark-variables.scss +0 -29
  71. package/src/styles/variables-export.scss +0 -72
  72. package/src/utils/index.js +278 -1
  73. package/src/components/xt-date-picker/SearchDate.vue +0 -45
  74. package/src/components/xt-date-picker/quarter.vue +0 -154
  75. package/src/components/xt-table/index copy.vue +0 -663
@@ -12,13 +12,13 @@ export default {
12
12
  span: {
13
13
  type: Number,
14
14
  default: 1,
15
- validator: (val) => val > 0
15
+ validator: (val) => val >= 1
16
16
  },
17
17
  // 跨行数
18
18
  rowSpan: {
19
19
  type: Number,
20
20
  default: 1,
21
- validator: (val) => val > 0
21
+ validator: (val) => val >= 1
22
22
  },
23
23
  // 起始列
24
24
  start: {
@@ -3,22 +3,35 @@
3
3
  class="xt-input"
4
4
  :class="[
5
5
  size ? 'xt-input--' + size : '',
6
- { 'is-disabled': disabled }
6
+ { 'is-disabled': disabled },
7
+ { 'is-error': hasError }
7
8
  ]"
8
9
  >
9
10
  <el-input
10
11
  :value="displayValue"
11
12
  :placeholder="placeholder"
12
- :type="isNumberType ? 'text' : type"
13
+ :type="inputType"
13
14
  :size="size"
14
15
  :disabled="disabled"
15
16
  :readonly="readonly"
16
17
  :style="inputStyle"
18
+ :maxlength="maxlength"
19
+ :show-word-limit="showWordLimit"
20
+ :prefix-icon="prefixIcon"
21
+ :suffix-icon="suffixIcon"
17
22
  @input="handleInput"
18
23
  @change="handleChange"
19
24
  @focus="handleFocus"
20
25
  @blur="handleBlur"
21
- />
26
+ @clear="handleClear"
27
+ >
28
+ <template v-if="$slots.prefix" #prefix>
29
+ <slot name="prefix"></slot>
30
+ </template>
31
+ <template v-if="$slots.suffix" #suffix>
32
+ <slot name="suffix"></slot>
33
+ </template>
34
+ </el-input>
22
35
  </div>
23
36
  </template>
24
37
 
@@ -33,7 +46,8 @@ export default {
33
46
  },
34
47
  type: {
35
48
  type: String,
36
- default: 'text'
49
+ default: 'text',
50
+ validator: (val) => ['text', 'number', 'integer', 'decimal', 'money', 'phone', 'email', 'idcard', 'password', 'textarea'].includes(val)
37
51
  },
38
52
  size: {
39
53
  type: String,
@@ -50,31 +64,87 @@ export default {
50
64
  color: {
51
65
  type: String,
52
66
  default: ''
67
+ },
68
+ precision: {
69
+ type: Number,
70
+ default: 2,
71
+ validator: (val) => val >= 0 && val <= 10
72
+ },
73
+ min: {
74
+ type: Number,
75
+ default: undefined
76
+ },
77
+ max: {
78
+ type: Number,
79
+ default: undefined
80
+ },
81
+ allowNegative: {
82
+ type: Boolean,
83
+ default: false
84
+ },
85
+ thousandSeparator: {
86
+ type: Boolean,
87
+ default: false
88
+ },
89
+ maxlength: {
90
+ type: Number,
91
+ default: undefined
92
+ },
93
+ showWordLimit: {
94
+ type: Boolean,
95
+ default: false
96
+ },
97
+ prefixIcon: {
98
+ type: String,
99
+ default: ''
100
+ },
101
+ suffixIcon: {
102
+ type: String,
103
+ default: ''
104
+ },
105
+ trim: {
106
+ type: Boolean,
107
+ default: false
53
108
  }
54
109
  },
55
110
  data() {
56
111
  return {
57
112
  currentStr: '',
58
- isFocused: false
113
+ isFocused: false,
114
+ hasError: false
59
115
  }
60
116
  },
61
117
  computed: {
118
+ inputType() {
119
+ if (this.type === 'textarea') {
120
+ return 'textarea'
121
+ }
122
+ if (this.type === 'password') {
123
+ return 'password'
124
+ }
125
+ if (this.isNumberType) {
126
+ return 'text'
127
+ }
128
+ return 'text'
129
+ },
62
130
  isNumberType() {
63
- return this.type === 'number'
131
+ return ['number', 'integer', 'decimal', 'money'].includes(this.type)
64
132
  },
65
133
  displayValue() {
66
134
  if (this.isNumberType) {
135
+ if (this.thousandSeparator && this.currentStr) {
136
+ return this.formatThousand(this.currentStr)
137
+ }
67
138
  return this.currentStr
68
139
  }
69
140
  return this.value
70
141
  },
71
142
  inputStyle() {
143
+ const style = {}
72
144
  if (this.color) {
73
- return {
74
- '--xt-input-focus-color': this.color
75
- }
145
+ style['--xt-input-focus-color'] = this.color
76
146
  }
77
- return {}
147
+ return style
78
148
  }
79
149
  },
80
150
  watch: {
@@ -82,34 +152,141 @@ export default {
82
152
  immediate: true,
83
153
  handler(val) {
84
154
  if (this.isNumberType && !this.isFocused) {
85
- this.currentStr = val === null || val === undefined || val === '' ? '' : String(val)
155
+ if (val === null || val === undefined || val === '') {
156
+ this.currentStr = ''
157
+ } else {
158
+ const strVal = String(val)
159
+ if (this.thousandSeparator) {
160
+ this.currentStr = this.parseThousand(strVal)
161
+ } else {
162
+ this.currentStr = strVal
163
+ }
164
+ }
86
165
  }
87
166
  }
88
167
  }
89
168
  },
90
169
  methods: {
91
170
  isValidNumber(str) {
92
- return /^[+-]?\d*\.?\d*$/.test(str)
171
+ if (!str) return true
172
+ const negativePattern = this.allowNegative ? '[-+]?' : ''
173
+ if (this.type === 'integer') {
174
+ return new RegExp(`^${negativePattern}\\d*$`).test(str)
175
+ }
176
+ if (this.type === 'decimal' || this.type === 'number') {
177
+ if (this.precision === 0) {
178
+ return new RegExp(`^${negativePattern}\\d*$`).test(str)
179
+ }
180
+ return new RegExp(`^${negativePattern}\\d*\\.?\\d{0,${this.precision}}$`).test(str)
181
+ }
182
+ if (this.type === 'money') {
183
+ return new RegExp(`^${negativePattern}\\d*\\.?\\d{0,${this.precision}}$`).test(str)
184
+ }
185
+ return true
186
+ },
187
+ isValidPhone(str) {
188
+ return /^1[3-9]\d{0,9}$/.test(str)
189
+ },
190
+ isValidEmail(str) {
191
+ if (!str) return true
192
+ return /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(str)
193
+ },
194
+ isValidIdCard(str) {
195
+ return /^[1-9]\d{0,17}$/.test(str)
196
+ },
197
+ formatThousand(str) {
198
+ if (!str) return ''
199
+ const parts = str.split('.')
200
+ parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',')
201
+ return parts.join('.')
202
+ },
203
+ parseThousand(str) {
204
+ return str.replace(/,/g, '')
205
+ },
206
+ parseToNumber(str) {
207
+ if (!str || str === '+' || str === '-' || str === '.' || str === '+.' || str === '-.' || str === '-.') {
208
+ return undefined
209
+ }
210
+ const num = parseFloat(str)
211
+ return isNaN(num) ? undefined : num
93
212
  },
94
213
  handleInput(val) {
214
+ let inputVal = val
215
+
216
+ if (this.thousandSeparator && this.isNumberType) {
217
+ inputVal = this.parseThousand(val)
218
+ }
219
+
220
+ if (this.type === 'phone') {
221
+ inputVal = val.replace(/[^\d]/g, '')
222
+ if (!this.isValidPhone(inputVal)) {
223
+ inputVal = inputVal.slice(0, -1)
224
+ }
225
+ this.$emit('input', inputVal)
226
+ return
227
+ }
228
+
229
+ if (this.type === 'idcard') {
230
+ inputVal = val.replace(/[^\dXx]/g, '')
231
+ if (!this.isValidIdCard(inputVal)) {
232
+ inputVal = inputVal.slice(0, -1)
233
+ }
234
+ this.$emit('input', inputVal.toUpperCase())
235
+ return
236
+ }
237
+
238
+ if (this.type === 'email') {
239
+ if (!this.isValidEmail(inputVal)) {
240
+ this.hasError = true
241
+ } else {
242
+ this.hasError = false
243
+ }
244
+ this.$emit('input', inputVal)
245
+ return
246
+ }
247
+
95
248
  if (this.isNumberType) {
96
- if (this.isValidNumber(val)) {
97
- this.currentStr = val
98
- const num = this.parseToNumber(val)
249
+ if (this.isValidNumber(inputVal)) {
250
+ this.currentStr = inputVal
251
+ const num = this.parseToNumber(inputVal)
99
252
  if (num !== undefined) {
100
- this.$emit('input', num)
253
+ let finalNum = num
254
+ if (this.min !== undefined && num < this.min) {
255
+ finalNum = this.min
256
+ this.currentStr = String(finalNum)
257
+ }
258
+ if (this.max !== undefined && num > this.max) {
259
+ finalNum = this.max
260
+ this.currentStr = String(finalNum)
261
+ }
262
+ this.$emit('input', finalNum)
263
+ this.hasError = false
264
+ } else {
265
+ this.$emit('input', undefined)
101
266
  }
102
267
  }
103
268
  } else {
104
- this.$emit('input', val)
269
+ if (this.trim) {
270
+ inputVal = inputVal.trim()
271
+ }
272
+ this.$emit('input', inputVal)
105
273
  }
106
274
  },
107
275
  handleChange(val) {
276
+ let changeVal = val
277
+
278
+ if (this.thousandSeparator && this.isNumberType) {
279
+ changeVal = this.parseThousand(val)
280
+ }
281
+
108
282
  if (this.isNumberType) {
109
- const num = this.parseToNumber(val)
283
+ const num = this.parseToNumber(changeVal)
110
284
  this.$emit('change', num)
111
285
  } else {
112
- this.$emit('change', val)
286
+ if (this.trim) {
287
+ changeVal = changeVal.trim()
288
+ }
289
+ this.$emit('change', changeVal)
113
290
  }
114
291
  },
115
292
  handleFocus(e) {
@@ -118,29 +295,48 @@ export default {
118
295
  },
119
296
  handleBlur(e) {
120
297
  this.isFocused = false
298
+
121
299
  if (this.isNumberType) {
122
300
  const num = this.parseToNumber(this.currentStr)
123
- this.$emit('blur', num, e)
124
301
  if (num !== undefined) {
125
- this.currentStr = String(num)
126
- this.$emit('input', num)
302
+ let finalNum = num
303
+ if (this.precision > 0) {
304
+ finalNum = Number(num.toFixed(this.precision))
305
+ }
306
+ this.currentStr = String(finalNum)
307
+ this.$emit('input', finalNum)
308
+ this.$emit('blur', finalNum, e)
309
+ this.hasError = false
127
310
  } else {
128
311
  if (this.currentStr !== '') {
129
312
  this.currentStr = ''
130
313
  this.$emit('input', undefined)
131
314
  }
315
+ this.$emit('blur', undefined, e)
316
+ this.hasError = false
132
317
  }
133
318
  } else {
319
+ if (this.type === 'email') {
320
+ if (!this.isValidEmail(this.value)) {
321
+ this.hasError = true
322
+ }
323
+ }
134
324
  this.$emit('blur', e)
135
325
  }
136
326
  },
137
- parseToNumber(str) {
138
- if (!str || str === '+' || str === '-' || str === '.' || str === '+.' || str === '-.' || str === '-.') {
139
- return undefined
327
+ handleClear() {
328
+ if (this.isNumberType) {
329
+ this.currentStr = ''
140
330
  }
141
- const num = parseFloat(str)
142
- return isNaN(num) ? undefined : num
331
+ this.hasError = false
332
+ this.$emit('input', this.isNumberType ? undefined : '')
333
+ this.$emit('clear')
334
+ },
335
+ reset() {
336
+ this.currentStr = ''
337
+ this.hasError = false
338
+ this.$emit('input', this.isNumberType ? undefined : '')
143
339
  }
144
340
  }
145
341
  }
146
- </script>
342
+ </script>
@@ -82,3 +82,13 @@
82
82
  .xt-input.is-disabled .el-input__inner::placeholder {
83
83
  color: var(--xt-input-disabled-text-color);
84
84
  }
85
+
86
+ // error 状态
87
+ .xt-input.is-error .el-input__inner {
88
+ border-color: var(--xt-color-danger, #f56c6c);
89
+ }
90
+
91
+ .xt-input.is-error .el-input__inner:focus {
92
+ border-color: var(--xt-color-danger, #f56c6c);
93
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--xt-color-danger, #f56c6c) 20%, transparent);
94
+ }
@@ -1,16 +1,16 @@
1
1
  <template>
2
2
  <fieldset class="exFieldset" :class="[border ? 'is-border' : 'part',type ? `is-${type}`: '',effect?`effect-${effect}`:'' ]">
3
3
  <legend class="fix-top legend">
4
- <BaseFlexBox class="title" content="between">
4
+ <XtFlexBox class="title" content="between">
5
5
  <slot name="legend">
6
6
  {{ legend }}
7
7
  </slot>
8
- </BaseFlexBox>
8
+ </XtFlexBox>
9
9
  </legend>
10
10
  <legend class="fix-top tool" v-if="$slots.tool">
11
- <BaseFlexBox content="end" gap="0 5">
11
+ <XtFlexBox content="end" gap="0 5">
12
12
  <slot name="tool"></slot>
13
- </BaseFlexBox>
13
+ </XtFlexBox>
14
14
  </legend>
15
15
  <div class="field" v-if="$slots.default">
16
16
  <slot />
@@ -1,8 +1,8 @@
1
- import XtList from './index.vue'
2
-
3
- XtList.install = function (Vue) {
4
- Vue.component(XtList.name, XtList)
5
- }
6
-
7
- export default XtList
1
+ import XtList from './index.vue'
2
+
3
+ XtList.install = function (Vue) {
4
+ Vue.component(XtList.name, XtList)
5
+ }
6
+
7
+ export default XtList
8
8
  export { XtList }