Forráskód Böngészése

Merge remote-tracking branch 'origin/master'

yusm 7 hónapja
szülő
commit
567221a234
34 módosított fájl, 1617 hozzáadás és 25382 törlés
  1. BIN
      fhKeeper/formulahousekeeper/customerBuler-crm/src/assets/code.jpg
  2. 30 4
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/login.vue
  3. 1 1
      fhKeeper/formulahousekeeper/inva_4_tivo/customerNew.html
  4. 3 3
      fhKeeper/formulahousekeeper/inva_4_tivo/moduleView/header.html
  5. BIN
      fhKeeper/formulahousekeeper/management-crm/crm.2024-06-03.log.gz
  6. BIN
      fhKeeper/formulahousekeeper/management-crm/crm.2024-06-04.log.gz
  7. BIN
      fhKeeper/formulahousekeeper/management-crm/crm.2024-06-28.log.gz
  8. BIN
      fhKeeper/formulahousekeeper/management-crm/crm.2024-06-29.log.gz
  9. BIN
      fhKeeper/formulahousekeeper/management-crm/crm.2024-06-30.log.gz
  10. BIN
      fhKeeper/formulahousekeeper/management-crm/crm.2024-07-01.log.gz
  11. BIN
      fhKeeper/formulahousekeeper/management-crm/crm.2024-07-02.log.gz
  12. BIN
      fhKeeper/formulahousekeeper/management-crm/crm.2024-07-03.log.gz
  13. BIN
      fhKeeper/formulahousekeeper/management-crm/crm.2024-07-04.log.gz
  14. 0 333
      fhKeeper/formulahousekeeper/management-crm/hs_err_pid23908.log
  15. 0 334
      fhKeeper/formulahousekeeper/management-crm/hs_err_pid30916.log
  16. 0 333
      fhKeeper/formulahousekeeper/management-crm/hs_err_pid35380.log
  17. 0 333
      fhKeeper/formulahousekeeper/management-crm/hs_err_pid36892.log
  18. 0 334
      fhKeeper/formulahousekeeper/management-crm/hs_err_pid6892.log
  19. 0 4076
      fhKeeper/formulahousekeeper/management-crm/replay_pid23908.log
  20. 0 4604
      fhKeeper/formulahousekeeper/management-crm/replay_pid30916.log
  21. 0 4441
      fhKeeper/formulahousekeeper/management-crm/replay_pid35380.log
  22. 0 4330
      fhKeeper/formulahousekeeper/management-crm/replay_pid36892.log
  23. 0 4711
      fhKeeper/formulahousekeeper/management-crm/replay_pid6892.log
  24. 3 7
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/application.yml
  25. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ProjectAuditor.java
  26. 32 13
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  27. 19 1
      fhKeeper/formulahousekeeper/timesheet/src/components/echartsEchar.vue
  28. 5 1
      fhKeeper/formulahousekeeper/timesheet/src/components/selectProject.vue
  29. 16 1
      fhKeeper/formulahousekeeper/timesheet/src/views/contract/components/customContract.vue
  30. 993 1515
      fhKeeper/formulahousekeeper/timesheet/src/views/project/cost.vue
  31. 29 0
      fhKeeper/formulahousekeeper/timesheet/src/views/project/costData.js
  32. 477 0
      fhKeeper/formulahousekeeper/timesheet/src/views/project/costReportExport.vue
  33. 2 2
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue
  34. 5 5
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/list.vue

BIN
fhKeeper/formulahousekeeper/customerBuler-crm/src/assets/code.jpg


+ 30 - 4
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/login.vue

@@ -24,16 +24,24 @@
         <img class="w-9 m-auto p-1 rounded-full border-blue-300 border-2 cursor-pointer" :src="qiyeweixin" alt="">
       </div>
       <div class="flex justify-between pb-5">
-        <el-link type="primary" :underline="false">联系客服</el-link>
+        <!-- <el-link type="primary" :underline="false">联系客服</el-link> -->
+        <el-link type="primary" class="btn" style="float:left;" :underline="false">联系客服
+            <div class="service">
+                <p style="color: #333">联系客服</p>
+                <img src="../assets/code.jpg">
+                <p><span style="color: #333">QQ:</span><span id="QQ">3052894409</span></p>
+            </div>
+        </el-link>
         <div class="flex justify-around">
           <el-link class="mr-4" type="primary" :underline="false"  @click="useHelp()">使用说明</el-link>
           <el-link type="primary" :underline="false" @click="toRegister()">企业注册</el-link>
         </div>
       </div>
       <el-dialog v-model="helpDialog" width="30%" title="使用说明">
-        <div class="p-2 text-xl">文档水水水水</div>
-        <div>文档水水水水</div>
-        <div>文档水水水水</div>
+        <div class="p-2 text-xl">
+          <a style="color:#075985;text-decoration:none" href="upload/客户管家使用说明书.docx" download="客户管家使用说明书.docx" 
+                            target="_blank">客户管家使用说明书.docx</a>
+        </div>
       </el-dialog>
     </div>
   </div>
