diff --git a/docs/component/datetime-picker-view.md b/docs/component/datetime-picker-view.md index d1fe25c9..9ceb0a07 100644 --- a/docs/component/datetime-picker-view.md +++ b/docs/component/datetime-picker-view.md @@ -64,10 +64,30 @@ const value = ref(Date.now()) const value4 = ref('11:12') ``` +## time 类型(带秒) + +`time` 类型设置 `use-second` 属性可以展示时分秒,绑定值为 `HH:mm:ss` 格式。 + +```html + +``` +```typescript +const value = ref('11:12:30') +``` + +## datetime 类型(带秒) + +`datetime` 类型设置 `use-second` 属性可以展示年月日时分秒,绑定值为时间戳。 + +```html + +``` +```typescript +const value = ref(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 | 事件名称 | 说明 | 参数 | 最低版本 | diff --git a/docs/component/datetime-picker.md b/docs/component/datetime-picker.md index 6f8ec269..53b7b95c 100644 --- a/docs/component/datetime-picker.md +++ b/docs/component/datetime-picker.md @@ -78,6 +78,28 @@ const value = ref(Date.now()) const value4 = ref('09:20') ``` +## time 类型(带秒) + +`time` 类型设置 `use-second` 属性可以展示时分秒,绑定值为 `HH:mm:ss` 格式。 + +```html + +``` +```typescript +const value = ref('09:20:30') +``` + +## datetime 类型(带秒) + +`datetime` 类型设置 `use-second` 属性可以展示年月日时分秒,绑定值为时间戳。 + +```html + +``` +```typescript +const value = ref(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 数据结构 diff --git a/docs/en-US/component/datetime-picker-view.md b/docs/en-US/component/datetime-picker-view.md index ff73397a..15b287ab 100644 --- a/docs/en-US/component/datetime-picker-view.md +++ b/docs/en-US/component/datetime-picker-view.md @@ -65,6 +65,28 @@ const value = ref(Date.now()) const value4 = ref('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 + +``` +```typescript +const value = ref('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 + +``` +```typescript +const value = ref(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 diff --git a/docs/en-US/component/datetime-picker.md b/docs/en-US/component/datetime-picker.md index 4d1a8d37..478603a8 100644 --- a/docs/en-US/component/datetime-picker.md +++ b/docs/en-US/component/datetime-picker.md @@ -78,6 +78,28 @@ const value = ref(Date.now()) const value4 = ref('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 + +``` +```typescript +const value = ref('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 + +``` +```typescript +const value = ref(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 diff --git a/src/locale/en-US.json b/src/locale/en-US.json index 72d636ef..9c9ae31b 100644 --- a/src/locale/en-US.json +++ b/src/locale/en-US.json @@ -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", diff --git a/src/locale/zh-CN.json b/src/locale/zh-CN.json index dfe4c51a..30b6f9c9 100644 --- a/src/locale/zh-CN.json +++ b/src/locale/zh-CN.json @@ -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": "石景山区", diff --git a/src/subPages/datetimePicker/Index.vue b/src/subPages/datetimePicker/Index.vue index 652441b9..e0ce28c9 100644 --- a/src/subPages/datetimePicker/Index.vue +++ b/src/subPages/datetimePicker/Index.vue @@ -4,10 +4,12 @@ + + @@ -34,7 +36,13 @@ - + (['', '']) const value15 = ref(['', 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(Date.now()) const maxDate = ref(new Date(new Date().getFullYear() + 1, new Date().getMonth(), new Date().getDate()).getTime()) diff --git a/src/subPages/datetimePickerView/Index.vue b/src/subPages/datetimePickerView/Index.vue index 00d9052d..6ef8821b 100644 --- a/src/subPages/datetimePickerView/Index.vue +++ b/src/subPages/datetimePickerView/Index.vue @@ -5,6 +5,10 @@ + + + + @@ -21,6 +25,10 @@ + + + + @@ -44,6 +52,9 @@ const value4 = ref('11:12') const value5 = ref(Date.now()) const value6 = ref(Date.now()) const value7 = ref('') +const value8 = ref(Date.now()) +const value9 = ref('11:12:13') + const formatter: DatetimePickerViewFormatter = (type, value) => { switch (type) { case 'year': diff --git a/src/uni_modules/wot-design-uni/components/common/abstracts/variable.scss b/src/uni_modules/wot-design-uni/components/common/abstracts/variable.scss index d877d7c5..c2e5198d 100644 --- a/src/uni_modules/wot-design-uni/components/common/abstracts/variable.scss +++ b/src/uni_modules/wot-design-uni/components/common/abstracts/variable.scss @@ -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))) diff --git a/src/uni_modules/wot-design-uni/components/wd-datetime-picker-view/index.scss b/src/uni_modules/wot-design-uni/components/wd-datetime-picker-view/index.scss deleted file mode 100644 index e69de29b..00000000 diff --git a/src/uni_modules/wot-design-uni/components/wd-datetime-picker-view/types.ts b/src/uni_modules/wot-design-uni/components/wd-datetime-picker-view/types.ts index 4cd324cf..6a5f4e7a 100644 --- a/src/uni_modules/wot-design-uni/components/wd-datetime-picker-view/types.ts +++ b/src/uni_modules/wot-design-uni/components/wd-datetime-picker-view/types.ts @@ -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 diff --git a/src/uni_modules/wot-design-uni/components/wd-datetime-picker-view/util.ts b/src/uni_modules/wot-design-uni/components/wd-datetime-picker-view/util.ts new file mode 100644 index 00000000..2f822924 --- /dev/null +++ b/src/uni_modules/wot-design-uni/components/wd-datetime-picker-view/util.ts @@ -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 +} diff --git a/src/uni_modules/wot-design-uni/components/wd-datetime-picker-view/wd-datetime-picker-view.vue b/src/uni_modules/wot-design-uni/components/wd-datetime-picker-view/wd-datetime-picker-view.vue index a7d27721..9e9c3610 100644 --- a/src/uni_modules/wot-design-uni/components/wd-datetime-picker-view/wd-datetime-picker-view.vue +++ b/src/uni_modules/wot-design-uni/components/wd-datetime-picker-view/wd-datetime-picker-view.vue @@ -1,21 +1,19 @@ - +defineExpose({ + updateColumns, + setColumns, + getSelects, + correctValue, + getPickerValue, + getOriginColumns +}) + diff --git a/src/uni_modules/wot-design-uni/components/wd-datetime-picker/types.ts b/src/uni_modules/wot-design-uni/components/wd-datetime-picker/types.ts index eab760d2..dd699732 100644 --- a/src/uni_modules/wot-design-uni/components/wd-datetime-picker/types.ts +++ b/src/uni_modules/wot-design-uni/components/wd-datetime-picker/types.ts @@ -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), /** * 自定义过滤选项的函数,返回列的选项数组 */ diff --git a/src/uni_modules/wot-design-uni/components/wd-datetime-picker/wd-datetime-picker.vue b/src/uni_modules/wot-design-uni/components/wd-datetime-picker/wd-datetime-picker.vue index 26d950a4..389d6d25 100644 --- a/src/uni_modules/wot-design-uni/components/wd-datetime-picker/wd-datetime-picker.vue +++ b/src/uni_modules/wot-design-uni/components/wd-datetime-picker/wd-datetime-picker.vue @@ -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[], 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[], 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}` } } diff --git a/tests/components/wd-datetime-picker-view.test.ts b/tests/components/wd-datetime-picker-view.test.ts index 72358157..76617c45 100644 --- a/tests/components/wd-datetime-picker-view.test.ts +++ b/tests/components/wd-datetime-picker-view.test.ts @@ -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) + }) }) diff --git a/tests/components/wd-datetime-picker.test.ts b/tests/components/wd-datetime-picker.test.ts index 8a99e067..2c35afb7 100644 --- a/tests/components/wd-datetime-picker.test.ts +++ b/tests/components/wd-datetime-picker.test.ts @@ -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) + }) }) diff --git a/tests/composables/useUpload.test.ts b/tests/composables/useUpload.test.ts index 94b7ccea..c4cd05cf 100644 --- a/tests/composables/useUpload.test.ts +++ b/tests/composables/useUpload.test.ts @@ -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) => {