-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
/
Copy pathCountdown.tsx
99 lines (91 loc) · 2.48 KB
/
Countdown.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import { defineComponent, onBeforeUnmount, onMounted, onUpdated, ref } from 'vue';
import initDefaultProps from '../_util/props-util/initDefaultProps';
import Statistic, { statisticProps } from './Statistic';
import type { countdownValueType, FormatConfig } from './utils';
import { formatCountdown as formatCD } from './utils';
const REFRESH_INTERVAL = 1000 / 30;
function getTime(value?: countdownValueType) {
return new Date(value as any).getTime();
}
export default defineComponent({
name: 'AStatisticCountdown',
props: initDefaultProps(statisticProps, {
format: 'HH:mm:ss',
}),
emits: ['finish', 'change'],
setup(props, { emit, slots }) {
const countdownId = ref<any>();
const statistic = ref();
const syncTimer = () => {
const { value } = props;
const timestamp = getTime(value);
if (timestamp >= Date.now()) {
startTimer();
} else {
stopTimer();
}
};
const startTimer = () => {
if (countdownId.value) return;
const timestamp = getTime(props.value);
countdownId.value = setInterval(() => {
statistic.value.$forceUpdate();
if (timestamp > Date.now()) {
emit('change', timestamp - Date.now());
}
syncTimer();
}, REFRESH_INTERVAL);
};
const stopTimer = () => {
const { value } = props;
if (countdownId.value) {
clearInterval(countdownId.value);
countdownId.value = undefined;
const timestamp = getTime(value);
if (timestamp < Date.now()) {
emit('finish');
}
}
};
const formatCountdown = ({
value,
config,
}: {
value: countdownValueType;
config: FormatConfig;
}) => {
const { format } = props;
return formatCD(value, { ...config, format });
};
const valueRenderHtml = (node: any) => node;
onMounted(() => {
syncTimer();
});
onUpdated(() => {
syncTimer();
});
onBeforeUnmount(() => {
stopTimer();
});
return () => {
const title = props.title ?? slots.title?.();
const prefix = props.prefix ?? slots.prefix?.();
const suffix = props.suffix ?? slots.suffix?.();
return (
<Statistic
ref={statistic}
{...{
...props,
valueRender: valueRenderHtml,
formatter: formatCountdown,
}}
v-slots={{
title,
prefix,
suffix,
}}
/>
);
};
},
});