Преглед на файлове

Merge branch 'master' of http://114.55.67.98:8070/Natural_p1/zjugis_OA

qiny преди 11 месеца
родител
ревизия
497526466b

+ 1 - 0
client/.env.dev

@@ -6,6 +6,7 @@ VITE_DEV=false
 # 请求路径
 # VITE_BASE_URL='http://10.10.9.113:48080'
 VITE_BASE_URL='http://10.10.10.7:18080'
+# VITE_BASE_URL='https://oa.zjugis.com:28080'
 
 # 上传路径
 VITE_UPLOAD_URL='/infra/file/upload'

+ 11 - 1
client/src/api/oa/workflow/index.ts

@@ -35,6 +35,16 @@ const jsonToFormData = (json: Object) => {
   })
   return formData
 }
+// 获取办件中心Tab列表
+export const officeCenterModule = async () => {
+  return await request.postOriginal(
+    {
+      url: '/HandlerCaseCenter/officeCenterModule',
+      headersType: 'application/form-data'
+    },
+    '/workflow'
+  )
+}
 // 获取办件中心列表
 export const getHandlerCaseCenterList = async (data) => {
   return await request.postOriginal(
@@ -274,7 +284,7 @@ export const openOfficeTip = async (data: {
 export const saveAndGetUrl = async (data: {
   activityInsId: string
   flowInsId: string
-  particiPantId: string
+  participantId: string
   status: string
   userId: string | null
   isView: boolean

Файловите разлики са ограничени, защото са твърде много
+ 3 - 0
client/src/assets/fonts/Iconfont/iconfont.css


+ 2 - 1
client/src/assets/fonts/index.scss

@@ -3,4 +3,5 @@
 @import "./Alibaba/Alibaba-PuHuiTi-Light.css";
 @import "./Alibaba/Alibaba-PuHuiTi-Medium.css";
 @import "./Alibaba/Alibaba-PuHuiTi-Regular.css";
-@import "./Fontawesome/Fontawesome.css";
+@import "./Fontawesome/Fontawesome.css";
+@import "./Iconfont/iconfont.css";

+ 234 - 163
client/src/views/OaSystem/officeCenter/mainOfficeCenter/common.ts

@@ -1,182 +1,253 @@
 import { formatDate } from '@/utils/formatTime'
 
+const pageParam = {
+  page: 1,
+  records: 0,
+  rows: 18
+}
 export const TabColumns = {
   //待办
-  '1': [
-    {
-      label: '操作',
-      name: 'action',
-      width: 138,
-      frozen: true,
-      fixed: true
-    },
-    { label: '业务编号', align: 'center', name: 'CODE', width: 250 },
-    {
-      label: '环节状态',
-      align: 'center',
-      name: 'statusVal',
-      width: 90
-    },
-    {
-      label: '流程描述',
-      align: 'left',
-      name: 'DESCRIBTION',
-      minminWidth: 600
-    },
-    { label: '流程名称', align: 'left', name: 'NAME', width: 130 },
-    { label: '办理环节', align: 'center', name: 'ACTIVITYNAME', width: 200 },
-    {
-      label: '接件时间',
-      align: 'center',
-      name: 'RECEIVE_TIME',
-      width: 190,
-      formatter(row: any, column: any, cellValue: any, index: number) {
-        if (cellValue) {
-          return formatDate(cellValue)
+  '1': {
+    column: [
+      {
+        label: '操作',
+        name: 'action',
+        width: 138,
+        frozen: true,
+        fixed: true
+      },
+      { label: '业务编号', align: 'center', name: 'CODE', width: 180, tooltip: true },
+      {
+        label: '环节状态',
+        align: 'center',
+        name: 'statusVal',
+        width: 90
+      },
+      {
+        label: '流程描述',
+        align: 'left',
+        name: 'DESCRIBTION',
+        minminWidth: 560,
+        tooltip: true
+      },
+      { label: '流程名称', align: 'left', name: 'NAME', width: 130 },
+      { label: '办理环节', align: 'center', name: 'ACTIVITYNAME', width: 200, tooltip: true },
+      {
+        label: '接件时间',
+        align: 'center',
+        name: 'RECEIVE_TIME',
+        width: 190,
+        formatter(row: any, column: any, cellValue: any, index: number) {
+          if (cellValue) {
+            return formatDate(cellValue)
+          }
         }
       }
-    }
-  ],
+    ],
+    data: [],
+    ...pageParam
+  },
   //已完成
-  '90': [
-    {
-      label: '操作',
-      name: 'action',
-      width: 200,
-      frozen: true,
-      fixed: true
-    },
-    { label: '业务编号', align: 'center', name: 'CODE', width: 200 },
-    {
-      label: '环节完成情况',
-      align: 'center',
-      name: 'statusVal',
-      width: 150
-    },
-    {
-      label: '流程描述',
-      align: 'left',
-      name: 'DESCRIBTION',
-      minWidth: 600
-    },
-    { label: '流程名称', align: 'left', name: 'NAME', width: 130 },
-    { label: '完成环节', align: 'center', name: 'ACTIVITYNAME', width: 160 },
-    {
-      label: '完成时间',
-      align: 'center',
-      name: 'FINISH_TIME',
-      width: 190,
-      formatter(row: any, column: any, cellValue: any, index: number) {
-        if (cellValue) {
-          return formatDate(cellValue)
+  '90': {
+    column: [
+      {
+        label: '操作',
+        name: 'action',
+        width: 200,
+        frozen: true,
+        fixed: true
+      },
+      { label: '业务编号', align: 'center', name: 'CODE', width: 160, tooltip: true },
+      {
+        label: '环节完成情况',
+        align: 'center',
+        name: 'statusVal',
+        width: 150
+      },
+      {
+        label: '流程描述',
+        align: 'left',
+        name: 'DESCRIBTION',
+        minWidth: 600,
+        tooltip: true
+      },
+      { label: '流程名称', align: 'left', name: 'NAME', width: 130 },
+      { label: '完成环节', align: 'center', name: 'ACTIVITYNAME', width: 160 },
+      {
+        label: '完成时间',
+        align: 'center',
+        name: 'FINISH_TIME',
+        width: 190,
+        formatter(row: any, column: any, cellValue: any, index: number) {
+          if (cellValue) {
+            return formatDate(cellValue)
+          }
         }
+      },
+      {
+        label: '当前在办环节',
+        align: 'center',
+        name: 'currentActivityVal',
+        width: 200,
+        tooltip: true
       }
-    },
-    { label: '当前在办环节', align: 'center', name: 'currentActivityVal', width: 200 }
-  ],
+    ],
+    data: [],
+    ...pageParam
+  },
   //已退回
-  '40': [
-    {
-      label: '操作',
-      name: 'action',
-      width: 138,
-      frozen: true,
-      fixed: true
-    },
-    { label: '业务编号', align: 'center', name: 'CODE', width: 250 },
-    {
-      label: '退至环节完成情况',
-      align: 'center',
-      name: 'statusVal',
-      width: 160,
-      fixed: true
-    },
-    {
-      label: '流程描述',
-      align: 'left',
-      name: 'DESCRIBTION',
-      minWidth: 600
-    },
-    { label: '流程名称', align: 'left', name: 'NAME', width: 130 },
-    { label: '被退环节', align: 'center', name: 'BACTIVITYNAME', width: 160 },
-    { label: '退至环节', align: 'center', name: 'ACTIVITYNAME', width: 160 },
-    {
-      label: '退回时间',
-      align: 'center',
-      name: 'CREATE_TIME',
-      width: 190,
-      formatter(row: any, column: any, cellValue: any, index: number) {
-        if (cellValue) {
-          return formatDate(cellValue)
+  '40': {
+    column: [
+      {
+        label: '操作',
+        name: 'action',
+        width: 138,
+        frozen: true,
+        fixed: true
+      },
+      { label: '业务编号', align: 'center', name: 'CODE', width: 150, tooltip: true },
+      {
+        label: '退至环节完成情况',
+        align: 'center',
+        name: 'statusVal',
+        width: 260,
+        tooltip: true
+      },
+      {
+        label: '流程描述',
+        align: 'left',
+        name: 'DESCRIBTION',
+        minWidth: 560,
+        tooltip: true
+      },
+      { label: '流程名称', align: 'left', name: 'NAME', width: 130 },
+      { label: '被退环节', align: 'center', name: 'BACTIVITYNAME', width: 160 },
+      { label: '退至环节', align: 'center', name: 'ACTIVITYNAME', width: 160 },
+      {
+        label: '退回时间',
+        align: 'center',
+        name: 'CREATE_TIME',
+        width: 190,
+        formatter(row: any, column: any, cellValue: any, index: number) {
+          if (cellValue) {
+            return formatDate(cellValue)
+          }
         }
       }
-    }
-  ],
+    ],
+    data: [],
+    ...pageParam
+  },
   //挂起
-  '20': [
-    {
-      label: '操作',
-      name: 'action',
-      width: 228,
-      frozen: true,
-      fixed: true
-    },
-    {
-      label: '挂起环节(挂起人)',
-      align: 'center',
-      name: 'activityInsName',
-      width: 250,
-      fixed: true
-    },
-    { label: '业务编号', align: 'center', name: 'flowCode', width: 250 },
-    {
-      label: '流程描述',
-      align: 'left',
-      name: 'DESCRIBTION',
-      minWidth: 600
-    },
-    { label: '流程名称', align: 'left', name: 'flowName', width: 130 },
-    { label: '挂起时间', align: 'center', name: 'hangUpTime', width: 160 },
-    {
-      label: '解挂后截止时间',
-      align: 'center',
-      name: 'shouldFinishDate',
-      width: 190,
-      formatter(row: any, column: any, cellValue: any, index: number) {
-        if (cellValue) {
-          return formatDate(cellValue)
+  '20': {
+    column: [
+      {
+        label: '操作',
+        name: 'action',
+        width: 228,
+        frozen: true,
+        fixed: true
+      },
+      {
+        label: '挂起环节(挂起人)',
+        align: 'center',
+        name: 'activityInsName',
+        width: 250
+      },
+      { label: '业务编号', align: 'center', name: 'flowCode', width: 180, tooltip: true },
+      {
+        label: '流程描述',
+        align: 'left',
+        name: 'DESCRIBTION',
+        minWidth: 600,
+        tooltip: true
+      },
+      { label: '流程名称', align: 'left', name: 'flowName', width: 130 },
+      { label: '挂起时间', align: 'center', name: 'hangUpTime', width: 160 },
+      {
+        label: '解挂后截止时间',
+        align: 'center',
+        name: 'shouldFinishDate',
+        width: 190,
+        formatter(row: any, column: any, cellValue: any, index: number) {
+          if (cellValue) {
+            return formatDate(cellValue)
+          }
         }
       }
-    }
-  ],
+    ],
+    data: [],
+    ...pageParam
+  },
   //作废
-  '160': [
-    {
-      label: '操作',
-      name: 'action',
-      width: 320,
-      frozen: true,
-      fixed: true
-    },
-    { label: '作废人', align: 'center', name: 'nullyUserName', width: 200 },
-    { label: '业务编号', align: 'center', name: 'flowCode', width: 250 },
-    {
-      label: '流程描述',
-      align: 'left',
-      name: 'DESCRIBTION',
-      minWidth: 600
-    },
-    { label: '流程名称', align: 'left', name: 'flowName', width: 130 },
-    {
-      label: '作废时间',
-      align: 'center',
-      name: 'nullyTime',
-      width: 190,
-      formatter(row: any, column: any, cellValue: any, index: number) {
-        if (cellValue) {
-          return formatDate(cellValue)
+  '160': {
+    column: [
+      {
+        label: '操作',
+        name: 'action',
+        width: 320,
+        frozen: true,
+        fixed: true
+      },
+      { label: '作废人', align: 'center', name: 'nullyUserName', width: 200 },
+      { label: '业务编号', align: 'center', name: 'flowCode', width: 160, tooltip: true },
+      {
+        label: '流程描述',
+        align: 'left',
+        name: 'DESCRIBTION',
+        minWidth: 600,
+        tooltip: true
+      },
+      { label: '流程名称', align: 'left', name: 'flowName', width: 130 },
+      {
+        label: '作废时间',
+        align: 'center',
+        name: 'nullyTime',
+        width: 190,
+        formatter(row: any, column: any, cellValue: any, index: number) {
+          if (cellValue) {
+            return formatDate(cellValue)
+          }
+        }
+      }
+    ],
+    data: [],
+    ...pageParam
+  },
+  //抄送
+  '210': {
+    column: [
+      {
+        label: '操作',
+        name: 'action',
+        width: 320,
+        frozen: true,
+        fixed: true
+      },
+      { label: '流程状态', align: 'center', name: 'statusVal', width: 200 },
+      { label: '业务编号', align: 'center', name: 'code', width: 250 },
+      {
+        label: '流程描述',
+        align: 'left',
+        name: 'DESCRIBTION',
+        minWidth: 600
+      },
+      { label: '流程名称', align: 'left', name: 'name', width: 130 },
+      { label: '当前在办环节', align: 'left', name: 'currentActivityName', width: 130 },
+      { label: '抄送人', align: 'left', name: 'carbonCopyUserName', width: 130 },
+      {
+        label: '抄送时间',
+        align: 'center',
+        name: 'carbonCopyTime',
+        width: 190,
+        formatter(row: any, column: any, cellValue: any, index: number) {
+          if (cellValue) {
+            return formatDate(cellValue)
+          }
         }
       }
-    }
-  ]
+    ],
+    data: [],
+    ...pageParam
+  }
 }

+ 16 - 4
client/src/views/OaSystem/officeCenter/mainOfficeCenter/index.scss

@@ -32,6 +32,9 @@
   padding: 15px;
   width: 100%;
   height: 100%;
+  :deep(.el-table .cell, .el-table td.el-table__cell div){
+    font-size: 15px !important;
+  }
   > .header {
     display: flex;
     position: relative;
@@ -63,7 +66,7 @@
         font-size: 15px;
         cursor: pointer;
         &.active {
-          border-top: 2px solid #2e77e6;
+          border-top: 4px solid #2e77e6;
           border-left: 1px solid #dee0e3;
           border-right: 1px solid #dee0e3;
           color: #2e77e6;
@@ -75,8 +78,8 @@
             width: 100%;
             left: 0px;
             right: 0px;
-            height: 2px;
-            bottom: -1px;
+            height: 4px;
+            bottom: -2px;
             background-color: #fff;
             z-index: 999;
           }
@@ -86,13 +89,22 @@
   }
   > .table_box {
     width: 100%;
-    height: calc(100% - 64px);
+    height: calc(100% - 110px);
     display: flex;
     flex-direction: column;
     position: relative;
+    .text_hover:hover {
+      text-decoration: underline;
+    }
+    :deep(.el-dropdown){
+      .el-button {
+        background-color: #2e77e6;
+      }
+    }
     > .table {
       display: block;
       width: 100%;
+      height: 100%;
       flex-grow: 1;
       position: relative;
     }

+ 116 - 97
client/src/views/OaSystem/officeCenter/mainOfficeCenter/index.vue

@@ -3,7 +3,9 @@
     <div class="header">
       <el-popover placement="bottom-start" title="" trigger="hover" width="auto">
         <template #reference>
-          <el-button type="danger">新建流程</el-button>
+          <el-button type="danger" color="#eb6237" style="color: #fff">
+            <i class="fa fa-plus-circle" style="margin-right: 5px"></i>新建流程
+          </el-button>
         </template>
         <ul class="flowTemplateBox">
           <li v-for="(item, index) in flowTemplateTree" :key="index">
@@ -61,16 +63,23 @@
             />
           </el-form-item>
           <el-form-item>
-            <el-button type="primary" @click="searchHandle">查询</el-button>
+            <el-button type="primary" @click="searchHandle" color="#2e77e6" style="color: #fff">
+              查询
+            </el-button>
           </el-form-item>
         </el-form>
       </div>
     </div>
-    <div class="table_box">
-      <div class="table" ref="tableRef">
+    <div
+      class="table_box"
+      v-for="(tabItem, tabIndex) in tabList"
+      v-show="currentTab === tabItem['key']"
+      :key="tabIndex"
+    >
+      <div class="table">
         <el-table
-          :data="tableData"
-          :style="{ width: '100%', height: tableHeight + 'px' }"
+          :data="tabTableMapping[tabItem['key']]['data']"
+          :style="{ width: '100%', height: '100%' }"
           stripe
           :header-cell-style="{
             background: '#E5F0FB',
@@ -81,7 +90,7 @@
           @row-dblclick="(item) => openFlowHandle(item)"
         >
           <el-table-column
-            v-for="(item, index) in currentColumn"
+            v-for="(item, index) in tabTableMapping[tabItem['key']]['column']"
             :key="index"
             :label="item['label']"
             :prop="item['name']"
@@ -89,15 +98,32 @@
             :min-width="item['minWidth']"
             :fixed="item['fixed']"
             :formatter="item['formatter']"
+            :show-overflow-tooltip="item['tooltip']"
           >
-            <template v-if="item['name'] === 'statusVal'" #default="scope">
+            <template v-if="item['name'] === 'DESCRIBTION'" #default="scope">
+              <span class="text_hover" @click="openFlowHandle(scope.row)">
+                {{ scope.row[item['name']] }}
+              </span>
+            </template>
+            <template v-else-if="item['name'] === 'statusVal'" #default="scope">
               <span v-html="scope.row[item['name']]"></span>
             </template>
             <template v-else-if="item['name'] === 'action'" #default="scope">
+              <template v-if="['90', '40', '20', '160', '210'].includes(currentTab)">
+                <el-button
+                  type="primary"
+                  color="#2e77e6"
+                  style="color: #fff"
+                  @click="openFlowHandle(scope.row, currentTab === '160' ? '160' : null)"
+                >
+                  <i class="fa fa-search" style="margin-right: 5px"></i> 查看
+                </el-button>
+              </template>
               <template v-if="currentTab === '1'">
                 <el-dropdown
                   split-button
                   type="primary"
+                  trigger="click"
                   @click="flowApplyHandle(scope.row)"
                   @command="
                     (name) => {
@@ -105,7 +131,7 @@
                     }
                   "
                 >
-                  办理
+                  <i class="fa fa-pencil" style="margin-right: 5px"></i>办理
                   <template #dropdown>
                     <el-dropdown-menu>
                       <el-dropdown-item
@@ -120,24 +146,15 @@
                 </el-dropdown>
               </template>
               <template v-else-if="currentTab === '90'">
-                <el-button type="primary" icon="Search" @click="openFlowHandle(scope.row)">
-                  查看
-                </el-button>
                 <el-popconfirm title="是否确定追回?" @confirm="recoverActivityHandle(scope.row)">
                   <template #reference>
-                    <el-button type="warning" icon="RefreshRight"> 追回 </el-button>
+                    <el-button type="warning" color="#e07541" style="color: #fff">
+                      <i class="fa fa-gavel" style="margin-right: 5px"></i> 追回
+                    </el-button>
                   </template>
                 </el-popconfirm>
               </template>
-              <template v-else-if="currentTab === '40'">
-                <el-button type="primary" icon="Search" @click="openFlowHandle(scope.row)">
-                  查看
-                </el-button>
-              </template>
               <template v-else-if="currentTab === '20'">
-                <el-button type="primary" icon="Search" @click="openFlowHandle(scope.row)">
-                  查看
-                </el-button>
                 <el-popconfirm title="是否确定解挂?" @confirm="addIHangUpHandle(scope.row)">
                   <template #reference>
                     <el-button type="warning" icon="RefreshRight"> 解挂 </el-button>
@@ -145,22 +162,22 @@
                 </el-popconfirm>
               </template>
               <template v-else-if="currentTab === '160'">
-                <el-button type="primary" icon="Search" @click="openFlowHandle(scope.row, '160')">
-                  查看
-                </el-button>
                 <el-button
                   type="warning"
-                  icon="RefreshRight"
                   @click="recoverINullyApplyHandle(scope.row)"
+                  color="#f08551"
+                  style="color: #fff"
                 >
-                  恢复
+                  <i class="fa fa-reply" style="margin-right: 5px"></i>恢复
                 </el-button>
                 <el-popconfirm
                   title="是否确定彻底作废?"
                   @confirm="completelyVoidINullyApplyHandle(scope.row)"
                 >
                   <template #reference>
-                    <el-button type="warning" icon="RefreshRight"> 彻底作废 </el-button>
+                    <el-button type="warning" color="#ec5b57" style="color: #fff">
+                      <i class="fa fa-trash-o" style="margin-right: 5px"></i>彻底作废
+                    </el-button>
                   </template>
                 </el-popconfirm>
               </template>
@@ -170,11 +187,11 @@
       </div>
       <div class="pageBox">
         <el-pagination
-          v-model:current-page="sendData.page"
-          :page-size="sendData.rows"
+          v-model:current-page="tabTableMapping[tabItem['key']]['page']"
+          :page-size="tabTableMapping[tabItem['key']]['rows']"
           background
           layout="total, prev, pager, next, jumper"
-          :total="records"
+          :total="tabTableMapping[tabItem['key']]['records']"
           @current-change="handleCurrentChange"
         />
       </div>
@@ -262,6 +279,7 @@ import {
   getFlowTemplateTreeDataByUser,
   getFlowTemplateTree,
   recoverActivity,
+  officeCenterModule,
   addIHangUp
 } from '@/api/oa/workflow'
 import subscribe from '@/utils/Subscribe'
@@ -276,12 +294,9 @@ defineOptions({
 })
 const message = useMessage()
 const currentTab = ref<string>('1')
-const currentColumn = ref<any[]>(TabColumns[currentTab.value])
-const tableData = ref<any[]>([])
-const records = ref<number>(0)
 const sendData = reactive({
   _search: false,
-  status: 1,
+  status: '1',
   flowTemIds: [],
   searchVal: '',
   isMobile: false,
@@ -292,89 +307,98 @@ const sendData = reactive({
   rows: 18
 })
 const cellClassNameHandle = (item) => {
-  if (sendData['status'] !== 1) return 'rowClass'
+  if (sendData['status'] !== '1') return 'rowClass'
   if (!item.row['RECEIVE_TIME']) {
     return 'fontWeight'
   }
   return 'rowClass'
 }
-/**
- * 初始化流程列表
- */
-const queryHandlerCaseCenterList = () => {
-  getHandlerCaseCenterList(sendData).then((result: any) => {
-    if (result.rows && result.rows.length > 0) {
-      result.rows.forEach((item) => {
-        item['btnArrJson'] = item['btnArrJson'] ? JSON.parse(item['btnArrJson']) : []
-      })
-    }
-    tableData.value = result.rows
-    records.value = result.records
-  })
-}
-queryHandlerCaseCenterList()
-const handleCurrentChange = (pageNo: number) => {
-  sendData['page'] = pageNo
-  queryHandlerCaseCenterList()
+const keyValMap = {
+  '1': 'NORMAL',
+  '90': 'FINISH',
+  '40': 'CALLBACK',
+  '20': 'HANG_UP',
+  '160': 'OBSOLETE'
 }
-/**
- *  tab表单汇总统计
- */
 type TabType = {
   name: string
   key: string
   value: number
+  column?: any[]
+  data?: any[]
 }
+const tabList = ref<TabType[]>([])
 
-const tabList = reactive<TabType[]>([
-  {
-    name: '待办',
-    key: '1',
-    value: 0
-  },
-  {
-    name: '已完成',
-    key: '90',
-    value: 0
-  },
-  {
-    name: '已退回',
-    key: '40',
-    value: 0
-  },
-  {
-    name: '挂起',
-    key: '20',
-    value: 0
-  },
-  {
-    name: '作废',
-    key: '160',
-    value: 0
+type TabTableType = {
+  column: any[]
+  data: any[]
+  page: number
+  records: number
+  rows: number
+}
+const tabTableMapping = ref<{
+  [key: string]: TabTableType
+}>(TabColumns)
+/**
+ *  tab初始化和角标汇总统计
+ */
+const queryOfficeCenterModule = async () => {
+  const result = await officeCenterModule()
+  const moduleList = result['moduleList']
+  if (moduleList && moduleList.length > 0) {
+    tabList.value = moduleList.map((item) => {
+      tabTableMapping.value[item['status']]['data'] = []
+      return {
+        name: item['name'],
+        key: item['status'],
+        value: 0
+      }
+    })
+    tabList.value.unshift({
+      name: '待办',
+      key: '1',
+      value: 0
+    })
   }
-])
-const queryHandlerCaseCenterCount = () => {
+  queryHandlerCaseCenterList()
+}
+const queryHandlerCaseCenterCount = async () => {
+  await queryOfficeCenterModule()
   const formData = new FormData()
   const keys = Object.keys(sendData)
   for (let key of keys) {
     formData.set(key, sendData[key])
   }
   getHandlerCaseCenterCount(formData).then((result) => {
-    tabList[0]['value'] = result['NORMAL']
-    tabList[1]['value'] = result['FINISH']
-    tabList[2]['value'] = result['CALLBACK']
-    tabList[3]['value'] = result['HANG_UP']
-    tabList[4]['value'] = result['OBSOLETE']
+    tabList.value.forEach((item) => {
+      item['value'] = result[keyValMap[item['key']]]
+    })
   })
 }
 queryHandlerCaseCenterCount()
+/**
+ * 初始化流程列表
+ */
+const queryHandlerCaseCenterList = () => {
+  getHandlerCaseCenterList(sendData).then((result: any) => {
+    if (result.rows && result.rows.length > 0) {
+      result.rows.forEach((item) => {
+        item['btnArrJson'] = item['btnArrJson'] ? JSON.parse(item['btnArrJson']) : []
+      })
+    }
+    tabTableMapping.value[sendData['status']]['data'] = result.rows
+    tabTableMapping.value[sendData['status']]['records'] = result.records
+  })
+}
+const handleCurrentChange = (pageNo: number) => {
+  sendData['page'] = tabTableMapping.value[sendData['status']]['page'] = pageNo
+  queryHandlerCaseCenterList()
+}
 //切换tab流程状态选项卡
 const switchTabHandle = (item) => {
-  currentTab.value = item['key']
-  currentColumn.value = TabColumns[currentTab.value]
+  sendData['status'] = currentTab.value = item['key']
+  sendData['page'] = tabTableMapping.value[item['key']]['page']
   queryFlowTemplateTreeDataByUser(item['key'])
-  sendData['status'] = item['key']
-  sendData['page'] = 1
   queryHandlerCaseCenterList()
 }
 
@@ -498,11 +522,6 @@ const addIHangUpHandle = (item: any) => {
     }
   })
 }
-const tableRef: any = ref(null)
-const tableHeight: any = ref(0)
-onMounted(() => {
-  tableHeight.value = tableRef.value.clientHeight
-})
 </script>
 
 <style lang="scss" scoped>

+ 508 - 0
client/src/views/OaSystem/officeCenter/mainOfficeCenter/index222.vue

@@ -0,0 +1,508 @@
+<template>
+  <div class="mainOfficeCenter">
+    <div class="header">
+      <el-popover placement="bottom-start" title="" trigger="hover" width="auto">
+        <template #reference>
+          <el-button type="danger">新建流程</el-button>
+        </template>
+        <ul class="flowTemplateBox">
+          <li v-for="(item, index) in flowTemplateTree" :key="index">
+            <span class="title">{{ item['name'] }}</span>
+            <ul v-for="(cItem, cIndex) in item['children']" :key="cIndex">
+              <li
+                @click="addTProcessHandle(cItem)"
+                v-if="
+                  [
+                    '开票申请',
+                    '分包申请',
+                    '外包申请',
+                    '合同签订',
+                    '项目验收',
+                    '项目结项',
+                    '分包合同签订',
+                    '外包合同签订'
+                  ].indexOf(cItem['name']) === -1
+                "
+                >{{ cItem['name'] }}</li
+              >
+            </ul>
+          </li>
+        </ul>
+      </el-popover>
+      <ul class="tabs">
+        <li
+          v-for="item in tabList"
+          :key="item['key']"
+          :class="{ active: currentTab === item['key'] }"
+          @click="switchTabHandle(item)"
+        >
+          {{ item['name'] }}({{ item['value'] }})
+        </li>
+      </ul>
+      <div class="search">
+        <el-form :inline="true" :model="searchForm" class="demo-form-inline">
+          <el-form-item label="流程名称">
+            <el-tree-select
+              :data="flowTemplates"
+              :props="defaultProps"
+              :render-after-expand="false"
+              ref="treeRef"
+              style="width: 240px"
+              default-expand-all
+              show-checkbox
+            />
+          </el-form-item>
+          <el-form-item label="">
+            <el-input
+              type="text"
+              style="width: 280px"
+              v-model="sendData['searchVal']"
+              placeholder="业务编号/流程描述/流程名称"
+            />
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="searchHandle">查询</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+    </div>
+    <div class="table_box">
+      <div class="table" ref="tableRef">
+        <el-table
+          :data="tableData"
+          :style="{ width: '100%', height: tableHeight + 'px' }"
+          stripe
+          :header-cell-style="{
+            background: '#E5F0FB',
+            color: '#233755',
+            height: '50px'
+          }"
+          :cell-class-name="cellClassNameHandle"
+          @row-dblclick="(item) => openFlowHandle(item)"
+        >
+          <el-table-column
+            v-for="(item, index) in currentColumn"
+            :key="index"
+            :label="item['label']"
+            :prop="item['name']"
+            :width="item['width']"
+            :min-width="item['minWidth']"
+            :fixed="item['fixed']"
+            :formatter="item['formatter']"
+          >
+            <template v-if="item['name'] === 'statusVal'" #default="scope">
+              <span v-html="scope.row[item['name']]"></span>
+            </template>
+            <template v-else-if="item['name'] === 'action'" #default="scope">
+              <template v-if="currentTab === '1'">
+                <el-dropdown
+                  split-button
+                  type="primary"
+                  @click="flowApplyHandle(scope.row)"
+                  @command="
+                    (name) => {
+                      commandHandle(name, scope.row)
+                    }
+                  "
+                >
+                  办理
+                  <template #dropdown>
+                    <el-dropdown-menu>
+                      <el-dropdown-item
+                        v-for="(bItem, bIndex) in scope.row.btnArrJson"
+                        :key="bIndex"
+                        :disabled="!bItem['iEnable']"
+                        :command="bItem['value']"
+                        >{{ bItem['value'] }}</el-dropdown-item
+                      >
+                    </el-dropdown-menu>
+                  </template>
+                </el-dropdown>
+              </template>
+              <template v-else-if="currentTab === '90'">
+                <el-button type="primary" icon="Search" @click="openFlowHandle(scope.row)">
+                  查看
+                </el-button>
+                <el-popconfirm title="是否确定追回?" @confirm="recoverActivityHandle(scope.row)">
+                  <template #reference>
+                    <el-button type="warning" icon="RefreshRight"> 追回 </el-button>
+                  </template>
+                </el-popconfirm>
+              </template>
+              <template v-else-if="currentTab === '40'">
+                <el-button type="primary" icon="Search" @click="openFlowHandle(scope.row)">
+                  查看
+                </el-button>
+              </template>
+              <template v-else-if="currentTab === '20'">
+                <el-button type="primary" icon="Search" @click="openFlowHandle(scope.row)">
+                  查看
+                </el-button>
+                <el-popconfirm title="是否确定解挂?" @confirm="addIHangUpHandle(scope.row)">
+                  <template #reference>
+                    <el-button type="warning" icon="RefreshRight"> 解挂 </el-button>
+                  </template>
+                </el-popconfirm>
+              </template>
+              <template v-else-if="currentTab === '160'">
+                <el-button type="primary" icon="Search" @click="openFlowHandle(scope.row, '160')">
+                  查看
+                </el-button>
+                <el-button
+                  type="warning"
+                  icon="RefreshRight"
+                  @click="recoverINullyApplyHandle(scope.row)"
+                >
+                  恢复
+                </el-button>
+                <el-popconfirm
+                  title="是否确定彻底作废?"
+                  @confirm="completelyVoidINullyApplyHandle(scope.row)"
+                >
+                  <template #reference>
+                    <el-button type="warning" icon="RefreshRight"> 彻底作废 </el-button>
+                  </template>
+                </el-popconfirm>
+              </template>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <div class="pageBox">
+        <el-pagination
+          v-model:current-page="sendData.page"
+          :page-size="sendData.rows"
+          background
+          layout="total, prev, pager, next, jumper"
+          :total="records"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+    </div>
+    <!-- 作废表单Dialog -->
+    <el-dialog v-model="nullyApplyVisible" :title="nullyApplyTitle" width="40%">
+      <el-form v-model="inullyApplyForm" label-width="100px">
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="申请人:">
+              <el-input v-model="inullyApplyForm.nickname" disabled />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="申请时间:">
+              <el-input v-model="inullyApplyForm.nullyApplyTime" disabled />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="24">
+            <el-form-item label="申请原因:">
+              <el-input
+                type="textarea"
+                rows="5"
+                style="width: 100%"
+                v-model="inullyApplyForm.nullyReason"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="nullyApplyVisible = false">关闭</el-button>
+          <el-button type="primary" @click="nullyApplySubmit">提交</el-button>
+        </div>
+      </template>
+    </el-dialog>
+    <!-- 退回表单Dialog -->
+    <el-dialog v-model="callbackVisible" title="退回" width="40%">
+      <el-form v-model="callbackForm" label-width="100px">
+        <div class="callback_header">
+          <span class="title">{{ callbackTitle }}</span>
+          <ul class="callback_process">
+            <li
+              v-for="(item, index) in callbacks"
+              :key="index"
+              :class="{ active: index === 0 }"
+              :icon="Edit"
+            >
+              <el-icon style="margin-right: 2px">
+                <DArrowRight />
+              </el-icon>
+              <span>{{ item['name'] }}</span>
+            </li>
+          </ul>
+        </div>
+        <div class="callback_header">
+          <span class="title">请填写退回原因</span>
+          <el-input
+            type="textarea"
+            rows="5"
+            style="width: 100%"
+            v-model="callbackForm.callbackRemark"
+          />
+        </div>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="callbackVisible = false">关闭</el-button>
+          <el-button type="primary" @click="callbackSumbit">提交</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { Edit } from '@element-plus/icons-vue'
+import { defaultProps, handleTree } from '@/utils/tree'
+import {
+  getHandlerCaseCenterList,
+  getHandlerCaseCenterCount,
+  getFlowTemplateTreeDataByUser,
+  getFlowTemplateTree,
+  recoverActivity,
+  officeCenterModule,
+  addIHangUp
+} from '@/api/oa/workflow'
+import subscribe from '@/utils/Subscribe'
+import { TabColumns } from './common'
+import { InullyApplyEnum, InullyApplyEnumType } from './inullyApply'
+import useLookAndApplyFlow from './lookAndApplyFlow'
+import useInullyApply from './inullyApply'
+import useCallback from './callback'
+
+defineOptions({
+  name: 'MainOfficeCenter2'
+})
+const message = useMessage()
+const currentTab = ref<string>()
+const currentColumn = ref<any[]>()
+const tableData = ref<any[]>([])
+const records = ref<number>(0)
+const sendData = reactive({
+  _search: false,
+  status: 1,
+  flowTemIds: [],
+  searchVal: '',
+  isMobile: false,
+  queryMethod: 0,
+  toSystemId: '',
+  excludedSystemId: '',
+  page: 1,
+  rows: 18
+})
+const cellClassNameHandle = (item) => {
+  if (sendData['status'] !== 1) return 'rowClass'
+  if (!item.row['RECEIVE_TIME']) {
+    return 'fontWeight'
+  }
+  return 'rowClass'
+}
+/**
+ * 初始化流程列表
+ */
+const isLoading = ref<boolean>(false)
+const queryHandlerCaseCenterList = () => {
+  isLoading.value = true
+  getHandlerCaseCenterList(sendData).then((result: any) => {
+    if (result.rows && result.rows.length > 0) {
+      result.rows.forEach((item) => {
+        item['btnArrJson'] = item['btnArrJson'] ? JSON.parse(item['btnArrJson']) : []
+      })
+    }
+    isLoading.value = false
+    tableData.value = result.rows
+    records.value = result.records
+  })
+}
+queryHandlerCaseCenterList()
+const handleCurrentChange = (pageNo: number) => {
+  sendData['page'] = pageNo
+  queryHandlerCaseCenterList()
+}
+/**
+ *  tab初始化和角标汇总统计
+ */
+const keyValMap = {
+  '1': 'NORMAL',
+  '90': 'FINISH',
+  '40': 'CALLBACK',
+  '20': 'HANG_UP',
+  '160': 'OBSOLETE'
+}
+type TabType = {
+  name: string
+  key: string
+  value: number
+}
+const tabList = ref<TabType[]>([])
+const queryOfficeCenterModule = async () => {
+  const result = await officeCenterModule()
+  const moduleList = result['moduleList']
+  if (moduleList && moduleList.length > 0) {
+    currentTab.value = moduleList[0]['status']
+    currentColumn.value = TabColumns[moduleList[0]['status']]
+    tabList.value = moduleList.map((item) => {
+      return {
+        name: item['name'],
+        key: item['status'],
+        value: 0
+      }
+    })
+  }
+}
+const queryHandlerCaseCenterCount = async () => {
+  await queryOfficeCenterModule()
+  const formData = new FormData()
+  const keys = Object.keys(sendData)
+  for (let key of keys) {
+    formData.set(key, sendData[key])
+  }
+  getHandlerCaseCenterCount(formData).then((result) => {
+    tabList.value.forEach((item) => {
+      item['value'] = result[keyValMap[item['key']]]
+    })
+  })
+}
+queryHandlerCaseCenterCount()
+//切换tab流程状态选项卡
+const switchTabHandle = (item) => {
+  currentTab.value = item['key']
+  currentColumn.value = TabColumns[currentTab.value]
+  queryFlowTemplateTreeDataByUser(item['key'])
+  sendData['status'] = item['key']
+  sendData['page'] = 1
+  queryHandlerCaseCenterList()
+}
+
+const initHandleCaseCenterData = () => {
+  queryHandlerCaseCenterCount()
+  queryHandlerCaseCenterList()
+}
+
+subscribe.on('updateHandleCenterEvent', () => {
+  //同步更新办件中心角标
+  initHandleCaseCenterData()
+})
+/**
+ * 初始化新建流程中流程模板Tree
+ */
+const flowTemplateTree = ref<any>()
+const initFlowTemplateTree = () => {
+  getFlowTemplateTree().then((result) => {
+    flowTemplateTree.value = result.data[0]['children']
+  })
+}
+initFlowTemplateTree()
+
+/**
+ * 初始化搜索条件中流程名称Tree结构数据
+ */
+const flowTemplates = ref<any[]>([])
+const queryFlowTemplateTreeDataByUser = (officeStatus = '1') => {
+  const formData = new FormData()
+  formData.append('isRight', '0')
+  formData.append('toSystemId', '') //后台获取
+  formData.append('excludedSystemId', '') //后台获取
+  formData.append('officeStatus', officeStatus)
+  getFlowTemplateTreeDataByUser(formData).then((result: any) => {
+    flowTemplates.value = handleTree(result, 'id', 'pid')
+  })
+}
+queryFlowTemplateTreeDataByUser()
+const searchForm = ref({
+  name: ''
+})
+const treeRef = ref()
+const searchHandle = () => {
+  sendData.flowTemIds = treeRef.value.getCheckedNodes(false).map((item) => item['id'])
+  handleCurrentChange(1)
+}
+const { addTProcessHandle, openFlowHandle, flowApplyHandle } = useLookAndApplyFlow()
+
+const commandHandle = (name, item) => {
+  if (name === '作废') {
+    cancelFlow(item)
+  } else if (name === '退回') {
+    callbackActivity(item)
+  }
+  return
+}
+/**
+ * 初始化作废Hook
+ */
+const {
+  nullyApplyTitle,
+  nullyApplyVisible,
+  inullyApplyForm,
+  cancelFlow,
+  nullyApplySubmit,
+  recoverINullyApplyHandle,
+  completelyVoidINullyApplyHandle
+} = useInullyApply({
+  success: (type: InullyApplyEnumType) => {
+    message.success(
+      type === InullyApplyEnum.Recover
+        ? '恢复作废成功!'
+        : type === InullyApplyEnum.Nully
+        ? '作废成功!'
+        : '彻底作废成功!'
+    )
+    initHandleCaseCenterData()
+  }
+})
+/**
+ * 初始化退回Hook
+ */
+const {
+  callbackVisible,
+  callbackTitle,
+  callbacks,
+  callbackForm,
+  callbackActivity,
+  callbackSumbit
+} = useCallback({
+  success: (msg: string) => {
+    message.success(msg)
+    initHandleCaseCenterData()
+  }
+})
+/***
+ * 追回
+ */
+const recoverActivityHandle = (item: any) => {
+  recoverActivity({
+    activityInstanceId: item['ACTIVITYINSID'],
+    participantId: item['PARTICIPANTID']
+  }).then((res) => {
+    if (res) {
+      message.success('追回成功!')
+      initHandleCaseCenterData()
+    }
+  })
+}
+
+/***
+ * 解挂
+ */
+const addIHangUpHandle = (item: any) => {
+  addIHangUp({
+    activityInstanceId: item['ACTIVITYINSID'],
+    isRecover: 1
+  }).then((res) => {
+    if (res) {
+      message.success('解挂成功!')
+    }
+  })
+}
+const tableRef: any = ref(null)
+const tableHeight: any = ref(0)
+onMounted(() => {
+  tableHeight.value = tableRef.value.clientHeight
+})
+</script>
+
+<style lang="scss" scoped>
+@import './index.scss';
+</style>

+ 1 - 1
client/src/views/OaSystem/officeCenter/mainOfficeCenter/lookAndApplyFlow.ts

@@ -81,7 +81,7 @@ const useLookAndApplyFlow = () => {
     const saveAndGetUrlReqParam = {
       activityInsId: item['ACTIVITYINSID'],
       flowInsId: item['FLOWINSID'],
-      particiPantId: item['PARTICIPANTID'],
+      participantId: item['PARTICIPANTID'],
       status: item['STATUS'],
       userId: '',
       isView: false

+ 4 - 2
client/src/views/OaSystem/projectCenter/projectDetail/projectDetail.vue

@@ -59,7 +59,8 @@
             v-if="
               projectPermis.projectPermisState.all ||
               projectPermis.projectPermisState.xsLeader ||
-              projectPermis.projectPermisState.xmLeader
+              projectPermis.projectPermisState.xmLeader ||
+              projectPermis.projectPermisState.projectMember
             "
             v-show="![2, 3].includes(projectDetail?.['xmzt'])"
             @click="handleStartSubcontract"
@@ -70,7 +71,8 @@
             v-if="
               projectPermis.projectPermisState.all ||
               projectPermis.projectPermisState.xsLeader ||
-              projectPermis.projectPermisState.xmLeader
+              projectPermis.projectPermisState.xmLeader ||
+              projectPermis.projectPermisState.projectMember
             "
             v-show="![2, 3].includes(projectDetail?.['xmzt'])"
             @click="handleStartOutsourcing"

+ 2 - 2
zjugis-workflow/src/main/resources/mapper/oracle/IFlowInstanceMapper.xml

@@ -352,7 +352,7 @@
         ) P ON R.ID = P.SEND_BACK_RECORD_ID
         )T
         INNER JOIN I_ACTIVITY_INSTANCE T1 ON T.BACK_TO_ACTIVITY_ID = T1.ID
-        INNER JOIN I_FLOW_INSTANCE T2 ON T1.FLOW_INSTANCE_ID = T2.ID
+        INNER JOIN I_FLOW_INSTANCE T2 ON T1.FLOW_INSTANCE_ID = T2.ID AND T1.I_END = 0
         <if test="p.flowTemIds != null and p.flowTemIds.size()>0">
             INNER JOIN T_FLOW_TEMPLATE_VERSION T3 on T2.FLOW_TEMPLATE_VERSION_ID= T3.ID
         </if>
@@ -1802,7 +1802,7 @@
             ) P ON R.ID = P.SEND_BACK_RECORD_ID
             )T
             INNER JOIN I_ACTIVITY_INSTANCE T1 ON T.BACK_TO_ACTIVITY_ID = T1.ID
-            INNER JOIN I_FLOW_INSTANCE T2 ON T1.FLOW_INSTANCE_ID = T2.ID
+            INNER JOIN I_FLOW_INSTANCE T2 ON T1.FLOW_INSTANCE_ID = T2.ID AND T2.I_END = 0
             <if test="p.flowTemIds != null and p.flowTemIds.size()>0">
                 INNER JOIN T_FLOW_TEMPLATE_VERSION T3 on T2.FLOW_TEMPLATE_VERSION_ID= T3.ID
             </if>

Някои файлове не бяха показани, защото твърде много файлове са промени