Просмотр исходного кода

feat:新增成本监审辅助管理-按钮权限,更改菜单svb图标

cb_luzhixia 1 месяц назад
Родитель
Сommit
4e08613efe
22 измененных файлов с 1214 добавлено и 474 удалено
  1. 4 4
      src/api/costFormManage.js
  2. BIN
      src/assets/index_images/index-icon7@2x.png
  3. BIN
      src/assets/index_images/index-icon8@2x.png
  4. BIN
      src/assets/index_images/index-icon9@2x.png
  5. 0 0
      src/assets/svg/企业申报管理.svg
  6. 25 5
      src/components/layouts/HtSideBar/components/HtMenuItem.vue
  7. 20 1
      src/components/layouts/HtSideBar/components/HtSubmenu.vue
  8. 152 0
      src/plugins/permissions.js
  9. 28 4
      src/views/costAudit/baseInfo/auditDocManage/index.vue
  10. 54 27
      src/views/costAudit/baseInfo/auditDocNoManage/index.vue
  11. 39 33
      src/views/costAudit/baseInfo/auditEntityManage/index.vue
  12. 30 1
      src/views/costAudit/baseInfo/auditReviewDocManage/index.vue
  13. 45 0
      src/views/costAudit/baseInfo/catalogManage/index.vue
  14. 45 5
      src/views/costAudit/baseInfo/costFormManage/index.vue
  15. 36 7
      src/views/costAudit/baseInfo/costFormManage/infoMaintain.vue
  16. 272 156
      src/views/costAudit/baseInfo/costVerifyManage/index.vue
  17. 47 4
      src/views/costAudit/baseInfo/financeSheetManage/index.vue
  18. 372 213
      src/views/costAudit/baseInfo/financeSheetManage/infoMaintain.vue
  19. 4 3
      src/views/costAudit/projectInfo/auditProjectManage/annualReviewPlan/index.vue
  20. 1 1
      src/views/costAudit/projectInfo/auditProjectManage/initiation/index.vue
  21. 1 1
      src/views/costAudit/projectInfo/auditTaskManage/taskCustomizedRelease/index.vue
  22. 39 9
      src/views/home/index.vue

+ 4 - 4
src/api/costFormManage.js

@@ -3,11 +3,11 @@ import request from '@/utils/request'
 const url = window.context.form
 
 // 获取成本调查表模板列表
-export function getCostFormList(params) {
+export function getCostFormList(data) {
   return request({
-    url: `${url}/costSurveyTemplate/v1/listAll`,
-    method: 'get',
-    params,
+    url: `${url}/costSurveyTemplate/v1/listPage`,
+    method: 'post',
+    data,
   })
 }
 

BIN
src/assets/index_images/index-icon7@2x.png


BIN
src/assets/index_images/index-icon8@2x.png


BIN
src/assets/index_images/index-icon9@2x.png


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


+ 25 - 5
src/components/layouts/HtSideBar/components/HtMenuItem.vue

@@ -5,11 +5,20 @@
       class="ht-fa-icon"
       :class="item.meta.icon || routeChildren.meta.icon"
     />
-    <i
-      v-else-if="routeChildren.meta && routeChildren.meta.icon"
-      class="ht-fa-icon"
-      :class="routeChildren.meta.icon"
-    />
+    <div v-else-if="routeChildren.meta && routeChildren.meta.icon">
+      <img
+        v-if="routeChildren.meta && routeChildren.meta.icon.indexOf('svg') >= 0"
+        :src="showSvgIcon(routeChildren.meta.icon, item)"
+        class="svg-icon"
+        alt="菜单图标"
+      />
+      <i
+        v-else-if="routeChildren.meta && routeChildren.meta.icon"
+        class="ht-fa-icon"
+        :class="routeChildren.meta.icon"
+      />
+    </div>
+
     <el-tooltip
       v-if="routeChildren.meta.title && routeChildren.meta.title.length > 8"
       :content="routeChildren.meta.title"
@@ -70,7 +79,12 @@
         default: '',
       },
     },
+    mounted() {},
     methods: {
+      showSvgIcon(iconPath, item) {
+        let path = iconPath.replace(/^.*\/(.*)\.[^.]+\.(svg)$/, '$1.$2')
+        return require('@/assets/svg/' + path)
+      },
       handlePath(routePath) {
         if (isExternal(routePath)) {
           return routePath
@@ -159,4 +173,10 @@
       font-size: 14px;
     }
   }
+  .svg-icon {
+    width: 16px;
+    height: 16px;
+    object-fit: contain;
+    filter: brightness(0) invert(1);
+  }
 </style>

+ 20 - 1
src/components/layouts/HtSideBar/components/HtSubmenu.vue

@@ -12,7 +12,13 @@
         class="ht-fa-icon"
       /> -->
       <template v-if="item.name !== 'moreMenu'">
-        <i class="ht-fa-icon" :class="item.meta.icon"></i>
+        <img
+          v-if="item.meta.icon.indexOf('svg') >= 0"
+          :src="showSvgIcon(item.meta.icon, item)"
+          class="icon-svg"
+          alt="菜单图标"
+        />
+        <i v-else class="ht-fa-icon" :class="item.meta.icon"></i>
 
         <el-tooltip
           v-if="item.meta.title && item.meta.title.length > 5"
@@ -65,7 +71,12 @@
         return hasIsNewList && hasIsNewList.length > 0 ? true : false
       },
     },
