Parcourir la source

Merge branch 'master' of http://1.71.9.215:3000/feiyi/cbjsxt-front-master

shiyanyu il y a 2 semaines
Parent
commit
18fda0fb7a

+ 1 - 0
src/views/costAudit/baseInfo/statistics/comprehensiveQuery.vue

@@ -310,6 +310,7 @@
           const params = {
             pageNum: this.pagination.currentPage,
             pageSize: this.pagination.pageSize,
+            isGd: 1,
             ...this.searchForm,
           }
           const response = await getReviewTaskList(params)

+ 52 - 26
src/views/costAudit/baseInfo/statistics/historyAnalysis.vue

@@ -243,11 +243,17 @@
             // 设置被监审单位选项
             if (selectedProject.auditedUnitId) {
               const unit = selectedProject.auditedUnitId.split(',')
-              this.auditedUnitOptions.forEach((item) => {
-                if (unit.includes(item.unitId)) {
-                  this.projectAuditedUnitOptions.push(item)
-                }
-              })
+              if (unit.length === 1) {
+                this.searchForm.auditedUnitId = unit[0]
+                this.searchForm.auditedUnitName =
+                  selectedProject.auditedUnitName
+              } else if (unit.length > 1) {
+                this.auditedUnitOptions.forEach((item) => {
+                  if (unit.includes(item.unitId)) {
+                    this.projectAuditedUnitOptions.push(item)
+                  }
+                })
+              }
             }
 
             // 设置监审期间
@@ -362,7 +368,8 @@
           !this.trendAllSeries ||
           this.trendAllSeries.length === 0 ||
           !this.trendData.xAxis ||
-          this.trendData.xAxis.length === 0
+          this.trendData.xAxis.length === 0 ||
+          this.trendTotalPages === 0
         ) {
           const emptyOption = {
             tooltip: {
@@ -401,7 +408,7 @@
           return
         }
 
-        // 根据当前页获取对应的数据
+        // 分页展示
         const pageSize = 8
         const startIndex = (this.trendCurrentPage - 1) * pageSize
         const endIndex = startIndex + pageSize
@@ -461,7 +468,7 @@
           return
         }
 
-        // 根据当前页获取对应的数据
+        // 分页展示
         const pageSize = 8
         const startIndex = (this.compositionCurrentPage - 1) * pageSize
         const endIndex = startIndex + pageSize
@@ -517,12 +524,17 @@
           if (this.isDestroyed) {
             return
           }
-          const dataSource =
-            res && res.costSurveysList && res.costSurveysList.length ? res : []
+          // 兼容接口返回数组或对象结构
+          let dataSource = []
+          if (Array.isArray(res)) {
+            dataSource = { costSurveysList: res }
+          } else if (res && res.costSurveysList) {
+            dataSource = res
+          }
           // 保留接口返回的原始列表,不再去重
           const normalizedDataSource = {
             ...dataSource,
-            costSurveysList: dataSource.costSurveysList || [],
+            costSurveysList: (dataSource && dataSource.costSurveysList) || [],
           }
           // 保存原始数据源
           this.rawDataSource = normalizedDataSource
@@ -595,11 +607,8 @@
       getParentIds(tree = []) {
         const ids = []
         const dfs = (node) => {
-          const isRoot =
-            node.parentId === undefined ||
-            node.parentId === null ||
-            String(node.parentId) === '-1'
-          if (isRoot) {
+          // 仅收集 parentId === '-1' 的根节点
+          if (String(node.parentId) === '-1') {
             ids.push(node.id)
           }
           if (node.children && node.children.length > 0) {
@@ -723,10 +732,24 @@
           }
 
           if (isSelected) {
-            // 选中的节点保留自身,并附上已过滤的子节点(若有)
+            // 选中的节点保留自身,并附上已过滤的子节点(若有)。
+            // 若自身没有年度数据,则用子节点汇总填充,以保证有折线数据。
+            const hasSurvey =
+              Array.isArray(node.surveysVos) && node.surveysVos.length
+            let fallback = { surveysVos: [], costSurveysVos: [] }
+            if (
+              !hasSurvey &&
+              node.costSurveysVos &&
+              node.costSurveysVos.length
+            ) {
+              fallback = this.aggregateNodeData(node)
+            }
             return {
               ...node,
-              costSurveysVos: filteredChildren,
+              surveysVos: hasSurvey ? node.surveysVos : fallback.surveysVos,
+              costSurveysVos: filteredChildren.length
+                ? filteredChildren
+                : fallback.costSurveysVos || [],
             }
           }
 
@@ -845,7 +868,7 @@
         // 保存所有趋势图数据
         this.trendAllSeries = series
         this.trendTotalCount = series.length
-        this.trendTotalPages = Math.ceil(series.length / 8)
+        this.trendTotalPages = Math.ceil(series.length / 8) || 0
         this.trendCurrentPage = 1
 
         // 构成图:使用选中节点及其子项,展示子项占比
@@ -858,7 +881,7 @@
         // 保存所有构成图数据
         this.compositionAllData = compositionData
         this.compositionTotalCount = compositionData.length
-        this.compositionTotalPages = Math.ceil(compositionData.length / 8)
+        this.compositionTotalPages = Math.ceil(compositionData.length / 8) || 0
         this.compositionCurrentPage = 1
 
         // 更新图表
@@ -881,7 +904,7 @@
             }
           )
 
-          // 启动自动轮播
+          // 自动轮播仅在总页数大于1时启动(在 mixin 中已限制)
           this.startTrendCarousel()
           this.startCompositionCarousel()
         })
