UNPKG

@cqmcui/cqmcui

Version:

轻量级移动端 Vue2、Vue3 组件库(支持小程序开发)

256 lines (255 loc) 6.87 kB
import { reactive, computed, onBeforeMount, watch, toRefs, openBlock, createElementBlock, normalizeClass, renderSlot } from "vue"; import { p as padZero, c as createComponent } from "./component-81a4c1d0.js"; import { _ as _export_sfc } from "./_plugin-vue_export-helper-cc2b3d55.js"; import "../locale/lang"; const getTimeStamp = (timeStr) => { if (!timeStr) return Date.now(); let t = timeStr; t = t > 0 ? +t : t.toString().replace(/\-/g, "/"); return new Date(t).getTime(); }; const { componentName, create, translate } = createComponent("countdown"); const _sfc_main = create({ props: { modelValue: { type: Object, default: () => { return {}; } }, paused: { default: false, type: Boolean }, startTime: { // 可以是服务器当前时间 type: [Number, String], validator(v) { const dateStr = new Date(v).toString().toLowerCase(); return dateStr !== "invalid date"; } }, endTime: { type: [Number, String], validator(v) { const dateStr = new Date(v).toString().toLowerCase(); return dateStr !== "invalid date"; } }, // 是否开启毫秒 millisecond: { default: false, type: Boolean }, // 时间格式化 format: { type: String, default: "HH:mm:ss" }, autoStart: { type: Boolean, default: true }, // 倒计时时长,单位毫秒 time: { type: [Number, String], default: 0 } }, emits: ["input", "on-end", "on-restart", "on-paused", "update:modelValue"], setup(props, { emit, slots }) { const state = reactive({ restTime: 0, // 倒计时剩余时间时间 timer: null, counting: !props.paused && props.autoStart, // 是否处于倒计时中 handleEndTime: Date.now(), // 最终截止时间 diffTime: 0 // 设置了 startTime 时,与 date.now() 的差异 }); const classes = computed(() => { const prefixCls = componentName; return { [prefixCls]: true }; }); const renderTime = computed(() => { return formatRemainTime(state.restTime); }); const initTime = () => { state.handleEndTime = props.endTime; state.diffTime = Date.now() - getTimeStamp(props.startTime); if (!state.counting) state.counting = true; tick(); }; const tick = () => { if (window !== void 0) { state.timer = requestAnimationFrame(() => { if (state.counting) { const currentTime = Date.now() - state.diffTime; const remainTime = Math.max(state.handleEndTime - currentTime, 0); state.restTime = remainTime; if (!remainTime) { state.counting = false; pause(); emit("on-end"); } if (remainTime > 0) { tick(); } } }); } }; const formatRemainTime = (t, type) => { const ts = t; let rest = { d: 0, h: 0, m: 0, s: 0, ms: 0 }; const SECOND = 1e3; const MINUTE = 60 * SECOND; const HOUR = 60 * MINUTE; const DAY = 24 * HOUR; if (ts > 0) { rest.d = ts >= SECOND ? Math.floor(ts / DAY) : 0; rest.h = Math.floor(ts % DAY / HOUR); rest.m = Math.floor(ts % HOUR / MINUTE); rest.s = Math.floor(ts % MINUTE / SECOND); rest.ms = Math.floor(ts % SECOND); } return type == "custom" ? rest : parseFormat({ ...rest }); }; const parseFormat = (time) => { let { d, h, m, s, ms } = time; let format = props.format; if (format.includes("DD")) { format = format.replace("DD", padZero(d)); } else { h += Number(d) * 24; } if (format.includes("HH")) { format = format.replace("HH", padZero(h)); } else { m += Number(h) * 60; } if (format.includes("mm")) { format = format.replace("mm", padZero(m)); } else { s += Number(m) * 60; } if (format.includes("ss")) { format = format.replace("ss", padZero(s)); } else { ms += Number(s) * 1e3; } if (format.includes("S")) { const msC = padZero(ms, 3).toString(); if (format.includes("SSS")) { format = format.replace("SSS", msC); } else if (format.includes("SS")) { format = format.replace("SS", msC.slice(0, 2)); } else if (format.includes("S")) { format = format.replace("SS", msC.slice(0, 1)); } } return format; }; const start = () => { if (!state.counting && !props.autoStart) { state.counting = true; state.handleEndTime = Date.now() + Number(state.restTime); tick(); emit("on-restart", state.restTime); } }; const pause = () => { cancelAnimationFrame(state.timer); state.counting = false; emit("on-paused", state.restTime); }; const reset = () => { if (!props.autoStart) { pause(); state.restTime = props.time; } }; onBeforeMount(() => { if (props.autoStart) { initTime(); } else { state.restTime = props.time; } }); watch( () => state.restTime, (value) => { let tranTime = formatRemainTime(value, "custom"); emit("update:modelValue", tranTime); emit("input", tranTime); } ); watch( () => props.paused, (v, ov) => { if (!ov) { if (state.counting) { pause(); } } else { if (!state.counting) { state.counting = true; state.handleEndTime = Date.now() + Number(state.restTime); tick(); } emit("on-restart", state.restTime); } } ); watch( () => props.endTime, (value) => { initTime(); } ); watch( () => props.startTime, (value) => { initTime(); } ); return { ...toRefs(props), slots, classes, start, pause, renderTime, translate, reset }; } }); const _hoisted_1 = ["innerHTML"]; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { return openBlock(), createElementBlock("view", { class: normalizeClass(_ctx.classes) }, [ _ctx.slots.default ? renderSlot(_ctx.$slots, "default", { key: 0 }) : (openBlock(), createElementBlock("view", { key: 1, class: "cqmc-countdown__content", innerHTML: _ctx.renderTime }, null, 8, _hoisted_1)) ], 2); } const index = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]); export { index as default };