+    mounted() {},
     methods: {
+      showSvgIcon(iconPath, item) {
+        let path = iconPath.replace(/^.*\/(.*)\.[^.]+\.(svg)$/, '$1.$2')
+        return require('@/assets/svg/' + path)
+      },
       handlePath(routePath) {
         if (isExternal(routePath)) {
           return routePath
@@ -102,4 +113,12 @@
       color: var(--themeColor);
     }
   }
+  .icon-svg {
+    width: 16px;
+    height: 16px;
+    object-fit: contain;
+    filter: brightness(0) invert(1);
+    margin-right: 0;
+    margin-right: 4px;
+  }
 </style>

+ 152 - 0
src/plugins/permissions.js

@@ -1,5 +1,6 @@
 import store from '@/store'
 
+// 现有权限指令
 const permissions = {
   inserted(element, binding) {
     const { value } = binding
@@ -12,14 +13,165 @@ const permissions = {
   },
 }
 
+// 权限处理逻辑封装为函数,方便inserted和update钩子复用
+function handlePermission(element, binding) {
+  // 获取用户信息
+  const userInfo = store.state.user.userInfo || {}
+  const user = userInfo.user || {}
+  // 更加健壮的管理员权限判断,接受布尔值true、字符串'true'等真值
+  const isAdmin = !!user.admin
+  const dataScope = user.dataScope ?? 999 // 默认无权限
+
+  // 权限级别定义
+  const PERMISSION_LEVEL = {
+    PROVINCE: 0, // 省级
+    CITY: 1, // 市级
+    COUNTY: 2, // 县级
+  }
+
+  // 分类权限定义 - 基于表格结构
+  const PERMISSION_CATEGORIES = {
+    // 第一类:省级维护,市县查看
+    ADMIN_PROVINCE_VIEW_OTHERS: [
+      'catalogManage', // 监审目录管理
+      'auditEntityManage', // 被监审单位管理
+      'costFormManage', // 成本监审表模板管理
+      'financeSheetManage', // 财务数据表模板管理
+      'costVerifyManage', // 成本核定表模板管理
+      'auditReviewDocManage', // 监审文书管理
+      'auditDocNoManage', // 监审文号管理
+      'auditDocManage', // 监审资料管理
+      'annualReviewPlan', // 年度审计计划
+      'auditInitiation', // 监审立项管理
+    ],
+
+    // 第二类:省市县可查看添加本级及下级,同级不可查看添加
+    // LEVEL_BASED_MANAGE: [
+    //   'annualReviewPlan',        // 年度审计计划
+    //   'auditInitiation',       // 监审立项管理
+    // ],
+
+    // 第三类:跟着数据权限走
+    // DATA_BASED_MANAGE: [
+    //   'auditProject',          // 监审项目管理
+    //   'taskManagement',        // 任务管理
+    //   'superviseMatters'       // 督办管理
+    // ],
+  }
+
+  // 解析绑定值
+  const options = binding.value || {}
+  const action = options.action || 'view' // 默认只有查看权限
+  const category = options.category || '' // 权限分类标识
+  const targetData = options.targetData || {} // 目标数据,用于判断同级等场景
+  const displayMode = options.displayMode || 'hidden' // 无权限时的显示模式:'hidden'(隐藏)或 'disabled'(禁用)
+
+  // 判断是否拥有权限
+  let hasPermission = false
+
+  // 管理员拥有所有权限
+  if (isAdmin) {
+    hasPermission = true
+  } else {
+    // 基于分类的权限判断逻辑
+
+    // 第一类权限:省级维护,市县查看
+    if (PERMISSION_CATEGORIES.ADMIN_PROVINCE_VIEW_OTHERS.includes(category)) {
+      if (action === 'view') {
+        // 所有级别都可查看
+        hasPermission = true
+      } else {
+        // 新增、编辑、删除操作只有省级可执行
+        // 确保dataScope为0的省级用户有正确权限
+        hasPermission = dataScope === PERMISSION_LEVEL.PROVINCE
+      }
+    }
+  }
+
+  // 根据displayMode决定无权限时的处理方式
+  if (!hasPermission) {
+    if (displayMode === 'disabled') {
+      // 禁用模式:保留元素但禁用交互
+      element.setAttribute('disabled', 'disabled')
+      element.style.cursor = 'not-allowed'
+      element.style.opacity = '0.6'
+      element.style.pointerEvents = 'none' // 禁用所有指针事件
+
+      // 添加提示类名,可用于自定义样式
+      element.classList.add('permission-disabled')
+
+      // 对于a标签的特殊处理
+      if (element.tagName === 'A') {
+        // 移除href属性或设置为无效值
+        if (element.hasAttribute('href')) {
+          element.setAttribute(
+            'data-original-href',
+            element.getAttribute('href')
+          )
+          element.removeAttribute('href')
+        }
+        element.setAttribute('tabindex', '-1') // 从Tab键序列中移除
+      }
+
+      // 阻止所有事件冒泡和默认行为,确保元素真正不可交互
+      const preventEvent = (e) => {
+        e.stopPropagation()
+        e.preventDefault()
+        return false
+      }
+
+      // 使用捕获模式添加所有可能的交互事件阻止
+      const events = [
+        'click',
+        'mousedown',
+        'mouseup',
+        'dblclick',
+        'touchstart',
+        'touchend',
+        'touchmove',
+        'touchcancel',
+        'keydown',
+        'keypress',
+        'keyup',
+        'focus',
+        'blur',
+      ]
+
+      events.forEach((event) => {
+        element.addEventListener(event, preventEvent, true)
+      })
+
+      // 重写元素上可能存在的onclick等属性
+      element.onclick = null
+      element.onmousedown = null
+      element.onmouseup = null
+      element.ondblclick = null
+    } else {
+      // 默认隐藏模式:移除元素
+      element.parentNode && element.parentNode.removeChild(element)
+    }
+  }
+}
+
+// 区域权限指令定义 - 同时使用inserted和update钩子确保动态元素也能正确应用权限
+const regionPermission = {
+  inserted: handlePermission,
+  update: handlePermission,
+}
+
+// 安装函数
 const install = function (Vue) {
   Vue.directive('permissions', permissions)
+  Vue.directive('region-permission', regionPermission)
 }
 
+// 全局安装
 if (window.Vue) {
   window['permissions'] = permissions
+  window['regionPermission'] = regionPermission
   Vue.use(install)
 }
 
+// 导出
 permissions.install = install
 export default permissions

+ 28 - 4
src/views/costAudit/baseInfo/auditDocManage/index.vue

@@ -34,6 +34,7 @@
     </div>
     <div class="button-container">
       <el-button
+        v-region-permission="{ category: 'auditDocManage', action: 'add' }"
         plain
         type="success"
         icon="el-icon-circle-plus"
@@ -57,7 +58,16 @@
         header-align="center"
       >
         <template slot-scope="scope">
-          <a href="#" class="link-text" @click.prevent="handleView(scope.row)">
+          <a
+            v-region-permission="{
+              category: 'auditDocManage',
+              action: 'view',
+              displayMode: 'disabled',
+            }"
+            href="#"
+            class="link-text"
+            @click.prevent="handleView(scope.row)"
+          >
             {{ scope.row.title }}
           </a>
         </template>
@@ -77,10 +87,19 @@
       >
         <template slot-scope="scope">
           <!-- 文字按钮样式 -->
-          <el-button size="mini" type="text" @click="handleEdit(scope.row)">
+          <el-button
+            v-region-permission="{ category: 'auditDocManage', action: 'edit' }"
+            size="mini"
+            type="text"
+            @click="handleEdit(scope.row)"
+          >
             修改
           </el-button>
           <el-button
+            v-region-permission="{
+              category: 'auditDocManage',
+              action: 'delete',
+            }"
             size="mini"
             type="text"
             class="delete-btn"
@@ -88,7 +107,12 @@
           >
             删除
           </el-button>
-          <el-button size="mini" type="text" @click="handleLink(scope.row)">
+          <el-button
+            v-region-permission="{ category: 'auditDocManage', action: 'edit' }"
+            size="mini"
+            type="text"
+            @click="handleLink(scope.row)"
+          >
             关联监审目录
           </el-button>
         </template>
@@ -111,7 +135,7 @@
     <el-dialog
       :title="dialogTitle"
       :visible.sync="dialogVisible"
-      width="30%"
+      width="500px"
       @close="handleDialogClose"
     >
       <el-form

+ 54 - 27
src/views/costAudit/baseInfo/auditDocNoManage/index.vue

@@ -63,6 +63,10 @@
         <!-- 操作按钮区域 -->
         <div class="operation-bar">
           <el-button
+            v-region-permission="{
+              category: 'auditDocNoManage',
+              action: 'add',
+            }"
             plain
             type="success"
             icon="el-icon-circle-plus"
@@ -71,6 +75,10 @@
             添加
           </el-button>
           <el-button
+            v-region-permission="{
+              category: 'auditDocNoManage',
+              action: 'delete',
+            }"
             plain
             type="danger"
             icon="el-icon-delete"
@@ -106,6 +114,42 @@
               {{ row.updateTime ? row.updateTime.split(' ')[1] : '' }}
             </div>
           </template>
+          <template #action="{ row }">
+            <el-button
+              v-region-permission="{
+                category: 'auditReviewDocManage',
+                action: 'view',
+              }"
+              type="text"
+              size="mini"
+              @click="handleDetail(row)"
+            >
+              详情
+            </el-button>
+            <el-button
+              v-region-permission="{
+                category: 'auditReviewDocManage',
+                action: 'edit',
+              }"
+              type="text"
+              size="mini"
+              @click="handleEdit(row)"
+            >
+              修改
+            </el-button>
+            <el-button
+              v-region-permission="{
+                category: 'auditReviewDocManage',
+                action: 'delete',
+              }"
+              type="text"
+              size="mini"
+              class="delete-btn"
+              @click="handleDeleteRow(row)"
+            >
+              删除
+            </el-button>
+          </template>
         </CostAuditTable>
 
         <!-- 添加/修改弹窗  -->
