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

依斯倍环保加的七个表

Lijy преди 10 месеца
родител
ревизия
ce1c11f43d

+ 5 - 0
fhKeeper/formulahousekeeper/timesheet/src/components/echartsEchar.vue

@@ -53,6 +53,11 @@ export default {
       return new Date().getTime();
     },
   },
+  beforeDestroy() {
+    if (this.myChart) {
+      this.myChart.dispose();
+    }
+  }
 };
 </script>
 

+ 160 - 0
fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/echartsData.js

@@ -84,4 +84,164 @@ export function getGroupConsumption(nameList = [], actualPlan = [], actualSupple
       },
     ],
   }
+}
+
+export function getPieEchartOption(titleName, datas = []) {
+  return {
+    title: {
+      text: titleName,
+      left: 'center',
+      top: 40
+    },
+    tooltip: {
+      trigger: 'item'
+    },
+    legend: {
+      orient: 'vertical',
+      left: 'left'
+    },
+    series: [
+      {
+        name: titleName,
+        type: 'pie',
+        radius: '50%',
+        data: datas,
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 10,
+            shadowOffsetX: 0,
+            shadowColor: 'rgba(0, 0, 0, 0.5)'
+          }
+        }
+      }
+    ]
+  }
+}
+
+export function debounce(func, delay) {
+  let timer;
+  return function() {
+    const context = this;
+    const args = arguments;
+    clearTimeout(timer);
+    timer = setTimeout(() => {
+      func.apply(context, args);
+    }, delay);
+  };
+}
+
+export const fixedTaskGrouping = ['工程部现场安装施工', '工程部配合调试', '生产部电气', '生产部车间', '研发部BIM设计', '研发部工艺设计', '研发部工艺调试验收', '研发部电气设计', '研发部电气调试验收', '研发部结构设计']
+
+// 固定分组数据
+export const fixedGrouping = {
+  technology: { // 研发工艺
+    tableFileds: [
+      { label: '方案设计', filed: '方案设计' },
+      { label: '研发部', filed: '研发部' },
+      { label: '研发部工艺调试', filed: '研发部工艺调试' },
+      { label: '研发部工艺调试验收', filed: '研发部工艺调试验收' },
+      { label: '研发部工艺设计', filed: '研发部工艺设计' },
+    ],
+    tabPicFileds: [
+      { label: '方案设计', filed: '方案设计', title: '报价项目占比' },
+      { label: '研发部', filed: '研发部', title: '行政项目占比' },
+      { label: '研发部工艺调试', filed: '研发部工艺调试', title: '项目设计占比' }
+    ],
+    name: '研发工艺',
+    tableKey: 1001
+  },
+  bim: { // 研发BIM
+    tableFileds: [
+      { label: '研发部', filed: '研发部' },
+      { label: '研发部BIM设计', filed: '研发部BIM设计' },
+    ],
+    tabPicFileds: [
+      { label: '研发部', filed: '研发部', title: 'BIM行政工时占比' },
+      { label: '研发部BIM设计', filed: '研发部BIM设计', title: 'BIM设计项目占比' }
+    ],
+    name: '研发BIM',
+    tableKey: 1002,
+  },
+  structure: { // 研发结构
+    tableFileds: [
+      { label: '研发部', filed: '研发部' },
+      { label: '研发部结构设计', filed: '研发部结构设计' },
+    ],
+    tabPicFileds: [
+      { label: '研发部', filed: '研发部', title: '研发行政工时占比' },
+      { label: '研发部结构设计', filed: '研发部结构设计', title: '结构设计项目占比' }
+    ],
+    name: '研发结构',
+    tableKey: 1003
+  },
+  electrical: { // 研发电气
+    tableFileds: [
+      { label: '研发部', filed: '研发部' },
+      { label: '研发部电气调试验收', filed: '研发电气调试验收' },
+      { label: '研发部电气设计', filed: '研发部电气设计' },
+      { label: '研发部售后', filed: '研发部售后' },
+    ],
+    tabPicFileds: [
+      { label: '研发部', filed: '研发部', title: '电气行政工时占比' },
+      { label: '研发部电气设计', filed: '研发部电气设计', title: '电气设计项目占比' },
+      { label: '研发部电气调试验收', filed: '研发部电气调试验收', title: '电气调试项目占比' }
+    ],
+    name: '研发电气',
+    tableKey: 1004
+  },
+  shakedown: { // 研发调试
+    tableFileds: [
+      { label: '研发部', filed: '研发部' },
+      { label: '研发部工艺调试', filed: '研发部工艺调试' },
+      { label: '研发部工艺调试验收', filed: '研发部工艺调试验收' },
+      { label: '研发部工艺设计', filed: '研发部工艺设计' },
+      { label: '研发部售后', filed: '研发部售后' },
+      { label: '研发部运维', filed: '研发部运维' },
+    ],
+    tabPicFileds: [
+      { label: '研发部', filed: '研发部', title: '研发调试行政工时占比' },
+      { label: '研发部工艺调试验收', filed: '研发部工艺调试验收', title: '调试项目占比' },
+      { label: '研发部售后', filed: '研发部售后', title: '售后项目占比' }
+    ],
+    name: '研发调试',
+    tableKey: 1005
+  },
+  produce: { // 生产部
+    tableFileds: [
+      { label: '生产部', filed: '生产部' },
+      { label: '生产部车间', filed: '生产部车间' },
+      { label: '生产部电气', filed: '生产部电气' },
+    ],
+    tabPicFileds: [
+      { label: '研发部', filed: '研发部', title: '生产部行政工时占比' },
+      { label: '生产部车间,生产部电气', filed: '生产部车间,生产部电气', title: '生产项目占比' }
+    ],
+    name: '生产部',
+    tableKey: 1006
+  },
+  engineering: { // 工程部
+    tableFileds: [
+      { label: '工程部', filed: '工程部' },
+      { label: '工程部配合调试', filed: '工程部配合调试' },
+      { label: '工程部配合运维', filed: '工程部配合运维' },
+      { label: '工程部售后', filed: '工程部售后' },
+      { label: '工程部现场安装施工', filed: '工程部现场安装施工' },
+      { label: '生产部', filed: '生产部' },
+      { label: '生产部车间', filed: '生产部车间' },
+      { label: '生产部电气', filed: '生产部电气' },
+      { label: '项目阶段', filed: '项目阶段' },
+      { label: '研发部工艺调试验收', filed: '研发部工艺调试验收' },
+      { label: '研发部运维', filed: '研发部运维' },
+    ],
+    tabPicFileds: [
+      { label: '工程部', filed: '工程部', title: '工程部行政工时占比' },
+      { label: '工程部配合调试', filed: '工程部配合调试', title: '配合调试工时占比' },
+      { label: '工程部售后', filed: '工程部售后', title: '售后占比' },
+      { label: '工程部配合运维', filed: '工程部配合运维', title: '运维占比' },
+      { label: '工程部现场安装施工', filed: '工程部现场安装施工', title: '施工占比' },
+      { label: '生产部,生产部车间,生产部电气', filed: '生产部,生产部车间,生产部电气', title: '配合生产占比' },
+    ],
+    name: '工程部',
+    tableKey: 1007
+  },
 }