@@ -125,4 +133,22 @@ const toRegister = () => {
 .loginView {
   background: #f0f2f5 url("../assets/login/background.png") no-repeat;
 }
+.service {
+  display: none;
+  width: 120px;
+  position: absolute;
+  background: #fff;
+  text-align: center;
+  padding: 10px;
+  left: -30px;
+  top: -210px;
+  border-radius: 5px;
+  box-shadow: 3px 3px 10px #dfdfdf;
+  img {
+      width: 80px;
+  }
+}
+.btn:hover .service {
+  display: block;
+}
 </style>

+ 1 - 1
fhKeeper/formulahousekeeper/inva_4_tivo/customerNew.html

@@ -51,7 +51,7 @@
       </div>
       
       <div class="bannar_text_btn">
-        <a href="javascript:;" class="btn btn-primary btn-lg">立即免费体验</a>
+        <a href="http://crm.ttkuaiban.com/login" class="btn btn-primary btn-lg">立即免费体验</a>
       </div>
     </div>
 

+ 3 - 3
fhKeeper/formulahousekeeper/inva_4_tivo/moduleView/header.html

@@ -20,7 +20,7 @@
           <!-- <img src="./image/logo.png" class="img" alt=""> -->
         </div>
         <div class="header-list" @mouseleave="mouseleave('left')">
-          <div class="header-item" @mouseenter="mouseenter('product', true)" @mouseleave="mouseleave('product')">产品矩</div>
+          <div class="header-item" @mouseenter="mouseenter('product', true)" @mouseleave="mouseleave('product')">产品矩</div>
           <div v-for="(item, index) in leftItemList" :key="index" @mouseenter="mouseenter('left', index)" :class="`${item.class}`">
             <a :href="item.value" target="_top" :class="`${ leftItemIndex == index ? 'item-hover' : '' }`"> {{ item.label }} </a>
           </div>
@@ -37,7 +37,7 @@
         </div>
       </div>
     </div>
-    <!-- 产品矩 -->
+    <!-- 产品矩 -->
     <div class="headerProduct" v-if="productFlag" @mouseenter="mouseenter('product', true)" @mouseleave="mouseleave('product')">
       <div class="content">
         <div class="product">
@@ -81,7 +81,7 @@
             index: { signIn: 'http://worktime.ttkuaiban.com/#/register', logIn: 'http://worktime.ttkuaiban.com/#/login' },
             followup: { signIn: 'http://clinic.ttkuaiban.com/#/register', logIn: 'http://clinic.ttkuaiban.com/#/login' },
             project: { signIn: 'http://worktime.ttkuaiban.com/#/register', logIn: 'http://worktime.ttkuaiban.com/#/login' },
-            customerNew: { signIn: '#', logIn: '#' },
+            customerNew: { signIn: 'http://crm.ttkuaiban.com/register', logIn: 'http://crm.ttkuaiban.com/login' },
             workshop: { signIn: '', logIn: 'http://workshop.ttkuaiban.com' },
             mobile: { signIn: 'http://worktime.ttkuaiban.com/#/register', logIn: 'http://worktime.ttkuaiban.com/#/login' },
           }

BIN
fhKeeper/formulahousekeeper/management-crm/crm.2024-06-03.log.gz


BIN
fhKeeper/formulahousekeeper/management-crm/crm.2024-06-04.log.gz


BIN
fhKeeper/formulahousekeeper/management-crm/crm.2024-06-28.log.gz


BIN
fhKeeper/formulahousekeeper/management-crm/crm.2024-06-29.log.gz


BIN
fhKeeper/formulahousekeeper/management-crm/crm.2024-06-30.log.gz


BIN
fhKeeper/formulahousekeeper/management-crm/crm.2024-07-01.log.gz


BIN
fhKeeper/formulahousekeeper/management-crm/crm.2024-07-02.log.gz


BIN
fhKeeper/formulahousekeeper/management-crm/crm.2024-07-03.log.gz


BIN
fhKeeper/formulahousekeeper/management-crm/crm.2024-07-04.log.gz


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 333
fhKeeper/formulahousekeeper/management-crm/hs_err_pid23908.log


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 334
fhKeeper/formulahousekeeper/management-crm/hs_err_pid30916.log


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 333
fhKeeper/formulahousekeeper/management-crm/hs_err_pid35380.log


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 333
fhKeeper/formulahousekeeper/management-crm/hs_err_pid36892.log


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 334
fhKeeper/formulahousekeeper/management-crm/hs_err_pid6892.log


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 4076
fhKeeper/formulahousekeeper/management-crm/replay_pid23908.log


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 4604
fhKeeper/formulahousekeeper/management-crm/replay_pid30916.log


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 4441
fhKeeper/formulahousekeeper/management-crm/replay_pid35380.log


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 4330
fhKeeper/formulahousekeeper/management-crm/replay_pid36892.log


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 4711
fhKeeper/formulahousekeeper/management-crm/replay_pid6892.log


+ 3 - 7
fhKeeper/formulahousekeeper/management-crm/src/main/resources/application.yml

@@ -142,13 +142,9 @@ management:
 referer:
   refererDomain:
     - localhost
