Bläddra i källkod

feat:新增菜单图标svg文件
fix:修补成本调查表显示的Bug
test:首页的样式,综合查询统计页面的样式

cb_luzhixia 1 månad sedan
förälder
incheckning
211eb06fdb

+ 11 - 2
src/api/user.js

@@ -23,13 +23,13 @@ export async function ssoLogin(data) {
     url = `${context.auth}/sso/auth?ssoMode=cas&ticket=${data.ticket}&service=${data.service}`
   } else if (window.ssoConfig.mode == 'oauth') {
     let params = {
-      code: data.code
+      code: data.code,
     }
     return request({
       url: `${commonSign}auth/sso/exchangeCode`,
       method: 'post',
       data: qs.stringify(params),
-      headers: {'Content-type': 'application/x-www-form-urlencoded'}
+      headers: { 'Content-type': 'application/x-www-form-urlencoded' },
     })
     // url = `${context.auth}/sso/auth?ssoMode=oauth&code=${data.code}&service=${data.service}`
   } else {
@@ -73,3 +73,12 @@ export function updatePassword(data) {
   const url = `${context.uc}/api/user/v1/user/changUserPsd`
   return request.post(url, data)
 }
+
+export function ssoLoginByCode(data) {
+  let url = window.context.form + '/api/data-middle-platform/sso/dmp'
+  return request({
+    url,
+    method: 'get',
+    params: data,
+  })
+}

+ 1 - 0
src/assets/svg/企业申报成本资料管理.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1760668771221" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1757" width="256" height="256" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M749.149091 595.130182a170.682182 170.682182 0 1 1 0 341.317818 170.682182 170.682182 0 0 1 0-341.317818zM651.636364 77.218909v482.955636a219.461818 219.461818 0 0 0-86.667637 327.68H182.318545c-25.6 0-42.682182-17.035636-42.682181-42.635636V196.701091c0-21.317818 12.8-38.4 34.117818-42.682182L600.436364 47.383273c21.317818-4.282182 42.682182 8.517818 51.2 29.835636z m55.249454 579.584a17.082182 17.082182 0 0 0-28.997818 12.101818c0 4.514909 1.722182 8.843636 4.840727 11.962182l34.210909 34.071273h-36.026181a17.035636 17.035636 0 0 0 0 34.071273h51.2v34.071272h-51.2a17.035636 17.035636 0 0 0 0 34.071273h51.2v45.428364a16.989091 16.989091 0 0 0 34.024727 0v-45.381819h51.2a17.408 17.408 0 0 0 17.128727-17.221818 16.896 16.896 0 0 0-5.026909-11.915636 16.849455 16.849455 0 0 0-12.008727-4.980364h-51.2v-34.071272h51.2a17.035636 17.035636 0 0 0 0-33.978182h-36.026182l34.164364-34.164364a16.756364 16.756364 0 0 0 4.840727-11.962182 17.082182 17.082182 0 0 0-28.904727-12.101818l-42.356364 42.216727z m-12.567273-195.584l187.717819 72.564364c17.082182 8.517818 25.6 21.317818 25.6 38.4l0.046545 42.402909a218.903273 218.903273 0 0 0-213.410909-68.887273V461.218909z m-213.364363 42.682182H310.318545c-25.6 0-42.682182 17.082182-42.682181 42.682182 0 21.317818 17.082182 38.4 38.4 42.635636h174.917818c25.6 0 42.682182-17.035636 42.682182-42.635636s-17.082182-42.682182-42.682182-42.682182z m0-213.317818H310.318545c-25.6 0-42.682182 17.035636-42.682181 42.635636 0 21.364364 17.082182 38.4 38.4 42.682182h174.917818c25.6 0 42.682182-17.082182 42.682182-42.682182s-17.082182-42.635636-42.682182-42.635636z" fill="#666666" p-id="1758"></path></svg>

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
src/assets/svg/成本监审管理.svg


+ 1 - 0
src/assets/svg/成本监审辅助管理.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1761013466462" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1066" width="256" height="256" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M856.355737 86.785039h-150.517306V22.751325c0-15.119953-7.504447-22.687862-22.6244-22.687862h-90.624523c-15.008893 0-22.6244 7.567909-22.6244 22.687862v63.986117H343.514859V22.751325c0-15.119953-7.504447-22.687862-22.687863-22.687862h-90.561061c-15.072356 0-22.703728 7.504447-22.703727 22.687862v63.922655H57.980974A53.165753 53.165753 0 0 0 4.228192 139.189241v834.532553a50.912832 50.912832 0 0 0 51.515727 50.214743h592.248396a278.965511 278.965511 0 0 1 261.783025-492.596324l0.301447-1.888011v-390.294692c0.047597-28.907192-23.988844-52.372471-53.72105-52.372471zM408.738496 585.87041H157.648911l-5.664033-0.412507a41.821821 41.821821 0 0 1 5.664033-83.294598h251.089585a41.853553 41.853553 0 0 1 0 83.707105z m223.181928-223.197794H157.648911l-5.664033-0.412506a41.821821 41.821821 0 0 1 5.664033-83.294599h474.271513a41.853553 41.853553 0 1 1 0 83.707105z" fill="#666666" p-id="1067"></path><path d="M796.574014 564.324874a223.197794 223.197794 0 1 0 223.197794 223.197793 223.197794 223.197794 0 0 0-223.197794-223.197793z m-139.395495 362.76781l26.289362-92.671191 66.381829 66.381829z m99.271297-32.937064l-66.365964-66.365964 146.185988-146.185987 66.365963 66.365963z m175.188373-175.156643l-22.418146 22.307087-66.381829-66.381829 22.322952-22.307086s10.629977-10.629977 21.450343 0.190387l43.662235 43.662236c11.899228 11.851631 1.316848 22.529206 1.316848 22.529205z" fill="#666666" p-id="1068"></path></svg>

+ 1 - 0
src/assets/svg/监审项目管理.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1760668951746" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3098" xmlns:xlink="http://www.w3.org/1999/xlink" width="256" height="256"><path d="M774.749091 295.796364c7.773091 4.468364 13.498182 11.682909 15.918545 20.433454l145.035637 513.396364a33.978182 33.978182 0 0 1-23.179637 42.077091l-159.883636 45.800727a33.512727 33.512727 0 0 1-41.565091-23.365818L566.132364 380.555636a33.838545 33.838545 0 0 1 23.179636-41.890909l159.883636-45.847272a34.210909 34.210909 0 0 1 25.6 2.978909z m-537.925818 10.752c18.944 0.186182 33.978182 15.406545 33.978182 33.978181v533.783273a33.931636 33.931636 0 0 1-33.792 33.978182H80.290909a33.792 33.792 0 0 1-33.745454-33.978182V340.526545c0-18.757818 15.034182-33.792 33.559272-33.978181h156.718546zM509.114182 139.636364c18.944 0.186182 33.978182 15.36 33.978182 33.978181v700.695273a33.931636 33.931636 0 0 1-33.792 33.978182H347.927273a33.792 33.792 0 0 1-33.745455-33.978182V173.568c0-18.711273 15.034182-33.745455 33.559273-33.931636h161.373091z m254.464 291.746909l-113.291637 32.488727a15.406545 15.406545 0 0 0-10.565818 18.897455l10.007273 35.793454a15.173818 15.173818 0 0 0 18.897455 10.565818l113.338181-32.442182a15.406545 15.406545 0 0 0 10.565819-18.944l-10.007273-35.793454a15.173818 15.173818 0 0 0-18.944-10.565818z m-546.909091 15.36H99.746909a15.36 15.36 0 0 0-15.406545 15.453091v37.096727c0 8.517818 6.842182 15.36 15.36 15.36h116.875636a15.36 15.36 0 0 0 15.36-15.36V462.196364a15.36 15.36 0 0 0-15.36-15.406546z m270.754909-189.160728h-116.829091a15.36 15.36 0 0 0-15.406545 15.406546v37.096727c0 8.517818 6.842182 15.36 15.36 15.36h116.875636a15.36 15.36 0 0 0 15.36-15.36v-37.096727a15.36 15.36 0 0 0-15.36-15.36z" fill="#666666" p-id="3099"></path></svg>

+ 8 - 1
src/config/setting.config.js

@@ -34,7 +34,14 @@ const setting = {
   // 路由模式,可选值为 history 或 hash
   routerMode: 'history',
   //不经过token校验的路由
-  routesWhiteList: ['/login', '/404', '/401', '/500', 'tenantLogin'],
+  routesWhiteList: [
+    '/login',
+    '/404',
+    '/401',
+    '/500',
+    'tenantLogin',
+    '/sso-login',
+  ],
   //加载时显示文字
   loadingText: '正在加载中...',
   //token名称

+ 6 - 0
src/router/index.js

@@ -13,6 +13,12 @@ export const constantRoutes = [
     hidden: true,
   },
   {
+    path: '/sso-login',
+    name: 'ssoLogin',
+    component: () => import('@/views/login/ssoLogin.vue'),
+    hidden: true,
+  },
+  {
     name: 'tenantLogin',
     path: '/login/:tenant',
     component: () => import('@/views/login/index'),

+ 486 - 310
src/views/costAudit/baseInfo/costFormManage/infoMaintain.vue

@@ -787,28 +787,15 @@
                 :data="contentEditForm.fixedTable.fixedTables"
                 border
                 style="width: 100%"
+                row-key="rowid"
+                default-expand-all
+                :tree-props="{
+                  children: 'children',
+                  hasChildren: 'hasChildren',
+                }"
                 @selection-change="handleSelectionChange"
               >
-                <el-table-column label="序号" width="100" align="center">
-                  <template slot-scope="scope">
-                    <el-input
-                      :value="
-                        scope.row.fixedValues
-                          ? scope.row.fixedValues['序号']
-                          : ''
-                      "
-                      size="small"
-                      placeholder="数字或中文"
-                      :disabled="viewDetail"
-                      @input="handleFixedValueChange(scope.row, '序号', $event)"
-                    ></el-input>
-                  </template>
-                </el-table-column>
-                <el-table-column
-                  label="父子节点关系"
-                  align="center"
-                  width="120"
-                >
+                <el-table-column label="父子节点" align="center" width="100">
                   <template slot-scope="scope">
                     <el-tag
                       v-if="
@@ -837,6 +824,22 @@
                     <el-tag v-else type="info" size="small">无</el-tag>
                   </template>
                 </el-table-column>
+                <el-table-column label="序号" width="120" align="center">
+                  <template slot-scope="scope">
+                    <el-input
+                      :value="
+                        scope.row.fixedValues
+                          ? scope.row.fixedValues['序号']
+                          : ''
+                      "
+                      size="small"
+                      placeholder="数字或中文"
+                      :disabled="viewDetail"
+                      style="flex: 1; margin: 0"
+                      @input="handleFixedValueChange(scope.row, '序号', $event)"
+                    ></el-input>
+                  </template>
+                </el-table-column>
                 <el-table-column
                   v-for="(item, index) in contentEditForm.fixedTable
                     .fixedTableHeaders"
@@ -932,19 +935,21 @@
                         type="text"
                         size="mini"
                         :disabled="viewDetail"
-                        @click="handleMoveUp(scope.$index, '固定表')"
+                        @click="handleMoveUp(scope.$index, '固定表', scope.row)"
                       >
                         上升
                       </el-button>
                       <el-button
                         v-if="
                           scope.$index !==
-                          contentEditForm.tableHeaders.length - 1
+                          contentEditForm.fixedTable.fixedTables.length - 1
                         "
                         type="text"
                         size="mini"
                         :disabled="viewDetail"
-                        @click="handleMoveDown(scope.$index, '固定表')"
+                        @click="
+                          handleMoveDown(scope.$index, '固定表', scope.row)
+                        "
                       >
                         下降
                       </el-button>
@@ -1229,30 +1234,15 @@
                 :data="contentEditForm.dynamicTable.dynamicTables"
                 border
                 style="width: 100%"
+                row-key="rowid"
+                default-expand-all
+                :tree-props="{
+                  children: 'children',
+                  hasChildren: 'hasChildren',
+                }"
                 @selection-change="handleSelectionChange"
               >
-                <el-table-column label="序号" width="100" align="center">
-                  <template slot-scope="scope">
-                    <el-input
-                      :value="
-                        scope.row.dynamicValues
-                          ? scope.row.dynamicValues['序号']
-                          : ''
-                      "
-                      size="small"
-                      placeholder="数字或中文"
-                      :disabled="viewDetail"
-                      @input="
-                        handleDynamicValueChange(scope.row, '序号', $event)
-                      "
-                    ></el-input>
-                  </template>
-                </el-table-column>
-                <el-table-column
-                  label="父子节点关系"
-                  align="center"
-                  width="120"
-                >
+                <el-table-column label="父子节点" align="center" width="100">
                   <template slot-scope="scope">
                     <el-tag
                       v-if="
@@ -1281,6 +1271,33 @@
                     <el-tag v-else type="info" size="small">无</el-tag>
                   </template>
                 </el-table-column>
+                <el-table-column label="序号" width="120" align="center">
+                  <template slot-scope="scope">
+                    <div
+                      style="
+                        display: flex;
+                        align-items: center;
+                        min-height: 32px;
+                      "
+                    >
+                      <el-input
+                        :value="
+                          scope.row.dynamicValues
+                            ? scope.row.dynamicValues['序号']
+                            : ''
+                        "
+                        size="small"
+                        placeholder="数字或中文"
+                        :disabled="viewDetail"
+                        style="flex: 1; margin: 0"
+                        @input="
+                          handleDynamicValueChange(scope.row, '序号', $event)
+                        "
+                      ></el-input>
+                    </div>
+                  </template>
+                </el-table-column>
+
                 <el-table-column
                   v-for="(item, index) in contentEditForm.dynamicTable
                     .dynamicTableHeaders"
@@ -1303,7 +1320,12 @@
                     ></el-input>
                   </template>
                 </el-table-column>
-                <el-table-column label="操作" align="center" fixed="right">
+                <el-table-column
+                  label="操作"
+                  align="center"
+                  fixed="right"
+                  width="200"
+                >
                   <template slot-scope="scope">
                     <div class="table-actions">
                       <el-button
@@ -1340,7 +1362,7 @@
                         type="text"
                         size="mini"
                         :disabled="viewDetail"
-                        @click="handleMoveUp(scope.$index, '动态表')"
+                        @click="handleMoveUp(scope.$index, '动态表', scope.row)"
                       >
                         上升
                       </el-button>
@@ -1352,7 +1374,9 @@
                         type="text"
                         size="mini"
                         :disabled="viewDetail"
-                        @click="handleMoveDown(scope.$index, '动态表')"
+                        @click="
+                          handleMoveDown(scope.$index, '动态表', scope.row)
+                        "
                       >
                         下降
                       </el-button>
@@ -2172,19 +2196,47 @@
 
         switch (type) {
           case '固定表项目':
+            let parentIndex1 =
+              this.contentEditForm.fixedTable.fixedTables.findIndex(
+                (item) => item.rowid == parentRow.rowid
+              )
+            if (
+              !this.contentEditForm.fixedTable.fixedTables[parentIndex1]
+                .children
+            ) {
+              this.$set(
+                this.contentEditForm.fixedTable.fixedTables[parentIndex1],
+                'children',
+                []
+              )
+            }
+
             let childOrderNum =
-              this.contentEditForm.fixedTable.fixedTables.length + 1
+              this.contentEditForm.fixedTable.fixedTables[parentIndex1].children
+                .length + 1
+
+            let fixedValues = {
+              ...parentRow.fixedValues,
+            }
+
+            for (const key in fixedValues) {
+              if (key == '序号') {
+                fixedValues[key] = childOrderNum
+              } else {
+                fixedValues[key] = ''
+              }
+            }
 
             const fixedNewRow = {
-              orderText: childOrderNum,
-              orderNum: childOrderNum,
+              orderText: this.contentEditForm.fixedTable.fixedTables.length + 1,
+              orderNum: this.contentEditForm.fixedTable.fixedTables.length + 1,
               cellCode: '',
               calculationFormula: '',
               unit: '',
               tabtype: this.templateType,
               surveyTemplateId: this.surveyTemplateId,
               versionId: this.versionId,
-              fixedValues: { ...parentRow.fixedValues },
+              fixedValues: fixedValues,
               parentid: parentRow.rowid,
               isChild: true,
               isSubItem: true,
@@ -2199,16 +2251,44 @@
               }
             )
 
-            this.contentEditForm.fixedTable.fixedTables.splice(
-              index + 1,
-              0,
-              fixedNewRow
-            )
+            // 先将子项添加到children数组
+            this.contentEditForm.fixedTable.fixedTables[
+              parentIndex1
+            ].children.push(fixedNewRow)
+
+            // this.contentEditForm.fixedTable.fixedTables.splice(
+            //   index + 1,
+            //   0,
+            //   fixedNewRow
+            // )
             break
 
           case '动态表项目':
+            let parentIndex2 =
+              this.contentEditForm.dynamicTable.dynamicTables.findIndex(
+                (item) => item.rowid == parentRow.rowid
+              )
+            if (
+              !this.contentEditForm.dynamicTable.dynamicTables[parentIndex2]
+                .children
+            ) {
+              this.$set(
+                this.contentEditForm.dynamicTable.dynamicTables[parentIndex2],
+                'children',
+                []
+              )
+            }
+
             let dynamicChildOrderNum =
               this.contentEditForm.dynamicTable.dynamicTables.length + 1
+            let dynamicValues = { ...parentRow.dynamicValues }
+            for (const key in dynamicValues) {
+              if (key == '序号') {
+                dynamicValues[key] = dynamicChildOrderNum
+              } else {
+                dynamicValues[key] = ''
+              }
+            }
 
             const dynamicNewRow = {
               orderText: dynamicChildOrderNum,
@@ -2216,7 +2296,7 @@
               tabtype: this.templateType,
               surveyTemplateId: this.surveyTemplateId,
               versionId: this.versionId,
-              dynamicValues: { ...parentRow.dynamicValues },
+              dynamicValues: dynamicValues,
               parentid: parentRow.rowid,
               isChild: true,
               isSubItem: true,
@@ -2230,12 +2310,15 @@
                 }
               }
             )
