uniapp-dyckui 4.1.5 → 4.1.7

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.
@@ -92,6 +92,10 @@ const showBasicToast = ref(false)
92
92
  | `customIcon` | `string` | `''` | 自定义图标字符 | - |
93
93
  | `large` | `boolean` | `false` | 是否为大尺寸模式 | `true/false` |
94
94
  | `customStyle` | `Record<string, any>` | `{}` | 自定义样式对象 | - |
95
+ | `countdown` | `boolean` | `false` | 是否开启倒计时功能 | `true/false` |
96
+ | `countdownSeconds` | `number` | `5` | 倒计时总时间(秒) | - |
97
+ | `countdownParentheses` | `boolean` | `false` | 是否在倒计时数字外添加括号 | `true/false` |
98
+ | `countdownSuffix` | `string` | `''` | 倒计时后追加的文字描述 | - |
95
99
 
96
100
  ### Emits 事件
97
101
 
@@ -221,6 +225,43 @@ const showBasicToast = ref(false)
221
225
  message="需要手动点击关闭"
222
226
  :duration="0"
223
227
  />
228
+
229
+ <!-- 带倒计时的提示 -->
230
+ <SwToast
231
+ v-model="showCountdownToast"
232
+ message="倒计时提示"
233
+ countdown
234
+ :countdownSeconds="10"
235
+ :duration="10000"
236
+ />
237
+
238
+ <!-- 带括号的倒计时 -->
239
+ <SwToast
240
+ v-model="showBracketCountdownToast"
241
+ message="倒计时提示"
242
+ countdown
243
+ countdownParentheses
244
+ :countdownSeconds="10"
245
+ />
246
+
247
+ <!-- 带后缀的倒计时 -->
248
+ <SwToast
249
+ v-model="showSuffixCountdownToast"
250
+ message="自动返回"
251
+ countdown
252
+ :countdownSeconds="10"
253
+ countdownSuffix="后返回首页"
254
+ />
255
+
256
+ <!-- 带括号和后缀的倒计时 -->
257
+ <SwToast
258
+ v-model="showBracketSuffixToast"
259
+ message=""
260
+ countdown
261
+ countdownParentheses
262
+ :countdownSeconds="10"
263
+ countdownSuffix="后返回首页"
264
+ /> <!-- 显示效果:(10秒后返回首页) -->
224
265
  ```
225
266
 
226
267
  ### 完整示例
@@ -572,6 +613,12 @@ class ToastQueue {
572
613
 
573
614
  ## 📄 更新日志
574
615
 
616
+ ### v1.0.1 (2024-01-08)
617
+ - ✨ 增强倒计时功能,支持括号显示和后缀文本
618
+ - ✨ 实现duration与countdownSeconds的自动联动
619
+ - ✨ 添加countdownParentheses参数,控制倒计时是否带括号
620
+ - ✨ 添加countdownSuffix参数,支持倒计时后追加文本
621
+
575
622
  ### v1.0.0 (2024-01-01)
576
623
  - 🎉 初始版本发布
577
624
  - ✨ 支持四种提示类型
@@ -23,13 +23,14 @@
23
23
 
24
24
  <!-- 状态图标 -->
25
25
  <view v-else-if="showIcon" class="sw-toast__icon">
26
- <text v-if="type === 'success'" class="sw-toast__icon--success">✓</text>
27
- <text v-else-if="type === 'fail'" class="sw-toast__icon--fail">✗</text>
26
+ <text v-if="type === 'success'" class="sw-toast__icon--success iconfont icon-zhengqueshixin" />
27
+ <text v-else-if="type === 'fail'" class="sw-toast__icon--fail iconfont icon-shanchu" />
28
+ <text v-else-if="type === 'warning'" class="sw-toast__icon--warning iconfont icon-jurassic_warn" />
28
29
  <text v-else-if="customIcon" class="sw-toast__custom-icon">{{ customIcon }}</text>
29
30
  </view>
30
31
 
31
32
  <!-- 文本内容 -->
32
- <text v-if="message" class="sw-toast__text">{{ message }}</text>
33
+ <text v-if="displayMessage" class="sw-toast__text" :class="{ 'sw-toast__text--long': longText }">{{ displayMessage }}</text>
33
34
  </view>
34
35
  </template>
35
36
 
@@ -45,7 +46,7 @@ interface Props {
45
46
  /**
46
47
  * 提示类型
47
48
  */
48
- type?: 'text' | 'loading' | 'success' | 'fail'
49
+ type?: 'text' | 'loading' | 'success' | 'fail' | 'warning'
49
50
  /**
50
51
  * 显示位置
51
52
  */
@@ -78,6 +79,26 @@ interface Props {
78
79
  * 自定义样式
79
80
  */
80
81
  customStyle?: Record<string, any>
82
+ /**
83
+ * 是否开启倒计时功能
84
+ */
85
+ countdown?: boolean
86
+ /**
87
+ * 倒计时总时间(秒)
88
+ */
89
+ countdownSeconds?: number
90
+ /**
91
+ * 是否在倒计时数字外添加括号
92
+ */
93
+ countdownParentheses?: boolean
94
+ /**
95
+ * 倒计时后追加的文字描述
96
+ */
97
+ countdownSuffix?: string
98
+ /**
99
+ * 是否开启长文本模式(允许换行)
100
+ */
101
+ longText?: boolean
81
102
  }
82
103
 
83
104
  const props = withDefaults(defineProps<Props>(), {
@@ -91,6 +112,11 @@ const props = withDefaults(defineProps<Props>(), {
91
112
  customIcon: '',
92
113
  large: false,
93
114
  customStyle: () => ({}),
115
+ countdown: false,
116
+ countdownSeconds: 5,
117
+ countdownParentheses: false,
118
+ countdownSuffix: '',
119
+ longText: false,
94
120
  })
95
121
 
96
122
  // Emits
@@ -112,10 +138,13 @@ const emit = defineEmits<{
112
138
  // Refs
113
139
  const toastRef = ref<any>(null)
114
140
  let timer: number | null | ReturnType<typeof setTimeout> = null
141
+ let countdownTimer: number | null | ReturnType<typeof setInterval> = null
115
142
 
116
143
  // 内部状态
117
144
  const showToast = ref(props.modelValue)
118
145
  const isClosing = ref(false)
146
+ const currentCountdown = ref(props.countdownSeconds)
147
+ const originalMessage = ref(props.message)
119
148
 
120
149
  // 计算是否需要显示图标
121
150
  const showIcon = computed(() => {
@@ -126,6 +155,24 @@ const showIcon = computed(() => {
126
155
  return true
127
156
  })
128
157
 
158
+ // 计算实际显示的消息(包含倒计时)
159
+ const displayMessage = computed(() => {
160
+ if (props.countdown && showToast.value) {
161
+ // 构建倒计时部分
162
+ let countdownPart = ''
163
+ if (props.countdownParentheses) {
164
+ // 带括号的倒计时格式:(10秒后返回首页)
165
+ countdownPart = `(${currentCountdown.value}秒${props.countdownSuffix})`
166
+ }
167
+ else {
168
+ // 不带括号的倒计时格式:10秒后返回首页
169
+ countdownPart = `${currentCountdown.value}秒${props.countdownSuffix}`
170
+ }
171
+ return `${originalMessage.value || ''} ${countdownPart}`
172
+ }
173
+ return props.message
174
+ })
175
+
129
176
  // 点击事件处理
130
177
  function onClick() {
131
178
  emit('click')
@@ -136,6 +183,8 @@ function close() {
136
183
  if (!showToast.value)
137
184
  return
138
185
 
186
+ // 清除倒计时定时器
187
+ clearCountdownTimer()
139
188
  // 添加关闭动画
140
189
  isClosing.value = true
141
190
  emit('close')
@@ -146,10 +195,13 @@ function startTimer() {
146
195
  // 清除之前的定时器
147
196
  clearTimer()
148
197
 
149
- if (props.duration > 0 && !props.loading) {
198
+ // 计算实际使用的duration:如果开启倒计时且countdownSeconds>0,则使用countdownSeconds*1000,否则使用props.duration
199
+ const actualDuration = props.countdown && props.countdownSeconds > 0 ? props.countdownSeconds * 1000 : props.duration
200
+
201
+ if (actualDuration > 0 && !props.loading) {
150
202
  timer = setTimeout(() => {
151
203
  close()
152
- }, props.duration)
204
+ }, actualDuration)
153
205
  }
154
206
  }
155
207
 
@@ -161,6 +213,38 @@ function clearTimer() {
161
213
  }
162
214
  }
163
215
 
216
+ // 开始倒计时
217
+ function startCountdown() {
218
+ // 清除之前的倒计时定时器
219
+ clearCountdownTimer()
220
+
221
+ if (props.countdown && props.countdownSeconds > 0) {
222
+ currentCountdown.value = props.countdownSeconds
223
+ originalMessage.value = props.message
224
+
225
+ countdownTimer = setInterval(() => {
226
+ currentCountdown.value--
227
+ if (currentCountdown.value <= 0) {
228
+ clearCountdownTimer()
229
+ // 如果开启了自动关闭,倒计时结束后关闭Toast
230
+ if (props.duration > 0) {
231
+ close()
232
+ }
233
+ }
234
+ }, 1000)
235
+ }
236
+ }
237
+
238
+ // 清除倒计时定时器
239
+ function clearCountdownTimer() {
240
+ if (countdownTimer) {
241
+ clearInterval(countdownTimer)
242
+ countdownTimer = null
243
+ }
244
+ // 重置当前倒计时
245
+ currentCountdown.value = props.countdownSeconds
246
+ }
247
+
164
248
  // 过渡结束处理
165
249
  function handleTransitionEnd() {
166
250
  if (isClosing.value) {
@@ -177,6 +261,10 @@ watch(() => props.modelValue, (newVal) => {
177
261
  showToast.value = true
178
262
  isClosing.value = false
179
263
  startTimer()
264
+ // 如果开启了倒计时,开始倒计时
265
+ if (props.countdown) {
266
+ startCountdown()
267
+ }
180
268
  }
181
269
  else {
182
270
  // 隐藏Toast
@@ -188,6 +276,20 @@ watch(() => props.modelValue, (newVal) => {
188
276
  watch(() => props.message, () => {
189
277
  if (showToast.value && !props.loading) {
190
278
  startTimer()
279
+ // 如果开启了倒计时,更新原始消息
280
+ if (props.countdown) {
281
+ originalMessage.value = props.message
282
+ }
283
+ }
284
+ })
285
+
286
+ // 监听countdown或countdownSeconds变化,重新开始倒计时
287
+ watch([() => props.countdown, () => props.countdownSeconds], () => {
288
+ if (showToast.value && props.countdown) {
289
+ startCountdown()
290
+ }
291
+ else {
292
+ clearCountdownTimer()
191
293
  }
192
294
  })
193
295
 
@@ -195,11 +297,16 @@ watch(() => props.message, () => {
195
297
  onMounted(() => {
196
298
  if (props.modelValue) {
197
299
  startTimer()
300
+ // 如果开启了倒计时,开始倒计时
301
+ if (props.countdown) {
302
+ startCountdown()
303
+ }
198
304
  }
199
305
  })
200
306
 
201
307
  onUnmounted(() => {
202
308
  clearTimer()
309
+ clearCountdownTimer()
203
310
  })
204
311
 
205
312
  // 暴露方法
@@ -216,11 +323,10 @@ defineExpose({
216
323
  display: inline-flex;
217
324
  align-items: center;
218
325
  justify-content: center;
219
- max-width: 80%;
220
- padding: 20rpx 32rpx;
221
- border-radius: 8rpx;
326
+ padding: 24rpx 40rpx;
327
+ border-radius: 12rpx;
222
328
  font-size: 28rpx;
223
- line-height: 40rpx;
329
+ line-height: 80rpx;
224
330
  color: #fff;
225
331
  background-color: rgba(0, 0, 0, 0.7);
226
332
  box-sizing: border-box;
@@ -229,12 +335,11 @@ defineExpose({
229
335
  position: fixed;
230
336
  left: 50%;
231
337
  transform: translateX(-50%) translateY(0);
232
- word-wrap: break-word;
233
- white-space: pre-wrap;
234
338
  user-select: none;
235
339
  opacity: 0;
236
340
  visibility: hidden;
237
341
  pointer-events: none;
342
+ border: 2rpx solid rgba(255, 255, 255, 0.2);
238
343
  }
239
344
 
240
345
  /* 显示动画 */
@@ -282,12 +387,52 @@ defineExpose({
282
387
  background-color: rgba(0, 0, 0, 0.7);
283
388
  }
284
389
 
390
+ .iconfont {
391
+ font-size: 40rpx;
392
+ vertical-align: middle;
393
+ }
285
394
  .sw-toast--success {
286
- background-color: #67c23a;
395
+ background-color: rgba(240, 249, 235, 1);
396
+ height: 80rpx;
397
+ border-width: 0rpx;
398
+ border-radius: 12rpx;
399
+ border-width: 2rpx;
400
+ border-style: solid;
401
+ box-sizing: border-box;
402
+ text-align: left;
403
+ font-size: 28rpx;
404
+ color: #67c23a;
405
+ border-color: rgba(227, 244, 218, 1);
287
406
  }
288
407
 
289
408
  .sw-toast--fail {
290
- background-color: #f56c6c;
409
+ background-color: #f5222d;
410
+ border-width: 0rpx;
411
+ background-color: rgba(254, 240, 240, 1);
412
+ box-sizing: border-box;
413
+ border-width: 2rpx;
414
+ border-style: solid;
415
+ border-color: rgba(253, 226, 226, 1);
416
+ border-radius: 12rpx;
417
+ height: 80rpx;
418
+ display: flex;
419
+ text-align: left;
420
+ font-size: 28rpx;
421
+ color: #f56c6c;
422
+ }
423
+
424
+ .sw-toast--warning {
425
+ background-color: rgba(253, 246, 236, 1);
426
+ height: 80rpx;
427
+ border-width: 0rpx;
428
+ border-radius: 12rpx;
429
+ border-width: 2rpx;
430
+ border-style: solid;
431
+ box-sizing: border-box;
432
+ text-align: left;
433
+ font-size: 28rpx;
434
+ color: #e6a23c;
435
+ border-color: rgba(255, 236, 208, 1);
291
436
  }
292
437
 
293
438
  /* 大尺寸样式 */
@@ -323,20 +468,32 @@ defineExpose({
323
468
  margin-right: 16rpx;
324
469
 
325
470
  &--success,
326
- &--fail {
471
+ &--fail,
472
+ &--warning {
327
473
  display: inline-block;
328
474
  width: 40rpx;
329
475
  height: 40rpx;
330
- font-size: 40rpx;
476
+ font-size: 32rpx;
331
477
  font-weight: bold;
478
+ text-align: center;
479
+ line-height: 40rpx;
332
480
  }
333
481
  }
334
482
 
335
483
  /* 文本内容 */
336
484
  .sw-toast__text {
337
485
  margin: 0;
486
+ white-space: nowrap;
487
+ width: auto;
488
+ }
489
+
490
+ /* 长文本模式样式 */
491
+ .sw-toast__text--long {
338
492
  word-wrap: break-word;
493
+ overflow-wrap: break-word;
339
494
  white-space: pre-wrap;
495
+ width: 100%;
496
+ word-break: break-all;
340
497
  }
341
498
 
342
499
  /* 加载动画 */
@@ -347,26 +504,24 @@ defineExpose({
347
504
  }
348
505
 
349
506
  /* 响应式设计 */
350
- @media (max-width: 768px) {
351
- .sw-toast {
352
- max-width: 90%;
353
- padding: 16rpx 24rpx;
354
- font-size: 26rpx;
355
- line-height: 36rpx;
356
- }
507
+ .sw-toast {
508
+ max-width: 100%;
509
+ padding: 16rpx 24rpx;
510
+ font-size: 26rpx;
511
+ line-height: 36rpx;
512
+ }
357
513
 
358
- .sw-toast--large {
359
- padding: 24rpx 40rpx;
360
- font-size: 30rpx;
361
- line-height: 44rpx;
362
- }
514
+ .sw-toast--large {
515
+ padding: 24rpx 40rpx;
516
+ font-size: 30rpx;
517
+ line-height: 44rpx;
518
+ }
363
519
 
364
- .sw-toast--top {
365
- top: 60rpx;
366
- }
520
+ .sw-toast--top {
521
+ top: 60rpx;
522
+ }
367
523
 
368
- .sw-toast--bottom {
369
- bottom: 60rpx;
370
- }
524
+ .sw-toast--bottom {
525
+ bottom: 60rpx;
371
526
  }
372
527
  </style>