-    - ttkuaiban.com
-    - www.ttkuaiban.com
-    - mobworktime.ttkuaiban.com
-    - worktime.ttkuaiban.com
-    - app71020.eapps.dingtalkcloud.com
-    - mldmobworktime.ttkuaiban.com
-    - mldworktime.ttkuaiban.com
+    - crm.ttkuaiban.com
+    - mobcrm.ttkuaiban.com
+    - 47.100.37.243
     - 47.101.180.183
 excludeUrls: /wxcorp/*,/wxcorp/*/*,/dingding/*,/feishu-info/*,/error,/testClient,/corpWXAuth,/corpWXScanningAuth,/corpInsideWXAuth,/wx-corp-info/*,/clean/*,/innerRoles/*,/project/getProjectListByToken,/project/getTimeCostByToken,/report/getReportListByToken,/report/getProcessErrorData,/project/synchronizationProject,/user/updateUserDeptHierarchy,/report/getUserTimeCostByThird,/report/getProjectTimeCostByThird
 

+ 2 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ProjectAuditor.java

@@ -45,6 +45,8 @@ public class ProjectAuditor extends Model<ProjectAuditor> {
     @TableField("auditor_name")
     private String auditorName;
 
+    @TableField(exist = false)
+    private String auditorDeptName;
 
     @Override
     protected Serializable pkVal() {

+ 32 - 13
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -728,15 +728,33 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     //对于简单模式的非项目,直接获取部门主管作为审核人
                     if (company.getNonProjectSimple() == 1 && project.getIsPublic() == 1) {
                         User user = userMapper.selectById(r.getCreatorId());
-                        Department department = departmentMapper.selectById(user.getDepartmentId());
-                        if (department != null) {
-                            User deptManager = userMapper.selectById(department.getManagerId());
-                            List<ProjectAuditor> auditorList1 = new ArrayList<>();
-                            ProjectAuditor auditor = new ProjectAuditor();
-                            auditor.setAuditorId(deptManager.getId());
-                            auditor.setAuditorName(deptManager.getName());
-                            auditorList1.add(auditor);
-                            r.setAuditUserList(auditorList1);
+                        //优先取个人的非项目审核人
+                        String superiorId = user.getSuperiorId();
+                        //其次取员工的部门主要负责人
+                        boolean isDirectSuperior = true;
+                        if (superiorId == null) {
+                            isDirectSuperior = false;
+                            Integer departmentId = user.getDepartmentId();
+                            Department department = departmentMapper.selectById(departmentId);
+                            if (department != null) {
+                                superiorId = department.getManagerId();
+                            }
+                        }
+                        if (superiorId != null) {
+                            User superior = userMapper.selectById(superiorId);
+                            if (superior != null) {
+                                List<ProjectAuditor> auditorList1 = new ArrayList<>();
+                                ProjectAuditor auditor = new ProjectAuditor();
+                                auditor.setAuditorId(superiorId);
+                                auditor.setAuditorName(superior.getName());
+                                if (isDirectSuperior) {
+                                    Integer deptId = user.getDepartmentId();
+                                    Department department = departmentMapper.selectById(deptId);
+                                    auditor.setAuditorDeptName(department != null? department.getDepartmentName(): null);
+                                }
+                                auditorList1.add(auditor);
+                                r.setAuditUserList(auditorList1);
+                            }
                         }
                         if (r.getProjectAuditorId() != null) {
                             Optional<ProjectAuditor> auItem = r.getAuditUserList().stream().filter(au->au.getAuditorId().equals(r.getProjectAuditorId())).findFirst();
@@ -10290,18 +10308,19 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         List<Map<String, Object>> resultList = new ArrayList<>();
         DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
         for (UserCorpwxTime corpwxTime : userCorpwxTimeList) {
-            boolean isFull = false;
+            boolean isMatch = true;
             double reportTime = 0;
             for (Report report : reportList) {
                 if (corpwxTime.getCreateDate().isEqual(report.getCreateDate())) {
                     reportTime = report.getWorkingTime();
-                    if (corpwxTime.getWorkHours() <= report.getWorkingTime()) {
-                        isFull = true;
+                    //不一致
+                    if (Math.abs(corpwxTime.getWorkHours() - report.getWorkingTime()) > 0.01) {
+                        isMatch = false;
                     }
                     break;
                 }
             }
-            if (!isFull) {
+            if (!isMatch) {
                 Map<String, Object> map = new HashMap<>();
                 map.put("name", corpwxTime.getName()==null?corpwxTime.getCorpwxUserid():corpwxTime.getName());
                 map.put("createDate", dateTimeFormatter.format(corpwxTime.getCreateDate()));

+ 19 - 1
fhKeeper/formulahousekeeper/timesheet/src/components/echartsEchar.vue

@@ -18,6 +18,14 @@ export default {
       type: Object,
       default: null,
     },
+    widthHtval: {
+      type: [String, Boolean],
+      default: false
+    },
+    clickOnTheEvent: { // 是否开启点击事件
+      type: [Boolean],
+      default: false
+    }
   },
   components: {},
   data() {
@@ -37,7 +45,12 @@ export default {
   watch: {
     options() {
       if (this.myChart) {
-        this.myChart.setOption(this.options);
+        if (this.widthHtval) {
+          this.myChart.resize({
+            width: this.widthHtval
+          })
+        }
+        this.myChart.setOption(this.options, { notMerge: true });
       }
     },
   },
@@ -47,6 +60,11 @@ export default {
   mounted() {
     this.myChart = echarts.init(document.getElementById(this.uuid));
     this.myChart.setOption(this.options);
+    if (this.clickOnTheEvent) {
+      this.myChart.getZr().on('click', params => {
+        this.$emit('chartClickEvents', { params, myChart: this.myChart })
+      })
+    }
   },
   methods: {
     idGen() {

+ 5 - 1
fhKeeper/formulahousekeeper/timesheet/src/components/selectProject.vue

@@ -1,6 +1,6 @@
 <template>
   <el-select v-model="selectedValue" :size="size" filterable remote @change="updateValue" :placeholder="placeholder"
-    :clearable="clearable" :remote-method="projectListRemotemethod" :loading="newProjectListLoading"
+    :clearable="clearable" :remote-method="projectListRemotemethod" :loading="newProjectListLoading" :style="`width: ${width}`"
     @visible-change="visibleChangeProjrct" @focus="peojectFocus">
     <div ref="mySelectProject" class="select-project-class">
       <el-option v-for="item in newProjectList" :key="item.id" :label="item.projectName + '\u3000' + item.projectCode"
@@ -34,6 +34,10 @@ export default {
     clearable: {
       type: [Boolean],
       default: false
+    },
+    width: {
+      type: [String],
+      default: '200px'
     }
   },
   data() {

+ 16 - 1
fhKeeper/formulahousekeeper/timesheet/src/views/contract/components/customContract.vue

@@ -113,6 +113,11 @@
         </template>
       </el-table-column>
       <el-table-column prop="amountsNoTax" label="合同金额(元)/不含税价" min-width="190"></el-table-column>
+      <el-table-column prop="isAmountFixed" label="是否固定金额" min-width="190">
+        <template slot-scope="scope">
+          <span>{{scope.row.isAmountFixed?'是':'否'}}</span>
+        </template>
+      </el-table-column>
       <el-table-column prop="currency" label="币种" min-width="190"></el-table-column>
       <el-table-column prop="finishStatus" label="合同状态(是否结清)" min-width="190">
         <template slot-scope="scope">
@@ -244,6 +249,12 @@
               <span slot="prefix">¥</span>
             </el-input>
           </el-form-item>
+          <el-form-item label="是否固定金额">
+            <el-select v-model="contractForm.isAmountFixed" :disabled="contractForm.status == 0" placeholder="请选择">
+              <el-option label="是" :value="true"></el-option>
+              <el-option label="否" :value="false"></el-option>
+            </el-select>
+          </el-form-item>
           <el-form-item label="币种">
             <el-input v-model="contractForm.currency" :disabled="contractForm.status == 0" :placeholder="$t('peaseenterthe')" clearable></el-input>
           </el-form-item>
@@ -451,6 +462,9 @@
           <el-form-item label="合同金额(元)/不含税价">
             ¥ {{contractForm.amountsNoTax}}
           </el-form-item>
+          <el-form-item label="是否固定金额">
+            {{contractForm.isAmountFixed?'是':'否'}}
+          </el-form-item>
           <el-form-item label="币种">
             {{contractForm.currency}}
           </el-form-item>
@@ -994,7 +1008,8 @@ export default {
         typeId: null,
         remarks: '',
         startDate: '',
-        endDate: ''
+        endDate: '',
+        isAmountFixed: true,
       }
       this.contractPaymentList = [];
       this.fileList = []

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 993 - 1515
fhKeeper/formulahousekeeper/timesheet/src/views/project/cost.vue


+ 29 - 0
fhKeeper/formulahousekeeper/timesheet/src/views/project/costData.js

@@ -0,0 +1,29 @@
+/**
+ * 柱状图图表数据
+ * 初始化数据,使用时使用 解构赋值:如:xxx.xAxis = { ...xxx.xAxis, data: xxxxx }
+ */
+export const barChartOptions = {
+  grid: {
+    top: "10%", // 上间距
+    right: "5%", // 右间距
+    bottom: "10%", // 下间距
+    left: "5%", // 左间距
+  },
+  xAxis: {
+    type: "category",
+    data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
+    axisLabel: {
+      interval: 0,
+      rotate: 20,
+    },
+  },
+  yAxis: {
+    type: "value",
+  },
+  series: [
+    {
+      data: [120, 200, 150, 80, 70, 110, 130],
+      type: "bar",
+    },
+  ],
+};