@@ -123,7 +167,7 @@
               :rules="formRules"
               label-width="120px"
               size="small"
-              :disabled="dialogVisible == '详情'"
+              :disabled="dialogTitle == '详情'"
             >
               <el-row :gutter="20">
                 <el-col :span="12">
@@ -286,7 +330,13 @@
           </div>
 
           <div slot="footer" class="dialog-footer">
-            <el-button type="primary" @click="handleSave">确认</el-button>
+            <el-button
+              v-if="dialogTitle === '添加'"
+              type="primary"
+              @click="handleSave"
+            >
+              确认
+            </el-button>
             <el-button @click="dialogVisible = false">取消</el-button>
           </div>
         </el-dialog>
@@ -450,31 +500,8 @@
             prop: 'action',
             label: '操作',
             align: 'center',
-            width: 200,
-            actions: [
-              {
-                name: 'detail',
-                label: '详情',
-                type: 'text',
-                size: 'mini',
-                onClick: this.handleDetail,
-              },
-              {
-                name: 'edit',
-                label: '修改',
-                type: 'text',
-                size: 'mini',
-                onClick: this.handleEdit,
-              },
-              {
-                name: 'delete',
-                label: '删除',
-                type: 'text',
-                size: 'mini',
-                className: 'delete-btn',
-                onClick: this.handleDeleteRow,
-              },
-            ],
+            width: 150,
+            slotName: 'action',
           },
         ],
       }

+ 39 - 33
src/views/costAudit/baseInfo/auditEntityManage/index.vue

@@ -39,6 +39,7 @@
     </div>
     <div class="operation-bar">
       <el-button
+        v-region-permission="{ category: 'auditEntityManage', action: 'add' }"
         plain
         type="success"
         icon="el-icon-circle-plus"
@@ -54,9 +55,45 @@
         :table-data="tableData"
         :columns="columns"
         :pagination="pagination"
-        :show-action-column="true"
         @pagination-change="handlePaginationChange"
-      ></cost-audit-table>
+      >
+        <!-- 操作列插槽 -->
+        <template #action="{ row }">
+          <div class="action-buttons">
+            <el-button
+              v-region-permission="{
+                category: 'auditEntityManage',
+                action: 'edit',
+              }"
+              type="text"
+              @click="handleEdit(row)"
+            >
+              修改
+            </el-button>
+            <el-button
+              v-region-permission="{
+                category: 'auditEntityManage',
+                action: 'delete',
+              }"
+              type="text"
+              class="delete-btn"
+              @click="handleDelete(row)"
+            >
+              删除
+            </el-button>
+            <el-button
+              v-region-permission="{
+                category: 'auditEntityManage',
+                action: 'edit',
+              }"
+              type="text"
+              @click="handleChangeStatus(row)"
+            >
+              {{ row.status === 1 ? '停用' : '启用' }}
+            </el-button>
+          </div>
+        </template>
+      </cost-audit-table>
     </div>
 
     <!-- 表单弹窗组件 -->
@@ -165,37 +202,6 @@
             align: 'center',
             fixed: 'right',
             showOverflowTooltip: false,
-            // 操作按钮配置
-            actions: [
-              {
-                name: 'edit',
-                label: '修改',
-                type: 'text',
-                onClick: (row) => {
-                  this.handleEdit(row)
-                },
-              },
-              {
-                name: 'delete',
-                label: '删除',
-                type: 'text',
-                className: 'delete-btn',
-                onClick: (row) => {
-                  this.handleDelete(row)
-                },
-              },
-              {
-                name: 'changeStatus',
-                label: '',
-                type: 'text',
-                onClick: (row) => {
-                  this.handleChangeStatus(row)
-                },
-                formatter: (row) => {
-                  return row.status === 1 ? '停用' : '启用'
-                },
-              },
-            ],
           },
         ],
       }

+ 30 - 1
src/views/costAudit/baseInfo/auditReviewDocManage/index.vue

@@ -51,6 +51,10 @@
       <!-- 操作按钮区域 -->
       <div class="action-buttons">
         <el-button
+          v-region-permission="{
+            category: 'auditReviewDocManage',
+            action: 'add',
+          }"
           plain
           type="success"
           icon="el-icon-circle-plus"
@@ -59,6 +63,10 @@
           添加
         </el-button>
         <el-button
+          v-region-permission="{
+            category: 'auditReviewDocManage',
+            action: 'delete',
+          }"
           plain
           type="danger"
           icon="el-icon-delete"
@@ -146,6 +154,11 @@
             <template slot-scope="scope">
               <el-switch
                 v-model="scope.row.status"
+                v-region-permission="{
+                  category: 'auditReviewDocManage',
+                  action: 'edit',
+                  displayMode: 'disabled',
+                }"
                 active-color="#13ce66"
                 active-value="1"
                 inactive-value="0"
@@ -194,16 +207,32 @@
           >
             <template slot-scope="scope">
               <el-button
+                v-region-permission="{
+                  category: 'auditReviewDocManage',
+                  action: 'view',
+                }"
                 type="text"
                 size="mini"
                 @click="handleDetail(scope.row)"
               >
                 详情
               </el-button>
-              <el-button type="text" size="mini" @click="handleEdit(scope.row)">
+              <el-button
+                v-region-permission="{
+                  category: 'auditReviewDocManage',
+                  action: 'edit',
+                }"
+                type="text"
+                size="mini"
+                @click="handleEdit(scope.row)"
+              >
                 修改
               </el-button>
               <el-button
+                v-region-permission="{
+                  category: 'auditReviewDocManage',
+                  action: 'delete',
+                }"
                 type="text"
                 size="mini"
                 class="delete-btn"

+ 45 - 0
src/views/costAudit/baseInfo/catalogManage/index.vue

@@ -57,6 +57,7 @@
       </div>
       <div class="operation-bar">
         <el-button
+          v-region-permission="{ category: 'catalogManage', action: 'add' }"
           plain
           type="success"
           icon="el-icon-circle-plus"
@@ -190,6 +191,10 @@
             <div>
               <el-button
                 v-if="scope.row.status != 0 && scope.row.nodeType !== 'nr'"
+                v-region-permission="{
+                  category: 'catalogManage',
+                  action: 'edit',
+                }"
                 type="text"
                 size="mini"
                 @click="handleEdit(scope.row)"
@@ -198,6 +203,10 @@
               </el-button>
               <el-button
                 v-if="scope.row.status != 0 && scope.row.nodeType !== 'nr'"
+                v-region-permission="{
+                  category: 'catalogManage',
+                  action: 'add',
+                }"
                 type="text"
                 size="mini"
                 @click="handleAddChild(scope.row)"
@@ -210,6 +219,10 @@
                   scope.row.status != 0 &&
                   scope.row.nodeType !== 'nr'
                 "
+                v-region-permission="{
+                  category: 'catalogManage',
+                  action: 'add',
+                }"
                 type="text"
                 size="mini"
                 @click="handleAddContent(scope.row)"
@@ -218,6 +231,10 @@
               </el-button>
               <el-button
                 v-if="scope.row.nodeType == 'nr' && scope.row.status != 0"