+ 180 - 45
fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue

@@ -121,7 +121,7 @@
         <template v-if="ins == 24">
           <el-radio-group v-model="tabPosition" size="small" @input="getGroupConsumptionData">
             <el-radio-button label="0">表格</el-radio-button>
-            <el-radio-button label="1">柱状图</el-radio-button>
+            <el-radio-button label="1">图</el-radio-button>
           </el-radio-group>
         </template>
           
@@ -139,7 +139,7 @@
           </el-option>
         </el-select>
 
-        <el-select v-if="ins == 24 && tabPosition == 1" v-model="groupConsumptionName" placeholder="请选择任务分组" clearable filterable size="small" @change="getList(true)" multiple collapse-tags style="margin-left:10px; width: 250px">
+        <el-select v-if="ins == 24 && tabPosition == 1" v-model="groupConsumptionName" placeholder="请选择任务分组" :clearable="tabsType == 'all' ? true : false" filterable size="small" @change="getList(true)" :multiple="tabsType == 'all' ? true : false" collapse-tags style="margin-left:10px; width: 250px" :key="groupTaskKey">
           <el-option v-for="(item, index) in groupConsumptionList" :key="item.id" :label="item" :value="item"> </el-option>
         </el-select>
 
@@ -1170,39 +1170,115 @@
               <el-table-column align="center" prop="projectCode" :label="$t('Itemno')"></el-table-column>
               <el-table-column align="center" prop="residueTime" :label="$t('shengYuGongShiH')" width="150"></el-table-column>
             </el-table>
