168 lines
5.4 KiB
Plaintext
168 lines
5.4 KiB
Plaintext
<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> |