+                v-region-permission="{
+                  category: 'catalogManage',
+                  action: 'edit',
+                }"
                 type="text"
                 size="mini"
                 @click="handleEditContent(scope.row)"
@@ -226,6 +243,10 @@
               </el-button>
               <el-button
                 v-if="scope.row.nodeType == 'nr' && scope.row.status != 0"
+                v-region-permission="{
+                  category: 'catalogManage',
+                  action: 'edit',
+                }"
                 type="text"
                 size="mini"
                 @click="handleDropdownCommand('infoMaintain', scope.row)"
@@ -234,6 +255,10 @@
               </el-button>
               <el-button
                 v-if="scope.row.nodeType == 'nr'"
+                v-region-permission="{
+                  category: 'catalogManage',
+                  action: 'edit',
+                }"
                 type="text"
                 @click.native="handleDropdownCommand('status', scope.row)"
               >
@@ -241,6 +266,10 @@
               </el-button>
               <el-button
                 v-if="scope.row.nodeType == 'nr'"
+                v-region-permission="{
+                  category: 'catalogManage',
+                  action: 'delete',
+                }"
                 type="text"
                 class="delete-btn"
                 @click.native="handleDropdownCommand('delete', scope.row)"
@@ -250,6 +279,10 @@
               <!-- 第四个以后的按钮放入更多下拉菜单 -->
               <el-dropdown
                 v-if="scope.row.status != 0 && scope.row.nodeType !== 'nr'"
+                v-region-permission="{
+                  category: 'catalogManage',
+                  action: 'edit',
+                }"
                 trigger="click"
                 class="ml10"
               >
@@ -260,6 +293,10 @@
                 <el-dropdown-menu slot="dropdown">
                   <el-dropdown-item
                     v-if="scope.row.nodeType == 'nr'"
+                    v-region-permission="{
+                      category: 'catalogManage',
+                      action: 'edit',
+                    }"
                     @click.native="
                       handleDropdownCommand('infoMaintain', scope.row)
                     "
@@ -267,12 +304,20 @@
                     信息维护
                   </el-dropdown-item>
                   <el-dropdown-item
+                    v-region-permission="{
+                      category: 'catalogManage',
+                      action: 'edit',
+                    }"
                     divided
                     @click.native="handleDropdownCommand('status', scope.row)"
                   >
                     {{ scope.row.status === 1 ? '停用' : '启用' }}
                   </el-dropdown-item>
                   <el-dropdown-item
+                    v-region-permission="{
+                      category: 'catalogManage',
+                      action: 'delete',
+                    }"
                     @click.native="handleDropdownCommand('delete', scope.row)"
                   >
                     删除

+ 45 - 5
src/views/costAudit/baseInfo/costFormManage/index.vue

@@ -50,6 +50,7 @@
       <!-- 操作按钮 -->
       <div class="operation-bar">
         <el-button
+          v-region-permission="{ category: 'costFormManage', action: 'add' }"
           plain
           type="success"
           icon="el-icon-circle-plus"
@@ -58,6 +59,7 @@
           添加
         </el-button>
         <el-button
+          v-region-permission="{ category: 'costFormManage', action: 'delete' }"
           plain
           type="danger"
           icon="el-icon-delete"
@@ -100,13 +102,33 @@
           </template>
           <!-- 操作列 -->
           <template #action="{ row }">
-            <el-button type="text" size="mini" @click="handleViewDetail(row)">
+            <el-button
+              v-region-permission="{
+                category: 'costFormManage',
+                action: 'view',
+              }"
+              type="text"
+              size="mini"
+              @click="handleViewDetail(row)"
+            >
               详情
             </el-button>
-            <el-button type="text" size="mini" @click="handleEdit(row)">
+            <el-button
+              v-region-permission="{
+                category: 'costFormManage',
+                action: 'edit',
+              }"
+              type="text"
+              size="mini"
+              @click="handleEdit(row)"
+            >
               修改
             </el-button>
             <el-button
+              v-region-permission="{
+                category: 'costFormManage',
+                action: 'delete',
+              }"
               class="delete-btn"
               type="text"
               size="mini"
@@ -114,18 +136,33 @@
             >
               删除
             </el-button>
-            <el-dropdown class="ml10" trigger="click">
+            <el-dropdown
+              v-region-permission="{
+                category: 'costFormManage',
+                action: 'edit',
+              }"
+              class="ml10"
+              trigger="click"
+            >
               <el-button type="text" size="mini">
                 更多
                 <i class="el-icon-arrow-down el-icon--right"></i>
               </el-button>
               <el-dropdown-menu slot="dropdown">
                 <el-dropdown-item
+                  v-region-permission="{
+                    category: 'costFormManage',
+                    action: 'edit',
+                  }"
                   @click.native="handleDropdownCommand('infoMaintain', row)"
                 >
                   内容维护
                 </el-dropdown-item>
                 <el-dropdown-item
+                  v-region-permission="{
+                    category: 'costFormManage',
+                    action: 'edit',
+                  }"
                   @click.native="handleDropdownCommand('status', row)"
                 >
                   {{ row.status === '0' ? '停用' : '启用' }}
@@ -147,7 +184,7 @@
     <CostAuditDialog
       :title="dialogTitle"
       :visible.sync="dialogVisible"
-      width="30%"
+      width="500px"
       :close-on-click-modal="false"
       :show-confirm-btn="dialogTitle !== '查看成本调查表'"
       :cancel-text="dialogTitle === '查看成本调查表' ? '关 闭' : '取 消'"
@@ -488,7 +525,10 @@
         const params = {
           catalogId: this.searchForm.catalogId,
           status: this.searchForm.status,
-          pageNum: this.pagination.currentPage,
+          contentType: '',
+          type: '',
+          keyword: '',
+          page: this.pagination.currentPage,
           pageSize: this.pagination.pageSize,
         }
         getCostFormList(params)

+ 36 - 7
src/views/costAudit/baseInfo/costFormManage/infoMaintain.vue

@@ -1392,7 +1392,7 @@
     <el-dialog
       title="计算公式"
       :visible.sync="calculationFormulaDialogVisible"
-      width="30%"
+      width="500px"
       :before-close="handleDialogClose"
       :close-on-click-modal="false"
     >