+            <div class="packetConsumption" v-if="ins == 24" :style="`height:${tabPosition == 0 ? tableHeight : tableHeight + 50}px`" v-loading="listLoading">
+              <el-tabs v-model="tabsType" :tab-position="'left'" @tab-click="handleClick" 
+              :style="`height: 100%;width: 100%;margin-right: 20px`">
+                <el-tab-pane name="all" label="分组耗用表">
+                  <PackTables :datas="{ 
+                    type: tabsType, 
+                    tabPosition: tabPosition,
+                    list: isbeCustomReport.consumptionSchedule,
+                    height: tableHeight,
+                    listArr1,
+                    listArr2,
+                    listArr3,
+                    params: {
+                      groupNames: groupConsumptionName,
+                      projectIds: proJuctId,
+                      pageIndex: page,
+                      pageSize: size,
+                      dataTime: rangeDatas
+                    },
+                    echartsData: groupConsumptionOption
+                  }" />
+                </el-tab-pane>
+                <el-tab-pane name="technology" label="研发工艺">
+                  <PackTables :datas="{ type: tabsType, regular: 'technology', height: tableHeight, tabPosition, params: {
+                    projectIds: proJuctId,
+                    groupNames: groupConsumptionName,
+                    dataTime: rangeDatas
+                  } }" />
+                </el-tab-pane>
+                <el-tab-pane name="bim" label="研发BIM">
+                  <PackTables :datas="{ type: tabsType, regular: 'bim', height: tableHeight, tabPosition, params: {
+                    projectIds: proJuctId,
+                    groupNames: groupConsumptionName,
+                    dataTime: rangeDatas
+                  } }" />
+                </el-tab-pane>
+                <el-tab-pane name="structure" label="研发结构">
+                  <PackTables :datas="{ type: tabsType, regular: 'structure', height: tableHeight, tabPosition, params: {
+                    projectIds: proJuctId,
+                    groupNames: groupConsumptionName,
+                    dataTime: rangeDatas
+                  } }" />
+                </el-tab-pane>
+                <el-tab-pane name="electrical" label="研发电气">
+                  <PackTables :datas="{ type: tabsType, regular: 'electrical', height: tableHeight, tabPosition, params: {
+                    projectIds: proJuctId,
+                    groupNames: groupConsumptionName,
+                    dataTime: rangeDatas
+                  } }" />
+                </el-tab-pane>
+                <el-tab-pane name="shakedown" label="研发调试">
+                  <PackTables :datas="{ type: tabsType, regular: 'shakedown', height: tableHeight, tabPosition, params: {
+                    projectIds: proJuctId,
+                    groupNames: groupConsumptionName,
+                    dataTime: rangeDatas
+                  } }" />
+                </el-tab-pane>
+                <el-tab-pane name="produce" label="生产部">
+                  <PackTables :datas="{ type: tabsType, regular: 'produce', height: tableHeight, tabPosition, params: {
+                    projectIds: proJuctId,
+                    groupNames: groupConsumptionName,
+                    dataTime: rangeDatas
+                  } }" />
+                </el-tab-pane>
+                <el-tab-pane name="engineering" label="工程部">
+                  <PackTables :datas="{ type: tabsType, regular: 'engineering', height: tableHeight, tabPosition, params: {
+                    projectIds: proJuctId,
+                    groupNames: groupConsumptionName,
+                    dataTime: rangeDatas
+                  } }" />
+                </el-tab-pane>
+              </el-tabs>
+              <!-- <div>
 
