Files
akmon/components/picker-date/picker-date.uvue
2026-01-20 08:04:15 +08:00

168 lines
5.4 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view>
<picker-view class="picker-view" :value="pickerValue" @change="onChange" :indicator-style="indicatorStyle"
:indicator-class="indicatorClass" :mask-style="maskStyle" :mask-class="maskClass"
:mask-top-style="maskTopStyle" :mask-bottom-style="maskBottomStyle">
<picker-view-column class="picker-view-column">
<view class="item" v-for="(item,index) in years" :key="index"><text class="text">{{item}}年</text></view>
</picker-view-column>
<picker-view-column class="picker-view-column">
<view class="item" v-for="(item,index) in months" :key="index"><text class="text">{{item}}月</text>
</view>
</picker-view-column>
<picker-view-column class="picker-view-column">
<view class="item" v-for="(item,index) in days" :key="index"><text class="text">{{item}}日</text></view>
</picker-view-column>
</picker-view>
</view>
</template>
<script lang="uts">
export default {
name: 'PickerDate',
props: {
startYear: { type: Number, default: 1970 },
endYear: { type: Number, default: 2030 },
value: { type: [Array, String], default: () => new Date().toISOString().split('T')[0] } // 支持数组 [year, month, day] 或字符串 "2025-06-09"
},
data() {
// 不能直接 this.startYear需本地变量
const localStartYear = 1970;
const localEndYear = 2030;
const years : number[] = [];
const months : number[] = [];
const days : number[] = [];
for (let i = localStartYear; i <= localEndYear; i++) years.push(i);
for (let i = 1; i <= 12; i++) months.push(i);
for (let i = 1; i <= 31; i++) days.push(i);
// 获取当前日期作为默认值
const now = new Date();
const currentYear = now.getFullYear();
const currentMonth = now.getMonth() + 1;
const currentDay = now.getDate();
let yearIdx = years.indexOf(currentYear);
let monthIdx = months.indexOf(currentMonth);
let dayIdx = days.indexOf(currentDay);
if (yearIdx < 0) yearIdx = 0;
if (monthIdx < 0) monthIdx = 0;
if (dayIdx < 0) dayIdx = 0;
return {
years,
months,
days,
pickerValue: [yearIdx, monthIdx, dayIdx],
localStartYear,
localEndYear,
indicatorStyle: '',
indicatorClass: '',
maskStyle: 'display:none;',
maskClass: '',
maskTopStyle: '',
maskBottomStyle: ''
}
},
created() {
// 生命周期里用 props 初始化本地变量
this.localStartYear = this.startYear;
this.localEndYear = this.endYear;
// 重新生成 years
this.years = [];
for (let i = this.localStartYear; i <= this.localEndYear; i++) this.years.push(i);
// 解析传入的日期值
const [y, m, d] = this.parseValue(this.value);
let yearIdx = this.years.indexOf(y);
let monthIdx = this.months.indexOf(m);
let dayIdx = this.days.indexOf(d);
if (yearIdx < 0) yearIdx = 0;
if (monthIdx < 0) monthIdx = 0;
if (dayIdx < 0) dayIdx = 0;
this.pickerValue = [yearIdx, monthIdx, dayIdx];
},
mounted() {
// 防止 picker-view-column 渲染时未能正确获取当前项,强制刷新 pickerValue
this.$nextTick(() => {
this.pickerValue = [...this.pickerValue];
});
},
watch: {
value(val : any) {
const [y, m, d] = this.parseValue(val);
let yearIdx = this.years.indexOf(y);
let monthIdx = this.months.indexOf(m);
let dayIdx = this.days.indexOf(d);
if (yearIdx < 0) yearIdx = 0;
if (monthIdx < 0) monthIdx = 0;
if (dayIdx < 0) dayIdx = 0;
this.pickerValue = [yearIdx, monthIdx, dayIdx];
}
},
methods: { // 解析日期值,支持数组和字符串格式
parseValue(value : any) : number[] {
if (Array.isArray(value)) {
const valueArray = value as any[];
const year : number = valueArray.length > 0 && typeof valueArray[0] === 'number' ? (valueArray[0] as number) : new Date().getFullYear();
const month : number = valueArray.length > 1 && typeof valueArray[1] === 'number' ? (valueArray[1] as number) : (new Date().getMonth() + 1);
const day : number = valueArray.length > 2 && typeof valueArray[2] === 'number' ? (valueArray[2] as number) : new Date().getDate();
return [year, month, day];
} else if (typeof value === 'string' && value.includes('-')) {
const parts = value.split('-');
const year = parseInt(parts[0]);
const month = parseInt(parts[1]);
const day = parseInt(parts[2]);
const now = new Date();
return [
isNaN(year) ? now.getFullYear() : year,
isNaN(month) ? (now.getMonth() + 1) : month,
isNaN(day) ? now.getDate() : day
];
} else {
// 默认返回当前日期
const now = new Date();
return [now.getFullYear(), now.getMonth() + 1, now.getDate()];
}
},
onChange(e : UniPickerViewChangeEvent) {
const idxs = e.detail.value;
const y = this.years[idxs[0]];
const m = this.months[idxs[1]];
const maxDay = new Date(y, m, 0).getDate();
let d = this.days[idxs[2]];
if (d > maxDay) d = maxDay;
// 返回字符串格式的日期
const monthStr = m < 10 ? '0' + m.toString() : m.toString();
const dayStr = d < 10 ? '0' + d.toString() : d.toString();
const formattedDate = `${y}-${monthStr}-${dayStr}`;
this.$emit('change', formattedDate);
}
}
}
</script>
<style scoped>
.picker-view {
width: 750rpx;
height: 320rpx;
margin-top: 10px;
margin-bottom: 20px;
}
.picker-view-column {
flex: 1;
}
.item {
height: 50px;
color: #000;
}
.text {
line-height: 50px;
text-align: center;
}
</style>