优化日期选择体验
This commit is contained in:
@@ -89,15 +89,10 @@ const props = defineProps({
|
||||
height: {
|
||||
type: Number,
|
||||
default: 600
|
||||
},
|
||||
// 选择后子集是否回到0
|
||||
resetOnChange: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(["change"]);
|
||||
const emit = defineEmits(["change-value", "change-index"]);
|
||||
|
||||
// 获取窗口宽度,用于计算选择器列宽
|
||||
const { windowWidth } = uni.getWindowInfo();
|
||||
@@ -151,33 +146,19 @@ const indicatorStyle = computed(() => {
|
||||
return str;
|
||||
});
|
||||
|
||||
// 选择器值改变事件
|
||||
// 监听选择器值改变事件
|
||||
function onChange(e: UniPickerViewChangeEvent) {
|
||||
// 获取选择器当前选中值数组
|
||||
const arr = e.detail.value;
|
||||
const indexs = e.detail.value;
|
||||
|
||||
// 如果选择后子集是否回到0
|
||||
if (props.resetOnChange) {
|
||||
// 记录第一个发生变化的列的索引,初始为-1表示未发生变化
|
||||
let start = -1;
|
||||
// 获取所有列的值
|
||||
const values = props.columns.map((c, i) => {
|
||||
return c[indexs[i]].value;
|
||||
});
|
||||
|
||||
// 遍历原选中值数组
|
||||
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>
|
||||
|
||||
|
||||
@@ -101,7 +101,8 @@
|
||||
:headers="headers"
|
||||
:value="indexes"
|
||||
:columns="columns"
|
||||
@change="onChange"
|
||||
:reset-on-change="false"
|
||||
@change-value="onChange"
|
||||
></cl-picker-view>
|
||||
</view>
|
||||
|
||||
@@ -514,12 +515,19 @@ const indexes = computed(() => {
|
||||
if (isEmpty(value.value)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// 遍历每一列,查找当前值在选项中的下标
|
||||
return value.value.map((e, i) => {
|
||||
const index = list.value[i].findIndex((a) => a.value == e);
|
||||
// 如果未找到,返回0
|
||||
let index = list.value[i].findIndex((a) => a.value == e) as number;
|
||||
|
||||
// 如果未找到,返回最后一个
|
||||
if (index == -1) {
|
||||
return 0;
|
||||
index = list.value[i].length - 1;
|
||||
}
|
||||
|
||||
// 如果小于0,返回0
|
||||
if (index < 0) {
|
||||
index = 0;
|
||||
}
|
||||
|
||||
return index;
|
||||
@@ -548,6 +556,58 @@ function toDate() {
|
||||
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("");
|
||||
|
||||
@@ -563,19 +623,19 @@ function getText() {
|
||||
}
|
||||
|
||||
// 选择器值改变事件,更新value
|
||||
async function onChange(arr: number[]) {
|
||||
const data = [] as number[];
|
||||
async function onChange(data: number[]) {
|
||||
// 更新value
|
||||
value.value = checkDate(data);
|
||||
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
const item = list.value[i][arr[i]];
|
||||
|
||||
if (!isNull(item)) {
|
||||
data.push(item.value as number);
|
||||
}
|
||||
// 不能大于结束日期
|
||||
if (dayUts(toDate()).isAfter(dayUts(props.end))) {
|
||||
value.value = dayUts(props.end).toArray();
|
||||
}
|
||||
|
||||
// 更新value
|
||||
value.value = data;
|
||||
// 不能小于开始日期
|
||||
if (dayUts(toDate()).isBefore(dayUts(props.start))) {
|
||||
value.value = dayUts(props.start).toArray();
|
||||
}
|
||||
|
||||
// 设置范围值
|
||||
if (props.rangeable) {
|
||||
@@ -597,10 +657,10 @@ function setValue(val: string) {
|
||||
|
||||
// 如果值为空,使用当前时间
|
||||
if (isNull(val) || isEmpty(val)) {
|
||||
value.value = dayUts().toArray();
|
||||
value.value = checkDate(dayUts().toArray());
|
||||
} else {
|
||||
// 否则解析为数组
|
||||
value.value = dayUts(val).toArray();
|
||||
value.value = checkDate(dayUts(val).toArray());
|
||||
getText();
|
||||
}
|
||||
}
|
||||
@@ -669,8 +729,7 @@ function close() {
|
||||
|
||||
// 选择器关闭后
|
||||
function onClosed() {
|
||||
value.value = [];
|
||||
values.value = [];
|
||||
values.value = ["", ""];
|
||||
}
|
||||
|
||||
// 清空选择器,重置显示文本并触发事件
|
||||
@@ -761,6 +820,14 @@ watch(
|
||||
}
|
||||
);
|
||||
|
||||
// 更新显示文本
|
||||
watch(
|
||||
computed(() => props.labelFormat),
|
||||
() => {
|
||||
getText();
|
||||
}
|
||||
);
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
close,
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
:headers="headers"
|
||||
:columns="columns"
|
||||
:reset-on-change="false"
|
||||
@change="onChange"
|
||||
@change-index="onChange"
|
||||
></cl-picker-view>
|
||||
</view>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user