@@ -912,12 +935,15 @@
           startYear: '',
           endYear: '',
         }
-        // 重置后恢复默认选中
+        // 图表数据为空
+        this.indicatorData = []
+        this.rawDataSource = []
         this.selectedIndicators = []
-        this.$nextTick(() => {
-          this.setDefaultSelection()
-        })
-        this.updateChartData(true)
+        this.trendAllSeries = []
+        this.trendData.xAxis = []
+        this.trendTotalPages = 0
+        this.compositionAllData = []
+        this.compositionTotalPages = 0
       },
 
       // 趋势图轮播相关方法

+ 91 - 27
src/views/costAudit/baseInfo/statistics/index.js

@@ -1,6 +1,8 @@
 import * as echarts from 'echarts'
 import { getAllUnitList } from '@/api/auditEntityManage.js'
-import { analyzeStatistics, getAuditTaskList } from '@/api/comprehensive'
+import { getAuditTaskList } from '@/api/auditInitiation.js'
+// , getAuditTaskList
+import { analyzeStatistics } from '@/api/comprehensive'
 // 综合分析页面的通用mixin
 export const comprehensiveMixin = {
   data() {
@@ -116,30 +118,30 @@ export const comprehensiveMixin = {
       return { ids, items }
     },
 
-    // 统一请求统计数据(接口失败或无数据时使用mock)
+    // 统一请求统计数据
     async requestStatistics(params = {}) {
       // 如果组件已销毁,直接返回 mock 数据
       if (this.isDestroyed) {
-        return mockStatisticsData
+        return []
       }
       try {
         const res = await analyzeStatistics(params)
         // 再次检查组件是否已销毁
         if (this.isDestroyed) {
-          return mockStatisticsData
+          return []
         }
         if (res && res.value) return res.value
       } catch (e) {
         // 如果是请求中止错误,静默处理
         if (e && e.message && e.message.includes('aborted')) {
-          return mockStatisticsData
+          return []
         }
         // 其他错误才打印警告
         if (!this.isDestroyed) {
           console.warn('analyzeStatistics 调用失败,使用 mock 数据', e)
         }
       }
-      return mockStatisticsData
+      return []
     },
 
     getOptions() {
@@ -249,11 +251,31 @@ export const comprehensiveMixin = {
       const result = []
       const dfs = (node) => {
         if (!node) return
-        result.push({
-          name: node.name,
-          value: node.rvalue,
-          surveysVos: node.svsurveysVos,
-        })
+        if (
+          Array.isArray(node.costSurveysVos) &&
+          node.costSurveysVos.length > 0
+        ) {
+          node.costSurveysVos.forEach((sv) => {
+            const surveysList = Array.isArray(sv.surveysVos)
+              ? sv.surveysVos
+              : []
+            result.push({
+              name: sv.name,
+              value:
+                surveysList.reduce(
+                  (sum, item) => sum + Number(item.value) || 0,
+                  0
+                ) || 0,
+              surveysVos: surveysList,
+            })
+          })
+        } else {
+          result.push({
+            name: node.name,
+            value: Number(node.rvalue) || 0,
+            surveysVos: node.surveysVos || [],
+          })
+        }
       }
       costSurveysList.forEach(dfs)
       return result
@@ -446,21 +468,32 @@ export const comprehensiveMixin = {
           show: true,
           trigger: 'item',
           formatter: (p) => {
-            let tooltipContent = `${p.name}: ${p.value} (${p.percent}%)`
-            // 如果有surveysVos信息,显示完整的surveysVos
-            if (p.data && p.data.surveysVos) {
-              const surveysVos = p.data.surveysVos
-              tooltipContent += '<br/>'
-              tooltipContent += `年份: ${surveysVos.name || ''}<br/>`
-              tooltipContent += `数值: ${surveysVos.value || ''}<br/>`
-              // 如果有其他属性,也可以显示
-              for (const key in surveysVos) {
-                if (key !== 'name' && key !== 'value') {
-                  tooltipContent += `${key}: ${surveysVos[key]}<br/>`
-                }
-              }
-            }
-            return tooltipContent
+            const header = `${p.name}: ${p.value} (${p.percent}%)`
+            const surveysVos = Array.isArray(p.data?.surveysVos)
+              ? p.data.surveysVos
+              : []
+            // 只展示年度和值,避免重复的字段名与分隔符
+            const details = surveysVos
+              .map((sv) => {
+                const yearLabel = sv.name || sv.year || '-'
+                const hasValue = sv.value !== undefined && sv.value !== null
+                const hasRvalue = sv.rvalue !== undefined && sv.rvalue !== null
+                const mainValue = hasValue
+                  ? sv.value
+                  : hasRvalue
+                  ? sv.rvalue
+                  : '-'
+                // 如果 value 和 rvalue 同时存在且不同,附加 rvalue 以显示所有值
+                const extra =
+                  hasValue && hasRvalue && sv.value !== sv.rvalue
+                    ? ` (rvalue: ${sv.rvalue})`
+                    : ''
+                return `${yearLabel}: ${mainValue}${extra}`
+              })
+              .filter(Boolean)
+            return details.length > 0
+              ? `${header}<br/>${details.join('<br/>')}`
+              : header
           },
         },
         legend: {
@@ -550,7 +583,38 @@ export const comprehensiveMixin = {
         tooltip: {
           show: true,
           trigger: 'item',
-          formatter: (p) => `${p.name}: ${p.value} (${p.percent}%)`,
+          formatter: (p) => {
+            let tooltipContent = `${p.name}: ${p.value} (${p.percent}%)`
+            // 如果有surveysVos信息,显示完整的surveysVos
+            if (p.data && p.data.surveysVos) {
+              const surveysVos = p.data.surveysVos
+              tooltipContent += '<br/>'
+              if (Array.isArray(surveysVos)) {
+                // 如果是数组,遍历显示每个元素
+                surveysVos.forEach((sv, index) => {
+                  if (index > 0) {
+                    tooltipContent += '<br/>---<br/>'
+                  }
+                  for (const key in sv) {
+                    if (sv[key] !== undefined && sv[key] !== null) {
+                      tooltipContent += `${key}: ${sv[key]}<br/>`
+                    }
+                  }
+                })
+              } else if (typeof surveysVos === 'object') {
+                // 如果是对象,直接显示所有属性
+                for (const key in surveysVos) {
+                  if (
+                    surveysVos[key] !== undefined &&
+                    surveysVos[key] !== null
+                  ) {
+                    tooltipContent += `${key}: ${surveysVos[key]}<br/>`
+                  }
+                }
+              }
+            }
+            return tooltipContent
+          },
         },
         legend: {
           show: true,

+ 86 - 68
src/views/costAudit/baseInfo/statistics/industryAnalysis.vue

@@ -36,9 +36,10 @@
                 filterable
                 allow-create
                 default-first-option
+                :disabled="!leftSearchForm.projectId"
               >
                 <el-option
-                  v-for="item in auditedUnitOptions"
+                  v-for="item in leftAuditedUnitOptions"
                   :key="item.unitId"
                   :label="item.unitName"
                   :value="item.unitId"
@@ -67,13 +68,23 @@
             </el-form-item>
 
             <el-form-item>
-              <el-button
-                icon="iconfont-5039297 icon-chaxun"
-                type="primary"
-                @click="handleLeftQuery"
+              <el-tooltip
+                class="item"
+                :content="'查询条件:项目名称、监审对象都需要选择,否则无法查询'"
+                placement="top"
               >
-                查询
-              </el-button>
+                <el-button
+                  icon="iconfont-5039297 icon-chaxun"
+                  type="primary"
+                  :disabled="
+                    !leftSearchForm.projectId || !leftSearchForm.auditedUnitId
+                  "
+                  @click="handleLeftQuery"
+                >
+                  查询
+                </el-button>
+              </el-tooltip>
+
               <el-button
                 icon="iconfont-5039297 icon-zhongzhi"
                 style="margin-left: 10px"
@@ -178,6 +189,7 @@
                 filterable
                 allow-create
                 default-first-option
+                :disabled="!rightSearchForm.projectId"
               >
                 <el-option
                   v-for="item in auditedUnitOptions"
@@ -209,9 +221,21 @@
             </el-form-item>
 
             <el-form-item>
-              <el-button type="primary" @click="handleRightQuery">
-                查询
-              </el-button>
+              <el-tooltip
+                class="item"
+                :content="'查询条件:项目名称、监审对象都需要选择,否则无法查询'"
+                placement="top"
+              >
+                <el-button
+                  type="primary"
+                  :disabled="
+                    !rightSearchForm.projectId || !rightSearchForm.auditedUnitId
+                  "
+                  @click="handleRightQuery"
+                >
+                  查询
+                </el-button>
+              </el-tooltip>
               <el-button style="margin-left: 10px" @click="handleRightReset">
                 重置
               </el-button>
@@ -227,31 +251,17 @@
             <div class="custom-list">
               <div class="list-header">项目</div>
               <div class="list-content">
-                <div v-if="rightDataItems && rightDataItems.length > 0">
-                  <div v-for="item in rightDataItems" :key="item.id">
-                    <div
-                      class="list-item level-0"
-                      :class="{ selected: isSelected(item.id, 'right') }"
-                      @click="selectItem(item.id, 'right')"
-                    >
-                      <span class="item-label">{{ item.label }}</span>
-                    </div>
-                    <div
-                      v-if="item.children && item.children.length > 0"
-                      class="list-children"
-                    >
-                      <div
-                        v-for="child in item.children"
-                        :key="child.id"
-                        class="list-item level-1"
-                        :class="{ selected: isSelected(child.id, 'right') }"
-                        @click="selectItem(child.id, 'right')"
-                      >
-                        <span class="item-label">{{ child.label }}</span>
-                      </div>
-                    </div>
-                  </div>
-                </div>
+                <el-tree
+                  v-if="rightDataItems && rightDataItems.length > 0"
+                  ref="rightIndicatorTree"
+                  class="indicator-tree"
+                  :data="rightDataItems"
+                  show-checkbox
+                  node-key="id"
+                  :props="treeProps"
+                  :check-strictly="true"
+                  @check="handleRightCheck"
+                ></el-tree>
                 <Empty v-else description="暂无数据"></Empty>
               </div>
             </div>
@@ -307,6 +317,7 @@
           startYear: '',
           endYear: '',
         },
+        leftAuditedUnitOptions: [],
         // 右侧搜索表单数据
         rightSearchForm: {
           projectName: '',
@@ -316,9 +327,9 @@
           startYear: '',
           endYear: '',
         },
-        // 左侧数据项树形结构(从mock数据构建)
+        // 左侧数据项树形结构
         leftDataItems: [],
-        // 右侧数据项树形结构(从mock数据构建)
+        // 右侧数据项树形结构
         rightDataItems: [],
         // 左侧数据源
         leftDataSource: null,
@@ -922,6 +933,16 @@
         this.updateLeftChartsBySelection()
       },
 
+      // 右侧树选中变更
+      handleRightCheck() {
+        const checkedKeys =
+          this.$refs.rightIndicatorTree?.getCheckedKeys?.() || []
+        this.rightSelectedItems = checkedKeys
+          .map((id) => this.findItemById(id, 'right'))
+          .filter(Boolean)
+        this.updateRightChartsBySelection()
+      },
+
       // 判断节点是否被选中
       isSelected(id, type = 'left') {
         const selectedItems =
@@ -1184,6 +1205,12 @@
                   this.auditedUnitOptions.find(
                     (item) => item.unitId === unitIdArray[0]
                   )?.unitName || ''
+              } else if (unitIdArray.length > 1) {
+                this.auditedUnitOptions.forEach((item) => {
+                  if (unitIdArray.includes(item.unitId)) {
+                    this.leftAuditedUnitOptions.push(item)
+                  }
+                })
               }
             }
 
@@ -1437,20 +1464,20 @@
         // 重置左侧搜索表单
         this.leftSearchForm = {
           projectName: '',
+          projectId: '',
+          auditedUnitName: '',
           auditedUnitId: '',
-          startYear: '2024',
-          endYear: '2025',
-        }
-        // 重置左侧树形选择
-        if (this.$refs.leftIndicatorTree) {
-          this.$refs.leftIndicatorTree.clearChecked()
+          startYear: '',
+          endYear: '',
         }
-        // 重置后默认选中(与 history 页一致)
-        this.setLeftDefaultSelection()
-        // 重置左侧图表
+        this.leftSelectedItems = []
+        this.leftDataItems = []
+        this.leftDataSource = []
+        this.leftTrendData = {}
+        this.leftProportionData = []
+        this.leftProportionAllData = []
+        this.leftProportionTotalPages = 0
         this.leftProportionCurrentPage = 1
-        this.updateLeftTrendChart()
-        this.updateLeftProportionChart()
       },
 
       // 左侧默认选中:优先根节点(parentId 为 -1),否则第一个叶子
@@ -1485,28 +1512,20 @@
         // 重置右侧搜索表单
         this.rightSearchForm = {
           projectName: '',
+          projectId: '',
+          auditedUnitName: '',
           auditedUnitId: '',
-          startYear: '2024',
-          endYear: '2025',
-        }
-        // 重置右侧树形选择
-        if (this.$refs.rightDataTree) {
-          this.$refs.rightDataTree.clearChecked()
-        }
-        // 重置后默认选中第一个父级节点(单选)
-        if (this.rightDataItems && this.rightDataItems.length > 0) {
-          const { items: parentItems } = this.getParentIds(this.rightDataItems)
-          const defaultItem =
-            parentItems.length > 0 ? parentItems[0] : this.rightDataItems[0]
-          this.rightSelectedItems = defaultItem ? [defaultItem] : []
-        } else {
-          // 如果没有数据,清空选中项
-          this.rightSelectedItems = []
+          startYear: '',
+          endYear: '',
         }
-        // 重置右侧图表
+        this.rightSelectedItems = []
+        this.rightDataSource = []
+        this.rightDataItems = []
+        this.rightTrendData = {}
+        this.rightProportionData = {}
+        this.rightProportionAllData = []
+        this.rightProportionTotalPages = 0
         this.rightProportionCurrentPage = 1
-        this.updateRightTrendChart()
-        this.updateRightProportionChart()
       },
     },
   }
@@ -1705,7 +1724,6 @@
   .custom-list {
     border-radius: 4px;
     overflow: hidden;
-    border: 1px solid #e0e0e0;
     height: 800px;
     max-height: 800px;
     overflow-x: hidden;