463 lines
11 KiB
Vue
463 lines
11 KiB
Vue
<template>
|
||
<Card title="各装置实际进度">
|
||
<div class="device-list">
|
||
<div class="select-right">
|
||
<el-cascader
|
||
size="small"
|
||
v-model="dataInfo.checkedNodeData.id"
|
||
:options="dataInfo.listData"
|
||
:props="{ value: 'id', label: 'deviceUnitName' }"
|
||
@change="handleChange"
|
||
:show-all-levels="false"
|
||
/>
|
||
<el-select v-model="dataInfo.deviceYearInfo.id" size="small" @change="selectChange">
|
||
<el-option v-for="(item, index) in dataInfo.deviceYearList" :key="index" :label="item.year" :value="item.id" />
|
||
</el-select>
|
||
</div>
|
||
<div class="centerBottom">
|
||
<div
|
||
v-if="dataInfo.listData.length > 0"
|
||
id="stateTotal"
|
||
class="chart"
|
||
ref="lineCharts"
|
||
></div>
|
||
<div v-else>
|
||
<div class="not-data">
|
||
<img src="@/assets/images/noData.png" />
|
||
<p>暂无数据</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</Card>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import Card from "@/components/card.vue";
|
||
import { ref, onMounted, reactive, nextTick } from "vue";
|
||
import * as echarts from "echarts";
|
||
import symbolIcon from "@/assets/images/lineSymbol.png";
|
||
import { getDeviceScheduleListApi, getDeviceYearListApi, getProgressPlanEquipmentTreeApi } from "@/api/modules/schedulePlan";
|
||
import { GlobalStore } from "@/stores";
|
||
const store = GlobalStore();
|
||
function selectChange(e: any) {
|
||
const find = dataInfo.deviceYearList.find((item: any) => item.id == dataInfo.deviceYearInfo.id);
|
||
if (find) {
|
||
dataInfo.deviceYearInfo = JSON.parse(JSON.stringify(find));
|
||
getDeviceScheduleList();
|
||
}
|
||
}
|
||
|
||
const dataInfo = reactive({
|
||
deviceScheduleList: [] as any[],
|
||
deviceYearInfo: {} as any,
|
||
deviceYearList: [] as any[],
|
||
listData: [] as any[],
|
||
checkedNodeData: {} as any
|
||
});
|
||
const lineCharts = ref(null);
|
||
|
||
const lineChartsFn = (el: any) => {
|
||
console.log(el);
|
||
let ageChart = echarts.init(el);
|
||
const maxCount = dataInfo.deviceScheduleList.reduce((prev, item) => {
|
||
const currentActual = Math.ceil(Number(item.currentActual));
|
||
const currentPlan = Math.ceil(Number(item.currentPlan));
|
||
const max = currentActual > currentPlan ? currentActual : currentPlan;
|
||
prev = max > prev ? max : prev;
|
||
return prev;
|
||
}, 0); // 最大显示数量
|
||
|
||
console.log(maxCount);
|
||
let option = {
|
||
tooltip: {
|
||
trigger: "axis"
|
||
},
|
||
// toolbox: {
|
||
// feature: {
|
||
// dataView: { show: true, readOnly: false },
|
||
// magicType: { show: true, type: ['line', 'bar'] },
|
||
// restore: { show: true },
|
||
// saveAsImage: { show: true }
|
||
// }
|
||
// },
|
||
legend: {
|
||
align: "left", //图例位置
|
||
itemGap: 15, //图例之间的间隔
|
||
orient: "vertical",
|
||
x: "right", //可设定图例在左、右、居中
|
||
y: "center", //可设定图例在上、下、居中
|
||
padding: [0, 20, 0, 0], //可设定图例[距上方距离,距右方距离,距下方距离,距左方距离]
|
||
data: [
|
||
{
|
||
icon: "roundRect",
|
||
name: "当期计划"
|
||
},
|
||
{
|
||
icon: "roundRect",
|
||
name: "当期实际"
|
||
},
|
||
{
|
||
icon: "circle",
|
||
name: "累计计划"
|
||
},
|
||
{
|
||
icon: "circle",
|
||
name: "累计实际"
|
||
}
|
||
],
|
||
itemWidth: 10,
|
||
itemHeight: 10,
|
||
textStyle: {
|
||
color: "#ffffff" //字体颜色
|
||
}
|
||
},
|
||
grid: {
|
||
left: "5%",
|
||
right: "12%",
|
||
bottom: "10%",
|
||
containLabel: true
|
||
},
|
||
// toolbox: {
|
||
// feature: {
|
||
// saveAsImage: {}
|
||
// }
|
||
// },
|
||
xAxis: {
|
||
// name: "月份", //X轴标题
|
||
type: "category",
|
||
// boundaryGap: false,
|
||
data: dataInfo.deviceScheduleList.map(item => item.year + "-" + item.month),
|
||
axisPointer: {
|
||
type: "shadow"
|
||
},
|
||
axisLine: {
|
||
show: true,
|
||
lineStyle: {
|
||
color: "#193c81"
|
||
}
|
||
},
|
||
axisLabel: {
|
||
show: true,
|
||
interval: 0,
|
||
textStyle: {
|
||
color: "#ffffff"
|
||
}
|
||
}
|
||
},
|
||
yAxis: [
|
||
{
|
||
name: "累计", //Y轴标题
|
||
type: "value",
|
||
axisTick: {
|
||
// 轴刻度
|
||
show: false
|
||
},
|
||
axisLine: {
|
||
// 轴线
|
||
show: true,
|
||
lineStyle: {
|
||
color: "#193c81"
|
||
}
|
||
},
|
||
itemStyle: {
|
||
//颜色 默认灰色
|
||
// color: 'rgba(255,255,255,1)',
|
||
color: "#fff"
|
||
},
|
||
nameTextStyle: {
|
||
padding: [0, 0, 0, -30], // 四个数字分别为上右下左与原位置距离
|
||
color: "#fff"
|
||
},
|
||
splitLine: {
|
||
show: true,
|
||
lineStyle: {
|
||
type: "dashed",
|
||
color: "#193c81"
|
||
}
|
||
},
|
||
axisLabel: {
|
||
show: true,
|
||
textStyle: {
|
||
color: "#ffffff"
|
||
}
|
||
}
|
||
},
|
||
{
|
||
name: "当期", //Y轴标题
|
||
min: 0,
|
||
max: maxCount,
|
||
// interval: 2,
|
||
type: "value",
|
||
axisTick: {
|
||
// 轴刻度
|
||
show: false
|
||
},
|
||
axisLine: {
|
||
// 轴线
|
||
show: true,
|
||
lineStyle: {
|
||
color: "#193c81"
|
||
}
|
||
},
|
||
itemStyle: {
|
||
//颜色 默认灰色
|
||
color: "#ffffff"
|
||
},
|
||
nameTextStyle: {
|
||
padding: [0, 0, 0, 0], // 四个数字分别为上右下左与原位置距离
|
||
color: "#fff"
|
||
},
|
||
splitLine: {
|
||
show: false,
|
||
lineStyle: {
|
||
type: "dashed",
|
||
color: "#193c81"
|
||
}
|
||
},
|
||
axisLabel: {
|
||
show: true,
|
||
textStyle: {
|
||
color: "#ffffff"
|
||
}
|
||
}
|
||
}
|
||
],
|
||
series: [
|
||
{
|
||
name: "当期计划",
|
||
type: "bar",
|
||
yAxisIndex: 1,
|
||
data: dataInfo.deviceScheduleList.map(item => item.currentPlan),
|
||
itemStyle: {
|
||
//颜色 默认灰色
|
||
color: "rgba(210,210,250,1)"
|
||
},
|
||
barWidth: 10 // 设置柱子粗细
|
||
},
|
||
{
|
||
name: "当期实际",
|
||
type: "bar",
|
||
yAxisIndex: 1,
|
||
// stack: 'Total',
|
||
data: dataInfo.deviceScheduleList.map(item => item.currentActual),
|
||
itemStyle: {
|
||
//颜色 默认灰色
|
||
color: "rgba(251,242,183,1)"
|
||
},
|
||
barWidth: 10 // 设置柱子粗细
|
||
},
|
||
{
|
||
name: "累计计划",
|
||
type: "line",
|
||
// stack: 'Total',
|
||
data: dataInfo.deviceScheduleList.map(item => item.cumulativePlan),
|
||
itemStyle: {
|
||
//颜色 默认灰色
|
||
color: "rgba(97,106,220,1)"
|
||
},
|
||
symbol: "circle", //将小圆点改成实心 不写symbol默认空心
|
||
symbolSize: 5 //小圆点的大小
|
||
},
|
||
{
|
||
name: "累计实际",
|
||
type: "line",
|
||
// stack: 'Total',
|
||
data: dataInfo.deviceScheduleList.map(item => item.cumulativeActual),
|
||
itemStyle: {
|
||
//颜色 默认灰色
|
||
color: "rgba(246,210,16,1)"
|
||
},
|
||
symbol: "circle", //将小圆点改成实心 不写symbol默认空心
|
||
symbolSize: 5 //小圆点的大小
|
||
}
|
||
],
|
||
dataZoom: [
|
||
{
|
||
type: "slider", //隐藏或显示(true)组件
|
||
show: dataInfo.deviceScheduleList.length > 12 ? true : false,
|
||
// backgroundColor: "rgb(19, 63, 100)", // 组件的背景颜色。
|
||
// fillerColor: "rgb(16, 171, 198)", // 选中范围的填充颜色。
|
||
// borderColor: "rgb(19, 63, 100)", // 边框颜色
|
||
showDetail: false, //是否显示detail,即拖拽时候显示详细数值信息
|
||
startValue: 0,
|
||
endValue: 11,
|
||
filterMode: "empty",
|
||
width: "50%", //滚动条高度
|
||
height: 6, //滚动条显示位置
|
||
left: "center",
|
||
zoomLoxk: true, // 是否锁定选择区域(或叫做数据窗口)的大小
|
||
handleSize: 0, //控制手柄的尺寸
|
||
bottom: 0 // dataZoom-slider组件离容器下侧的距离
|
||
},
|
||
{
|
||
//没有下面这块的话,只能拖动滚动条,鼠标滚轮在区域内不能控制外部滚动条
|
||
type: "inside",
|
||
zoomOnMouseWheel: false, //滚轮是否触发缩放
|
||
moveOnMouseMove: true, //鼠标滚轮触发滚动
|
||
moveOnMouseWheel: true
|
||
}
|
||
]
|
||
} as any;
|
||
ageChart.setOption(option);
|
||
window.addEventListener("resize", () => {
|
||
ageChart.resize();
|
||
});
|
||
};
|
||
const getDeviceScheduleList = () => {
|
||
let data = {
|
||
projectSn: store.sn,
|
||
pageNo: 1,
|
||
pageSize: -1,
|
||
deviceUnitId: dataInfo.checkedNodeData.id,
|
||
year: dataInfo.deviceYearInfo.year == "全部" ? "" : dataInfo.deviceYearInfo.year
|
||
// isFilterQualityRegionEnterprise: 1
|
||
};
|
||
getDeviceScheduleListApi(data).then((res: any) => {
|
||
if (res.code == 200) {
|
||
dataInfo.deviceScheduleList = res.result.records;
|
||
nextTick(() => {
|
||
lineChartsFn(lineCharts.value);
|
||
});
|
||
console.log("查询装置主进度计划详情信息", dataInfo.deviceScheduleList);
|
||
}
|
||
});
|
||
};
|
||
|
||
//查询装置主进度计划年份信息
|
||
const getDeviceYearList = () => {
|
||
let data = {
|
||
projectSn: store.sn,
|
||
pageNo: 1,
|
||
pageSize: -1,
|
||
deviceUnitId: dataInfo.checkedNodeData.id
|
||
// isFilterQualityRegionEnterprise: 1
|
||
};
|
||
getDeviceYearListApi(data).then((res: any) => {
|
||
if (res.code == 200) {
|
||
dataInfo.deviceYearList = [
|
||
{
|
||
id: "",
|
||
year: "全部"
|
||
},
|
||
...res.result.records
|
||
];
|
||
dataInfo.deviceYearInfo = JSON.parse(JSON.stringify(dataInfo.deviceYearList[0]));
|
||
console.log("查询装置主进度计划年份信息", dataInfo.deviceYearList);
|
||
getDeviceScheduleList();
|
||
}
|
||
});
|
||
};
|
||
|
||
//获取左侧---列表信息
|
||
const getDangerTypeRecordList = () => {
|
||
console.log(22);
|
||
let data = {
|
||
projectSn: store.sn,
|
||
hasAll: 1
|
||
};
|
||
getProgressPlanEquipmentTreeApi(data).then((res: any) => {
|
||
if (res.code == 200) {
|
||
if (res.result.length > 0) {
|
||
dataInfo.listData = [
|
||
// {
|
||
// id: '',
|
||
// children: [],
|
||
// deviceUnitName: '全部'
|
||
// },
|
||
...res.result
|
||
];
|
||
dataInfo.checkedNodeData.id = dataInfo.listData[0].id;
|
||
getDeviceYearList();
|
||
console.log("获取左侧---列表信息", dataInfo.listData);
|
||
} else {
|
||
dataInfo.listData = [];
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
const handleChange = (e: any) => {
|
||
// console.log('handleChange', e);
|
||
// // const find = dataInfo.listData.find((item: any) => item.id == dataInfo.checkedNodeData.id[dataInfo.checkedNodeData.id.length - 1]);
|
||
// const find = nodeTree(dataInfo.listData, e[e.length - 1]);
|
||
// const resultList = find.filter((item:any) => item.length > 0)
|
||
// console.log('handleChange', find);
|
||
// if(resultList && resultList[0]) {
|
||
// dataInfo.checkedNodeData = resultList[0][0].deviceUnitName == "全部装置" ? dataInfo.listData[0] : resultList[0][0];
|
||
// getDeviceYearList();
|
||
// }
|
||
dataInfo.checkedNodeData.id = e[e.length - 1];
|
||
getDeviceYearList();
|
||
|
||
console.log("handleChange", dataInfo.checkedNodeData, dataInfo.listData, e);
|
||
};
|
||
|
||
const nodeTree = (node: any, id: any) => {
|
||
return node
|
||
.map((item: any) => {
|
||
if (item.id == id)
|
||
return {
|
||
...item
|
||
};
|
||
if (item.children && item.children.length > 0) {
|
||
return nodeTree(item.children, id).filter((item: any) => item !== undefined);
|
||
}
|
||
})
|
||
.filter((item: any) => item !== undefined);
|
||
};
|
||
|
||
onMounted(async () => {
|
||
// await getChartTotal();
|
||
// draw();
|
||
getDangerTypeRecordList();
|
||
// console.log("Mount_type", dialogIndex.value);
|
||
});
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.device-list {
|
||
width: 100%;
|
||
height: 100%;
|
||
box-sizing: border-box;
|
||
position: relative;
|
||
.select-right {
|
||
position: absolute;
|
||
right: 3%;
|
||
width: 15%;
|
||
top: -18%;
|
||
z-index: 9;
|
||
display: flex;
|
||
> div:not(:first-child) {
|
||
margin-left: 20px;
|
||
}
|
||
}
|
||
.centerBottom {
|
||
width: 100%;
|
||
height: 100%;
|
||
position: relative;
|
||
.chart {
|
||
width: 920px;
|
||
height: 228px;
|
||
}
|
||
.not-data {
|
||
width: 20%;
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
img {
|
||
width: 40%;
|
||
margin: 5% 30%;
|
||
}
|
||
p {
|
||
color: #fff;
|
||
font-size: calc(100vw * 14 / 1920);
|
||
margin: 0;
|
||
text-align: center;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|