+ 477 - 0
fhKeeper/formulahousekeeper/timesheet/src/views/project/costReportExport.vue

@@ -0,0 +1,477 @@
+<template>
+  <el-dialog title="报表导出" :visible.sync="value" top="7.8vh" customClass="customWidth" width="500px"
+    :before-close="handleClose">
+    <el-form ref="exportFormRef" :model="exportParam">
+      <!-- 头部 -->
+      <div style="text-align: center;margin-bottom: 20px">
+        <el-radio-group size="medium" v-model="exportParam.reportType">
+          <el-radio-button :label="0">常规报表</el-radio-button>
+          <el-radio-button :label="1">月度报表</el-radio-button>
+        </el-radio-group>
+      </div>
+      <!-- 常规报表 -->
+      <template v-if="exportParam.reportType == 0">
+
+        <el-form-item prop="projectCategoryId" :label="$t('projectclassification')"
+          v-if="singleChoiceType == $t('projectclassification') || singleChoiceType == $t('other.project')">
+          <el-select v-model="exportParam.projectCategoryId" :placeholder="$t('classificationitems')" clearable
+            style="width:350px;" filterable="true" @change="filterCategory">
+            <el-option v-for="item in categoryList" :key="item.id" :label="item.name" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+
+        <el-form-item prop="projectId" :label="'选择项目'" v-if="!['人员', '项目分类', '部门', '主项目'].includes(singleChoiceType)">
+          <select-project v-model="exportParam.projectId" :size="'medium'" :placeholder="'全部项目'" width="350px"
+            clearable></select-project>
+        </el-form-item>
+
+        <el-form-item prop="exportContent" :label="$t('daoChuNeiRon')"
+          v-if="permissions.countCost && permissions.countHours && (['项目', '项目分类'].includes(singleChoiceType))">
+          <el-select v-model="exportParam.exportContent" style="width:350px;" filterable="true"
+            popper-class="projectSelectPopperClass">
+            <el-option :label="$t('gongShiHeChengBen')" value="hoursAndCost"></el-option>
+            <el-option :label="$t('jingGongShi')" value="hours"></el-option>
+            <el-option :label="$t('jingChenBen')" value="cost"></el-option>
+          </el-select>
+        </el-form-item>
+
+        <el-form-item :label="$t('departmentchoice')" v-if="singleChoiceType == $t('other.project')">
+          <el-cascader v-if="user.userNameNeedTranslate != 1" v-model="exportParam.deptId" :options="departmentList"
+            :placeholder="$t('defaultText.pleaseChoose')" :props="{ checkStrictly: true, expandTrigger: 'hover' }"
+            clearable filterable style="width:350px;"></el-cascader>
+
+          <vueCascader :size="'medium'" :widthStr="'350'" :clearable="true" :subject="departmentList" :radios="true"
+            :distinction="'1'" @vueCasader="vueCasader" v-if="user.userNameNeedTranslate == 1"></vueCascader>
+        </el-form-item>
+
+        <el-form-item prop="userIds" :label="$t('screening.selectPeople')" v-if="singleChoiceType == $t('ren-yuan')">
+          <el-select v-if="user.userNameNeedTranslate != '1'" v-model="exportParam.userIds"
+            :placeholder="$t('lable.allStaff')" multiple="true" clearable style="width:350px;" filterable="true">
+            <el-option v-for="item in hasReportUserList" :key="item.id" :label="item.name" :value="item.id"></el-option>
+          </el-select>
+
+          <selectCat v-if="user.userNameNeedTranslate == '1'" :size="'medium'" :widthStr="'350'" :filterable="true"
+            :subject="hasReportUserList" :clearable="true" :multiSelect="true" @selectCal="selectCal"
+            :distinction="'1'"></selectCat>
+        </el-form-item>
+
+        <el-form-item prop="userIds" :label="$t('screening.selectPeople')"
+          v-if="['项目', '项目分类'].includes(singleChoiceType)">
+          <el-select v-if="user.userNameNeedTranslate != '1'" v-model="exportParam.userIds"
+            :placeholder="$t('lable.allStaff')" multiple="true" clearable style="width:350px;" filterable="true">
+            <el-option v-for="item in users" :key="item.id" :label="item.name" :value="item.id"></el-option>
+          </el-select>
+
+          <selectCat v-if="user.userNameNeedTranslate == '1'" :size="'medium'" :widthStr="'350'" :filterable="true"
+            :subject="users" :clearable="true" :multiSelect="true" @selectCal="selectCal" :distinction="'1'">
+          </selectCat>
+        </el-form-item>
+
+        <el-form-item prop="projectId"
+          :label="user.timeType.fixMonthcost == 0 ? $t('time.dateRange') : $t('Selectmonth')">
+          <el-date-picker v-show="user.timeType.fixMonthcost == 0" v-model="exportParam.dateRange" :editable="false"
+            format="yyyy-MM-dd" value-format="yyyy-MM-dd" :clearable="false" :range-separator="$t('other.to')"
+            type="daterange" :start-placeholder="$t('time.startDate')"
+            :end-placeholder="$t('time.endDate')"></el-date-picker>
+
+
+          <el-date-picker v-show="user.timeType.fixMonthcost == 1" v-model="dateRange" :editable="false"
+            format="yyyy-MM" value-format="yyyy-MM" @change="getEchart" :clearable="true" type="month"></el-date-picker>
+        </el-form-item>
+
+        <el-form-item :label="$t('screening.selectPeople')" v-if="false">
+          <el-select v-if="user.userNameNeedTranslate != '1'" v-model="exportParam.userId"
+            :placeholder="$t('lable.allStaff')" style="width: 350px" filterable="true" clearable="true">
+            <span v-for="(item, index) in users" :key="index">
+              <el-option :label="item.name" :value="item.id"></el-option>
+            </span>
+          </el-select>
+
+          <selectCat v-if="user.userNameNeedTranslate == '1'" :size="'medium'" :distinction="'4'" :widthStr="'350'"
+            :subject="users" :clearable="true" @selectCal="selectCal"></selectCat>
+        </el-form-item>
+
+        <el-form-item prop="type" :label="$t('choosethestyle')" v-if="['项目', '项目分类'].includes(singleChoiceType)">
+          <el-select v-model="exportParam.type" :placeholder="$t('choosethestyle')" style="width:350px;">
+            <el-option
+              :label="singleChoiceType == $t('projectclassification') ? $t('classifiedontheline') : $t('Itemontheline')"
+              value="0"></el-option>
+            <el-option
+              :label="singleChoiceType == $t('projectclassification') ? $t('classifiedcolumns') : $t('itemisonthecolumn')"
+              value="1"></el-option>
+          </el-select>
+          <div class="prompt">
+            <el-popover placement="top" width="1200" trigger="hover">
+              <img src="../../assets/image/hanglie.png" alt="" width="100%"
+                v-if="this.singleChoiceType != $t('projectclassification')">
+              <img src="../../assets/image/hanglie_corp.png" alt="" width="100%" v-else>
+              <i class="el-icon-question" slot="reference" />
+            </el-popover>
+          </div>
+        </el-form-item>
+
+        <el-form-item
+          v-if="exportParam.type == 1 && permissions.countHours && (singleChoiceType == $t('other.project'))">
+          <el-checkbox v-model="exportParam.withPercent">{{ $t('gongHhiZhanbiXmu') }}</el-checkbox>
+        </el-form-item>
+
+        <el-form-item v-if="['项目', '项目分类', '主项目'].includes(singleChoiceType) && exportParam.type == '0'">
+          <el-checkbox v-model="exportParam.projectSum">{{ $t('individualprojectdata') }}</el-checkbox>
+        </el-form-item>
+
+        <el-form-item v-if="singleChoiceType == $t('ren-yuan') && user.timeType.mainProjectState == 1">
+          <el-checkbox v-model="exportParam.mainProjectColumn">{{ $t('hanZhuXiangMu') }}</el-checkbox>
+        </el-form-item>
+      </template>
+      <!-- 月度报表 -->
+      <template v-if="exportParam.reportType == 1">
+        <el-form-item prop="date" :label="this.$t('Selectmonth')">
+          <el-date-picker size="small" v-model="exportParam.date" :editable="false" format="yyyy-MM"
+            value-format="yyyy-MM" :clearable="false" type="month" :placeholder="$t('Selectmonth')"
+            style="margin-right: 20px"></el-date-picker>
+        </el-form-item>
+      </template>
+    </el-form>
+
+    <!-- 导出按钮 -->
+    <div slot="footer" class="dialog-footer">
+      <el-button type="primary" @click="exportParam.reportType == 0 ? exportProjectData() : exportMonthlyProjectData()"
+        style="width:100%;" :loading="exporting">{{ $t('export.export') }}</el-button>
+    </div>
+  </el-dialog>
+</template>
+<script>
+import selectProject from "../../components/selectProject.vue";
+import selectCat from "@/components/select.vue"
+import vueCascader from "@/components/cascader.vue"
+export default {
+  components: {
+    selectProject,
+    selectCat,
+    vueCascader
+  },
+  props: {
+    value: { // 双向数据绑定
+      type: [String, Number, Array],
+      required: true
+    },
+    singleChoiceType: {
+      type: String,
+      default: '项目'
+    },
+    hasReportUserList: {
+      type: Array,
+      default: []
+    },
+    chartDate: {
+      type: Array,
+      default: []
+    },
+    theCustomListId: {
+      type: [String, Number],
+      default: ''
+    },
+    theCustomListPlant: {
+      type: [String, Number],
+      default: ''
+    },
+  },
+  data() {
+    return {
+      user: JSON.parse(sessionStorage.getItem("user")),
+      permissions: JSON.parse(sessionStorage.getItem("permissions")),
+      categoryList: [],
+      departmentList: [],
+      dateRange: [],
+      projectList: [],
+      newProjectList: [],
+      exporting: false,
+      exportParam: {
+        reportType: 0,
+        projectId: null,
+        dateRange: [],
+        userId: null,
+        type: '0',
+        withPercent: false,
+        date: null,
+        exportContent: 'hoursAndCost'
+      }
+    }
+  },
+  methods: {
+    exportMonthlyProjectData() {
+      var url = '/project/exportTimeByProjectAndEmployee';
+      var fileName = this.exportParam.date + '月度工时统计表.xlsx';
+      this.exporting = true;
+      this.postData(url, this.exportParam).then((res) => {
+        const aTag = document.createElement('a');
+        aTag.download = fileName;
+        aTag.href = res.data;
+        aTag.click()
+      }).finally(() => {
+        this.exporting = false
+        this.updateValue()
+      })
+    },
+    exportProjectData() {
+      let param = { stateKey: 1 }
+      if (this.exportParam.dateRange != null) {
+        param = {
+          startDate: this.exportParam.dateRange[0],
+          endDate: this.exportParam.dateRange[1],
+          stateKey: 1
+        };
+      }
+      var url = "/project/exportTimeCost";
+      var fileName = this.$t('projectmanhourcoststatistics') + '.xlsx';
+      if (this.singleChoiceType == this.$t('zhu-xiang-mu')) {
+        param.withMainProject = 1;
+      }
+      if (this.singleChoiceType == this.$t('other.project')) {
+        if (this.exportParam.userIds != null && this.exportParam.userIds.length > 0) {
+          var ids = '';
+          this.exportParam.userIds.forEach(u => {
+            ids += u + ',';
+          })
+          param.userIds = ids.substring(0, ids.length - 1);
+        }
+        if (this.exportParam.projectCategoryId) {
+          param.projectCategoryId = this.exportParam.projectCategoryId
+        }
+        //是否含工时占比显示
+        if (this.exportParam.withPercent) {
+          param.withPercent = 1;
+        }
+      }
+      if (this.singleChoiceType == this.$t('ren-yuan')) {
+        //  console.log(this.exportParam.userIds);
+        fileName = this.$t('labortimecoststatistics') + '.xlsx';
+        url = '/department/exportUserStatistic';
+        if (this.exportParam.userIds != null && this.exportParam.userIds.length > 0) {
+          var ids = '';
+          this.exportParam.userIds.forEach(u => {
+            ids += u + ',';
+          })
+          param.userIds = ids.substring(0, ids.length - 1);
+        }
+        param.mainProjectColumn = this.exportParam.mainProjectColumn;
+      }
+      if (this.singleChoiceType == this.$t('projectclassification')) {
+        fileName = this.$t('projectclassificationlaborosttatistics') + '.xlsx';
+        url = '/project/exportTimeCostByCategory'
+        if (this.exportParam.projectCategoryId) {
+          param.projectCategoryId = this.exportParam.projectCategoryId
+        }
+        if (this.exportParam.userIds != null && this.exportParam.userIds.length > 0) {
+          var ids = '';
+          this.exportParam.userIds.forEach(u => {
+            ids += u + ',';
+          })
+          param.userIds = ids.substring(0, ids.length - 1);
+        }
+      }
+      if (this.singleChoiceType == this.$t('lable.department')) {
+        fileName = this.$t('departmenthourscoststatistics') + '.xlsx'
+        url = '/department/exportDeptStatistic'
+      }
+
+      if (this.exportParam.projectId && this.singleChoiceType != this.$t('ren-yuan') && this.singleChoiceType != this.$t('projectclassification')) {
+        param.projectId = this.exportParam.projectId;
+      }
+      if (this.exportParam.userId) {
+        if (this.singleChoiceType == this.$t('lable.department') || this.singleChoiceType == this.$t('ren-yuan')) {
+          param.userId = this.exportParam.userId;
+        }
+      }
+      if (this.exportParam.type == 1) {
+        this.exportParam.projectSum = null
+      }
+      if (this.exportParam.projectSum != null) {
+        if (this.singleChoiceType == this.$t('other.project') || this.singleChoiceType == this.$t('lable.department') || this.singleChoiceType == this.$t('projectclassification') || this.singleChoiceType == this.$t('zhu-xiang-mu')) {
+          param.projectSum = this.exportParam.projectSum;
+        }
+      }
+      if (!this.theCustomListFlg) {
+        param.type = this.exportParam.type * 1
+      }
+      console.log(this.singleChoiceType)
+
+      if (this.theCustomListFlg) {
+        url = '/project/exportTimeCostByUserCustom'
+        fileName = this.singleChoiceType + this.$t('statistical') + '.xlsx'
+        param.customId = this.theCustomListId
+        param.fieldName = this.theCustomListPlant
+      }
+      if (this.exportParam.deptId) {
+        if (this.exportParam.deptId.length > 0) {
+          param.deptId = this.exportParam.deptId[this.exportParam.deptId.length - 1]
+        }
+      }
+      if (this.permissions.countCost && this.permissions.countHours && (this.singleChoiceType == this.$t('other.project') || this.singleChoiceType == this.$t('projectclassification'))) {
+        param.exportContent = this.exportParam.exportContent
+      }
+
+      if (this.singleChoiceType == this.namess) {
+        url = '/project/exportDegreeCost'
+        param = {
+          startDate: this.exportParam.dateRange[0],
+          endDate: this.exportParam.dateRange[1],
+          projectId: this.exportParam.projectId,
+        }
+        fileName = this.singleChoiceType + this.$t('chenBenTongJi') + '.xlsx'
+      }
+      this.exporting = true;
+      this.postData(url, param).then((res) => {
+        this.exporting = false;
+        const aTag = document.createElement('a');
+        aTag.download = fileName;
+        aTag.href = res.data;
+        aTag.click();
+      }).finally(() => {
+        this.exportDialog = false;
+        this.updateValue()
+      })
+    },
+    resetForm() {
+      if (this.$refs['exportFormRef']) {
+        this.$refs['exportFormRef'].resetFields();
+      }
+      this.exportParam = {
+        reportType: 0,
+        projectId: null,
+        dateRange: this.chartDate,
+        userId: null,
+        type: '0',
+        withPercent: false,
+        date: this.dayjs().format('YYYY-MM'),
+        exportContent: 'hoursAndCost'
+      }
+    },
+    getUsers() {
+      this.postData(`/user/getSimpleActiveUserList`, {}).then((res) => {
+        this.users = res.data;
+      })
+    },
+    getMyProjectList() {
+      this.postData(`/project/getProjectList`, {
+        category: this.exportParam.projectCategoryId || ''
+      }).then((res) => {
+        this.projectList = res.data;
+        this.newProjectList = res.data
+      })
+    },
+    getCategoryList() {
+      this.postData(`/project-category/list`, {}).then((res) => {
+        this.categoryList = res.data
+      })
+    },
+    getDepartmentList() {
+      this.postData(this.port.manage.depList, {}).then((res) => {
+        let dptlist = JSON.parse(JSON.stringify(res.data));
+        this.departmentList = this.changeArr(dptlist);
+      })
+    },
+    changeArr(arr) {
+      for (var i = 0; i < arr.length; i++) {
+        if (arr[i].id != -1 && arr[i].id != 0) {
+          if (arr[i].children != null && arr[i].children.length > 0) {
+            arr[i].children = this.changeArr(arr[i].children);
+          }
+          arr[i].id && (arr[i].value = arr[i].id);
+          delete arr[i].id;
+        }
+      }
+      for (var i in arr) {
+        if (arr[i].id == -1 || arr[i].id == 0) {
+          arr.splice(i, 1)
+        }
+      }
+      return arr;
+    },
+    filterCategory() {
+      this.exportParam.projectId = ''
+      const id = this.exportParam.projectCategoryId
+      if (!id) {
+        this.projectList = JSON.parse(JSON.stringify(this.newProjectList))
+        return
+      }
+      const list = JSON.parse(JSON.stringify(this.newProjectList))
+      this.projectList = list.filter(item => item.category == id)
+    },
+    // 自定义事件
+    selectCal(obj) {
+      if (obj.distinction == 1) {
+        let arr = []
+        for (var i in obj.arrUserList) {
+          arr.push(obj.arrUserList[i].id)
+        }
+        this.exportParam.userIds = arr
+      } else if (obj.distinction == 2) {
+        this.personnelValue = obj.name
+        this.personnel()
+      } else if (obj.distinction == 4) {
+        this.exportParam.userId = obj.id
+      }
+    },
+    vueCasader(obj) {
+      if (obj.distinction == 1) {
+        let arr = []
+        arr.push(obj.id)
+        this.exportParam.deptId = arr
+      }
+    },
+    handleClose(done) {
+      this.updateValue(false)
+      done()
+    },
+    updateValue(value) { // 更新数据
+      this.resetForm()
+      this.$emit('input', value);
+      this.$emit('change', value);
+    },
+    // 单独封装请求
+    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)
+          }
+        )
+      });
+    },
+  },
+  mounted() {
+    this.exportParam.dateRange = this.chartDate
+    this.exportParam.date = this.dayjs().format('YYYY-MM')
+    this.exportParam.exportContent = 'hoursAndCost'
+    this.getUsers()
+    this.getCategoryList()
+    this.getDepartmentList()
+    this.getMyProjectList()
+  },
+}
+</script>
+<style lang="scss" scoped>
+.prompt {
+  position: absolute;
+  right: 10px;
+  top: 0;
+}
+</style>