-            <!-- 分组耗用进度表 -->
-            <el-table  v-if="ins == 24 && tabPosition==0" :key="24" border :data="isbeCustomReport.consumptionSchedule" highlight-current-row v-loading="listLoading" :height="(+tableHeight - 0) - 1" style="width: 100%;" :span-method="objectSpanMethod">
-              <el-table-column align="center" prop="projectName" :label="$t('headerTop.projectName')" min-width="200"></el-table-column>
-              <el-table-column align="center" prop="department_name" :label="$t('fuZeBuMen')" min-width="150">
-                <template slot-scope="scope">
-                  <div>
-                    <span v-if="user.userNameNeedTranslate == '1'">
-                      <TranslationOpenDataText type='departmentName' :openid='scope.row.corpwxDeptId'></TranslationOpenDataText>
-                    </span>
-                    <span v-if="user.userNameNeedTranslate != '1'">
-                      {{scope.row.departmentName}}
-                    </span>
-                    <!-- {{ scope.row.corpwxDeptId }} -->
-                  </div>
-                </template>
-              </el-table-column>
-              <el-table-column align="center" prop="groupName" :label="$t('lable.taskGrouping')" min-width="150"></el-table-column>
-              <el-table-column align="center" prop="planHour" :label="$t('jiHuaGongShiCaiWu')" width="120"></el-table-column>
-              <el-table-column align="center" :label="$t('shiJiGongShiChengBen')">
-                <el-table-column align="center" prop="afterSetPlanHour" :label="$t('zengBuGongShiH')" width="120"></el-table-column>
-                <el-table-column align="center" prop="normalHour" :label="$t('zhengChangGongShiH')" width="100"></el-table-column>
-                <el-table-column align="center" prop="overHour" :label="$t('jiaBanGongShiH')" width="100"></el-table-column>
-                <el-table-column align="center" prop="realHour" :label="$t('heJiGongShiH')" width="100"></el-table-column>
-                <el-table-column align="center" prop="realCost" :label="$t('heJiGongShiChengBen')" width="140"></el-table-column>
-              </el-table-column>
-              <el-table-column align="center" prop="process" :label="$t('gongShiHaoYongShuai')" width="150"></el-table-column>
-            </el-table>
+              </div>
+              <div class="packetConsumption-flex"></div> -->
+              <!-- 分组耗用进度表 -->
+              <!-- <el-table  v-if="ins == 24 && tabPosition==0" :key="24" border :data="isbeCustomReport.consumptionSchedule" highlight-current-row v-loading="listLoading" :height="(+tableHeight - 0) - 1" style="width: 100%;" :span-method="objectSpanMethod">
+                <el-table-column align="center" prop="projectName" :label="$t('headerTop.projectName')" min-width="200"></el-table-column>
+                <el-table-column align="center" prop="department_name" :label="$t('fuZeBuMen')" min-width="150">
+                  <template slot-scope="scope">
+                    <div>
+                      <span v-if="user.userNameNeedTranslate == '1'">
+                        <TranslationOpenDataText type='departmentName' :openid='scope.row.corpwxDeptId'></TranslationOpenDataText>
+                      </span>
+                      <span v-if="user.userNameNeedTranslate != '1'">
+                        {{scope.row.departmentName}}
+                      </span>
+                    </div>
+                  </template>
+                </el-table-column>
+                <el-table-column align="center" prop="groupName" :label="$t('lable.taskGrouping')" min-width="150"></el-table-column>
+                <el-table-column align="center" prop="planHour" :label="$t('jiHuaGongShiCaiWu')" width="120"></el-table-column>
+                <el-table-column align="center" :label="$t('shiJiGongShiChengBen')">
+                  <el-table-column align="center" prop="afterSetPlanHour" :label="$t('zengBuGongShiH')" width="120"></el-table-column>
+                  <el-table-column align="center" prop="normalHour" :label="$t('zhengChangGongShiH')" width="100"></el-table-column>
+                  <el-table-column align="center" prop="overHour" :label="$t('jiaBanGongShiH')" width="100"></el-table-column>
+                  <el-table-column align="center" prop="realHour" :label="$t('heJiGongShiH')" width="100"></el-table-column>
+                  <el-table-column align="center" prop="realCost" :label="$t('heJiGongShiChengBen')" width="140"></el-table-column>
+                </el-table-column>
+                <el-table-column align="center" prop="process" :label="$t('gongShiHaoYongShuai')" width="150"></el-table-column>
+              </el-table> -->
 
-            <!-- 分组耗用进度图表 -->
-            <div v-if="ins == 24 && tabPosition!=0" class="useASchedule" :style="`height:${tableHeight + 50}px`" v-loading="groupConsumptionLoading">
-              <EchartsEchar :options="groupConsumptionOption"></EchartsEchar>
+              <!-- 分组耗用进度图表 -->
+              <!-- <div v-if="ins == 24 && tabPosition == 1 && tabsType == 'all'" class="useASchedule" :style="`height:${tableHeight + 50}px;width: 100%`" v-loading="groupConsumptionLoading">
+                <EchartsEchar :options="groupConsumptionOption"></EchartsEchar>
+              </div> -->
             </div>
+            
 
             <!-- 项目耗用进度表 -->
             <el-table  v-if="ins == 25" :key="25" border :data="isbeCustomReport.consumptionScheduleTwo" highlight-current-row v-loading="listLoading" :height="(+tableHeight) - 1" style="width: 100%;" >
@@ -1330,7 +1406,7 @@
               <el-table-column align="center" prop="onTimePercent" :label="$t('anShiWanChengShuai')" min-width="150"></el-table-column>
             </el-table>
         <!--工具条-->
-        <el-col :span="24" class="toolbar" v-if="ins != 6 && ins != 20 && ins != 21 && tabPosition==0">
+        <el-col :span="24" class="toolbar" v-if="ins != 6 && ins != 20 && ins != 21 && tabPosition==0 && tabsType == 'all'">
           <el-pagination
                 v-if="ins == 12"
                 @size-change="groupSizeChange"
@@ -1647,14 +1723,16 @@ import selectCat from "@/components/select.vue"
 // 引入自定义级联组件
 import vueCascader from "@/components/cascader.vue"
 import EchartsEchar from "@/components/echartsEchar.vue"
