xt-element-ui 1.3.3 → 1.3.4

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 (111) hide show
  1. package/CHANGELOG.md +72 -72
  2. package/LICENSE +21 -21
  3. package/README.md +240 -240
  4. package/docs/README.md +100 -100
  5. package/docs/components/base/xt-button.md +114 -114
  6. package/docs/components/base/xt-card-item.md +104 -104
  7. package/docs/components/base/xt-card.md +108 -108
  8. package/docs/components/base/xt-config-provider.md +199 -199
  9. package/docs/components/base/xt-flex-box.md +115 -115
  10. package/docs/components/base/xt-grid-box.md +302 -302
  11. package/docs/components/base/xt-input.md +150 -150
  12. package/docs/components/base/xt-map-provider.md +23 -23
  13. package/docs/components/base/xt-map.md +331 -331
  14. package/docs/components/base/xt-step-price.md +165 -165
  15. package/docs/components/base/xt-text.md +212 -212
  16. package/docs/components/base/xt-time.md +165 -165
  17. package/docs/components/extend/ex-bar.md +67 -67
  18. package/docs/components/extend/ex-button.md +62 -62
  19. package/docs/components/extend/ex-card.md +86 -86
  20. package/docs/components/extend/ex-chart.md +463 -463
  21. package/docs/components/extend/ex-icon.md +189 -189
  22. package/docs/components/extend/ex-line.md +70 -70
  23. package/docs/components/extend/ex-multi.md +155 -155
  24. package/docs/components/extend/ex-pie.md +69 -69
  25. package/docs/components/extend/ex-select-tree.md +210 -210
  26. package/docs/components/extend/ex-table.md +590 -590
  27. package/docs/components/extend/ex-upload.md +134 -134
  28. package/docs/components/utils/size.md +147 -147
  29. package/docs/components/utils/theme.md +182 -182
  30. package/lib/index.common.js +4112 -4122
  31. package/lib/index.umd.js +4072 -4081
  32. package/lib/index.umd.min.js +3 -3
  33. package/package.json +80 -81
  34. package/src/components/ex-button/index.js +7 -7
  35. package/src/components/ex-button/index.vue +66 -66
  36. package/src/components/ex-button/style/index.scss +67 -67
  37. package/src/components/ex-card/index.js +7 -7
  38. package/src/components/ex-card/index.vue +68 -68
  39. package/src/components/ex-card/style/index.scss +73 -73
  40. package/src/components/ex-chart/index.js +7 -7
  41. package/src/components/ex-chart/index.vue +136 -136
  42. package/src/components/ex-date-picker/index.js +7 -7
  43. package/src/components/ex-icon/index.js +7 -7
  44. package/src/components/ex-icon/index.vue +168 -168
  45. package/src/components/ex-icon/style/index.scss +7 -7
  46. package/src/components/ex-page/index.js +7 -7
  47. package/src/components/ex-select-tree/index.js +7 -7
  48. package/src/components/ex-table/ExTableCell.vue +22 -22
  49. package/src/components/ex-table/index.js +7 -7
  50. package/src/components/ex-table/virtualScrollData.js +35 -35
  51. package/src/components/ex-upload/index.js +7 -7
  52. package/src/components/index.scss +39 -39
  53. package/src/components/xt-button/index.js +7 -7
  54. package/src/components/xt-button/index.vue +97 -97
  55. package/src/components/xt-card/index.js +7 -7
  56. package/src/components/xt-card/style/index.scss +48 -48
  57. package/src/components/xt-card-item/index.js +7 -7
  58. package/src/components/xt-card-item/style/index copy.scss +71 -71
  59. package/src/components/xt-card-item/style/index.scss +82 -82
  60. package/src/components/xt-config-provider/index.js +7 -7
  61. package/src/components/xt-config-provider/index.vue +362 -362
  62. package/src/components/xt-config-provider/style/index.scss +11 -11
  63. package/src/components/xt-flex-box/index.js +7 -7
  64. package/src/components/xt-flex-box/style/index.scss +81 -81
  65. package/src/components/xt-grid-box/index.js +7 -7
  66. package/src/components/xt-grid-box/style/index.scss +92 -92
  67. package/src/components/xt-grid-item/index.js +7 -7
  68. package/src/components/xt-grid-item/index.vue +106 -106
  69. package/src/components/xt-input/index.js +7 -7
  70. package/src/components/xt-input/index.vue +66 -66
  71. package/src/components/xt-input/style/index.scss +84 -84
  72. package/src/components/xt-map/adapters/amap.js +235 -235
  73. package/src/components/xt-map/adapters/baidu.js +254 -254
  74. package/src/components/xt-map/adapters/base.js +267 -267
  75. package/src/components/xt-map/adapters/index.js +29 -29
  76. package/src/components/xt-map/adapters/tianditu.js +242 -242
  77. package/src/components/xt-map/config/xt-map-config.js +197 -197
  78. package/src/components/xt-map/index.js +8 -8
  79. package/src/components/xt-map/index.vue +351 -351
  80. package/src/components/xt-map/loaders/script-loader.js +114 -114
  81. package/src/components/xt-map/provider.vue +200 -200
  82. package/src/components/xt-map/style/index.scss +77 -77
  83. package/src/components/xt-map-provider/index.js +8 -8
  84. package/src/components/xt-step-price/index.js +10 -10
  85. package/src/components/xt-step-price/index.vue +272 -272
  86. package/src/components/xt-step-price/style/index.scss +123 -123
  87. package/src/components/xt-step-price-item/index.js +7 -7
  88. package/src/components/xt-step-price-item/index.vue +187 -187
  89. package/src/components/xt-text/index.js +7 -7
  90. package/src/components/xt-text/index.vue +1 -1
  91. package/src/components/xt-text/style/index.scss +92 -92
  92. package/src/components/xt-time/index.js +7 -7
  93. package/src/components/xt-time/index.vue +313 -313
  94. package/src/components/xt-time/style/index.scss +23 -23
  95. package/src/config/element-registry.js +135 -135
  96. package/src/index.js +162 -178
  97. package/src/styles/css-variables.scss +257 -257
  98. package/src/styles/theme/background.scss +5 -5
  99. package/src/styles/theme/border-radius.scss +3 -3
  100. package/src/styles/theme/borders.scss +3 -3
  101. package/src/styles/theme/colors.scss +101 -101
  102. package/src/styles/theme/component-variables.scss +69 -69
  103. package/src/styles/theme/dark-variables.scss +28 -28
  104. package/src/styles/theme/font.scss +12 -12
  105. package/src/styles/theme/index.scss +11 -11
  106. package/src/styles/theme/shadows.scss +2 -2
  107. package/src/styles/theme/spacing.scss +4 -4
  108. package/src/styles/theme/transitions.scss +2 -2
  109. package/src/styles/theme/typography.scss +4 -4
  110. package/src/styles/variables-export.scss +85 -85
  111. package/src/utils/index.js +191 -202