-
-            this.contentEditForm.dynamicTable.dynamicTables.splice(
-              index + 1,
-              0,
-              dynamicNewRow
-            )
+            this.contentEditForm.dynamicTable.dynamicTables[
+              parentIndex2
+            ].children.push(dynamicNewRow)
+
+            // this.contentEditForm.dynamicTable.dynamicTables.splice(
+            //   index + 1,
+            //   0,
+            //   dynamicNewRow
+            // )
             break
         }
 
@@ -2517,6 +2600,7 @@
               fixedValues: {},
               parentid: -1,
               rowid: this.generateUUID(),
+              children: [],
             }
 
             this.contentEditForm.fixedTable.fixedTablesTitle.forEach(
@@ -2564,6 +2648,7 @@
               dynamicValues: {},
               parentid: -1,
               rowid: this.generateUUID(),
+              children: [],
             }
 
             this.contentEditForm.dynamicTable.dynamicTablesTitle.forEach(
@@ -2630,12 +2715,53 @@
             break
 
           case '固定表项目':
-            if (this.contentEditForm.fixedTable.fixedTables.length <= 1) {
-              this.$message.warning('至少保留一个项目')
-              return
+            // 检查是否是删除子项
+            const isChildItem = row.isChild || row.isSubItem || false
+
+            if (isChildItem) {
+              // 查找父项
+              const parentItem =
+                this.contentEditForm.fixedTable.fixedTables.find(
+                  (item) =>
+                    item.children &&
+                    item.children.some((child) => child.rowid === row.rowid)
+                )
+
+              if (parentItem && parentItem.children) {
+                // 从父项的children数组中删除子项
+                const childIndex = parentItem.children.findIndex(
+                  (child) => child.rowid === row.rowid
+                )
+                if (childIndex > -1) {
+                  parentItem.children.splice(childIndex, 1)
+
+                  // 如果children数组为空,将hasChildren设为false
+                  if (parentItem.children.length === 0) {
+                    this.$set(parentItem, 'hasChildren', false)
+                  } else {
+                    // 重新计算子项序号
+                    parentItem.children.forEach((child, idx) => {
+                      child.orderText = idx + 1
+                      child.orderNum = idx + 1
+                    })
+                  }
+
+                  // 确保Vue响应式系统检测到变化
+                  const children = [...parentItem.children]
+                  this.$set(parentItem, 'children', children)
+
+                  handleDelete() // 执行删除逻辑
+                }
+              }
+            } else {
+              // 处理删除父项的情况
+              if (this.contentEditForm.fixedTable.fixedTables.length <= 1) {
+                this.$message.warning('至少保留一个项目')
+                return
+              }
+              this.contentEditForm.fixedTable.fixedTables.splice(index, 1)
+              handleDelete() // 执行删除逻辑
             }
-            this.contentEditForm.fixedTable.fixedTables.splice(index, 1)
-            handleDelete() // 执行删除逻辑
             break
           case '动态表表头':
             if (this.contentEditForm.dynamicTable.tableHeaders.length <= 1) {
@@ -2678,40 +2804,109 @@
       },
 
       // 上升
-      handleMoveUp(index, tableType) {
+      handleMoveUp(index, tableType, row) {
         if (tableType === '固定表') {
-          if (index > 0) {
-            const temp = this.contentEditForm.fixedTable.fixedTables[index]
-            this.contentEditForm.fixedTable.fixedTables.splice(index, 1)
-            this.contentEditForm.fixedTable.fixedTables.splice(
-              index - 1,
-              0,
-              temp
-            )
-            // 更新固定表行的序号
-            this.updateFixedTableOrderNumbers()
-          }
+          const fixedTableData = this.contentEditForm.fixedTable.fixedTables
+          const newFixedTableData = [...fixedTableData]
+          this.swamTableArr(newFixedTableData, row, true)
+          this.contentEditForm.fixedTable.fixedTables = newFixedTableData
         } else if (tableType === '动态表') {
-          if (index > 0) {
-            const temp = this.contentEditForm.dynamicTable.dynamicTables[index]
-            this.contentEditForm.dynamicTable.dynamicTables.splice(index, 1)
-            this.contentEditForm.dynamicTable.dynamicTables.splice(
-              index - 1,
-              0,
-              temp
-            )
-            // 更新动态表行的序号
-            this.updateDynamicTableOrderNumbers()
+          const dynamicTableData =
+            this.contentEditForm.dynamicTable.dynamicTables
+          const newDynamicTableData = [...dynamicTableData]
+          this.swamTableArr(newDynamicTableData, row, true)
+          this.contentEditForm.dynamicTable.dynamicTables = newDynamicTableData
+        } else {
+          const tableHeaders = this.contentEditForm.tableHeaders
+          const newTableHeaders = [...tableHeaders]
+          this.swamTableArr(newTableHeaders, row, true, true)
+          this.contentEditForm.tableHeaders = newTableHeaders
+          // if (index > 0) {
+          //   const temp = this.contentEditForm.tableHeaders[index]
+          //   this.contentEditForm.tableHeaders.splice(index, 1)
+          //   this.contentEditForm.tableHeaders.splice(index - 1, 0, temp)
+          //   // 更新表头的序号
+          //   this.updateTableHeadersOrderNumbers()
+          // }
+        }
+      },
+      // 下降
+      handleMoveDown(index, tableType, row) {
+        if (tableType === '固定表') {
+          const fixedTableData = this.contentEditForm.fixedTable.fixedTables
+          const newFixedTableData = [...fixedTableData]
+          this.swamTableArr(newFixedTableData, row, false)
+          this.contentEditForm.fixedTable.fixedTables = newFixedTableData
+        } else if (tableType === '动态表') {
+          const dynamicTableData =
+            this.contentEditForm.dynamicTable.dynamicTables
+          const newDynamicTableData = [...dynamicTableData]
+          this.swamTableArr(newDynamicTableData, row, false)
+          this.contentEditForm.dynamicTable.dynamicTables = newDynamicTableData
+        } else {
+          const tableHeaders = this.contentEditForm.tableHeaders
+          const newTableHeaders = [...tableHeaders]
+          this.swamTableArr(newTableHeaders, row, false)
+          this.contentEditForm.tableHeaders = newTableHeaders
+          // if (index < this.contentEditForm.tableHeaders.length - 1) {
+          //   const temp = this.contentEditForm.tableHeaders[index]
+          //   this.contentEditForm.tableHeaders.splice(index, 1)
+          //   this.contentEditForm.tableHeaders.splice(index + 1, 0, temp)
+          //   // 更新表头的序号
+          //   this.updateTableHeadersOrderNumbers()
+          // }
+        }
+      },
+
+      swamTableArr(arr, row, asc, isHeader) {
+        const isChild = row.isChild || row.isSubItem || false
+        if (isChild) {
+          // 子节点处理逻辑后续实现 parentid rowid
+          let child = arr.find((item) => item.rowid === row.parentid)
+          // const rowIndex = arr.indexOf(row);
+          // newFixedTableData[rowIndex]
+          this.doSwamTableArr(child.children, row, asc, isHeader)
+        } else {
+          // 创建数组副本以确保Vue能检测到变化
+          // 直接替换整个数组,确保Vue能检测到变化
+          this.doSwamTableArr(arr, row, asc, isHeader)
+        }
+      },
+
+      doSwamTableArr(arr, row, asc, isHeader) {
+        const rowIndex = arr.indexOf(row)
+        let swamIndex = 0
+        if (asc) {
+          // 正序
+          if (rowIndex < 1) {
+            return
           }
+          swamIndex = rowIndex - 1
         } else {
-          if (index > 0) {
-            const temp = this.contentEditForm.tableHeaders[index]
-            this.contentEditForm.tableHeaders.splice(index, 1)
-            this.contentEditForm.tableHeaders.splice(index - 1, 0, temp)
-            // 更新表头的序号
-            this.updateTableHeadersOrderNumbers()
+          // 倒序
+          if (rowIndex >= arr.length - 1) {
+            return
           }
+          swamIndex = rowIndex + 1
         }
+
+        const curr = arr[rowIndex]
+        const swam = arr[swamIndex]
+
+        // 交换orderNum
+        const tempOrderNum = curr.orderNum
+        curr.orderNum = swam.orderNum
+        swam.orderNum = tempOrderNum
+
+        if (row.isChild && !isHeader) {
+          let currIndex = curr.fixedValues['序号']
+          curr.fixedValues['序号'] = swam.fixedValues['序号']
+          swam.fixedValues['序号'] = currIndex
+        }
+
+        // 交换数组中的位置
+        arr[rowIndex] = swam
+        arr[swamIndex] = curr
       },
 
       // 启动/停用状态
@@ -2762,45 +2957,6 @@
         }
       },
 
-      // 下降
-      handleMoveDown(index, tableType) {
-        if (tableType === '固定表') {
-          if (index < this.contentEditForm.fixedTable.fixedTables.length - 1) {
-            const temp = this.contentEditForm.fixedTable.fixedTables[index]
-            this.contentEditForm.fixedTable.fixedTables.splice(index, 1)
-            this.contentEditForm.fixedTable.fixedTables.splice(
-              index + 1,
-              0,
-              temp
-            )
-            // 更新固定表行的序号
-            this.updateFixedTableOrderNumbers()
-          }
-        } else if (tableType === '动态表') {
-          if (
-            index <
-            this.contentEditForm.dynamicTable.dynamicTables.length - 1
-          ) {
-            const temp = this.contentEditForm.dynamicTable.dynamicTables[index]
-            this.contentEditForm.dynamicTable.dynamicTables.splice(index, 1)
-            this.contentEditForm.dynamicTable.dynamicTables.splice(
-              index + 1,
-              0,
-              temp
-            )
-            // 更新动态表行的序号
-            this.updateDynamicTableOrderNumbers()
-          }
-        } else {
-          if (index < this.contentEditForm.tableHeaders.length - 1) {
-            const temp = this.contentEditForm.tableHeaders[index]
-            this.contentEditForm.tableHeaders.splice(index, 1)
-            this.contentEditForm.tableHeaders.splice(index + 1, 0, temp)
-            // 更新表头的序号
-            this.updateTableHeadersOrderNumbers()
-          }
-        }
-      },
       // 更新固定表行序号
       updateFixedTableOrderNumbers() {
         this.contentEditForm.fixedTable.fixedTables.forEach((row, index) => {
@@ -3168,10 +3324,21 @@
         // 结果数组
         const result = []
 
-        // 遍历每一行数据
-        fixedTables.forEach((row, rowIndex) => {
+        // 递归处理树形结构中的所有节点
+        const processNode = (node, parentRowIndex = 0) => {
+          // 确保node和fixedValues存在
+          if (!node) {
+            console.warn('遇到空节点,跳过处理')
+            return
+          }
+
+          // 确保fixedValues属性存在,如果不存在则初始化为空对象
+          if (!node.fixedValues) {
+            node.fixedValues = {}
+          }
+
           // 为每个固定列创建一条记录
-          fixedTitles.forEach((title, colIndex) => {
+          fixedTitles.forEach((title) => {
             // 找到对应的表头信息
             const correspondingHeader = fixedHeaders.find(
               (header) => header.fieldName === title.rkey
@@ -3179,41 +3346,35 @@
 
             const newItem = {
               rkey: title.rkey,
-              rvalue: row.fixedValues ? row.fixedValues[title.rkey] || '' : '',
-              surveyTemplateId: row.surveyTemplateId,
-              versionId: row.versionId,
-              tabtype: row.tabtype,
-              rowIndex: rowIndex,
+              rvalue: node.fixedValues[title.rkey] || '',
+              surveyTemplateId: node.surveyTemplateId || this.surveyTemplateId,
+              versionId: node.versionId || this.versionId,
+              tabtype: node.tabtype || this.templateType,
               // 添加 headersId 字段(表头的id)
               headersId: correspondingHeader ? correspondingHeader.id : null,
               // 添加记录的id(itemlist中每条记录的id)
-              id: row.itemId || null,
+              id: node.itemId || null,
               // 添加父子关系字段
-              parentid: row.parentid || -1, // 父项ID,默认为-1表示无父项
-              isChild: row.isChild || false, // 是否为子项
+              parentid: node.parentid || -1, // 父项ID,默认为-1表示无父项
+              isChild: node.isChild || false, // 是否为子项
               // 添加 rowid 字段
-              rowid: row.rowid || null,
+              rowid: node.rowid || null,
               // 添加计算公式相关字段
-              calculationFormula: row.calculationFormula || null,
-              jsonstr: row.jsonstr || null,
-            }
-
-            // 只有非子项才添加序号
-            if (!row.isSubItem && row.orderNum) {
-              newItem.orderNum =
-                typeof row.orderNum === 'number'
-                  ? row.orderNum
-                  : parseInt(row.orderNum, 10) || 0
+              calculationFormula: node.calculationFormula || null,
+              jsonstr: node.jsonstr || null,
+              orderNum:
+                typeof node.orderNum === 'number'
+                  ? node.orderNum
+                  : parseInt(node.orderNum, 10) || 0,
             }
-
             // 添加其他固定表特有的字段
-            if (!row.isSubItem) {
-              newItem.cellCode = row.cellCode || ''
-              newItem.unit = row.unit || ''
+            if (!node.isSubItem) {
+              newItem.cellCode = node.cellCode || ''
+              newItem.unit = node.unit || ''
             }
 
             // 添加其他可能需要的字段,但排除特定字段
-            Object.keys(row).forEach((key) => {
+            Object.keys(node).forEach((key) => {
               if (
                 !(key in newItem) &&
                 key !== 'fixedValues' &&
@@ -3224,14 +3385,77 @@
                 key !== 'isSubItem' &&
                 key !== 'rowid' &&
                 key !== 'jsonstr' &&
-                key !== 'calculationFormula'
+                key !== 'calculationFormula' &&
+                key !== 'children' // 排除children字段
               ) {
-                newItem[key] = row[key]
+                newItem[key] = node[key]
               }
             })
 
             result.push(newItem)
           })
+
+          // 递归处理子节点
+          if (node.children && node.children.length > 0) {
+            node.children.forEach((childNode) => {
+              processNode(childNode)
+            })
+          }
+        }
+
+        // 遍历所有顶级节点
+        fixedTables.forEach((row) => {
+          processNode(row)
+        })
+        // 重新给子节点赋值orderNum 保证所有元素orderNum字段不重复
+        // 为所有子节点分配唯一的orderNum,但保持父节点的orderNum不变
+        // 计算所有已存在的orderNum中的最大值
+        let maxExistingOrderNum = 0
+
+        // 首先遍历结果数组找出当前最大的orderNum
+        result.forEach((item) => {
+          const orderNum =
+            typeof item.orderNum === 'number'
+              ? item.orderNum
+              : parseInt(item.orderNum, 10) || 0
+          if (orderNum > maxExistingOrderNum) {
+            maxExistingOrderNum = orderNum
+          }
+        })
+
+        // 子节点orderNum从当前最大orderNum + 1开始
+        let childOrderNumCounter = maxExistingOrderNum + 1
+
+        // 创建一个映射表,用于记录每个子节点对应的新orderNum
+        const childOrderMap = new Map()
+
+        // 第一次遍历:为每个子节点分配新的orderNum并存储映射关系
+        function assignChildOrderNums(nodes) {
+          nodes.forEach((node) => {
+            if (node.isChild || node.isSubItem) {
+              // 为每个子节点分配唯一的orderNum
+              childOrderMap.set(node.id || node.rowid, childOrderNumCounter++)
+            }
+            // 递归处理子节点
+            if (node.children && node.children.length > 0) {
+              assignChildOrderNums(node.children)
+            }
+          })
+        }
+
+        // 第二次遍历:更新结果数组中的orderNum
+        assignChildOrderNums(fixedTables)
+
+        // 应用新的orderNum到结果数组
+        result.forEach((item) => {
+          // 只更新子节点的orderNum
+          if (item.isChild || item.isSubItem) {
+            const newOrderNum =
+              childOrderMap.get(item.id) || childOrderMap.get(item.rowid)
+            if (newOrderNum) {
+              item.orderNum = newOrderNum
+            }
+          }
         })
 
         return result
@@ -3248,10 +3472,21 @@
         // 结果数组
         const result = []
 
-        // 遍历每一行数据
-        dynamicTables.forEach((row, rowIndex) => {
+        // 递归处理树形结构中的所有节点
+        const processNode = (node) => {
+          // 确保node和dynamicValues存在
+          if (!node) {
+            console.warn('遇到空节点,跳过处理')
+            return
+          }
+
+          // 确保dynamicValues属性存在,如果不存在则初始化为空对象
+          if (!node.dynamicValues) {
+            node.dynamicValues = {}
+          }
+
           // 为每个固定列创建一条记录
-          dynamicTitles.forEach((title, colIndex) => {
+          dynamicTitles.forEach((title) => {
             // 找到对应的表头信息
             const correspondingHeader = dynamicHeaders.find(
               (header) => header.fieldName === title.rkey
@@ -3259,37 +3494,30 @@
 
             const newItem = {
               rkey: title.rkey,
-              rvalue: row.dynamicValues
-                ? row.dynamicValues[title.rkey] || ''
-                : '',
-              surveyTemplateId: row.surveyTemplateId,
-              versionId: row.versionId,
-              tabtype: row.tabtype,
-              rowIndex: rowIndex,
+              rvalue: node.dynamicValues[title.rkey] || '',
+              surveyTemplateId: node.surveyTemplateId,
+              versionId: node.versionId,
+              tabtype: node.tabtype,
               // 添加 headersId 字段(表头的id)
               headersId: correspondingHeader ? correspondingHeader.id : null,
               // 添加记录的id(itemlist中每条记录的id)
-              id: row.itemId || null,
+              id: node.itemId || null,
               // 添加父子关系字段
-              parentid: row.parentid || -1, // 父项ID,默认为-1表示无父项
-              isChild: row.isChild || false, // 是否为子项
+              parentid: node.parentid || -1, // 父项ID,默认为-1表示无父项
+              isChild: node.isChild || false, // 是否为子项
               // 添加 rowid 字段
-              rowid: row.rowid || null,
+              rowid: node.rowid || null,
               // 添加计算公式相关字段
-              calculationFormula: row.calculationFormula || null,
-              jsonstr: row.jsonstr || null,
-            }
-
-            // 只有非子项才添加序号
-            if (!row.isSubItem && row.orderNum) {
-              newItem.orderNum =
-                typeof row.orderNum === 'number'
-                  ? row.orderNum
-                  : parseInt(row.orderNum, 10) || 0
+              calculationFormula: node.calculationFormula || null,
+              jsonstr: node.jsonstr || null,
+              orderNum:
+                typeof node.orderNum === 'number'
+                  ? node.orderNum
+                  : parseInt(node.orderNum, 10) || 0,
             }
 
             // 添加其他可能需要的字段,但排除特定字段
-            Object.keys(row).forEach((key) => {
+            Object.keys(node).forEach((key) => {
               if (
                 !(key in newItem) &&
                 key !== 'dynamicValues' &&
@@ -3300,14 +3528,27 @@
                 key !== 'isSubItem' &&
                 key !== 'rowid' &&
                 key !== 'jsonstr' &&
-                key !== 'calculationFormula'
+                key !== 'calculationFormula' &&
+                key !== 'children' // 排除children字段
               ) {
-                newItem[key] = row[key]
+                newItem[key] = node[key]
               }
             })
 
             result.push(newItem)
           })
+
+          // 递归处理子节点
+          if (node.children && node.children.length > 0) {
+            node.children.forEach((childNode) => {
+              processNode(childNode)
+            })
+          }
+        }
+
+        // 遍历所有顶级节点
+        dynamicTables.forEach((row) => {
+          processNode(row)
         })
 
         return result
@@ -3413,6 +3654,7 @@
 
         const itemList = responseData.value.itemlist
         const allRows = []
+        const rowMap = new Map()
 
         // 清空现有数据
         this.contentEditForm.fixedTable.fixedTables = []
@@ -3438,6 +3680,7 @@
             isSubItem: isSubItem,
             rowid: item.rowid || this.generateUUID(),
             jsonstr: item.jsonstr || null,
+            children: [], // 添加children数组用于树形结构
           }
 
           // 确保orderNum是数字类型
@@ -3451,55 +3694,40 @@
           })
 
           allRows.push(newRow)
+          // 构建rowMap用于快速查找
+          if (newRow.rowid) rowMap.set(String(newRow.rowid), newRow)
+          if (newRow.itemId) rowMap.set(String(newRow.itemId), newRow)
         })
 
-        // 按父子关系排序:父项在前,子项在对应的父项后面
-        allRows.sort((a, b) => {
-          // 先按orderNum排序父项
-          if (a.isChild && !b.isChild) {
-            // 如果a是子项,b是父项,需要检查a的父项是否在b之后
-            const parentOfA = allRows.find(
-              (item) => item.rowid === a.parentid || item.itemId === a.parentid
-            )
-            if (parentOfA && parentOfA.orderNum > b.orderNum) {
-              return 1
-            }
-            return -1
-          }
-          if (!a.isChild && b.isChild) {
-            // 如果a是父项,b是子项,需要检查b的父项是否在a之前
-            const parentOfB = allRows.find(
-              (item) => item.rowid === b.parentid || item.itemId === b.parentid
-            )
-            if (parentOfB && parentOfB.orderNum < a.orderNum) {
-              return -1
+        // 构建树形结构
+        const treeData = []
+        const parentItems = allRows.filter((item) => !item.isChild)
+
+        // 父级按orderNum正序排序
+        parentItems.sort((a, b) => (a.orderNum || 0) - (b.orderNum || 0))
+
+        // 将子项添加到对应的父项的children中
+        allRows.forEach((item) => {
+          if (item.isChild) {
+            const parentId = String(item.parentid)
+            const parent = rowMap.get(parentId)
+            if (parent) {
+              parent.children.push(item)
             }
-            return 1
           }
-
-          // 如果都是父项或都是子项,按orderNum排序
-          return (a.orderNum || 0) - (b.orderNum || 0)
         })
 
-        // 重新排序,确保子项紧跟在其对应的父项后面
-        const sortedArray = []
-        const parentItems = allRows.filter((item) => !item.isChild)
-        const childItems = allRows.filter((item) => item.isChild)
-
+        // 对子项进行排序
         parentItems.forEach((parent) => {
-          sortedArray.push(parent)
-          // 找到并添加该父项的所有子项
-          const relatedChildren = childItems.filter(
-            (child) =>
-              child.parentid === parent.rowid ||
-              child.parentid === parent.itemId
+          parent.children.sort(
+            (a, b) =>
+              (a.fixedValues['序号'] || 0) - (b.fixedValues['序号'] || 0)
           )
-          // 子项按orderNum排序
-          relatedChildren.sort((a, b) => (a.orderNum || 0) - (b.orderNum || 0))
-          sortedArray.push(...relatedChildren)
+          treeData.push(parent)
         })
 
-        this.contentEditForm.fixedTable.fixedTables = sortedArray
+        this.contentEditForm.fixedTable.fixedTables = treeData
+        console.log('树形结构数据:', treeData)
       },
 
       /**
@@ -3530,8 +3758,8 @@
         }
 
         const itemList = responseData.value.itemlist
-
         const allRows = []
+        const rowMap = new Map()
 
         // 清空现有数据
         this.contentEditForm.dynamicTable.dynamicTables = []
@@ -3553,6 +3781,7 @@
             isSubItem: isSubItem,
             rowid: item.rowid || this.generateUUID(),
             jsonstr: item.jsonstr || null,
+            children: [], // 添加children数组用于树形结构
           }
 
           // 确保orderNum是数字类型
@@ -3574,94 +3803,41 @@
           })
 
           allRows.push(newRow)
+          // 构建rowMap用于快速查找
+          if (newRow.rowid) rowMap.set(String(newRow.rowid), newRow)
+          if (newRow.itemId) rowMap.set(String(newRow.itemId), newRow)
         })
 
-        // 按父子关系排序:父项在前,子项在对应的父项后面
-        // 1. 先创建一个映射表,方便通过ID查找父项
-        const rowMap = new Map()
-        const sortedArray = []
-        const addedItems = new Set()
-
-        // 深拷贝原始数据并过滤掉重复项
-        const uniqueRows = allRows.reduce((acc, current) => {
-          const isDuplicate = acc.some(
-            (row) =>
-              (row.rowid && current.rowid && row.rowid === current.rowid) ||
-              (row.itemId && current.itemId && row.itemId === current.itemId)
-          )
-          if (!isDuplicate) {
-            acc.push(JSON.parse(JSON.stringify(current)))
-          }
-          return acc
-        }, [])
-
-        // 填充映射表
-        uniqueRows.forEach((row) => {
-          if (row.rowid) rowMap.set(String(row.rowid), row)
-          if (row.itemId) rowMap.set(String(row.itemId), row)
-        })
-
-        // 先按orderNum排序所有父项
-        const parentItems = uniqueRows.filter((item) => !item.isChild)
-        parentItems.sort(
-          (a, b) => (Number(a.orderNum) || 0) - (Number(b.orderNum) || 0)
-        )
-
-        // 递归添加父项及其子项的函数
-        const addItemWithChildren = (item) => {
-          // 确保项目ID唯一
-          const itemIdKey = String(
-            item.rowid || item.itemId || `temp_${Math.random()}`
-          )
-
-          // 如果已经添加过,则跳过
-          if (addedItems.has(itemIdKey)) return
+        // 构建树形结构
+        const treeData = []
+        const parentItems = allRows.filter((item) => !item.isChild)
 
-          // 添加当前项目
-          sortedArray.push(item)
-          addedItems.add(itemIdKey)
+        // 父级按orderNum正序排序
+        parentItems.sort((a, b) => (a.orderNum || 0) - (b.orderNum || 0))
 
-          // 找到并添加所有子项
-          const children = uniqueRows.filter((child) => {
-            if (child.isChild) {
-              const childParentId = String(child.parentid)
-              return (
-                childParentId === String(item.rowid) ||
-                childParentId === String(item.itemId)
-              )
+        // 将子项添加到对应的父项的children中
+        allRows.forEach((item) => {
+          if (item.isChild) {
+            const parentId = String(item.parentid)
+            const parent = rowMap.get(parentId)
+            if (parent) {
+              parent.children.push(item)
             }
-            return false
-          })
-
-          // 子项按orderNum排序
-          children.sort(
-            (a, b) => (Number(a.orderNum) || 0) - (Number(b.orderNum) || 0)
-          )
-
-          // 添加所有子项
-          children.forEach((child) => addItemWithChildren(child))
-        }
-
-        // 遍历所有父项,添加父项及其子项
-        parentItems.forEach((parent) => addItemWithChildren(parent))
-
-        // 添加剩余的没有被添加的项目(应该很少,但作为兜底)
-        uniqueRows.forEach((row) => {
-          const itemIdKey = String(
-            row.rowid || row.itemId || `temp_${Math.random()}`
-          )
-          if (!addedItems.has(itemIdKey)) {
-            sortedArray.push(row)
-            addedItems.add(itemIdKey)
           }
         })
 
-        // 最后,重新计算显示序号,确保序号连续且正确
-        sortedArray.forEach((item, index) => {
-          item.orderText = String(index + 1)
+        // 对子项进行排序
+        parentItems.forEach((parent) => {
+          parent.children.sort(
+            (a, b) =>
+              (Number(a.dynamicValues['序号']) || 0) -
+              (Number(b.dynamicValues['序号']) || 0)
+          )
+          treeData.push(parent)
         })
 
-        this.contentEditForm.dynamicTable.dynamicTables = sortedArray
+        this.contentEditForm.dynamicTable.dynamicTables = treeData
+        console.log('树形结构数据:', treeData)
       },
       //分割字符串
       stringToObjects(str) {

+ 12 - 12
src/views/costAudit/baseInfo/statistics/comprehensiveQuery.vue

@@ -41,8 +41,14 @@
           ></el-date-picker>
         </el-form-item>
         <el-form-item>
-          <el-button type="primary" @click="handleQuery">查询</el-button>
-          <el-button style="margin-left: 10px" @click="handleReset">
+          <el-button type="primary" icon="el-icon-search" @click="handleQuery">
+            查询
+          </el-button>
+          <el-button
+            icon="el-icon-refresh"
+            style="margin-left: 10px"
+            @click="handleReset"
+          >
             重置
           </el-button>
         </el-form-item>
@@ -62,9 +68,9 @@
         @pagination-change="handlePaginationChange"
       >
         <!-- 项目名称链接 -->
-        <template #projectName="{ row }">
+        <!-- <template #projectName="{ row }">
           <a href="javascript:;" class="link-text">{{ row.projectName }}</a>
-        </template>
+        </template> -->
 
         <!-- 下载按钮组 -->
         <template #download="{ row }">
@@ -166,7 +172,7 @@
           {
             prop: 'projectName',
             label: '成本监审项目名称',
-            slotName: 'projectName',
+            // slotName: 'projectName',
           },
           {
             prop: 'auditObject',
@@ -247,14 +253,8 @@
 </script>
 
 <style lang="scss" scoped>
+  @import '@/styles/costAudit.scss';
   .comprehensive-query {
     padding: 20px;
-    .link-text {
-      color: #409eff;
-      text-decoration: none;
-      &:hover {
-        text-decoration: underline;
-      }
-    }
   }
 </style>

+ 23 - 29
src/views/costAudit/baseInfo/statistics/historyAnalysis.vue

@@ -37,8 +37,12 @@
           ></el-date-picker>
         </el-form-item>
         <el-form-item>
-          <el-button type="primary" @click="handleQuery">查询</el-button>
-          <el-button @click="handleReset">重置</el-button>
+          <el-button type="primary" icon="el-icon-search" @click="handleQuery">
+            查询
+          </el-button>
+          <el-button icon="el-icon-refresh" @click="handleReset">
+            重置
+          </el-button>
         </el-form-item>
       </el-form>
     </div>
@@ -50,6 +54,7 @@
         <div class="list-title">请选择数据项后查看分析:</div>
         <el-tree
           v-model="selectedIndicators"
+          class="indicator-tree"
           :data="indicatorData"
           show-checkbox
           node-key="id"
@@ -172,7 +177,7 @@
             },
           },
           legend: {
-            data: ['预测', '指纹'],
+            data: ['指标1', '指标2'],
             bottom: 0,
           },
           grid: {
@@ -367,54 +372,43 @@
 <style scoped lang="scss">
   .history-analysis-container {
     padding: 20px;
-    background-color: #f5f7fa;
-    min-height: 100vh;
-  }
-
-  .search-area {
-    background-color: #fff;
-    padding: 20px;
-    border-radius: 8px;
-    margin-bottom: 20px;
-    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+    height: calc(100vh - 40px); /* 减去padding,基于视口高度 */
   }
 
   .main-content {
     display: flex;
     gap: 20px;
+    height: 100%;
   }
 
   .indicator-list {
     width: 300px;
-    background-color: #fff;
-    padding: 20px;
-    border-radius: 8px;
-    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+    height: 100%;
+  }
+  .indicator-tree {
+    border: 1px solid #e8e8e8;
+    height: 100%;
   }
 
   .list-title {
     font-size: 16px;
-    font-weight: 600;
-    margin-bottom: 15px;
+    margin-bottom: 10px;
     color: #333;
   }
 
   .chart-area {
     flex: 1;
-    background-color: #fff;
+  }
+  .charts-wrapper {
+    border: 1px solid #e8e8e8;
     padding: 20px;
-    border-radius: 8px;
-    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
   }
-
   .chart-title {
-    font-size: 18px;
-    font-weight: 600;
-    margin-bottom: 20px;
+    width: 80px;
+    text-align: center;
     color: #fff;
-    padding: 10px 20px;
-    background-color: #9254de;
-    border-radius: 4px;
+    padding: 6px 10px;
+    background-color: #8400ff;
   }
 
   .charts-wrapper {

+ 563 - 149
src/views/costAudit/baseInfo/statistics/industryAnalysis.vue

@@ -1,86 +1,193 @@
 <template>
   <div class="industry-analysis-container">
-    <!-- 搜索区域 -->
-    <div class="search-section">
-      <el-form :inline="true" :model="searchForm" class="search-form">
-        <el-form-item label="项目名称:">
-          <el-select
-            v-model="searchForm.projectName"
-            placeholder="请选择"
-            style="width: 200px"
-          >
-            <el-option label="请选择" value=""></el-option>
-            <!-- 这里可以根据实际数据动态加载选项 -->
-          </el-select>
-        </el-form-item>
-
-        <el-form-item label="监审对象:">
-          <el-select
-            v-model="searchForm.auditObject"
-            placeholder="请选择"
-            style="width: 200px"
-          >
-            <el-option label="请选择" value=""></el-option>
-            <!-- 这里可以根据实际数据动态加载选项 -->
-          </el-select>
-        </el-form-item>
-
-        <el-form-item label="计划年度:">
-          <el-date-picker
-            v-model="searchForm.startYear"
-            type="year"
-            placeholder="开始年份"
-            format="yyyy年"
-            value-format="yyyy"
-            style="width: 120px; margin-right: 10px"
-          ></el-date-picker>
-          <span style="margin: 0 5px">~</span>
-          <el-date-picker
-            v-model="searchForm.endYear"
-            type="year"
-            placeholder="结束年份"
-            format="yyyy年"
-            value-format="yyyy"
-            style="width: 120px"
-          ></el-date-picker>
-        </el-form-item>
-
-        <el-form-item>
-          <el-button type="primary" @click="handleQuery">查询</el-button>
-          <el-button style="margin-left: 10px" @click="handleReset">
-            重置
-          </el-button>
-        </el-form-item>
-      </el-form>
-    </div>
+    <!-- 主体内容区域 - 双栏对比布局 -->
+    <div class="comparison-container">
+      <!-- 左侧面板 -->
+      <div class="comparison-panel left-panel">
+        <!-- 左侧搜索区域 -->
+        <div class="search-section">
+          <el-form :inline="true" :model="leftSearchForm" class="search-form">
+            <el-form-item label="项目名称:">
+              <el-select
+                v-model="leftSearchForm.projectName"
+                placeholder="请选择"
+                style="width: 200px"
+              >
+                <el-option label="请选择" value=""></el-option>
+                <!-- 这里可以根据实际数据动态加载选项 -->
+              </el-select>
+            </el-form-item>
+
+            <el-form-item label="监审对象:">
+              <el-select
+                v-model="leftSearchForm.auditObject"
+                placeholder="请选择"
+                style="width: 200px"
+              >
+                <el-option label="请选择" value=""></el-option>
+                <!-- 这里可以根据实际数据动态加载选项 -->
+              </el-select>
+            </el-form-item>
+
+            <el-form-item label="计划年度:">
+              <el-date-picker
+                v-model="leftSearchForm.startYear"
+                type="year"
+                placeholder="开始年份"
+                format="yyyy年"
+                value-format="yyyy"
+                style="width: 120px; margin-right: 10px"
+              ></el-date-picker>
+              <span style="margin: 0 5px">~</span>
+              <el-date-picker
+                v-model="leftSearchForm.endYear"
+                type="year"
+                placeholder="结束年份"
+                format="yyyy年"
+                value-format="yyyy"
+                style="width: 120px"
+              ></el-date-picker>
+            </el-form-item>
+
+            <el-form-item>
+              <el-button type="primary" @click="handleLeftQuery">
+                查询
+              </el-button>
+              <el-button style="margin-left: 10px" @click="handleLeftReset">
+                重置
+              </el-button>
+            </el-form-item>
+          </el-form>
+        </div>
+
+        <!-- 左侧数据项选择和图表 -->
+        <div class="panel-content">
+          <!-- 左侧数据项选择 -->
+          <div class="data-selector">
+            <div class="panel-title">请选择数据项后查看分析:</div>
+            <el-tree
+              ref="leftDataTree"
+              :data="dataItems"
+              show-checkbox
+              node-key="id"
+              :props="treeProps"
+              :default-checked-keys="['1-6']"
+              :default-expanded-keys="['1', '2']"
+              @check="handleLeftDataItemCheck"
+            ></el-tree>
+          </div>
 
-    <!-- 主体内容区域 -->
-    <div class="main-content">
-      <!-- 左侧数据项选择 -->
-      <div class="left-panel">
-        <div class="panel-title">请选择数据项后查看分析:</div>
-        <el-tree
-          ref="dataTree"
-          :data="dataItems"
-          show-checkbox
-          node-key="id"
-          :props="treeProps"
-          @check="handleDataItemCheck"
-        ></el-tree>
+          <!-- 左侧图表展示 -->
+          <div class="chart-section">
+            <!-- 指标趋势分析 -->
+            <div class="chart-container">
+              <h3 class="chart-title">指标趋势分析</h3>
+              <div id="leftTrendChart" class="chart"></div>
+            </div>
+
+            <!-- 指标占比分析 -->
+            <div class="chart-container">
+              <h3 class="chart-title">指标占比分析</h3>
+              <div id="leftProportionChart" class="chart"></div>
+            </div>
+          </div>
+        </div>
       </div>
 
-      <!-- 右侧图表展示 -->
-      <div class="right-panel">
-        <!-- 指标趋势分析 -->
-        <div class="chart-container">
-          <h3 class="chart-title">指标趋势分析</h3>
-          <div id="trendChart" class="chart"></div>
+      <!-- VS对比图标 -->
+      <div class="vs-container">
+        <div class="vs-icon">VS</div>
+      </div>
+
+      <!-- 右侧面板 -->
+      <div class="comparison-panel right-panel">
+        <!-- 右侧搜索区域 -->
+        <div class="search-section">
+          <el-form :inline="true" :model="rightSearchForm" class="search-form">
+            <el-form-item label="项目名称:">
+              <el-select
+                v-model="rightSearchForm.projectName"
+                placeholder="请选择"
+                style="width: 200px"
+              >
+                <el-option label="请选择" value=""></el-option>
+                <!-- 这里可以根据实际数据动态加载选项 -->
+              </el-select>
+            </el-form-item>
+
+            <el-form-item label="监审对象:">
+              <el-select
+                v-model="rightSearchForm.auditObject"
+                placeholder="请选择"
+                style="width: 200px"
+              >
+                <el-option label="请选择" value=""></el-option>
+                <!-- 这里可以根据实际数据动态加载选项 -->
+              </el-select>
+            </el-form-item>
+
+            <el-form-item label="计划年度:">
+              <el-date-picker
+                v-model="rightSearchForm.startYear"
+                type="year"
+                placeholder="开始年份"
+                format="yyyy年"
+                value-format="yyyy"
+                style="width: 120px; margin-right: 10px"
+              ></el-date-picker>
+              <span style="margin: 0 5px">~</span>
+              <el-date-picker
+                v-model="rightSearchForm.endYear"
+                type="year"
+                placeholder="结束年份"
+                format="yyyy年"
+                value-format="yyyy"
+                style="width: 120px"
+              ></el-date-picker>
+            </el-form-item>
+
+            <el-form-item>
+              <el-button type="primary" @click="handleRightQuery">
+                查询
+              </el-button>
+              <el-button style="margin-left: 10px" @click="handleRightReset">
+                重置
+              </el-button>
+            </el-form-item>
+          </el-form>
         </div>
 
-        <!-- 指标占比分析 -->
-        <div class="chart-container">
-          <h3 class="chart-title">指标占比分析</h3>
-          <div id="proportionChart" class="chart"></div>
+        <!-- 右侧数据项选择和图表 -->
+        <div class="panel-content">
+          <!-- 右侧数据项选择 -->
+          <div class="data-selector">
+            <div class="panel-title">请选择数据项后查看分析:</div>
+            <el-tree
+              ref="rightDataTree"
+              :data="dataItems"
+              show-checkbox
+              node-key="id"
+              :props="treeProps"
+              :default-checked-keys="['1-6']"
+              :default-expanded-keys="['1', '2']"
+              @check="handleRightDataItemCheck"
+            ></el-tree>
+          </div>
+
+          <!-- 右侧图表展示 -->
+          <div class="chart-section">
+            <!-- 指标趋势分析 -->
+            <div class="chart-container">
+              <h3 class="chart-title">指标趋势分析</h3>
+              <div id="rightTrendChart" class="chart"></div>
+            </div>
+
+            <!-- 指标占比分析 -->
+            <div class="chart-container">
+              <h3 class="chart-title">指标占比分析</h3>
+              <div id="rightProportionChart" class="chart"></div>
+            </div>
+          </div>
         </div>
       </div>
     </div>
@@ -94,8 +201,15 @@
     name: 'IndustryAnalysis',
     data() {
       return {
-        // 搜索表单数据
-        searchForm: {
+        // 左侧搜索表单数据
+        leftSearchForm: {
+          projectName: '',
+          auditObject: '',
+          startYear: '2024',
+          endYear: '2025',
+        },
+        // 右侧搜索表单数据
+        rightSearchForm: {
           projectName: '',
           auditObject: '',
           startYear: '2024',
@@ -141,16 +255,32 @@
           children: 'children',
           label: 'label',
         },
-        // 选中的数据项
-        selectedItems: [],
-        // 图表实例
-        trendChart: null,
-        proportionChart: null,
-        // 图表数据
-        trendData: {
+        // 左侧选中的数据项
+        leftSelectedItems: [{ id: '1-6', label: '其他人员支出' }],
+        // 右侧选中的数据项
+        rightSelectedItems: [{ id: '1-6', label: '其他人员支出' }],
+        // 左侧图表实例
+        leftTrendChart: null,
+        leftProportionChart: null,
+        // 右侧图表实例
+        rightTrendChart: null,
+        rightProportionChart: null,
+        // 左侧图表数据
+        leftTrendData: {
           '1-6': [7, 7, 9.5], // 其他人员支出 2022-2024年数据
         },
-        proportionData: {
+        leftProportionData: {
+          '1-1': 12.43, // 基本工资占比
+          '1-2': 12.26, // 津贴占比
+          '1-3': 16.87, // 奖金占比
+          '1-4': 25.75, // 福利费占比
+          '1-6': 32.68, // 其他人员支出占比
+        },
+        // 右侧图表数据
+        rightTrendData: {
+          '1-6': [7, 7, 9.5], // 其他人员支出 2022-2024年数据
+        },
+        rightProportionData: {
           '1-1': 12.43, // 基本工资占比
           '1-2': 12.26, // 津贴占比
           '1-3': 16.87, // 奖金占比
@@ -162,16 +292,31 @@
     mounted() {
       // 初始化图表
       this.initCharts()
+      // 设置默认选中状态
+      setTimeout(() => {
+        if (this.$refs.leftDataTree) {
+          this.$refs.leftDataTree.setCheckedKeys(['1-6'])
+        }
+        if (this.$refs.rightDataTree) {
+          this.$refs.rightDataTree.setCheckedKeys(['1-6'])
+        }
+      }, 100)
       // 监听窗口大小变化,调整图表大小
       window.addEventListener('resize', this.handleResize)
     },
     beforeDestroy() {
       // 清理图表实例
-      if (this.trendChart) {
-        this.trendChart.dispose()
+      if (this.leftTrendChart) {
+        this.leftTrendChart.dispose()
       }
-      if (this.proportionChart) {
-        this.proportionChart.dispose()
+      if (this.leftProportionChart) {
+        this.leftProportionChart.dispose()
+      }
+      if (this.rightTrendChart) {
+        this.rightTrendChart.dispose()
+      }
+      if (this.rightProportionChart) {
+        this.rightProportionChart.dispose()
       }
       // 移除事件监听
       window.removeEventListener('resize', this.handleResize)
@@ -179,20 +324,91 @@
     methods: {
       // 初始化图表
       initCharts() {
-        // 初始化趋势图
-        this.trendChart = echarts.init(document.getElementById('trendChart'))
-        // 初始化占比图
-        this.proportionChart = echarts.init(
-          document.getElementById('proportionChart')
+        // 初始化左侧图表
+        this.leftTrendChart = echarts.init(
+          document.getElementById('leftTrendChart')
+        )
+        this.leftProportionChart = echarts.init(
+          document.getElementById('leftProportionChart')
+        )
+
+        // 初始化右侧图表
+        this.rightTrendChart = echarts.init(
+          document.getElementById('rightTrendChart')
+        )
+        this.rightProportionChart = echarts.init(
+          document.getElementById('rightProportionChart')
         )
 
         // 设置默认图表数据
-        this.updateTrendChart()
-        this.updateProportionChart()
+        this.updateLeftTrendChart()
+        this.updateLeftProportionChart()
+        this.updateRightTrendChart()
+        this.updateRightProportionChart()
+      },
+
+      // 更新左侧趋势图
+      updateLeftTrendChart() {
+        const option = {
+          tooltip: {
+            trigger: 'axis',
+            formatter: '{b}<br/>{a}: {c}',
+          },
+          grid: {
+            left: '3%',
+            right: '4%',
+            bottom: '3%',
+            containLabel: true,
+          },
+          xAxis: {
+            type: 'category',
+            boundaryGap: false,
+            data: ['2022年', '2023年', '2024年'],
+            axisLine: {
+              lineStyle: {
+                color: '#333',
+              },
+            },
+          },
+          yAxis: {
+            type: 'value',
+            min: 6.5,
+            max: 10,
+            interval: 0.5,
+            axisLine: {
+              lineStyle: {
+                color: '#333',
+              },
+            },
+            axisTick: {
+              show: false,
+            },
+          },
+          series: [
+            {
+              name: '其他人员支出',
+              type: 'line',
+              data: [7, 7, 9.5],
+              lineStyle: {
+                width: 2,
+                color: '#37A2DA',
+              },
+              symbol: 'circle',
+              symbolSize: 8,
+              itemStyle: {
+                color: '#37A2DA',
+              },
+              emphasis: {
+                focus: 'series',
+              },
+            },
+          ],
+        }
+        this.leftTrendChart.setOption(option)
       },
 
-      // 更新趋势图
-      updateTrendChart() {
+      // 更新右侧趋势图
+      updateRightTrendChart() {
         const option = {
           tooltip: {
             trigger: 'axis',
@@ -224,6 +440,9 @@
                 color: '#333',
               },
             },
+            axisTick: {
+              show: false,
+            },
           },
           series: [
             {
@@ -245,11 +464,84 @@
             },
           ],
         }
-        this.trendChart.setOption(option)
+        this.rightTrendChart.setOption(option)
+      },
+
+      // 更新左侧占比图
+      updateLeftProportionChart() {
+        const option = {
+          tooltip: {
+            trigger: 'item',
+            formatter: '{a} <br/>{b}: {c}%',
+          },
+          legend: {
+            orient: 'horizontal',
+            bottom: 10,
+            left: 'center',
+            data: ['基本工资', '津贴', '奖金', '福利费', '其他人员支出'],
+            formatter: function (name) {
+              const percentMap = {
+                基本工资: '12.43%',
+                津贴: '12.26%',
+                奖金: '16.87%',
+                福利费: '25.75%',
+                其他人员支出: '32.68%',
+              }
+              return `${name}: ${percentMap[name] || ''}`
+            },
+          },
+          series: [
+            {
+              name: '指标占比',
+              type: 'pie',
+              radius: ['40%', '70%'],
+              avoidLabelOverlap: false,
+              itemStyle: {
+                borderRadius: 10,
+                borderColor: '#fff',
+                borderWidth: 2,
+              },
+              label: {
+                show: false,
+                position: 'center',
+              },
+              emphasis: {
+                label: {
+                  show: true,
+                  fontSize: 20,
+                  fontWeight: 'bold',
+                },
+              },
+              labelLine: {
+                show: false,
+              },
+              data: [
+                {
+                  value: 12.43,
+                  name: '基本工资',
+                  itemStyle: { color: '#37A2DA' },
+                },
+                { value: 12.26, name: '津贴', itemStyle: { color: '#5470C6' } },
+                { value: 16.87, name: '奖金', itemStyle: { color: '#91CC75' } },
+                {
+                  value: 25.75,
+                  name: '福利费',
+                  itemStyle: { color: '#FAC858' },
+                },
+                {
+                  value: 32.68,
+                  name: '其他人员支出',
+                  itemStyle: { color: '#EE6666' },
+                },
+              ],
+            },
+          ],
+        }
+        this.leftProportionChart.setOption(option)
       },
 
-      // 更新占比图
-      updateProportionChart() {
+      // 更新右侧占比图
+      updateRightProportionChart() {
         const option = {
           tooltip: {
             trigger: 'item',
@@ -278,9 +570,9 @@
               radius: ['40%', '70%'],
               avoidLabelOverlap: false,
               itemStyle: {
-                borderRadius: 0,
+                borderRadius: 10,
                 borderColor: '#fff',
-                borderWidth: 0,
+                borderWidth: 2,
               },
               label: {
                 show: false,
@@ -318,60 +610,111 @@
             },
           ],
         }
-        this.proportionChart.setOption(option)
+        this.rightProportionChart.setOption(option)
+      },
+
+      // 处理左侧数据项选择
+      handleLeftDataItemCheck() {
+        // 获取选中的节点
+        this.leftSelectedItems = this.$refs.leftDataTree.getCheckedNodes()
+        // 更新左侧图表
+        this.updateLeftChartsBySelection()
       },
 
-      // 处理数据项选择
-      handleDataItemCheck() {
+      // 处理右侧数据项选择
+      handleRightDataItemCheck() {
         // 获取选中的节点
-        this.selectedItems = this.$refs.dataTree.getCheckedNodes()
-        // 可以在这里根据选中的数据项更新图表数据
-        this.updateChartsBySelection()
+        this.rightSelectedItems = this.$refs.rightDataTree.getCheckedNodes()
+        // 更新右侧图表
+        this.updateRightChartsBySelection()
       },
 
-      // 根据选中的数据项更新图表
-      updateChartsBySelection() {
+      // 根据选中的数据项更新左侧图表
+      updateLeftChartsBySelection() {
         // 这里可以根据选中的数据项动态更新图表数据
         // 示例中使用了固定数据,实际应用中可以根据选中的项目从后端获取数据
-        this.updateTrendChart()
-        this.updateProportionChart()
+        this.updateLeftTrendChart()
+        this.updateLeftProportionChart()
+      },
+
+      // 根据选中的数据项更新右侧图表
+      updateRightChartsBySelection() {
+        // 这里可以根据选中的数据项动态更新图表数据
+        // 示例中使用了固定数据,实际应用中可以根据选中的项目从后端获取数据
+        this.updateRightTrendChart()
+        this.updateRightProportionChart()
       },
 
       // 处理窗口大小变化
       handleResize() {
-        if (this.trendChart) {
-          this.trendChart.resize()
+        // 调整左侧图表大小
+        if (this.leftTrendChart) {
+          this.leftTrendChart.resize()
         }
-        if (this.proportionChart) {
-          this.proportionChart.resize()
+        if (this.leftProportionChart) {
+          this.leftProportionChart.resize()
         }
+        // 调整右侧图表大小
+        if (this.rightTrendChart) {
+          this.rightTrendChart.resize()
+        }
+        if (this.rightProportionChart) {
+          this.rightProportionChart.resize()
+        }
+      },
+
+      // 左侧查询按钮点击事件
+      handleLeftQuery() {
+        // 这里可以根据搜索条件从后端获取数据
+        // 示例中使用了固定数据
+        this.updateLeftChartsBySelection()
       },
 
-      // 查询按钮点击事件
-      handleQuery() {
+      // 右侧查询按钮点击事件
+      handleRightQuery() {
         // 这里可以根据搜索条件从后端获取数据
         // 示例中使用了固定数据
-        this.updateChartsBySelection()
+        this.updateRightChartsBySelection()
+      },
+
+      // 左侧重置按钮点击事件
+      handleLeftReset() {
+        // 重置左侧搜索表单
+        this.leftSearchForm = {
+          projectName: '',
+          auditObject: '',
+          startYear: '2024',
+          endYear: '2025',
+        }
+        // 重置左侧树形选择
+        if (this.$refs.leftDataTree) {
+          this.$refs.leftDataTree.clearChecked()
+        }
+        // 重置左侧选中项
+        this.leftSelectedItems = []
+        // 重置左侧图表
+        this.updateLeftTrendChart()
+        this.updateLeftProportionChart()
       },
 
-      // 重置按钮点击事件
-      handleReset() {
-        // 重置搜索表单
-        this.searchForm = {
+      // 右侧重置按钮点击事件
+      handleRightReset() {
+        // 重置右侧搜索表单
+        this.rightSearchForm = {
           projectName: '',
           auditObject: '',
           startYear: '2024',
           endYear: '2025',
         }
-        // 重置树形选择
-        if (this.$refs.dataTree) {
-          this.$refs.dataTree.clearChecked()
+        // 重置右侧树形选择
+        if (this.$refs.rightDataTree) {
+          this.$refs.rightDataTree.clearChecked()
         }
-        // 重置选中项
-        this.selectedItems = []
-        // 重置图表
-        this.updateTrendChart()
-        this.updateProportionChart()
+        // 重置右侧选中项
+        this.rightSelectedItems = []
+        // 重置右侧图表
+        this.updateRightTrendChart()
+        this.updateRightProportionChart()
       },
     },
   }
@@ -381,21 +724,50 @@
   .industry-analysis-container {
     padding: 20px;
   }
+
   .search-form {
     display: flex;
     align-items: center;
+    flex-wrap: wrap;
   }
 
-  .main-content {
+  .comparison-container {
     display: flex;
-    gap: 20px;
+    gap: 0;
+    position: relative;
+  }
+
+  .comparison-panel {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
   }
 
   .left-panel {
+    border-right: 1px solid #e0e0e0;
+  }
+
+  .right-panel {
+    border-left: none;
+  }
+
+  .panel-content {
+    display: flex;
+    gap: 20px;
+    flex: 1;
+    padding: 20px 0;
+  }
+
+  .data-selector {
     width: 250px;
-    background-color: #fff;
     padding: 20px;
-    border-radius: 4px;
+  }
+
+  .chart-section {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    gap: 20px;
   }
 
   .panel-title {
@@ -410,17 +782,8 @@
     overflow-y: auto;
   }
 
-  .right-panel {
-    flex: 1;
-    display: flex;
-    flex-direction: column;
-    gap: 20px;
-  }
-
   .chart-container {
-    background-color: #fff;
     padding: 20px;
-    border-radius: 4px;
   }
 
   .chart-title {
@@ -436,16 +799,67 @@
     height: 400px;
   }
 
-  @media (max-width: 1200px) {
-    .main-content {
+  .search-section {
+    padding: 20px;
+  }
+
+  .vs-container {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    z-index: 10;
+  }
+
+  .vs-icon {
+    background-color: #ffa940;
+    border: none;
+    border-radius: 50%;
+    width: 50px;
+    height: 50px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 18px;
+    font-weight: bold;
+    color: #ffffff;
+    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
+  }
+
+  @media (max-width: 1400px) {
+    .panel-content {
       flex-direction: column;
     }
 
-    .left-panel {
+    .data-selector {
       width: 100%;
     }
 
     .chart {
+      height: 350px;
+    }
+  }
+
+  @media (max-width: 1024px) {
+    .comparison-container {
+      flex-direction: column;
+    }
+
+    .left-panel {
+      border-right: none;
+      border-bottom: 1px solid #e0e0e0;
+      margin-bottom: 20px;
+    }
+
+    .right-panel {
+      border-left: none;
+    }
+
+    .vs-container {
+      display: none;
+    }
+
+    .chart {
       height: 300px;
     }
   }

+ 38 - 7
src/views/costAudit/projectInfo/auditProjectManage/initiation/index.vue

@@ -175,24 +175,41 @@
             {{ orgNameMap[scope.row.orgId] }}
           </template>
         </el-table-column>
+        <el-table-column
+          prop="status"
+          label="项目状态"
+          align="center"
+          width="100"
+        >
+          <template slot-scope="scope">
+            {{ scope.row.status | statusFilter }}
+          </template>
+        </el-table-column>
         <el-table-column label="操作" width="200" align="center">
           <template slot-scope="scope">
-            <el-button type="text" size="small" @click="handleEdit(scope.row)">
-              修改
+            <el-button
+              type="text"
+              size="small"
+              @click="handleViewDetail(scope.row)"
+            >
+              查看
             </el-button>
             <el-button
+              v-if="scope.row.status != '2'"
               type="text"
               size="small"
-              @click="handleDelete(scope.row)"
+              class="delete-btn"
+              @click="handleEdit(scope.row)"
             >
-              删除
+              修改
             </el-button>
             <el-button
+              v-if="scope.row.status != '2'"
               type="text"
               size="small"
-              @click="handleViewDetail(scope.row)"
+              @click="handleDelete(scope.row)"
             >
-              查看
+              删除
             </el-button>
           </template>
         </el-table-column>
@@ -237,6 +254,19 @@
     components: {
       EstablishmentDialog, // 注册组件
     },
+    filters: {
+      statusFilter(value) {
+        if (!value) return ''
+        switch (value) {
+          case '1':
+            return '未发布'
+          case '2':
+            return '已发布'
+          default:
+            return value
+        }
+      },
+    },
     mixins: [dictMixin, regionMixin],
     data() {
       return {
@@ -500,7 +530,8 @@
   }
 </script>
 
-<style scoped>
+<style scoped lang="scss">
+  @import '@/styles/costAudit.scss';
   .cost-audit-initiation {
     padding: 20px;
     background-color: #fff;

+ 1 - 1
src/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/index.vue

@@ -185,7 +185,7 @@
           case '2':
             return '已发布'
           default:
-            return '未知状态'
+            return value
         }
       },
     },

+ 23 - 3
src/views/costAudit/projectInfo/auditTaskManage/taskProgressManage/index.vue

@@ -52,6 +52,7 @@
           rowKey: 'id',
           treeProps: { children: 'children', hasChildren: 'hasChildren' },
           defaultExpandAll: true,
+          showExpandColumn: false,
         }"
       >
         <!-- 预警列自定义内容 -->
@@ -82,13 +83,28 @@
             >
               详情
             </el-button>
-            <el-button size="mini" type="text" @click="handlePause(row)">
+            <el-button
+              v-if="row.status != 400 && row.status != 300"
+              size="mini"
+              type="text"
+              @click="handlePause(row)"
+            >
               中止
             </el-button>
-            <el-button size="mini" type="text" @click="handleDelegate(row)">
+            <el-button
+              v-if="row.status != 400 && row.status != 300"
+              size="mini"
+              type="text"
+              @click="handleDelegate(row)"
+            >
               代办
             </el-button>
-            <el-button size="mini" type="text" @click="handleUrge(row)">
+            <el-button
+              v-if="row.status != 400 && row.status != 300"
+              size="mini"
+              type="text"
+              @click="handleUrge(row)"
+            >
               督办
             </el-button>
           </template>
@@ -274,6 +290,10 @@
             formatter: (row) => {
               return row.year || ''
             },
+            renderHeader: ({ column, $index }) => {
+              return <span>{column.label}</span>
+            },
+            slotName: 'expand',
           },
           {
             prop: 'projectName',

+ 19 - 15
src/views/home/index.vue

@@ -9,20 +9,22 @@
               <h3>成本监审办理情况</h3>
             </div>
             <div class="header-actions">
-              <el-select
-                v-model="province"
-                placeholder="请选择省份"
-                style="width: 100px; margin-right: 10px"
-              >
-                <el-option label="山西省" value="山西省"></el-option>
-              </el-select>
-              <el-select
+              <el-cascader
+                v-model="areaCode"
+                :options="districtTree"
+                :show-all-levels="false"
+                :props="districtTreeCascaderProps"
+                style="width: 120px; margin-right: 10px"
+                placeholder="请选择"
+              />
+              <el-date-picker
                 v-model="year"
-                placeholder="请选择年份"
-                style="width: 100px"
-              >
-                <el-option label="2025" value="2025"></el-option>
-              </el-select>
+                type="year"
+                placeholder="选择年"
+                format="yyyy"
+                value-format="yyyy"
+                style="width: 120px"
+              ></el-date-picker>
             </div>
           </div>
           <div
@@ -331,14 +333,16 @@
 </template>
 
 <script>
+  // 引入地区选择混入
+  import { regionMixin } from '@/mixins/useDict'
   import * as echarts from 'echarts'
   import { memoManageMixin } from '@/views/costAudit/projectInfo/auditProjectManage/memoManage/memoManageMixin'
   export default {
     name: 'Dashboard',
-    mixins: [memoManageMixin],
+    mixins: [regionMixin, memoManageMixin],
     data() {
       return {
-        province: '山西省',
+        areaCode: '140000',
         year: '2025',
         auditType: '山西省公立幼儿园教育成本监审',
         searchKeyword: '',

+ 135 - 0
src/views/login/ssoLogin.vue

@@ -0,0 +1,135 @@
+<template>
+  <div class="login-container">
+    <div class="login-content">
+      <div class="login-title">正在登录中...</div>
+      <div class="loading-spinner">
+        <i class="el-icon-loading"></i>
+      </div>
+      <div class="login-status">{{ statusText }}</div>
+    </div>
+  </div>
+</template>
+
+<script>
+  import { ssoLoginByCode } from '@/api/user'
+  import store from '@/store'
+  import router from '@/router'
+
+  export default {
+    name: 'SsoLogin',
+    data() {
+      return {
+        statusText: '正在解析登录参数...',
+      }
+    },
+    mounted() {
+      this.handleSSOLogin()
+    },
+    methods: {
+      getUrlParam(key) {
+        var query = window.location.search.substring(1)
+        var vars = query.split('&')
+        for (var i = 0; i < vars.length; i++) {
+          var pair = vars[i].split('=')
+          if (pair[0] == key) {
+            return pair[1]
+          }
+        }
+        return false
+      },
+      async handleSSOLogin() {
+        try {
+          // 1. 获取URL中的code参数
+          const code = this.getUrlParam('code')
+          if (!code) {
+            this.statusText = '未获取到登录参数,请重试'
+            setTimeout(() => {
+              router.replace('/login')
+            }, 2000)
+            return
+          }
+
+          this.statusText = '正在验证登录信息...'
+
+          // 2. 调用后端接口,将code传给后端
+          const res = await ssoLoginByCode({
+            code,
+          })
+          if (res.token) {
+            this.statusText = '登录成功,正在跳转...'
+            // 使用authentication统一处理用户信息
+            await store.dispatch('user/authentication', res)
+            // 5. 登录成功后跳转到首页或重定向页面
+            const redirect = this.getUrlParam('redirect') || '/'
+            router.replace(redirect)
+          } else if (!res.state) {
+            this.statusText = res.message || '单点登录失败'
+            setTimeout(() => {
+              router.replace('/login')
+            }, 2000)
+            return
+          }
+        } catch (error) {
+          console.error('单点登录失败:', error)
+          this.statusText = '登录失败'
+
+          // 登录失败后重定向到登录页
+          setTimeout(() => {
+            router.replace('/login')
+          }, 2000)
+        }
+      },
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+  .login-container {
+    min-height: 100vh;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background-color: #f0f2f5;
+  }
+
+  .login-content {
+    background: #fff;
+    padding: 40px;
+    border-radius: 8px;
+    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
+    text-align: center;
+    min-width: 360px;
+  }
+
+  .login-title {
+    font-size: 20px;
+    font-weight: 500;
+    color: #303133;
+    margin-bottom: 30px;
+  }
+
+  .loading-spinner {
+    margin: 20px 0;
+  }
+
+  .loading-spinner i {
+    font-size: 48px;
+    color: #409eff;
+    animation: rotate 1.5s linear infinite;
+  }
+
+  .login-status {
+    font-size: 14px;
+    color: #606266;
+    margin-top: 20px;
+  }
+
+  @keyframes rotate {
+    from {
+      transform: rotate(0deg);
+    }
+    to {
+      transform: rotate(360deg);
+    }
+  }
+</style>

Vissa filer visades inte eftersom för många filer har ändrats