mirror of
https://gitee.com/wot-design-uni/wot-design-uni.git
synced 2025-12-06 17:18:40 +08:00
feat: ✨ DatetimePicker 支持time和date-time类型下配置选择到秒 (#1117)
✅ Closes: #844
This commit is contained in:
parent
60261374ac
commit
f2e8fdad80
@ -64,10 +64,30 @@ const value = ref<number>(Date.now())
|
||||
const value4 = ref<string>('11:12')
|
||||
```
|
||||
|
||||
## time 类型(带秒)
|
||||
|
||||
`time` 类型设置 `use-second` 属性可以展示时分秒,绑定值为 `HH:mm:ss` 格式。
|
||||
|
||||
```html
|
||||
<wd-datetime-picker-view type="time" v-model="value" label="时分秒" use-second />
|
||||
```
|
||||
```typescript
|
||||
const value = ref<string>('11:12:30')
|
||||
```
|
||||
|
||||
## datetime 类型(带秒)
|
||||
|
||||
`datetime` 类型设置 `use-second` 属性可以展示年月日时分秒,绑定值为时间戳。
|
||||
|
||||
```html
|
||||
<wd-datetime-picker-view type="datetime" v-model="value" label="年月日时分秒" use-second />
|
||||
```
|
||||
```typescript
|
||||
const value = ref<number>(Date.now())
|
||||
```
|
||||
|
||||
## 修改内部格式
|
||||
|
||||
|
||||
|
||||
给 `formatter` 属性传入一个函数,接收 `type` 和 `value` 值,返回展示的文本内容。`type` 有 `year`、`month`、`date`、`hour`、`minute` 类型,`value` 为 `number` 类型。
|
||||
使用自定义`formatter`会关闭内置的默认`display-format`函数。
|
||||
|
||||
@ -133,6 +153,8 @@ const filter = (type, values) => {
|
||||
| minMinute | 最小分钟,time类型时生效 | number | - | 0 | - |
|
||||
| maxMinute | 最大分钟,time类型时生效 | number | - | 59 | - |
|
||||
| immediate-change | 是否在手指松开时立即触发picker-view的 change 事件。若不开启则会在滚动动画结束后触发 change 事件,1.2.25版本起提供,仅微信小程序和支付宝小程序支持。 | boolean | - | false | 1.2.25 |
|
||||
| use-second | 是否显示秒选择,仅在 time 和 datetime 类型下生效 | boolean | - | false | $LOWEST_VERSION$ |
|
||||
|
||||
## Events
|
||||
|
||||
| 事件名称 | 说明 | 参数 | 最低版本 |
|
||||
|
||||
@ -78,6 +78,28 @@ const value = ref<number>(Date.now())
|
||||
const value4 = ref<string>('09:20')
|
||||
```
|
||||
|
||||
## time 类型(带秒)
|
||||
|
||||
`time` 类型设置 `use-second` 属性可以展示时分秒,绑定值为 `HH:mm:ss` 格式。
|
||||
|
||||
```html
|
||||
<wd-datetime-picker type="time" v-model="value" label="时分秒" use-second />
|
||||
```
|
||||
```typescript
|
||||
const value = ref<string>('09:20:30')
|
||||
```
|
||||
|
||||
## datetime 类型(带秒)
|
||||
|
||||
`datetime` 类型设置 `use-second` 属性可以展示年月日时分秒,绑定值为时间戳。
|
||||
|
||||
```html
|
||||
<wd-datetime-picker type="datetime" v-model="value" label="年月日时分秒" use-second />
|
||||
```
|
||||
```typescript
|
||||
const value = ref<number>(Date.now())
|
||||
```
|
||||
|
||||
## 修改展示格式
|
||||
|
||||
|
||||
@ -295,6 +317,7 @@ const displayFormatTabLabel = (items) => {
|
||||
| prop | 表单域 `model` 字段名,在使用表单校验功能的情况下,该属性是必填的 | string | - | - | - |
|
||||
| rules | 表单验证规则,结合`wd-form`组件使用 | `FormItemRule []` | - | `[]` | - |
|
||||
| immediate-change | 是否在手指松开时立即触发picker-view的 change 事件。若不开启则会在滚动动画结束后触发 change 事件,1.2.25版本起提供,仅微信小程序和支付宝小程序支持。 | boolean | - | false | 1.2.25 |
|
||||
| use-second | 是否显示秒选择,仅在 time 和 datetime 类型下生效 | boolean | - | false | $LOWEST_VERSION$ |
|
||||
|
||||
### FormItemRule 数据结构
|
||||
|
||||
|
||||
@ -65,6 +65,28 @@ const value = ref<number>(Date.now())
|
||||
const value4 = ref<string>('11:12')
|
||||
```
|
||||
|
||||
## Time Type (with Seconds)
|
||||
|
||||
`time` type with `use-second` property displays hour, minute and second, the binding value is in `HH:mm:ss` format.
|
||||
|
||||
```html
|
||||
<wd-datetime-picker-view type="time" v-model="value" label="Hour Minute Second" use-second />
|
||||
```
|
||||
```typescript
|
||||
const value = ref<string>('11:12:30')
|
||||
```
|
||||
|
||||
## Datetime Type (with Seconds)
|
||||
|
||||
`datetime` type with `use-second` property displays year, month, day, hour, minute and second, the binding value is timestamp.
|
||||
|
||||
```html
|
||||
<wd-datetime-picker-view type="datetime" v-model="value" label="Year Month Day Hour Minute Second" use-second />
|
||||
```
|
||||
```typescript
|
||||
const value = ref<number>(Date.now())
|
||||
```
|
||||
|
||||
## Modify Internal Format
|
||||
|
||||
Pass a function to the `formatter` property, which receives `type` and `value` values and returns the display text content. `type` can be `year`, `month`, `date`, `hour`, `minute`, and `value` is of type `number`.
|
||||
@ -131,6 +153,7 @@ const filter = (type, values) => {
|
||||
| minMinute | Minimum minute, effective for time type | number | - | 0 | - |
|
||||
| maxMinute | Maximum minute, effective for time type | number | - | 59 | - |
|
||||
| immediate-change | Whether to trigger the picker-view's change event immediately when the finger is released. If not enabled, the change event will be triggered after the scrolling animation ends. Available from version 1.2.25, only supported on WeChat Mini Program and Alipay Mini Program. | boolean | - | false | 1.2.25 |
|
||||
| use-second | Whether to display the second selection, only effective for time and datetime types | boolean | - | false | $LOWEST_VERSION$ |
|
||||
|
||||
## Events
|
||||
|
||||
|
||||
@ -78,6 +78,28 @@ const value = ref<number>(Date.now())
|
||||
const value4 = ref<string>('09:20')
|
||||
```
|
||||
|
||||
## Time Type (with Seconds)
|
||||
|
||||
`time` type with `use-second` property displays hour, minute and second, the binding value is in `HH:mm:ss` format.
|
||||
|
||||
```html
|
||||
<wd-datetime-picker type="time" v-model="value" label="Hour Minute Second" use-second />
|
||||
```
|
||||
```typescript
|
||||
const value = ref<string>('09:20:30')
|
||||
```
|
||||
|
||||
## Datetime Type (with Seconds)
|
||||
|
||||
`datetime` type with `use-second` property displays year, month, day, hour, minute and second, the binding value is timestamp.
|
||||
|
||||
```html
|
||||
<wd-datetime-picker type="datetime" v-model="value" label="Year Month Day Hour Minute Second" use-second />
|
||||
```
|
||||
```typescript
|
||||
const value = ref<number>(Date.now())
|
||||
```
|
||||
|
||||
## Modify Display Format
|
||||
|
||||
Pass a function to the `display-format` property, which receives an array of all selected items and returns the display text content.
|
||||
@ -290,6 +312,7 @@ const displayFormatTabLabel = (items) => {
|
||||
| prop | Form field `model` field name, required when using form validation | string | - | - | - |
|
||||
| rules | Form validation rules, used with `wd-form` component | `FormItemRule []` | - | `[]` | - |
|
||||
| immediate-change | Whether to trigger the picker-view's change event immediately when the finger is released. If not enabled, the change event will be triggered after the scrolling animation ends. Available from version 1.2.25, only supported on WeChat Mini Program and Alipay Mini Program. | boolean | - | false | 1.2.25 |
|
||||
| use-second | Whether to display the second selection, only effective for time and datetime types | boolean | - | false | $LOWEST_VERSION$ |
|
||||
|
||||
### FormItemRule Data Structure
|
||||
|
||||
|
||||
@ -969,6 +969,7 @@
|
||||
"ri-qi-xuan-ze-1": "Date selection",
|
||||
"ri-qi-xuan-ze-2": "Date selection",
|
||||
"ri-qi-xuan-ze-3": "Date selection",
|
||||
"ri-qi-xuan-ze-dai-miao": "Date selection (with seconds)",
|
||||
"ri-zhou-yue-qie-huan": "Day Week Month Switching",
|
||||
"ring-lei-xing-loading": "Ring type loading",
|
||||
"ru-ding-dan-chu-yu-zan-ting-zhuang-tai-jin-ru-wo-de-ding-dan-ye-mian-zhao-dao-yao-qu-xiao-de-ding-dan-dian-ji-qu-xiao-ding-dan-an-niu-xuan-ze-ding-dan-qu-xiao-yuan-yin-hou-dian-ji-xia-yi-bu-ti-jiao-shen-qing-ji-ke": "If the order is in a suspended state, go to the \"My Orders\" page, find the order you want to cancel, and click the \"Cancel Order\" button; After selecting the reason for canceling the order, click \"Next\" to submit the application.",
|
||||
@ -1035,6 +1036,7 @@
|
||||
"shi-jian-fan-wei-yi-nian": "Time Range: One Year",
|
||||
"shi-jian-he-di-zhi": "Time and Address",
|
||||
"shi-jian-lei-xing": "TIME",
|
||||
"shi-jian-xuan-ze-dai-miao": "Time selection (with seconds)",
|
||||
"shi-jiao-xiao-yan": "Out of focus verification",
|
||||
"shi-jiao-xiao-yan-0": "Out of focus verification",
|
||||
"shi-jing-shan-qu": "SHIJINGSHAN",
|
||||
|
||||
@ -969,6 +969,7 @@
|
||||
"ri-qi-xuan-ze-1": "日期选择",
|
||||
"ri-qi-xuan-ze-2": "日期选择",
|
||||
"ri-qi-xuan-ze-3": "日期选择",
|
||||
"ri-qi-xuan-ze-dai-miao": "日期选择(带秒)",
|
||||
"ri-zhou-yue-qie-huan": "日周月切换",
|
||||
"ring-lei-xing-loading": "ring类型loading",
|
||||
"ru-ding-dan-chu-yu-zan-ting-zhuang-tai-jin-ru-wo-de-ding-dan-ye-mian-zhao-dao-yao-qu-xiao-de-ding-dan-dian-ji-qu-xiao-ding-dan-an-niu-xuan-ze-ding-dan-qu-xiao-yuan-yin-hou-dian-ji-xia-yi-bu-ti-jiao-shen-qing-ji-ke": "如订单处于暂停状态,进入“我的订单”页面,找到要取消的订单,点击“取消订单”按钮;选择订单取消原因后,点击“下一步”提交申请即可。",
|
||||
@ -1035,6 +1036,7 @@
|
||||
"shi-jian-fan-wei-yi-nian": "时间范围一年",
|
||||
"shi-jian-he-di-zhi": "时间和地址",
|
||||
"shi-jian-lei-xing": "时间类型",
|
||||
"shi-jian-xuan-ze-dai-miao": "时间选择(带秒)",
|
||||
"shi-jiao-xiao-yan": "失焦校验",
|
||||
"shi-jiao-xiao-yan-0": "失焦校验",
|
||||
"shi-jing-shan-qu": "石景山区",
|
||||
|
||||
@ -4,10 +4,12 @@
|
||||
<demo-block transparent>
|
||||
<wd-cell-group border>
|
||||
<wd-datetime-picker :label="$t('ri-qi-xuan-ze')" v-model="value1" @confirm="handleConfirm1" />
|
||||
<wd-datetime-picker :label="$t('ri-qi-xuan-ze-dai-miao')" use-second v-model="value18" />
|
||||
<wd-datetime-picker :label="$t('nian-yue-ri')" v-model="value2" type="date" @confirm="handleConfirm2" />
|
||||
<wd-datetime-picker :label="$t('nian-yue')" v-model="value3" type="year-month" @confirm="handleConfirm3" />
|
||||
<wd-datetime-picker :label="$t('nian')" v-model="value16" type="year" @confirm="handleConfirm16" />
|
||||
<wd-datetime-picker :label="$t('shi-fen')" v-model="value4" type="time" @confirm="handleConfirm4" />
|
||||
<wd-datetime-picker :label="$t('shi-jian-xuan-ze-dai-miao')" v-model="value19" type="time" use-second />
|
||||
<wd-datetime-picker :label="$t('zhan-shi-ge-shi')" v-model="value5" :display-format="displayFormat" @confirm="handleConfirm5" />
|
||||
<wd-datetime-picker :label="$t('nei-bu-ge-shi')" v-model="value6" :formatter="formatter" @confirm="handleConfirm6" />
|
||||
<wd-datetime-picker :label="$t('guo-lv-xuan-xiang')" v-model="value7" :filter="filter" @confirm="handleConfirm7" />
|
||||
@ -34,7 +36,13 @@
|
||||
<wd-datetime-picker :label="$t('ri-qi-xuan-ze-1')" align-right v-model="value13" @confirm="handleConfirm13" />
|
||||
</demo-block>
|
||||
<demo-block :title="$t('qu-yu-xuan-ze')" transparent>
|
||||
<wd-datetime-picker :label="$t('ri-qi-xuan-ze-2')" :title="$t('qing-xuan-ze-qu-jian')" v-model="value14" @confirm="handleConfirm14" />
|
||||
<wd-datetime-picker
|
||||
:label="$t('ri-qi-xuan-ze-2')"
|
||||
:title="$t('qing-xuan-ze-qu-jian')"
|
||||
v-model="value14"
|
||||
use-second
|
||||
@confirm="handleConfirm14"
|
||||
/>
|
||||
</demo-block>
|
||||
<demo-block :title="$t('fan-wei-tab-zhan-shi-ge-shi')" transparent>
|
||||
<wd-datetime-picker
|
||||
@ -76,7 +84,8 @@ const value14 = ref<any[]>(['', ''])
|
||||
const value15 = ref<any[]>(['', Date.now()])
|
||||
const value16 = ref(Date.now())
|
||||
const value17 = ref(Date.now())
|
||||
|
||||
const value18 = ref(Date.now())
|
||||
const value19 = ref('09:20:26')
|
||||
const minDate = ref<number>(Date.now())
|
||||
const maxDate = ref<number>(new Date(new Date().getFullYear() + 1, new Date().getMonth(), new Date().getDate()).getTime())
|
||||
|
||||
|
||||
@ -5,6 +5,10 @@
|
||||
<wd-datetime-picker-view v-model="value1" @change="onChange1" />
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('ri-qi-xuan-ze-dai-miao')" transparent>
|
||||
<wd-datetime-picker-view v-model="value8" use-second />
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('nian-yue-ri')" transparent>
|
||||
<wd-datetime-picker-view type="date" v-model="value2" @change="onChange2" />
|
||||
</demo-block>
|
||||
@ -21,6 +25,10 @@
|
||||
<wd-datetime-picker-view type="time" v-model="value4" @change="onChange4" />
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('shi-jian-xuan-ze-dai-miao')" transparent>
|
||||
<wd-datetime-picker-view type="time" v-model="value9" use-second @change="onChange4" />
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('nei-bu-ge-shi')" transparent>
|
||||
<wd-datetime-picker-view v-model="value5" :formatter="formatter" @change="onChange5" />
|
||||
</demo-block>
|
||||
@ -44,6 +52,9 @@ const value4 = ref<string>('11:12')
|
||||
const value5 = ref<number>(Date.now())
|
||||
const value6 = ref<number>(Date.now())
|
||||
const value7 = ref<string>('')
|
||||
const value8 = ref<number>(Date.now())
|
||||
const value9 = ref<string>('11:12:13')
|
||||
|
||||
const formatter: DatetimePickerViewFormatter = (type, value) => {
|
||||
switch (type) {
|
||||
case 'year':
|
||||
|
||||
@ -84,6 +84,7 @@ $-fw-semibold: var(--wot-fw-semibold, 600) !default; // PingFangSC-Semibold
|
||||
|
||||
/* 尺寸 */
|
||||
$-size-side-padding: var(--wot-size-side-padding, 15px) !default; // 屏幕两边留白
|
||||
$-size-side-padding-small: var(--wot-size-side-padding-small, 6px) !default; // 屏幕两边留白小值
|
||||
|
||||
/*-------------------------------- Theme color application size. end --------------------------------*/
|
||||
|
||||
@ -438,7 +439,7 @@ $-picker-column-height: var(--wot-picker-column-height, 210px) !default; // 列
|
||||
$-picker-column-item-height: var(--wot-picker-column-item-height, 35px) !default; // 列高 滚筒外部的高度
|
||||
$-picker-column-select-bg: var(--wot-picker-column-select-bg, #f5f5f5) !default;
|
||||
$-picker-loading-button-color: var(--wot-picker-loading-button-color, rgba(0, 0, 0, 0.25)) !default; // loading 背景颜色
|
||||
$-picker-column-padding: var(--wot-picker-column-padding, 0 $-size-side-padding) !default; // 选项内间距
|
||||
$-picker-column-padding: var(--wot-picker-column-padding, 0 $-size-side-padding-small) !default; // 选项内间距
|
||||
|
||||
$-picker-column-disabled-color: var(--wot-picker-column-disabled-color, rgba(0, 0, 0, 0.25)) !default; // 选择器选项禁用的颜色
|
||||
$-picker-mask: var(--wot-picker-mask, linear-gradient(180deg, hsla(0, 0%, 100%, 0.9), hsla(0, 0%, 100%, 0.25)))
|
||||
|
||||
@ -3,29 +3,6 @@ import { baseProps, makeBooleanProp, makeNumberProp, makeRequiredProp, makeStrin
|
||||
|
||||
export type DateTimeType = 'date' | 'year-month' | 'time' | 'datetime' | 'year'
|
||||
|
||||
/**
|
||||
* @description 根据传入的值和类型,获取当前的选项数组,便于传入 pickerView
|
||||
* @param value
|
||||
* @param type picker类型
|
||||
* @return {Array} pickerValue
|
||||
*/
|
||||
export function getPickerValue(value: string | number, type: DateTimeType) {
|
||||
const values: number[] = []
|
||||
const date = new Date(value)
|
||||
if (type === 'time') {
|
||||
const pair = String(value).split(':')
|
||||
values.push(parseInt(pair[0]), parseInt(pair[1]))
|
||||
} else {
|
||||
values.push(date.getFullYear(), date.getMonth() + 1)
|
||||
if (type === 'date') {
|
||||
values.push(date.getDate())
|
||||
} else if (type === 'datetime') {
|
||||
values.push(date.getDate(), date.getHours(), date.getMinutes())
|
||||
}
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
export const datetimePickerViewProps = {
|
||||
...baseProps,
|
||||
/**
|
||||
@ -44,7 +21,13 @@ export const datetimePickerViewProps = {
|
||||
* picker内部滚筒高
|
||||
*/
|
||||
columnsHeight: makeNumberProp(217),
|
||||
/**
|
||||
* 选项的key
|
||||
*/
|
||||
valueKey: makeStringProp('value'),
|
||||
/**
|
||||
* 选项的label
|
||||
*/
|
||||
labelKey: makeStringProp('label'),
|
||||
/**
|
||||
* 选择器类型,可选值:date / year-month / time
|
||||
@ -86,6 +69,18 @@ export const datetimePickerViewProps = {
|
||||
* 最大分钟,time类型时生效
|
||||
*/
|
||||
maxMinute: makeNumberProp(59),
|
||||
/**
|
||||
* 是否显示秒选择,仅在 time 和 datetime 类型下生效
|
||||
*/
|
||||
useSecond: makeBooleanProp(false),
|
||||
/**
|
||||
* 最小秒数,仅在 time 和 datetime 类型下生效
|
||||
*/
|
||||
minSecond: makeNumberProp(0),
|
||||
/**
|
||||
* 最大秒数,仅在 time 和 datetime 类型下生效
|
||||
*/
|
||||
maxSecond: makeNumberProp(59),
|
||||
/**
|
||||
* 是否在手指松开时立即触发picker-view的 change 事件。若不开启则会在滚动动画结束后触发 change 事件,1.2.25版本起提供,仅微信小程序和支付宝小程序支持。
|
||||
*/
|
||||
@ -93,7 +88,7 @@ export const datetimePickerViewProps = {
|
||||
startSymbol: makeBooleanProp(false)
|
||||
}
|
||||
|
||||
export type DatetimePickerViewColumnType = 'year' | 'month' | 'date' | 'hour' | 'minute'
|
||||
export type DatetimePickerViewColumnType = 'year' | 'month' | 'date' | 'hour' | 'minute' | 'second'
|
||||
|
||||
export type DatetimePickerViewOption = {
|
||||
label: string
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
import { type DateTimeType } from './types'
|
||||
|
||||
/**
|
||||
* @description 根据传入的值和类型,获取当前的选项数组,便于传入 pickerView
|
||||
* @param value
|
||||
* @param type picker类型
|
||||
* @return {Array} pickerValue
|
||||
*/
|
||||
export function getPickerValue(value: string | number, type: DateTimeType) {
|
||||
const values: number[] = []
|
||||
const date = new Date(value)
|
||||
if (type === 'time') {
|
||||
const pair = String(value).split(':')
|
||||
values.push(parseInt(pair[0]), parseInt(pair[1]))
|
||||
if (pair[2]) {
|
||||
values.push(parseInt(pair[2]))
|
||||
}
|
||||
} else {
|
||||
values.push(date.getFullYear(), date.getMonth() + 1)
|
||||
if (type === 'date') {
|
||||
values.push(date.getDate())
|
||||
} else if (type === 'datetime') {
|
||||
values.push(date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds())
|
||||
}
|
||||
}
|
||||
return values
|
||||
}
|
||||
@ -1,21 +1,19 @@
|
||||
<template>
|
||||
<view>
|
||||
<wd-picker-view
|
||||
ref="datePickerview"
|
||||
:custom-class="customClass"
|
||||
:custom-style="customStyle"
|
||||
:immediate-change="immediateChange"
|
||||
v-model="pickerValue"
|
||||
:columns="columns"
|
||||
:columns-height="columnsHeight"
|
||||
:columnChange="columnChange"
|
||||
:loading="loading"
|
||||
:loading-color="loadingColor"
|
||||
@change="onChange"
|
||||
@pickstart="onPickStart"
|
||||
@pickend="onPickEnd"
|
||||
></wd-picker-view>
|
||||
</view>
|
||||
<wd-picker-view
|
||||
ref="datePickerview"
|
||||
:custom-class="customClass"
|
||||
:custom-style="customStyle"
|
||||
:immediate-change="immediateChange"
|
||||
v-model="pickerValue"
|
||||
:columns="columns"
|
||||
:columns-height="columnsHeight"
|
||||
:columnChange="columnChange"
|
||||
:loading="loading"
|
||||
:loading-color="loadingColor"
|
||||
@change="onChange"
|
||||
@pickstart="onPickStart"
|
||||
@pickend="onPickEnd"
|
||||
></wd-picker-view>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
@ -30,14 +28,9 @@ export default {
|
||||
import wdPickerView from '../wd-picker-view/wd-picker-view.vue'
|
||||
import { getCurrentInstance, onBeforeMount, ref, watch } from 'vue'
|
||||
import { debounce, isFunction, isDef, padZero, range, isArray, isString } from '../common/util'
|
||||
import {
|
||||
getPickerValue,
|
||||
datetimePickerViewProps,
|
||||
type DatetimePickerViewColumnType,
|
||||
type DatetimePickerViewOption,
|
||||
type DatetimePickerViewExpose
|
||||
} from './types'
|
||||
import { datetimePickerViewProps, type DatetimePickerViewColumnType, type DatetimePickerViewOption, type DatetimePickerViewExpose } from './types'
|
||||
import type { PickerViewInstance } from '../wd-picker-view/types'
|
||||
import { getPickerValue } from './util'
|
||||
|
||||
// 本地时间戳
|
||||
/** @description 判断时间戳是否合法 */
|
||||
@ -78,20 +71,11 @@ const innerValue = ref<null | string | number>(null)
|
||||
const columns = ref<DatetimePickerViewOption[][]>([])
|
||||
// 传递给pickerView的value的数据
|
||||
const pickerValue = ref<string | number | boolean | string[] | number[] | boolean[]>([])
|
||||
// 自定义组件是否已经调用created hook
|
||||
// 是否已经初始化
|
||||
const created = ref<boolean>(false)
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
defineExpose<DatetimePickerViewExpose>({
|
||||
updateColumns,
|
||||
setColumns,
|
||||
getSelects,
|
||||
correctValue,
|
||||
getPickerValue,
|
||||
getOriginColumns,
|
||||
...props
|
||||
})
|
||||
/**
|
||||
* @description updateValue 防抖函数的占位符
|
||||
*/
|
||||
@ -171,8 +155,10 @@ watch(
|
||||
() => props.minHour,
|
||||
() => props.maxHour,
|
||||
() => props.minMinute,
|
||||
() => props.minMinute,
|
||||
() => props.maxMinute
|
||||
() => props.maxMinute,
|
||||
() => props.minSecond,
|
||||
() => props.maxSecond,
|
||||
() => props.useSecond
|
||||
],
|
||||
() => {
|
||||
updateValue()
|
||||
@ -260,7 +246,7 @@ function getOriginColumns() {
|
||||
*/
|
||||
function getRanges(): Array<{ type: DatetimePickerViewColumnType; range: number[] }> {
|
||||
if (props.type === 'time') {
|
||||
return [
|
||||
const result: Array<{ type: DatetimePickerViewColumnType; range: number[] }> = [
|
||||
{
|
||||
type: 'hour',
|
||||
range: [props.minHour, props.maxHour]
|
||||
@ -270,10 +256,17 @@ function getRanges(): Array<{ type: DatetimePickerViewColumnType; range: number[
|
||||
range: [props.minMinute, props.maxMinute]
|
||||
}
|
||||
]
|
||||
if (props.useSecond) {
|
||||
result.push({
|
||||
type: 'second',
|
||||
range: [props.minSecond, props.maxSecond]
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const { maxYear, maxDate, maxMonth, maxHour, maxMinute } = getBoundary('max', innerValue.value as number)
|
||||
const { minYear, minDate, minMonth, minHour, minMinute } = getBoundary('min', innerValue.value as number)
|
||||
const { maxYear, maxDate, maxMonth, maxHour, maxMinute, maxSecond } = getBoundary('max', innerValue.value as number)
|
||||
const { minYear, minDate, minMonth, minHour, minMinute, minSecond } = getBoundary('min', innerValue.value as number)
|
||||
|
||||
const result: Array<{ type: DatetimePickerViewColumnType; range: number[] }> = [
|
||||
{
|
||||
@ -298,6 +291,13 @@ function getRanges(): Array<{ type: DatetimePickerViewColumnType; range: number[
|
||||
}
|
||||
]
|
||||
|
||||
if (props.type === 'datetime' && props.useSecond) {
|
||||
result.push({
|
||||
type: 'second',
|
||||
range: [minSecond, maxSecond]
|
||||
})
|
||||
}
|
||||
|
||||
if (props.type === 'date') result.splice(3, 2)
|
||||
if (props.type === 'year-month') result.splice(2, 3)
|
||||
if (props.type === 'year') result.splice(1, 4)
|
||||
@ -316,15 +316,19 @@ function correctValue(value: string | number | Date): string | number {
|
||||
value = props.minDate
|
||||
} else if (!isDateType && !value) {
|
||||
// 非Date类型,无入参,使用最小小时代替
|
||||
value = `${padZero(props.minHour)}:00`
|
||||
value = props.useSecond ? `${padZero(props.minHour)}:00:00` : `${padZero(props.minHour)}:00`
|
||||
}
|
||||
|
||||
// 当type为time时
|
||||
if (!isDateType) {
|
||||
// 非Date类型,直接走此逻辑
|
||||
let [hour, minute] = (isString(value) ? value : value.toString()).split(':')
|
||||
let [hour, minute, second = '00'] = (isString(value) ? value : value.toString()).split(':')
|
||||
hour = padZero(range(Number(hour), props.minHour, props.maxHour))
|
||||
minute = padZero(range(Number(minute), props.minMinute, props.maxMinute))
|
||||
if (props.useSecond) {
|
||||
second = padZero(range(Number(second), props.minSecond, props.maxSecond))
|
||||
return `${hour}:${minute}:${second}`
|
||||
}
|
||||
return `${hour}:${minute}`
|
||||
}
|
||||
|
||||
@ -347,12 +351,14 @@ function getBoundary(type: 'min' | 'max', innerValue: number) {
|
||||
let date: number = 1
|
||||
let hour: number = 0
|
||||
let minute: number = 0
|
||||
let second: number = 0
|
||||
|
||||
if (type === 'max') {
|
||||
month = 12
|
||||
date = getMonthEndDay(value.getFullYear(), value.getMonth() + 1)
|
||||
hour = 23
|
||||
minute = 59
|
||||
second = 59
|
||||
}
|
||||
|
||||
if (value.getFullYear() === year) {
|
||||
@ -363,6 +369,9 @@ function getBoundary(type: 'min' | 'max', innerValue: number) {
|
||||
hour = boundary.getHours()
|
||||
if (value.getHours() === hour) {
|
||||
minute = boundary.getMinutes()
|
||||
if (value.getMinutes() === minute) {
|
||||
second = boundary.getSeconds()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -372,7 +381,8 @@ function getBoundary(type: 'min' | 'max', innerValue: number) {
|
||||
[`${type}Month`]: month,
|
||||
[`${type}Date`]: date,
|
||||
[`${type}Hour`]: hour,
|
||||
[`${type}Minute`]: minute
|
||||
[`${type}Minute`]: minute,
|
||||
[`${type}Second`]: second
|
||||
}
|
||||
}
|
||||
|
||||
@ -401,13 +411,17 @@ function updateColumnValue(value: string | number) {
|
||||
* @return {date} innerValue
|
||||
*/
|
||||
function updateInnerValue() {
|
||||
const { type } = props
|
||||
const { type, useSecond } = props
|
||||
let innerValue: string | number = ''
|
||||
const pickerVal = datePickerview.value?.getValues() || []
|
||||
const values = isArray(pickerVal) ? pickerVal : [pickerVal]
|
||||
|
||||
if (type === 'time') {
|
||||
innerValue = `${padZero(values[0])}:${padZero(values[1])}`
|
||||
if (useSecond) {
|
||||
innerValue = `${padZero(values[0])}:${padZero(values[1])}:${padZero(values[2])}`
|
||||
} else {
|
||||
innerValue = `${padZero(values[0])}:${padZero(values[1])}`
|
||||
}
|
||||
return innerValue
|
||||
}
|
||||
|
||||
@ -425,15 +439,19 @@ function updateInnerValue() {
|
||||
date = (Number(values[2]) && parseInt(String(values[2]))) > maxDate ? maxDate : values[2] && parseInt(String(values[2]))
|
||||
}
|
||||
|
||||
// 处理 时分 索引位3,4
|
||||
// 处理 时分秒 索引位3,4,5
|
||||
let hour = 0
|
||||
let minute = 0
|
||||
let second = 0
|
||||
|
||||
if (type === 'datetime') {
|
||||
hour = Number(values[3]) && parseInt(values[3])
|
||||
minute = Number(values[4]) && parseInt(values[4])
|
||||
if (useSecond) {
|
||||
second = Number(values[5]) && parseInt(values[5])
|
||||
}
|
||||
}
|
||||
const value = new Date(Number(year), Number(month) - 1, Number(date), hour, minute).getTime()
|
||||
const value = new Date(Number(year), Number(month) - 1, Number(date), hour, minute, second).getTime()
|
||||
|
||||
innerValue = correctValue(value)
|
||||
return innerValue
|
||||
@ -456,11 +474,15 @@ function columnChange(picker: PickerViewInstance) {
|
||||
date = date > maxDate ? maxDate : date
|
||||
let hour: number = 0
|
||||
let minute: number = 0
|
||||
let second: number = 0
|
||||
if (props.type === 'datetime') {
|
||||
hour = Number(values[3])
|
||||
minute = Number(values[4])
|
||||
if (props.useSecond) {
|
||||
second = Number(values[5])
|
||||
}
|
||||
}
|
||||
const value = new Date(year, month - 1, date, hour, minute).getTime()
|
||||
const value = new Date(year, month - 1, date, hour, minute, second).getTime()
|
||||
/** 根据计算选中项的时间戳,重新计算所有的选项列表 */
|
||||
// 更新选中时间戳
|
||||
innerValue.value = correctValue(value)
|
||||
@ -497,8 +519,13 @@ function getSelects() {
|
||||
if (isArray(pickerVal)) return pickerVal
|
||||
return [pickerVal]
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
||||
defineExpose<DatetimePickerViewExpose>({
|
||||
updateColumns,
|
||||
setColumns,
|
||||
getSelects,
|
||||
correctValue,
|
||||
getPickerValue,
|
||||
getOriginColumns
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -53,14 +53,6 @@ export const datetimePickerProps = {
|
||||
* 设置左侧标题宽度
|
||||
*/
|
||||
labelWidth: makeStringProp('33%'),
|
||||
/**
|
||||
* 使用默认插槽
|
||||
*/
|
||||
useDefaultSlot: makeBooleanProp(false),
|
||||
/**
|
||||
* label 使用插槽
|
||||
*/
|
||||
useLabelSlot: makeBooleanProp(false),
|
||||
/**
|
||||
* 是否为错误状态,错误状态时右侧内容为红色
|
||||
*/
|
||||
@ -85,7 +77,13 @@ export const datetimePickerProps = {
|
||||
* picker内部滚筒高
|
||||
*/
|
||||
columnsHeight: makeNumberProp(217),
|
||||
/**
|
||||
* 选项的key
|
||||
*/
|
||||
valueKey: makeStringProp('value'),
|
||||
/**
|
||||
* 选项的label
|
||||
*/
|
||||
labelKey: makeStringProp('label'),
|
||||
/**
|
||||
* 选中项,当 type 为 time 时,类型为字符串;当 type 为 Array 时,类型为范围选择;否则为 时间戳
|
||||
@ -119,6 +117,18 @@ export const datetimePickerProps = {
|
||||
* 最大分钟,time类型时生效
|
||||
*/
|
||||
maxMinute: makeNumberProp(59),
|
||||
/**
|
||||
* 是否启用秒选择,仅在 time 和 datetime 类型下生效
|
||||
*/
|
||||
useSecond: makeBooleanProp(false),
|
||||
/**
|
||||
* 最小秒数,仅在 time 和 datetime 类型下生效
|
||||
*/
|
||||
minSecond: makeNumberProp(0),
|
||||
/**
|
||||
* 最大秒数,仅在 time 和 datetime 类型下生效
|
||||
*/
|
||||
maxSecond: makeNumberProp(59),
|
||||
/**
|
||||
* 自定义过滤选项的函数,返回列的选项数组
|
||||
*/
|
||||
|
||||
@ -101,6 +101,9 @@
|
||||
:min-date="minDate"
|
||||
:max-minute="maxMinute"
|
||||
:min-minute="minMinute"
|
||||
:use-second="useSecond"
|
||||
:min-second="minSecond"
|
||||
:max-second="maxSecond"
|
||||
:start-symbol="true"
|
||||
:immediate-change="immediateChange"
|
||||
@change="onChangeStart"
|
||||
@ -128,6 +131,9 @@
|
||||
:min-date="minDate"
|
||||
:max-minute="maxMinute"
|
||||
:min-minute="minMinute"
|
||||
:use-second="useSecond"
|
||||
:min-second="minSecond"
|
||||
:max-second="maxSecond"
|
||||
:start-symbol="false"
|
||||
:immediate-change="immediateChange"
|
||||
@change="onChangeEnd"
|
||||
@ -158,7 +164,6 @@ import { computed, getCurrentInstance, nextTick, onBeforeMount, onMounted, ref,
|
||||
import { deepClone, isArray, isDef, isEqual, isFunction, padZero } from '../common/util'
|
||||
import { useCell } from '../composables/useCell'
|
||||
import {
|
||||
getPickerValue,
|
||||
type DatetimePickerViewInstance,
|
||||
type DatetimePickerViewColumnFormatter,
|
||||
type DatetimePickerViewColumnType
|
||||
@ -168,6 +173,7 @@ import { useParent } from '../composables/useParent'
|
||||
import { useTranslate } from '../composables/useTranslate'
|
||||
import { datetimePickerProps, type DatetimePickerExpose } from './types'
|
||||
import { dayjs } from '../common/dayjs'
|
||||
import { getPickerValue } from '../wd-datetime-picker-view/util'
|
||||
|
||||
const props = defineProps(datetimePickerProps)
|
||||
const emit = defineEmits(['change', 'open', 'toggle', 'cancel', 'confirm', 'update:modelValue'])
|
||||
@ -334,11 +340,11 @@ function handleBoundaryValue(
|
||||
currentArray: number[],
|
||||
boundary: number[]
|
||||
): boolean {
|
||||
const { type } = props
|
||||
const { type, useSecond } = props
|
||||
|
||||
switch (type) {
|
||||
case 'datetime': {
|
||||
const [year, month, date, hour, minute] = boundary
|
||||
const [year, month, date, hour, minute, second] = boundary
|
||||
if (columnType === 'year') {
|
||||
return isStart ? value > year : value < year
|
||||
}
|
||||
@ -354,6 +360,17 @@ function handleBoundaryValue(
|
||||
if (columnType === 'minute' && currentArray[0] === year && currentArray[1] === month && currentArray[2] === date && currentArray[3] === hour) {
|
||||
return isStart ? value > minute : value < minute
|
||||
}
|
||||
if (
|
||||
useSecond &&
|
||||
columnType === 'second' &&
|
||||
currentArray[0] === year &&
|
||||
currentArray[1] === month &&
|
||||
currentArray[2] === date &&
|
||||
currentArray[3] === hour &&
|
||||
currentArray[4] === minute
|
||||
) {
|
||||
return isStart ? value > second : value < second
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'year-month': {
|
||||
@ -387,13 +404,16 @@ function handleBoundaryValue(
|
||||
break
|
||||
}
|
||||
case 'time': {
|
||||
const [hour, minute] = boundary
|
||||
const [hour, minute, second] = boundary
|
||||
if (columnType === 'hour') {
|
||||
return isStart ? value > hour : value < hour
|
||||
}
|
||||
if (columnType === 'minute' && currentArray[0] === hour) {
|
||||
return isStart ? value > minute : value < minute
|
||||
}
|
||||
if (useSecond && columnType === 'second' && currentArray[0] === hour && currentArray[1] === minute) {
|
||||
return isStart ? value > second : value < second
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -725,9 +745,9 @@ function defaultDisplayFormat(items: Record<string, any>[], tabLabel: boolean =
|
||||
if (props.formatter) {
|
||||
const typeMaps = {
|
||||
year: ['year'],
|
||||
datetime: ['year', 'month', 'date', 'hour', 'minute'],
|
||||
datetime: props.useSecond ? ['year', 'month', 'date', 'hour', 'minute', 'second'] : ['year', 'month', 'date', 'hour', 'minute'],
|
||||
date: ['year', 'month', 'date'],
|
||||
time: ['hour', 'minute'],
|
||||
time: props.useSecond ? ['hour', 'minute', 'second'] : ['hour', 'minute'],
|
||||
'year-month': ['year', 'month']
|
||||
}
|
||||
return items
|
||||
@ -745,9 +765,11 @@ function defaultDisplayFormat(items: Record<string, any>[], tabLabel: boolean =
|
||||
case 'year-month':
|
||||
return `${items[0].label}-${items[1].label}`
|
||||
case 'time':
|
||||
return `${items[0].label}:${items[1].label}`
|
||||
return props.useSecond ? `${items[0].label}:${items[1].label}:${items[2].label}` : `${items[0].label}:${items[1].label}`
|
||||
case 'datetime':
|
||||
return `${items[0].label}-${items[1].label}-${items[2].label} ${items[3].label}:${items[4].label}`
|
||||
return props.useSecond
|
||||
? `${items[0].label}-${items[1].label}-${items[2].label} ${items[3].label}:${items[4].label}:${items[5].label}`
|
||||
: `${items[0].label}-${items[1].label}-${items[2].label} ${items[3].label}:${items[4].label}`
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import WdDatetimePickerView from '@/uni_modules/wot-design-uni/components/wd-datetime-picker-view/wd-datetime-picker-view.vue'
|
||||
import { describe, expect, test, vi } from 'vitest'
|
||||
import { DatetimePickerViewFilter, DatetimePickerViewFormatter } from '@/uni_modules/wot-design-uni/components/wd-datetime-picker-view/types'
|
||||
import {
|
||||
type DatetimePickerViewFilter,
|
||||
type DatetimePickerViewFormatter
|
||||
} from '@/uni_modules/wot-design-uni/components/wd-datetime-picker-view/types'
|
||||
import { nextTick } from 'vue'
|
||||
|
||||
describe('WdDatetimePickerView 日期时间选择器视图', () => {
|
||||
@ -314,4 +317,108 @@ describe('WdDatetimePickerView 日期时间选择器视图', () => {
|
||||
|
||||
expect(wrapper.props('type')).toBe('year-month')
|
||||
})
|
||||
|
||||
test('useSecond 属性 - 时间类型', async () => {
|
||||
const wrapper = mount(WdDatetimePickerView, {
|
||||
props: {
|
||||
modelValue: '12:30:45',
|
||||
type: 'time',
|
||||
useSecond: true
|
||||
}
|
||||
})
|
||||
|
||||
expect(wrapper.props('useSecond')).toBe(true)
|
||||
expect(wrapper.props('type')).toBe('time')
|
||||
expect(wrapper.props('modelValue')).toBe('12:30:45')
|
||||
})
|
||||
|
||||
test('useSecond 属性 - 日期时间类型', async () => {
|
||||
const now = Date.now()
|
||||
const wrapper = mount(WdDatetimePickerView, {
|
||||
props: {
|
||||
modelValue: now,
|
||||
type: 'datetime',
|
||||
useSecond: true
|
||||
}
|
||||
})
|
||||
|
||||
expect(wrapper.props('useSecond')).toBe(true)
|
||||
expect(wrapper.props('type')).toBe('datetime')
|
||||
expect(wrapper.props('modelValue')).toBe(now)
|
||||
})
|
||||
|
||||
test('useSecond 属性 - 时间范围限制', async () => {
|
||||
const wrapper = mount(WdDatetimePickerView, {
|
||||
props: {
|
||||
modelValue: '12:30:45',
|
||||
type: 'time',
|
||||
useSecond: true,
|
||||
minSecond: 0,
|
||||
maxSecond: 30
|
||||
}
|
||||
})
|
||||
|
||||
expect(wrapper.props('useSecond')).toBe(true)
|
||||
expect(wrapper.props('minSecond')).toBe(0)
|
||||
expect(wrapper.props('maxSecond')).toBe(30)
|
||||
})
|
||||
|
||||
test('useSecond 属性 - 日期时间范围限制', async () => {
|
||||
const now = Date.now()
|
||||
const wrapper = mount(WdDatetimePickerView, {
|
||||
props: {
|
||||
modelValue: now,
|
||||
type: 'datetime',
|
||||
useSecond: true,
|
||||
minSecond: 0,
|
||||
maxSecond: 30
|
||||
}
|
||||
})
|
||||
|
||||
expect(wrapper.props('useSecond')).toBe(true)
|
||||
expect(wrapper.props('minSecond')).toBe(0)
|
||||
expect(wrapper.props('maxSecond')).toBe(30)
|
||||
})
|
||||
|
||||
test('useSecond 属性 - 时间格式化', async () => {
|
||||
const formatter: DatetimePickerViewFormatter = (type, value) => {
|
||||
if (type === 'second') {
|
||||
return value + '秒'
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
const wrapper = mount(WdDatetimePickerView, {
|
||||
props: {
|
||||
modelValue: '12:30:45',
|
||||
type: 'time',
|
||||
useSecond: true,
|
||||
formatter
|
||||
}
|
||||
})
|
||||
|
||||
expect(wrapper.props('useSecond')).toBe(true)
|
||||
expect(wrapper.props('formatter')).toBe(formatter)
|
||||
})
|
||||
|
||||
test('useSecond 属性 - 时间过滤', async () => {
|
||||
const filter: DatetimePickerViewFilter = (type, values) => {
|
||||
if (type === 'second') {
|
||||
return values.filter((value) => value % 5 === 0)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
const wrapper = mount(WdDatetimePickerView, {
|
||||
props: {
|
||||
modelValue: '12:30:45',
|
||||
type: 'time',
|
||||
useSecond: true,
|
||||
filter
|
||||
}
|
||||
})
|
||||
|
||||
expect(wrapper.props('useSecond')).toBe(true)
|
||||
expect(wrapper.props('filter')).toBe(filter)
|
||||
})
|
||||
})
|
||||
|
||||
@ -668,4 +668,148 @@ describe('WdDatetimePicker 日期时间选择器', () => {
|
||||
expect(wrapper.props('prop')).toBe('date')
|
||||
expect(wrapper.props('rules')).toEqual(rules)
|
||||
})
|
||||
|
||||
test('useSecond 属性 - 时间类型', async () => {
|
||||
const wrapper = mount(WdDatetimePicker, {
|
||||
props: {
|
||||
modelValue: '12:30:45',
|
||||
type: 'time',
|
||||
useSecond: true
|
||||
},
|
||||
global: {
|
||||
components: globalComponents
|
||||
}
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(wrapper.props('useSecond')).toBe(true)
|
||||
expect(wrapper.props('type')).toBe('time')
|
||||
expect(wrapper.props('modelValue')).toBe('12:30:45')
|
||||
expect(wrapper.find('.wd-picker__value').text()).toBe('12:30:45')
|
||||
})
|
||||
|
||||
test('useSecond 属性 - 日期时间类型', async () => {
|
||||
const now = Date.now()
|
||||
const wrapper = mount(WdDatetimePicker, {
|
||||
props: {
|
||||
modelValue: now,
|
||||
type: 'datetime',
|
||||
useSecond: true
|
||||
},
|
||||
global: {
|
||||
components: globalComponents
|
||||
}
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(wrapper.props('useSecond')).toBe(true)
|
||||
expect(wrapper.props('type')).toBe('datetime')
|
||||
expect(wrapper.props('modelValue')).toBe(now)
|
||||
})
|
||||
|
||||
test('useSecond 属性 - 时间范围限制', async () => {
|
||||
const wrapper = mount(WdDatetimePicker, {
|
||||
props: {
|
||||
modelValue: '12:30:45',
|
||||
type: 'time',
|
||||
useSecond: true,
|
||||
minSecond: 0,
|
||||
maxSecond: 30
|
||||
},
|
||||
global: {
|
||||
components: globalComponents
|
||||
}
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(wrapper.props('useSecond')).toBe(true)
|
||||
expect(wrapper.props('minSecond')).toBe(0)
|
||||
expect(wrapper.props('maxSecond')).toBe(30)
|
||||
})
|
||||
|
||||
test('useSecond 属性 - 日期时间范围限制', async () => {
|
||||
const now = Date.now()
|
||||
const wrapper = mount(WdDatetimePicker, {
|
||||
props: {
|
||||
modelValue: now,
|
||||
type: 'datetime',
|
||||
useSecond: true,
|
||||
minSecond: 0,
|
||||
maxSecond: 30
|
||||
},
|
||||
global: {
|
||||
components: globalComponents
|
||||
}
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(wrapper.props('useSecond')).toBe(true)
|
||||
expect(wrapper.props('minSecond')).toBe(0)
|
||||
expect(wrapper.props('maxSecond')).toBe(30)
|
||||
})
|
||||
|
||||
test('useSecond 属性 - 自定义显示格式', async () => {
|
||||
const displayFormat = vi.fn((items) => {
|
||||
return `${items[0].label}时${items[1].label}分${items[2].label}秒`
|
||||
})
|
||||
|
||||
const wrapper = mount(WdDatetimePicker, {
|
||||
props: {
|
||||
modelValue: '12:30:45',
|
||||
type: 'time',
|
||||
useSecond: true,
|
||||
displayFormat
|
||||
},
|
||||
global: {
|
||||
components: globalComponents
|
||||
}
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(wrapper.props('useSecond')).toBe(true)
|
||||
expect(wrapper.props('displayFormat')).toBe(displayFormat)
|
||||
expect(displayFormat).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('useSecond 属性 - 范围选择', async () => {
|
||||
const startDate = new Date(2024, 0, 1, 12, 30, 45).getTime()
|
||||
const endDate = new Date(2024, 0, 1, 13, 30, 45).getTime()
|
||||
|
||||
const wrapper = mount(WdDatetimePicker, {
|
||||
props: {
|
||||
modelValue: [startDate, endDate],
|
||||
type: 'datetime',
|
||||
useSecond: true
|
||||
},
|
||||
global: {
|
||||
components: globalComponents
|
||||
}
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(wrapper.props('useSecond')).toBe(true)
|
||||
expect(Array.isArray(wrapper.props('modelValue'))).toBe(true)
|
||||
expect(wrapper.props('modelValue')).toEqual([startDate, endDate])
|
||||
})
|
||||
|
||||
test('useSecond 属性 - 表单验证', async () => {
|
||||
const rules = [{ required: true, message: '请选择时间' }]
|
||||
const wrapper = mount(WdDatetimePicker, {
|
||||
props: {
|
||||
modelValue: '',
|
||||
type: 'time',
|
||||
useSecond: true,
|
||||
prop: 'time',
|
||||
rules
|
||||
},
|
||||
global: {
|
||||
components: globalComponents
|
||||
}
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
expect(wrapper.props('useSecond')).toBe(true)
|
||||
expect(wrapper.props('prop')).toBe('time')
|
||||
expect(wrapper.props('rules')).toEqual(rules)
|
||||
})
|
||||
})
|
||||
|
||||
@ -355,50 +355,6 @@ describe('useUpload', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// 测试选择媒体文件
|
||||
it('should choose media files', async () => {
|
||||
const mockChooseMedia = vi.fn().mockImplementation((options) => {
|
||||
options.success({
|
||||
tempFiles: [
|
||||
{
|
||||
fileType: 'image',
|
||||
tempFilePath: 'temp/image.jpg',
|
||||
size: 1024,
|
||||
duration: 0
|
||||
},
|
||||
{
|
||||
fileType: 'video',
|
||||
tempFilePath: 'temp/video.mp4',
|
||||
thumbTempFilePath: 'temp/thumb.jpg',
|
||||
size: 10240,
|
||||
duration: 15
|
||||
}
|
||||
]
|
||||
})
|
||||
})
|
||||
;(global as any).uni.chooseMedia = mockChooseMedia
|
||||
|
||||
const files = await chooseFile({
|
||||
accept: 'media',
|
||||
multiple: true,
|
||||
maxCount: 9,
|
||||
sizeType: ['original', 'compressed'],
|
||||
sourceType: ['album', 'camera'],
|
||||
compressed: true,
|
||||
maxDuration: 60,
|
||||
camera: 'back'
|
||||
})
|
||||
|
||||
expect(files).toHaveLength(2)
|
||||
expect(files[1]).toEqual({
|
||||
type: 'video',
|
||||
path: 'temp/video.mp4',
|
||||
thumb: 'temp/thumb.jpg',
|
||||
size: 10240,
|
||||
duration: 15
|
||||
})
|
||||
})
|
||||
|
||||
// 测试选择文件失败的情况
|
||||
it('should handle choose file failure', async () => {
|
||||
const mockChooseImage = vi.fn().mockImplementation((options) => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user