Files
yudao-dev/src/views/home/components/Header.vue
‘937886381’ 2d200dd1a6 修改
2025-12-09 16:55:39 +08:00

420 lines
13 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>
<header class="report-header">
<!-- 左侧区域logo + 标题 -->
<div class="left-content">
<img style="height: 36px;" src="../../../assets/img/cnbm.png" alt="benmaLogo" >
<div class="top-title">{{ topTitle }}</div>
</div>
<div class="center-content">
<!-- 循环 pageRoutes不再硬编码文字 -->
<div class="item" v-for="(page, index) in pageRoutes" :key="index" @click="goToPage(page.path, index)">
<span class="item-text">{{ page.text }}</span>
</div>
</div>
<!-- :class="{ 'no-skew': activeIndex === index }
" -->
<!-- 右侧区域全屏按钮 -->
<div class="right-content">
<el-button type="text" class="screen-btn" :title="isFullScreen ? '退出全屏' : '全屏'" @click="changeFullScreen">
<svg-icon style="color: #0B58FF;" v-if="isFullScreen" icon-class="unFullScreenView" />
<svg-icon style="color: #0B58FF;" v-else icon-class="fullScreenView" />
</el-button>
</div>
<!-- 时间选择区域//年按钮 + label + 日期选择器 -->
<div class="timeType">
<div class="item" v-for="(item, index) in timeTypes" :key="index" @click="activeTime = index"
:class="{ 'no-skew': activeTime === index }">
<span class="item-text">{{ item.text }}</span>
</div>
<div class="dateP">
<div class="label">
<span class="label-text">日期选择</span>
</div>
<el-date-picker v-model="date" :type="getPickerType" :placeholder="getPickerPlaceholder"
class="custom-date-picker" style="width: 132px;height: 29px;" @change="emitTimeRange" />
</div>
</div>
</header>
</template>
<script>
import moment from 'moment'
export default {
name: 'Header',
props: {
isFullScreen: { type: Boolean, default: false },
topTitle: { type: String, default: '' }
},
data() {
return {
currentTime: '',
timeTimer: null,
date: undefined,
activeIndex: -1,
activeTime: 1, // 0=日1=月2=年(默认选中“日”)
pageRoutes: [
{ text: '营业收入', path: '/operatingRevenue' },
{ text: '利润分析', path: '/profitAnalysis' },
{ text: '产销率库存分析', path: '/PSIAnal' },
{ text: '成本分析', path: '/cost/cost' },
{ text: '驾驶舱报表', path: '/cockpit' }
],
// 定义时间类型配置text=按钮文字pickerType=选择器类型placeholder=占位符
timeTypes: [
{ text: '日', pickerType: 'date', placeholder: '选择日期' },
{ text: '月', pickerType: 'month', placeholder: '选择月份' },
{ text: '年', pickerType: 'year', placeholder: '选择年份' }
]
}
},
computed: {
// 动态获取日期选择器类型
getPickerType() {
return this.timeTypes[this.activeTime].pickerType;
},
// 动态获取日期选择器占位符
getPickerPlaceholder() {
return this.timeTypes[this.activeTime].placeholder;
}
},
methods: {
goToPage(path, index) {
// 1. 跳转到对应路由
this.$router.push(path);
// 2. 更新activeIndex让当前点击项高亮
this.activeIndex = index;
},
changeFullScreen() { this.$emit('screenfullChange') },
padZero(num) { return num < 10 ? '0' + num : num },
/**
* 核心方法1根据维度计算时间区间首次进入时基于赋值的当月日期计算“当月第一天0点→次月第一天0点”
* @returns {Object} 包含 start开始时间、end结束时间、dimension维度的区间对象
*/
calculateTimeRange() {
let startTime = 0;
let endTime = 0;
const mode = this.activeTime + 1; // 1=日2=月3=年
const defaultMoment = moment(); // 默认当前时间
const targetMoment = this.date
? moment(this.date, this.getPickerType === 'date' ? 'YYYY-MM-DD' : (this.getPickerType === 'month' ? 'YYYY-MM' : 'YYYY'))
: defaultMoment;
if (!targetMoment.isValid()) {
console.error('无效日期:', this.date);
return { startTime, endTime, mode };
}
// 1. 日维度00:00:00 → 23:59:59无毫秒
if (this.activeTime === 0) {
startTime = targetMoment.startOf('day').millisecond(0).valueOf();
endTime = targetMoment.endOf('day').millisecond(0).valueOf();
}
// 2. 月维度当月1日00:00:00 → 当月最后一天23:59:59无毫秒
else if (this.activeTime === 1) {
startTime = targetMoment.startOf('month').millisecond(0).valueOf();
endTime = targetMoment.endOf('month').millisecond(0).valueOf();
}
// 3. 年维度当年1月1日00:00:00 → 当年最后一天23:59:59无毫秒
else if (this.activeTime === 2) {
startTime = targetMoment.startOf('year').millisecond(0).valueOf();
endTime = targetMoment.endOf('year').millisecond(0).valueOf();
}
// 调试输出:验证是否去掉毫秒
console.log('时间范围计算结果:', {
mode,
startTime: moment(startTime * 1000).format('YYYY-MM-DD HH:mm:ss'), // 格式2025-11-30 00:00:00
endTime: moment(endTime * 1000).format('YYYY-MM-DD HH:mm:ss'), // 格式2025-11-30 23:59:59无毫秒
startTimeStamp: startTime, // 秒级时间戳1764422400
endTimeStamp: endTime // 秒级时间戳1764508799
});
return { startTime, endTime, mode };
},
/**
* 核心方法2传递时间区间给父组件首次进入时触发传递“当月第一天0点→次月第一天0点”
*/
emitTimeRange() {
const timeRange = this.calculateTimeRange();
this.$emit('timeRangeChange', timeRange);
// 调试用:查看首次传递的区间(如{start: "2025-10-01T00:00:00", end: "2025-11-01T00:00:00", dimension: "月"}
console.log('当前时间区间:', timeRange);
}
},
watch: {
// 维度切换时:清空选择的日期,并传递当前维度的默认区间
activeTime(newVal, oldVal) {
if (newVal !== oldVal) {
this.date = undefined;
// this.emitTimeRange();
}
}
},
mounted() {
// 核心逻辑:首次进入页面,计算当月默认日期并赋值给选择器,同时传递区间
const now = new Date();
const year = now.getFullYear();
const month = this.padZero(now.getMonth() + 1); // 月份从0开始+1后补零如1月→01
// 赋值当月默认日期格式YYYY-MM适配month类型选择器
this.date = `${year}-${month}`;
// 确保选择器渲染完成后传递“当月第一天0点→次月第一天0点”的区间
this.$nextTick(() => this.emitTimeRange());
},
}
</script>
<style scoped lang="scss">
/* 原有样式不变仅补充label文字的倾斜抵消样式 */
@font-face {
font-family: "YouSheBiaoTiHei";
src: url('../../../assets/fonts/YouSheBiaoTiHe.ttf') format('truetype');
}
.report-header {
height: 117px;
width: 100%;
display: flex;
justify-content: space-around;
background: url('../../../assets/img/topTitle.png') no-repeat;
background-size: cover;
background-position: 0 0;
box-sizing: border-box;
position: relative;
/* 确保timeType绝对定位生效 */
.left-content {
margin-top: 11px;
margin-left: 44px;
height: 55px;
display: flex;
align-items: center;
gap: 16px;
}
.top-title {
height: 55px;
font-family: "YouSheBiaoTiHei", sans-serif;
font-size: 42px;
color: #1E1651;
line-height: 55px;
letter-spacing: 6px;
text-align: left;
}
.center-content {
display: flex;
gap: 8px;
margin-top: 18px;
margin-left: 70px;
.item {
width: 180px;
height: 50px;
background: #E1EEFC;
transform: skew(-20deg);
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 20px;
color: #1E1651;
line-height: 50px;
letter-spacing: 2px;
text-align: center;
cursor: pointer;
overflow: hidden;
box-shadow: 0px 13px 16px 0px rgba(179, 217, 255, 0.43),
0px 2px 4px 0px rgba(92, 140, 255, 0.25),
inset 0px -43px 13px 0px rgba(255, 255, 255, 0.51);
.item-text {
display: inline-block;
transform: skew(20deg);
}
}
.item.no-skew {
background: none !important;
transform: none !important;
box-shadow: none !important;
color: #1E1651;
.item-text {
transform: none !important;
}
}
}
.timeType {
position: absolute;
display: flex;
align-items: center;
/* 垂直居中,避免元素高低错位 */
top: 42px;
right:10px;
margin-top: 18px;
gap: 0;
/* 清除间隙,让按钮与选择器紧密连接 */
}
.timeType .item {
width: 40px;
height: 28px;
background: rgba(236, 244, 254, 1);
transform: skew(-20deg);
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 14px;
color: rgba(11, 88, 255, 1);
line-height: 28px;
letter-spacing: 2px;
text-align: center;
cursor: pointer;
overflow: hidden;
/* 选中按钮与未选中按钮倾斜角度统一,避免切换时跳动 */
}
.timeType .item .item-text {
display: inline-block;
transform: skew(20deg);
transition: all 0.2s ease;
}
.timeType .item.no-skew {
background: rgba(11, 88, 255, 1);
color: rgba(249, 252, 255, 1);
transform: skew(-20deg) !important;
/* 统一倾斜角度修复原30deg的错位 */
box-shadow: 0 2px 8px rgba(11, 88, 255, 0.3);
}
.timeType .item.no-skew .item-text {
transform: skew(20deg) !important;
/* 同步统一文字倾斜角度 */
}
.dateP {
position: relative;
margin-left: 30px;
display: flex;
align-items: center;
gap: 0;
}
.dateP .label {
width: 70px;
height: 28px;
background: rgba(236, 244, 254, 1);
transform: skew(-25deg);
/* 与按钮倾斜角度统一原30deg改为25deg避免视觉错位 */
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 14px;
color: #0B58FF;
line-height: 28px;
text-align: center;
overflow: hidden;
}
/* 补充label文字抵消倾斜原代码遗漏导致文字倾斜 */
.dateP .label-text {
display: inline-block;
transform: skew(25deg);
/* 与label倾斜角度相反确保文字正立 */
}
.right-content {
display: flex;
flex-direction: column;
margin-top: 12px;
margin-right: 4px;
gap: 20px;
}
.current-time {
color: #FFFFFF;
font-family: PingFangSC, PingFang SC;
font-weight: 500;
font-size: 22px;
line-height: 24px;
letter-spacing: 1px;
}
.screen-btn {
width: 26px;
margin-left: 300px;
color: #00fff0;
font-size: 26px;
padding: 0;
}
}
/* 日期选择器样式保持不变 */
::v-deep .custom-date-picker {
position: absolute;
right: 8px;
width: 132px !important;
height: 28px !important;
position: relative;
margin: 0 !important;
/* 1. 调整输入框文字:确保行高与输入框高度一致,垂直居中 */
.el-input__inner {
height: 28px !important;
width: 132px !important;
text-align: center;
padding-left: 15px !important;
padding-right: 32px !important;
/* 给图标留空间,避免文字被遮挡 */
font-size: 14px !important;
line-height: 28px !important;
/* 行高=输入框高度,文字垂直居中 */
color: rgba(237, 245, 253, 1) !important;
vertical-align: middle !important;
/* 强制文字垂直对齐 */
clip-path: polygon(18px 0, 100% 0, 100% 100%, 0 100%);
border: none !important;
box-shadow: none !important;
background-color: rgba(11, 88, 255, 1) !important;
border-left: 1px solid rgba(255, 255, 255, 0.2);
}
/* 2. 调整图标容器:让图标与文字在同一水平线上 */
.el-input__prefix {
left: auto !important;
right: 8px !important;
top: 50% !important;
/* 从40%改为50%,基于输入框垂直居中 */
transform: translateY(-50%) !important;
/* 向上偏移自身50%,精准居中 */
display: inline-flex !important;
/* 让容器内图标垂直居中 */
align-items: center !important;
/* 图标在容器内垂直居中 */
height: 28px !important;
/* 容器高度=输入框高度,避免偏移 */
}
/* 3. 调整图标本身:确保图标大小和对齐方式 */
.el-input__icon {
color: #ffffff !important;
font-size: 16px !important;
line-height: 28px !important;
/* 图标行高=输入框高度,与文字对齐 */
vertical-align: middle !important;
/* 强制图标垂直对齐 */
}
/* 4. 图标伪类:确保颜色和对齐继承 */
.el-icon-date::before {
color: #ffffff !important;
font-size: 16px !important;
line-height: inherit !important;
/* 继承父级行高,避免错位 */
}
}
</style>