@@ -2054,7 +2054,20 @@
         }
         let _data = []
         if (this.radioType == 'current') {
-          _data = this.contentEditForm.fixedTable.fixedTables
+          // 使用递归函数扁平化树形结构
+          const flattenTree = (nodes) => {
+            let result = []
+            nodes.forEach((node) => {
+              result.push(node)
+              if (node.children && node.children.length > 0) {
+                result = result.concat(flattenTree(node.children))
+              }
+            })
+            return result
+          }
+
+          // 扁平化数据并提取cellCode
+          _data = flattenTree(this.contentEditForm.fixedTable.fixedTables)
             .filter((item) => item.cellCode)
             .map((item) => item.cellCode)
         } else if (this.radioType == 'other') {
@@ -2897,11 +2910,27 @@
         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
+        // row.isChild &&
+        if (!isHeader) {
+          // 获取当前项的序号值
+          let currIndex = curr.fixedValues
+            ? curr.fixedValues['序号']
+            : curr.dynamicValues['序号']
+          // 获取交换项的序号值
+          let swamIndex = swam.fixedValues
+            ? swam.fixedValues['序号']
+            : swam.dynamicValues['序号']
+          // 先保存交换项的值,再进行赋值,避免值被覆盖
+          if (curr.fixedValues) {
+            curr.fixedValues['序号'] = swamIndex
+          } else {
+            curr.dynamicValues['序号'] = swamIndex
+          }
+          if (swam.fixedValues) {
+            swam.fixedValues['序号'] = currIndex
+          } else {
+            swam.dynamicValues['序号'] = currIndex
+          }
         }
 
         // 交换数组中的位置

+ 272 - 156
src/views/costAudit/baseInfo/costVerifyManage/index.vue

@@ -686,32 +686,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="150" align="center">
-                  <template slot-scope="scope">
-                    <div class="row-indent-container">
-                      <el-input
-                        :value="
-                          scope.row.fixedValues
-                            ? scope.row.fixedValues['序号']
-                            : ''
-                        "
-                        size="small"
-                        placeholder="数字或中文"
-                        :disabled="dialogTitle == '查看成本核定模板'"
-                        @input="
-                          handleFixedValueChange(scope.row, '序号', $event)
-                        "
-                      ></el-input>
-                    </div>
-                  </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="
@@ -740,6 +723,29 @@
                     <el-tag v-else type="info" size="small">无</el-tag>
                   </template>
                 </el-table-column>
+                <el-table-column label="序号" width="150" align="center">
+                  <template slot-scope="scope">
+                    <div
+                      class="row-indent-container"
+                      :style="getRowIndentStyle(scope.row)"
+                    >
+                      <el-input
+                        :value="
+                          scope.row.fixedValues
+                            ? scope.row.fixedValues['序号']
+                            : ''
+                        "
+                        size="small"
+                        placeholder="数字或中文"
+                        :disabled="dialogTitle == '查看成本核定模板'"
+                        @input="
+                          handleFixedValueChange(scope.row, '序号', $event)
+                        "
+                      ></el-input>
+                    </div>
+                  </template>
+                </el-table-column>
+
                 <el-table-column
                   v-for="(item, index) in contentEditForm.fixedTable
                     .fixedTableHeaders"
@@ -853,7 +859,7 @@
                         type="text"
                         size="mini"
                         :disabled="dialogTitle == '查看成本核定模板'"
-                        @click="handleMoveUp(scope.$index, '固定表')"
+                        @click="handleMoveUp(scope.$index, '固定表', scope.row)"
                       >
                         上升
                       </el-button>
@@ -886,7 +892,7 @@
     <el-dialog
       title="计算公式"
       :visible.sync="calculationFormulaDialogVisible"
-      width="30%"
+      width="500px"
       :before-close="handleDialogClose"
       :close-on-click-modal="false"
     >
@@ -1778,6 +1784,10 @@
         if (!row.fixedValues) {
           this.$set(row, 'fixedValues', {})
         }
+        // 初始化children数组,支持树形结构
+        if (!row.children) {
+          this.$set(row, 'children', [])
+        }
         this.contentEditForm.fixedTable.fixedTablesTitle.forEach(
           (title, index) => {
             if (!(title.rkey in row.fixedValues)) {
@@ -1841,74 +1851,96 @@
       // 上升
       handleMoveUp(index, tableType) {
         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.updateFixedTableDisplayOrder()
-          }
+          const fixedTableData = this.contentEditForm.fixedTable.fixedTables
+          const newFixedTableData = [...fixedTableData]
+          this.swamTableArr(newFixedTableData, row, true)
+          this.contentEditForm.fixedTable.fixedTables = newFixedTableData
         } else {
-          if (index > 0) {
-            const temp = this.contentEditForm.fixedTable.tableHeaders[index]
-            this.contentEditForm.fixedTable.tableHeaders.splice(index, 1)
-            this.contentEditForm.fixedTable.tableHeaders.splice(
-              index - 1,
-              0,
-              temp
-            )
-
-            // 更新orderNum字段(从1开始)
-            this.contentEditForm.fixedTable.tableHeaders.forEach(
-              (header, idx) => {
-                if (header.orderNum !== undefined) {
-                  header.orderNum = idx + 1
-                }
-              }
-            )
-          }
+          const tableHeaders = this.contentEditForm.tableHeaders
+          const newTableHeaders = [...tableHeaders]
+          this.swamTableArr(newTableHeaders, row, true, true)
+          this.contentEditForm.tableHeaders = newTableHeaders
         }
       },
       // 下降
       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
-            )
+          const fixedTableData = this.contentEditForm.fixedTable.fixedTables
+          const newFixedTableData = [...fixedTableData]
+          this.swamTableArr(newFixedTableData, row, false)
+          this.contentEditForm.fixedTable.fixedTables = newFixedTableData
+        } else {
+          const tableHeaders = this.contentEditForm.tableHeaders
+          const newTableHeaders = [...tableHeaders]
+          this.swamTableArr(newTableHeaders, row, false)
+          this.contentEditForm.tableHeaders = newTableHeaders
+        }
+      },
+      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)
+        }
+      },
 
-            // 更新显示的序号值
-            this.updateFixedTableDisplayOrder()
+      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 < this.contentEditForm.fixedTable.tableHeaders.length - 1) {
-            const temp = this.contentEditForm.fixedTable.tableHeaders[index]
-            this.contentEditForm.fixedTable.tableHeaders.splice(index, 1)
-            this.contentEditForm.fixedTable.tableHeaders.splice(
-              index + 1,
-              0,
-              temp
-            )
+          // 倒序
+          if (rowIndex >= arr.length - 1) {
+            return
+          }
+          swamIndex = rowIndex + 1
+        }
 
-            // 更新orderNum字段(从1开始)
-            this.contentEditForm.fixedTable.tableHeaders.forEach(
-              (header, idx) => {
-                if (header.orderNum !== undefined) {
-                  header.orderNum = idx + 1
-                }
-              }
-            )
+        const curr = arr[rowIndex]
+        const swam = arr[swamIndex]
+
+        // 交换orderNum
+        const tempOrderNum = curr.orderNum
+        curr.orderNum = swam.orderNum
+        swam.orderNum = tempOrderNum
+        // row.isChild &&
+        if (!isHeader) {
+          // 获取当前项的序号值
+          let currIndex = curr.fixedValues
+            ? curr.fixedValues['序号']
+            : curr.dynamicValues['序号']
+          // 获取交换项的序号值
+          let swamIndex = swam.fixedValues
+            ? swam.fixedValues['序号']
+            : swam.dynamicValues['序号']
+          // 先保存交换项的值,再进行赋值,避免值被覆盖
+          if (curr.fixedValues) {
+            curr.fixedValues['序号'] = swamIndex
+          } else {
+            curr.dynamicValues['序号'] = swamIndex
+          }
+          if (swam.fixedValues) {
+            swam.fixedValues['序号'] = currIndex
+          } else {
+            swam.dynamicValues['序号'] = currIndex
           }
         }
+
+        // 交换数组中的位置
+        arr[rowIndex] = swam
+        arr[swamIndex] = curr
       },
       // 更新固定表中显示的序号值
       updateFixedTableDisplayOrder() {
@@ -2184,7 +2216,20 @@
         }
         let _data = []
         if (this.radioType == 'current') {
-          _data = this.contentEditForm.fixedTable.fixedTables
+          // 使用递归函数扁平化树形结构
+          const flattenTree = (nodes) => {
+            let result = []
+            nodes.forEach((node) => {
+              result.push(node)
+              if (node.children && node.children.length > 0) {
+                result = result.concat(flattenTree(node.children))
+              }
+            })
+            return result
+          }
+
+          // 扁平化数据并提取cellCode
+          _data = flattenTree(this.contentEditForm.fixedTable.fixedTables)
             .filter((item) => item.cellCode)
             .map((item) => item.cellCode)
         } else if (this.radioType == 'other') {
@@ -2273,6 +2318,10 @@
         // 清空现有数据
         this.contentEditForm.fixedTable.fixedTables = []
 
+        // 使用Map来存储所有行,便于快速查找父项
+        const rowMap = new Map()
+        const parentItems = []
+
         // 遍历itemList,为每个项目创建一行数据
         itemList.forEach((item, index) => {
           // 判断是否为子项(parentid不为-1且不为"-1")
@@ -2293,6 +2342,7 @@
             isSubItem: isSubItem,
             rowid: item.rowid || this.generateUUID(),
             jsonstr: item.jsonstr || null,
+            children: [], // 添加children数组用于树形结构
           }
 
           // 确保orderNum是数字类型
@@ -2304,60 +2354,44 @@
             newRow.fixedValues[title.rkey] = item[title.rkey] || ''
           })
 
