优化日期选择体验
This commit is contained in:
@@ -2,14 +2,18 @@
|
|||||||
<cl-page>
|
<cl-page>
|
||||||
<view class="p-3">
|
<view class="p-3">
|
||||||
<demo-item :label="t('基础用法')">
|
<demo-item :label="t('基础用法')">
|
||||||
<cl-select-date v-model="form.date1" type="date"></cl-select-date>
|
<cl-select-date
|
||||||
|
v-model="form.date1"
|
||||||
|
type="date"
|
||||||
|
@change="onDateChange"
|
||||||
|
></cl-select-date>
|
||||||
</demo-item>
|
</demo-item>
|
||||||
|
|
||||||
<demo-item :label="t('固定开始、结束日期')">
|
<demo-item :label="t('固定开始、结束日期')">
|
||||||
<cl-select-date
|
<cl-select-date
|
||||||
v-model="form.date3"
|
v-model="form.date3"
|
||||||
start="2025-06-01"
|
start="2025-06-01"
|
||||||
end="2026-06-01"
|
end="2027-08-01"
|
||||||
type="date"
|
type="date"
|
||||||
></cl-select-date>
|
></cl-select-date>
|
||||||
</demo-item>
|
</demo-item>
|
||||||
@@ -34,7 +38,7 @@
|
|||||||
|
|
||||||
<demo-item :label="t('自定义快捷选项')">
|
<demo-item :label="t('自定义快捷选项')">
|
||||||
<cl-select-date
|
<cl-select-date
|
||||||
v-model:values="form.date5"
|
v-model:values="form.date6"
|
||||||
type="date"
|
type="date"
|
||||||
rangeable
|
rangeable
|
||||||
:shortcuts="shortcuts"
|
:shortcuts="shortcuts"
|
||||||
@@ -43,7 +47,7 @@
|
|||||||
|
|
||||||
<demo-item :label="t('自定义')">
|
<demo-item :label="t('自定义')">
|
||||||
<cl-select-date
|
<cl-select-date
|
||||||
v-model="form.date6"
|
v-model="form.date7"
|
||||||
:type="type"
|
:type="type"
|
||||||
:label-format="labelFormat"
|
:label-format="labelFormat"
|
||||||
:disabled="isDisabled"
|
:disabled="isDisabled"
|
||||||
@@ -129,13 +133,23 @@ import { dayUts } from "@/cool";
|
|||||||
|
|
||||||
const ui = useUi();
|
const ui = useUi();
|
||||||
|
|
||||||
|
// 测试日期选择变化事件
|
||||||
|
function onDateChange(value: string) {
|
||||||
|
console.log("日期选择变化:", value);
|
||||||
|
ui.showToast({
|
||||||
|
message: `选择了日期: ${value}`,
|
||||||
|
type: "success"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
type Form = {
|
type Form = {
|
||||||
date1: string;
|
date1: string;
|
||||||
date2: string;
|
date2: string;
|
||||||
date3: string;
|
date3: string;
|
||||||
date4: string;
|
date4: string;
|
||||||
date5: string[];
|
date5: string[];
|
||||||
date6: string;
|
date6: string[];
|
||||||
|
date7: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const form = reactive<Form>({
|
const form = reactive<Form>({
|
||||||
@@ -144,7 +158,8 @@ const form = reactive<Form>({
|
|||||||
date3: "",
|
date3: "",
|
||||||
date4: "",
|
date4: "",
|
||||||
date5: [],
|
date5: [],
|
||||||
date6: ""
|
date6: [],
|
||||||
|
date7: ""
|
||||||
});
|
});
|
||||||
|
|
||||||
const isDisabled = ref(false);
|
const isDisabled = ref(false);
|
||||||
|
|||||||
@@ -89,15 +89,10 @@ const props = defineProps({
|
|||||||
height: {
|
height: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 600
|
default: 600
|
||||||
},
|
|
||||||
// 选择后子集是否回到0
|
|
||||||
resetOnChange: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(["change"]);
|
const emit = defineEmits(["change-value", "change-index"]);
|
||||||
|
|
||||||
// 获取窗口宽度,用于计算选择器列宽
|
// 获取窗口宽度,用于计算选择器列宽
|
||||||
const { windowWidth } = uni.getWindowInfo();
|
const { windowWidth } = uni.getWindowInfo();
|
||||||
@@ -151,33 +146,19 @@ const indicatorStyle = computed(() => {
|
|||||||
return str;
|
return str;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 选择器值改变事件
|
// 监听选择器值改变事件
|
||||||
function onChange(e: UniPickerViewChangeEvent) {
|
function onChange(e: UniPickerViewChangeEvent) {
|
||||||
// 获取选择器当前选中值数组
|
// 获取选择器当前选中值数组
|
||||||
const arr = e.detail.value;
|
const indexs = e.detail.value;
|
||||||
|
|
||||||
// 如果选择后子集是否回到0
|
// 获取所有列的值
|
||||||
if (props.resetOnChange) {
|
const values = props.columns.map((c, i) => {
|
||||||
// 记录第一个发生变化的列的索引,初始为-1表示未发生变化
|
return c[indexs[i]].value;
|
||||||
let start = -1;
|
|
||||||
|
|
||||||
// 遍历原选中值数组
|
|
||||||
props.value.forEach((e, i) => {
|
|
||||||
if (start >= 0) {
|
|
||||||
// 如果之前的列发生过变化,后续列都重置为0
|
|
||||||
arr[i] = 0;
|
|
||||||
} else {
|
|
||||||
// 比较当前列的值是否发生变化
|
|
||||||
if (e != arr[i]) {
|
|
||||||
// 记录第一个变化的列的索引
|
|
||||||
start = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// 触发change事件,传递新的选中值数组
|
// 返回所有列的值或下标
|
||||||
emit("change", arr);
|
emit("change-value", values);
|
||||||
|
emit("change-index", indexs);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,8 @@
|
|||||||
:headers="headers"
|
:headers="headers"
|
||||||
:value="indexes"
|
:value="indexes"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
@change="onChange"
|
:reset-on-change="false"
|
||||||
|
@change-value="onChange"
|
||||||
></cl-picker-view>
|
></cl-picker-view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -514,12 +515,19 @@ const indexes = computed(() => {
|
|||||||
if (isEmpty(value.value)) {
|
if (isEmpty(value.value)) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 遍历每一列,查找当前值在选项中的下标
|
// 遍历每一列,查找当前值在选项中的下标
|
||||||
return value.value.map((e, i) => {
|
return value.value.map((e, i) => {
|
||||||
const index = list.value[i].findIndex((a) => a.value == e);
|
let index = list.value[i].findIndex((a) => a.value == e) as number;
|
||||||
// 如果未找到,返回0
|
|
||||||
|
// 如果未找到,返回最后一个
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
return 0;
|
index = list.value[i].length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果小于0,返回0
|
||||||
|
if (index < 0) {
|
||||||
|
index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
@@ -548,6 +556,58 @@ function toDate() {
|
|||||||
return parts.join("");
|
return parts.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查边界值
|
||||||
|
function checkDate(values: number[]): number[] {
|
||||||
|
if (values.length == 0) {
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保至少有6个元素,缺失的用默认值填充
|
||||||
|
const checkedValues = [...values];
|
||||||
|
const defaultValues = [2000, 1, 1, 0, 0, 0];
|
||||||
|
for (let i = checkedValues.length; i < 6; i++) {
|
||||||
|
checkedValues.push(defaultValues[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
let [year, month, date, hour, minute, second] = checkedValues;
|
||||||
|
|
||||||
|
// 检查日期边界(根据年份和月份确定最大天数)
|
||||||
|
// 判断是否为闰年
|
||||||
|
const isLeapYear = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
|
||||||
|
// 每月天数数组,2月根据闰年判断
|
||||||
|
const daysInMonth = [31, isLeapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
||||||
|
const maxDay = daysInMonth[month - 1];
|
||||||
|
|
||||||
|
if (date < 1) {
|
||||||
|
date = 1;
|
||||||
|
} else if (date > maxDay) {
|
||||||
|
date = maxDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查小时边界 (0-23)
|
||||||
|
if (hour < 0) {
|
||||||
|
hour = 0;
|
||||||
|
} else if (hour > 23) {
|
||||||
|
hour = 23;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查分钟边界 (0-59)
|
||||||
|
if (minute < 0) {
|
||||||
|
minute = 0;
|
||||||
|
} else if (minute > 59) {
|
||||||
|
minute = 59;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查秒钟边界 (0-59)
|
||||||
|
if (second < 0) {
|
||||||
|
second = 0;
|
||||||
|
} else if (second > 59) {
|
||||||
|
second = 59;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [year, month, date, hour, minute, second];
|
||||||
|
}
|
||||||
|
|
||||||
// 显示文本,展示当前选中的日期字符串
|
// 显示文本,展示当前选中的日期字符串
|
||||||
const text = ref("");
|
const text = ref("");
|
||||||
|
|
||||||
@@ -563,19 +623,19 @@ function getText() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 选择器值改变事件,更新value
|
// 选择器值改变事件,更新value
|
||||||
async function onChange(arr: number[]) {
|
async function onChange(data: number[]) {
|
||||||
const data = [] as number[];
|
|
||||||
|
|
||||||
for (let i = 0; i < arr.length; i++) {
|
|
||||||
const item = list.value[i][arr[i]];
|
|
||||||
|
|
||||||
if (!isNull(item)) {
|
|
||||||
data.push(item.value as number);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新value
|
// 更新value
|
||||||
value.value = data;
|
value.value = checkDate(data);
|
||||||
|
|
||||||
|
// 不能大于结束日期
|
||||||
|
if (dayUts(toDate()).isAfter(dayUts(props.end))) {
|
||||||
|
value.value = dayUts(props.end).toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 不能小于开始日期
|
||||||
|
if (dayUts(toDate()).isBefore(dayUts(props.start))) {
|
||||||
|
value.value = dayUts(props.start).toArray();
|
||||||
|
}
|
||||||
|
|
||||||
// 设置范围值
|
// 设置范围值
|
||||||
if (props.rangeable) {
|
if (props.rangeable) {
|
||||||
@@ -597,10 +657,10 @@ function setValue(val: string) {
|
|||||||
|
|
||||||
// 如果值为空,使用当前时间
|
// 如果值为空,使用当前时间
|
||||||
if (isNull(val) || isEmpty(val)) {
|
if (isNull(val) || isEmpty(val)) {
|
||||||
value.value = dayUts().toArray();
|
value.value = checkDate(dayUts().toArray());
|
||||||
} else {
|
} else {
|
||||||
// 否则解析为数组
|
// 否则解析为数组
|
||||||
value.value = dayUts(val).toArray();
|
value.value = checkDate(dayUts(val).toArray());
|
||||||
getText();
|
getText();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -669,8 +729,7 @@ function close() {
|
|||||||
|
|
||||||
// 选择器关闭后
|
// 选择器关闭后
|
||||||
function onClosed() {
|
function onClosed() {
|
||||||
value.value = [];
|
values.value = ["", ""];
|
||||||
values.value = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清空选择器,重置显示文本并触发事件
|
// 清空选择器,重置显示文本并触发事件
|
||||||
@@ -761,6 +820,14 @@ watch(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 更新显示文本
|
||||||
|
watch(
|
||||||
|
computed(() => props.labelFormat),
|
||||||
|
() => {
|
||||||
|
getText();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
open,
|
open,
|
||||||
close,
|
close,
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
:headers="headers"
|
:headers="headers"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:reset-on-change="false"
|
:reset-on-change="false"
|
||||||
@change="onChange"
|
@change-index="onChange"
|
||||||
></cl-picker-view>
|
></cl-picker-view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user