+ 2 - 2
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

@@ -205,7 +205,7 @@
                                                         <span v-else>
                                                             <span v-if="item2.isDeptAudit==0">
                                                                 <span v-if="item2.projectAuditState==0">
-                                                                    <!-- 待项目审核人 --> {{user.companyId == 469?"待部门主管":$t('other.waitForTheProjectReviewer')}}
+                                                                    <!-- 待项目审核人 --> {{user.companyId == 469?(item2.auditorDeptName?('待'+item2.auditorDeptName):"待部门主管"):$t('other.waitForTheProjectReviewer')}}
                                                                     <span v-if="item2.projectAuditorName != null">(
                                                                         <!-- {{item2.projectAuditorName}} -->
                                                                         <TranslationOpenData :configurationItems="{ openType: 'userName', openId: item2.projectAuditorName, renderIndex: 0 }" />
@@ -213,7 +213,7 @@
                                                                     <!-- 审核 --> {{$t('other.audit')}}
                                                                 </span>
                                                                 <span style="color:#32CD32;" v-else-if="item2.projectAuditState==1">
-                                                                    <!-- 项目审核人 --> {{user.companyId == 469?"部门主管":$t('other.projectAuditor')}}
+                                                                    <!-- 项目审核人 --> {{user.companyId == 469?(item2.auditorDeptName?('待'+item2.auditorDeptName):"部门主管"):$t('other.projectAuditor')}}
                                                                     <span v-if="item2.projectAuditorName != null">(
                                                                         <!-- {{item2.projectAuditorName}} -->
                                                                         <TranslationOpenData :configurationItems="{ openType: 'userName', openId: item2.projectAuditorName, renderIndex: 0 }" />

+ 5 - 5
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/list.vue

@@ -233,21 +233,21 @@
                 </el-table-column>
                 <el-table-column prop="cardHours" :label="$t('workAttendance') + '(h)'" v-if="user.timeType.showCorpwxCardtime==1||user.timeType.showDdCardtime==1">
                     <template slot-scope="scope">
-                        {{scope.row.cardHours?scope.row.cardHours.toFixed(1):'-'}}
+                        <span :style="scope.row.cardHours != scope.row.reportTime?'color:red':''">{{scope.row.cardHours?scope.row.cardHours.toFixed(1):'-'}}</span>
                     </template>
                 </el-table-column>
                 
-                <el-table-column label="项目工时" v-if="user.companyId == 469">
+                <el-table-column label="项目工时" v-if="user.companyId == 469" width="180">
                     <template slot-scope="scope">
                         <span v-for="(projItem, projIndex) in scope.row.data">{{ projItem.project+'('+projItem.time+'h)' + (projIndex < scope.row.data.length-1?',':'')}}</span>
                     </template>
                 </el-table-column>
-                <el-table-column label="工作内容" v-if="user.companyId == 469">
+                <el-table-column label="工作内容" v-if="user.companyId == 469" width="480">
                     <template slot-scope="scope">
-                        {{scope.row.data.length == 0?'':scope.row.data[0].content}}
+                        <span v-for="(item, index) in scope.row.data" style="margin-right:10px;"><b>{{item.project}}</b>{{ ':'+item.content }}</span>
                     </template>
                 </el-table-column>
-                <el-table-column prop="state" :label="$t('state.states')" sortable>
+                <el-table-column prop="state" :label="$t('state.states')" sortable width="200">
                     <template slot-scope="scope">
                         <span v-if="scope.row.state == 0" style="color:#DAA520;">
                             <span v-if="user.timeType.reportAuditType == 7">{{ $t('state.WaitingAudit') }}</span>