mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
[new feature] add CountDown component (#3805)
This commit is contained in:
parent
577194b16d
commit
9fcc9086f7
@ -227,6 +227,10 @@ export default {
|
|||||||
path: '/collapse',
|
path: '/collapse',
|
||||||
title: 'Collapse 折叠面板'
|
title: 'Collapse 折叠面板'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/count-down',
|
||||||
|
title: 'CountDown 倒计时'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/divider',
|
path: '/divider',
|
||||||
title: 'Divider 分割线'
|
title: 'Divider 分割线'
|
||||||
@ -561,6 +565,10 @@ export default {
|
|||||||
path: '/collapse',
|
path: '/collapse',
|
||||||
title: 'Collapse'
|
title: 'Collapse'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/count-down',
|
||||||
|
title: 'CountDown'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/divider',
|
path: '/divider',
|
||||||
title: 'Divider'
|
title: 'Divider'
|
||||||
|
@ -179,7 +179,7 @@ export default {
|
|||||||
|
|
||||||
### Checkbox Slots
|
### Checkbox Slots
|
||||||
|
|
||||||
| 名称 | 说明 | slot-scope |
|
| 名称 | 说明 | slot-scope 参数 |
|
||||||
|------|------|------|
|
|------|------|------|
|
||||||
| default | 自定义文本 | - |
|
| default | 自定义文本 | - |
|
||||||
| icon | 自定义图标 | checked: 是否为选中状态 |
|
| icon | 自定义图标 | checked: 是否为选中状态 |
|
||||||
|
114
src/count-down/README.md
Normal file
114
src/count-down/README.md
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
# CountDown
|
||||||
|
|
||||||
|
### Install
|
||||||
|
|
||||||
|
``` javascript
|
||||||
|
import { CountDown } from 'vant';
|
||||||
|
|
||||||
|
Vue.use(CountDown);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Basic Usage
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-count-down :time="time" />
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
time: 30 * 60 * 60 * 1000
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Format
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-count-down
|
||||||
|
:time="time"
|
||||||
|
format="DD Day, HH:mm:ss"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Millisecond
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-count-down
|
||||||
|
millisecond
|
||||||
|
:time="time"
|
||||||
|
format="HH:mm:ss:SSS"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Style
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-count-down :time="time">
|
||||||
|
<template v-slot="timeData">
|
||||||
|
<span class="item">{{ timeData.hours }}</span>
|
||||||
|
<span class="item">{{ timeData.minutes }}</span>
|
||||||
|
<span class="item">{{ timeData.seconds }}</span>
|
||||||
|
</template>
|
||||||
|
</van-count-down>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.item {
|
||||||
|
display: inline-block;
|
||||||
|
width: 22px;
|
||||||
|
margin-right: 5px;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #1989fa;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual Control
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-count-down
|
||||||
|
ref="countDown"
|
||||||
|
millisecond
|
||||||
|
:time="3000"
|
||||||
|
:auto-start="false"
|
||||||
|
format="ss:SSS"
|
||||||
|
@finish="finished"
|
||||||
|
/>
|
||||||
|
<van-grid clickable :column-num="3">
|
||||||
|
<van-grid-item text="Start" icon="play-circle-o" @click="start" />
|
||||||
|
<van-grid-item text="Pause" icon="pause-circle-o" @click="pause" />
|
||||||
|
<van-grid-item text="Reset" icon="replay" @click="reset" />
|
||||||
|
</van-grid>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
start() {
|
||||||
|
this.$refs.countDown.start();
|
||||||
|
},
|
||||||
|
pause() {
|
||||||
|
this.$refs.countDown.pause();
|
||||||
|
},
|
||||||
|
reset() {
|
||||||
|
this.$refs.countDown.reset();
|
||||||
|
},
|
||||||
|
finish() {
|
||||||
|
this.$toast('Finished');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### Props
|
||||||
|
|
||||||
|
| Attribute | Description | Type | Default |
|
||||||
|
|------|------|------|------|
|
160
src/count-down/README.zh-CN.md
Normal file
160
src/count-down/README.zh-CN.md
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
# CountDown 倒计时
|
||||||
|
|
||||||
|
### 引入
|
||||||
|
|
||||||
|
``` javascript
|
||||||
|
import { CountDown } from 'vant';
|
||||||
|
|
||||||
|
Vue.use(CountDown);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 代码演示
|
||||||
|
|
||||||
|
### 基本用法
|
||||||
|
|
||||||
|
`time`属性表示倒计时总时长,单位为毫秒
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-count-down :time="time" />
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
time: 30 * 60 * 60 * 1000
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 自定义格式
|
||||||
|
|
||||||
|
通过`format`属性设置倒计时文本的内容
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-count-down
|
||||||
|
:time="time"
|
||||||
|
format="DD 天 HH 时 mm 分 ss 秒"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 毫秒级渲染
|
||||||
|
|
||||||
|
倒计时默认每秒渲染一次,设置`millisecond`属性可以开启毫秒级渲染
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-count-down
|
||||||
|
millisecond
|
||||||
|
:time="time"
|
||||||
|
format="HH:mm:ss:SSS"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 自定义样式
|
||||||
|
|
||||||
|
通过插槽自定义倒计时的样式,`timeData`对象格式见下方表格
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-count-down :time="time">
|
||||||
|
<template v-slot="timeData">
|
||||||
|
<span class="item">{{ timeData.hours }}</span>
|
||||||
|
<span class="item">{{ timeData.minutes }}</span>
|
||||||
|
<span class="item">{{ timeData.seconds }}</span>
|
||||||
|
</template>
|
||||||
|
</van-count-down>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.item {
|
||||||
|
display: inline-block;
|
||||||
|
width: 22px;
|
||||||
|
margin-right: 5px;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #1989fa;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 手动控制
|
||||||
|
|
||||||
|
通过 ref 获取到组件实例后,可以调用`start`、`pause`、`reset`方法
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-count-down
|
||||||
|
ref="countDown"
|
||||||
|
millisecond
|
||||||
|
:time="3000"
|
||||||
|
:auto-start="false"
|
||||||
|
format="ss:SSS"
|
||||||
|
@finish="finished"
|
||||||
|
/>
|
||||||
|
<van-grid clickable>
|
||||||
|
<van-grid-item text="开始" icon="play-circle-o" @click="start" />
|
||||||
|
<van-grid-item text="暂停" icon="pause-circle-o" @click="pause" />
|
||||||
|
<van-grid-item text="重置" icon="replay" @click="reset" />
|
||||||
|
</van-grid>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
start() {
|
||||||
|
this.$refs.countDown.start();
|
||||||
|
},
|
||||||
|
pause() {
|
||||||
|
this.$refs.countDown.pause();
|
||||||
|
},
|
||||||
|
reset() {
|
||||||
|
this.$refs.countDown.reset();
|
||||||
|
},
|
||||||
|
finish() {
|
||||||
|
this.$toast('倒计时结束');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### Props
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||||
|
|------|------|------|------|------|
|
||||||
|
| time | 倒计时时长,单位毫秒 | `Number` | - | - |
|
||||||
|
| format | 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒 | `String` | `HH:mm:ss` | - |
|
||||||
|
| auto-start | 是否自动开始倒计时 | `Boolean` | `true` | - |
|
||||||
|
| millisecond | 是否开启毫秒级渲染 | `Boolean` | `false` | - |
|
||||||
|
|
||||||
|
### Events
|
||||||
|
|
||||||
|
| 事件名 | 说明 | 回调参数 |
|
||||||
|
|------|------|------|
|
||||||
|
| finish | 倒计时结束时触发 | - |
|
||||||
|
|
||||||
|
### Slots
|
||||||
|
|
||||||
|
| 名称 | 说明 | slot-scope 参数 |
|
||||||
|
|------|------|------|
|
||||||
|
| default | 自定义内容 | timeData |
|
||||||
|
|
||||||
|
### timeData 格式
|
||||||
|
|
||||||
|
| 名称 | 说明 | 类型 |
|
||||||
|
|------|------|------|
|
||||||
|
| days | 剩余天数 | `number` |
|
||||||
|
| hours | 剩余小时 | `number` |
|
||||||
|
| minutes | 剩余分钟 | `number` |
|
||||||
|
| seconds | 剩余秒数 | `number` |
|
||||||
|
| milliseconds | 剩余毫秒 | `number` |
|
||||||
|
|
||||||
|
### 方法
|
||||||
|
|
||||||
|
通过 ref 可以获取到 CountDown 实例并调用实例方法
|
||||||
|
|
||||||
|
| 方法名 | 参数 | 返回值 | 介绍 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| start | - | - | 开始倒计时 |
|
||||||
|
| pause | - | - | 暂停倒计时 |
|
||||||
|
| reset | - | - | 重设倒计时,若`auto-start`为`true`,重设后会自动开始倒计时 |
|
148
src/count-down/demo/index.vue
Normal file
148
src/count-down/demo/index.vue
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
<template>
|
||||||
|
<demo-section>
|
||||||
|
<demo-block :title="$t('basicUsage')">
|
||||||
|
<van-count-down :time="time" />
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="$t('customFormat')">
|
||||||
|
<van-count-down
|
||||||
|
:time="time"
|
||||||
|
:format="$t('formatWithDay')"
|
||||||
|
/>
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="$t('millisecond')">
|
||||||
|
<van-count-down
|
||||||
|
millisecond
|
||||||
|
:time="time"
|
||||||
|
format="HH:mm:ss:SSS"
|
||||||
|
/>
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="$t('customStyle')">
|
||||||
|
<van-count-down
|
||||||
|
:time="time"
|
||||||
|
>
|
||||||
|
<template v-slot="currentTime">
|
||||||
|
<span class="item">{{ currentTime.hours }}</span>
|
||||||
|
<span class="item">{{ currentTime.minutes }}</span>
|
||||||
|
<span class="item">{{ currentTime.seconds }}</span>
|
||||||
|
</template>
|
||||||
|
</van-count-down>
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="$t('manualControl')">
|
||||||
|
<van-count-down
|
||||||
|
ref="countDown"
|
||||||
|
millisecond
|
||||||
|
:time="manualTime"
|
||||||
|
:auto-start="false"
|
||||||
|
format="ss:SSS"
|
||||||
|
@finish="$toast($t('finished'))"
|
||||||
|
/>
|
||||||
|
<van-grid
|
||||||
|
clickable
|
||||||
|
:column-num="3"
|
||||||
|
>
|
||||||
|
<van-grid-item
|
||||||
|
icon="play-circle-o"
|
||||||
|
:text="$t('start')"
|
||||||
|
@click="start"
|
||||||
|
/>
|
||||||
|
<van-grid-item
|
||||||
|
icon="pause-circle-o"
|
||||||
|
:text="$t('pause')"
|
||||||
|
@click="pause"
|
||||||
|
/>
|
||||||
|
<van-grid-item
|
||||||
|
icon="replay"
|
||||||
|
:text="$t('reset')"
|
||||||
|
@click="reset"
|
||||||
|
/>
|
||||||
|
</van-grid>
|
||||||
|
</demo-block>
|
||||||
|
</demo-section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
i18n: {
|
||||||
|
'zh-CN': {
|
||||||
|
millisecond: '毫秒级渲染',
|
||||||
|
customStyle: '自定义样式',
|
||||||
|
customFormat: '自定义格式',
|
||||||
|
manualControl: '手动控制',
|
||||||
|
formatWithDay: 'DD 天 HH 时 mm 分 ss 秒',
|
||||||
|
add: '延长',
|
||||||
|
reset: '重置',
|
||||||
|
pause: '暂停',
|
||||||
|
start: '开始',
|
||||||
|
finished: '倒计时结束'
|
||||||
|
},
|
||||||
|
'en-US': {
|
||||||
|
millisecond: 'Millisecond',
|
||||||
|
customStyle: 'Custom Style',
|
||||||
|
customFormat: 'Custom Format',
|
||||||
|
manualControl: 'Manual Control',
|
||||||
|
formatWithDay: 'DD Day, HH:mm:ss',
|
||||||
|
add: 'Add',
|
||||||
|
reset: 'Reset',
|
||||||
|
pause: 'Pause',
|
||||||
|
start: 'Start',
|
||||||
|
finished: 'Finished'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
time: 30 * 60 * 60 * 1000,
|
||||||
|
manualTime: 3000
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
start() {
|
||||||
|
this.$refs.countDown.start();
|
||||||
|
},
|
||||||
|
|
||||||
|
pause() {
|
||||||
|
this.$refs.countDown.pause();
|
||||||
|
},
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.$refs.countDown.reset();
|
||||||
|
},
|
||||||
|
|
||||||
|
add() {
|
||||||
|
this.manualTime += 3000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
@import '../../style/var';
|
||||||
|
|
||||||
|
.demo-count-down {
|
||||||
|
background-color: @white;
|
||||||
|
|
||||||
|
.van-count-down {
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
display: inline-block;
|
||||||
|
width: 22px;
|
||||||
|
margin-right: 5px;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: @blue;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.van-grid {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
127
src/count-down/index.js
Normal file
127
src/count-down/index.js
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
import { createNamespace } from '../utils';
|
||||||
|
import { raf, cancelRaf } from '../utils/dom/raf';
|
||||||
|
import { isSameSecond, parseTimeData, parseFormat } from './utils';
|
||||||
|
|
||||||
|
const [createComponent, bem] = createNamespace('count-down');
|
||||||
|
|
||||||
|
export default createComponent({
|
||||||
|
props: {
|
||||||
|
millisecond: Boolean,
|
||||||
|
time: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
format: {
|
||||||
|
type: String,
|
||||||
|
default: 'HH:mm:ss'
|
||||||
|
},
|
||||||
|
autoStart: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
remain: 0
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
timeData() {
|
||||||
|
return parseTimeData(this.remain);
|
||||||
|
},
|
||||||
|
|
||||||
|
formattedTime() {
|
||||||
|
return parseFormat(this.format, this.timeData);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
time: {
|
||||||
|
immediate: true,
|
||||||
|
handler() {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
start() {
|
||||||
|
if (this.counting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.counting = true;
|
||||||
|
this.endTime = Date.now() + this.remain;
|
||||||
|
this.tick();
|
||||||
|
},
|
||||||
|
|
||||||
|
pause() {
|
||||||
|
this.counting = false;
|
||||||
|
cancelRaf(this.rafId);
|
||||||
|
},
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.pause();
|
||||||
|
this.remain = this.time;
|
||||||
|
|
||||||
|
if (this.autoStart) {
|
||||||
|
this.start();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
tick() {
|
||||||
|
if (this.millisecond) {
|
||||||
|
this.microTick();
|
||||||
|
} else {
|
||||||
|
this.macroTick();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
microTick() {
|
||||||
|
this.rafId = raf(() => {
|
||||||
|
this.setRemain(this.getRemain());
|
||||||
|
|
||||||
|
if (this.remain !== 0) {
|
||||||
|
this.microTick();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
macroTick() {
|
||||||
|
this.rafId = raf(() => {
|
||||||
|
const remain = this.getRemain();
|
||||||
|
|
||||||
|
if (!isSameSecond(remain, this.remain) || remain === 0) {
|
||||||
|
this.setRemain(remain);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.remain !== 0) {
|
||||||
|
this.macroTick();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getRemain() {
|
||||||
|
return Math.max(this.endTime - Date.now(), 0);
|
||||||
|
},
|
||||||
|
|
||||||
|
setRemain(remain) {
|
||||||
|
this.remain = remain;
|
||||||
|
|
||||||
|
if (remain === 0) {
|
||||||
|
this.pause();
|
||||||
|
this.$emit('finish');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render(h) {
|
||||||
|
return (
|
||||||
|
<div class={bem()}>
|
||||||
|
{this.slots('default', this.timeData) || this.formattedTime}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
7
src/count-down/index.less
Normal file
7
src/count-down/index.less
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
@import '../style/var';
|
||||||
|
|
||||||
|
.van-count-down {
|
||||||
|
color: @count-down-text-color;
|
||||||
|
font-size: @count-down-font-size;
|
||||||
|
line-height: @count-down-line-height;
|
||||||
|
}
|
35
src/count-down/test/__snapshots__/demo.spec.js.snap
Normal file
35
src/count-down/test/__snapshots__/demo.spec.js.snap
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`renders demo correctly 1`] = `
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<div class="van-count-down">30:00:00</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="van-count-down">01 天 06 时 00 分 00 秒</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="van-count-down">30:00:00:000</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="van-count-down"><span class="item">6</span> <span class="item">0</span> <span class="item">0</span></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="van-count-down">03:000</div>
|
||||||
|
<div class="van-grid van-hairline--top">
|
||||||
|
<div class="van-grid-item" style="flex-basis: 33.333333333333336%;">
|
||||||
|
<div class="van-grid-item__content van-grid-item__content--center van-grid-item__content--clickable van-hairline"><i class="van-icon van-icon-play-circle-o van-grid-item__icon">
|
||||||
|
<!----></i><span class="van-grid-item__text">开始</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="van-grid-item" style="flex-basis: 33.333333333333336%;">
|
||||||
|
<div class="van-grid-item__content van-grid-item__content--center van-grid-item__content--clickable van-hairline"><i class="van-icon van-icon-pause-circle-o van-grid-item__icon">
|
||||||
|
<!----></i><span class="van-grid-item__text">暂停</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="van-grid-item" style="flex-basis: 33.333333333333336%;">
|
||||||
|
<div class="van-grid-item__content van-grid-item__content--center van-grid-item__content--clickable van-hairline"><i class="van-icon van-icon-replay van-grid-item__icon">
|
||||||
|
<!----></i><span class="van-grid-item__text">重置</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
4
src/count-down/test/demo.spec.js
Normal file
4
src/count-down/test/demo.spec.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import Demo from '../demo';
|
||||||
|
import demoTest from '../../../test/demo-test';
|
||||||
|
|
||||||
|
demoTest(Demo);
|
65
src/count-down/utils.ts
Normal file
65
src/count-down/utils.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { padZero } from '../utils/format/string';
|
||||||
|
|
||||||
|
export type TimeData = {
|
||||||
|
days: number;
|
||||||
|
hours: number;
|
||||||
|
minutes: number;
|
||||||
|
seconds: number;
|
||||||
|
milliseconds: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const SECOND = 1000;
|
||||||
|
const MINUTE = 60 * SECOND;
|
||||||
|
const HOUR = 60 * MINUTE;
|
||||||
|
const DAY = 24 * HOUR;
|
||||||
|
|
||||||
|
export function parseTimeData(time: number): TimeData {
|
||||||
|
const days = Math.floor(time / DAY);
|
||||||
|
const hours = Math.floor((time % DAY) / HOUR);
|
||||||
|
const minutes = Math.floor((time % HOUR) / MINUTE);
|
||||||
|
const seconds = Math.floor((time % MINUTE) / SECOND);
|
||||||
|
const milliseconds = Math.floor(time % SECOND);
|
||||||
|
|
||||||
|
return {
|
||||||
|
days,
|
||||||
|
hours,
|
||||||
|
minutes,
|
||||||
|
seconds,
|
||||||
|
milliseconds
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseFormat(format: string, timeData: TimeData): string {
|
||||||
|
const { days } = timeData;
|
||||||
|
let { hours, minutes, seconds, milliseconds } = timeData;
|
||||||
|
|
||||||
|
if (format.indexOf('DD') === -1) {
|
||||||
|
hours += days * 24;
|
||||||
|
} else {
|
||||||
|
format = format.replace('DD', padZero(days));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format.indexOf('HH') === -1) {
|
||||||
|
minutes += hours * 60;
|
||||||
|
} else {
|
||||||
|
format = format.replace('HH', padZero(hours));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format.indexOf('mm') === -1) {
|
||||||
|
seconds += minutes * 60;
|
||||||
|
} else {
|
||||||
|
format = format.replace('mm', padZero(minutes));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format.indexOf('ss') === -1) {
|
||||||
|
milliseconds += seconds * 1000;
|
||||||
|
} else {
|
||||||
|
format = format.replace('ss', padZero(seconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
return format.replace('SSS', padZero(milliseconds, 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isSameSecond(time1: number, time2: number): boolean {
|
||||||
|
return Math.floor(time1 / 1000) === Math.floor(time2 / 1000);
|
||||||
|
}
|
@ -13,6 +13,7 @@
|
|||||||
@import './image/index';
|
@import './image/index';
|
||||||
@import './circle/index';
|
@import './circle/index';
|
||||||
@import './collapse-item/index';
|
@import './collapse-item/index';
|
||||||
|
@import './count-down/index';
|
||||||
@import './divider/index';
|
@import './divider/index';
|
||||||
@import './list/index';
|
@import './list/index';
|
||||||
@import './nav-bar/index';
|
@import './nav-bar/index';
|
||||||
|
@ -18,6 +18,7 @@ import CollapseItem from './collapse-item';
|
|||||||
import ContactCard from './contact-card';
|
import ContactCard from './contact-card';
|
||||||
import ContactEdit from './contact-edit';
|
import ContactEdit from './contact-edit';
|
||||||
import ContactList from './contact-list';
|
import ContactList from './contact-list';
|
||||||
|
import CountDown from './count-down';
|
||||||
import Coupon from './coupon';
|
import Coupon from './coupon';
|
||||||
import CouponCell from './coupon-cell';
|
import CouponCell from './coupon-cell';
|
||||||
import CouponList from './coupon-list';
|
import CouponList from './coupon-list';
|
||||||
@ -107,6 +108,7 @@ const components = [
|
|||||||
ContactCard,
|
ContactCard,
|
||||||
ContactEdit,
|
ContactEdit,
|
||||||
ContactList,
|
ContactList,
|
||||||
|
CountDown,
|
||||||
Coupon,
|
Coupon,
|
||||||
CouponCell,
|
CouponCell,
|
||||||
CouponList,
|
CouponList,
|
||||||
@ -201,6 +203,7 @@ export {
|
|||||||
ContactCard,
|
ContactCard,
|
||||||
ContactEdit,
|
ContactEdit,
|
||||||
ContactList,
|
ContactList,
|
||||||
|
CountDown,
|
||||||
Coupon,
|
Coupon,
|
||||||
CouponCell,
|
CouponCell,
|
||||||
CouponList,
|
CouponList,
|
||||||
|
@ -143,7 +143,7 @@ export default {
|
|||||||
|
|
||||||
### Radio Slots
|
### Radio Slots
|
||||||
|
|
||||||
| 名称 | 说明 | slot-scope |
|
| 名称 | 说明 | slot-scope 参数 |
|
||||||
|------|------|------|
|
|------|------|------|
|
||||||
| default | 自定义文本 | - |
|
| default | 自定义文本 | - |
|
||||||
| icon | 自定义图标 | checked: 是否为选中状态 |
|
| icon | 自定义图标 | checked: 是否为选中状态 |
|
||||||
|
@ -166,6 +166,11 @@
|
|||||||
@contact-list-add-button-z-index: 9999;
|
@contact-list-add-button-z-index: 9999;
|
||||||
@contact-list-item-padding: 15px;
|
@contact-list-item-padding: 15px;
|
||||||
|
|
||||||
|
// CountDown
|
||||||
|
@count-down-text-color: @text-color;
|
||||||
|
@count-down-font-size: 14px;
|
||||||
|
@count-down-line-height: 20px;
|
||||||
|
|
||||||
// Coupon
|
// Coupon
|
||||||
@coupon-margin: 0 15px 15px;
|
@coupon-margin: 0 15px 15px;
|
||||||
@coupon-content-height: 100px;
|
@coupon-content-height: 100px;
|
||||||
|
@ -4,6 +4,12 @@ export function camelize(str: string): string {
|
|||||||
return str.replace(camelizeRE, (_, c) => c.toUpperCase());
|
return str.replace(camelizeRE, (_, c) => c.toUpperCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
export function padZero(num: number | string): string {
|
export function padZero(num: number | string, targetLength = 2): string {
|
||||||
return (num < 10 ? '0' : '') + num;
|
let str = num + '';
|
||||||
|
|
||||||
|
while (str.length < targetLength) {
|
||||||
|
str = '0' + str;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
|
1
types/index.d.ts
vendored
1
types/index.d.ts
vendored
@ -17,6 +17,7 @@ export class Button extends VanComponent {}
|
|||||||
export class Card extends VanComponent {}
|
export class Card extends VanComponent {}
|
||||||
export class Cell extends VanComponent {}
|
export class Cell extends VanComponent {}
|
||||||
export class CellGroup extends VanComponent {}
|
export class CellGroup extends VanComponent {}
|
||||||
|
export class CountDown extends VanComponent {}
|
||||||
export class Divider extends VanComponent {}
|
export class Divider extends VanComponent {}
|
||||||
export class SwipeCell extends VanComponent {}
|
export class SwipeCell extends VanComponent {}
|
||||||
export class Checkbox extends VanComponent {}
|
export class Checkbox extends VanComponent {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user