diff --git a/packages/devui-vue/devui/countdown/__tests__/countdown.spec.ts b/packages/devui-vue/devui/countdown/__tests__/countdown.spec.ts index 138a2a5c6b379f6e04a51fc6274e528713dd0dc4..4eeb18c5d9edadd58d9ffa9dfb7f35b2b26710cb 100644 --- a/packages/devui-vue/devui/countdown/__tests__/countdown.spec.ts +++ b/packages/devui-vue/devui/countdown/__tests__/countdown.spec.ts @@ -1,8 +1,94 @@ import { mount } from '@vue/test-utils'; import { Countdown } from '../index'; +import { nextTick } from 'vue' describe('countdown test', () => { - it('countdown init render', async () => { + it('countdown default render', async () => { // todo + const wrapper = mount(Countdown, { + props: { + value: +new Date() + } + }) + expect(wrapper.get('.countdown-content')); + + }) + + it('countdown text', () => { + // todo + const time = Date.now() + 11 * 24 * 60 * 60 * 1000 + 8 * 60 * 60 * 1000 + 40 * 60 * 1000 + 40 * 1000; + [ + ['YY-MM-DD HH:mm:ss', '00-00-11 08:40:40'], + ['HH:mm:ss', '272:40:40'], + ['YY-MM-DD mm:ss', '00-00-11 520:40'], + ].forEach(async ([format, value]) => { + const wrapper = await mount(Countdown, { + props: { + format, + value: time, + } + }) + expect(wrapper.find('.countdown-value').text()).toEqual(value) + }) + + }) + + it('countdown millisecond', async () => { + const time = Date.now() + 11 * 24 * 60 * 60 * 1000 + 8 * 60 * 60 * 1000 + 40 * 60 * 1000 + 40 * 1000 + 5; + const wrapper = await mount(Countdown, { + props: { + format: 'HHH:mm:ss SSS', + value: time, + } + }) + await nextTick(); + expect(Math.abs(time -Date.now() - wrapper.emitted('onChange')[0][0].leftTime) < 16).toEqual(true); + }) + + it('countdown prefix and suffix', async () => { + const time = Date.now() + 5000; + const prefix = '前缀-'; + const suffix = '前缀-'; + const wrapper = mount(Countdown, { + props: { + format: 'HHH:mm:ss SSS', + value: time, + prefix, + suffix + } + }) + expect(wrapper.find('.countdown-prefix').text()).toEqual(prefix); + expect(wrapper.find('.countdown-suffix').text()).toEqual(suffix); + }) + + it('countdown valueStyle', async () => { + const time = Date.now() + 5000; + const valueStyle = {'color': 'rgb(94, 124, 224)', 'font-size': '20px'}; + const wrapper = await mount(Countdown, { + props: { + format: 'HHH:mm:ss SSS', + value: time, + valueStyle + } + }) + const { style } = wrapper.find('.countdown-content').attributes(); + let styleStr = ''; + for (const k in valueStyle) { + styleStr += `${k}: ${valueStyle[k]}; ` + } + expect(style).toEqual(styleStr.slice(0,-1)); + }) + + it('countdown slot', async () => { + const time = Date.now() + 5000; + const wrapper = await mount(Countdown, { + props: { + value: time + }, + slots: { + default: 'test slot' + } + }) + expect(wrapper.find('.devui-countdown').text()).toEqual('test slot'); }) }) diff --git a/packages/devui-vue/devui/countdown/src/countdown.scss b/packages/devui-vue/devui/countdown/src/countdown.scss index 33f1814075d7e782f4878f584393756e549fbacc..3bc82c8f3267bf4b79c2f5dced3c4b08480286fe 100644 --- a/packages/devui-vue/devui/countdown/src/countdown.scss +++ b/packages/devui-vue/devui/countdown/src/countdown.scss @@ -3,9 +3,9 @@ .devui-countdown { .countdown-content { font-size: 24px; + color: $devui-text; span { - color: $devui-text; display: inline-block; } diff --git a/packages/devui-vue/devui/countdown/src/countdown.tsx b/packages/devui-vue/devui/countdown/src/countdown.tsx index d5aec728ba7f82304e786aeb01de4f6451800099..1486b2b757714ee6cd61b0a5055663cd8931b87e 100644 --- a/packages/devui-vue/devui/countdown/src/countdown.tsx +++ b/packages/devui-vue/devui/countdown/src/countdown.tsx @@ -1,4 +1,4 @@ -import { defineComponent, ref, onUnmounted } from 'vue' +import { defineComponent, ref, onUnmounted ,onMounted } from 'vue' import { countdownProps, CountdownProps } from './countdown-types' import './countdown.scss' import { getFormatTime, getLegalTime, getTimeSplit, getDeduplication, numFormat } from './utils' @@ -8,6 +8,7 @@ export default defineComponent({ props: countdownProps, emits: ['onChange', 'onFinish'], setup(props: CountdownProps, ctx) { + const countdown = ref() const s = getDeduplication(props.format); const timeFormat = getTimeSplit(props.format); const timeStr = ref('') @@ -20,11 +21,12 @@ export default defineComponent({ } return pre + cur.k; }, '') - timeStr.value = t; + timeStr.value = t; } const getTime = () => { - const leftTime = props.value > new Date().getTime() ? props.value - new Date().getTime() : 0 + const value = new Date(props.value).getTime(); + const leftTime = value > new Date().getTime() ? value - new Date().getTime() : 0 const formatTime = getFormatTime(leftTime); const legalTime = getLegalTime(s, formatTime); !ctx.slots.default && getTimeStr(legalTime); @@ -36,19 +38,25 @@ export default defineComponent({ return leftTime; } - const countdown = setInterval(() => { - const t = getTime(); - if (t === 0) { - ctx.emit('onFinish'); - clearInterval(countdown) - } - }, s.has('S') ? 100 : 1000) + const startTime = () => { + getTime(); + if (countdown.value) return; + countdown.value = setInterval(() => { + const t = getTime(); + if (t === 0) { + ctx.emit('onFinish'); + clearInterval(countdown.value) + } + }, s.has('S') ? 100 : 1000) + + } - getTime(); + onMounted(()=>{ + startTime() + }) onUnmounted(() => { - clearInterval(countdown); + clearInterval(countdown.value); }) - return () => { return (
{ diff --git a/packages/devui-vue/docs/components/countdown/index.md b/packages/devui-vue/docs/components/countdown/index.md index af6b6a68aeaf1d716c8a76f66fdafff2b03fdfe9..fcdce27a66ab0335a9c1bb473fb325248c4f6bc9 100644 --- a/packages/devui-vue/docs/components/countdown/index.md +++ b/packages/devui-vue/docs/components/countdown/index.md @@ -8,13 +8,13 @@ ### 基本用法 -默认:时分秒 +默认:时分秒: :::demo ```vue @@ -23,12 +23,52 @@ import { defineComponent, ref } from 'vue' export default defineComponent({ setup() { + const deadline = ref(Date.now() + 100 *1000); const changeTime = (n) => { } const finishTime = () => { } return { msg: 'Countdown 倒计时 组件文档示例', + deadline, + changeTime, + finishTime + } + } +}) + + + +``` +::: + + +### 时间格式 +时分秒毫秒: +:::demo + +```vue + + + + + +``` +::: + + + +### 前缀和后缀 +:::demo + +```vue + + + + + +``` +::: + + + +### 设置style +设置倒计时文字样式: +:::demo + +```vue + + + + + +``` +::: + + ### 插槽 :::demo @@ -150,15 +308,14 @@ export default defineComponent({ d-countdown 参数 -| 参数 | 类型 | 默认 | 说明 | -| ---- | ---- | ---- | ---- | -| format | string | HH:mm:ss | 格式化倒计时展示,参考moment | -| value | number | - | 数值内容 | -| prefix | string | - | 设置数值的前缀 | -| suffix | string | - | 设置数值的后缀 | -| valueStyle | CSSProperties | - | 设置数值的样式 | +| 参数 | 类型 | 默认 | 说明 | 跳转demo | +| ---- | ---- | ---- | ---- | ---- | +| format | string | HH:mm:ss | 格式化倒计时展示,参考moment | [时间格式](#时间格式) | +| value | number | - | 数值内容 | [基本用法](#基本用法) | +| prefix | string | - | 设置数值的前缀 | [前缀和后缀](#前缀和后缀) | +| suffix | string | - | 设置数值的后缀 | [前缀和后缀](#前缀和后缀) | +| valueStyle | CSSProperties | - | 设置数值的样式 | [设置style](#设置style) | -### d-countdown 事件 d-countdown 事件