lanan-repair-app/components/commonTimeSelect.vue

237 lines
5.6 KiB
Vue
Raw Normal View History

2025-10-20 11:41:40 +08:00
<template>
<view class="date-range-selector">
2025-10-31 11:27:50 +08:00
<u-subsection :list="filteredDateRangeList" keyName="label" :current="selected"
@change="handleSubsectionChange" />
2025-10-20 11:41:40 +08:00
<uni-datetime-picker :value="internalDateRange" type="daterange" @change="handleDatePickerChange" />
</view>
</template>
<script>
export default {
props: {
// Vue2 中使用 value 作为 v-model 的 prop
value: {
type: Array,
required: true
},
2025-10-31 11:27:50 +08:00
// 模式控制basic-基础范围relative-相对天数all-全部
mode: {
type: String,
default: 'basic', // 'basic' | 'relative' | 'all'
validator: (value) => ['basic', 'relative', 'all'].includes(value)
},
2025-10-20 11:41:40 +08:00
dateRangeList: {
type: Array,
2025-10-31 11:27:50 +08:00
default: () => [
// 基础范围
{
2025-10-20 11:41:40 +08:00
label: "今日",
2025-10-31 11:27:50 +08:00
value: "day",
mode: ['basic', 'all']
2025-10-20 11:41:40 +08:00
},
2025-10-31 11:27:50 +08:00
// {
// label: "本周",
// value: "week",
// mode: ['basic', 'all']
// },
2025-10-20 11:41:40 +08:00
{
2025-10-31 11:27:50 +08:00
label: "本月",
value: "month",
mode: ['basic', 'all']
2025-10-20 11:41:40 +08:00
},
{
2025-10-31 11:27:50 +08:00
label: "本年",
value: "year",
mode: ['basic', 'all']
},
// 相对天数范围
{
label: "近7天",
value: "7days",
mode: ['relative', 'all']
},
{
label: "近30天",
value: "30days",
mode: ['relative', 'all']
},
{
label: "近60天",
value: "60days",
mode: ['relative', 'all']
},
{
label: "近90天",
value: "90days",
mode: ['relative', 'all']
2025-10-20 11:41:40 +08:00
}
]
}
},
data() {
return {
selected: 0,
internalDateRange: this.value
};
},
2025-10-31 11:27:50 +08:00
computed: {
// 根据模式过滤选项列表
filteredDateRangeList() {
return this.dateRangeList.filter(item =>
item.mode.includes(this.mode)
);
}
},
2025-10-20 11:41:40 +08:00
watch: {
value(newVal) {
if (JSON.stringify(newVal) !== JSON.stringify(this.internalDateRange)) {
this.internalDateRange = newVal;
this.resetSelectedIndex();
}
},
internalDateRange(newVal) {
this.$emit('input', newVal); // Vue2 中使用 input 事件
this.$emit('subsection-change', newVal);
2025-10-31 11:27:50 +08:00
},
// 监听模式变化,重置选中状态
mode() {
this.selected = 0;
this.resetToDefaultRange();
2025-10-20 11:41:40 +08:00
}
},
methods: {
// 获取日期范围
getDateRange(type) {
const now = new Date()
let start, end
2025-10-31 11:27:50 +08:00
switch (type) {
case 'week':
// 获取本周的开始(周一)和结束(周日)
const day = now.getDay() || 7 // Sunday 为 0设为 7
start = new Date(now)
start.setDate(now.getDate() - day + 1)
end = new Date(start)
end.setDate(start.getDate() + 6)
break;
case 'month':
// 获取本月的开始和结束
start = new Date(now.getFullYear(), now.getMonth(), 1)
end = new Date(now.getFullYear(), now.getMonth() + 1, 0) // 本月最后一天
break;
case 'day':
// 获取当天的开始和结束00:00:00 到 23:59:59
start = new Date(now)
start.setHours(0, 0, 0, 0)
end = new Date(now)
end.setHours(23, 59, 59, 999)
break;
case 'year':
// 获取本年的开始和结束
start = new Date(now.getFullYear(), 0, 1); // 本年1月1日
end = new Date(now.getFullYear(), 11, 31); // 本年12月31日
break;
case '7days':
// 近7天
end = new Date(now);
end.setHours(23, 59, 59, 999);
start = new Date(now);
start.setDate(now.getDate() - 6);
start.setHours(0, 0, 0, 0);
break;
case '30days':
// 近30天
end = new Date(now);
end.setHours(23, 59, 59, 999);
start = new Date(now);
start.setDate(now.getDate() - 29);
start.setHours(0, 0, 0, 0);
break;
case '60days':
// 近60天
end = new Date(now);
end.setHours(23, 59, 59, 999);
start = new Date(now);
start.setDate(now.getDate() - 59);
start.setHours(0, 0, 0, 0);
break;
case '90days':
// 近90天
end = new Date(now);
end.setHours(23, 59, 59, 999);
start = new Date(now);
start.setDate(now.getDate() - 89);
start.setHours(0, 0, 0, 0);
break;
default:
console.warn('不支持的类型:', type)
return []
2025-10-20 11:41:40 +08:00
}
return [
this.formatDateCus(start),
this.formatDateCus(end)
]
},
// 格式化日期
formatDateCus(date) {
const y = date.getFullYear()
const m = (date.getMonth() + 1).toString().padStart(2, '0')
const d = date.getDate().toString().padStart(2, '0')
return `${y}-${m}-${d}`
},
handleSubsectionChange(index) {
this.selected = index;
const {
value
2025-10-31 11:27:50 +08:00
} = this.filteredDateRangeList[index];
2025-10-20 11:41:40 +08:00
this.internalDateRange = this.getDateRange(value);
},
2025-10-31 11:27:50 +08:00
2025-10-20 11:41:40 +08:00
handleDatePickerChange(newRange) {
this.internalDateRange = newRange;
this.resetSelectedIndex();
},
2025-10-31 11:27:50 +08:00
2025-10-20 11:41:40 +08:00
resetSelectedIndex() {
2025-10-31 11:27:50 +08:00
const filteredList = this.filteredDateRangeList;
const selectedIndex = filteredList.findIndex((item) => {
2025-10-20 11:41:40 +08:00
const range = this.getDateRange(item.value);
return JSON.stringify(range) === JSON.stringify(this.internalDateRange);
});
2025-10-31 11:27:50 +08:00
this.selected = selectedIndex !== -1 ? selectedIndex : -1;
},
// 重置到默认范围
resetToDefaultRange() {
const defaultType = this.filteredDateRangeList[0]?.value || 'day';
this.internalDateRange = this.getDateRange(defaultType);
2025-10-20 11:41:40 +08:00
}
},
created() {
2025-10-31 11:27:50 +08:00
// 默认选择第一个选项
2025-10-20 11:41:40 +08:00
if (!this.value || this.value.length === 0) {
2025-10-31 11:27:50 +08:00
this.resetToDefaultRange();
2025-10-20 11:41:40 +08:00
} else {
this.resetSelectedIndex();
}
}
};
</script>
<style scoped>
.date-range-selector {
/* 可以写样式 */
}
</style>