This commit is contained in:
‘937886381’
2025-11-14 14:16:43 +08:00
parent 5ddab768ef
commit 3d167e8d71
21 changed files with 717 additions and 144 deletions

View File

@@ -70,7 +70,7 @@ export default {
label: { backgroundColor: '#6a7985' } label: { backgroundColor: '#6a7985' }
} }
}, },
grid: { top: 10, bottom: 20, right: 25, left: 30 }, grid: { top: 10, bottom: 20, right: 25, left: 50 },
xAxis: [ xAxis: [
{ {
type: 'category', type: 'category',
@@ -94,9 +94,9 @@ export default {
yAxis: { yAxis: {
type: 'value', type: 'value',
nameTextStyle: { color: 'rgba(0, 0, 0, 0.45)', fontSize: 14, align: 'left' }, nameTextStyle: { color: 'rgba(0, 0, 0, 0.45)', fontSize: 14, align: 'left' },
min: () => 0, // min: () => 0,
max: (value) => Math.ceil(value.max), // max: (value) => Math.ceil(value.max),
scale: true, // scale: true,
axisTick: { show: false }, axisTick: { show: false },
axisLabel: { color: 'rgba(0, 0, 0, 0.45)', fontSize: 12 }, axisLabel: { color: 'rgba(0, 0, 0, 0.45)', fontSize: 12 },
splitLine: { lineStyle: { color: 'rgba(0, 0, 0, 0.15)' } }, splitLine: { lineStyle: { color: 'rgba(0, 0, 0, 0.15)' } },

View File

@@ -22,7 +22,7 @@
<div class="right"> <div class="right">
<!-- 完成率颜色动态绑定 --> <!-- 完成率颜色动态绑定 -->
<div class="number" :style="{ 'color': item.completed === 0 ? '#FF8400' : 'rgba(54, 181, 138, .7)' }"> <div class="number" :style="{ 'color': item.completed === 0 ? '#FF8400' : 'rgba(54, 181, 138, .7)' }">
{{ item.proportion !== null && item.proportion !== undefined ? (item.proportion * 100) + '%' : '0%' }} {{ item.proportion !== null && item.proportion !== undefined ? (item.proportion) + '%' : '0%' }}
</div> </div>
<div class="title">完成率</div> <div class="title">完成率</div>
</div> </div>

View File

@@ -23,7 +23,7 @@
<div class="right"> <div class="right">
<!-- 完成率颜色动态绑定 --> <!-- 完成率颜色动态绑定 -->
<div class="number" :style="{ 'color': item.completed === 0 ? '#FF8400' : 'rgba(54, 181, 138, .7)' }"> <div class="number" :style="{ 'color': item.completed === 0 ? '#FF8400' : 'rgba(54, 181, 138, .7)' }">
{{ item.proportion !== null && item.proportion !== undefined ? (item.proportion * 100) + '%' : '0%' }} {{ item.proportion !== null && item.proportion !== undefined ? (item.proportion) + '%' : '0%' }}
</div> </div>
<div class="title">完成率</div> <div class="title">完成率</div>
</div> </div>

View File

@@ -80,7 +80,7 @@ export default {
return { return {
targetValue: targetItem?.[`${field}Target`] || 0, // 对应指标的目标值字段(如 profitTarget targetValue: targetItem?.[`${field}Target`] || 0, // 对应指标的目标值字段(如 profitTarget
value: targetItem?.[field] || 0, // 对应指标的实际值 value: targetItem?.[field] || 0, // 对应指标的实际值
proportion: (targetItem?.[`${field}Proportion`] || 0) * 100, // 对应指标的占比(转百分比) proportion: (targetItem?.[`${field}Proportion`] || 0), // 对应指标的占比(转百分比)
completed: targetItem?.[`${field}Completed`] ?? 0 // 状态字段(复用分公司的 completed completed: targetItem?.[`${field}Completed`] ?? 0 // 状态字段(复用分公司的 completed
}; };
}); });

View File

@@ -6,7 +6,7 @@
<div class="content-wrapper"> <div class="content-wrapper">
<div class="left"> <div class="left">
<div class="number" style="color: rgba(103, 103, 103, 0.79);">{{ item.targetValue }}</div> <div class="number" style="color: rgba(103, 103, 103, 0.79);">{{ item.targetValue }}</div>
<div class="title">目标值</div> <div class="title" style="color: rgba(134, 134, 135, 1);">目标值</div>
</div> </div>
<div class="line"></div> <div class="line"></div>
<!-- 实际值根据 实际值目标值 动态绑定类名 --> <!-- 实际值根据 实际值目标值 动态绑定类名 -->
@@ -17,7 +17,7 @@
}"> }">
{{ item.currentValue }} {{ item.currentValue }}
</div> </div>
<div class="title">实际值</div> <div class="title" style="color: rgba(134, 134, 135, 1);">实际值</div>
</div> </div>
</div> </div>
<div class="line"></div> <div class="line"></div>
@@ -236,7 +236,7 @@ export default {
/* 百分比 - 实际值≥目标值(绿色) */ /* 百分比 - 实际值≥目标值(绿色) */
.percent-exceed { .percent-exceed {
color: #28CB97 !important; color: rgba(54, 181, 138, 1) !important;
} }
/* 百分比 - 实际值<目标值(黄色) */ /* 百分比 - 实际值<目标值(黄色) */

View File

@@ -55,14 +55,14 @@ export default {
unit: "原片成本·元/㎡", unit: "原片成本·元/㎡",
route: "cost/cost", route: "cost/cost",
target: 16, target: 16,
actual: 18, actual: 16,
progress: 110 progress: 110
}, },
{ {
unit: "加工成本·元/㎡", unit: "加工成本·元/㎡",
route: "cost/cost", route: "cost/cost",
target: 16, target: 16,
actual: 14, actual: 16,
progress: 85 progress: 85
}, },
{ {

View File

@@ -1,25 +1,29 @@
<template> <template>
<div class="coreItem" :style="{ 'height': height + 'px' }"> <div class="coreItem" :style="{ 'height': height + 'px' }">
<!-- v-for 动态生成每个 item --> <!-- 遍历每个item使用item自身的flag -->
<div class="item" v-for="(item, index) in itemList" :key="index"> <div class="item" v-for="(item, index) in itemList" :key="index">
<div class="unit">{{ item.name }}</div> <div class="unit">{{ item.name }}</div>
<div class="item-content"> <div class="item-content">
<!-- 左右内容容器 -->
<div class="content-wrapper"> <div class="content-wrapper">
<div class="left"> <div class="left">
<div class="number"> {{ item.targetValue || 0 }}</div> <div class="number"> {{ item.targetValue || 0 }}</div>
<div class="title">目标值</div> <div class="title">目标值</div>
</div> </div>
<div class="line"></div> <div class="line"></div>
<!-- 实际值根据 flag 动态绑定颜色 --> <!-- 实际值使用当前item的flag判断颜色 -->
<div class="right"> <div class="right">
<div class="number" :style="{ 'color': flagColor }"> {{ item.value || 0 }}</div> <div class="number"
:style="{ 'color': item.flag === 0 ? 'rgba(255, 132, 0, 1)' : 'rgba(54, 181, 138, 1)' }">
{{ item.value || 0 }}
</div>
<div class="title">实际值</div> <div class="title">实际值</div>
</div> </div>
<div class="line"></div> <div class="line"></div>
<!-- 完成率根据 flag 动态绑定颜色 --> <!-- 完成率同样使用当前item的flag判断颜色 -->
<div class="right"> <div class="right">
<div class="number" :style="{ 'color': flagColor }"> {{ item.proportion !== null && item.proportion !== undefined ? (item.proportion) + '%' : '0%' }} <div class="number"
:style="{ 'color': item.flag === 0 ? 'rgba(255, 132, 0, 1)' : 'rgba(54, 181, 138, 1)' }">
{{ item.proportion != null ? (item.proportion + '%') : '0%' }}
</div> </div>
<div class="title">完成率</div> <div class="title">完成率</div>
</div> </div>
@@ -35,23 +39,15 @@ export default {
components: {}, components: {},
props: [ props: [
'itemList', 'itemList',
'height', 'height'
'flag' // 新增 flag 属性,用于控制颜色 // 移除组件级的flag属性不再需要
], ],
data() { data() {
return { return {
progress: 90, progress: 90,
}; };
}, },
computed: { // 移除flagColor计算属性改为item级判断
// 根据 flag 计算实际值和完成率的颜色
flagColor() {
// flag 为 0 时使用灰色,为 1 时使用橙色
return this.flag === 1
? 'rgba(255, 132, 0, 1)'
: 'rgba(54, 181, 138, 1)';
}
},
watch: { watch: {
itemList: { itemList: {
handler(newList) { handler(newList) {
@@ -65,7 +61,7 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
/* 原有样式保持不变 */ /* 样式保持不变 */
.coreItem { .coreItem {
display: flex; display: flex;
overflow: hidden; overflow: hidden;
@@ -122,7 +118,7 @@ export default {
height: 46px; height: 46px;
background: linear-gradient(to bottom, background: linear-gradient(to bottom,
rgba(255, 0, 0, 0), rgba(255, 0, 0, 0),
rgba(203, 203, 203, 1.00)); rgba(203, 203, 203, 1.00));
} }
.left, .left,
@@ -143,7 +139,6 @@ export default {
line-height: 22px; line-height: 22px;
text-align: center; text-align: center;
font-style: normal; font-style: normal;
/* 颜色由动态样式绑定控制,此处不设置默认值 */
} }
.title { .title {

View File

@@ -6,7 +6,7 @@
<!-- 新增topItem 专属包裹容器统一控制样式和布局 --> <!-- 新增topItem 专属包裹容器统一控制样式和布局 -->
<div class="topItem-container" style="display: flex; flex-direction: column;gap: 16px;overflow: hidden;"> <div class="topItem-container" style="display: flex; flex-direction: column;gap: 16px;overflow: hidden;">
<!-- <topItem :itemList="parentItemList" /> --> <!-- <topItem :itemList="parentItemList" /> -->
<rawItem :itemList="itemData" /> <rawItem :itemList="sortedItemData" />
</div> </div>
<!-- 2. .top 保持 flex无需固定高度自动跟随子元素拉伸 --> <!-- 2. .top 保持 flex无需固定高度自动跟随子元素拉伸 -->
@@ -50,6 +50,21 @@ export default {
deep: true // 若对象内属性变化需触发,需加 deep: true deep: true // 若对象内属性变化需触发,需加 deep: true
} }
}, },
computed: {
// 处理排序:包含“总成本”的项放前面,其余项按原顺序排列
sortedItemData() {
// 过滤出包含“总成本”的项(不区分大小写)
const totalCostItems = this.itemData.filter(item =>
item.name && item.name.includes('总成本')
);
// 过滤出不包含“总成本”的项
const otherItems = this.itemData.filter(item =>
!item.name || !item.name.includes('总成本')
);
// 合并:总成本项在前,其他项在后
return [...totalCostItems, ...otherItems];
}
},
mounted() { mounted() {
// 初始化图表(若需展示图表,需在模板中添加对应 DOM // 初始化图表(若需展示图表,需在模板中添加对应 DOM
// this.$nextTick(() => this.updateChart()) // this.$nextTick(() => this.updateChart())

View File

@@ -143,8 +143,8 @@ export default {
fontSize: 12, fontSize: 12,
align: 'left' align: 'left'
}, },
min: 0, // min: 0,
max: 100, // max: 100,
axisTick: { show: false }, axisTick: { show: false },
axisLabel: { axisLabel: {
color: 'rgba(0, 0, 0, 0.45)', color: 'rgba(0, 0, 0, 0.45)',
@@ -204,7 +204,7 @@ export default {
color: (params) => { color: (params) => {
const dataIndex = params.dataIndex; const dataIndex = params.dataIndex;
const currentFlag = safeFlag[dataIndex] || 0; // 双重保险,防止越界 const currentFlag = safeFlag[dataIndex] || 0; // 双重保险,防止越界
return currentFlag === 0 return currentFlag === 1
? 'rgba(118, 218, 190, 1)' ? 'rgba(118, 218, 190, 1)'
: 'rgba(249, 164, 74, 1)'; : 'rgba(249, 164, 74, 1)';
}, },

View File

@@ -64,12 +64,12 @@ export default {
{ name: "燃动力", targetValue: 0, value: 0, proportion: 0, flag: 0, route:'fuelPowerCostAnalysis/fuelPowerCostAnalysis' }, { name: "燃动力", targetValue: 0, value: 0, proportion: 0, flag: 0, route:'fuelPowerCostAnalysis/fuelPowerCostAnalysis' },
{ {
name: "包装物", targetValue: 0, value: 0, proportion: 0, flag: 0, name: "包装物", targetValue: 0, value: 0, proportion: 0, flag: 0,
route:'rawMaterialCostAnalysis/rawMaterialCostAnalysis' route:'packagingCostAnalysis/packagingCostAnalysis'
}, },
{ {
name: "辅料", targetValue: 0, value: 0, proportion: 0, flag: 0, name: "辅料", targetValue: 0, value: 0, proportion: 0, flag: 0,
route: 'rawMaterialCostAnalysis/rawMaterialCostAnalysis' route: 'packagingCostAnalysis/packagingCostAnalysis'
}, },
{ {
@@ -137,13 +137,13 @@ export default {
// 根据 flag 获取文字/进度条颜色 // 根据 flag 获取文字/进度条颜色
getColorByFlag(flag, isProgressBar = false) { getColorByFlag(flag, isProgressBar = false) {
const colorMap = { const colorMap = {
0: {
text: 'rgba(54, 181, 138, 1)',
progress: 'rgba(103, 103, 103, 0.5)' // 进度条颜色稍浅
},
1: { 1: {
text: 'rgba(98, 213, 180, 1)',
progress: 'rgba(98, 213, 180, 1)' // 进度条颜色稍浅
},
0: {
text: 'rgba(255, 132, 0, 1)', text: 'rgba(255, 132, 0, 1)',
progress: 'rgba(255, 132, 0, 0.7)' // 进度条颜色稍浅 progress: 'rgba(249, 164, 74, 1)' // 进度条颜色稍浅
} }
}; };
const currentFlag = flag === 1 ? 1 : 0; const currentFlag = flag === 1 ? 1 : 0;

View File

@@ -2,7 +2,7 @@
<div style="flex: 1"> <div style="flex: 1">
<Container :name="title" icon="cockpitItemIcon" size="productBasicBg" topSize="middle"> <Container :name="title" icon="cockpitItemIcon" size="productBasicBg" topSize="middle">
<!-- 1. 移除 .kpi-content 的固定高度改为自适应 --> <!-- 1. 移除 .kpi-content 的固定高度改为自适应 -->
<div class="kpi-content" style="padding: 14px 16px; display: flex; width: 100%;"> <div class="kpi-content" style="height: 107px;padding: 14px 16px; display: flex; width: 100%;">
<!-- 新增topItem 专属包裹容器统一控制样式和布局 --> <!-- 新增topItem 专属包裹容器统一控制样式和布局 -->
<div class="topItem-container" style="display: flex; flex-direction: column;gap: 16px;overflow: hidden;"> <div class="topItem-container" style="display: flex; flex-direction: column;gap: 16px;overflow: hidden;">
<!-- <topItem :itemList="parentItemList" /> --> <!-- <topItem :itemList="parentItemList" /> -->

View File

@@ -2,7 +2,7 @@
<div style="width: 100%;"> <div style="width: 100%;">
<Container name="领用明细" icon="cockpitItemIcon" size="productMiddleBg" topSize="middle"> <Container name="领用明细" icon="cockpitItemIcon" size="productMiddleBg" topSize="middle">
<!-- 1. 移除 .kpi-content 的固定高度改为自适应 --> <!-- 1. 移除 .kpi-content 的固定高度改为自适应 -->
<div class="kpi-content" style="padding: 14px 16px; display: flex;width: 100%;"> <div class="kpi-content" style=" padding: 14px 16px; display: flex;width: 100%;">
<div class="bottom" <div class="bottom"
style="padding: 14px 16px; height: 620px; display: flex; width: 100%;background-color: rgba(249, 252, 255, 1);"> style="padding: 14px 16px; height: 620px; display: flex; width: 100%;background-color: rgba(249, 252, 255, 1);">
<!-- <top-item /> --> <!-- <top-item /> -->

View File

@@ -0,0 +1,250 @@
<template>
<div class="coreBar">
<div class="lineBottom" style="height: 100%; width: 1590px">
<profitImpactLineChart :yName="yName" style="height: 99%; width: 1590px" />
</div>
</div>
</template>
<script>
import profitImpactLineChart from './profitImpactLineChart.vue';
export default {
name: "Container",
components: { profitImpactLineChart },
props: ['dateData','yName'],
data() {
return {
isDropdownShow: false,
selectedProfit: '原料', // 默认选中"原料"
profitOptions: ['原料', '其他选项1', '其他选项2'], // 可根据实际需求修改选项
};
},
computed: {},
methods: {
selectProfit(item) {
this.selectedProfit = item;
this.isDropdownShow = false;
}
},
mounted() {
// 点击外部关闭下拉菜单
const handleOutsideClick = (e) => {
if (!this.$el.contains(e.target)) {
this.isDropdownShow = false;
}
};
document.addEventListener('click', handleOutsideClick);
this.$once('hook:beforeDestroy', () => {
document.removeEventListener('click', handleOutsideClick);
});
}
};
</script>
<style scoped lang="scss">
.coreBar {
display: flex;
flex-direction: column;
width: 100%;
padding: 12px;
.barTop {
display: flex;
justify-content: flex-end;
align-items: center;
gap: 16px;
width: 100%;
.title {
height: 18px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 18px;
color: #000000;
line-height: 18px;
letter-spacing: 1px;
text-align: left;
font-style: normal;
white-space: nowrap;
}
.right-container {
display: flex;
align-items: center;
gap: 24px;
}
.legend {
display: flex;
gap: 16px;
align-items: center;
margin: 0;
}
.legend-item {
display: flex;
align-items: center;
gap: 8px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 14px;
color: rgba(0, 0, 0, 0.8);
text-align: left;
font-style: normal;
white-space: nowrap;
}
.legend-icon {
display: inline-block;
}
.legend-icon.line {
width: 12px;
height: 2px;
position: relative;
&::before {
position: absolute;
content: "";
top: -2px;
left: 3px;
width: 6px;
border-radius: 50%;
height: 6px;
background-color: rgba(40, 138, 255, 1);
}
}
.legend-icon.square {
width: 8px;
height: 8px;
}
.yield {
background: rgba(40, 138, 255, 1);
}
.target {
background: #2889FF;
}
.achieved {
background: rgba(40, 203, 151, 1);
}
.unachieved {
background: rgba(255, 132, 0, 1);
}
.legend-item.close-item+.legend-item.close-item {
margin-left: -8px;
}
// 按钮组:完全复用第二个组件样式,仅保持原有宽度适配
.button-group {
display: flex;
position: relative;
gap: 2px;
align-items: center;
height: 24px;
background: #ecf4fe;
margin: 0;
.dropdown-container {
position: relative;
z-index: 10;
}
.item-button {
cursor: pointer;
height: 24px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 12px;
line-height: 24px;
font-style: normal;
letter-spacing: 2px;
padding: 0 24px 0 12px;
overflow: hidden;
.item-text {
display: inline-block;
}
}
.category-btn {
width: 88px;
border-top-left-radius: 12px;
border-bottom-left-radius: 12px;
background: #ffffff;
color: #0b58ff;
text-align: center;
}
.profit-btn {
width: 102px; // 保持原组件要求的宽度,其余样式与第二个组件一致
border-top-right-radius: 12px;
border-bottom-right-radius: 12px;
position: relative;
background: #ffffff;
color: #0b58ff;
text-align: left;
&.active {
background: #3071ff;
color: rgba(249, 252, 255, .8);
}
.profit-text {
text-align: left;
width: 100%;
}
}
.dropdown-arrow {
position: absolute;
right: 8px;
top: 50%;
transform: translateY(-50%);
width: 0;
height: 0;
border-left: 6px solid currentColor;
border-top: 4px solid transparent;
border-bottom: 4px solid transparent;
border-right: 4px solid transparent;
transition: transform 0.2s ease;
&.rotate {
transform: rotate(90deg);
}
}
.dropdown-options {
position: absolute;
top: 100%;
right: 0;
margin-top: 2px;
width: 102px; // 与按钮宽度一致
background: #ffffff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
overflow: hidden;
.dropdown-option {
padding: 6px 12px;
font-size: 12px;
color: #333;
cursor: pointer;
text-align: left;
letter-spacing: 1px;
&:hover {
background: #f5f7fa;
color: #3071ff;
}
}
}
}
}
}
</style>

View File

@@ -0,0 +1,145 @@
<template>
<div ref="cockpitEffChip" id="coreLineChart" style="width: 100%; height: 500px;"></div>
</template>
<script>
import * as echarts from 'echarts';
export default {
components: {},
data() {
return {};
},
props: {
yName: {
type: String,
default: () => '元/㎡'
},
},
mounted() {
this.$nextTick(() => {
this.initData();
});
},
methods: {
initData() {
const chartDom = this.$refs.cockpitEffChip;
if (!chartDom) {
console.error('图表容器未找到!');
return;
}
const myChart = echarts.init(chartDom);
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
},
// 优化tooltip内容区分各系列含义
formatter: (params) => {
let html = `${params[0].axisValue}<br/>`;
params.forEach(item => {
// 直接使用系列名,无需映射,仅保留单位判断
html += `${item.marker} ${item.seriesName}: ${item.value}${item.seriesName === '完成率' ? '%' : '元'}<br/>`;
});
return html;
}
},
grid: {
top: 30,
bottom: 30, // 增大底部间距避免柱子与X轴标签重叠
right: 70,
left: 40,
},
xAxis: [
{
type: 'category',
boundaryGap: true, // 开启边界间隙,让柱子居中显示,不贴边
axisTick: { show: false },
axisLine: {
show: true,
lineStyle: { color: 'rgba(0, 0, 0, 0.15)' }
},
axisLabel: {
color: 'rgba(0, 0, 0, 0.45)',
fontSize: 12,
interval: 0,
padding: [5, 0, 0, 0] // 标签向下偏移,避免与柱子底部重叠
},
data: ['6月', '7月', '8月', '9月', '10月', '11月']
}
],
yAxis: [
// 左侧Y轴目标/达标/未达标(数量,单位“片”)
{
type: 'value',
// name: this.yName,
nameTextStyle: {
color: 'rgba(0, 0, 0, 0.45)',
fontSize: 12,
align: 'right'
},
min: 0, // 最小值设0确保柱子从X轴底部开始不超过X轴
max: (value) => Math.ceil(value.max * 1.1), // 最大值留10%余量,避免柱子顶满
scale: false, // 关闭缩放强制从0开始
axisTick: { show: false },
axisLabel: {
color: 'rgba(0, 0, 0, 0.45)',
fontSize: 12,
formatter: '{value}'
},
splitLine: { lineStyle: { color: 'rgba(0, 0, 0, 0.15)' } },
axisLine: { lineStyle: { color: 'rgba(0, 0, 0, 0.15)' } },
splitNumber: 4
},
],
series: [
{
name: '利润',
type: 'line',
// yAxisIndex: 1,
lineStyle: {
color: 'rgba(40, 138, 255, .5)',
width: 2
},
itemStyle: {
color: 'rgba(40, 138, 255, 1)',
borderColor: 'rgba(40, 138, 255, 1)',
borderWidth: 2,
radius: 4
},
areaStyle: {
opacity: 0.2,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(40, 138, 255, .9)' },
{ offset: 1, color: 'rgba(255, 132, 0, 0)' }
])
},
data: [200, 280, 180, 300, 220, 350],
symbol: 'circle',
symbolSize: 6
},
],
};
option && myChart.setOption(option);
// 窗口缩放适配
window.addEventListener('resize', () => {
myChart.resize();
});
// 组件销毁清理
this.$once('hook:destroyed', () => {
window.removeEventListener('resize', () => {
myChart.resize();
});
myChart.dispose();
});
}
},
};
</script>

View File

@@ -26,7 +26,7 @@ export default {
default: () => [] // 默认空数组,避免报错 default: () => [] // 默认空数组,避免报错
}, },
dateData: { // 接收父组件传递的设备数据数组 dateData: { // 接收父组件传递的设备数据数组
type: Array, type: Object,
default: () => {} // 默认空数组,避免报错 default: () => {} // 默认空数组,避免报错
}, },
yName: { // 接收父组件传递的设备数据数组 yName: { // 接收父组件传递的设备数据数组

View File

@@ -0,0 +1,233 @@
<template>
<div style="width: 100%;">
<Container :name="name" icon="cockpitItemIcon" size="operatingLarge" topSize="large">
<!-- 1. 移除 .kpi-content 的固定高度改为自适应 -->
<div class="kpi-content" style="padding: 14px 16px; display: flex;width: 100%;">
<div class="bottom" style="height: 420px; display: flex; width: 100%;background-color: rgba(249, 252, 255, 1);">
<!-- <top-item /> -->
<costBar :yName="yName" :dateData="dateData" />
</div>
</div>
</Container>
</div>
</template>
<script>
import Container from './container.vue'
import costBar from './profitImpactLine'
export default {
name: 'ProductionStatus',
components: { Container, costBar },
// mixins: [resize],
props: {
trendData: { // 接收父组件传递的设备数据数组
type: Array,
default: () => [] // 默认空数组,避免报错
},
dateData: { // 接收父组件传递的设备数据数组
type: Array,
default: () => {} // 默认空数组,避免报错
},
yName: { // 接收父组件传递的设备数据数组
type: String,
default: () => '' // 默认空数组,避免报错
},
name: { // 接收父组件传递的设备数据数组
type: String,
default: () => '趋势图' // 默认空数组,避免报错
},
},
data() {
return {
chart: null
}
},
watch: {
productionOverviewVo: {
handler(newValue, oldValue) {
this.updateChart()
},
deep: true // 若对象内属性变化需触发,需加 deep: true
}
},
mounted() {
// 初始化图表(若需展示图表,需在模板中添加对应 DOM
// this.$nextTick(() => this.updateChart())
},
methods: {
updateChart() {
}
}
}
</script>
<style lang='scss' scoped>
/* 3. 核心:滚动容器样式(固定高度+溢出滚动+隐藏滚动条) */
.scroll-container {
/* 1. 固定容器高度根据页面布局调整示例300px超出则滚动 */
max-height: 210px;
/* 2. 溢出滚动:内容超出高度时显示滚动功能 */
overflow-y: auto;
/* 3. 隐藏横向滚动条(防止设备名过长导致横向滚动) */
overflow-x: hidden;
/* 4. 内边距:与标题栏和容器边缘对齐 */
padding: 10px 0;
/* 5. 隐藏滚动条(兼容主流浏览器) */
/* Chrome/Safari */
&::-webkit-scrollbar {
display: none;
}
/* Firefox */
scrollbar-width: none;
/* IE/Edge */
-ms-overflow-style: none;
}
/* 设备项样式优化:增加间距,避免拥挤 */
.proBarInfo {
display: flex;
flex-direction: column;
padding: 8px 27px;
/* 调整内边距,优化排版 */
margin-bottom: 10px;
/* 设备项之间的垂直间距 */
}
/* 原有样式保留,优化细节 */
.proBarInfoEqInfo {
display: flex;
justify-content: space-between;
align-items: center;
/* 垂直居中,避免序号/文字错位 */
}
.slot {
width: 21px;
height: 23px;
background: rgba(0, 106, 205, 0.22);
backdrop-filter: blur(1.5px);
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 16px;
color: #68B5FF;
line-height: 23px;
/* 垂直居中文字 */
text-align: center;
font-style: normal;
}
.eq-name {
margin-left: 8px;
/* 增加与序号的间距 */
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 16px;
color: #FFFFFF;
line-height: 18px;
letter-spacing: 1px;
text-align: left;
font-style: normal;
}
.eqStatus {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 16px;
color: #FFFFFF;
line-height: 18px;
text-align: right;
font-style: normal;
}
.splitLine {
width: 1px;
height: 14px;
border: 1px solid #ADADAD;
margin: 0 8px;
/* 优化分割线间距 */
}
.yield {
height: 18px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 16px;
color: #00FFFF;
line-height: 18px;
text-align: right;
font-style: normal;
}
.proBarInfoEqInfoLeft {
display: flex;
align-items: center;
/* 序号和设备名垂直居中 */
}
.proBarInfoEqInfoRight {
display: flex;
align-items: center;
/* 状态/分割线/百分比垂直居中 */
}
.proBarWrapper {
position: relative;
height: 10px;
margin-top: 6px;
/* 进度条与上方信息的间距 */
border-radius: 5px;
/* 进度条圆角,优化视觉 */
overflow: hidden;
}
.proBarLine {
width: 100%;
height: 100%;
background: linear-gradient(65deg, rgba(82, 82, 82, 0) 0%, #ACACAC 100%);
opacity: 0.2;
}
.proBarLineTop {
position: absolute;
top: 0;
left: 0;
height: 100%;
background: linear-gradient(65deg, rgba(53, 223, 247, 0) 0%, rgba(54, 220, 246, 0.92) 92%, #36F6E5 100%, #37ACF5 100%);
border-radius: 5px;
transition: width 0.3s ease;
/* 进度变化时添加过渡动画,更流畅 */
}
/* 图表相关样式保留 */
.chartImgBottom {
position: absolute;
bottom: 45px;
left: 58px;
}
.line {
display: inline-block;
position: absolute;
left: 57px;
bottom: 42px;
width: 1px;
height: 20px;
background-color: #00E8FF;
}
</style>
<style>
/* 全局 tooltip 样式(不使用 scoped确保生效 */
.production-status-chart-tooltip {
background: #0a2b4f77 !important;
border: none !important;
backdrop-filter: blur(12px);
}
.production-status-chart-tooltip * {
color: #fff !important;
}
</style>

View File

@@ -134,12 +134,12 @@ export default {
getColorByFlag(flag, isProgressBar = false) { getColorByFlag(flag, isProgressBar = false) {
const colorMap = { const colorMap = {
1: { 1: {
text: 'rgba(54, 181, 138, 1)', text: 'rgba(98, 213, 180, 1)',
progress: 'rgba(103, 103, 103, 0.5)' // 进度条颜色稍浅 progress: 'rgba(98, 213, 180, 1)' // 进度条颜色稍浅
}, },
0: { 0: {
text: 'rgba(255, 132, 0, 1)', text: 'rgba(255, 132, 0, 1)',
progress: 'rgba(255, 132, 0, 0.7)' // 进度条颜色稍浅 progress: 'rgba(249, 164, 74, 1)' // 进度条颜色稍浅
} }
}; };
const currentFlag = flag === 1 ? 1 : 0; const currentFlag = flag === 1 ? 1 : 0;

View File

@@ -86,14 +86,6 @@ export default {
this.destroy() this.destroy()
}, },
mounted() { mounted() {
const startTime = moment().startOf('week').format('YYYY-MM-DD')
const endTime = moment().format('YYYY-MM-DD')
console.log(this.date, 'date')
this.date = [startTime, endTime]
// this.weekDay = this.weekArr[moment(this.date).format('e')]
// this.getData()
this.loopTime()
console.log(1111);
const _this = this; const _this = this;
_this.beilv = document.documentElement.clientWidth / 1920 _this.beilv = document.documentElement.clientWidth / 1920
window.onresize = () => { window.onresize = () => {
@@ -104,39 +96,6 @@ export default {
} }
}, },
methods: { methods: {
handleTimeChange(data) {
console.log(data);
},
windowWidth(value) {
this.clientWidth = value
this.beilv2 = this.clientWidth / 1920
},
getToday8StartTimestamp() {
const date = new Date(); // 获取当前时间
// 将时设为8、分0、秒0、毫秒0
date.setHours(8, 0, 0, 0);
return date.getTime(); // 转换为时间戳(毫秒)
},
// 获取第二天早上八点的时间戳
getTomorrow8EndTimestamp() {
const date = new Date(); // 获取当前时间
// 先加一天,再设置为早上八点
date.setDate(date.getDate() + 1);
date.setHours(8, 0, 0, 0);
return date.getTime(); // 转换为时间戳(毫秒)
},
loopTime() {
const _this = this
_this.timer = setInterval(
function() {
// _this.getData()
}, 60000)
},
change() { change() {
this.isFullScreen = screenfull.isFullscreen this.isFullScreen = screenfull.isFullscreen
}, },
@@ -173,37 +132,6 @@ export default {
} }
screenfull.toggle(this.$refs.dayReportB) screenfull.toggle(this.$refs.dayReportB)
}, },
changeDate(val) {
this.date = val
// this.weekDay = this.weekArr[moment(this.date).format('e')]
// this.getData()
if (this.date === moment().format('yyyy-MM-DD')) {
this.loopTime()
} else {
clearInterval(this.timer)
}
},
// 导出
// exportPDF() {
// this.$message.success('正在导出,请稍等!')
// const element = document.getElementById('dayRepDom')
// element.style.display = 'block'
// const fileName = '株洲碲化镉生产日报' + moment().format('yyMMDD') + '.pdf'
// html2canvas(element, {
// dpi: 300, // Set to 300 DPI
// scale: 3 // Adjusts your resolution
// }).then(function(canvas) {
// const imgWidth = 595.28
// const imgHeight = 841.89
// const pageData = canvas.toDataURL('image/jpeg', 1.0)
// const PDF = new JsPDF('', 'pt', [imgWidth, imgHeight])
// PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
// setTimeout(() => {
// PDF.save(fileName) // 导出文件名
// }, 1000)
// })
// element.style.display = 'none'
// }
} }
} }
</script> </script>

View File

@@ -34,7 +34,7 @@
gap: 12px; gap: 12px;
grid-template-columns: 1624px; grid-template-columns: 1624px;
"> ">
<profitLineChart :name=" '总利润趋势·元' " :yName="'元' " /> <profitLineChart :name=" '总利润趋势·元' " :yName="'元' " />
</div> </div>
</div> </div>
</div> </div>
@@ -54,7 +54,7 @@ import { Sidebar } from "../../layout/components";
import screenfull from "screenfull"; import screenfull from "screenfull";
import changeBase from "./costComponents/changeBase"; import changeBase from "./costComponents/changeBase";
import totalProfit from "./costComponents/totalProfit.vue"; import totalProfit from "./costComponents/totalProfit.vue";
import profitLineChart from "./costComponents/profitLineChart.vue"; import profitLineChart from "./costComponents/profitTotalChart.vue";
import { mapState } from "vuex"; import { mapState } from "vuex";
import singleTopSelect from "./costComponents/singleTopSelect.vue"; import singleTopSelect from "./costComponents/singleTopSelect.vue";
// import PSDO from "./components/PSDO.vue"; // import PSDO from "./components/PSDO.vue";

View File

@@ -217,16 +217,6 @@ export default {
} }
screenfull.toggle(this.$refs.dayReportB); screenfull.toggle(this.$refs.dayReportB);
}, },
changeDate(val) {
this.date = val;
// this.weekDay = this.weekArr[moment(this.date).format('e')]
// this.getData()
if (this.date === moment().format("yyyy-MM-DD")) {
this.loopTime();
} else {
clearInterval(this.timer);
}
},
// 导出 // 导出
// exportPDF() { // exportPDF() {
// this.$message.success('正在导出,请稍等!') // this.$message.success('正在导出,请稍等!')

View File

@@ -16,7 +16,7 @@
gap: 12px; gap: 12px;
grid-template-columns: 1624px; grid-template-columns: 1624px;
"> ">
<changeBase /> <changeBase @selectChange="getBase" />
</div> </div>
</div> </div>
<div class="top" style="display: flex; gap: 16px;margin-top: -20px;"> <div class="top" style="display: flex; gap: 16px;margin-top: -20px;">
@@ -25,8 +25,8 @@
gap: 12px; gap: 12px;
grid-template-columns:804px 804px; grid-template-columns:804px 804px;
"> ">
<productItemOverviewItem :parentItemList="itemLeftList" :title=" '领用汇总' " /> <productItemOverviewItem :parentItemList="receiveTotal" :title=" '领用汇总' " />
<productItemOverviewItem :parentItemList="itemRightList" :title="'入账汇总'" /> <productItemOverviewItem :parentItemList="inStorageTotal" :title="'入账汇总'" />
</div> </div>
</div> </div>
@@ -37,8 +37,7 @@
grid-template-columns: 804px 804px; grid-template-columns: 804px 804px;
"> ">
<productLeftTable :tableData="receiveDetailList" /> <productLeftTable :tableData="receiveDetailList" />
<productRightTable :tableData="accountSumaryList"/> <productRightTable :tableData="accountSumaryList" />
</div> </div>
</div> </div>
</div> </div>
@@ -82,8 +81,11 @@ export default {
timer: null, timer: null,
beilv: 1, beilv: 1,
value: 100, value: 100,
levelId:1,
accountSumaryList: [], accountSumaryList: [],
receiveDetailList:[], receiveDetailList: [],
receiveTotal: [],
inStorageTotal: [],
itemLeftList: [ itemLeftList: [
{ name: "备品备件", value: 137,}, { name: "备品备件", value: 137,},
{ {
@@ -168,23 +170,38 @@ export default {
}; };
}, },
methods: { methods: {
getBase(data) {
console.log(data);
this.levelId = data
this.getData()
},
getData() { getData() {
getReceiveDetailPage({ getReceiveDetailPage({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
levelId: 1 levelId: this.levelId
}).then((res) => { }).then((res) => {
console.log(res); console.log(res);
this.receiveDetailList = res.data.领用明细 this.receiveDetailList = res.data.receiveDetail
this.receiveTotal = res.data.receiveTotal.map((item) => {
const name = Object.keys(item)[0];
const value = item[name];
console.log(name);
return { name, value };
});
}) })
getAccountSumaryPage({ getAccountSumaryPage({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
levelId: 1 levelId: this.levelId
}).then((res) => { }).then((res) => {
console.log(res); console.log(res);
this.accountSumaryList = res.data.入账明细 this.accountSumaryList = res.data.inStorageDetail
this.inStorageTotal = res.data.inStorageTotal.map((item) => {
const name = Object.keys(item)[0];
const value = item[name];
return { name, value };
});
}) })
}, },
handleClickOutside() { handleClickOutside() {