-          this.contentEditForm.fixedTable.fixedTables.push(newRow)
-        })
+          // 将行添加到Map中
+          rowMap.set(newRow.rowid, newRow)
+          if (newRow.itemId) {
+            rowMap.set(newRow.itemId, newRow)
+          }
 
-        // 按父子关系和orderNum排序,确保子项显示在父项后面
-        this.contentEditForm.fixedTable.fixedTables.sort((a, b) => {
-          // 先按orderNum排序父项
-          if (a.isChild && !b.isChild) {
-            // 如果a是子项,b是父项,需要检查a的父项是否在b之后
-            const parentOfA = this.contentEditForm.fixedTable.fixedTables.find(
-              (item) => item.rowid === a.parentid || item.itemId === a.parentid
-            )
-            if (parentOfA && parentOfA.orderNum > b.orderNum) {
-              return 1
-            }
-            return -1
+          // 如果是父项,添加到父项数组
+          if (!isSubItem) {
+            parentItems.push(newRow)
           }
-          if (!a.isChild && b.isChild) {
-            // 如果a是父项,b是子项,需要检查b的父项是否在a之前
-            const parentOfB = this.contentEditForm.fixedTable.fixedTables.find(
-              (item) => item.rowid === b.parentid || item.itemId === b.parentid
-            )
-            if (parentOfB && parentOfB.orderNum < a.orderNum) {
-              return -1
+        })
+
+        // 构建父子关系
+        rowMap.forEach((row) => {
+          if (row.isChild && row.parentid) {
+            const parent = rowMap.get(row.parentid)
+            if (parent) {
+              parent.children.push(row)
+              // 确保父项有hasChildren标记
+              parent.hasChildren = true
             }
-            return 1
           }
-
-          // 如果都是父项或都是子项,按orderNum排序
-          return (a.orderNum || 0) - (b.orderNum || 0)
         })
 
-        // 重新排序,确保子项紧跟在其对应的父项后面
-        const sortedArray = []
-        const parentItems = this.contentEditForm.fixedTable.fixedTables.filter(
-          (item) => !item.isChild
-        )
-        const childItems = this.contentEditForm.fixedTable.fixedTables.filter(
-          (item) => item.isChild
-        )
+        // 对父项按orderNum排序
+        parentItems.sort((a, b) => (a.orderNum || 0) - (b.orderNum || 0))
 
+        // 对子项按orderNum排序
         parentItems.forEach((parent) => {
-          sortedArray.push(parent)
-          // 找到并添加该父项的所有子项
-          const relatedChildren = childItems.filter(
-            (child) =>
-              child.parentid === parent.rowid ||
-              child.parentid === parent.itemId
-          )
-          // 子项按orderNum排序
-          relatedChildren.sort((a, b) => (a.orderNum || 0) - (b.orderNum || 0))
-          sortedArray.push(...relatedChildren)
+          if (parent.children && parent.children.length > 0) {
+            parent.children.sort(
+              (a, b) => (a.orderNum || 0) - (b.orderNum || 0)
+            )
+          }
         })
 
-        this.contentEditForm.fixedTable.fixedTables = sortedArray
+        // 设置最终的fixedTables数据
+        this.contentEditForm.fixedTable.fixedTables = parentItems
       },
       /**
        * 将固定表项目的数据根据固定列拆分成对应的数据结构
@@ -2370,10 +2404,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
@@ -2381,41 +2426,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' &&
@@ -2426,14 +2465,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
@@ -2446,6 +2548,20 @@
           rvalue: '',
         }))
       },
+      /**
+       * 获取行缩进样式,用于树形结构展示
+       * @param {Object} row - 表格行数据
+       * @returns {Object} 样式对象
+       */
+      getRowIndentStyle(row) {
+        // 为子项添加缩进
+        if (row.isChild) {
+          return {
+            marginLeft: '30px',
+          }
+        }
+        return {}
+      },
       handleSaveTemplate() {
         // 校验表单
         this.$refs['contentEditForm'].validate((valid) => {

+ 47 - 4
src/views/costAudit/baseInfo/financeSheetManage/index.vue

@@ -49,6 +49,10 @@
       <!-- 操作按钮 -->
       <div class="operation-bar">
         <el-button
+          v-region-permission="{
+            category: 'financeSheetManage',
+            action: 'add',
+          }"
           plain
           type="success"
           icon="el-icon-circle-plus"
@@ -57,6 +61,10 @@
           添加
         </el-button>
         <el-button
+          v-region-permission="{
+            category: 'financeSheetManage',
+            action: 'delete',
+          }"
           plain
           type="danger"
           icon="el-icon-delete"
@@ -99,13 +107,33 @@
           </template>
           <!-- 操作列 -->
           <template #action="{ row }">
-            <el-button type="text" size="mini" @click="handleViewDetail(row)">
+            <el-button
+              v-region-permission="{
+                category: 'financeSheetManage',
+                action: 'view',
+              }"
+              type="text"
+              size="mini"
+              @click="handleViewDetail(row)"
+            >
               详情
             </el-button>
-            <el-button type="text" size="mini" @click="handleEdit(row)">
+            <el-button
+              v-region-permission="{
+                category: 'financeSheetManage',
+                action: 'edit',
+              }"
+              type="text"
+              size="mini"
+              @click="handleEdit(row)"
+            >
               修改
             </el-button>
             <el-button
+              v-region-permission="{
+                category: 'financeSheetManage',
+                action: 'delete',
+              }"
               class="delete-btn"
               type="text"
               size="mini"
@@ -113,18 +141,33 @@
             >
               删除
             </el-button>
-            <el-dropdown class="ml10" trigger="click">
+            <el-dropdown
+              v-region-permission="{
+                category: 'financeSheetManage',
+                action: 'edit',
+              }"
+              class="ml10"
+              trigger="click"
+            >
               <el-button type="text" size="mini">
                 更多
                 <i class="el-icon-arrow-down el-icon--right"></i>
               </el-button>
               <el-dropdown-menu slot="dropdown">
                 <el-dropdown-item
+                  v-region-permission="{
+                    category: 'financeSheetManage',
+                    action: 'edit',
+                  }"
                   @click.native="handleDropdownCommand('infoMaintain', row)"
                 >
                   内容维护
                 </el-dropdown-item>
                 <el-dropdown-item
+                  v-region-permission="{
+                    category: 'financeSheetManage',
+                    action: 'edit',
+                  }"
                   @click.native="handleDropdownCommand('status', row)"
                 >
                   {{ row.status === '0' ? '停用' : '启用' }}
@@ -146,7 +189,7 @@
     <CostAuditDialog
       :title="dialogTitle"
       :visible.sync="dialogVisible"
