mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 12:18:42 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			164 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			164 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
<template>
 | 
						||
	<view class="u-count-down">
 | 
						||
		<slot>
 | 
						||
			<text class="u-count-down__text">{{ formattedTime }}</text>
 | 
						||
		</slot>
 | 
						||
	</view>
 | 
						||
</template>
 | 
						||
 | 
						||
<script>
 | 
						||
	import props from './props.js';
 | 
						||
	import {
 | 
						||
		isSameSecond,
 | 
						||
		parseFormat,
 | 
						||
		parseTimeData
 | 
						||
	} from './utils';
 | 
						||
	/**
 | 
						||
	 * u-count-down 倒计时
 | 
						||
	 * @description 该组件一般使用于某个活动的截止时间上,通过数字的变化,给用户明确的时间感受,提示用户进行某一个行为操作。
 | 
						||
	 * @tutorial https://uviewui.com/components/countDown.html
 | 
						||
	 * @property {String | Number}	time		倒计时时长,单位ms (默认 0 )
 | 
						||
	 * @property {String}			format		时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒  (默认 'HH:mm:ss' )
 | 
						||
	 * @property {Boolean}			autoStart	是否自动开始倒计时 (默认 true )
 | 
						||
	 * @property {Boolean}			millisecond	是否展示毫秒倒计时 (默认 false )
 | 
						||
	 * @event {Function} finish 倒计时结束时触发 
 | 
						||
	 * @event {Function} change 倒计时变化时触发 
 | 
						||
	 * @event {Function} start	开始倒计时
 | 
						||
	 * @event {Function} pause	暂停倒计时 
 | 
						||
	 * @event {Function} reset	重设倒计时,若 auto-start 为 true,重设后会自动开始倒计时 
 | 
						||
	 * @example <u-count-down :time="time"></u-count-down>
 | 
						||
	 */
 | 
						||
	export default {
 | 
						||
		name: 'u-count-down',
 | 
						||
		mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
 | 
						||
		data() {
 | 
						||
			return {
 | 
						||
				timer: null,
 | 
						||
				// 各单位(天,时,分等)剩余时间
 | 
						||
				timeData: parseTimeData(0),
 | 
						||
				// 格式化后的时间,如"03:23:21"
 | 
						||
				formattedTime: '0',
 | 
						||
				// 倒计时是否正在进行中
 | 
						||
				runing: false,
 | 
						||
				endTime: 0, // 结束的毫秒时间戳
 | 
						||
				remainTime: 0, // 剩余的毫秒时间
 | 
						||
			}
 | 
						||
		},
 | 
						||
		watch: {
 | 
						||
			time(n) {
 | 
						||
				this.reset()
 | 
						||
			}
 | 
						||
		},
 | 
						||
		mounted() {
 | 
						||
			this.init()
 | 
						||
		},
 | 
						||
		methods: {
 | 
						||
			init() {
 | 
						||
				this.reset()
 | 
						||
			},
 | 
						||
			// 开始倒计时
 | 
						||
			start() {
 | 
						||
				if (this.runing) return
 | 
						||
				// 标识为进行中
 | 
						||
				this.runing = true
 | 
						||
				// 结束时间戳 = 此刻时间戳 + 剩余的时间
 | 
						||
				this.endTime = Date.now() + this.remainTime
 | 
						||
				this.toTick()
 | 
						||
			},
 | 
						||
			// 根据是否展示毫秒,执行不同操作函数
 | 
						||
			toTick() {
 | 
						||
				if (this.millisecond) {
 | 
						||
					this.microTick()
 | 
						||
				} else {
 | 
						||
					this.macroTick()
 | 
						||
				}
 | 
						||
			},
 | 
						||
			macroTick() {
 | 
						||
				this.clearTimeout()
 | 
						||
				// 每隔一定时间,更新一遍定时器的值
 | 
						||
				// 同时此定时器的作用也能带来毫秒级的更新
 | 
						||
				this.timer = setTimeout(() => {
 | 
						||
					// 获取剩余时间
 | 
						||
					const remain = this.getRemainTime()
 | 
						||
					// 重设剩余时间
 | 
						||
					if (!isSameSecond(remain, this.remainTime) || remain === 0) {
 | 
						||
						this.setRemainTime(remain)
 | 
						||
					}
 | 
						||
					// 如果剩余时间不为0,则继续检查更新倒计时
 | 
						||
					if (this.remainTime !== 0) {
 | 
						||
						this.macroTick()
 | 
						||
					}
 | 
						||
				}, 30)
 | 
						||
			},
 | 
						||
			microTick() {
 | 
						||
				this.clearTimeout()
 | 
						||
				this.timer = setTimeout(() => {
 | 
						||
					this.setRemainTime(this.getRemainTime())
 | 
						||
					if (this.remainTime !== 0) {
 | 
						||
						this.microTick()
 | 
						||
					}
 | 
						||
				}, 50)
 | 
						||
			},
 | 
						||
			// 获取剩余的时间
 | 
						||
			getRemainTime() {
 | 
						||
				// 取最大值,防止出现小于0的剩余时间值
 | 
						||
				return Math.max(this.endTime - Date.now(), 0)
 | 
						||
			},
 | 
						||
			// 设置剩余的时间
 | 
						||
			setRemainTime(remain) {
 | 
						||
				this.remainTime = remain
 | 
						||
				// 根据剩余的毫秒时间,得出该有天,小时,分钟等的值,返回一个对象
 | 
						||
				const timeData = parseTimeData(remain)
 | 
						||
				this.$emit('change', timeData)
 | 
						||
				// 得出格式化后的时间
 | 
						||
				this.formattedTime = parseFormat(this.format, timeData)
 | 
						||
				// 如果时间已到,停止倒计时
 | 
						||
				if (remain <= 0) {
 | 
						||
					this.pause()
 | 
						||
					this.$emit('finish')
 | 
						||
				}
 | 
						||
			},
 | 
						||
			// 重置倒计时
 | 
						||
			reset() {
 | 
						||
				this.pause()
 | 
						||
				this.remainTime = this.time
 | 
						||
				this.setRemainTime(this.remainTime)
 | 
						||
				if (this.autoStart) {
 | 
						||
					this.start()
 | 
						||
				}
 | 
						||
			},
 | 
						||
			// 暂停倒计时
 | 
						||
			pause() {
 | 
						||
				this.runing = false;
 | 
						||
				this.clearTimeout()
 | 
						||
			},
 | 
						||
			// 清空定时器
 | 
						||
			clearTimeout() {
 | 
						||
				clearTimeout(this.timer)
 | 
						||
				this.timer = null
 | 
						||
			}
 | 
						||
		},
 | 
						||
		beforeDestroy() {
 | 
						||
			this.clearTimeout()
 | 
						||
		}
 | 
						||
	}
 | 
						||
</script>
 | 
						||
 | 
						||
<style
 | 
						||
	lang="scss"
 | 
						||
	scoped
 | 
						||
>
 | 
						||
	@import "../../libs/css/components.scss";
 | 
						||
	$u-count-down-text-color:$u-content-color !default;
 | 
						||
	$u-count-down-text-font-size:15px !default;
 | 
						||
	$u-count-down-text-line-height:22px !default;
 | 
						||
 | 
						||
	.u-count-down {
 | 
						||
		&__text {
 | 
						||
			color: $u-count-down-text-color;
 | 
						||
			font-size: $u-count-down-text-font-size;
 | 
						||
			line-height: $u-count-down-text-line-height;
 | 
						||
		}
 | 
						||
	}
 | 
						||
</style>
 |