263 lines
11 KiB
Vue
263 lines
11 KiB
Vue
<template>
|
||
<div class="ultabs" :style="{'margin-top': dateShowType && (dateShowType === 'day' || dateShowType === 'month') ? '35px' : '10px'}">
|
||
<div v-if="sideIcon" style="display: inline-block;padding-left: 1px;float: right;">
|
||
<el-dropdown trigger="click">
|
||
<span class="el-dropdown-link">
|
||
<i style="font-size: 1.5rem;margin-top: 5px;" class="el-icon-s-tools"></i>
|
||
</span>
|
||
<el-dropdown-menu slot="dropdown">
|
||
<el-dropdown-item v-for="item of sideIcon && sideIcon.iconName" class="clearfix">
|
||
<div @click="onChange(item)">{{item.name}}</div>
|
||
</el-dropdown-item>
|
||
</el-dropdown-menu>
|
||
</el-dropdown>
|
||
</div>
|
||
<ul style="display: inline-block;padding-left: 1px;vertical-align: middle;margin:0;float: right;">
|
||
<template v-if="dateShowType === 'day'">
|
||
<li :class="{ 'activesbgs' : isActive == 'DAY' }" @click="toggle('DAY',7)">前7天</li>
|
||
<li :class="{ 'activesbgs' : isActive == 'WEEK' }" @click="toggle('WEEK',15)">前15天</li>
|
||
<li :class="{ 'activesbgs' : isActive == 'MONTH' }" @click="toggle('MONTH')">前一个月</li>
|
||
</template>
|
||
<template v-if="dateShowType === 'month'">
|
||
<li :class="{ 'activesbgs' : isActive == 'THREEMONTH' }" @click="toggle('THREEMONTH', 3)">前三个月</li>
|
||
<li :class="{ 'activesbgs' : isActive == 'HALFYEAR' }" @click="toggle('HALFYEAR', 6)">前半年</li>
|
||
<li :class="{ 'activesbgs' : isActive == 'YEAR' }" @click="toggle('YEAR', 12)">前一年</li>
|
||
</template>
|
||
</ul>
|
||
<el-date-picker
|
||
v-model="dateRange"
|
||
:class="dateShowType === 'datetimerange' ? null : 'timeIconSty'"
|
||
:type="dateShowType === 'month' ? 'monthrange' : dateShowType === 'day' ? 'daterange' : dateShowType ? dateShowType : 'daterange'"
|
||
:start-placeholder="dateShowType === 'month' ? '开始日期' : '开始时间'"
|
||
:end-placeholder="dateShowType === 'month' ? '结束日期' : '结束时间'"
|
||
range-separator="至"
|
||
:format="dateShowType === 'month' ? 'yyyy-MM' : dateShowType === 'datetimerange' ? 'yyyy-MM-dd HH:mm:ss' : 'yyyy-MM-dd' "
|
||
:value-format="dateShowType === 'month' ? 'yyyy-MM' : dateShowType === 'datetimerange' ? 'yyyy-MM-dd HH:mm:ss' : 'yyyy-MM-dd'"
|
||
:style="{display: 'inline-block!important', verticalAlign: 'middle', marginRight: '10px', float: 'right', width: dateShowType === 'datetimerange' ? '75%!important' : '45%!important'}"
|
||
:default-time="dateShowType === 'datetimerange' ? ['12:00:00', '12:00:00'] : null"
|
||
@change="dateChange"/>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
export default {
|
||
name: 'dateTimeSelect',
|
||
props: {
|
||
dateShowType: {
|
||
type: String,
|
||
default: null
|
||
},
|
||
sideIcon: {
|
||
type: Object,
|
||
default: () => {}
|
||
},
|
||
dateDataTrans: {
|
||
type: Object,
|
||
default: () => {}
|
||
}
|
||
},
|
||
watch: {
|
||
dateDataTrans: {
|
||
handler(val) {
|
||
if (val && val.dateRange) {
|
||
this.dateRange = val.dateRange;
|
||
}
|
||
},
|
||
deep: true,
|
||
immediate: true
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
dateRange: [],
|
||
isActive: ''
|
||
}
|
||
},
|
||
// DOM 挂载完成后
|
||
mounted() {
|
||
this.isActive = this.dateShowType && this.dateShowType === 'day' ? 'MONTH' : 'YEAR';
|
||
// 可以访问 DOM 元素
|
||
// setTimeout(() => {
|
||
// // this.getLastDays(6);
|
||
// // this.getDaysOfPreviousMonth();
|
||
// this.$emit("dataChange", this.isActive, []);
|
||
// }, 500);
|
||
},
|
||
methods: {
|
||
toggle(val, num) {
|
||
this.isActive = val;
|
||
this.dateRange = [];
|
||
if (val && val === 'MONTH') {
|
||
this.getDaysOfPreviousMonth();
|
||
} else if (val && (val === 'THREEMONTH' || val === 'HALFYEAR' || val === 'YEAR')) {
|
||
this.getLastMonths(num);
|
||
} else {
|
||
this.getLastDays(num - 1);
|
||
}
|
||
},
|
||
// 时间选择器
|
||
dateChange() {
|
||
if (this.dateDataTrans && this.dateDataTrans.transList) {
|
||
this.getDaysOfPreviousMonth(this.dateRange[0], this.dateRange[1]);
|
||
} else {
|
||
this.$emit("dataChange", this.isActive, this.dateRange);
|
||
this.isActive = '';
|
||
}
|
||
},
|
||
// 获取当前日期前7天的所有日期(格式:YYYY-MM-DD)
|
||
getLastDays(num) {
|
||
const dayList = [];
|
||
const today = new Date();
|
||
|
||
for (let i = num; i >= 0; i--) {
|
||
const d = new Date(today);
|
||
d.setDate(today.getDate() - i);
|
||
|
||
// 格式化日期为 YYYY-MM-DD
|
||
const year = d.getFullYear();
|
||
const month = String(d.getMonth() + 1).padStart(2, '0');
|
||
const day = String(d.getDate()).padStart(2, '0');
|
||
|
||
dayList.push(`${year}-${month}-${day}`);
|
||
}
|
||
let timeArr = [dayList[0], dayList[dayList.length - 1]];
|
||
this.$emit("dataChange", this.isActive, timeArr);
|
||
// this.$emit("dataChange", this.isActive, dayList);
|
||
},
|
||
// 获取前一个月的所有日期
|
||
getDaysOfPreviousMonth(star, end) {
|
||
// 1. 获取当前日期(终点日期)
|
||
let currentDate = new Date();
|
||
if (end) {
|
||
currentDate = new Date(end);
|
||
}
|
||
const endYear = currentDate.getFullYear();
|
||
const endMonth = currentDate.getMonth(); // 0=1月,11=12月
|
||
const endDay = currentDate.getDate(); // 当前日(如8)
|
||
|
||
// 2. 计算起点日期(当前日期的“上月同日”,处理边界:如3月31日→2月28/29日)
|
||
let startDate = new Date(endYear, endMonth, endDay);
|
||
if (star) {
|
||
startDate = new Date(star);
|
||
} else {
|
||
// 核心:将当前日期的月份减1(得到上月同日,自动处理天数不足问题)
|
||
startDate.setMonth(startDate.getMonth() - 1);
|
||
}
|
||
// 日期后面的时间
|
||
let timeStar = '';
|
||
let timeEnd = '';
|
||
if (this.dateShowType === 'datetimerange') {
|
||
timeStar = String(new Date(startDate).getHours()).padStart(2, '0') + ':' + String(new Date(startDate).getMinutes()).padStart(2, '0') + ':' + String(new Date(startDate).getSeconds()).padStart(2, '0');
|
||
timeEnd = String(new Date(currentDate).getHours()).padStart(2, '0') + ':' + String(new Date(currentDate).getMinutes()).padStart(2, '0') + ':' + String(new Date(currentDate).getSeconds()).padStart(2, '0');
|
||
}
|
||
|
||
// 3. 提取起点日期的年、月、日(用于循环判断)
|
||
const startYear = startDate.getFullYear();
|
||
const startMonth = startDate.getMonth();
|
||
const startDay = startDate.getDate();
|
||
|
||
// 4. 循环生成“起点~终点”的所有日期
|
||
const dateCollection = [];
|
||
// 临时日期:从起点日期开始递增
|
||
const tempDate = new Date(startYear, startMonth, startDay);
|
||
|
||
// 循环条件:临时日期 <= 当前日期(终点)
|
||
while (tempDate <= currentDate) {
|
||
// 格式化日期为“YYYY-MM-DD”(补零处理:如8月→08,5日→05)
|
||
const year = tempDate.getFullYear();
|
||
const month = String(tempDate.getMonth() + 1).padStart(2, '0');
|
||
const day = String(tempDate.getDate()).padStart(2, '0');
|
||
let formattedDate = `${year}-${month}-${day}`;
|
||
if (this.dateShowType === 'datetimerange') {
|
||
if (dateCollection && dateCollection.length <= 0) {
|
||
formattedDate = formattedDate + ' ' + timeStar;
|
||
} else {
|
||
formattedDate = formattedDate + ' ' + timeEnd;
|
||
}
|
||
}
|
||
dateCollection.push(formattedDate);
|
||
// 临时日期加1天(进入下一天)
|
||
tempDate.setDate(tempDate.getDate() + 1);
|
||
}
|
||
let timeArr = [dateCollection[0], dateCollection[dateCollection.length - 1]];
|
||
this.$emit("dataChange", this.isActive, {timeArr: timeArr, timeList: dateCollection});
|
||
// this.$emit("dataChange", this.isActive, oneMonthDays);
|
||
},
|
||
// 获取前三个月的月
|
||
getLastMonths(num) {
|
||
const threeMonths = [];
|
||
const today = new Date(); // 当前日期
|
||
const currentYear = today.getFullYear();
|
||
const currentMonth = today.getMonth() + 1; // 月份从0开始(0=1月,11=12月)
|
||
// 循环获取前3个月(i=0: 前1个月,i=1: 前2个月,i=2: 前3个月)
|
||
for (let i = 1; i <= num; i++) {
|
||
// 计算目标月份(当前月 - i)
|
||
let targetMonth = currentMonth - i;
|
||
let targetYear = currentYear;
|
||
// 处理月份溢出(如1月-1=12月,年份减1)
|
||
if (targetMonth < 0) {
|
||
targetMonth += 12;
|
||
targetYear -= 1;
|
||
}
|
||
// 格式化月份为两位数(如5月→'05')
|
||
const monthStr = String(targetMonth + 1).padStart(2, '0'); // 加1是因为月份从0开始
|
||
threeMonths.unshift(`${targetYear}-${monthStr}`);
|
||
}
|
||
let timeArr = [threeMonths[0], threeMonths[threeMonths.length - 1]];
|
||
this.$emit("dataChange", this.isActive, timeArr);
|
||
// this.$emit("dataChange", this.isActive, threeMonths);
|
||
},
|
||
onChange(val){
|
||
this.$emit("dataChange", null, null, val);
|
||
},
|
||
}
|
||
}
|
||
</script>
|
||
<style scoped>
|
||
::v-deep .el-range-editor .el-range-input {
|
||
vertical-align: super!important;
|
||
}
|
||
::v-deep .el-date-editor .el-range-separator {
|
||
vertical-align: super!important;
|
||
}
|
||
::v-deep .timeIconSty .el-range__close-icon {
|
||
margin-top: -38px;
|
||
margin-right: -14px;
|
||
}
|
||
.ultabs {
|
||
width: 500px;
|
||
float: right;
|
||
position: relative;
|
||
z-index: 9;
|
||
}
|
||
|
||
.ultabs ul li {
|
||
user-select: none;
|
||
cursor: pointer;
|
||
list-style: none;
|
||
display: inline-block;
|
||
width: 70px;
|
||
text-align: center;
|
||
height: 38px;
|
||
line-height: 38px;
|
||
}
|
||
/*.ultabs ul li:nth-child样式做了更改*/
|
||
.ultabs ul li {
|
||
border-radius: 4px;
|
||
border: 1px solid #CCCCCC;
|
||
margin: 0 5px;
|
||
}
|
||
.activesbgs {
|
||
color: #FFF;
|
||
background: #5D78FF;
|
||
cursor: pointer;
|
||
list-style: none;
|
||
display: inline-block;
|
||
width: 70px;
|
||
text-align: center;
|
||
height: 40px !important;
|
||
line-height: 40px !important;
|
||
border: 1px solid #5D78FF;
|
||
}
|
||
</style>
|