-      width="30%"
+      width="500px"
       :close-on-click-modal="false"
       :show-confirm-btn="dialogTitle !== '查看财务数据表'"
       :cancel-text="dialogTitle === '查看财务数据表' ? '关 闭' : '取 消'"

+ 372 - 213
src/views/costAudit/baseInfo/financeSheetManage/infoMaintain.vue

@@ -451,7 +451,7 @@
                 </template>
               </el-table-column>
 
-              <el-table-column label="操作" width="150" fixed="right">
+              <el-table-column label="操作" width="200" fixed="right">
                 <template slot-scope="scope">
                   <div class="table-actions">
                     <el-button
@@ -469,7 +469,7 @@
                       type="text"
                       size="mini"
                       :disabled="viewDetail"
-                      @click="handleMoveUp(scope.$index)"
+                      @click="handleMoveUp(scope.$index, '', scope.row)"
                     >
                       上升
                     </el-button>
@@ -480,7 +480,7 @@
                       type="text"
                       size="mini"
                       :disabled="viewDetail"
-                      @click="handleMoveDown(scope.$index)"
+                      @click="handleMoveDown(scope.$index, '', scope.row)"
                     >
                       下降
                     </el-button>
@@ -716,7 +716,7 @@
                   </div>
                 </template>
               </el-table-column>
-              <el-table-column label="操作" width="150" fixed="right">
+              <el-table-column label="操作" width="200" fixed="right">
                 <template slot-scope="scope">
                   <div class="table-actions">
                     <el-button
@@ -780,28 +780,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="
@@ -830,6 +817,22 @@
                     <el-tag v-else type="info" size="small">无</el-tag>
                   </template>
                 </el-table-column>
+                <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
                   v-for="(item, index) in contentEditForm.fixedTable
                     .fixedTableHeaders"
@@ -888,7 +891,12 @@
                     ></el-input>
                   </template>
                 </el-table-column>
-                <el-table-column label="操作" align="center" fixed="right">
+                <el-table-column
+                  label="操作"
+                  align="center"
+                  width="220"
+                  fixed="right"
+                >
                   <template slot-scope="scope">
                     <div class="table-actions">
                       <el-button
@@ -924,7 +932,7 @@
                         v-if="scope.$index !== 0"
                         type="text"
                         size="mini"
-                        @click="handleMoveUp(scope.$index, '固定表')"
+                        @click="handleMoveUp(scope.$index, '固定表', scope.row)"
                       >
                         上升
                       </el-button>
@@ -936,7 +944,9 @@
                         type="text"
                         size="mini"
                         :disabled="viewDetail"
-                        @click="handleMoveDown(scope.$index, '固定表')"
+                        @click="
+                          handleMoveDown(scope.$index, '固定表', scope.row)
+                        "
                       >
                         下降
                       </el-button>
@@ -1157,7 +1167,7 @@
                   </div>
                 </template>
               </el-table-column>
-              <el-table-column label="操作" width="150" fixed="right">
+              <el-table-column label="操作" width="200" fixed="right">
                 <template slot-scope="scope">
                   <div class="table-actions">
                     <el-button
@@ -1221,30 +1231,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="
@@ -1273,6 +1268,24 @@
                     <el-tag v-else type="info" size="small">无</el-tag>
                   </template>
                 </el-table-column>
+                <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
                   v-for="(item, index) in contentEditForm.dynamicTable
                     .dynamicTableHeaders"
@@ -1295,7 +1308,12 @@
                     ></el-input>
                   </template>
                 </el-table-column>
-                <el-table-column label="操作" align="center" fixed="right">
+                <el-table-column
+                  label="操作"
+                  width="220"
+                  align="center"
+                  fixed="right"
+                >
                   <template slot-scope="scope">
                     <div class="table-actions">
                       <el-button
@@ -1332,7 +1350,7 @@
                         type="text"
                         size="mini"
                         :disabled="viewDetail"
-                        @click="handleMoveUp(scope.$index, '动态表')"
+                        @click="handleMoveUp(scope.$index, '动态表', scope.row)"
                       >
                         上升
                       </el-button>
@@ -1344,7 +1362,9 @@
                         type="text"
                         size="mini"
                         :disabled="viewDetail"
-                        @click="handleMoveDown(scope.$index, '动态表')"
+                        @click="
+                          handleMoveDown(scope.$index, '动态表', scope.row)
+                        "
                       >
                         下降
                       </el-button>
@@ -1774,7 +1794,7 @@
         this.surveyTemplateId = row.surveyTemplateId
         this.templateType = row.templateType
         this.surveyTemplateName = row.surveyTemplateName
-        this.contentEditForm.tableName = row.storageTable
+        this.contentEditForm.tableName = row.surveyTemplateName
         this.contentEditForm.templateType = row.templateType
         this.handleSearch()
         this.loadDictTypeList()
@@ -2020,7 +2040,20 @@
         }
         let _data = []
         if (this.radioType == 'current') {
-          _data = this.contentEditForm.fixedTable.fixedTables
+          // 使用递归函数扁平化树形结构
+          const flattenTree = (nodes) => {
+            let result = []
+            nodes.forEach((node) => {
+              result.push(node)
+              if (node.children && node.children.length > 0) {
+                result = result.concat(flattenTree(node.children))
+              }
+            })
+            return result
+          }
+
+          // 扁平化数据并提取cellCode
+          _data = flattenTree(this.contentEditForm.fixedTable.fixedTables)
             .filter((item) => item.cellCode)
             .map((item) => item.cellCode)
         } else if (this.radioType == 'other') {
@@ -2785,116 +2818,126 @@
       },
 
       // 上升
-      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
-            )
-          }
+          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
-            )
-          }
+          const dynamicTableData =
+            this.contentEditForm.dynamicTable.dynamicTables
+          const newDynamicTableData = [...dynamicTableData]
+          this.swamTableArr(newDynamicTableData, row, true)
+          this.contentEditForm.dynamicTable.dynamicTables = newDynamicTableData
         } else {
-          if (index > 0) {
-            const temp = this.contentEditForm.tableHeaders[index]
-            this.contentEditForm.tableHeaders.splice(index, 1)
-            this.contentEditForm.tableHeaders.splice(index - 1, 0, temp)
-          }
+          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, true)
+          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()
+          // }
         }
       },
 
-      // 启动/停用状态
-      handleStatus(row) {
-        const action = row.status === '0' ? '停用' : '启用'
-        if (row.status === '0') {
-          this.$confirm(`确认要停用该数据吗?`, '操作确认', {
-            confirmButtonText: '确定',
-            cancelButtonText: '取消',
-            type: 'warning',
-          })
-            .then(() => {
-              row.status = '-1'
-              putSurveyFdTemplatePublishVersion(row).then((res) => {
-                if (res.code === 200) {
-                  this.$message.success(`${action}成功`)
-                  this.handleSearch()
-                }
-              })
-            })
-            .catch(() => {
-              this.$message({
-                type: 'info',
-                message: '已取消操作',
-              })
-            })
-        } else if (row.status === '-1') {
-          this.$confirm(`确认要启用该数据吗?`, '操作确认', {
-            confirmButtonText: '确定',
-            cancelButtonText: '取消',
-            type: 'warning',
-          })
-            .then(() => {
-              row.status = '0'
-              putSurveyFdTemplatePublishVersion(row).then((res) => {
-                if (res.code === 200) {
-                  this.$message.success(`停用成功`)
-                  this.handleSearch()
-                }
-              })
-            })
-            .catch(() => {
-              this.$message({
-                type: 'info',
-                message: '已取消操作',
-              })
-            })
+      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)
         }
       },
 