-import { getGroupConsumption } from "./echartsData"
+import { getGroupConsumption, fixedTaskGrouping, fixedGrouping } from "./echartsData"
+import PackTables from "./packetConsumption/tables.vue"
 
 export default {
   name: "expense",
   components: {
     selectCat,
     vueCascader,
-    EchartsEchar
+    EchartsEchar,
+    PackTables
   },
   props: {},
   data() {
@@ -1885,9 +1963,12 @@ export default {
       // 分组耗用进度图表
       groupConsumptionOption: {},
       groupConsumptionLoading: false,
-      groupConsumptionList: ['工程部现场安装施工', '工程部配合调试', '生产部电气', '生产部车间', '研发部BIM设计', '研发部工艺设计', '研发部工艺调试验收', '研发部电气设计', '研发部电气调试验收', '研发部结构设计'],
+      groupConsumptionList: fixedTaskGrouping,
       groupConsumptionName: [],
-      groupConsumptionTimer: null
+      groupConsumptionTimer: null,
+      tabsType: 'all',
+      tabParams: {},
+      groupTaskKey: 1
     };
   },
   computed: {},
@@ -1968,6 +2049,26 @@ export default {
       }
   },
   methods: {
+    handleClick() {
+      console.log(this.tabsType, '<==== 返回的书')
+      this.groupTaskKey++
+      if(this.tabsType == 'all') {
+        this.$set(this, 'groupConsumptionName', '')
+        this.$set(this, 'groupConsumptionList', fixedTaskGrouping)
+        this.$set(this, 'rangeDatas', null)
+        if(this.tabPosition == 1) {
+          this.getGroupConsumptionData()
+        } else {
+          this.getConsumptionSchedule()
+        }
+        return
+      }
+      this.rangeDatas = this.getCurrentRangeTime()
+      const type = this.tabsType
+      const list = fixedGrouping[type].tabPicFileds
+      this.groupConsumptionName = list[0].filed
+      this.groupConsumptionList = list.map(item => item.filed)
+    },
     authorityToJudge() {
       if(this.permissions.reportProject || this.permissions.reportAllProject) {this.ssl(0);this.defaultActive = '1-1';return} else
       if(this.permissions.reportTask || this.permissions.reportAllTask) {this.ssl(1);this.defaultActive = '1-2';return} else
@@ -2273,7 +2374,9 @@ export default {
             getList(e) {
               let noUserList = [16, 17, 18, 19, 20, 21, 22, 24, 25, 26,27]
               if(this.ins == 24) {
-                this.rangeDatas = []
+                if(this.tabsType == 'all') {
+                  this.rangeDatas = []
+                }
               } else if(this.ins == 15) {
                 this.rangeDatas = null
               } else if(!e){
@@ -2535,11 +2638,23 @@ export default {
           this.userId ? sl.userId = this.userId : ''
           dept ? sl.deptId = dept : ''
         } else if(this.ins == 24) {
-          fName = this.$t('fenZuHaoYongJinDuBiao') + '.xlsx'
-          url = "/project/exportGroupExpendProcessList"
-          this.proJuctId ? sl.projectId = this.proJuctId : ''
-          sl.startDate = this.rangeDatas[0]
-          sl.endDate = this.rangeDatas[1]
+          if(this.tabsType == 'all') {
+            fName = this.$t('fenZuHaoYongJinDuBiao') + '.xlsx'
+            url = "/project/exportGroupExpendProcessList"
+            this.proJuctId ? sl.projectId = this.proJuctId : ''
+            sl.startDate = this.rangeDatas[0]
+            sl.endDate = this.rangeDatas[1]
+          } else {
+            const type = this.tabsType
+            const row = fixedGrouping[type]
+            const listText = row.tableFileds.map(item => item.label).join(',')
+            fName = row + '表' + '.xlsx'
+            url = "/project/exportGroupExpendProcessListForUser"
+            this.proJuctId ? sl.projectId = this.proJuctId : ''
+            sl.startDate = this.rangeDatas[0]
+            sl.endDate = this.rangeDatas[1]
+            sl.titleStr = (listText || '')+',所属部门,工号,员工,总计'
+          }
         } else if(this.ins == 25) {
           fName = this.$t('xiangMuHaoYongJinDuBiao') + '.xlsx'
           url = "/project/exportProjectExpendProcessList"
@@ -2651,6 +2766,7 @@ export default {
       this.userId = null
       this.selUserList = this.userList
       this.tabPosition="0"
+      this.tabsType = 'all'
       this.getList();
     },
     stateKeySel(){
@@ -4176,6 +4292,9 @@ export default {
     },
     // 分组耗用进度表
     async getConsumptionSchedule() {
+      if(this.tabsType != 'all') {
+        return
+      }
       let parameter = {
         // startDate: this.rangeDatas[0],
         // endDate: this.rangeDatas[1],
@@ -4293,18 +4412,23 @@ export default {
         clearTimeout(this.groupConsumptionTimer)
       }
       this.groupConsumptionTimer = setTimeout(async () => {
+        if(this.tabsType != 'all') {
+          return
+        }
         if(this.tabPosition == 0) {
           this.proJuctId = ''
           return
         }
-        this.groupConsumptionLoading = true
+        // this.groupConsumptionLoading = true
+        this.listLoading = true
         let { data } = await this.postData('/project/groupExpendProcessListForChart', {
           startDate: this.rangeDatas[0],
           endDate: this.rangeDatas[1],
           projectIds: this.proJuctId,
           groupNames: this.groupConsumptionName.join(',')
         })
-        this.groupConsumptionLoading = false
+        // this.groupConsumptionLoading = false
+        this.listLoading = false
         let nameList = data.map(item => (item.groupName || ''))
         let realHourList = data.map(item => returnNum((item.realHour || 0)))
         let actualPlan = data.map(item => returnNum((item.planHour || 0)))
@@ -4548,4 +4672,15 @@ export default {
 .useASchedule {
   width: 100%;
 }
+
+.packetConsumption {
+  width: 100%;
+  display: flex;
+  &>div {
+    height: 100%;
+  }
+  .packetConsumption-flex {
+    flex: 1;
+  }
+}
 </style>

+ 350 - 0
fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/packetConsumption/tables.vue

@@ -0,0 +1,350 @@
+<template>
+  <div class="tabless">
+    <!-- 表格 -->
+    <template v-if="tabPosition != '1'">
+      <template v-if="types != 'all'">
+        <el-table :key="typesDataObj[types].tableKey" border :data="tableList" highlight-current-row :height="(+tableHeight - 0) - 1" style="width: 100%;" :span-method="objectSpanMethod" show-summary :summary-method="getSummaries" v-loading="tableLoading">
+          <el-table-column align="center" prop="departmentName" :label="'所属部门'" min-width="200">
+            <template slot-scope="scope">
+              <template v-for="(list, listIndex) in scope.row.departmentNameList">
+                <TranslationOpenDataText type='departmentName' :openid='list'></TranslationOpenDataText> <template v-if="listIndex < scope.row.departmentNameList.length - 1">/</template>
+              </template>
+            </template>
+          </el-table-column>
+          <el-table-column align="center" prop="jobNumber" :label="'工号'" min-width="150"></el-table-column>
+          <el-table-column align="center" prop="userName" :label="'员工'" min-width="150">
+            <template slot-scope="scope">
+              <TranslationOpenDataText type='userName' :openid='scope.row.userName'></TranslationOpenDataText>
+            </template>
+          </el-table-column>
+          <template v-for="(item, index) in typesDataObj[types].tableFileds">
+            <el-table-column align="center" :prop="item.filed" :label="`${item.label}(h)`" min-width="170" :key="index">
+              <template slot-scope="scope">
+                <div>
+                  {{ scope.row[item.filed] || 0 }}
+                </div>
+              </template>
+            </el-table-column>
+          </template>
+          <el-table-column align="center" prop="totalWorkTime" :label="'总计(h)'" min-width="150">
+            <template slot-scope="scope">
+              <div>
+                {{ scope.row['totalWorkTime'] || 0 }}
+              </div>
+            </template>
+          </el-table-column>
+        </el-table>
+      </template>
+
+      <!-- 单个 -->
+      <template v-if="types == 'all'">
+        <el-table :key="24" border :data="tableList" highlight-current-row :height="(+tableHeight - 0) - 1" style="width: 100%;" :span-method="objectSpanMethod">
+          <el-table-column align="center" prop="projectName" :label="$t('headerTop.projectName')" min-width="200"></el-table-column>
+          <el-table-column align="center" prop="department_name" :label="$t('fuZeBuMen')" min-width="150">
+            <template slot-scope="scope">
+              <div>
+                <span v-if="user.userNameNeedTranslate == '1'">
+                  <TranslationOpenDataText type='departmentName' :openid='scope.row.corpwxDeptId'></TranslationOpenDataText>
+                </span>
+                <span v-if="user.userNameNeedTranslate != '1'">
+                  {{scope.row.departmentName}}
+                </span>
+              </div>
+            </template>
+          </el-table-column>
+          <el-table-column align="center" prop="groupName" :label="$t('lable.taskGrouping')" min-width="150"></el-table-column>
+          <el-table-column align="center" prop="planHour" :label="$t('jiHuaGongShiCaiWu')" width="120"></el-table-column>
+          <el-table-column align="center" :label="$t('shiJiGongShiChengBen')">
+            <el-table-column align="center" prop="afterSetPlanHour" :label="$t('zengBuGongShiH')" width="120"></el-table-column>
+            <el-table-column align="center" prop="normalHour" :label="$t('zhengChangGongShiH')" width="100"></el-table-column>
+            <el-table-column align="center" prop="overHour" :label="$t('jiaBanGongShiH')" width="100"></el-table-column>
+            <el-table-column align="center" prop="realHour" :label="$t('heJiGongShiH')" width="100"></el-table-column>
+            <el-table-column align="center" prop="realCost" :label="$t('heJiGongShiChengBen')" width="140"></el-table-column>
+          </el-table-column>
+          <el-table-column align="center" prop="process" :label="$t('gongShiHaoYongShuai')" width="150"></el-table-column>
+        </el-table>
+      </template>
+    </template>
+
+    <!-- 图表 -->
+    <template v-if="tabPosition == '1'">
+      <template v-if="echartTableType == '图表'">
+        <div ref="echartsRef" :style="`width: 100%;height: ${tableHeight - 0}px;`" v-loading="echartsLoading">
+          <EchartsEchar :options="echartsEcharData" :key="echartsKey"></EchartsEchar>
+        </div>
+      </template>
+      <template v-if="echartTableType == '表格'">
+        <el-table :data="echartsTableData" border style="width: 100%" :height="(+tableHeight - 0) - 1" v-loading="echartsLoading" show-summary :summary-method="getSummaries">
+          <el-table-column prop="projectCode" label="项目编号"></el-table-column>
+          <el-table-column prop="projectName" label="项目名称"></el-table-column>
+          <el-table-column prop="workTime" label="时长(h)" width="180"></el-table-column>
+        </el-table>
+      </template>
+      <div class="echarts-table" v-if="types != 'all'">
+        <el-radio-group v-model="echartTableType" size="small">
+          <el-radio-button label="表格"></el-radio-button>
+          <el-radio-button label="图表"></el-radio-button>
+        </el-radio-group>
+        </div>
+    </template>
+  </div>
+</template>
+
+<script>
+import { debounce, fixedGrouping, getPieEchartOption } from "../echartsData.js";
+import EchartsEchar from "@/components/echartsEchar.vue"
+export default {
+  props: {
+    datas: { type: Object, default: () => {} },
+    tabType: { type: String, default: () => "all" },
+  },
+  components: {
+    EchartsEchar
+  },
+  data() {
+    return {
+      user: JSON.parse(sessionStorage.user),
+      permissions: JSON.parse(sessionStorage.getItem("permissions")),
+      types: "all",
+      tableList: [],
+      timer: null,
+      tableHeight: 0,
+      tabPosition: '0',
+      list1: [],
+      listArr1: [],
+      listArr2: [],
+      listArr3: [],
+      echartsWidth: 0,
+      listPosition1: [],
+      tableLoading: false,
+      echartsLoading: false,
+      echartsEcharData: {},
+      typesDataObj: fixedGrouping,
+      echartsTableData: [],
+      echartsKey: 1,
+      echartTableType: '图表'
+    };
+  },
+  computed: {},
+  watch: {
+    datas(newVal) {
+      const { type, regular, tabPosition } = newVal
+      this.types = type;
+      this.tabPosition = tabPosition
+      this.handleWatchTabDatas(newVal);
+    },
+  },
+  created() {},
+  mounted() {
+  },
+  methods: {
+    handleWatchTabDatas(newVal) {
+      const { type, list, regular, height, tabPosition, params, listArr1, listArr2, listArr3, echartsData = {} } = newVal;
+      this.tableHeight = height;
+      this.tableList = []
+      this.echartTableType = '图表'
+      if(type == regular && tabPosition == '0') {
+        this.getTableList(params)
+      }
+      if(type == regular && tabPosition == '1') {
+        this.getEchartsData(params)
+      }
+      if (type == "all") {
+        this.echartsKey++
+        this.listArr1 = listArr1
+        this.listArr2 = listArr2
+        this.listArr3 = listArr3
+        this.echartsEcharData = echartsData
+        setTimeout(() => {  
+          this.tableList = list;
+        }, 200)
+      }
+    },
+    async getEchartsData(params) {
+      const { groupNames, dataTime = [], projectIds } = params
+      this.echartsLoading = true
+      let res = await this.postData('/project/groupExpendProcessListForProject', {
+        projectIds,
+        startDate: dataTime[0] || '',
+        endDate: dataTime[1] || '',
+        deptIdStr: '',
+        groupNames
+      })
+      this.echartsKey++
+      this.echartsLoading = false
+      const dataList = res.data.record
+      this.echartsTableData = dataList
+      const type = this.types
+      const list = fixedGrouping[type].tabPicFileds
+      const item = list.find(item => item.filed == groupNames)
+      const datas = dataList.map(item => {
+        return {
+          name: `${item.projectName} ${item.percent}`,
+          value: item.workTime
+        }
+      })
+      this.echartsEcharData = getPieEchartOption(item.title, datas)
+    },
+    async getTableList(params) {
+      const { dataTime = [], projectIds } = params
+      this.tableLoading = true
+      let groupNames = this.typesDataObj[this.types].tableFileds.map(item => item.label).join(',')
+      let { data } = await this.postData('/project/groupExpendProcessListForUser', {
+        projectIds,
+        startDate: dataTime[0] || '',
+        endDate: dataTime[1] || '',
+        deptIdStr: '',
+        groupNames
+      })
+      this.tableLoading = false
+      this.listArr1 = []
+      this.listArr2 = []
+      this.listArr3 = []
+      this.listPosition1 = 0
+      this.listPosition2 = 0
+      this.listPosition3 = 0
+      this.tableList = data.record.map(item => {
+        return {
+          ...item,
+          departmentNameList: item.departmentName.split('/')
+        }
+      })
+      this.typesDataObj[this.types].tableKey = this.randomInt()
+      console.log(this.tableList, '<====== 返回最终的数据')
+    },
+    objectSpanMethod({ row, column, rowIndex, columnIndex }){
+      const { companyId } = this.user
+      if(columnIndex == 0 && this.listArr1.length > 0){
+        const _row = this.listArr1[rowIndex]
+        const _col = _row > 0 ? 1 : 0
+        return {
+          rowspan: _row,
+          colspan: _col
+        }
+      }
+      if(columnIndex == 1 && this.listArr2.length > 0){
+        const _row = this.listArr2[rowIndex]
+        const _col = _row > 0 ? 1 : 0
+        return {
+          rowspan: _row,
+          colspan: _col
+        }
+      }
+      if(columnIndex == 2 && companyId == '3092' && this.listArr3.length > 0) {
+        const _row = this.listArr3[rowIndex]
+        const _col = _row > 0 ? 1 : 0
+        return {
+          rowspan: _row,
+          colspan: _col
+        }
+      }
+    },
+    // 单独封装请求
+    async postData(urls, param) {
+      return new Promise((resolve, reject) => {
+        this.http.post(urls, { ...param },
+          res => {
+            if(res.code == 'ok') {
+              resolve(res)
+            } else {
+              this.$message({
+                message: res.msg,
+                type: 'error'
+              })
+              reject(res)
+            }
+            resolve(res)
+          },
+          error => {
+            this.$message({
+              message: error,
+              type: "error"
+            });
+            reject(error)
+          }
+        )
+      });
+    },
+    groupByJobNumber(data) {
+        let groupedData = [];
+        data.reduce((acc, obj) => {
+            let found = acc.find(item => item.jobNumber === obj.jobNumber);
+            if (found) {
+                found.list.push(obj);
+            } else {
+                acc.push({ 
+                  jobNumber: obj.jobNumber, 
+                  userName: obj.userName, 
+                  departmentName: obj.departmentName, 
+                  workTime: obj.workTime,
+                  list: [obj],
+                });
+            }
+            return acc;
+        }, groupedData);
+        return groupedData;
+    },
+    rowspan(spanArr,position,spanName,dataItem = [],fields=false){
+      let newArray = dataItem.length > 0 ? dataItem : this.tableList
+      newArray.forEach((item,index) => {
+        if(index == 0){
+          spanArr.push(1)
+          position = 0
+        }else {
+          let newArrFlag = newArray[index][spanName] == newArray[index-1][spanName] && (!fields || newArray[index][fields] == newArray[index-1][fields]);
+          // if(newArray[index][spanName] == newArray[index-1][spanName]){
+          if(newArrFlag){
+            spanArr[position] += 1
+            spanArr.push(0)
+          }else {
+            spanArr.push(1)
+            position = index
+          }
+        }
+      })
+    },
+    // 随机整数
+    randomInt(min = 1, max = 10000) {
+      return Math.floor(Math.random() * (max - min + 1) + min);
+    },
+    getSummaries(param) {
+      const { columns, data } = param;
+      const sums = [];
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = '总计';
+          return;
+        }
+        const values = data.map(item => Number(item[column.property]));
+        if (!values.every(value => isNaN(value))) {
+          sums[index] = values.reduce((prev, curr) => {
+            const value = Number(curr);
+            if (!isNaN(value)) {
+              return prev + curr;
+            } else {
+              return prev;
+            }
+          }, 0);
+          sums[index] += ' h';
+        } else {
+          sums[index] = ' ';
+        }
+      });
+
+      return sums;
+    }
+  },
+};
+</script>
+
+<style scoped lang="scss">
+.tabless {
+  width: 100%;
+  height: 100%;
+}
+.echarts-table {
+  position: fixed;
+  bottom: 15px;
+  right: 38px;
+}
+</style>