@@ -1,313 +1,313 @@
1
- <template>
2
- <span
3
- class="xt-time"
4
- :class="[
5
- typeColor ? 'xt-time--' + typeColor : '',
6
- 'xt-time--' + size,
7
- { 'xt-time--bold': bold }
8
- ]"
9
- :style="customStyle"
10
- @click="handleClick"
11
- >
12
- <slot name="prefix">{{ prefix }}</slot>
13
-
14
- <slot>
15
- <template v-if="mode === 'text'">
16
- <template v-if="displayText !== undefined">{{ displayText }}</template>
17
- <template v-else-if="!hideEmpty">{{ emptyText }}</template>
18
- </template>
19
-
20
- <template v-else-if="mode === 'now'">
21
- {{ nowText }}
22
- </template>
23
-
24
- <template v-else-if="mode === 'countdown'">
25
- <template v-if="isCountdownFinished">
26
- <slot name="finished">{{ finishedText }}</slot>
27
- </template>
28
- <template v-else>
29
- {{ countdownText }}
30
- </template>
31
- </template>
32
- </slot>
33
-
34
- <slot name="suffix">{{ suffix }}</slot>
35
- </span>
36
- </template>
37
-
38
- <script>
39
- const DEFAULT_FORMAT = 'YYYY-MM-DD HH:mm:ss'
40
-
41
- function pad(n) {
42
- const s = String(n)
43
- return s.length < 2 ? '0' + s : s
44
- }
45
-
46
- /**
47
- * 根据字符串/数字/Date 解析为 Date 对象
48
- * 兼容:时间戳(ms/s)、Date、"2024-01-01"、"2024/01/01 12:00:00"、ISO 字符串
49
- */
50
- function parseDate(value) {
51
- if (value === null || value === undefined || value === '') return null
52
- if (value instanceof Date) return isNaN(value.getTime()) ? null : value
53
-
54
- // 数字时间戳
55
- if (typeof value === 'number') {
56
- // 10 位秒级时间戳补 000
57
- const t = value < 1e12 ? value * 1000 : value
58
- const d = new Date(t)
59
- return isNaN(d.getTime()) ? null : d
60
- }
61
-
62
- if (typeof value === 'string') {
63
- // 纯数字字符串
64
- if (/^\d+$/.test(value)) {
65
- const n = Number(value)
66
- const t = n < 1e12 ? n * 1000 : n
67
- const d = new Date(t)
68
- return isNaN(d.getTime()) ? null : d
69
- }
70
- // 将 "-" 统一为 "/",避免 Safari 下 "YYYY-MM-DD" 解析失败
71
- const normalized = value.replace(/-/g, '/')
72
- const d = new Date(normalized)
73
- return isNaN(d.getTime()) ? null : d
74
- }
75
-
76
- return null
77
- }
78
-
79
- /**
80
- * 简易 formatDateTime 实现(不依赖外部库)
81
- * 支持占位符:YYYY MM DD HH mm ss SSS
82
- */
83
- function formatDateTime(date, fmt) {
84
- if (!date) return ''
85
- const f = fmt || DEFAULT_FORMAT
86
- const map = {
87
- YYYY: date.getFullYear(),
88
- MM: pad(date.getMonth() + 1),
89
- DD: pad(date.getDate()),
90
- HH: pad(date.getHours()),
91
- mm: pad(date.getMinutes()),
92
- ss: pad(date.getSeconds()),
93
- SSS: String(date.getMilliseconds()).padStart(3, '0')
94
- }
95
- return f.replace(/YYYY|MM|DD|HH|mm|ss|SSS/g, (k) => map[k])
96
- }
97
-
98
- export default {
99
- name: 'XtTime',
100
-
101
- props: {
102
- // 显示模式:now(当前时间实时刷新)/ countdown(倒计时)/ text(格式化日期文本)
103
- type: {
104
- type: String,
105
- default: 'now',
106
- validator: (val) => ['now', 'countdown', 'text'].includes(val)
107
- },
108
-
109
- // ===== 通用 =====
110
- size: {
111
- type: String,
112
- default: 'base',
113
- validator: (val) =>
114
- ['extra-large', 'large', 'medium', 'base', 'small', 'extra-small'].includes(val)
115
- },
116
- typeColor: {
117
- type: String,
118
- default: '',
119
- validator: (val) => ['', 'primary', 'success', 'warning', 'danger'].includes(val)
120
- },
121
- bold: {
122
- type: Boolean,
123
- default: false
124
- },
125
- format: {
126
- type: String,
127
- default: DEFAULT_FORMAT
128
- },
129
- prefix: {
130
- type: String,
131
- default: ''
132
- },
133
- suffix: {
134
- type: String,
135
- default: ''
136
- },
137
- emptyText: {
138
- type: String,
139
- default: '-'
140
- },
141
- hideEmpty: {
142
- type: Boolean,
143
- default: false
144
- },
145
- interval: {
146
- type: Number,
147
- default: 1000,
148
- validator: (val) => val >= 100
149
- },
150
-
151
- // ===== text 模式 =====
152
- // 兼容 v-model 用法,也可直接传 value / :value
153
- value: {
154
- type: [String, Number, Date],
155
- default: ''
156
- },
157
-
158
- // ===== countdown 模式 =====
159
- targetTime: {
160
- type: [String, Number, Date],
161
- default: ''
162
- },
163
- // 倒计时显示格式:
164
- // DHMS -> 3天 12时 08分 30秒
165
- // HMS -> 12时 08分 30秒(天数自动折算到小时)
166
- // MS -> 08分 30秒(全部折算到分钟)
167
- // SEC -> 3200秒
168
- countdownFormat: {
169
- type: String,
170
- default: 'DHMS',
171
- validator: (val) => ['DHMS', 'HMS', 'MS', 'SEC'].includes(val)
172
- },
173
- finishedText: {
174
- type: String,
175
- default: '已结束'
176
- }
177
- },
178
-
179
- data() {
180
- return {
181
- tick: 0
182
- }
183
- },
184
-
185
- computed: {
186
- mode() {
187
- return this.type
188
- },
189
-
190
- parsedValue() {
191
- return parseDate(this.value)
192
- },
193
-
194
- parsedTarget() {
195
- return parseDate(this.targetTime)
196
- },
197
-
198
- displayText() {
199
- if (!this.parsedValue) return undefined
200
- return formatDateTime(this.parsedValue, this.format)
201
- },
202
-
203
- nowText() {
204
- // 通过 tick 触发刷新
205
- // eslint-disable-next-line no-unused-vars
206
- const _ = this.tick
207
- return formatDateTime(new Date(), this.format)
208
- },
209
-
210
- // 剩余毫秒数(countdown 模式)
211
- remainingMs() {
212
- if (this.mode !== 'countdown') return 0
213
- // eslint-disable-next-line no-unused-vars
214
- const _ = this.tick
215
- if (!this.parsedTarget) return 0
216
- const diff = this.parsedTarget.getTime() - Date.now()
217
- return diff > 0 ? diff : 0
218
- },
219
-
220
- isCountdownFinished() {
221
- return this.mode === 'countdown' && this.parsedTarget && this.remainingMs <= 0
222
- },
223
-
224
- countdownText() {
225
- if (!this.parsedTarget) return this.emptyText
226
- const total = Math.floor(this.remainingMs / 1000)
227
- if (total <= 0) return this.finishedText
228
-
229
- switch (this.countdownFormat) {
230
- case 'SEC':
231
- return `${total}秒`
232
- case 'MS': {
233
- const m = Math.floor(total / 60)
234
- const s = total % 60
235
- return `${pad(m)}分${pad(s)}秒`
236
- }
237
- case 'HMS': {
238
- const h = Math.floor(total / 3600)
239
- const m = Math.floor((total % 3600) / 60)
240
- const s = total % 60
241
- return `${pad(h)}时${pad(m)}分${pad(s)}秒`
242
- }
243
- case 'DHMS':
244
- default: {
245
- const d = Math.floor(total / 86400)
246
- const h = Math.floor((total % 86400) / 3600)
247
- const m = Math.floor((total % 3600) / 60)
248
- const s = total % 60
249
- return `${d}天${pad(h)}时${pad(m)}分${pad(s)}秒`
250
- }
251
- }
252
- },
253
-
254
- customStyle() {
255
- return {}
256
- }
257
- },
258
-
259
- watch: {
260
- type() {
261
- this.restartTimer()
262
- },
263
- interval() {
264
- this.restartTimer()
265
- }
266
- },
267
-
268
- mounted() {
269
- this.restartTimer()
270
- },
271
-
272
- beforeDestroy() {
273
- this.clearTimer()
274
- },
275
-
276
- activated() {
277
- this.restartTimer()
278
- },
279
-
280
- deactivated() {
281
- this.clearTimer()
282
- },
283
-
284
- methods: {
285
- restartTimer() {
286
- this.clearTimer()
287
- if (this.mode === 'now' || this.mode === 'countdown') {
288
- // 立即刷新一次,避免首次渲染时 tick=0 导致的差异
289
- this.tick++
290
- this._timer = setInterval(() => {
291
- this.tick++
292
- // 倒计时结束触发 finish 事件
293
- if (this.mode === 'countdown' && this.parsedTarget && this.remainingMs <= 0) {
294
- this.clearTimer()
295
- this.$emit('finish')
296
- }
297
- }, this.interval)
298
- }
299
- },
300
-
301
- clearTimer() {
302
- if (this._timer) {
303
- clearInterval(this._timer)
304
- this._timer = null
305
- }
306
- },
307
-
308
- handleClick(e) {
309
- this.$emit('click', e)
310
- }
311
- }
312
- }
313
- </script>
1
+ <template>
2
+ <span
3
+ class="xt-time"
4
+ :class="[
5
+ typeColor ? 'xt-time--' + typeColor : '',
6
+ 'xt-time--' + size,
7
+ { 'xt-time--bold': bold }
8
+ ]"
9
+ :style="customStyle"
10
+ @click="handleClick"
11
+ >
12
+ <slot name="prefix">{{ prefix }}</slot>
13
+
14
+ <slot>
15
+ <template v-if="mode === 'text'">
16
+ <template v-if="displayText !== undefined">{{ displayText }}</template>
17
+ <template v-else-if="!hideEmpty">{{ emptyText }}</template>
18
+ </template>
19
+
20
+ <template v-else-if="mode === 'now'">
21
+ {{ nowText }}
22
+ </template>
23
+
24
+ <template v-else-if="mode === 'countdown'">
25
+ <template v-if="isCountdownFinished">
26
+ <slot name="finished">{{ finishedText }}</slot>
27
+ </template>
28
+ <template v-else>
29
+ {{ countdownText }}
30
+ </template>
31
+ </template>
32
+ </slot>
33
+
34
+ <slot name="suffix">{{ suffix }}</slot>
35
+ </span>
36
+ </template>
37
+
38
+ <script>
39
+ const DEFAULT_FORMAT = 'YYYY-MM-DD HH:mm:ss'
40
+
41
+ function pad(n) {
42
+ const s = String(n)
43
+ return s.length < 2 ? '0' + s : s
44
+ }
45
+
46
+ /**
47
+ * 根据字符串/数字/Date 解析为 Date 对象
48
+ * 兼容:时间戳(ms/s)、Date、"2024-01-01"、"2024/01/01 12:00:00"、ISO 字符串
49
+ */
50
+ function parseDate(value) {
51
+ if (value === null || value === undefined || value === '') return null
52
+ if (value instanceof Date) return isNaN(value.getTime()) ? null : value
53
+
54
+ // 数字时间戳
55
+ if (typeof value === 'number') {
56
+ // 10 位秒级时间戳补 000
57
+ const t = value < 1e12 ? value * 1000 : value
58
+ const d = new Date(t)
59
+ return isNaN(d.getTime()) ? null : d
60
+ }
61
+
62
+ if (typeof value === 'string') {
63
+ // 纯数字字符串
64
+ if (/^\d+$/.test(value)) {
65
+ const n = Number(value)
66
+ const t = n < 1e12 ? n * 1000 : n
67
+ const d = new Date(t)
68
+ return isNaN(d.getTime()) ? null : d
69
+ }
70
+ // 将 "-" 统一为 "/",避免 Safari 下 "YYYY-MM-DD" 解析失败
71
+ const normalized = value.replace(/-/g, '/')
72
+ const d = new Date(normalized)
73
+ return isNaN(d.getTime()) ? null : d
74
+ }
75
+
76
+ return null
77
+ }
78
+
79
+ /**
80
+ * 简易 formatDateTime 实现(不依赖外部库)
81
+ * 支持占位符:YYYY MM DD HH mm ss SSS
82
+ */
83
+ function formatDateTime(date, fmt) {
84
+ if (!date) return ''
85
+ const f = fmt || DEFAULT_FORMAT
86
+ const map = {
87
+ YYYY: date.getFullYear(),
88
+ MM: pad(date.getMonth() + 1),
89
+ DD: pad(date.getDate()),
90
+ HH: pad(date.getHours()),
91
+ mm: pad(date.getMinutes()),
92
+ ss: pad(date.getSeconds()),
93
+ SSS: String(date.getMilliseconds()).padStart(3, '0')
94
+ }
95
+ return f.replace(/YYYY|MM|DD|HH|mm|ss|SSS/g, (k) => map[k])
96
+ }
97
+
98
+ export default {
99
+ name: 'XtTime',
100
+
101
+ props: {
102
+ // 显示模式:now(当前时间实时刷新)/ countdown(倒计时)/ text(格式化日期文本)
103
+ type: {
104
+ type: String,
105
+ default: 'now',
106
+ validator: (val) => ['now', 'countdown', 'text'].includes(val)
107
+ },
108
+
109
+ // ===== 通用 =====
110
+ size: {
111
+ type: String,
112
+ default: 'base',
113
+ validator: (val) =>
114
+ ['extra-large', 'large', 'medium', 'base', 'small', 'extra-small'].includes(val)
115
+ },
116
+ typeColor: {
117
+ type: String,
118
+ default: '',
119
+ validator: (val) => ['', 'primary', 'success', 'warning', 'danger'].includes(val)
120
+ },
121
+ bold: {
122
+ type: Boolean,
123
+ default: false
124
+ },
125
+ format: {
126
+ type: String,
127
+ default: DEFAULT_FORMAT
128
+ },
129
+ prefix: {
130
+ type: String,
131
+ default: ''
132
+ },
133
+ suffix: {
134
+ type: String,
135
+ default: ''
136
+ },
137
+ emptyText: {
138
+ type: String,
139
+ default: '-'
140
+ },
141
+ hideEmpty: {
142
+ type: Boolean,
143
+ default: false
144
+ },
145
+ interval: {
146
+ type: Number,
147
+ default: 1000,
148
+ validator: (val) => val >= 100
149
+ },
150
+
151
+ // ===== text 模式 =====
152
+ // 兼容 v-model 用法,也可直接传 value / :value
153
+ value: {
154
+ type: [String, Number, Date],
155
+ default: ''
156
+ },
157
+
158
+ // ===== countdown 模式 =====
159
+ targetTime: {
160
+ type: [String, Number, Date],
161
+ default: ''
162
+ },
163
+ // 倒计时显示格式:
164
+ // DHMS -> 3天 12时 08分 30秒
165
+ // HMS -> 12时 08分 30秒(天数自动折算到小时)
166
+ // MS -> 08分 30秒(全部折算到分钟)
167
+ // SEC -> 3200秒
168
+ countdownFormat: {
169
+ type: String,
170
+ default: 'DHMS',
171
+ validator: (val) => ['DHMS', 'HMS', 'MS', 'SEC'].includes(val)
172
+ },
173
+ finishedText: {
174
+ type: String,
175
+ default: '已结束'
176
+ }
177
+ },
178
+
179
+ data() {
180
+ return {
181
+ tick: 0
182
+ }
183
+ },
184
+
185
+ computed: {
186
+ mode() {
187
+ return this.type
188
+ },
189
+
190
+ parsedValue() {
191
+ return parseDate(this.value)
192
+ },
193
+
194
+ parsedTarget() {
195
+ return parseDate(this.targetTime)
196
+ },
197
+
198
+ displayText() {
199
+ if (!this.parsedValue) return undefined
200
+ return formatDateTime(this.parsedValue, this.format)
201
+ },
202
+
203
+ nowText() {
204
+ // 通过 tick 触发刷新
205
+ // eslint-disable-next-line no-unused-vars
206
+ const _ = this.tick
207
+ return formatDateTime(new Date(), this.format)
208
+ },
209
+
210
+ // 剩余毫秒数(countdown 模式)
211
+ remainingMs() {
212
+ if (this.mode !== 'countdown') return 0
213
+ // eslint-disable-next-line no-unused-vars
214
+ const _ = this.tick
215
+ if (!this.parsedTarget) return 0
216
+ const diff = this.parsedTarget.getTime() - Date.now()
217
+ return diff > 0 ? diff : 0
218
+ },
219
+
220
+ isCountdownFinished() {
221
+ return this.mode === 'countdown' && this.parsedTarget && this.remainingMs <= 0
222
+ },
223
+
224
+ countdownText() {
225
+ if (!this.parsedTarget) return this.emptyText
226
+ const total = Math.floor(this.remainingMs / 1000)
227
+ if (total <= 0) return this.finishedText
228
+
229
+ switch (this.countdownFormat) {
230
+ case 'SEC':
231
+ return `${total}秒`
232
+ case 'MS': {
233
+ const m = Math.floor(total / 60)
234
+ const s = total % 60
235
+ return `${pad(m)}分${pad(s)}秒`
236
+ }
237
+ case 'HMS': {
238
+ const h = Math.floor(total / 3600)
239
+ const m = Math.floor((total % 3600) / 60)
240
+ const s = total % 60
241
+ return `${pad(h)}时${pad(m)}分${pad(s)}秒`
242
+ }
243
+ case 'DHMS':
244
+ default: {
245
+ const d = Math.floor(total / 86400)
246
+ const h = Math.floor((total % 86400) / 3600)
247
+ const m = Math.floor((total % 3600) / 60)
248
+ const s = total % 60
249
+ return `${d}天${pad(h)}时${pad(m)}分${pad(s)}秒`
250
+ }
251
+ }
252
+ },
253
+
254
+ customStyle() {
255
+ return {}
256
+ }
257
+ },
258
+
259
+ watch: {
260
+ type() {
261
+ this.restartTimer()
262
+ },
263
+ interval() {
264
+ this.restartTimer()
265
+ }
266
+ },
267
+
268
+ mounted() {
269
+ this.restartTimer()
270
+ },
271
+
272
+ beforeDestroy() {
273
+ this.clearTimer()
274
+ },
275
+
276
+ activated() {
277
+ this.restartTimer()
278
+ },
279
+
280
+ deactivated() {
281
+ this.clearTimer()
282
+ },
283
+
284
+ methods: {
285
+ restartTimer() {
286
+ this.clearTimer()
287
+ if (this.mode === 'now' || this.mode === 'countdown') {
288
+ // 立即刷新一次,避免首次渲染时 tick=0 导致的差异
289
+ this.tick++
290
+ this._timer = setInterval(() => {
291
+ this.tick++
292
+ // 倒计时结束触发 finish 事件
293
+ if (this.mode === 'countdown' && this.parsedTarget && this.remainingMs <= 0) {
294
+ this.clearTimer()
295
+ this.$emit('finish')
296
+ }
297
+ }, this.interval)
298
+ }
299
+ },
300
+
301
+ clearTimer() {
302
+ if (this._timer) {
303
+ clearInterval(this._timer)
304
+ this._timer = null
305
+ }
306
+ },
307
+
308
+ handleClick(e) {
309
+ this.$emit('click', e)
310
+ }
311
+ }
312
+ }
313
+ </script>
@@ -1,23 +1,23 @@
1
- .xt-time {
2
- display: inline-block;
3
- color: var(--xt-text-color, #303133);
4
- font-variant-numeric: tabular-nums;
5
- transition: color 0.2s ease;
6
- }
7
-
8
- /* 字号(同步 XtText 的 CSS 变量方案,若未定义则使用 fallback) */
9
- .xt-time--extra-large { font-size: var(--xt-font-size-extra-large, 20px); }
10
- .xt-time--large { font-size: var(--xt-font-size-large, 18px); }
11
- .xt-time--medium { font-size: var(--xt-font-size-medium, 16px); }
12
- .xt-time--base { font-size: var(--xt-font-size-base, 14px); }
13
- .xt-time--small { font-size: var(--xt-font-size-small, 13px); }
14
- .xt-time--extra-small { font-size: var(--xt-font-size-extra-small, 12px); }
15
-
16
- /* 加粗 */
17
- .xt-time--bold { font-weight: 700; }
18
-
19
- /* 颜色语义:与 Element UI/XT 主题色一致 */
20
- .xt-time--primary { color: var(--xt-color-primary, #409eff); }
21
- .xt-time--success { color: var(--xt-color-success, #67c23a); }
22
- .xt-time--warning { color: var(--xt-color-warning, #e6a23c); }
23
- .xt-time--danger { color: var(--xt-color-danger, #f56c6c); }
1
+ .xt-time {
2
+ display: inline-block;
3
+ color: var(--xt-text-color, #303133);
4
+ font-variant-numeric: tabular-nums;
5
+ transition: color 0.2s ease;
6
+ }
7
+
8
+ /* 字号(同步 XtText 的 CSS 变量方案,若未定义则使用 fallback) */
9
+ .xt-time--extra-large { font-size: var(--xt-font-size-extra-large, 20px); }
10
+ .xt-time--large { font-size: var(--xt-font-size-large, 18px); }
11
+ .xt-time--medium { font-size: var(--xt-font-size-medium, 16px); }
12
+ .xt-time--base { font-size: var(--xt-font-size-base, 14px); }
13
+ .xt-time--small { font-size: var(--xt-font-size-small, 13px); }
14
+ .xt-time--extra-small { font-size: var(--xt-font-size-extra-small, 12px); }
15
+
16
+ /* 加粗 */
17
+ .xt-time--bold { font-weight: 700; }
18
+
19
+ /* 颜色语义:与 Element UI/XT 主题色一致 */
20
+ .xt-time--primary { color: var(--xt-color-primary, #409eff); }
21
+ .xt-time--success { color: var(--xt-color-success, #67c23a); }
22
+ .xt-time--warning { color: var(--xt-color-warning, #e6a23c); }
23
+ .xt-time--danger { color: var(--xt-color-danger, #f56c6c); }