|
|
@@ -0,0 +1,285 @@
|
|
|
+<template>
|
|
|
+ <div class="hc-layout-box">
|
|
|
+ <div v-if="contractInfo?.contractType === 2 || contractInfo?.contractType === 3">
|
|
|
+ <hc-new-switch :datas="contractTypeTab" :keys="contractTypeTabKey" size="default" @change="contractTypeTabChange" />
|
|
|
+ </div>
|
|
|
+ <div v-loading="isProcessLoading" class="hc-round-chart mt-14px">
|
|
|
+ <el-row :gutter="30">
|
|
|
+ <template v-for="(item, index) in processMaterialList" :key="index">
|
|
|
+ <el-col v-if="item.isHide === 0" :span="isProcessSpan">
|
|
|
+ <div class="hc-round-chart-card-box">
|
|
|
+ <div class="hc-card-content-box">
|
|
|
+ <div class="card-title w-100 flex justify-between">
|
|
|
+ <div>
|
|
|
+ {{ item.title }}
|
|
|
+ </div>
|
|
|
+ <!-- <div class="eye-icon-container">
|
|
|
+ <HcTooltip keys="schedule-data-hide">
|
|
|
+ <el-link type="warning" @click="hideData(item)">
|
|
|
+ <HcIcon name="eye-off" />
|
|
|
+ </el-link>
|
|
|
+ </HcTooltip>
|
|
|
+ </div> -->
|
|
|
+ </div>
|
|
|
+ <div class="card-ratio-box">
|
|
|
+ <div class="ratio-num">{{ item.ratio }}</div>
|
|
|
+ <div class="ratio-text">
|
|
|
+ <div class="unit">%</div>
|
|
|
+ <div class="text">完成率</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="card-amount-box">
|
|
|
+ <div class="amount-item">
|
|
|
+ <div class="text">应填(份)</div>
|
|
|
+ <div class="num">{{ item.amount }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="amount-divider" />
|
|
|
+ <div class="amount-item">
|
|
|
+ <div class="text">已填(份)</div>
|
|
|
+ <div class="num">{{ item.successAmount }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="hc-card-chart-box">
|
|
|
+ <RoundChart :ratio="item.ratio" />
|
|
|
+ <div class="text-num">{{ item.ratio }}%</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </template>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
+ <div class="hc-chart-flex">
|
|
|
+ <el-row :gutter="30" class="h-full">
|
|
|
+ <el-col :span="18" class="h-full">
|
|
|
+ <div class="hc-report-chart-card-box">
|
|
|
+ <div class="hc-chart-title">
|
|
|
+ <span class="title">报表资料审批统计</span>
|
|
|
+ <span class="hc-chart-text">(已审批{{ materialList }}份)</span>
|
|
|
+ </div>
|
|
|
+ <div class="hc-report-chart-box">
|
|
|
+ <ReportChart :datas="processMaterialStatusList" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="6" class="h-full">
|
|
|
+ <div class="hc-media-chart-card-box">
|
|
|
+ <div class="hc-chart-title">
|
|
|
+ <span class="title">声像媒体资料统计</span>
|
|
|
+ <el-button round size="large" @click="toTableClick">
|
|
|
+ <span>WBS节点进度</span>
|
|
|
+ <HcIcon name="arrow-right-s" style="margin-right: 0;" ui="ml-2" />
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ <div class="hc-media-chart-box">
|
|
|
+ <div class="hc-media-pian-box">
|
|
|
+ <div class="item">
|
|
|
+ <span class="name">总计</span>
|
|
|
+ <span class="num">{{ imageClassInfo.amount }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="item">
|
|
|
+ <span class="name">图片</span>
|
|
|
+ <span class="num c1">{{ imageClassInfo.image }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="item">
|
|
|
+ <span class="name">视频</span>
|
|
|
+ <span class="num c2">{{ imageClassInfo.video }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <MediaChart :datas="contractImageClassificationList" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { onActivated, ref } from 'vue'
|
|
|
+import { useRouter } from 'vue-router'
|
|
|
+import { useAppStore } from '~src/store'
|
|
|
+import { getArrValue, useClick } from 'js-fast-way'
|
|
|
+import RoundChart from './components/echarts/RoundChart.vue'
|
|
|
+import ReportChart from './components/echarts/ReportChart.vue'
|
|
|
+import MediaChart from './components/echarts/MediaChart.vue'
|
|
|
+import DataApi from '~api/schedule/data'
|
|
|
+
|
|
|
+//变量
|
|
|
+const router = useRouter()
|
|
|
+const useAppState = useAppStore()
|
|
|
+const projectId = ref(useAppState.getProjectId)
|
|
|
+const contractId = ref(useAppState.getContractId)
|
|
|
+const contractInfo = ref(useAppState.getContractInfo)
|
|
|
+const isCollapse = ref(useAppState.getCollapse)
|
|
|
+
|
|
|
+//渲染完成
|
|
|
+onActivated(async () => {
|
|
|
+ await useClick()
|
|
|
+ queryMaterialProgress()
|
|
|
+ queryMaterialProgressStatus()
|
|
|
+ queryImageClassification()
|
|
|
+})
|
|
|
+
|
|
|
+//结构类型tab数据和相关处理
|
|
|
+const contractTypeTabKey = ref(2)
|
|
|
+const contractTypeTab = ref([
|
|
|
+ { key: '1', name: '施工数据' },
|
|
|
+ { key: '2', name: '监理数据' },
|
|
|
+])
|
|
|
+const contractTypeTabChange = ({ key }) => {
|
|
|
+ contractTypeTabKey.value = key
|
|
|
+ queryMaterialProgress()
|
|
|
+ queryMaterialProgressStatus()
|
|
|
+ queryImageClassification()
|
|
|
+}
|
|
|
+
|
|
|
+//获取合同段类型
|
|
|
+const getContractTypeKey = () => {
|
|
|
+ const { contractType } = contractInfo.value
|
|
|
+ if (contractType === 2 || contractType === 3) {
|
|
|
+ return contractTypeTabKey.value ?? '1'
|
|
|
+ } else {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//查询内业资料进度
|
|
|
+const isProcessLoading = ref(false)
|
|
|
+const processMaterialList = ref([])
|
|
|
+const isProcessSpan = ref(24)
|
|
|
+const queryMaterialProgress = async () => {
|
|
|
+ isProcessLoading.value = true
|
|
|
+ const classifyType = getContractTypeKey()
|
|
|
+ const { error, code, data } = await DataApi.queryMaterialProgress({
|
|
|
+ projectId: projectId.value,
|
|
|
+ contractId: contractId.value,
|
|
|
+ classifyType: classifyType,
|
|
|
+ })
|
|
|
+ //处理数据
|
|
|
+ isProcessLoading.value = false
|
|
|
+ if (!error && code === 200) {
|
|
|
+ const newArr = getArrValue(data?.processMaterialList)
|
|
|
+ processMaterialList.value = newArr
|
|
|
+ if (newArr.length === 4) {
|
|
|
+ isProcessSpan.value = 6
|
|
|
+ } else if (newArr.length === 3) {
|
|
|
+ isProcessSpan.value = 8
|
|
|
+ } else if (newArr.length === 2) {
|
|
|
+ isProcessSpan.value = 12
|
|
|
+ } else if (newArr.length === 1) {
|
|
|
+ isProcessSpan.value = 24
|
|
|
+ } else if (newArr.length === 0) {
|
|
|
+ isProcessSpan.value = 24
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ processMaterialList.value = []
|
|
|
+ isProcessSpan.value = 24
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//报表资料审批统计
|
|
|
+const materialList = ref(0)
|
|
|
+const isMaterialLoading = ref(false)
|
|
|
+const processMaterialStatusList = ref([])
|
|
|
+const queryMaterialProgressStatus = async () => {
|
|
|
+ isMaterialLoading.value = true
|
|
|
+ const classifyType = getContractTypeKey()
|
|
|
+ const { error, code, data } = await DataApi.queryMaterialProgressStatus({
|
|
|
+ projectId: projectId.value,
|
|
|
+ contractId: contractId.value,
|
|
|
+ classifyType: classifyType,
|
|
|
+ })
|
|
|
+ //处理数据
|
|
|
+ isMaterialLoading.value = false
|
|
|
+ if (!error && code === 200) {
|
|
|
+ let num = 0
|
|
|
+ const listData = getArrValue(data?.processMaterialStatusList)
|
|
|
+ for (let i = 0; i < listData.length; i++) {
|
|
|
+ const Amount = listData[i]?.approvalAmount || 0
|
|
|
+ num += Amount
|
|
|
+ }
|
|
|
+ materialList.value = num
|
|
|
+ processMaterialStatusList.value = listData
|
|
|
+ } else {
|
|
|
+ materialList.value = 0
|
|
|
+ processMaterialStatusList.value = []
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//声像媒体资料统计
|
|
|
+const isImageClassLoading = ref(false)
|
|
|
+const contractImageClassificationList = ref([])
|
|
|
+const imageClassInfo = ref({ amount: 0, image: 0, video: 0 })
|
|
|
+const queryImageClassification = async () => {
|
|
|
+ isImageClassLoading.value = true
|
|
|
+ const classifyType = getContractTypeKey()
|
|
|
+ const { error, code, data } = await DataApi.queryImageClassification({
|
|
|
+ projectId: projectId.value,
|
|
|
+ contractId: contractId.value,
|
|
|
+ classifyType: classifyType,
|
|
|
+ })
|
|
|
+ //处理数据
|
|
|
+ isImageClassLoading.value = false
|
|
|
+ if (!error && code === 200) {
|
|
|
+ const imageClassList = getArrValue(data?.contractImageClassificationList)
|
|
|
+ contractImageClassificationList.value = imageClassList
|
|
|
+ //数据显示
|
|
|
+ let AxisData = { amount: 0, image: 0, video: 0 }
|
|
|
+ for (let i = 0; i < imageClassList.length; i++) {
|
|
|
+ AxisData.amount = imageClassList[i].amount
|
|
|
+ AxisData.image = imageClassList[i].imageAmount
|
|
|
+ AxisData.video = imageClassList[i].videoAmount
|
|
|
+ }
|
|
|
+ imageClassInfo.value = AxisData
|
|
|
+ } else {
|
|
|
+ contractImageClassificationList.value = []
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//查看WBS节点进度
|
|
|
+const toTableClick = () => {
|
|
|
+ router.push({ path: '/schedule/table' })
|
|
|
+}
|
|
|
+const hideLoad = ref(false)
|
|
|
+const hideData = async (item)=>{
|
|
|
+ hideLoad.value = true
|
|
|
+ const classifyType = getContractTypeKey()
|
|
|
+ const { error, code, msg } = await DataApi.hideProcessMaterial({
|
|
|
+ hideType:item.hideType,
|
|
|
+ contractId: contractId.value,
|
|
|
+ classifyType: classifyType,
|
|
|
+ type:1,
|
|
|
+ })
|
|
|
+ //处理数据
|
|
|
+ hideLoad.value = false
|
|
|
+ if (!error && code === 200) {
|
|
|
+ window.$message.success(msg)
|
|
|
+ queryMaterialProgress()
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+/* 默认隐藏闭眼图标容器 */
|
|
|
+.hc-round-chart-card-box .eye-icon-container {
|
|
|
+ display: none;
|
|
|
+}
|
|
|
+
|
|
|
+/* 鼠标移入卡片时显示闭眼图标 */
|
|
|
+.hc-round-chart-card-box:hover .eye-icon-container {
|
|
|
+ display: block;
|
|
|
+}
|
|
|
+
|
|
|
+/* 可选:添加过渡效果让显示更平滑 */
|
|
|
+.eye-icon-container {
|
|
|
+ transition: opacity 0.3s ease;
|
|
|
+ opacity: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.hc-round-chart-card-box:hover .eye-icon-container {
|
|
|
+ opacity: 1;
|
|
|
+}
|
|
|
+@import "../../styles/schedule/hc-data.scss";
|
|
|
+</style>
|