-      // 下降
-      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
-            )
-          }
-        } 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
-            )
+      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 < 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)
+          // 倒序
+          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
+
+        // 刷新序号 row.isChild&&
+        if (!isHeader) {
+          // 获取当前项的序号值
+          let currIndex = curr.fixedValues
+            ? curr.fixedValues['序号']
+            : curr.dynamicValues['序号']
+          // 获取交换项的序号值
+          let swamIndex = swam.fixedValues
+            ? swam.fixedValues['序号']
+            : swam.dynamicValues['序号']
+          // 先保存交换项的值,再进行赋值,避免值被覆盖
+          if (curr.fixedValues) {
+            curr.fixedValues['序号'] = swamIndex
+          } else {
+            curr.dynamicValues['序号'] = swamIndex
+          }
+          if (swam.fixedValues) {
+            swam.fixedValues['序号'] = currIndex
+          } else {
+            swam.dynamicValues['序号'] = currIndex
           }
         }
+
+        // 交换数组中的位置
+        arr[rowIndex] = swam
+        arr[swamIndex] = curr
       },
 
       // 绑定字典变化
@@ -3094,10 +3137,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
@@ -3105,41 +3159,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' &&
@@ -3150,14 +3198,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
@@ -3174,10 +3285,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
@@ -3185,37 +3307,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' &&
@@ -3226,14 +3341,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
@@ -3338,6 +3466,8 @@
         }
 
         const itemList = responseData.value.itemlist
+        const allRows = []
+        const rowMap = new Map()
 
         // 清空现有数据
         this.contentEditForm.fixedTable.fixedTables = []
@@ -3361,8 +3491,9 @@
             parentid: item.parentid || -1,
             isChild: isSubItem,
             isSubItem: isSubItem,
-            rowid: item.rowid || Date.now() + Math.random() + index,
+            rowid: item.rowid || this.generateUUID(),
             jsonstr: item.jsonstr || null,
+            children: [], // 添加children数组用于树形结构
           }
 
           // 确保orderNum是数字类型
@@ -3375,13 +3506,41 @@
             newRow.fixedValues[title.rkey] = item[title.rkey] || ''
           })
 
-          this.contentEditForm.fixedTable.fixedTables.push(newRow)
+          allRows.push(newRow)
+          // 构建rowMap用于快速查找
+          if (newRow.rowid) rowMap.set(String(newRow.rowid), newRow)
+          if (newRow.itemId) rowMap.set(String(newRow.itemId), newRow)
         })
 
-        // 按orderNum排序,确保整个列表按统一序号排序
-        this.contentEditForm.fixedTable.fixedTables.sort((a, b) => {
-          return (a.orderNum || 0) - (b.orderNum || 0)
+        // 构建树形结构
+        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)
+            }
+          }
+        })
+
+        // 对子项进行排序
+        parentItems.forEach((parent) => {
+          parent.children.sort(
+            (a, b) =>
+              (a.fixedValues['序号'] || 0) - (b.fixedValues['序号'] || 0)
+          )
+          treeData.push(parent)
         })
+
+        this.contentEditForm.fixedTable.fixedTables = treeData
+        console.log('树形结构数据:', treeData)
       },
       /**
        * 解析并回显动态表项目数据

+ 4 - 3
src/views/costAudit/projectInfo/auditProjectManage/annualReviewPlan/index.vue

@@ -168,7 +168,7 @@
     <el-dialog
       :title="dialogTitle"
       :visible.sync="dialogVisible"
-      width="50%"
+      width="700px"
       z-index="8000"
       :close-on-click-modal="false"
       @close="handleDialogClose"
@@ -209,7 +209,7 @@
                   placeholder="请选择单位"
                   clearable
                   multiple
-                  style="width: 85%"
+                  style="width: 80%"
                 >
                   <el-option
                     v-for="unit in unitList"
@@ -384,7 +384,7 @@
     <el-dialog
       title="选择单位"
       :visible.sync="dialogUnitVisible"
-      width="30%"
+      width="500px"
       @close="handleDialogClose"
     ></el-dialog>
 
@@ -696,6 +696,7 @@
       // 处理地区选择变化
       handleRegionChange(region) {
         this.areaCode = region.code
+        this.currentProject.areaLevel = region.level
       },
 
       handleSearch() {

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

@@ -198,13 +198,13 @@
               v-if="scope.row.status != '2'"
               type="text"
               size="small"
-              class="delete-btn"
               @click="handleEdit(scope.row)"
             >
               修改
             </el-button>
             <el-button
               v-if="scope.row.status != '2'"
+              class="delete-btn"
               type="text"
               size="small"
               @click="handleDelete(scope.row)"

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

@@ -93,7 +93,7 @@
     <el-dialog
       title="任务发布"
       :visible.sync="publishDialogVisible"
-      width="30%"
+      width="500px"
       :before-close="handleClosePublishDialog"
     >
       <el-form

+ 39 - 9
src/views/home/index.vue

@@ -102,23 +102,45 @@
             :stripe="false"
             class="no-zebra"
           >
-            <el-table-column label="预警" width="60">
+            <el-table-column align="center" label="预警" width="60">
               <template slot-scope="scope">
                 <el-tag v-if="scope.row.warning" type="warning">预警</el-tag>
               </template>
             </el-table-column>
-            <el-table-column prop="task" label="成本监审任务"></el-table-column>
-            <el-table-column prop="unit" label="被监审单位"></el-table-column>
+            <el-table-column
+              align="center"
+              prop="task"
+              label="成本监审任务"
+              show-overflow-tooltip
+            ></el-table-column>
+            <el-table-column
+              align="center"
+              prop="unit"
+              label="被监审单位"
+              show-overflow-tooltip
+            ></el-table-column>
             <el-table-column
               prop="auditForm"
               label="监审形式"
+              width="100"
+              align="center"
+              show-overflow-tooltip
             ></el-table-column>
             <el-table-column
               prop="auditPeriod"
               label="监审期间"
+              width="150"
+              align="center"
+              show-overflow-tooltip
             ></el-table-column>
-            <el-table-column prop="status" label="办理状态"></el-table-column>
-            <el-table-column label="操作" width="100">
+            <el-table-column
+              align="center"
+              prop="status"
+              label="办理状态"
+              width="100"
+              show-overflow-tooltip
+            ></el-table-column>
+            <el-table-column align="center" label="操作" width="100">
               <template slot-scope="scope">
                 <el-button
                   v-if="scope.row.op === '任务详情'"
@@ -300,7 +322,7 @@
                             height: 14px;
                             vertical-align: middle;
                           "
-                          src="@/assets/index_images/index-icon4@2x.png"
+                          src="@/assets/index_images/index-icon8@2x.png"
                         />
                         <span>{{ item.title }}</span>
                       </div>
@@ -312,14 +334,22 @@
                             vertical-align: middle;
                           "
                           src="@/assets/index_images/index-icon4@2x.png"
-                          alt="时间"
                         />
                         <span>{{ item.memoDate }}</span>
                       </div>
                     </div>
                     <div class="news-meta">
-                      <i class="el-icon-document"></i>
-                      <span class="content-text">{{ item.content }}</span>
+                      <div class="left-icon">
+                        <img
+                          style="
+                            width: 14px;
+                            height: 14px;
+                            vertical-align: middle;
+                          "
+                          src="@/assets/index_images/index-icon9@2x.png"
+                        />
+                        <span class="content-text">{{ item.content }}</span>
+                      </div>
                     </div>
                   </div>
                 </li>