Files
profitManage1.1/src/components/echartsList/dateTimeSelect.vue
2025-10-16 19:08:32 +08:00

263 lines
11 KiB
Vue
Raw 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>
<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月→085日→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>