602 lines
16 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>
<Card title="总体统筹计划">
<!-- {{pageInfo.yearList.length}} {{pageInfo.milestoneList.length}} -->
<div
class="fullHeight"
v-loading.lock="isLoading"
element-loading-text="正在转换中"
element-loading-background="rgba(0, 0, 0, 0.8)"
>
<div class="searchBox whiteBlock">
<el-tooltip class="box-item" effect="dark" :content="schedulePlanFlag ? '自动' : '手动'" placement="top">
<el-icon v-if="schedulePlanFlag" @click="showSchedulePlanSwitch" class="elSwitch"><Switch /></el-icon>
<el-icon v-else @click="showSchedulePlanSwitch" class="elSwitch"><Pointer /></el-icon>
</el-tooltip>
<el-select class="ml_20" size="small" @change="onProjectTypeChange" v-model="searchForm.projectType" placeholder="Select">
<el-option v-for="item in projectTypeList" :key="item.id" :label="item.projectTypeName" :value="item.id" />
</el-select>
<el-cascader
class="ml_20"
size="small"
@change="onChildCategoryChange"
v-model="searchForm.childCategoryId"
:options="planWorkCategoryList"
:props="{ checkStrictly: true, emitPath: false, value: 'id', label: 'name', children: 'children' }"
clearable
></el-cascader>
<div class="rhombus ml_20">
图例
<div>
<div class="rhombus_bg"></div>
<div>关键控制点</div>
</div>
<div>
<div class="rhombus_bg1"></div>
<div>重要事件的控制</div>
</div>
<div>
<div class="rhombus_bg2"></div>
<div>作业项目的节点</div>
</div>
<div>
<div class="rhombus_bg3"></div>
<div>非关键路径</div>
</div>
<div>
<div class="rhombus_bg4"></div>
<div>关键路径</div>
</div>
</div>
<el-tooltip v-if="pageInfo.yearList.length > 0" class="box-item" effect="dark" content="转换" placement="top">
<el-icon @click="showDomIsImage" class="elSwitch"><Switch /></el-icon>
</el-tooltip>
</div>
<div
v-if="pageInfo.yearList.length > 0 && pageInfo.isLoadingAll"
class="table_wrap whiteBlock"
:class="{ table_wrap_active: pageInfo.showDown && pageInfo.domIsImage }"
>
<template v-if="!pageInfo.domIsImage">
<GanttChart
:yearList="pageInfo.yearList"
:monthList="pageInfo.monthList"
:milestoneList="pageInfo.milestoneList"
:projectItemList="pageInfo.projectItemList"
:showDwon="pageInfo.showDown"
@scheduleSwitchChange="onScheduleSwitchChange"
/>
</template>
<template v-if="!pageInfo.imageUrl && pageInfo.domIsImage">
<OldGanttChart
:yearList="pageInfo.yearList"
:monthList="pageInfo.monthList"
:milestoneList="pageInfo.milestoneList"
:projectItemList="pageInfo.projectItemList"
:showDwon="pageInfo.showDown"
@onImgData="onImgData"
/>
</template>
<el-image
class="elImage"
v-if="pageInfo.imageUrl && pageInfo.domIsImage"
:src="pageInfo.imageUrl"
:preview-src-list="[pageInfo.imageUrl]"
></el-image>
</div>
<div class="not-data" v-else>
<img src="@/assets/images/noData.png" alt="" />
<p>暂无数据</p>
</div>
</div>
</Card>
</template>
<script setup lang="ts">
import { base64ToFile, base64ToUrl } from "@/utils/util";
import dayjs from "dayjs";
import {
getMilestoneListApi,
getMilestoneTopBarPlanRecord,
getProjectPlanGraphApi,
getMilestoneChartPlanRecord,
getPlanWorkCategoryTreePage,
getPlanMilestone2LeftTreeApi
} from "@/api/modules/schedulePlan";
import { computed, reactive, ref, onMounted, onBeforeMount, watch, nextTick, defineAsyncComponent } from "vue";
import { uploadImgNew } from "@/api/modules/upload";
import { GlobalStore } from "@/stores";
import Card from "@/components/card.vue";
import { ElMessage } from "element-plus";
import { is } from "date-fns/locale";
const emits = defineEmits(["setSchedulePlanShowDownFn"]);
// import lrz from "lrz";
const GanttChart = defineAsyncComponent(() => import("./ganttChart.vue"));
const OldGanttChart = defineAsyncComponent(() => import("./oldGanttChart.vue"));
// import GanttChart from "./ganttChart.vue";
// import OldGanttChart from "./oldGanttChart.vue";
const BASEURL = import.meta.env.VITE_API_URL;
const store = GlobalStore();
const props = defineProps({
showDown: {
type: Boolean,
default: true
}
});
const onScheduleSwitchChange = () => {
if(searchForm.projectType != 2) {
searchForm.projectType = 2;
onProjectTypeChange()
}else {
const findIndex = planWorkCategoryList.value.findIndex((item: any) => item.id == searchForm.childCategoryId);
if(findIndex > -1 ) {
console.log("切换下一个分类1", findIndex + 1, planWorkCategoryList.value.length)
if(findIndex + 1 >= planWorkCategoryList.value.length) {
console.log("已经是最后一个分类")
if(!store.showDown){
store.setSchedulePlanTime(Date.now());
}
return
}
console.log("切换下一个分类2", findIndex + 1, planWorkCategoryList.value[findIndex + 1].id)
searchForm.childCategoryId = planWorkCategoryList.value[findIndex + 1].id;
onChildCategoryChange();
}
}
}
const pageInfo = reactive({
pageNo: 1,
pageSize: 10,
total: 10,
milestoneList: [],
yearList: [] as any[],
monthList: [] as any[],
projectItemList: [],
projectSn: "",
imageUrl: "",
isLoading: true,
domIsImage: true,
isLoadingAll: false,
showDown: true
});
watch(() => props.showDown, () => {
pageInfo.showDown = props.showDown;
}, { deep: true })
const onImgData = (data: any) => {
// console.log(11111111111111, base64ToFile(data, "项目总体计划"));
const file = base64ToFile(data, "项目总体计划");
// console.log(22222222, url, url.size);
// lrz(url, { quality: 1 }).then((rst: any) => {
// console.log(33333, rst);
const formData = new FormData();
formData.append("files", file, "项目总体计划.png");
uploadImgNew(formData, true).then((res: any) => {
// console.log(22222222, res);
if (res.status == "SUCCESS") {
pageInfo.imageUrl = BASEURL + "/image/" + res.data[0].imageUrl;
store.setShedulePlanImage(pageInfo.imageUrl, searchForm.projectType);
if(schedulePlanFlag.value) {
setTimeout(() => {
// showDomIsImage();
pageInfo.domIsImage = false;
emits("setSchedulePlanShowDownFn");
}, 30000)
}
} else {
ElMessage.error("转换失败!");
}
});
// });
// const url = base64ToUrl(data);
// pageInfo.imageUrl = url;
// store.setShedulePlanImage(url);
// console.log(111111, "赋值");
// pageInfo.imageUrl = data;
// localStorage.setItem("shedulePlanImage", data);
// store.setShedulePlanImage(url);
};
const isLoading = computed(() => {
console.log(33333, "isLoading", pageInfo.isLoading, pageInfo.domIsImage, pageInfo.isLoading && pageInfo.domIsImage && pageInfo.yearList.length > 0);
return pageInfo.isLoading && pageInfo.domIsImage && pageInfo.yearList.length > 0;
});
const onChildCategoryChange = () => {
loadCardData();
getProjectMilestonePlanRecordList();
};
watch(
() => pageInfo.imageUrl,
() => {
if (pageInfo.imageUrl) {
nextTick(() => {
// console.log(111111, "关闭loading");
pageInfo.isLoading = false;
});
}
}
);
const showDomIsImage = () => {
pageInfo.domIsImage = !pageInfo.domIsImage;
if (pageInfo.domIsImage) {
if(searchForm.projectType == 1) {
pageInfo.imageUrl = store.schedulePlanImage1;
} else if(searchForm.projectType == 2) {
pageInfo.imageUrl = store.schedulePlanImage2;
}
}
};
const schedulePlanFlag = ref(false);
const showSchedulePlanSwitch = () => {
schedulePlanFlag.value = !schedulePlanFlag.value;
if(pageInfo.domIsImage){
pageInfo.domIsImage = false;
}
store.setSchedulePlan(schedulePlanFlag.value);
}
const searchForm = reactive({
childCategoryId: "",
projectType: 1
});
const projectTypeList = ref([
{
id: 1,
// projectTypeName: "项目里程碑"
projectTypeName: "项目总体统筹计划"
},
{
id: 2,
// projectTypeName: "装置里程碑"
projectTypeName: "各装置总体统筹计划"
}
]);
const onProjectTypeChange = () => {
if(pageInfo.domIsImage) {
if(store.schedulePlanImage1 && searchForm.projectType == 1) {
pageInfo.imageUrl = store.schedulePlanImage1;
return
}
if(store.schedulePlanImage2 && searchForm.projectType == 2) {
pageInfo.imageUrl = store.schedulePlanImage2;
return
}
pageInfo.imageUrl = "";
pageInfo.isLoading = true;
}
searchForm.childCategoryId = "";
getPlanWorkCategoryTree();
// pageInfo.domIsImage = true;
};
const planWorkCategoryList = ref([] as any[]);
const getPlanWorkCategoryTree = async () => {
const result: any = await getPlanMilestone2LeftTreeApi({
projectSn: store.sn,
pageNo: 1,
pageSize: -1,
whichModule: 4,
type: searchForm.projectType
});
if (result.success) {
planWorkCategoryList.value = result.result.records;
if(searchForm.projectType == 2) {
searchForm.childCategoryId = result.result.records[0].id;
}
onChildCategoryChange();
}
return result.success;
};
const loadCardData = async () => {
let data = {
projectSn: store.sn,
deviceUnitId: "",
pageNo: 1,
pageSize: -1,
// timeAsc: 1,
projectType: searchForm.projectType,
isImportantMilestone: 1,
childCategoryId: searchForm.childCategoryId ? searchForm.childCategoryId : ""
};
const res: any = await getMilestoneTopBarPlanRecord(data);
if (res.code == 200) {
// pageInfo.yearList = Array.from(
// new Set(
// res.result.records.map((ele: any) => {
// return dayjs(ele.milestoneTime).format("YYYY");
// })
// )
// );
pageInfo.milestoneList = res.result.records.reduce((pre: any[], cur: any, index: number) => {
if (pre.length == 0) {
pre.push({
id: "id-" + Math.random().toString(36).substr(2, 9),
firstQuarterList: []
});
}
pre[0].firstQuarterList.push({
...cur,
yearTime: cur.milestoneTime,
name: cur.milestoneName
});
return pre;
}, []);
// pageInfo.tableData = res.result.records;
pageInfo.total = res.result.total;
console.log(pageInfo.yearList);
}
return res.success;
};
const getProjectPlanGraph = () => {
let data = {
projectSn: store.sn
};
getProjectPlanGraphApi(data).then((res: any) => {
if (res.code == 200) {
pageInfo.projectItemList = res.result.reduce((pre: any[], cur: any) => {
console.log(cur, cur.children);
const children = cur.children.map((ele: any) => {
const newRestul = ele.schedules.sort((a: any, b: any) => Date.parse(a.timeNode) - Date.parse(b.timeNode));
console.log(newRestul, ele.schedules);
return {
...ele,
firstQuarterList: newRestul.map((ele: any) => {
return {
...ele,
isShowHidden: true
};
}),
minStartTime: newRestul.length > 0 ? newRestul[0].timeNode : -1,
maxEndTime: newRestul.length > 0 ? newRestul[newRestul.length - 1].timeNode : -1
};
});
pre.push({
...cur,
children: children
});
return pre;
}, []);
console.log(pageInfo.projectItemList);
}
console.log(res);
});
};
const getProjectMilestonePlanRecordList = async () => {
const res: any = await getMilestoneChartPlanRecord({
projectSn: store.sn,
type: searchForm.projectType,
childCategoryId: searchForm.childCategoryId ? searchForm.childCategoryId : ""
});
if (res.code == 200) {
console.log(res, "获取项目里程碑计划记录列表");
const timeEnd = dayjs(res.result.end).add(1, 'month').format('YYYY-MM-DD HH:mm:ss');
const timeBegin = dayjs(res.result.begin).subtract(1, 'month').format('YYYY-MM-DD HH:mm:ss');
const timeDiff = dayjs(timeEnd).diff(dayjs(timeBegin), 'year');
console.log(timeBegin, timeEnd, '获取项目里程碑计划记录列表');
if (timeBegin) {
pageInfo.yearList = [dayjs(timeBegin).format('YYYY')];
if (timeDiff > 0) {
for (let i = 0; i < timeDiff; i++) {
const year = dayjs(timeBegin).format('YYYY');
pageInfo.yearList.push(Number(year) + (i + 1));
}
if (timeDiff == 1) {
pageInfo.yearList.push(dayjs(timeEnd).format('YYYY'));
}
} else if (dayjs(timeBegin).format('YYYY') != dayjs(timeEnd).format('YYYY')) {
pageInfo.yearList.push(dayjs(timeEnd).format('YYYY'));
}
}
pageInfo.monthList = [timeBegin, timeEnd];
console.log(pageInfo.yearList, timeDiff);
pageInfo.projectItemList = res.result.list.reduce((pre: any[], cur: any) => {
// console.log(cur, cur.children);
const children = treeChildren(cur.children);
pre.push({
...cur,
children: children
});
return pre;
}, []);
console.log(22222, pageInfo.projectItemList);
console.log("我进来了11",store, schedulePlanFlag.value, pageInfo.imageUrl);
}
return res.success;
};
const treeChildren = (dataList: any[], result = []) => {
return dataList.map(ele => {
if (ele.children instanceof Array && ele.children.length > 0) {
ele.children = treeChildren(ele.children, result);
}
const newRestul =
ele.records instanceof Array &&
ele.records.sort((a: any, b: any) => Date.parse(a.beginDate) - Date.parse(b.beginDate));
// const newRestul2 =
// ele.records instanceof Array &&
// ele.records.sort((a: any, b: any) => Date.parse(a.plannedFinish) - Date.parse(b.plannedFinish));
// console.log(newRestul, ele.schedules);
if (newRestul instanceof Array && newRestul.length > 0) {
// const newPlannedStart = newRestul.filter((item: any) => item.milestoneType == 1);
// const newPlannedFinish = newRestul2.filter((item: any) => item.milestoneType == 2);
return {
...ele,
firstQuarterList: newRestul.map(ele => {
return {
...ele,
isShowHidden: true
};
}),
minStartTime: newRestul.length > 0 ? newRestul[0].beginDate : -1,
maxEndTime: newRestul.length > 0 ? newRestul[newRestul.length - 1].beginDate : -1
};
}
return {
...ele,
minStartTime: -1,
maxEndTime: -1
};
});
};
onMounted(async () => {
schedulePlanFlag.value = store.schedulePlanFlag;
if(searchForm.projectType == 1) {
pageInfo.imageUrl = store.schedulePlanImage1;
} else if(searchForm.projectType == 2) {
pageInfo.imageUrl = store.schedulePlanImage2;
}
console.log("图片", pageInfo.imageUrl, pageInfo.domIsImage);
Promise.all([getPlanWorkCategoryTree()]).then((res) => {
if(schedulePlanFlag.value && pageInfo.imageUrl) {
console.log("我进来了11");
setTimeout(() => {
// showDomIsImage();
pageInfo.domIsImage = false;
emits("setSchedulePlanShowDownFn");
}, 30000)
}
pageInfo.isLoadingAll = res.every((item) => item === true);
console.log("我是共同执行的",res, pageInfo.isLoadingAll);
});
// getPlanWorkCategoryTree();
// loadCardData();
// // getProjectPlanGraph();
// getProjectMilestonePlanRecordList();
// if(localStorage.getItem("shedulePlanImage")) {
// const shedulePlanImage = localStorage.getItem("shedulePlanImage") as string;
// pageInfo.imageUrl = shedulePlanImage;
// }
});
</script>
<style lang="scss" scoped>
.not-data {
top: 50%;
width: 20%;
left: 50%;
transform: translate(-50%, -50%);
position: absolute;
text-align: center;
img {
width: 50%;
}
p {
color: #fff;
font-size: 14px;
}
}
/* 加载前 */
.elImage :deep(.el-image__placeholder) {
background-color: #f5f7fa;
background-image: url("@/assets/images/bthgIcon/loading.gif");
background-repeat: no-repeat;
background-size: 30px 30px;
background-position: 50% 50%;
}
.fullHeight {
height: 100%;
}
.table_wrap {
height: calc(100%);
.elImage {
height: 100%;
width: 100%;
}
}
.table_wrap_active {
height: calc(98%);
display: flex;
justify-content: center;
}
.searchBox {
height: 40px;
display: flex;
align-items: center;
color: white;
padding: 0 20px;
justify-content: space-between;
position: absolute;
top: 0;
right: 10px;
.ml_20,
.mr_20,
:deep(.el-cascader) {
margin-left: 20px;
}
.elSwitch {
font-size: 20px;
cursor: pointer;
}
}
.rhombus {
display: flex;
align-items: center;
font-size: 16px;
> div {
display: flex;
align-items: center;
margin-right: 10px;
> div:last-child {
margin-left: 4px;
font-size: 14px;
}
}
.rhombus_bg {
width: 10px;
height: 10px;
background-color: #ff0000;
transform: rotateZ(45deg) skew(15deg, 15deg);
}
.rhombus_bg1 {
width: 6px;
height: 6px;
background-color: #fff;
border: 2px solid #000000;
transform: rotateZ(45deg) skew(15deg, 15deg);
}
.rhombus_bg2 {
width: 10px;
height: 10px;
background-color: #fff;
border: 2px solid #000000;
border-radius: 50%;
}
.rhombus_bg3 {
width: 30px;
height: 4px;
background-color: #13c865;
}
.rhombus_bg4 {
width: 30px;
height: 4px;
background-color: #ff0000;
}
}
.download {
color: #1684fc;
cursor: pointer;
}
</style>