Skip to content

Commit

Permalink
feat(countdown): i18n and refactor the way of formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
BeADre committed Mar 10, 2021
1 parent 5851cbb commit 7be2461
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 97 deletions.
99 changes: 25 additions & 74 deletions packages/varlet-ui/src/countdown/Countdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,14 @@

<script lang="ts">
import { defineComponent, Ref, ref, watch } from 'vue'
import dayjs, { UnitTypeLongPlural } from 'dayjs'
import duration, { Duration } from 'dayjs/plugin/duration'
import { props } from './props'
import { requestAnimationFrame, cancelAnimationFrame } from '../utils/elements'
import { toNumber } from '../utils/shared'
import { toNumber, parseFormat, Time } from '../utils/shared'
dayjs.extend(duration)
type Format = {
DD: Duration['asDays']
HH: Duration['asHours']
mm: Duration['asMinutes']
ss: Duration['asSeconds']
}
type TimeData = Exclude<UnitTypeLongPlural, 'months' | 'years' | 'dates'>
const SECOND = 1000
const MINUTE = 60 * SECOND
const HOUR = 60 * MINUTE
const DAY = 24 * HOUR
export default defineComponent({
name: 'VarCountdown',
Expand All @@ -34,77 +26,36 @@ export default defineComponent({
const showTime: Ref<string> = ref('')
const handle: Ref<number> = ref(0)
const pauseTime: Ref<number> = ref(0)
const timeData: Ref<Record<TimeData, number>> = ref({
days: 0,
hours: 0,
minutes: 0,
seconds: 0,
milliseconds: 0,
})
const isSameTime = (durationTime: number, newFormat: string): boolean => {
if (!showTime.value) return true
return showTime.value === dayjs.duration(durationTime).format(newFormat)
}
const replaceValue = (milliseconds: number, fixedLength: number): string => {
const len = `${milliseconds}`.length
if (fixedLength === 3) {
return len === 1 ? `00${milliseconds}` : len === 2 ? `0${milliseconds}` : `${milliseconds}`
}
const sliceMilliseconds = `${milliseconds}`.slice(0, 2)
return len === 1 ? `0${sliceMilliseconds}` : `${sliceMilliseconds}`
}
const formatMilliseconds = (milliseconds: number, newFormat: string): string => {
let time = newFormat
if (time.includes('SSS')) time = time.replaceAll('SSS', replaceValue(milliseconds, 3))
if (time.includes('SS')) time = (time || time).replaceAll('SS', replaceValue(milliseconds, 2))
if (time.includes('S')) time = (time || time).replaceAll('S', `${milliseconds}`.slice(0, 1))
return time
}
const formatTime = (type: keyof Format, durationTime: number) => {
const duration = dayjs.duration(durationTime)
const format: Format = {
DD: duration.asDays,
HH: duration.asHours,
mm: duration.asMinutes,
ss: duration.asSeconds,
const timeData: Ref<Partial<Record<keyof Time, number>>> = ref({})
const formatTime = (durationTime: number) => {
const days = Math.floor(durationTime / DAY)
const hours = Math.floor((durationTime % DAY) / HOUR)
const minutes = Math.floor((durationTime % HOUR) / MINUTE)
const seconds = Math.floor((durationTime % MINUTE) / SECOND)
const milliseconds = Math.floor(durationTime % SECOND)
const time = {
days,
hours,
minutes,
seconds,
milliseconds,
}
const millis = duration.milliseconds()
const method = format[type].bind(duration)
let roundTime = `${Math.floor(method())}`
roundTime = +roundTime < 10 ? `0${roundTime}` : roundTime
let newFormat = props.format.replaceAll(type, roundTime)
newFormat = formatMilliseconds(millis, newFormat)
timeData.value = {
days: duration.days(),
hours: duration.hours(),
minutes: duration.minutes(),
seconds: duration.seconds(),
milliseconds: duration.milliseconds(),
}
if (!isSameTime(durationTime, newFormat)) props.onChange?.(timeData.value)
showTime.value = duration.format(newFormat)
timeData.value = time
props.onChange?.(timeData.value)
showTime.value = parseFormat(props.format, time)
}
const countdown = () => {
const { format, time, onEnd, autoStart } = props
const { time, onEnd, autoStart } = props
const now = Date.now()
if (!endTime.value) endTime.value = now + toNumber(time)
let durationTime = endTime.value - now
if (durationTime < 0) durationTime = 0
pauseTime.value = durationTime
if (format.includes('DD')) formatTime('DD', durationTime)
else if (format.includes('HH')) formatTime('HH', durationTime)
else if (format.includes('mm')) formatTime('mm', durationTime)
else if (format.includes('ss')) formatTime('ss', durationTime)
else showTime.value = `${durationTime}`
formatTime(durationTime)
if (durationTime === 0) {
onEnd?.()
Expand Down
2 changes: 1 addition & 1 deletion packages/varlet-ui/src/countdown/docs/en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Use `time` to set countdown time(ms).
Use `format` to set time text.

```html
<var-countdown :time="time" format="DD HH 时 mm 分 ss 秒" />
<var-countdown :time="time" format="DD Day, HH:mm:ss" />
```

### Show Millisecond
Expand Down
25 changes: 16 additions & 9 deletions packages/varlet-ui/src/countdown/example/index.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
<template>
<div>
<app-type>基本使用</app-type>
<app-type>{{ pack.basicUsage }}</app-type>
<var-countdown time="108000000" />
</div>
<div>
<app-type>自定义格式</app-type>
<var-countdown time="108000000" format="DD 天 HH 时 mm 分 ss 秒" />
<app-type>{{ pack.customFormat }}</app-type>
<var-countdown time="108000000" :format="pack.format" />
</div>
<div>
<app-type>显示毫秒</app-type>
<app-type>{{ pack.showMillisecond }}</app-type>
<var-countdown time="108000000" format="HH : mm : ss : SS" />
</div>
<div>
<app-type>自定义样式</app-type>
<app-type>{{ pack.customStyle }}</app-type>
<var-countdown time="108000000">
<template #default="timeData">
<span class="block">{{ timeData.hours }}</span>
Expand All @@ -24,27 +24,31 @@
</var-countdown>
</div>
<div>
<app-type>手动控制</app-type>
<app-type>{{ pack.manualControl }}</app-type>
<var-countdown :time="time" ref="countdown" :auto-start="false" format="ss : SSS" @end="end" @change="change" />
<div class="btn-container">
<var-button type="primary" @click="$refs.countdown.start()">开始</var-button>
<var-button @click="$refs.countdown.pause()">暂停</var-button>
<var-button @click="$refs.countdown.reset()">重置</var-button>
<var-button type="primary" @click="$refs.countdown.start()">{{ pack.startText }}</var-button>
<var-button @click="$refs.countdown.pause()">{{ pack.pauseText }}</var-button>
<var-button @click="$refs.countdown.reset()">{{ pack.resetText }}</var-button>
</div>
</div>
</template>

<script>
import { defineComponent, ref } from 'vue'
import AppType from '@varlet/cli/site/mobile/components/AppType'
import Countdown from '..'
import Snackbar from '../../snackbar'
import Button from '../../button'
import { pack, use } from './locale'
import { watchLang } from '../../utils/components'
export default defineComponent({
name: 'CountdownExample',
components: {
[Countdown.name]: Countdown,
[Button.name]: Button,
AppType,
},
setup() {
const countdown = ref(null)
Expand All @@ -57,8 +61,11 @@ export default defineComponent({
console.log('change')
}
watchLang(use)
return {
time,
pack,
end,
countdown,
change,
Expand Down
11 changes: 11 additions & 0 deletions packages/varlet-ui/src/countdown/example/locale/en-US.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export default {
basicUsage: 'Basic Usage',
customFormat: 'Custom Format',
showMillisecond: 'Show Millisecond',
customStyle: 'Custom Style',
manualControl: 'Manual Control',
format: 'DD Day, HH:mm:ss',
startText: 'Start',
pauseText: 'Pause',
resetText: 'Reset',
}
23 changes: 23 additions & 0 deletions packages/varlet-ui/src/countdown/example/locale/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// lib
import _zhCN from '../../../locale/zh-CN'
import _enCN from '../../../locale/en-US'
// mobile example doc
import zhCN from './zh-CN'
import enUS from './en-US'
import { useLocale, add as _add, use as _use } from '../../../locale'

const { add, use: exampleUse, pack, packs, merge } = useLocale()

const use = (lang: string) => {
_use(lang)
exampleUse(lang)
}

export { add, pack, packs, merge, use }

// lib
_add('zh-CN', _zhCN)
_add('en-US', _enCN)
// mobile example doc
add('zh-CN', zhCN)
add('en-US', enUS)
11 changes: 11 additions & 0 deletions packages/varlet-ui/src/countdown/example/locale/zh-CN.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export default {
basicUsage: '基本使用',
customFormat: '自定义格式',
showMillisecond: '显示毫秒',
customStyle: '自定义样式',
manualControl: '手动控制',
format: 'DD 天 HH 时 mm 分 ss 秒',
startText: '开始',
pauseText: '暂停',
resetText: '重置',
}
2 changes: 1 addition & 1 deletion packages/varlet-ui/src/countdown/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const props = {
},
format: {
type: String,
default: 'HH:mm:ss',
default: 'HH : mm : ss',
},
autoStart: {
type: Boolean,
Expand Down
24 changes: 12 additions & 12 deletions packages/varlet-ui/src/utils/shared.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
export type Time = {
days: number
hours: number
minutes: number
seconds: number
milliseconds: number
}

export interface CacheInstance<T> {
cache: T[]

Expand Down Expand Up @@ -76,7 +84,7 @@ export const throttle = (method: any, mustRunDelay = 200): (() => void) => {
export const debounce = (method: any, delay = 200) => {
let timer: number

return function(this: unknown, ...args: any[]) {
return function (this: unknown, ...args: any[]) {
timer && window.clearTimeout(timer)
timer = window.setTimeout(() => {
method.apply(this, args)
Expand Down Expand Up @@ -117,7 +125,7 @@ export const createCache = <T>(max: number): CacheInstance<T> => {

remove(key: T) {
this.has(key) && removeItem(this.cache, key)
}
},
}
}

Expand All @@ -126,16 +134,8 @@ export const cubic = (value: number): number => value ** 3
export const easeInOutCubic = (value: number): number =>
value < 0.5 ? cubic(value * 2) / 2 : 1 - cubic((1 - value) * 2) / 2

export function parseFormat(format: string, time: {
days: string
hours: string
minutes: string
seconds: string
milliseconds: string
}): string {
const { days, hours, minutes, seconds, milliseconds } = time

const scannedTimes: number[] = [days, hours, minutes, seconds, milliseconds].map(toNumber)
export function parseFormat(format: string, time: Time): string {
const scannedTimes = Object.values(time)
const scannedFormats = ['DD', 'HH', 'mm', 'ss']
const padValues = [24, 60, 60, 1000]

Expand Down

0 comments on commit 7be2461

Please sign in to comment.