Browse Source

Merge branch 'master' of http://47.100.37.243:10191/wutt/manHourHousekeeper

Guo1B0 1 year ago
parent
commit
ec1f46928f
96 changed files with 2781 additions and 762 deletions
  1. 3 0
      fhKeeper/formulahousekeeper/customerBuler-crm/.gitignore
  2. 6 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/App.vue
  3. 4 4
      fhKeeper/formulahousekeeper/customerBuler-crm/src/components/detailcompinents/relatedTasks.vue
  4. 39 5
      fhKeeper/formulahousekeeper/customerBuler-crm/src/components/relatedProducts/relatedProducts.vue
  5. 1 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/main.ts
  6. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/component/information.vue
  7. 5 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/component/products.vue
  8. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/component/relatedTasks.vue
  9. 34 12
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/index.vue
  10. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/type.d.ts
  11. 4 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/component/relatedBusiness.vue
  12. 5 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/component/relatedBusiness.vue
  13. 4 4
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/index.vue
  14. 1 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/constant.ts
  15. 58 17
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/detail/components/information.vue
  16. 3 3
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/detail/components/operationRecord.vue
  17. 62 19
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/detail/index.vue
  18. 31 16
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/index.vue
  19. 12 3
      fhKeeper/formulahousekeeper/customerBuler-crm/src/styles/global.scss
  20. 62 15
      fhKeeper/formulahousekeeper/customerBuler-crm/src/utils/customInstructions.ts
  21. 2 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/utils/globalVariables.ts
  22. 28 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/utils/tools.ts
  23. 89 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/FinancialAuditController.java
  24. 59 29
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java
  25. 35 9
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportLogController.java
  26. 2 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/TaskController.java
  27. 105 125
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserWithBeisenController.java
  28. 18 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java
  29. 83 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/FinancialAudit.java
  30. 3 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/SysModule.java
  31. 19 5
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/TimeType.java
  32. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/FinancialAuditMapper.java
  33. 1 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ReportMapper.java
  34. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/FinancialAuditService.java
  35. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ReportService.java
  36. 4 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/WxCorpInfoService.java
  37. 20 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FinancialAuditServiceImpl.java
  38. 6 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/PermissionServiceImpl.java
  39. 91 23
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  40. 5 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java
  41. 54 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java
  42. 268 137
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java
  43. 12 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/DateTimeUtil.java
  44. 21 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/FinancialAuditMapper.xml
  45. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportMapper.xml
  46. 3 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/TimeTypeMapper.xml
  47. 5 0
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/controller/PlanController.java
  48. 24 24
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/controller/ReportController.java
  49. 19 0
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/controller/WxCorpInfoController.java
  50. 1 1
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/entity/Plan.java
  51. 14 0
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/entity/ProdProcedureTeam.java
  52. 6 0
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/entity/User.java
  53. 8 8
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/mapper/ReportMapper.java
  54. 2 0
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/PlanService.java
  55. 12 12
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/ReportService.java
  56. 5 0
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/WxCorpInfoService.java
  57. 53 10
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/PlanServiceImpl.java
  58. 4 1
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/ProdProcedureServiceImpl.java
  59. 6 0
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/ProductServiceImpl.java
  60. 227 68
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  61. 76 0
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java
  62. 2 1
      fhKeeper/formulahousekeeper/management-workshop/src/main/resources/mapper/ProdProcedureTeamMapper.xml
  63. 43 19
      fhKeeper/formulahousekeeper/management-workshop/src/main/resources/mapper/ReportMapper.xml
  64. BIN
      fhKeeper/formulahousekeeper/management-workshop/src/main/resources/upload/今日计划导入模板.xlsx
  65. BIN
      fhKeeper/formulahousekeeper/management-workshop/src/main/resources/upload/插单计划导入模板.xlsx
  66. BIN
      fhKeeper/formulahousekeeper/management-workshop/src/main/resources/upload/明日计划导入模板.xlsx
  67. 2 2
      fhKeeper/formulahousekeeper/plugIn/form-design-master/.vscode/settings.json
  68. 26 0
      fhKeeper/formulahousekeeper/plugIn/form-design-master/src/components.d.ts
  69. 1 0
      fhKeeper/formulahousekeeper/plugIn/form-design-master/src/design/WidgetFormItem.vue
  70. 11 0
      fhKeeper/formulahousekeeper/plugIn/form-design-master/src/generate/GenerateForm.vue
  71. 50 3
      fhKeeper/formulahousekeeper/plugIn/form-design-master/src/generate/GenerateFormItem.vue
  72. 1 0
      fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/generate/GenerateForm.vue.d.ts
  73. 6 2
      fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/generate/GenerateFormItem.vue.d.ts
  74. 1 1
      fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/index.css
  75. 69 16
      fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/index.es.js
  76. 1 1
      fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/index.es.js.map
  77. 3 0
      fhKeeper/formulahousekeeper/timesheet-workshop-h5/src/views/planView/component/planComponent.vue
  78. 42 5
      fhKeeper/formulahousekeeper/timesheet-workshop-h5/src/views/planView/todayPlan/distribution.vue
  79. 9 2
      fhKeeper/formulahousekeeper/timesheet-workshop/src/views/plan/planComponent.vue
  80. 4 0
      fhKeeper/formulahousekeeper/timesheet-workshop/src/views/plan/planComponentDetil.vue
  81. 10 1
      fhKeeper/formulahousekeeper/timesheet-workshop/src/views/product/list.vue
  82. 57 17
      fhKeeper/formulahousekeeper/timesheet-workshop/src/views/statistic/index.vue
  83. 235 0
      fhKeeper/formulahousekeeper/timesheet/src/components/cascadeSelection.vue
  84. 10 10
      fhKeeper/formulahousekeeper/timesheet/src/components/select.vue
  85. 2 1
      fhKeeper/formulahousekeeper/timesheet/src/i18n/en.json
  86. 2 1
      fhKeeper/formulahousekeeper/timesheet/src/i18n/zh.json
  87. 16 0
      fhKeeper/formulahousekeeper/timesheet/src/routes.js
  88. 5 2
      fhKeeper/formulahousekeeper/timesheet/src/views/Home.vue
  89. 212 0
      fhKeeper/formulahousekeeper/timesheet/src/views/financeAudit/financeAudit.vue
  90. 5 0
      fhKeeper/formulahousekeeper/timesheet/src/views/project/cost.vue
  91. 37 53
      fhKeeper/formulahousekeeper/timesheet/src/views/project/list.vue
  92. 18 3
      fhKeeper/formulahousekeeper/timesheet/src/views/settings/timetype.vue
  93. 78 31
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue
  94. 49 22
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/list_import.vue
  95. 1 1
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/edit/weekEdit.vue
  96. 11 4
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/view/calendar.vue

+ 3 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/.gitignore

@@ -22,3 +22,6 @@ dist-ssr
 *.njsproj
 *.sln
 *.sw?
+
+!plugIn/form-design-master/update/node_modules/
+!plugIn/form-design-master/update/dist/

+ 6 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/App.vue

@@ -17,6 +17,7 @@ const beforeunloadFn = (() => {
   setAsyncRoutesMark(false)
 })
 
+// 消息提示弹窗
 provide<GlobalPopup>('globalPopup', {
   showSuccess: (message?: string) => {
     notificationTiop({
@@ -99,4 +100,9 @@ body,
     padding: 0 !important;
   }
 }
+
+// 重置样式
+.el-loading-mask {
+  z-index: 1900 !important;
+}
 </style>

+ 4 - 4
fhKeeper/formulahousekeeper/customerBuler-crm/src/components/detailcompinents/relatedTasks.vue

@@ -3,7 +3,7 @@
         <div class="flex justify-between">
             <div class="title">相关任务</div>
             <div>
-                <el-button type="primary" @click="newTask()">新建任务</el-button>
+                <el-button type="primary" @click="newTask()" v-permission="['tasksAdd']">新建任务</el-button>
             </div>
         </div>
         <div class="flex-1 overflow-auto pt-3">
@@ -15,11 +15,11 @@
                         }}</el-button>
                     </template>
                 </el-table-column>
-                <el-table-column prop="priorityStr" label="优先级" width="130" />
+                <el-table-column prop="priorityStr" sortable label="优先级" width="130" />
                 <el-table-column prop="statusStr" label="状态" width="130" />
                 <el-table-column prop="executorNamesStr" label="执行人" width="130" />
-                <el-table-column prop="startTimes" label="开始时间" width="130" />
-                <el-table-column prop="endTimes" label="截至时间" width="130" />
+                <el-table-column prop="startTimes" sortable label="开始时间" width="130" />
+                <el-table-column prop="endTimes" sortable label="截至时间" width="130" />
             </el-table>
         </div>
     </div>

+ 39 - 5
fhKeeper/formulahousekeeper/customerBuler-crm/src/components/relatedProducts/relatedProducts.vue

@@ -1,5 +1,5 @@
 <template>
-    <div>
+    <div class="pt-2">
         <el-table ref="productTableRef" :data="productTable" border :row-class-name="tableRowClassName"
             @row-click="tableRowItem" :style="{ width: '100%', height: heightClass }">
             <el-table-column label="序号" width="60" align="center">
@@ -55,11 +55,22 @@
                 </template>
             </el-table-column>
         </el-table>
+
+        <div class="flex w-full justify-between pt-2 pb-1">
+            <div>整单折扣率(%)</div>
+            <div class="flex">
+                <div>已选中产品:<span class="text-[red] pr-2">{{ selectedQuantity }}</span>个</div>
+                <div class="pl-4">
+                    总金额:<span class="pr-1">{{ totalAmount }}</span> 元
+                </div>
+            </div>
+        </div>
     </div>
 </template>
   
 <script lang="ts" setup>
-import { ref, reactive, onMounted, inject, watchEffect } from "vue";
+import { ElNotification } from "element-plus";
+import { ref, reactive, onMounted, inject, watchEffect, computed } from "vue";
 
 const props = defineProps<{
     productTableList: any,
@@ -116,14 +127,37 @@ function returnData() {
     let jsonstr = JSON.stringify(productTable.value)
     let json = '[{"index":0}]'
     if (jsonstr == json) {
-        return false
+        return []
+    }
+
+    const list = productTable.value.filter((item: any) => item.productId)
+    const incompleteProduct = list.find((item: any) => !item.sellingPrice || !item.quantity || !item.discount);
+    if (incompleteProduct) {
+        ElNotification.closeAll();
+        ElNotification({
+            title: '提示',
+            message: `相关产品【${incompleteProduct.productName}】请填写完整`,
+            type: 'warning',
+        });
+        return false;
     }
-    productTable.value.forEach((item: any) => {
+
+    list.forEach((item: any) => {
         delete item.index
     });
-    return productTable.value
+    return list || []
 }
 
+const selectedQuantity = computed(() => {
+    return productTable.value.filter((item: any) => item.productId).length
+})
+
+const totalAmount = computed(() => {
+    return productTable.value.filter((item: any) => item.productId).reduce((pre: number, cur: any) => {
+        return pre + (cur.totalPrice || 0)
+    }, 0)
+})
+
 watchEffect(() => {
     const { productTableList, height, productTableListValue = [] } = props
     console.log(productTableListValue, '<==== 数据')

+ 1 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/main.ts

@@ -31,6 +31,7 @@ app.config.globalProperties.$echarts = echarts;
 app
   .use(ElementPlus, {
     locale: zhCn,
+    zIndex: 1900,
   })
   .use(createPinia())
   .use(router)

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/component/information.vue

@@ -32,7 +32,7 @@
             </div>
             <div class="formItem flex pt-5 pb-1">
                 <div class="w-22 text-right text-gray-500">负责人:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ information.creatorName }}</div>
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ information.inchargerName }}</div>
             </div>
             <div class="formItem flex pt-5 pb-1">
                 <div class="w-22 text-right text-gray-500">预计成交日期:</div>

+ 5 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/component/products.vue

@@ -58,6 +58,7 @@ import { post } from '@/utils/request';
 import RelatedProducts from '@/components/relatedProducts/relatedProducts.vue'
 import { UPDATEINSET } from '../api';
 import { all } from 'axios';
+import { judgmentaAmounteEqual } from '@/utils/tools';
 
 const emits = defineEmits(['refreshData']);
 const props = defineProps<{
@@ -78,10 +79,13 @@ const allLoading = reactive({
 
 function editProduct() {
     let productTableListData = relatedProductsRef?.value?.returnData()
+    const { id, name, customerId, contactsId, amountOfMoney, expectedTransactionDate, stageId, inchargerId, remark } = information.value
+    if(!productTableListData || judgmentaAmounteEqual({ amountOfMoney }, productTableListData)) {
+      return
+    }
     productTableListData.forEach((item: any) => {
         delete item.id
     })
-    const { id, name, customerId, contactsId, amountOfMoney, expectedTransactionDate, stageId, inchargerId, remark } = information.value
     const formData = { id, name, customerId, contactsId, amountOfMoney, expectedTransactionDate, stageId, inchargerId, remark }
     allLoading.editProductLoading = true
     post(UPDATEINSET, { ...formData, businessItemProductList: JSON.stringify(productTableListData) }).then((_res) => {

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/component/relatedTasks.vue

@@ -3,7 +3,7 @@
         <div class="flex justify-between">
             <div class="title">相关任务</div>
             <div>
-                <el-button type="primary">新建任务</el-button>
+                <el-button type="primary" v-permission="['tasksAdd']">新建任务</el-button>
             </div>
         </div>
         <div class="flex-1 overflow-auto pt-3">

+ 34 - 12
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/index.vue

@@ -29,8 +29,8 @@
               </el-select>
             </el-form-item>
             <el-form-item label="创建时间">
-              <el-date-picker v-model="businessOpportunityForm.startTime" type="date" placeholder="请选择" :clearable="false"
-                format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
+              <el-date-picker v-model="businessOpportunityForm.startTime" type="date" placeholder="请选择"
+                :clearable="false" format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
             </el-form-item>
             <el-form-item label="">
               <el-date-picker v-model="businessOpportunityForm.endTime" type="date" placeholder="请选择" :clearable="false"
@@ -47,14 +47,17 @@
     <div class="flex-1 p-5 overflow-auto">
       <div class="bg-white w-full h-full p-3 shadow-md rounded-md flex flex-col">
         <div class="flex justify-end pb-3">
-          <el-button v-permission="['businessAddAnEdit']" type="primary" @click="editNewBusiness(false)">新建商机</el-button>
+          <el-button v-permission="['businessAddAnEdit']" type="primary"
+            @click="editNewBusiness(false)">新建商机</el-button>
           <el-button type="primary" @click="showVisible('batchTransferVisible')"
             :disabled="batchTableData.length <= 0">批量转移</el-button>
           <el-button type="primary" @click="batchDeteleItem()" :disabled="batchTableData.length <= 0">批量删除</el-button>
           <el-button type="primary" @click="showVisible('stageSetVisible')">阶段设置</el-button>
           <el-button type="primary" @click="showVisible('deteleBusinessVisible')">回收站</el-button>
-          <el-button v-permission="['businessImport']" type="primary" @click="showVisible('importVisible')">导入</el-button>
-          <el-button v-permission="['businessExport']" type="primary" @click="exportBusinessTableList()" :loading="allLoading.exoprtLoading">导出</el-button>
+          <el-button v-permission="['businessImport']" type="primary"
+            @click="showVisible('importVisible')">导入</el-button>
+          <el-button v-permission="['businessExport']" type="primary" @click="exportBusinessTableList()"
+            :loading="allLoading.exoprtLoading">导出</el-button>
         </div>
         <div class="flex-1 w-full overflow-hidden">
           <el-table ref="businessTableRef" :data="businessTable" border v-loading="allLoading.businessTableLading"
@@ -70,16 +73,19 @@
             </el-table-column>
             <el-table-column label="操作" fixed="right" width="200">
               <template #default="scope">
-                <el-button link type="primary" size="large" @click="editNewBusiness(scope.row)" v-permission="['businessAddAnEdit']">编辑</el-button>
-                <el-button link type="primary" size="large" @click="newTask(scope.row)" v-permission="['tasksAdd']">新建任务</el-button>
-                <el-button link type="danger" size="large"
-                  @click="businessDeteleItem(scope.row.id, scope.row.name)" v-permission="['businessAddAnEdit']">删除</el-button>
+                <el-button link type="primary" size="large" @click="editNewBusiness(scope.row)"
+                  v-permission="['businessAddAnEdit']">编辑</el-button>
+                <el-button link type="primary" size="large" @click="newTask(scope.row)"
+                  v-permission="['tasksAdd']">新建任务</el-button>
+                <el-button link type="danger" size="large" @click="businessDeteleItem(scope.row.id, scope.row.name)"
+                  v-permission="['businessAddAnEdit']">删除</el-button>
               </template>
             </el-table-column>
           </el-table>
         </div>
         <div class="flex justify-end pt-3">
-          <el-pagination layout="total, prev, pager, next, sizes" :total="businessTotalTable"
+          <el-pagination layout="total, prev, pager, next, sizes" :page-size="businessOpportunityForm.pageFrom"
+            @size-change="handleSizeChange" @current-change="handleCurrentChange" :total="businessTotalTable"
             :hide-on-single-page="true" />
         </div>
       </div>
@@ -173,7 +179,7 @@ import { useRouter, useRoute } from "vue-router";
 import { GETSYSFILED, MOD, GETPERSONNEL, GETGENERATEFOEM, GETBUSINESSLIST, UPDATEINSET, BUSINESSDETELE, BATCHTRANSFER, MODURL, tableColumn, BUSIESS_GETSATE, URL_IMPOERBUSINESS, BUSIESS_INFO, URL_EXPORTBUSINESS } from './api'
 import { GETTABLELIST } from '@/pages/product/api'
 import { post, get, uploadFile } from "@/utils/request";
-import { getAllListByCode, getFromValue, resetFromValue, getFirstDayOfMonth, createTaskFromType, formatDate, confirmAction, downloadTemplate, downloadFile } from '@/utils/tools'
+import { getAllListByCode, getFromValue, resetFromValue, getFirstDayOfMonth, createTaskFromType, formatDate, confirmAction, downloadTemplate, downloadFile, judgmentaAmounteEqual } from '@/utils/tools'
 import { createTask } from '@/components/TaskModal/taskFunction'
 import { formatDateTime } from '@/utils/times'
 import { GenerateForm } from '@zmjs/form-design';
@@ -246,7 +252,12 @@ const productTableListValue = ref([])
 
 function editBusiness(visibles: boolean) {
   businessTemplateRef.value?.getData().then((res: any) => {
-    let productTableListData = relatedProductsRef?.value?.returnData() || []
+    let productTableListData = relatedProductsRef?.value?.returnData()
+    console.log(!productTableListData, judgmentaAmounteEqual({...businessTemplateValue.value, ...res}, productTableListData))
+    if(!productTableListData || judgmentaAmounteEqual({...businessTemplateValue.value, ...res}, productTableListData)) {
+      return
+    }
+
     productTableListData.forEach((item: any) => {
       delete item.id
     })
@@ -393,6 +404,17 @@ function editProduct(row: any) {
   })
 }
 
+function handleSizeChange(val: number) {
+  businessOpportunityForm.pageIndex = 1
+  businessOpportunityForm.pageFrom = val
+  getBusinessTableList()
+}
+
+function handleCurrentChange(val: number) {
+  businessOpportunityForm.pageIndex = val
+  getBusinessTableList()
+}
+
 function showVisible(type: keyof typeof allVisible) { // 显示弹窗
   allVisible[type] = true
 }

+ 2 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/type.d.ts

@@ -8,8 +8,8 @@ interface businessOpportunityFormType {
   inchargerId: string | number;
   startTime: string | number;
   endTime: string | number;
-  pageIndex: string | number;
-  pageFrom: string | number;
+  pageIndex: number;
+  pageFrom: number;
 }
 
 interface fixedDataInterface {

+ 4 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/component/relatedBusiness.vue

@@ -57,6 +57,7 @@ import RelatedProducts from '@/components/relatedProducts/relatedProducts.vue'
 import { formatDateTime } from '@/utils/times';
 import { GETGENERATEFOEM, UPDATEINSET } from '@/pages/business/api';
 import { GETTABLELIST } from '@/pages/product/api';
+import { judgmentaAmounteEqual } from '@/utils/tools';
 
 const router = useRouter()
 const globalPopup = inject<GlobalPopup>('globalPopup')
@@ -95,6 +96,9 @@ function toBusDetal(row: any) {
 function editBusiness() {
     businessTemplateRef.value?.getData().then((res: any) => {
         let productTableListData = relatedProductsRef?.value?.returnData()
+        if(!productTableListData || judgmentaAmounteEqual({ ...businessTemplateValue.value, ...res }, productTableListData)) {
+            return
+        }
         let newForm = {
             ...res,
             expectedTransactionDate: res.expectedTransactionDate ? formatDateTime(new Date(res.expectedTransactionDate)) : '',

+ 5 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/component/relatedBusiness.vue

@@ -54,7 +54,7 @@ import { GenerateForm } from '@zmjs/form-design';
 import RelatedProducts from '@/components/relatedProducts/relatedProducts.vue'
 import { GETTABLELIST } from '@/pages/product/api';
 import { GETGENERATEFOEM, UPDATEINSET } from '@/pages/business/api';
-import { setTemplateDataDisable } from '@/utils/tools';
+import { judgmentaAmounteEqual, setTemplateDataDisable } from '@/utils/tools';
 import { formatDateTime } from '@/utils/times';
 
 const emits = defineEmits(['refreshData']);
@@ -86,7 +86,10 @@ const allLoading = reactive({
 
 function editBusiness(visibles: boolean) {
     businessTemplateRef.value?.getData().then((res: any) => {
-        let productTableListData = relatedProductsRef?.value?.returnData() || []
+        let productTableListData = relatedProductsRef?.value?.returnData()
+        if(!productTableListData || judgmentaAmounteEqual({ ...businessTemplateValue.value, ...res }, productTableListData)) {
+            return
+        }
         productTableListData.forEach((item: any) => {
             delete item.id
         })

+ 4 - 4
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/customer/index.vue

@@ -8,7 +8,7 @@
               <el-input v-model="customerCriteriaForm.customName" clearable placeholder="请输入"></el-input>
             </el-form-item>
             <el-form-item label="客户来源">
-              <el-select v-model="customerCriteriaForm.customSourceId" placeholder="请选择">
+              <el-select v-model="customerCriteriaForm.customSourceId" placeholder="请选择" clearable>
                 <el-option v-for="item in fixedData.ClueSources" :key="item.id" :label="item.name" :value="item.id" />
               </el-select>
             </el-form-item>
@@ -19,17 +19,17 @@
               <el-input v-model="customerCriteriaForm.email" clearable placeholder="请输入"></el-input>
             </el-form-item>
             <el-form-item label="客户行业">
-              <el-select v-model="customerCriteriaForm.customerIndustryId" placeholder="请选择">
+              <el-select v-model="customerCriteriaForm.customerIndustryId" placeholder="请选择" clearable>
                 <el-option v-for="item in fixedData.CustomIndustry" :key="item.id" :label="item.name" :value="item.id" />
               </el-select>
             </el-form-item>
             <el-form-item label="客户级别">
-              <el-select v-model="customerCriteriaForm.customerLevelId" placeholder="请选择">
+              <el-select v-model="customerCriteriaForm.customerLevelId" placeholder="请选择" clearable>
                 <el-option v-for="item in fixedData.CustomLevel" :key="item.id" :label="item.name" :value="item.id" />
               </el-select>
             </el-form-item>
             <el-form-item label="负责人">
-              <el-select v-model="customerCriteriaForm.inchargerId" placeholder="请选择">
+              <el-select v-model="customerCriteriaForm.inchargerId" placeholder="请选择" clearable>
                 <el-option v-for="item in fixedData.Personnel" :key="item.id" :label="item.name" :value="item.id" />
               </el-select>
             </el-form-item>

+ 1 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/constant.ts

@@ -6,6 +6,7 @@ export const GETPERSONNEL = '/user/getSimpleActiveUserList'
 export const GETTEMPLATE = `/sys-form/getListByCode${MOD}`
 export const GETTEMPLATETWO = `/sys-form/getListByCode/business`
 export const GETTABLE = `${prefix}/listClue`
+export const GETTALLCLUE = `${prefix}/getAll`
 export const GETDETAIL = `${prefix}/getDetail`
 export const UNDATECLAIM = `${prefix}/claim`
 export const UNDATEFORM = `${prefix}/insertAndUpdate`

+ 58 - 17
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/detail/components/information.vue

@@ -3,54 +3,63 @@
         <div class="flex justify-between">
             <div class="title">基本信息</div>
             <div>
-                <el-button type="primary" @click="showVisible('newBusinessisible')">转为商机</el-button>
+                <el-button type="primary" v-permission="['threadEdit', userInfo.id == information.inchargerId]"
+                    @click="showVisible('newBusinessisible')">转为商机</el-button>
                 <el-button type="primary" @click="claimClues()" v-if="!information.inchargerName">认领</el-button>
                 <el-button type="primary" @click="showVisible('clueDialogVisible')" v-else>转移</el-button>
-                <el-button type="primary" @click="editClue(information)">编辑</el-button>
+                <el-button type="primary" @click="editClue(information)" v-permission="['tasksAdd']">编辑</el-button>
             </div>
         </div>
         <div class="form flex flex-wrap justify-between">
             <div class="formItem flex pt-3 pb-1">
                 <div class="w-20 text-right text-gray-500">线索名称:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ information.clueName }}</div>
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1" v-ellipsis-tooltip>{{
+                    information.clueName }}</div>
             </div>
             <div class="formItem flex pt-3 pb-1">
                 <div class="w-20 text-right text-gray-500">线索来源:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ information.clueSourceValue }}
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1" v-ellipsis-tooltip>{{
+                    information.clueSourceValue }}
                 </div>
             </div>
             <div class="formItem flex pt-3 pb-1">
                 <div class="w-20 text-right text-gray-500">电话号码:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ information.phone }}</div>
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1" v-ellipsis-tooltip>{{
+                    information.phone }}</div>
             </div>
             <div class="formItem flex pt-3 pb-1">
                 <div class="w-20 text-right text-gray-500">邮箱:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ information.email }}</div>
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1" v-ellipsis-tooltip>{{
+                    information.email }}</div>
             </div>
             <div class="formItem flex pt-3 pb-1">
                 <div class="w-20 text-right text-gray-500">客户行业:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1" v-ellipsis-tooltip>{{
                     information.customerIndustryValue
-                }}</div>
+                    }}</div>
             </div>
             <div class="formItem flex pt-3 pb-1">
                 <div class="w-20 text-right text-gray-500">客户级别:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ information.customerLevelValue
-                }}
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1" v-ellipsis-tooltip>{{
+                    information.customerLevelValue
+                    }}
                 </div>
             </div>
             <div class="formItem flex pt-3 pb-1">
                 <div class="w-20 text-right text-gray-500">客户地址:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ information.address }}</div>
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1" v-ellipsis-tooltip>{{
+                    information.address }}</div>
             </div>
             <div class="formItem flex pt-3 pb-1">
                 <div class="w-20 text-right text-gray-500">负责人:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ information.inchargerName }}
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1" v-ellipsis-tooltip>{{
+                    information.inchargerName }}
                 </div>
             </div>
             <div class="formItem flex pt-3 pb-1">
                 <div class="w-20 text-right text-gray-500">创建人:</div>
-                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ information.createName }}</div>
+                <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1" v-ellipsis-tooltip>{{
+                    information.createName }}</div>
             </div>
             <div class="formItem flex pt-3 pb-1">
                 <div class="w-20 text-right text-gray-500">创建时间:</div>
@@ -59,7 +68,7 @@
             </div>
             <div class="formItem flex pt-3 pb-1" style="width: 100%;">
                 <div class="w-20 text-right text-gray-500">备注:</div>
-                <div class="flex-1 ml-1 text ">
+                <div class="flex-1 ml-1 text" v-ellipsis-tooltip>
                     {{ information.remark }}
                 </div>
             </div>
@@ -89,7 +98,8 @@
                 <div class="flex justify-between items-center border-b pb-3 dialog-header">
                     <h4 :id="titleId">{{ allText.clueText }}</h4>
                     <div>
-                        <el-button type="primary" :loading="allLoading.clueLoading" @click="transferClues()">转移</el-button>
+                        <el-button type="primary" :loading="allLoading.clueLoading"
+                            @click="transferClues()">转移</el-button>
                         <el-button @click="dialogVisible.clueDialogVisible = false">取消</el-button>
                     </div>
                 </div>
@@ -120,7 +130,7 @@
             <div class="h-[60vh] overflow-y-auto scroll-bar pt-3">
                 <GenerateForm ref="generateFormDataRef" :data="generateFormData" :value="generateFormVal" />
                 <div>相关产品</div>
-                <RelatedProducts ref="relatedProductsRef" :productTableList="productTableList" />
+                <RelatedProducts ref="relatedProductsRef" :productTableList="productTableList" :productTableListValue="{}" />
             </div>
         </el-dialog>
     </div>
@@ -128,7 +138,7 @@
 <script lang="ts" setup>
 import { ref, reactive, onMounted, onUnmounted, defineExpose, inject, watchEffect } from 'vue'
 import { GenerateForm } from '@zmjs/form-design';
-import { formatDate, confirmAction, backPath } from '@/utils/tools'
+import { formatDate, confirmAction, backPath, judgmentaAmounteEqual } from '@/utils/tools'
 import { GETTEMPLATE, UNDATEFORM, GETPERSONNEL, UNDATECLAIM, GETTEMPLATETWO } from '../../constant'
 import { get, post } from '@/utils/request'
 import { useStore } from '@/store/index'
@@ -137,6 +147,7 @@ import RelatedProducts from '@/components/relatedProducts/relatedProducts.vue'
 import { all } from 'axios';
 import { formatDateTime } from '@/utils/times';
 import { UPDATEINSET } from '@/pages/business/api';
+import { GETTABLELIST } from '@/pages/product/api';
 
 interface personnelInterface {
     id: string | number,
@@ -191,6 +202,9 @@ const transferOptions = ref<personnelInterface[]>([]) // 转移人员列表
 function transferBusiness() {
     generateFormDataRef.value?.getData().then((res: any) => {
         let productTableListData = relatedProductsRef?.value?.returnData()
+        if(!productTableListData || judgmentaAmounteEqual({ ...res }, productTableListData)) {
+            return
+        }
         let newForm = {
             ...res,
             expectedTransactionDate: res.expectedTransactionDate ? formatDateTime(new Date(res.expectedTransactionDate)) : '',
@@ -304,6 +318,32 @@ async function getSystemField() {
     })
 }
 
+function getProductTableList() {
+    post(GETTABLELIST, { pageIndex: -1, pageSize: -1 }).then((res) => {
+        if (res.code == 'ok') {
+            const { record, total } = res.data
+            productTableList.value = record.map((item: any) => {
+                const { id, productName, productCode, unit, unitName, typeName, type, price, inventory } = item
+                return {
+                    id,
+                    productId: id,
+                    productName,
+                    productCode,
+                    unit,
+                    unitName,
+                    price,
+                    type,
+                    typeName,
+                    inventory,
+                    quantity: '',
+                    discount: '',
+                    totalPrice: ''
+                }
+            })
+        }
+    })
+}
+
 watchEffect(() => {
     receiveAssignment(props)
 });
@@ -317,6 +357,7 @@ onMounted(async () => {
     let newData = JSON.parse(data.data[0].config)
     generateFormData.value = newData
     getSystemField()
+    getProductTableList()
 });
 </script>
 <style scoped lang="scss">

+ 3 - 3
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/detail/components/operationRecord.vue

@@ -5,7 +5,7 @@
         </div>
         <div class="flex-1 overflow-auto pt-5">
             <el-table :data="operationRecordtable" border style="width: 100%;height: 100%;">
-                <el-table-column prop="creatTime" label="操作时间" width="140" />
+                <el-table-column prop="creatTime" label="操作时间" width="150" />
                 <el-table-column prop="userName" label="操作人" width="120" />
                 <el-table-column prop="name" label="操作内容" />
             </el-table>
@@ -13,7 +13,7 @@
     </div>
 </template>
 <script lang="ts" setup>
-import { formatDate } from '@/utils/tools';
+import { formatDateMinutes } from '@/utils/times';
 import { ref, onMounted, watchEffect } from 'vue'
 
 const props = defineProps<{
@@ -24,7 +24,7 @@ const operationRecordtable = ref([])
 
 watchEffect(() => {
     props.data.forEach((item: any) => {
-        item.creatTime = formatDate(new Date(item.creatTime))
+        item.creatTime = formatDateMinutes(new Date(item.creatTime))
     })
     operationRecordtable.value = props.data
 });

+ 62 - 19
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/detail/index.vue

@@ -1,51 +1,86 @@
 <template>
-  <div class="h-full threadDetail">
-    <div class="layout p-3">
-      <div class="bg-white w-1/2 shadow-md rounded-md">
-        <Information :data="information" @refreshData="refreshData"></Information>
+  <div class="h-full flex p-3 flex-col thredDetail">
+    <div class="w-full bg-white p-2 mb-2 shadow-md rounded-md flex items-center">
+      <div class="icon mr-4">
+        <el-link :underline="false" @click="backPath()">
+          <el-icon class="el-icon--right"><icon-view /></el-icon> 返回线索列表
+        </el-link>
       </div>
-      <div class="bg-white w-1/2 ml-3 shadow-md rounded-md">
-        <Attachment :data="attachment" :information="information" @refreshData="refreshData"></Attachment>
+      <div class="mr-8">
+        <el-select v-model="values" placeholder="请选择" style="width: 250px" @change="getDetail()">
+          <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
+        </el-select>
       </div>
     </div>
-    <div class="layout pl-3 pr-3 pb-3">
-      <div class="bg-white w-2/3 shadow-md rounded-md">
-        <DetailCompinents :data="relatedTasks" :information="information" :formTaskType="3" :disabledList="['taskType', 'clueId']" :filed="'clueId'" @refreshData="refreshData"></DetailCompinents>
-      </div>
-      <div class="bg-white w-1/3 ml-3 shadow-md rounded-md">
-        <OperationRecord :data="operationRecord" :information="information" @refreshData="refreshData"></OperationRecord>
+    <div class="flex-1 flex flex-col overflow-y-auto overflow-x-hidden scroll-bar" v-loading="loadings">
+      <div class="h-full threadDetail">
+        <div class="layout">
+          <div class="bg-white w-1/2 shadow-md rounded-md">
+            <Information :data="information" @refreshData="refreshData"></Information>
+          </div>
+          <div class="bg-white w-1/2 ml-3 shadow-md rounded-md">
+            <Attachment :data="attachment" :information="information" @refreshData="refreshData"></Attachment>
+          </div>
+        </div>
+        <div class="layout pt-3">
+          <div class="bg-white w-2/3 shadow-md rounded-md">
+            <DetailCompinents :data="relatedTasks" :information="information" :formTaskType="3"
+              :disabledList="['taskType', 'clueId']" :filed="'clueId'" @refreshData="refreshData"></DetailCompinents>
+          </div>
+          <div class="bg-white w-1/3 ml-3 shadow-md rounded-md">
+            <OperationRecord :data="operationRecord" :information="information" @refreshData="refreshData">
+            </OperationRecord>
+          </div>
+        </div>
       </div>
     </div>
   </div>
+
 </template>
-  
+
 <script lang="ts" setup>
 import Information from './components/information.vue'
 import Attachment from './components/attachment.vue'
 import DetailCompinents from '@/components/detailcompinents/relatedTasks.vue'
 import OperationRecord from './components/operationRecord.vue';
 import { ref, reactive, onMounted, inject } from "vue";
+import { Edit, ArrowLeft as IconView } from '@element-plus/icons-vue'
 import { post, get } from "@/utils/request";
 import { useRouter, useRoute } from "vue-router";
-import { GETDETAIL } from "../constant"
+import { GETDETAIL, GETTALLCLUE } from "../constant"
+import { backPath } from '@/utils/tools'
 
 const route = useRoute()
 
 const globalPopup = inject<GlobalPopup>('globalPopup')
-const addressParameters: any = ref(0) // 地址上的参数
+const values = ref<any>('')
+const options = ref<optionType[]>([])
 const information = ref({}) // 基本信息
 const attachment = ref([]) // 附件
 const relatedTasks = ref([]) // 相关任务
 const operationRecord = ref([]) // 操作记录
+const loadings = ref(false)
 
 function getDetail() {
-  const id = addressParameters.value
+  const id = values.value
+  loadings.value = true
   post(GETDETAIL, { id }).then((res) => {
     const { clueLogList, files, taskList } = res.data
     information.value = res.data
     attachment.value = files || []
     relatedTasks.value = taskList || []
     operationRecord.value = clueLogList || []
+  }).finally(() => {
+    loadings.value = false
+  })
+}
+
+function getAllClue() {
+  post(GETTALLCLUE, { }).then(({ data }) => {
+    options.value = (data ?? []).map((item: { clueName: string; id: number }) => ({
+      label: item.clueName,
+      value: item.id
+    }));
   })
 }
 
@@ -55,13 +90,21 @@ function refreshData() {
 
 onMounted(() => {
   const { id } = route.query
-  addressParameters.value = id
+  values.value = id ? +id : ''
   getDetail()
-
+  getAllClue()
 })
 </script>
-  
+
 <style lang="scss" scoped>
+.thredDetail {
+  .icon {
+    .el-link {
+      color: #0052CC;
+    }
+  }
+}
+
 .threadDetail {
   display: flex;
   flex-direction: column;

+ 31 - 16
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/index.vue

@@ -52,22 +52,20 @@
     <div class="flex-1 p-5 overflow-auto">
       <div class="bg-white w-full h-full p-3 shadow-md rounded-md flex flex-col">
         <div class="flex justify-end pb-3">
-          <el-button type="primary" @click="editClue(false)">新建线索</el-button>
-          <el-button type="primary" @click="batchTransfer()">批量转移</el-button>
-          <el-button type="primary" @click="batchDeletes()">批量删除</el-button>
+          <el-button type="primary" v-permission="['threadAdd']" @click="editClue(false)">新建线索</el-button>
+          <el-button type="primary" :disabled="batchTableData.length <= 0" @click="batchTransfer()">批量转移</el-button>
+          <el-button type="primary" :disabled="batchTableData.length <= 0" @click="batchDeletes()">批量删除</el-button>
           <el-button type="primary" @click="showDeteleClue(true)">回收站</el-button>
-          <el-button type="primary" @click="dialogVisible.importVisible = true">导入</el-button>
-          <el-button type="primary" @click="exportTheadTableList()" :loading="allLoading.exoprtLoading">导出</el-button>
+          <el-button type="primary" v-permission="['threadImport']" @click="dialogVisible.importVisible = true">导入</el-button>
+          <el-button type="primary" v-permission="['threadExport']" @click="exportTheadTableList()" :loading="allLoading.exoprtLoading">导出</el-button>
         </div>
         <div class="flex-1 w-full overflow-hidden">
-          <el-table ref="clueTableRef" :data="clueTable" border v-loading="allLoading.clueTableLading"
-            style="width: 100%;height: 100%;">
+          <el-table :show-overflow-tooltip="tableShowOverflowTooltip" ref="clueTableRef" :data="clueTable" border v-loading="allLoading.clueTableLading"
+            style="width: 100%;height: 100%;" @selection-change="changeBatch">
             <el-table-column type="selection" width="55" />
             <el-table-column prop="clueName" label="线索名称" width="180">
               <template #default="scope">
-                <el-button link type="primary" size="large" @click.prevent="toClueTableDetail(scope.row)">{{
-                  scope.row.clueName
-                }}</el-button>
+                <div class="table-text-textnowrap" @click.prevent="toClueTableDetail(scope.row)">{{ scope.row.clueName }}</div>
               </template>
             </el-table-column>
             <el-table-column prop="clueSourceValue" label="线索来源" width="180"></el-table-column>
@@ -80,11 +78,11 @@
             <el-table-column prop="createTime" label="创建时间" width="180"></el-table-column>
             <el-table-column label="操作" fixed="right" width="200">
               <template #default="scope">
-                <el-button link type="primary" size="large" @click="editClue(scope.row)">编辑</el-button>
+                <el-button link type="primary" size="large" @click="editClue(scope.row)" v-permission="['threadEdit']">编辑</el-button>
                 <!-- <el-button link type="primary" size="large"
                   @click="dialogVisible.taskModalVisible = true">新建任务</el-button> -->
-                <el-button link type="primary" size="large" @click="newTask(scope.row)">新建任务</el-button>
-                <el-button link type="danger" size="large" @click.prevent="deleteRow(scope.row)">删除</el-button>
+                <el-button link type="primary" size="large" @click="newTask(scope.row)" v-permission="['tasksAdd']">新建任务</el-button>
+                <el-button link type="danger" size="large" @click.prevent="deleteRow(scope.row)" v-permission="['threadEdit']">删除</el-button>
               </template>
             </el-table-column>
           </el-table>
@@ -103,8 +101,8 @@
         <div class="flex justify-between items-center border-b pb-3 dialog-header">
           <h4 :id="titleId">{{ allText.editClueText }}</h4>
           <div>
-            <el-button type="primary" @click="saveEditClue(true)">保存并新建</el-button>
-            <el-button type="primary" @click="saveEditClue(false)">保存</el-button>
+            <el-button type="primary" :loading="allLoading.clueSaveLoading" @click="saveEditClue(true)">保存并新建</el-button>
+            <el-button type="primary" :loading="allLoading.clueSaveLoading" @click="saveEditClue(false)">保存</el-button>
             <el-button @click="dialogVisible.editClueDialogVisible = false">取消</el-button>
           </div>
         </div>
@@ -178,6 +176,7 @@ import { GenerateForm } from '@zmjs/form-design';
 import TaskModal from '@/components/TaskModal/index.vue'
 import DeteleTables from "./deteleTables.vue";
 import { createTask } from "@/components/TaskModal/taskFunction";
+import { tableShowOverflowTooltip } from '@/utils/globalVariables'
 
 // 定义类型
 interface fixedDataInterface {
@@ -220,6 +219,7 @@ const allLoading = reactive({
   clueLoading: false,
   importLoading: false,
   exoprtLoading: false,
+  clueSaveLoading: false
 })
 const dialogVisible = reactive({
   editClueDialogVisible: false,
@@ -248,6 +248,7 @@ const clueTemplate = ref({
 }) // 线索模板
 const editForm = ref({}) // 编辑表单
 const taskModalForm = ref({}) // 任务弹窗表单
+const batchTableData = ref([])
 
 // 批量变量
 const transferForm = reactive({
@@ -289,6 +290,7 @@ function transferClues() {
     if (res.code == 'ok') {
       globalPopup?.showSuccess('批量转移成功')
       dialogVisible.clueDialogVisible = false
+      changeBatch(false)
       getClueTable()
     }
   })
@@ -344,13 +346,14 @@ async function saveEditClue(flag: boolean) {
   const data = await generateForm.value.getData()
   let newData = { ...editForm.value, ...data }
   delete newData.createTime
+  allLoading.clueSaveLoading = true
   post(UNDATEFORM, { ...newData }).then((res) => {
     if (res.code != 'ok') {
       globalPopup?.showError(res.msg)
       return
     }
     globalPopup?.showSuccess('保存成功')
-    if (!flag) {
+    if (flag) {
       editForm.value = {}
       generateForm.value && generateForm.value.reset()
       generateFormKey.value++
@@ -359,6 +362,8 @@ async function saveEditClue(flag: boolean) {
     getClueTable()
   }).catch((_err) => {
     console.log(_err)
+  }).finally(() => {
+    allLoading.clueSaveLoading = false
   })
 }
 
@@ -391,6 +396,15 @@ async function importProducts(param: UploadRequestOptions) {
   globalPopup?.showError(res.msg || '')
 }
 
+function changeBatch(flag: boolean = true) {
+  if (flag) {
+    batchTableData.value = clueTableRef.value && clueTableRef.value.getSelectionRows()
+  } else {
+    batchTableData.value = []
+    clueTableRef.value && clueTableRef.value.clearSelection()
+  }
+}
+
 function batchTransfer() {
   const data = clueTableRef.value && clueTableRef.value.getSelectionRows()
   if (!data.length) {
@@ -417,6 +431,7 @@ function batchDeletes() {
         return
       }
       globalPopup?.showSuccess('删除成功')
+      changeBatch(false)
       getClueTable()
     })
   })

+ 12 - 3
fhKeeper/formulahousekeeper/customerBuler-crm/src/styles/global.scss

@@ -23,7 +23,7 @@ $modena: #6f4afe;
 }
 
 .scroll-bar::-webkit-scrollbar-thumb {
-  background: linear-gradient(to bottom right, #C1C1C1 0%, #C1C1C1 100%);
+  background: linear-gradient(to bottom right, #c1c1c1 0%, #c1c1c1 100%);
   border-radius: 5px;
 }
 
@@ -33,7 +33,7 @@ $modena: #6f4afe;
 }
 
 .scroll-bar::-webkit-scrollbar-button {
-  background-color: #C1C1C1;
+  background-color: #c1c1c1;
   border-radius: 2px;
   height: 4px;
 }
@@ -47,7 +47,16 @@ $modena: #6f4afe;
   height: 0px;
 }
 
-.el-dialog__header, .el-dialog__body{
+.el-dialog__header,
+.el-dialog__body {
   margin: 0 !important;
   padding: 0 !important;
 }
+
+.table-text-textnowrap {
+  white-space: nowrap;  
+  overflow: hidden;
+  text-overflow: ellipsis;
+  color: #075985;
+  cursor: pointer;
+}

+ 62 - 15
fhKeeper/formulahousekeeper/customerBuler-crm/src/utils/customInstructions.ts

@@ -1,25 +1,30 @@
-import { Directive, ObjectDirective } from 'vue';
+import { Directive, ObjectDirective, DirectiveBinding, render, createVNode, h } from 'vue';
+import { ElTooltip } from 'element-plus';
+import 'element-plus/theme-chalk/el-tooltip.css';
 
 // 权限控制
-const PermissionDirective: Directive = {
-    mounted(el: HTMLElement, binding: { value: string[] }, vnode: any) {
+const PermissionDirective: Directive = { // 数组, 权限 code 和 布尔值,
+    // mounted(el: HTMLElement, binding: { value: (string | boolean)[] }, vnode: any) {
+    updated(el: HTMLElement, binding: { value: (string | boolean)[] }, vnode: any) {
         const routePath: string = vnode.ctx.appContext.config.globalProperties.$route.path;
         const userInfo: { userInfo: { functionList: { code: string }[] } } | null = JSON.parse(localStorage.getItem('storeInfo') || '');
         const authorityCodes: string[] = (userInfo?.userInfo?.functionList || []).map(({ code }) => code);
-        const permissions: string[] = binding.value;
+        const permissions: (string | boolean)[] = binding.value;
+        const hasPermission: any[] = (binding.value || []).filter(item => typeof item !== 'boolean');
 
         if (!Array.isArray(permissions)) {
             console.error('权限必须以数组形式提供');
             return;
         }
 
-        if (!permissions.every(permission => authorityCodes.includes(permission))) {
-            el.parentNode && el.parentNode.removeChild(el);
+        if (permissions.some((element): element is boolean => element === true)) {
+            return;
         }
 
-        console.log(extractPath(routePath), authorityCodes);
-        console.log(permissions, !permissions.every(permission => authorityCodes.includes(permission)))
-    }
+        if (!hasPermission.every(permission => authorityCodes.includes(permission))) {
+            el.parentNode && el.parentNode.removeChild(el);
+        }
+    },
 };
 
 // input 字符串数字
@@ -32,7 +37,50 @@ const PositiveIntegerDirective: ObjectDirective = {
     },
 };
 
-function handleInput(event: Event) {
+// 检测文字是否被省略并显示工具提示
+const EllipsisTooltipDirective: ObjectDirective = {
+    mounted(el: HTMLElement) {
+        const tooltipVNode = createVNode(ElTooltip, {
+            content: el.textContent,
+            placement: 'top',
+            effect: 'dark'
+        }, {
+            default: () => h('span', '')
+        });
+
+        const tooltipWrapper = document.createElement('div');
+        document.body.appendChild(tooltipWrapper);
+        render(tooltipVNode, tooltipWrapper);
+
+        el.addEventListener('mouseenter', (event: MouseEvent) => {
+            if (isTextEllipsis(el)) {
+                tooltipVNode.component!.props.content = el.textContent;
+                tooltipVNode.component!.props.visible = true;
+                const targetElement = event.currentTarget as HTMLElement;
+                const { clientWidth, clientHeight } = targetElement;
+                const { top, left } = targetElement.getBoundingClientRect();
+
+                tooltipWrapper.style.position = 'absolute';
+                tooltipWrapper.style.left = `${left + 10}px`;
+                tooltipWrapper.style.top = `${top}px`;
+                // tooltipWrapper.style.width = `${clientWidth}px`;
+                // tooltipWrapper.style.height = `${clientHeight}px`;
+            }
+        });
+
+        el.addEventListener('mouseleave', () => {
+            tooltipVNode.component!.props.visible = false;
+        });
+    },
+    unmounted(el: HTMLElement) {
+        el.removeEventListener('mouseenter', () => { });
+        el.removeEventListener('mouseleave', () => { });
+    }
+}
+
+
+// 对应方法
+function handleInput(event: Event) { // 处理输入
     const input = event.target as HTMLInputElement;
     const regex = /^\d*\.?\d*$/;
     if (!regex.test(input.value)) {
@@ -40,16 +88,15 @@ function handleInput(event: Event) {
     }
 }
 
-function extractPath(str: any) {
-    const startIndex = str.indexOf('/');
-    const endIndex = str.indexOf('/', startIndex + 1);
-    return str.slice(startIndex, endIndex !== -1 ? endIndex : undefined);
+function isTextEllipsis(element: HTMLElement): boolean { // 判断文字是否被省略
+    return element.scrollWidth > element.clientWidth || element.scrollHeight > element.clientHeight;
 }
 
 // 导出的自定义指令
 const customize = [
     { key: 'permission', directive: PermissionDirective, name: '角色权限' },
-    { key: 'enterNumber', directive: PositiveIntegerDirective, name: 'input正整数' }
+    { key: 'enterNumber', directive: PositiveIntegerDirective, name: 'input正整数' },
+    { key: 'ellipsisTooltip', directive: EllipsisTooltipDirective, name: '文字省略显示工具提示' },
 ]
 
 export default customize;

+ 2 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/utils/globalVariables.ts

@@ -0,0 +1,2 @@
+// 表格一行显示,超出 提示 Tooltip
+export const tableShowOverflowTooltip: any = { enterable: true, placement: 'top', showArrow: true, hideAfter: 200, popperOptions: { strategy: 'fixed' } }

+ 28 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/utils/tools.ts

@@ -1,4 +1,5 @@
 import { defalutModalForm } from "@/components/TaskModal/api";
+import { ElNotification } from "element-plus";
 import { ElMessageBox } from "element-plus";
 import { IMPORTTIMELIST } from '../pages/api'
 import { get, post } from "./request";
@@ -263,3 +264,30 @@ export function setTemplateDataDisable(list: Array<any>, fieldList: Array<any>)
   })
   return result;
 } 
+
+/**
+ * 新建商机指定方法,用来判断商机金额需与产品总金额是否相等
+ * @param mob 商机表单
+ * @param arr 相关产品
+ * @returns Boolean
+ */
+export function judgmentaAmounteEqual(mob: any, arr: any) {
+  if(!arr || arr.length <= 0) {
+    return false;
+  }
+  let flag = false;
+  const amounte = mob.amountOfMoney || 0;
+  const totalAmounte = arr.reduce((pre: number, cur: any) => pre + (cur.totalPrice || 0), 0);
+
+  if (amounte != totalAmounte) {
+    ElNotification.closeAll();
+    ElNotification({
+      title: '提示',
+      message: `商机金额${amounte > totalAmounte ? '大于' : '小于'}产品总金额,请修改`,
+      type: 'warning',
+    });
+    flag = true;
+  }
+
+  return flag;
+}

+ 89 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/FinancialAuditController.java

@@ -0,0 +1,89 @@
+package com.management.platform.controller;
+
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.management.platform.entity.FinancialAudit;
+import com.management.platform.entity.Project;
+import com.management.platform.entity.ProjectStage;
+import com.management.platform.entity.User;
+import com.management.platform.mapper.UserMapper;
+import com.management.platform.service.FinancialAuditService;
+import com.management.platform.service.ProjectStageService;
+import com.management.platform.util.HttpRespMsg;
+import com.management.platform.util.MessageUtils;
+import io.lettuce.core.pubsub.PubSubOutput;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-06-05
+ */
+@RestController
+@RequestMapping("/financial-audit")
+public class FinancialAuditController {
+    @Autowired
+    private FinancialAuditService financialAuditService;
+    @Resource
+    private UserMapper userMapper;
+
+    @RequestMapping("/list")
+    public HttpRespMsg list(Integer pageIndex, Integer pageSize, String startDate, String endDate, Integer status, HttpServletRequest request) throws ParseException {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        LambdaQueryWrapper<FinancialAudit> financialAuditLambdaQueryWrapper = new LambdaQueryWrapper<>();
+        financialAuditLambdaQueryWrapper.eq(FinancialAudit::getCompanyId,companyId).between(FinancialAudit::getReportYrmnth,startDate,endDate).eq(status!=0,FinancialAudit::getReviewStatus,status);
+
+//            QueryWrapper<FinancialAudit> queryWrapper = new QueryWrapper<FinancialAudit>()
+//                    .eq("company_id", companyId)
+//                    .eq("review_status", status)
+//                    .ge("report_yrMnth", startDate)
+//                    .le("report_yrMnth", endDate);
+
+        IPage<FinancialAudit> auditIPage = financialAuditService.page(new Page<FinancialAudit>(pageIndex, pageSize), financialAuditLambdaQueryWrapper);
+        Map<String, Object> map = new HashMap<>();
+        map.put("records", auditIPage.getRecords());
+        map.put("total", auditIPage.getTotal());
+    
+        httpRespMsg.data = map;  
+        return httpRespMsg;
+    }
+
+    @RequestMapping("/audit")
+    public HttpRespMsg audit(Integer id, HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        String token = request.getHeader("Token");
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
+        User user = userMapper.selectById(token);
+//                financialAuditService.update().eq("id", id).set("review_status", 2).set("reviewer_id", user.getId()).set("reviewer_name", user.getName());
+        FinancialAudit item = new FinancialAudit();
+        item.setId(id);
+        item.setReviewStatus(2);
+        item.setReviewerId(user.getId());
+        item.setReviewerName(user.getName());
+        item.setReviewTime(sdf.format(new Date()));
+        financialAuditService.updateById(item);
+        return httpRespMsg;
+    }
+}
+

+ 59 - 29
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java

@@ -296,8 +296,8 @@ public class ReportController {
     }
 
     @RequestMapping("/getWeeklyReportData")
-    public HttpRespMsg getWeeklyReportData(@RequestParam String targetDate) {
-        return reportService.getWeeklyReportData(targetDate, request);
+    public HttpRespMsg getWeeklyReportData(@RequestParam String targetDate, String targetUserId) {
+        return reportService.getWeeklyReportData(targetDate, targetUserId, request);
     }
 
     //新版按周填报
@@ -1088,35 +1088,41 @@ public class ReportController {
                             if (comTimeType.getReportAuditType() == 3) {
                                 report.setAuditorSetting(auditorSettingList.get(i));
                             }
-                            if (auditWorkflowList.size() == 0) {
-                                //没有自定义审核流,直接代填的,就算审核通过
-                                report.setIsDeptAudit(0);
-                                report.setIsFinalAudit(1);
-                                report.setState(1);
+                            if (comTimeType.getReportAuditType() == 7) {
+                                report.setState(draft==0?0:3);
                             } else {
-                                //有审核流程的,取项目经理后面的流程节点
-                                int projectLeaderNodeIndex = 0;
-                                for (int t=0;t<auditWorkflowList.size(); t++) {
-                                    if (auditWorkflowList.get(t).getIsDeptAudit() == 0) {
-                                        projectLeaderNodeIndex = t;
-                                        break;
-                                    }
-                                }
-                                if (projectLeaderNodeIndex == auditWorkflowList.size() -1) {
-                                    //最后一个节点就是项目经理,那就不用审核了,直接通过
+                                //并非并行审核模式下的代填,需要设置审核状态
+                                if (auditWorkflowList.size() == 0) {
+                                    //没有自定义审核流,直接代填的,就算审核通过
+                                    report.setIsDeptAudit(0);
+                                    report.setIsFinalAudit(1);
                                     report.setState(1);
                                 } else {
-                                    //否则取下一个节点,待审核
-                                    report.setState(0);
-                                    int nextIndex = projectLeaderNodeIndex + 1;
-                                    AuditWorkflowTimeSetting nextNode = auditWorkflowList.get(nextIndex);
-                                    report.setIsFinalAudit((nextIndex == auditWorkflowList.size()-1)?1:0);
-                                    report.setIsDeptAudit(nextNode.getIsDeptAudit());
-                                    report.setAuditDeptid(nextNode.getAuditDeptId());
-                                    report.setAuditDeptManagerid(nextNode.getAuditDeptId() != null?allDeptList.stream().filter(d->d.getDepartmentId().equals(nextNode.getAuditDeptId())).findFirst().get().getManagerId(): null);
+                                    //有审核流程的,取项目经理后面的流程节点
+                                    int projectLeaderNodeIndex = 0;
+                                    for (int t=0;t<auditWorkflowList.size(); t++) {
+                                        if (auditWorkflowList.get(t).getIsDeptAudit() == 0) {
+                                            projectLeaderNodeIndex = t;
+                                            break;
+                                        }
+                                    }
+                                    if (projectLeaderNodeIndex == auditWorkflowList.size() -1) {
+                                        //最后一个节点就是项目经理,那就不用审核了,直接通过
+                                        report.setState(1);
+                                    } else {
+                                        //否则取下一个节点,待审核
+                                        report.setState(0);
+                                        int nextIndex = projectLeaderNodeIndex + 1;
+                                        AuditWorkflowTimeSetting nextNode = auditWorkflowList.get(nextIndex);
+                                        report.setIsFinalAudit((nextIndex == auditWorkflowList.size()-1)?1:0);
+                                        report.setIsDeptAudit(nextNode.getIsDeptAudit());
+                                        report.setAuditDeptid(nextNode.getAuditDeptId());
+                                        report.setAuditDeptManagerid(nextNode.getAuditDeptId() != null?allDeptList.stream().filter(d->d.getDepartmentId().equals(nextNode.getAuditDeptId())).findFirst().get().getManagerId(): null);
+                                    }
                                 }
                             }
 
+
                             if (taskId != null && taskId[i] != null && taskId[i] != 0) {
                                 report.setTaskId(taskId[i]);
                             }
@@ -1454,8 +1460,20 @@ public class ReportController {
                     report.setProjectAuditState(0);
                     Department department = departmentMapper.selectById(user.getDepartmentId());
                     if (department != null) {
-                        report.setAuditDeptid(department.getDepartmentId());
-                        report.setAuditDeptManagerid(department.getManagerId());
+                        if (user.getId().equals(department.getManagerId())) {
+                            //自己就是当前部门的负责人,让上级部门负责人审核
+                            Department parentDept = departmentMapper.selectById(department.getSuperiorId());
+                            if (parentDept != null) {
+                                report.setAuditDeptid(parentDept.getDepartmentId());
+                                report.setAuditDeptManagerid(parentDept.getManagerId());
+                            } else {
+                                //没有上级部门,直接算部门审核通过
+                                report.setDepartmentAuditState(1);
+                            }
+                        } else {
+                            report.setAuditDeptid(department.getDepartmentId());
+                            report.setAuditDeptManagerid(department.getManagerId());
+                        }
                     }
                 }
             } else {
@@ -1466,8 +1484,20 @@ public class ReportController {
                     User targetUser = targetUserList.stream().filter(t -> t.getId().equals(report.getCreatorId())).findFirst().get();
                     Department department = departmentMapper.selectById(targetUser.getDepartmentId());
                     if (department != null) {
-                        report.setAuditDeptid(department.getDepartmentId());
-                        report.setAuditDeptManagerid(department.getManagerId());
+                        if (targetUser.getId().equals(department.getManagerId())) {
+                            //自己就是当前部门的负责人,让上级部门负责人审核
+                            Department parentDept = departmentMapper.selectById(department.getSuperiorId());
+                            if (parentDept != null) {
+                                report.setAuditDeptid(parentDept.getDepartmentId());
+                                report.setAuditDeptManagerid(parentDept.getManagerId());
+                            } else {
+                                //没有上级部门,直接算部门审核通过
+                                report.setDepartmentAuditState(1);
+                            }
+                        } else {
+                            report.setAuditDeptid(department.getDepartmentId());
+                            report.setAuditDeptManagerid(department.getManagerId());
+                        }
                     }
                 }
             }

+ 35 - 9
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportLogController.java

@@ -107,6 +107,7 @@ public class ReportLogController {
         titleList.add("姓名");
         titleList.add("工号");
         titleList.add("工作日期");
+        titleList.add("填报时间");
         titleList.add("项目名称");
         titleList.add("项目编号");
         titleList.add("审核通过时间");
@@ -138,6 +139,13 @@ public class ReportLogController {
             item.add(String.valueOf(df.format(reportLog.getCreateDate())));
             String ids = reportLog.getReportIds();
             String[] split = ids.split(",");
+            List<Integer> subReportIdList = Arrays.asList(split).stream().map(id -> Integer.valueOf(id)).collect(Collectors.toList());
+            Optional<Report> target = reportList.stream().filter(r ->subReportIdList.contains(r.getId())).findFirst();
+            if(target.isPresent()){
+                item.add(df1.format(target.get().getCreateTime()));
+            }else {
+                item.add("");
+            }
             StringBuilder projectNames=new StringBuilder();
             StringBuilder projectCodes=new StringBuilder();
             for (int i = 0; i < split.length; i++) {
@@ -238,9 +246,10 @@ public class ReportLogController {
                 XSSFCell nameCell = row.getCell(1);
                 XSSFCell jobNumCell = row.getCell(2);
                 XSSFCell createDateCell = row.getCell(3);
-                XSSFCell projectNameCell = row.getCell(4);
-                XSSFCell projectCodeCell = row.getCell(5);
-                XSSFCell auditDateCell = row.getCell(6);
+                XSSFCell createTimeCell = row.getCell(4);
+                XSSFCell projectNameCell = row.getCell(5);
+                XSSFCell projectCodeCell = row.getCell(6);
+                XSSFCell auditDateCell = row.getCell(7);
 
                 if (numCell != null) {
                     String code = numCell.getStringCellValue().trim().replaceAll("\\u00a0", "");
@@ -254,6 +263,7 @@ public class ReportLogController {
                 if (nameCell != null)nameCell.setCellType(CellType.STRING);
                 if (jobNumCell != null)jobNumCell.setCellType(CellType.STRING);
                 if (createDateCell != null)createDateCell.setCellType(CellType.STRING);
+                if (createTimeCell != null)createTimeCell.setCellType(CellType.STRING);
                 if (projectNameCell != null)projectNameCell.setCellType(CellType.STRING);
                 if (projectCodeCell != null)projectCodeCell.setCellType(CellType.STRING);
                 if (auditDateCell != null)auditDateCell.setCellType(CellType.STRING);
@@ -262,6 +272,7 @@ public class ReportLogController {
                 String nameCellValue = nameCell.getStringCellValue();
                 String jobNumCellValue =jobNumCell.getStringCellValue();
                 String createDateCellValue = createDateCell.getStringCellValue();
+                String createTimeCellValue = createTimeCell.getStringCellValue();
                 String projectNameCellValue = projectNameCell.getStringCellValue();
                 String projectCodeCellValue = projectCodeCell.getStringCellValue();
                 String auditDateCellValue = auditDateCell.getStringCellValue();
@@ -273,19 +284,34 @@ public class ReportLogController {
                     String reportIdSplit = reportLog.getReportIds();
                     List<Integer> ids = Arrays.asList(reportIdSplit.split(",")).stream().map(s -> Integer.valueOf(s)).collect(Collectors.toList());
                     List<Report> reports = reportList.stream().filter(r -> ids.contains(r.getId())).collect(Collectors.toList());
-                    if(auditDateCellValue!=null){
-                        LocalDateTime time = null;
+                    LocalDateTime auditDateTime = null;
+                    LocalDateTime createTimeTime = null;
+                    if(auditDateCellValue!=null&&!StringUtils.isEmpty(auditDateCellValue)){
                         try {
-                             time = LocalDateTime.parse(auditDateCellValue, df);
+                            auditDateTime = LocalDateTime.parse(auditDateCellValue, df);
                         }catch (Exception e){
                             msg.setError("第"+row+"行审核时间格式错误,请检查审核时间数据");
                             return msg;
                         }
-                        reportLog.setOperateDate(time);
+                        reportLog.setOperateDate(auditDateTime);
                         needUpdateReportLogList.add(reportLog);
-                        LocalDateTime finalTime = time;
+                        LocalDateTime finalAuditDateTime = auditDateTime;
+                        LocalDateTime finalCreateTimeTime = createTimeTime;
+                        reports.forEach(r->{
+                            r.setProjectAuditTime(finalAuditDateTime);
+                        });
+                        needUpdateReportList.addAll(reports);
+                    }
+                    if(createTimeCellValue!=null&&!StringUtils.isEmpty(createTimeCellValue)){
+                        try {
+                            createTimeTime = LocalDateTime.parse(createTimeCellValue, df);
+                        }catch (Exception e){
+                            msg.setError("第"+row+"行填报时间格式错误,请检查审核时间数据");
+                            return msg;
+                        }
+                        LocalDateTime finalCreateTimeTime = createTimeTime;
                         reports.forEach(r->{
-                            r.setProjectAuditTime(finalTime);
+                            r.setCreateTime(finalCreateTimeTime);
                         });
                         needUpdateReportList.addAll(reports);
                     }

+ 2 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/TaskController.java

@@ -188,7 +188,8 @@ public class TaskController {
             //针对依斯呗的校验
             if(user.getCompanyId()==3092){
                 Project project = projectService.getById(task.getProjectId());
-                if(task.getGroupId()!=null&&(project.getCategory()!=null&&project.getCategory()==696)){
+                //除了报价项目  售后报价项目和研发项目不管控  其它项目都管控
+                if(task.getGroupId()!=null&&(project.getCategory()!=null && !(project.getCategory()==644 || project.getCategory()==647 || project.getCategory()==697))){
                     TaskGroup taskGroup = taskGroupService.getById(task.getGroupId());
                     if(taskGroup.getManDay()==null){
                         msg.setError("创建失败,请先分配任务分组的预估工时");

+ 105 - 125
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserWithBeisenController.java

@@ -12,6 +12,7 @@ import com.management.platform.mapper.UserMapper;
 import com.management.platform.mapper.UserWithBeisenMapper;
 import com.management.platform.service.*;
 import com.management.platform.util.BeiSenUtils;
+import com.management.platform.util.DateTimeUtil;
 import com.management.platform.util.HttpRespMsg;
 import com.management.platform.util.WorkDayCalculateUtils;
 import org.springframework.transaction.annotation.Transactional;
@@ -194,29 +195,27 @@ public class UserWithBeisenController {
                 Stream<JSONObject> timeStream1 = times.stream().map(time -> (JSONObject) time);
                 //获取最早上班打卡时间
                 List<LocalTime> minLocalTimeList = timeStream.filter(t -> t.getIntValue("Type") == 1).map(i -> LocalDateTime.parse(i.getString("ActualTime"),df1).toLocalTime()).collect(Collectors.toList());
-                Optional<LocalTime> min = minLocalTimeList.stream().min(LocalTime::compareTo);
+                Optional<LocalTime> minOp = minLocalTimeList.stream().min(LocalTime::compareTo);
                 //获取最晚下班时间
                 List<LocalTime> maxLocalTimeList = timeStream1.filter(t -> t.getIntValue("Type") == 9).map(i -> LocalDateTime.parse(i.getString("ActualTime"),df1).toLocalTime()).collect(Collectors.toList());
-                Optional<LocalTime> max = maxLocalTimeList.stream().max(LocalTime::compareTo);
+                Optional<LocalTime> maxOp = maxLocalTimeList.stream().max(LocalTime::compareTo);
                 if(first.isPresent()){
-                    boolean workDay = WorkDayCalculateUtils.isWorkDay(localDate)&&!holidaySettings.stream().anyMatch(h->h.getHolidayDate().isEqual(localDate));
+                    boolean workDay = WorkDayCalculateUtils.isWorkDay(localDate);
                     //todo:针对景昱 工作日默认以8小时工作制度加上加班时长 非工作日以加班时长为准
-                    Duration between = Duration.between(min.get(), max.get());
                     Double workTime;
-                    if(timeType.getCompanyId()==5978){
+                    LocalTime min = minOp.get();
+                    LocalTime max = maxOp.get();
+                    Duration between = Duration.between(min,max);
+                    if(between.toHours()<=0){
+                        continue;
+                    }else {
                         if(workDay){
+                            //去掉休息时长
                             workTime=8.0;
                         }else {
+                            //去掉休息时长
                             workTime=0.0;
                         }
-                    }else {
-                        if(between.toHours()<0){
-                            workTime=0.0;
-                        }else {
-                            BigDecimal decimal = new BigDecimal(between.toMinutes());
-                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
-                            workTime=decimal.doubleValue();
-                        }
                     }
                     Stream<JSONObject> overTimeStream = allOverTimeList.stream().map(elment -> (JSONObject) elment);
                     Stream<JSONObject> vacationStream = allVacationList.stream().map(elment -> (JSONObject) elment);
@@ -229,22 +228,33 @@ public class UserWithBeisenController {
                         List<JSONObject> overTimeList = overTimeStream.filter(a -> a.getString("StaffId").equals(beisen.get().getUserId())
                                 && (a.getIntValue("ApproveStatus") == 2||a.getIntValue("ApproveStatus") == 1)).collect(Collectors.toList());
                         //加班数据可能存在结束日期是当前日期的情况的情况
-                        BigDecimal overTimeBigDecimal= new BigDecimal(0);;
+                        BigDecimal overTimeBigDecimal= new BigDecimal(0);
+                        //计算加班时长 工作日打卡超过19:00:00算加班那 非工作日全天算加班
+                        if(workDay){
+                            //工作日打卡超过19:00:00算加班那 非工作日全天算加班
+                            if(max.isAfter(LocalTime.parse("19:00:00", df4))){
+                                overTimeBigDecimal = new BigDecimal(Duration.between(LocalTime.parse("18:00:00", df4),max).toMinutes());
+                            }
+                        }else {
+                            //非工作日全天 去掉休息时长 都算加班
+                            overTimeBigDecimal=new BigDecimal(Duration.between(min, max).toMinutes()) ;
+                            long rest1 = DateTimeUtil.calculateOverlap(min, max, LocalTime.parse("12:00:00", df4), LocalTime.parse("13:00:00", df4));
+                            long rest2 = DateTimeUtil.calculateOverlap(min, max, LocalTime.parse("17:30:00", df4), LocalTime.parse("18:00:00", df4));
+                            overTimeBigDecimal=overTimeBigDecimal.subtract(new BigDecimal(rest1)).subtract(new BigDecimal(rest2));
+                        }
                         for (JSONObject o : overTimeList) {
                             //存在开始日期为当前日期的数据以及结束日期为当天日期的数据 分开计算
                             if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(localDate)){
                                 //存在开始日期为当天的数据
                                 if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate())){
                                     //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
-                                    //判断打卡时间是不是大于19:00 大于才算加班 通过打卡计算加班时长 与加班单作比较 取小
-                                    Duration timeDurantion = Duration.between(LocalTime.parse(workDay?"18:00:00":"08:30:00", df4), max.get());
-                                    BigDecimal decimal = new BigDecimal(timeDurantion.toMinutes());
-                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
-                                    double l = decimal.doubleValue();
-                                    if(l<o.getDouble("OverTimeDuration")){
-                                        overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l<0?0:l));
-                                    }else {
-                                        overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(o.getDouble("OverTimeDuration")));
+                                    //对比打卡体现的加班时长和加班单时长取小
+                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
+                                    if(divide.doubleValue()>o.getDouble("OverTimeDuration")){
+                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
+                                        workTime=workTime+o.getDouble("OverTimeDuration");
+                                    }else{
+                                        workTime=workTime+divide.doubleValue();
                                     }
                                 }else {
                                     //开始日期和结束日期是不相同的情况 说明是加班区间存在加班到第二天的情况
@@ -252,17 +262,15 @@ public class UserWithBeisenController {
                                     LocalDateTime stop = start.toLocalDate().atTime(LocalTime.MAX);
                                     Duration duration = Duration.between(start, stop);
                                     BigDecimal decimal = new BigDecimal(duration.toMinutes());
-                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_DOWN);
                                     double l = decimal.doubleValue();
-                                    //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
-                                    Duration timeDurantion = Duration.between(LocalTime.parse(workDay?"18:00:00":"08:30:00", df4), max.get());
-                                    BigDecimal decimal1 = new BigDecimal(timeDurantion.toMinutes());
-                                    decimal1=decimal1.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
-                                    double l1 = decimal1.doubleValue();
-                                    if(l1<l){
-                                        overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l1<0?0:l1));
+                                    //对比打卡体现的加班时长和加班单时长取小
+                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
+                                    if(divide.doubleValue()>l){
+                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
+                                        workTime=workTime+l;
                                     }else {
-                                        overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l));
+                                        workTime=workTime+divide.doubleValue();
                                     }
                                 }
                             }else if(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate().isEqual(localDate)){
@@ -270,14 +278,12 @@ public class UserWithBeisenController {
                                 if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate())){
                                     //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
                                     //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
-                                    Duration timeDurantion = Duration.between(LocalTime.parse(workDay?"18:00:00":"08:30:00", df4), max.get());
-                                    BigDecimal decimal = new BigDecimal(timeDurantion.toMinutes());
-                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
-                                    double l = decimal.doubleValue();
-                                    if(l<o.getDouble("OverTimeDuration")){
-                                        overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l<0?0:l));
+                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
+                                    if(divide.doubleValue()>o.getDouble("OverTimeDuration")){
+                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
+                                        workTime=workTime+o.getDouble("OverTimeDuration");
                                     }else {
-                                        overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(o.getDouble("OverTimeDuration")));
+                                        workTime=workTime+divide.doubleValue();
                                     }
                                 }else {
                                     //开始日期和结束日期是不相同的情况 说明是加班区间存在加班到第二天的情况
@@ -285,34 +291,19 @@ public class UserWithBeisenController {
                                     LocalDateTime start = stop.toLocalDate().atTime(LocalTime.MIN);
                                     Duration duration = Duration.between(start, stop);
                                     BigDecimal decimal = new BigDecimal(duration.toMinutes());
-                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_DOWN);
                                     double l = decimal.doubleValue();
-                                    //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
-                                    Duration timeDurantion = Duration.between(LocalTime.parse(workDay?"18:00:00":"08:30:00", df4), max.get());
-                                    BigDecimal decimal1 = new BigDecimal(timeDurantion.toMinutes());
-                                    decimal1=decimal1.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
-                                    double l1 = decimal1.doubleValue();
-                                    if(l1<l){
-                                        overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l1<0?0:l1));
+                                    //对比打卡体现的加班时长和加班单时长取小
+                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
+                                    if(divide.doubleValue()>l){
+                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
+                                        workTime=workTime+l;
                                     }else {
-                                        overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l));
+                                        workTime=workTime+divide.doubleValue();
                                     }
                                 }
                             }
                         }
-                        if(workDay){
-                            //工作日计算按照前面的逻辑计算加班时长计算
-                            workTime= workTime+overTimeBigDecimal.doubleValue();
-                        }else {
-                            //非工作日加班 根据实际打卡时长 比较 加班单时长
-                            BigDecimal decimal = new BigDecimal(between.toMinutes());
-                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
-                            if((decimal.doubleValue())>overTimeBigDecimal.doubleValue()){
-                                workTime= workTime+overTimeBigDecimal.doubleValue();
-                            }else {
-                                workTime= workTime+(decimal.doubleValue());
-                            }
-                        }
                         //处理修改
                         List<JSONObject> vacationList = vacationStream.filter(a ->{
                             LocalDate vacationStartDate = LocalDateTime.parse(a.getString("VacationStartDateTime"), df3).toLocalDate();
@@ -332,7 +323,7 @@ public class UserWithBeisenController {
                         if(vacationList.size()>0){
                             double vacationDuration = vacationList.stream().mapToDouble(i -> i.getDouble("VacationDuration")).sum();
                             BigDecimal decimal = new BigDecimal(vacationDuration);
-                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_DOWN);
 //                            //可能存在休假多天 只减去一天
                             if(decimal.doubleValue()>=8){
                                 workTime= workTime-8;
@@ -343,8 +334,8 @@ public class UserWithBeisenController {
                     }
                     UserFvTime userFvTime=new UserFvTime();
                     userFvTime.setWorkDate(localDate);
-                    userFvTime.setStartTime(min.isPresent()?df2.format(min.get()):"08:30");
-                    userFvTime.setEndTime(max.isPresent()?df2.format(max.get()):"17:30");
+                    userFvTime.setStartTime(df2.format(min));
+                    userFvTime.setEndTime(df2.format(max));
                     userFvTime.setUserId(first.get().getId());
                     userFvTime.setCompanyId(companyId);
                     userFvTime.setWorkHours(workTime.floatValue());
@@ -459,20 +450,17 @@ public class UserWithBeisenController {
             Duration between = Duration.between(LocalTime.parse(firstCard, df4), LocalTime.parse(lastCard, df4));
             LocalTime min = LocalTime.parse(firstCard, df4);
             LocalTime max = LocalTime.parse(lastCard, df4);
-            if(timeType.getCompanyId()==5978){
-                if(workDay){
-                    workTime=8.0;
-                }else {
-                    workTime=0.0;
-                }
+            if(between.toHours()<=0){
+                msg.setError("无考勤记录");
+                return msg;
             }else {
-                if(between.toHours()<0){
-                    workTime=0.0;
-                }else {
-                    BigDecimal decimal = new BigDecimal(between.toMinutes());
-                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
-                    workTime=decimal.doubleValue();
-                }
+              if(workDay){
+                  //去掉休息时长
+                  workTime=8.0;
+              }else {
+                  //去掉休息时长
+                  workTime=0.0;
+              }
             }
             Stream<JSONObject> overTimeStream = allOverTimeList.stream().map(elment -> (JSONObject) elment);
             Stream<JSONObject> vacationStream = vacationList.stream().map(elment -> (JSONObject) elment);
@@ -487,21 +475,32 @@ public class UserWithBeisenController {
                 LocalDate localDate = LocalDate.parse(createDate, df);
                 //加班数据可能存在结束日期是当前日期的情况的情况
                 BigDecimal overTimeBigDecimal= new BigDecimal(0);
+                //计算加班时长 工作日打卡超过19:00:00算加班那 非工作日全天算加班
+                if(workDay){
+                    //工作日打卡超过19:00:00算加班那 非工作日全天算加班
+                    if(max.isAfter(LocalTime.parse("19:00:00", df4))){
+                        overTimeBigDecimal = new BigDecimal(Duration.between(LocalTime.parse("18:00:00", df4), LocalTime.parse(lastCard, df4)).toMinutes());
+                    }
+                }else {
+                    //非工作日全天 去掉休息时长 都算加班
+                    overTimeBigDecimal=new BigDecimal(Duration.between(LocalTime.parse(firstCard, df4), LocalTime.parse(lastCard, df4)).toMinutes()) ;
+                    long rest1 = DateTimeUtil.calculateOverlap(min, max, LocalTime.parse("12:00:00", df4), LocalTime.parse("13:00:00", df4));
+                    long rest2 = DateTimeUtil.calculateOverlap(min, max, LocalTime.parse("17:30:00", df4), LocalTime.parse("18:00:00", df4));
+                    overTimeBigDecimal=overTimeBigDecimal.subtract(new BigDecimal(rest1)).subtract(new BigDecimal(rest2));
+                }
                 for (JSONObject o : overTimeList) {
                     //存在开始日期为当前日期的数据以及结束日期为当天日期的数据 分开计算
                     if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(localDate)){
                         //存在开始日期为当天的数据
                         if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate())){
                             //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
-                            //判断打卡时间是不是大于19:00 大于才算加班 通过打卡计算加班时长 与加班单作比较 取小
-                            Duration timeDurantion = Duration.between(LocalTime.parse(workDay?"18:00:00":"08:30:00", df4), max);
-                            BigDecimal decimal = new BigDecimal(timeDurantion.toMinutes());
-                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
-                            double l = decimal.doubleValue();
-                            if(l<o.getDouble("OverTimeDuration")){
-                                overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l<0?0:l));
-                            }else {
-                                overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(o.getDouble("OverTimeDuration")));
+                            //对比打卡体现的加班时长和加班单时长取小
+                            BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
+                            if(divide.doubleValue()>o.getDouble("OverTimeDuration")){
+                                //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
+                                workTime=workTime+o.getDouble("OverTimeDuration");
+                            }else{
+                                workTime=workTime+divide.doubleValue();
                             }
                         }else {
                             //开始日期和结束日期是不相同的情况 说明是加班区间存在加班到第二天的情况
@@ -509,17 +508,15 @@ public class UserWithBeisenController {
                             LocalDateTime stop = start.toLocalDate().atTime(LocalTime.MAX);
                             Duration duration = Duration.between(start, stop);
                             BigDecimal decimal = new BigDecimal(duration.toMinutes());
-                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_DOWN);
                             double l = decimal.doubleValue();
-                            //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
-                            Duration timeDurantion = Duration.between(LocalTime.parse(workDay?"18:00:00":"08:30:00", df4), max);
-                            BigDecimal decimal1 = new BigDecimal(timeDurantion.toMinutes());
-                            decimal1=decimal1.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
-                            double l1 = decimal1.doubleValue();
-                            if(l1<l){
-                                overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l1<0?0:l1));
+                            //对比打卡体现的加班时长和加班单时长取小
+                            BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
+                            if(divide.doubleValue()>l){
+                                //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
+                                workTime=workTime+l;
                             }else {
-                                overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l));
+                                workTime=workTime+divide.doubleValue();
                             }
                         }
                     }else if(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate().isEqual(localDate)){
@@ -527,14 +524,12 @@ public class UserWithBeisenController {
                         if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate())){
                             //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
                             //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
-                            Duration timeDurantion = Duration.between(LocalTime.parse(workDay?"18:00:00":"08:30:00", df4), max);
-                            BigDecimal decimal = new BigDecimal(timeDurantion.toMinutes());
-                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
-                            double l = decimal.doubleValue();
-                            if(l<o.getDouble("OverTimeDuration")){
-                                overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l<0?0:l));
+                            BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
+                            if(divide.doubleValue()>o.getDouble("OverTimeDuration")){
+                                //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
+                                workTime=workTime+o.getDouble("OverTimeDuration");
                             }else {
-                                overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(o.getDouble("OverTimeDuration")));
+                                workTime=workTime+divide.doubleValue();
                             }
                         }else {
                             //开始日期和结束日期是不相同的情况 说明是加班区间存在加班到第二天的情况
@@ -542,34 +537,19 @@ public class UserWithBeisenController {
                             LocalDateTime start = stop.toLocalDate().atTime(LocalTime.MIN);
                             Duration duration = Duration.between(start, stop);
                             BigDecimal decimal = new BigDecimal(duration.toMinutes());
-                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_DOWN);
                             double l = decimal.doubleValue();
-                            //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
-                            Duration timeDurantion = Duration.between(LocalTime.parse(workDay?"18:00:00":"08:30:00", df4), max);
-                            BigDecimal decimal1 = new BigDecimal(timeDurantion.toMinutes());
-                            decimal1=decimal1.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
-                            double l1 = decimal1.doubleValue();
-                            if(l1<l){
-                                overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l1<0?0:l1));
+                            //对比打卡体现的加班时长和加班单时长取小
+                            BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
+                            if(divide.doubleValue()>l){
+                                //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
+                                workTime=workTime+l;
                             }else {
-                                overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l));
+                                workTime=workTime+divide.doubleValue();
                             }
                         }
                     }
                 }
-                if(workDay){
-                    //工作日计算按照前面的逻辑计算加班时长计算
-                    workTime= workTime+overTimeBigDecimal.doubleValue();
-                }else {
-                    //非工作日加班 根据实际打卡时长 比较 加班单时长
-                    BigDecimal decimal = new BigDecimal(between.toMinutes());
-                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
-                    if((decimal.doubleValue())>overTimeBigDecimal.doubleValue()){
-                        workTime= workTime+overTimeBigDecimal.doubleValue();
-                    }else {
-                        workTime= workTime+(decimal.doubleValue());
-                    }
-                }
                 //处理修改
                 List<JSONObject> lastVacationList = vacationStream.filter(a ->{
                     LocalDate vacationStartDate = LocalDateTime.parse(a.getString("VacationStartDateTime"), df3).toLocalDate();
@@ -589,7 +569,7 @@ public class UserWithBeisenController {
                 if(lastVacationList.size()>0){
                     double vacationDuration = lastVacationList.stream().mapToDouble(i -> i.getDouble("VacationDuration")).sum();
                     BigDecimal decimal = new BigDecimal(vacationDuration);
-                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_DOWN);
 //                            //可能存在休假多天 只减去一天
                     if(decimal.doubleValue()>=8){
                         workTime= workTime-8;

+ 18 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java

@@ -4045,4 +4045,22 @@ public class WeiXinCorpController {
         }
         return msg;
     }
+
+
+    @RequestMapping("/testGetApprovalList")
+    public HttpRespMsg testGetApprovalList(String startDate,String endDate) throws Exception {
+        HttpRespMsg msg=new HttpRespMsg();
+        JSONArray jsonArrayFilter = new JSONArray();
+        JSONObject filter1 = new JSONObject();
+        filter1.put("key","record_type");
+        filter1.put("value",1);
+        jsonArrayFilter.add(filter1);
+        JSONObject filter2 = new JSONObject();
+        filter2.put("key","sp_status ");
+        filter2.put("value",2);
+        jsonArrayFilter.add(filter2);
+        JSONArray approvalInfo = wxCorpInfoService.getApprovalInfo(7, startDate, endDate, "", jsonArrayFilter);
+        msg.setData(approvalInfo.toArray());
+        return msg;
+    }
 }

+ 83 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/FinancialAudit.java

@@ -0,0 +1,83 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import java.time.LocalDate;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-06-05
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class FinancialAudit extends Model<FinancialAudit> {
+
+    private static final long serialVersionUID=1L;
+
+    /**
+     * 财务审核id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 日报年月
+     */
+    @TableField("report_yrMnth")
+    @DateTimeFormat(pattern = "yyyy-MM")
+    @JsonFormat(pattern = "yyyy-MM")
+    private LocalDate reportYrmnth;
+
+    /**
+     * 审核人_id
+     */
+    @TableField("reviewer_id")
+    private String reviewerId;
+
+    /**
+     * 审核人_name
+     */
+    @TableField("reviewer_name")
+    private String reviewerName;
+
+    /**
+     * 审核时间
+     */
+    @TableField("review_time")
+    @DateTimeFormat(pattern = "yyyy-MM-dd hh:mm")
+    @JsonFormat(pattern = "yyyy-MM-dd hh:mm")
+    private String reviewTime;
+
+    /**
+     * 审核状态,1-未审核,2-已审核
+     */
+    @TableField("review_status")
+    private Integer reviewStatus;
+
+    /**
+     * 对应公司
+     */
+    @TableField("company_id")
+    private Integer companyId;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 3 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/SysModule.java

@@ -110,6 +110,9 @@ public class SysModule extends Model<SysModule> {
     @TableField("package_engineering")
     private Integer packageEngineering;
 
+    @TableField(exist = false)
+    private Integer packageFinanceAudit;
+
     /**
      * 是否属于合同管理
      */

+ 19 - 5
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/TimeType.java

@@ -17,7 +17,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2024-03-26
+ * @since 2024-06-06
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -297,7 +297,7 @@ public class TimeType extends Model<TimeType> {
     private Integer mainProjectState;
 
     /**
-     * 日报的审核类型, 0-项目审核人审核,1-分组负责人审核,2-先分组负责人审核再项目负责人(PM)审核;3-员工自由选择审批人 4-项目所属BU审核 5-直属审核人或部门负责人审核,6-直属或部门负责人审核->项目日报审核人审核
+     * 日报的审核类型, 0-项目审核人审核,1-分组负责人审核,2-先分组负责人审核再项目负责人(PM)审核;3-员工自由选择审批人 4-项目所属BU审核 5-直属审核人或部门负责人审核,6-直属或部门负责人审核->项目日报审核人审核,7-项目和部门并行审核
      */
     @TableField("report_audit_type")
     private Integer reportAuditType;
@@ -560,6 +560,12 @@ public class TimeType extends Model<TimeType> {
     @TableField("hide_subproject")
     private Integer hideSubproject;
 
+    /**
+     * 开启日报审批流的本部门负责人由上级部门负责人审核
+     */
+    @TableField("report_audit_flow_enable_super_dept_aduit")
+    private Integer reportAuditFlowEnableSuperDeptAduit;
+
     /**
      * 是否开启设置可填报部门 0-否 1-是
      */
@@ -567,10 +573,17 @@ public class TimeType extends Model<TimeType> {
     private Integer userWithMultiDept;
 
     /**
-     * 开启日报审批流的本部门负责人由上级部门负责人审核
+     * 提醒审核日,默认周一
      */
-    @TableField("report_audit_flow_enable_super_dept_aduit")
-    private Integer reportAuditFlowEnableSuperDeptAduit;
+    @TableField("alert_check_day")
+    private Integer alertCheckDay;
+
+    /**
+     * 提醒审核的文字消息
+     */
+    @TableField("alert_check_msg")
+    private String alertCheckMsg;
+
 
     @TableField(exist = false)
     private List<User> userList;
@@ -579,6 +592,7 @@ public class TimeType extends Model<TimeType> {
     @TableField(exist = false)
     private Integer saasSyncContact;
 
+
     @Override
     protected Serializable pkVal() {
         return this.companyId;

+ 16 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/FinancialAuditMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.FinancialAudit;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-06-05
+ */
+public interface FinancialAuditMapper extends BaseMapper<FinancialAudit> {
+
+}

+ 1 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ReportMapper.java

@@ -218,4 +218,5 @@ public interface ReportMapper extends BaseMapper<Report> {
     void denyReportWithUserAndCreateDate(String userId, String createDate);
 
     List<Map<String, Object>> getUserDailyWorkTimeReminder(Integer companyId,String startDate, String endDate,@Param("list") List<Integer> deptIds,Integer deptId,String leaderId);
+
 }

+ 16 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/FinancialAuditService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.FinancialAudit;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-06-05
+ */
+public interface FinancialAuditService extends IService<FinancialAudit> {
+
+}

+ 1 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ReportService.java

@@ -122,7 +122,7 @@ public interface ReportService extends IService<Report> {
 
     HttpRespMsg getAIReport(HttpServletRequest request);
 
-    HttpRespMsg getWeeklyReportData(String targetDate, HttpServletRequest request);
+    HttpRespMsg getWeeklyReportData(String targetDate, String targetUserId, HttpServletRequest request);
 
     HttpRespMsg batchDelete(String userIds, Integer deptId, String startDate, String endDate, HttpServletRequest request);
 

+ 4 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/WxCorpInfoService.java

@@ -1,5 +1,6 @@
 package com.management.platform.service;
 
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.management.platform.entity.LeaveSheet;
@@ -81,5 +82,7 @@ public interface WxCorpInfoService extends IService<WxCorpInfo> {
 
     public String getTemplateDetail(Integer companyId) throws Exception;
 
-    public String applyEvent(HttpServletRequest request,JSONObject data) throws Exception;
+    JSONArray getApprovalInfo(Integer companyId, String startDate, String endDate, String newCursor, JSONArray filterArray) throws Exception;
+
+    public String applyEvent(HttpServletRequest request, JSONObject data) throws Exception;
 }

+ 20 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FinancialAuditServiceImpl.java

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.FinancialAudit;
+import com.management.platform.mapper.FinancialAuditMapper;
+import com.management.platform.service.FinancialAuditService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-06-05
+ */
+@Service
+public class FinancialAuditServiceImpl extends ServiceImpl<FinancialAuditMapper, FinancialAudit> implements FinancialAuditService {
+
+}

+ 6 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/PermissionServiceImpl.java

@@ -220,8 +220,14 @@ public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permiss
         if(!user.getRoleName().equals("超级管理员")){
             queryWrapper.and(wrapper->wrapper.in("id",moduleIds));
         }
+
         queryWrapper.orderByAsc("orderitem");
         List<SysModule> moduleList = sysModuleMapper.selectList(queryWrapper);
+        if (companyId == 5978) {
+            //针对景昱,返回财务报告审核模块
+            SysModule module = sysModuleMapper.selectOne(new QueryWrapper<SysModule>().eq("name", "财务报告审核"));
+            moduleList.add(module);
+        }
         if(companyId!=3092){
             moduleList=moduleList.stream().filter(m->!m.getName().equals("预估工时审核")).collect(Collectors.toList());
         }

+ 91 - 23
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -2226,7 +2226,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                         if (r.getDepartmentAuditState() == 0 && user.getId().equals(r.getAuditDeptManagerid())) {
                             newReport.setDepartmentAuditState(1);
                             r.setDepartmentAuditState(1);
-                        } else if (r.getProjectAuditState() == 0 && user.getId().equals(r.getProjectAuditorId())) {
+                        }
+                        if (r.getProjectAuditState() == 0 && user.getId().equals(r.getProjectAuditorId())) {
                             newReport.setProjectAuditState(1);
                             newReport.setProjectAuditTime(LocalDateTime.now());
                             r.setProjectAuditState(1);
@@ -3493,7 +3494,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                         if (r.getDepartmentAuditState() == 0 && user.getId().equals(r.getAuditDeptManagerid())) {
                             newReport.setDepartmentAuditState(1);
                             r.setDepartmentAuditState(1);
-                        } else if (r.getProjectAuditState() == 0 && user.getId().equals(r.getProjectAuditorId())) {
+                        }
+                        if (r.getProjectAuditState() == 0 && user.getId().equals(r.getProjectAuditorId())) {
                             newReport.setProjectAuditState(1);
                             newReport.setProjectAuditTime(LocalDateTime.now());
                             r.setProjectAuditState(1);
@@ -4077,7 +4079,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     public HttpRespMsg getReportFillStatus(String startDate, String endDate, String userId, HttpServletRequest request)throws Exception {
         HttpRespMsg msg = new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("token"));
-        DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
         List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, user.getCompanyId()));
         List<UserCustom> userCustomList = userCustomMapper.selectList(new LambdaQueryWrapper<UserCustom>().eq(UserCustom::getCompanyId, user.getCompanyId()));
         List<UserFvTime> userFvTimeList = userFvTimeMapper.selectList(new LambdaQueryWrapper<UserFvTime>().between(UserFvTime::getWorkDate, startDate, endDate));
@@ -4113,6 +4115,38 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     }
                 }
             }
+        } else if (user.getReportStatus() == 0){
+            //获取企业微信,钉钉的考勤
+            WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, user.getCompanyId()));
+            if (wxCorpInfo != null) {
+                TimeType timeType = timeTypeMapper.selectById(user.getCompanyId());
+                if (timeType.getSyncCorpwxTime() == 1) {
+                    //企业微信考勤
+                    List<UserCorpwxTime> corpwxTimeList = userCorpwxTimeMapper.selectList(new LambdaQueryWrapper<UserCorpwxTime>().between(UserCorpwxTime::getCreateDate, startDate, endDate).eq(UserCorpwxTime::getCorpwxUserid, user.getCorpwxUserid()));
+                    //遍历corpwxTimeList,在reportFillStatus中找到对应的日期的工时
+                    for (UserCorpwxTime time : corpwxTimeList) {
+                        boolean find = false;
+                        if (time.getWorkHours() > 0) {
+                            String cDate = time.getCreateDate().format(df);
+                            for (Map<String, Object> map : reportFillStatus) {
+                                if (cDate.equals(String.valueOf(map.get("createDate")))) {
+                                    find = true;
+                                    break;
+                                }
+                            }
+                            if (!find) {
+                                //没有找到,添加到reportFillStatus
+                                Map<String, Object> map = new HashMap<>();
+                                map.put("createDate", cDate);
+                                map.put("workingTime", 0);
+                                map.put("missReport", 1);
+                                reportFillStatus.add(map);
+                            }
+                        }
+
+                    }
+                }
+            }
         }
         msg.data =reportFillStatus;
         return msg;
@@ -4403,7 +4437,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         }
         List<UserMonthWork> userMonthWorks = new ArrayList<UserMonthWork>();
         //获取所有同步的企业微信数据
-        List<Map> userCorpwxTimeMapList = userCorpwxTimeMapper.selectByAsk(companyId,startDate,endDate);
+//        List<Map> userCorpwxTimeMapList = userCorpwxTimeMapper.selectByAsk(companyId,startDate,endDate);
+        List<UserCorpwxTime> userCorpwxTimeList = userCorpwxTimeMapper.selectList(new QueryWrapper<UserCorpwxTime>().between("create_date", LocalDate.parse(startDate, df), LocalDate.parse(endDate, df)).eq("corpwx_userid", user.getCorpwxUserid()));
         String lastUserId = null;
         UserMonthWork lastUserData = null;
         for (Map<String, Object> data : list) {
@@ -4477,31 +4512,61 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         for (UserMonthWork userMonthWork : userMonthWorks) {
             List<Map<String, Object>> worktimeList = userMonthWork.worktimeList;
             //获取到该员工请假的数据
-            List<Map<String, Object>> curUserCorpTime = new ArrayList<>();
-            for (Map<String, Object> corpWx : userCorpwxTimeMapList) {
-                if (((String)corpWx.get("corpwx_userid")).equals(userMonthWork.corpwxUserId)) {
-                    curUserCorpTime.add(corpWx);
-                }
-            }
+            List<UserCorpwxTime> curUserCorpTime = userCorpwxTimeList.stream().filter(s->s.getCorpwxUserid().equals(userMonthWork.corpwxUserId)).collect(Collectors.toList());
+//            for (Map<String, Object> corpWx : userCorpwxTimeMapList) {
+//                if (((String)corpWx.get("corpwx_userid")).equals(userMonthWork.corpwxUserId)) {
+//                    curUserCorpTime.add(corpWx);
+//                }
+//            }
 
             //处理企业微信的请假数据
+//            curUserCorpTime.forEach(corpTime->{
+//                java.sql.Date leaveDate = (java.sql.Date)corpTime.get("create_date");
+//                String leaveDateStr = sdf.format(leaveDate);
+//                Optional<Map<String, Object>> find = worktimeList.stream().filter(w->((String)w.get("createDate")).equals(leaveDateStr)).findFirst();
+//                if (find.isPresent()) {
+//                    //打卡的有记录,加上请假
+//                    String newStr = (double)find.get().get("workingTime")+"("+MessageUtils.message("leave.leave")+(corpTime.get("ask_leave_time"))+"h)";
+//                    find.get().put("workingTime", newStr);
+//                } else {
+//                    //没有对应的打卡记录,直接加上当天请假
+//                    Map<String, Object> leaveMap = new HashMap<>();
+//                    leaveMap.put("createDate", leaveDateStr);
+//                    //leaveMap.put("workingTime", "当天请假"+corpTime.get("ask_leave_time")+"h");
+//                    leaveMap.put("workingTime", MessageUtils.message("leave.leaveOfDay")+corpTime.get("ask_leave_time")+"h");
+//                    worktimeList.add(leaveMap);
+//                }
+//            });
             curUserCorpTime.forEach(corpTime->{
-                java.sql.Date leaveDate = (java.sql.Date)corpTime.get("create_date");
-                String leaveDateStr = sdf.format(leaveDate);
-                Optional<Map<String, Object>> find = worktimeList.stream().filter(w->((String)w.get("createDate")).equals(leaveDateStr)).findFirst();
+                LocalDate wDate = corpTime.getCreateDate();
+                String curWDateStr = df.format(wDate);
+                double askLeaveTime = corpTime.getAskLeaveTime();
+//                String leaveDateStr = sdf.format(leaveDate);
+                Optional<Map<String, Object>> find = worktimeList.stream().filter(w->((String)w.get("createDate")).equals(curWDateStr)).findFirst();
                 if (find.isPresent()) {
-                    //打卡的有记录,加上请假
-                    String newStr = (double)find.get().get("workingTime")+"("+MessageUtils.message("leave.leave")+(corpTime.get("ask_leave_time"))+"h)";
-                    find.get().put("workingTime", newStr);
+                    //打卡的有记录,如果有请假,加上请假
+                    if (askLeaveTime > 0) {
+                        String newStr = (double)find.get().get("workingTime")+"("+MessageUtils.message("leave.leave")+(corpTime.getAskLeaveTime())+"h)";
+                        find.get().put("workingTime", newStr);
+                    }
                 } else {
                     //没有对应的打卡记录,直接加上当天请假
-                    Map<String, Object> leaveMap = new HashMap<>();
-                    leaveMap.put("createDate", leaveDateStr);
-                    //leaveMap.put("workingTime", "当天请假"+corpTime.get("ask_leave_time")+"h");
-                    leaveMap.put("workingTime", MessageUtils.message("leave.leaveOfDay")+corpTime.get("ask_leave_time")+"h");
-                    worktimeList.add(leaveMap);
+                    if (askLeaveTime > 0) {
+                        Map<String, Object> leaveMap = new HashMap<>();
+                        leaveMap.put("createDate", curWDateStr);
+                        leaveMap.put("workingTime", MessageUtils.message("leave.leaveOfDay")+corpTime.getAskLeaveTime()+"h");
+                        worktimeList.add(leaveMap);
+                    } else {
+                        Map<String, Object> leaveMap = new HashMap<>();
+                        leaveMap.put("createDate", curWDateStr);
+                        leaveMap.put("workingTime", "漏填");
+                        leaveMap.put("missReport", 1);
+                        worktimeList.add(leaveMap);
+                    }
+
                 }
             });
+
             //钉钉请假的数据
             if ((timeType.getSyncDingding() == 1 || timeType.getSyncFanwei()==1 || company.getPackageOa() == 1)&& leaveSheets != null && leaveSheets.size() > 0) {
                 List<LeaveSheet> curUserLeaveList = leaveSheets.stream().filter(leave -> leave.getOwnerId().equals(userMonthWork.userId)).collect(Collectors.toList());
@@ -7721,9 +7786,12 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     }
 
     @Override
-    public HttpRespMsg getWeeklyReportData(String targetDate, HttpServletRequest request) {
+    public HttpRespMsg getWeeklyReportData(String targetDate, String targetUserId, HttpServletRequest request) {
         HttpRespMsg msg = new HttpRespMsg();
         String userId = request.getHeader("TOKEN");
+        if (!StringUtils.isEmpty(targetUserId)) {
+            userId = targetUserId;
+        }
         User user = userMapper.selectById(userId);
         Company company = companyMapper.selectById(user.getCompanyId());
         //根据targetDate获取本周的日期
@@ -9184,7 +9252,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 reportMapper.denyReportWithUserAndCreateDate(String.valueOf(e.get("userId")),String.valueOf(e.get("createDate")));
                 //发送企业微信消息
                 if(wxCorpInfo!=null&&e.get("corpwxUserId")!=null){
-                    wxCorpInfoService.sendWXCorpMsg(wxCorpInfo,String.valueOf(e.get("corpwxUserId")), "您在"+String.valueOf(e.get("createDate"))+"的日报考勤填报异常,请完成填报变更", null, WxCorpInfoServiceImpl.TEXT_CARD_MSG_REPORT_DENY);
+                    wxCorpInfoService.sendWXCorpMsg(wxCorpInfo,String.valueOf(e.get("corpwxUserId")), "您在"+String.valueOf(e.get("createDate"))+"的日报考勤填报异常,请完成填报变更", null, WxCorpInfoServiceImpl.TEXT_CARD_MSG_REPORT_ABNOEMAL);
                 }
             });
         }

+ 5 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java

@@ -604,7 +604,11 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
         }
 
         List<SysModule> moduleList = sysModuleMapper.selectList(queryWrapper);
-
+        if (company.getId() == 5978) {
+            //针对景昱,返回财务报告审核模块
+            SysModule module = sysModuleMapper.selectOne(new QueryWrapper<SysModule>().eq("name", "财务报告审核"));
+            moduleList.add(module);
+        }
         //过滤一下,这个角色选中的模块
         moduleList = moduleList.stream().filter(m->ids.contains(m.getId())).collect(Collectors.toList());
         if (company.getPackageEngineering() == 1) {

+ 54 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java

@@ -89,13 +89,19 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
     //提交审批至企业微信
     public static final String APPLY_EVENT = "https://qyapi.weixin.qq.com/cgi-bin/oa/applyevent?access_token=ACCESS_TOKEN";
 
+    //批量获取企业审批单号
+    public static final String BATCH_GET_APPROVAL_INFO = "https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovalinfo?access_token=ACCESS_TOKEN";
+
+    //获取审批申请详情
+    public static final String GET_APPROVAL_DETAIL = "https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovaldetail?access_token=ACCESS_TOKEN";
+
 
     public static final int TEXT_CARD_MSG_BUSTRIP_WAITING_AUDIT = 0;//出差待审核
     public static final int TEXT_CARD_MSG_BUSTRIP_AGREE = 1;//出差审核通过
     public static final int TEXT_CARD_MSG_BUSTRIP_DENY = 2;//出差审核驳回
     public static final int TEXT_CARD_MSG_REPORT_DENY = 10;//日报驳回
     public static final int TEXT_CARD_MSG_REPORT_AGREE = 11; //日报审核通过
-
+    public static final int TEXT_CARD_MSG_REPORT_ABNOEMAL = 12;//日报驳回
     public static final int TEXT_CARD_MSG_EXPENSE_AGREE = 21;//费用报销审核通过
     public static final int TEXT_CARD_MSG_EXPENSE_DENY = 22;//费用报销审核驳回
 
@@ -297,6 +303,8 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                     title = "日报驳回";
                 } else if (msgType.equals(TEXT_CARD_MSG_REPORT_AGREE)) {
                     title = "日报审核通过";
+                }else if (msgType.equals(TEXT_CARD_MSG_REPORT_ABNOEMAL)) {
+                    title = "异常提醒";
                 }
             } else {
                 jumpUrl = jumpUrl.replace("STATE", pageRouter);
@@ -2403,6 +2411,51 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
         return null;
     }
 
+    /**
+     * 批量获取审批单号
+     * PS:Integer recordType 1-请假;2-打卡补卡;3-出差;4-外出;5-加班; 6- 调班;7-会议室预定;8-退款审批;9-红包报销审批
+     *    Integer sp_status 1-审批中;2-已通过;3-已驳回;4-已撤销;6-通过后撤销;7-已删除;10-已支付
+     * */
+    @Override
+    public JSONArray getApprovalInfo(Integer companyId, String startDate, String endDate, String newCursor, JSONArray filterArray) throws Exception {
+        DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        LocalDateTime startDateTime = LocalDate.parse(startDate, df).atTime(LocalTime.MIN);
+        LocalDateTime endDateTime = LocalDate.parse(endDate, df).atTime(LocalTime.MAX);
+        long startTime = startDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli() -
+                LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
+        long endTime = endDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli() -
+                LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
+        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id",companyId));
+        String url=BATCH_GET_APPROVAL_INFO.replace("ACCESS_TOKEN",getCorpAccessToken(wxCorpInfo));
+        HttpHeaders headers = new HttpHeaders();
+        RestTemplate restTemplate = new RestTemplate();
+        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
+        headers.setContentType(type);
+        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
+        JSONObject requestMap = new JSONObject();
+        requestMap.put("starttime",startTime);
+        requestMap.put("endtime",endTime);
+        requestMap.put("new_cursor",newCursor);
+        requestMap.put("size",100);
+        requestMap.put("filters",filterArray);
+        HttpEntity<JSONObject> entity = new HttpEntity<>(requestMap, headers);
+        ResponseEntity<String> ResponseEntity = restTemplate.postForEntity(url, entity, String.class);
+        if (ResponseEntity.getStatusCode() == HttpStatus.OK) {
+            JSONArray jsonArray=new JSONArray();
+            String resp = ResponseEntity.getBody();
+            JSONObject jsonObject = JSONObject.parseObject(resp);
+            JSONArray sp_no_list = jsonObject.getJSONArray("sp_no_list");
+            jsonArray.addAll(sp_no_list);
+            if(jsonObject.containsKey("new_next_cursor")){
+                String new_next_cursor = jsonObject.getString("new_next_cursor");
+                JSONArray approvalInfo = getApprovalInfo(companyId, startDate, endDate, new_next_cursor, filterArray);
+                jsonArray.addAll(approvalInfo);
+            }
+            return jsonArray;
+        }
+        return null;
+    }
+
     /**
      * 提交审批到企业微信
      * */

+ 268 - 137
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java

@@ -96,6 +96,8 @@ public class TimingTask {
     @Resource
     private CompanyDingdingMapper companyDingdingMapper;
     @Resource
+    FinancialAuditService financialAuditService;
+    @Resource
     private ScreenshotMapper screenshotMapper;
     @Resource
     private TimeTypeMapper timeTypeMapper;
@@ -936,90 +938,205 @@ public class TimingTask {
     private void alertWaitingApprove() {
         if (isDev) return;
         LocalDateTime now = LocalDateTime.now();
-        DateTimeFormatter df=DateTimeFormatter.ofPattern("HH:mm");
+        DateTimeFormatter df = DateTimeFormatter.ofPattern("HH:mm");
         List<TimeType> timeTypeList = timeTypeMapper.selectList(new QueryWrapper<TimeType>().eq("wait_check_alert_time", df.format(now.toLocalTime())));
         List<Integer> companyIds = timeTypeList.stream().map(TimeType::getCompanyId).distinct().collect(Collectors.toList());
         companyIds.add(-1);
         List<CompanyDingding> list = companyDingdingMapper.getDingdingCompanyList(companyIds);
         for (CompanyDingding companyDingding : list) {
-            List<Map<String, Object>> result = reportMapper.getProWaitingApproveCnt(companyDingding.getCompanyId());
-            List<Map<String, Object>> result1 = reportMapper.getDeptWaitingApproveCnt(companyDingding.getCompanyId());
-            List<Object> resultCorpwxUserIds = result.stream().map(rl -> rl.get("auditorDDId")).collect(Collectors.toList());
-            for (Map<String, Object> map : result) {
-                Optional<Map<String, Object>> first = result1.stream().filter(r1 -> r1.get("auditorDDId") != null && r1.get("auditorDDId").equals(map.get("auditorDDId"))).findFirst();
-                Long num = Long.valueOf(String.valueOf(map.get("num")));
-                BigDecimal bigDecimal=new BigDecimal(num);
-                if(first.isPresent()){
-                    bigDecimal=bigDecimal.add(new BigDecimal(String.valueOf(first.get().get("num"))));
-                }
-                companyDingdingService.sendReportWaitingApplyMsg(companyDingding.getCompanyId(), companyDingding.getAgentId(),
-                        bigDecimal.longValue(), (String)map.get("auditorDDId"));
+            //发送推送提醒
+            Integer companyId = companyDingding.getCompanyId();
+            Company company = companyMapper.selectById(companyId);
+            //过期公司不提醒
+            if(company.getExpirationDate().isBefore(LocalDateTime.now())){
+                continue;
             }
-            for (Map<String, Object> map : result1) {
-                if(!resultCorpwxUserIds.stream().anyMatch(ol->ol != null && ((String)ol).equals(map.get("auditorDDId")))){
-                    Long num = Long.valueOf(String.valueOf(map.get("num")));
-                    BigDecimal bigDecimal=new BigDecimal(num);
-                    companyDingdingService.sendReportWaitingApplyMsg(companyDingding.getCompanyId(), companyDingding.getAgentId(),
-                            bigDecimal.longValue(), (String)map.get("auditorDDId"));
+            //判断日报审核类型
+            timeTypeList.stream().filter(timeType -> timeType.getCompanyId().equals(companyId)).findFirst().ifPresent(timeType -> {
+                if (timeType.getReportAuditType() == 7) {//并行审核模式
+                    List<User> userList = userMapper.selectList(new QueryWrapper<User>().select("id,dingding_userid", "corpwx_userid").eq("company_id", companyId));
+                    List<Report> reportList = reportMapper.selectList(new QueryWrapper<Report>().select("id, project_auditor_id, audit_dept_managerid,project_audit_state,department_audit_state").eq("company_id", companyId).eq("state", 0));
+                    HashMap<String, Long> auditorMap = new HashMap();
+                    for (Report report : reportList) {
+                        //按审核人汇总统计
+                        String pAuditorId = null;
+                        if (report.getProjectAuditState() == 0) {
+                            pAuditorId = report.getProjectAuditorId();
+                            if (auditorMap.get(pAuditorId) == null) {
+                                auditorMap.put(pAuditorId, 1L);
+                            } else {
+                                auditorMap.put(pAuditorId, auditorMap.get(pAuditorId) + 1);
+                            }
+                        }
+                        String deptAuditorId = null;
+                        if (report.getDepartmentAuditState() == 0) {
+                            deptAuditorId = report.getAuditDeptManagerid();
+                            if (deptAuditorId != null &&!deptAuditorId.equals(pAuditorId)) {
+                                //不是同一个人,需要单独统计
+                                if (auditorMap.get(deptAuditorId) == null) {
+                                    auditorMap.put(deptAuditorId, 1L);
+                                } else {
+                                    auditorMap.put(deptAuditorId, auditorMap.get(deptAuditorId) + 1);
+                                }
+                            }
+                        }
+                    }
+                    for (Map.Entry<String, Long> entry : auditorMap.entrySet()) {
+                        String auditorId = entry.getKey();
+                        Long num = entry.getValue();
+                        Optional<User> first = userList.stream().filter(ul -> ul.getId().equals(auditorId)).findFirst();
+                        if (first.isPresent()) {
+                            companyDingdingService.sendReportWaitingApplyMsg(companyId, companyDingding.getAgentId(), num, first.get().getDingdingUserid());
+                        }
+                    }
+                } else {
+                    List<Map<String, Object>> result = reportMapper.getProWaitingApproveCnt(companyDingding.getCompanyId());
+                    List<Map<String, Object>> result1 = reportMapper.getDeptWaitingApproveCnt(companyDingding.getCompanyId());
+                    List<Object> resultCorpwxUserIds = result.stream().map(rl -> rl.get("auditorDDId")).collect(Collectors.toList());
+                    for (Map<String, Object> map : result) {
+                        Optional<Map<String, Object>> first = result1.stream().filter(r1 -> r1.get("auditorDDId") != null && r1.get("auditorDDId").equals(map.get("auditorDDId"))).findFirst();
+                        Long num = Long.valueOf(String.valueOf(map.get("num")));
+                        BigDecimal bigDecimal=new BigDecimal(num);
+                        if(first.isPresent()){
+                            bigDecimal=bigDecimal.add(new BigDecimal(String.valueOf(first.get().get("num"))));
+                        }
+                        companyDingdingService.sendReportWaitingApplyMsg(companyId, companyDingding.getAgentId(),
+                                bigDecimal.longValue(), (String)map.get("auditorDDId"));
+                    }
+                    for (Map<String, Object> map : result1) {
+                        if(!resultCorpwxUserIds.stream().anyMatch(ol->ol != null && ((String)ol).equals(map.get("auditorDDId")))){
+                            Long num = Long.valueOf(String.valueOf(map.get("num")));
+                            BigDecimal bigDecimal=new BigDecimal(num);
+                            companyDingdingService.sendReportWaitingApplyMsg(companyId, companyDingding.getAgentId(),
+                                    bigDecimal.longValue(), (String)map.get("auditorDDId"));
+                        }
+                    }
                 }
-            }
+            });
         }
         List<WxCorpInfo> wxCorpInfoList = wxCorpInfoMapper.getWxCompanyList(companyIds);
         for (WxCorpInfo wxCorpInfo : wxCorpInfoList) {
             if (wxCorpInfo!=null) {
-                List<Map<String, Object>> result = reportMapper.getProWaitingApproveCnt(wxCorpInfo.getCompanyId());
-                List<Map<String, Object>> result1 = reportMapper.getDeptWaitingApproveCnt(wxCorpInfo.getCompanyId());
-                List<Object> resultCorpwxUserIds = result.stream().map(rl -> rl.get("corpwxUserid")).collect(Collectors.toList());
-                for (Map<String, Object> map : result) {
-                    Optional<Map<String, Object>> first = result1.stream().filter(r1 -> r1.get("corpwxUserid") != null && r1.get("corpwxUserid").equals(map.get("corpwxUserid"))).findFirst();
-                    if(map.get("corpwxUserid")!=null){
-                    String corpwxUserid = (String) map.get("corpwxUserid");
-                    //推送到企业微信
-                    JSONObject json=new JSONObject();
-                    JSONArray dataJson=new JSONArray();
-                    JSONObject jsonObj=new JSONObject();
-                    Integer num = Integer.valueOf(String.valueOf(map.get("num")));
-                    BigDecimal bigDecimal=new BigDecimal(num);
-                    if(first.isPresent()){
-                        bigDecimal=bigDecimal.add(new BigDecimal(String.valueOf(first.get().get("num"))));
-                    }
-                    jsonObj.put("key", "待审核数量");
-                    jsonObj.put("value",bigDecimal.toPlainString());
-                    dataJson.add(jsonObj);
-                    if(isPrivateDeploy){
-                        json.put("content","待审核数量: "+(bigDecimal.toPlainString())+"\\n<a href=\\\"https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww4e237fd6abb635af&redirect_uri="+pcUrl+"/api/corpWXAuth&response_type=code&scope=snsapi_base&state=0#wechat_redirect\\\">去审核</a>");
-                    }else {
-                        json.put("template_id","tty9TkCAAAuPvPjabDdQXGocnG0K24EQ");
-                        json.put("url","https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww4e237fd6abb635af&redirect_uri=http://worktime.ttkuaiban.com/api/corpWXAuth&response_type=code&scope=snsapi_base&state=review#wechat_redirect");
-                        json.put("content_item",dataJson);
-                    }
-                    wxCorpInfoService.sendWXCorpTemplateMsg(wxCorpInfo, corpwxUserid, json);
-                    }
+                //发送推送提醒
+                Company company = companyMapper.selectById(wxCorpInfo.getCompanyId());
+                Integer companyId = company.getId();
+                //过期公司不提醒
+                if(company.getExpirationDate().isBefore(LocalDateTime.now())){
+                    continue;
                 }
-                for (Map<String, Object> map : result1) {
-                    if(!resultCorpwxUserIds.stream().anyMatch(ol->ol != null && ((String)ol).equals(map.get("corpwxUserid")))){
-                        if(map.get("corpwxUserid")!=null){
-                            String corpwxUserid = (String) map.get("corpwxUserid");
-                            //推送到企业微信
-                            JSONObject json=new JSONObject();
-                            JSONArray dataJson=new JSONArray();
-                            JSONObject jsonObj=new JSONObject();
-                            Integer num = Integer.valueOf(String.valueOf(map.get("num")));
-                            BigDecimal bigDecimal=new BigDecimal(num);
-                            jsonObj.put("key", "待审核数量");
-                            jsonObj.put("value",bigDecimal.toPlainString());
-                            dataJson.add(jsonObj);
-                            if(isPrivateDeploy){
-                                json.put("content","待审核数量: "+(bigDecimal.toPlainString())+"\\n<a href=\\\"https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww4e237fd6abb635af&redirect_uri="+pcUrl+"/api/corpWXAuth&response_type=code&scope=snsapi_base&state=0#wechat_redirect\\\">去审核</a>");
-                            }else {
-                                json.put("template_id","tty9TkCAAAuPvPjabDdQXGocnG0K24EQ");
-                                json.put("url","https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww4e237fd6abb635af&redirect_uri=http://worktime.ttkuaiban.com/api/corpWXAuth&response_type=code&scope=snsapi_base&state=review#wechat_redirect");
-                                json.put("content_item",dataJson);
+                //判断日报审核类型
+                timeTypeList.stream().filter(timeType -> timeType.getCompanyId().equals(companyId)).findFirst().ifPresent(timeType -> {
+                    if (timeType.getReportAuditType() == 7) {//并行审核模式
+                        List<User> userList = userMapper.selectList(new QueryWrapper<User>().select("id,dingding_userid", "corpwx_userid").eq("company_id", companyId));
+                        List<Report> reportList = reportMapper.selectList(new QueryWrapper<Report>().select("id, project_auditor_id, audit_dept_managerid,project_audit_state,department_audit_state").eq("company_id", companyId).eq("state", 0));
+                        HashMap<String, Long> auditorMap = new HashMap();
+                        for (Report report : reportList) {
+                            //按审核人汇总统计
+                            String pAuditorId = null;
+                            if (report.getProjectAuditState() == 0) {
+                                pAuditorId = report.getProjectAuditorId();
+                                if (auditorMap.get(pAuditorId) == null) {
+                                    auditorMap.put(pAuditorId, 1L);
+                                } else {
+                                    auditorMap.put(pAuditorId, auditorMap.get(pAuditorId) + 1);
+                                }
+                            }
+                            String deptAuditorId = null;
+                            if (report.getDepartmentAuditState() == 0) {
+                                deptAuditorId = report.getAuditDeptManagerid();
+                                if (!deptAuditorId.equals(pAuditorId)) {
+                                    //不是同一个人,需要单独统计
+                                    if (auditorMap.get(deptAuditorId) == null) {
+                                        auditorMap.put(deptAuditorId, 1L);
+                                    } else {
+                                        auditorMap.put(deptAuditorId, auditorMap.get(deptAuditorId) + 1);
+                                    }
+                                }
+                            }
+                        }
+                        for (Map.Entry<String, Long> entry : auditorMap.entrySet()) {
+                            String auditorId = entry.getKey();
+                            Long num = entry.getValue();
+                            Optional<User> first = userList.stream().filter(ul -> ul.getId().equals(auditorId)).findFirst();
+                            if (first.isPresent()) {
+                                if (first.get().getCorpwxUserid() != null) {
+                                    String corpwxUserid = first.get().getCorpwxUserid();
+                                    //推送到企业微信
+                                    JSONObject json=new JSONObject();
+                                    JSONArray dataJson=new JSONArray();
+                                    JSONObject jsonObj=new JSONObject();
+                                    jsonObj.put("key", "待审核数量");
+                                    jsonObj.put("value",num+"");
+                                    dataJson.add(jsonObj);
+                                    if(isPrivateDeploy){
+                                        json.put("content","待审核数量: "+num+"\\n<a href=\\\"https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww4e237fd6abb635af&redirect_uri="+pcUrl+"/api/corpWXAuth&response_type=code&scope=snsapi_base&state=0#wechat_redirect\\\">去审核</a>");
+                                    }else {
+                                        json.put("template_id","tty9TkCAAAuPvPjabDdQXGocnG0K24EQ");
+                                        json.put("url","https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww4e237fd6abb635af&redirect_uri=http://worktime.ttkuaiban.com/api/corpWXAuth&response_type=code&scope=snsapi_base&state=review#wechat_redirect");
+                                        json.put("content_item",dataJson);
+                                    }
+//                                    System.out.println("发送企业微信消息==用户:"+first.get().getId()+", name="+first.get().getName()+", "+json.toJSONString());
+                                    wxCorpInfoService.sendWXCorpTemplateMsg(wxCorpInfo, corpwxUserid, json);
+                                }
+                            }
+                        }
+                    } else {
+                        List<Map<String, Object>> result = reportMapper.getProWaitingApproveCnt(wxCorpInfo.getCompanyId());
+                        List<Map<String, Object>> result1 = reportMapper.getDeptWaitingApproveCnt(wxCorpInfo.getCompanyId());
+                        List<Object> resultCorpwxUserIds = result.stream().map(rl -> rl.get("corpwxUserid")).collect(Collectors.toList());
+                        for (Map<String, Object> map : result) {
+                            Optional<Map<String, Object>> first = result1.stream().filter(r1 -> r1.get("corpwxUserid") != null && r1.get("corpwxUserid").equals(map.get("corpwxUserid"))).findFirst();
+                            if(map.get("corpwxUserid")!=null){
+                                String corpwxUserid = (String) map.get("corpwxUserid");
+                                //推送到企业微信
+                                JSONObject json=new JSONObject();
+                                JSONArray dataJson=new JSONArray();
+                                JSONObject jsonObj=new JSONObject();
+                                Integer num = Integer.valueOf(String.valueOf(map.get("num")));
+                                BigDecimal bigDecimal=new BigDecimal(num);
+                                if(first.isPresent()){
+                                    bigDecimal=bigDecimal.add(new BigDecimal(String.valueOf(first.get().get("num"))));
+                                }
+                                jsonObj.put("key", "待审核数量");
+                                jsonObj.put("value",bigDecimal.toPlainString());
+                                dataJson.add(jsonObj);
+                                if(isPrivateDeploy){
+                                    json.put("content","待审核数量: "+(bigDecimal.toPlainString())+"\\n<a href=\\\"https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww4e237fd6abb635af&redirect_uri="+pcUrl+"/api/corpWXAuth&response_type=code&scope=snsapi_base&state=0#wechat_redirect\\\">去审核</a>");
+                                }else {
+                                    json.put("template_id","tty9TkCAAAuPvPjabDdQXGocnG0K24EQ");
+                                    json.put("url","https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww4e237fd6abb635af&redirect_uri=http://worktime.ttkuaiban.com/api/corpWXAuth&response_type=code&scope=snsapi_base&state=review#wechat_redirect");
+                                    json.put("content_item",dataJson);
+                                }
+                                wxCorpInfoService.sendWXCorpTemplateMsg(wxCorpInfo, corpwxUserid, json);
+                            }
+                        }
+                        for (Map<String, Object> map : result1) {
+                            if(!resultCorpwxUserIds.stream().anyMatch(ol->ol != null && ((String)ol).equals(map.get("corpwxUserid")))){
+                                if(map.get("corpwxUserid")!=null){
+                                    String corpwxUserid = (String) map.get("corpwxUserid");
+                                    //推送到企业微信
+                                    JSONObject json=new JSONObject();
+                                    JSONArray dataJson=new JSONArray();
+                                    JSONObject jsonObj=new JSONObject();
+                                    Integer num = Integer.valueOf(String.valueOf(map.get("num")));
+                                    BigDecimal bigDecimal=new BigDecimal(num);
+                                    jsonObj.put("key", "待审核数量");
+                                    jsonObj.put("value",bigDecimal.toPlainString());
+                                    dataJson.add(jsonObj);
+                                    if(isPrivateDeploy){
+                                        json.put("content","待审核数量: "+(bigDecimal.toPlainString())+"\\n<a href=\\\"https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww4e237fd6abb635af&redirect_uri="+pcUrl+"/api/corpWXAuth&response_type=code&scope=snsapi_base&state=0#wechat_redirect\\\">去审核</a>");
+                                    }else {
+                                        json.put("template_id","tty9TkCAAAuPvPjabDdQXGocnG0K24EQ");
+                                        json.put("url","https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww4e237fd6abb635af&redirect_uri=http://worktime.ttkuaiban.com/api/corpWXAuth&response_type=code&scope=snsapi_base&state=review#wechat_redirect");
+                                        json.put("content_item",dataJson);
+                                    }
+                                    wxCorpInfoService.sendWXCorpTemplateMsg(wxCorpInfo, corpwxUserid, json);
+                                }
                             }
-                            wxCorpInfoService.sendWXCorpTemplateMsg(wxCorpInfo, corpwxUserid, json);
                         }
                     }
-                }
+                });
+
             }
         }
     }
@@ -1341,7 +1458,7 @@ public class TimingTask {
             if (str.equals(t.getAlertTime())) {
                 //节假日是否提醒
                 Boolean workDay = timeTypeService.isWorkDay(t.getCompanyId(), localDate);
-                if (!workDay){
+                if ((t.getAlertType() == 0 || t.getAlertType() == 1) && !workDay){
                     return;
                 }
                 //发送推送提醒
@@ -1455,6 +1572,9 @@ public class TimingTask {
                         if (u.get("corpwxUserid") != null){
                             //推送到企业微信
                             String corpUid = (String) u.get("corpwxUserid");
+                            if ("woy9TkCAAAyVAc5oXhGwCO-DFWF8SfKg".equals(corpUid)){
+                                System.out.println("发送给 【顾焕峰】漏填提醒");
+                            }
                             JSONObject json=new JSONObject();
                             JSONArray dataJson = new JSONArray();
                             JSONObject jsonObj = new JSONObject();
@@ -1468,7 +1588,13 @@ public class TimingTask {
                                 }
                             } else {
                                 if (finalLastWeekNotFill) {
-                                    jsonObj.put("value", "您上周有"+(Integer)u.get("days")+"天未填写工时报告,请尽快填写");
+                                    String text = null;
+                                    if (!StringUtils.isEmpty(t.getAlertMsg()) && t.getAlertMsg().contains("{0}")) {
+                                        text = t.getAlertMsg().replace("{0}", u.get("daysTxt").toString());
+                                    } else {
+                                        text = "您上周有"+(Integer)u.get("days")+"天未填写工时报告,请尽快填写";
+                                    }
+                                    jsonObj.put("value", text);
                                 } else {
                                     jsonObj.put("value", StringUtils.isEmpty(t.getAlertMsg())?"":t.getAlertMsg());
                                 }
@@ -1482,7 +1608,7 @@ public class TimingTask {
                                 json.put("content_item",dataJson);
                             }
                             if (cpList.size() > 0) {
-//                            System.out.println("发送企业微信漏填提醒:" + LocalDateTime.now().toString() + ", corpUid=" + corpUid + ", json=" + json.toJSONString());
+                                System.out.println("发送企业微信漏填提醒:" + LocalDateTime.now().toString() + ", corpUid=" + corpUid + ", json=" + json.toJSONString());
                                 wxCorpInfoService.sendWXCorpTemplateMsg(cpList.get(0), corpUid, json);
                             }
                         } else if (u.get("wxOpenid") != null) {
@@ -1497,7 +1623,6 @@ public class TimingTask {
                         companyDingdingService.sendFillReportAlertMsg(t.getCompanyId(), compDingding.getAgentId(), t.getAlertMsg(), idStr);
                     }
                 }
-
             }
         });
         if (isDev) {
@@ -2144,30 +2269,28 @@ public class TimingTask {
                 Stream<JSONObject> timeStream1 = times.stream().map(time -> (JSONObject) time);
                 //获取最早上班打卡时间
                 List<LocalTime> minLocalTimeList = timeStream.filter(t -> t.getIntValue("Type") == 1).map(i -> LocalDateTime.parse(i.getString("ActualTime"),df1).toLocalTime()).collect(Collectors.toList());
-                Optional<LocalTime> min = minLocalTimeList.stream().min(LocalTime::compareTo);
+                Optional<LocalTime> minOp = minLocalTimeList.stream().min(LocalTime::compareTo);
                 //获取最早上班打卡时间
                 List<LocalTime> maxLocalTimeList = timeStream1.filter(t -> t.getIntValue("Type") == 9).map(i -> LocalDateTime.parse(i.getString("ActualTime"),df1).toLocalTime()).collect(Collectors.toList());
-                Optional<LocalTime> max = maxLocalTimeList.stream().max(LocalTime::compareTo);
+                Optional<LocalTime> maxOp = maxLocalTimeList.stream().max(LocalTime::compareTo);
                 //获取最晚下班时间
                 if(first.isPresent()){
-                    boolean workDay = WorkDayCalculateUtils.isWorkDay(localDate)&&!holidaySettings.stream().anyMatch(h->h.getHolidayDate().isEqual(localDate));
+                    boolean workDay = WorkDayCalculateUtils.isWorkDay(localDate);
                     //todo:针对景昱 工作日默认以8小时工作制度加上加班时长 非工作日以加班时长为准
-                    Duration between = Duration.between(min.get(), max.get());
                     Double workTime;
-                    if(beisenConfig.getCompanyId()==5978){
+                    LocalTime min = minOp.get();
+                    LocalTime max = maxOp.get();
+                    Duration between = Duration.between(min,max);
+                    if(between.toHours()<=0){
+                        continue;
+                    }else {
                         if(workDay){
+                            //去掉休息时长
                             workTime=8.0;
                         }else {
+                            //去掉休息时长
                             workTime=0.0;
                         }
-                    }else {
-                        if(between.toHours()<0){
-                            workTime=0.0;
-                        }else {
-                            BigDecimal decimal = new BigDecimal(between.toMinutes());
-                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
-                            workTime=decimal.doubleValue();
-                        }
                     }
                     Stream<JSONObject> overTimeStream = allOverTimeList.stream().map(elment -> (JSONObject) elment);
                     Stream<JSONObject> vacationStream = allVacationList.stream().map(elment -> (JSONObject) elment);
@@ -2180,22 +2303,33 @@ public class TimingTask {
                         List<JSONObject> overTimeList = overTimeStream.filter(a -> a.getString("StaffId").equals(beisen.get().getUserId())
                                 && (a.getIntValue("ApproveStatus") == 2||a.getIntValue("ApproveStatus") == 1)).collect(Collectors.toList());
                         //加班数据可能存在结束日期是当前日期的情况的情况
-                        BigDecimal overTimeBigDecimal= new BigDecimal(0);;
+                        BigDecimal overTimeBigDecimal= new BigDecimal(0);
+                        //计算加班时长 工作日打卡超过19:00:00算加班那 非工作日全天算加班
+                        if(workDay){
+                            //工作日打卡超过19:00:00算加班那 非工作日全天算加班
+                            if(max.isAfter(LocalTime.parse("19:00:00", df4))){
+                                overTimeBigDecimal = new BigDecimal(Duration.between(LocalTime.parse("18:00:00", df4),max).toMinutes());
+                            }
+                        }else {
+                            //非工作日全天 去掉休息时长 都算加班
+                            overTimeBigDecimal=new BigDecimal(Duration.between(min, max).toMinutes()) ;
+                            long rest1 = DateTimeUtil.calculateOverlap(min, max, LocalTime.parse("12:00:00", df4), LocalTime.parse("13:00:00", df4));
+                            long rest2 = DateTimeUtil.calculateOverlap(min, max, LocalTime.parse("17:30:00", df4), LocalTime.parse("18:00:00", df4));
+                            overTimeBigDecimal=overTimeBigDecimal.subtract(new BigDecimal(rest1)).subtract(new BigDecimal(rest2));
+                        }
                         for (JSONObject o : overTimeList) {
                             //存在开始日期为当前日期的数据以及结束日期为当天日期的数据 分开计算
                             if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(localDate)){
                                 //存在开始日期为当天的数据
                                 if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate())){
                                     //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
-                                    //判断打卡时间是不是大于19:00 大于才算加班 通过打卡计算加班时长 与加班单作比较 取小
-                                    Duration timeDurantion = Duration.between(LocalTime.parse(workDay?"18:00:00":"08:30:00", df4), max.get());
-                                    BigDecimal decimal = new BigDecimal(timeDurantion.toMinutes());
-                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
-                                    double l = decimal.doubleValue();
-                                    if(l<o.getDouble("OverTimeDuration")){
-                                        overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l<0?0:l));
-                                    }else {
-                                        overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(o.getDouble("OverTimeDuration")));
+                                    //对比打卡体现的加班时长和加班单时长取小
+                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
+                                    if(divide.doubleValue()>o.getDouble("OverTimeDuration")){
+                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
+                                        workTime=workTime+o.getDouble("OverTimeDuration");
+                                    }else{
+                                        workTime=workTime+divide.doubleValue();
                                     }
                                 }else {
                                     //开始日期和结束日期是不相同的情况 说明是加班区间存在加班到第二天的情况
@@ -2203,17 +2337,15 @@ public class TimingTask {
                                     LocalDateTime stop = start.toLocalDate().atTime(LocalTime.MAX);
                                     Duration duration = Duration.between(start, stop);
                                     BigDecimal decimal = new BigDecimal(duration.toMinutes());
-                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_DOWN);
                                     double l = decimal.doubleValue();
-                                    //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
-                                    Duration timeDurantion = Duration.between(LocalTime.parse(workDay?"18:00:00":"08:30:00", df4), max.get());
-                                    BigDecimal decimal1 = new BigDecimal(timeDurantion.toMinutes());
-                                    decimal1=decimal1.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
-                                    double l1 = decimal1.doubleValue();
-                                    if(l1<l){
-                                        overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l1<0?0:l1));
+                                    //对比打卡体现的加班时长和加班单时长取小
+                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
+                                    if(divide.doubleValue()>l){
+                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
+                                        workTime=workTime+l;
                                     }else {
-                                        overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l));
+                                        workTime=workTime+divide.doubleValue();
                                     }
                                 }
                             }else if(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate().isEqual(localDate)){
@@ -2221,14 +2353,12 @@ public class TimingTask {
                                 if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate())){
                                     //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
                                     //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
-                                    Duration timeDurantion = Duration.between(LocalTime.parse(workDay?"18:00:00":"08:30:00", df4), max.get());
-                                    BigDecimal decimal = new BigDecimal(timeDurantion.toMinutes());
-                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
-                                    double l = decimal.doubleValue();
-                                    if(l<o.getDouble("OverTimeDuration")){
-                                        overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l<0?0:l));
+                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
+                                    if(divide.doubleValue()>o.getDouble("OverTimeDuration")){
+                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
+                                        workTime=workTime+o.getDouble("OverTimeDuration");
                                     }else {
-                                        overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(o.getDouble("OverTimeDuration")));
+                                        workTime=workTime+divide.doubleValue();
                                     }
                                 }else {
                                     //开始日期和结束日期是不相同的情况 说明是加班区间存在加班到第二天的情况
@@ -2236,34 +2366,19 @@ public class TimingTask {
                                     LocalDateTime start = stop.toLocalDate().atTime(LocalTime.MIN);
                                     Duration duration = Duration.between(start, stop);
                                     BigDecimal decimal = new BigDecimal(duration.toMinutes());
-                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_DOWN);
                                     double l = decimal.doubleValue();
-                                    //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
-                                    Duration timeDurantion = Duration.between(LocalTime.parse(workDay?"18:00:00":"08:30:00", df4), max.get());
-                                    BigDecimal decimal1 = new BigDecimal(timeDurantion.toMinutes());
-                                    decimal1=decimal1.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
-                                    double l1 = decimal1.doubleValue();
-                                    if(l1<l){
-                                        overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l1<0?0:l1));
+                                    //对比打卡体现的加班时长和加班单时长取小
+                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
+                                    if(divide.doubleValue()>l){
+                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
+                                        workTime=workTime+l;
                                     }else {
-                                        overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l));
+                                        workTime=workTime+divide.doubleValue();
                                     }
                                 }
                             }
                         }
-                        if(workDay){
-                            //工作日计算按照前面的逻辑计算加班时长计算
-                            workTime= workTime+overTimeBigDecimal.doubleValue();
-                        }else {
-                            //非工作日加班 根据实际打卡时长 比较 加班单时长
-                            BigDecimal decimal = new BigDecimal(between.toMinutes());
-                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
-                            if((decimal.doubleValue())>overTimeBigDecimal.doubleValue()){
-                                workTime= workTime+overTimeBigDecimal.doubleValue();
-                            }else {
-                                workTime= workTime+(decimal.doubleValue());
-                            }
-                        }
                         List<JSONObject> vacationList = vacationStream.filter(a ->{
                             LocalDate vacationStartDate = LocalDateTime.parse(a.getString("VacationStartDateTime"), df3).toLocalDate();
                             LocalDate vacationStopDate = LocalDateTime.parse(a.getString("VacationStopDateTime"), df3).toLocalDate();
@@ -2282,7 +2397,7 @@ public class TimingTask {
                         if(vacationList.size()>0){
                             double vacationDuration = vacationList.stream().mapToDouble(i -> i.getDouble("VacationDuration")).sum();
                             BigDecimal decimal = new BigDecimal(vacationDuration);
-                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_DOWN);
 //                            //可能存在休假多天 只减去一天
                             if(decimal.doubleValue()>=8){
                                 workTime= workTime-8;
@@ -2293,8 +2408,8 @@ public class TimingTask {
                     }
                     UserFvTime userFvTime=new UserFvTime();
                     userFvTime.setWorkDate(localDate);
-                    userFvTime.setStartTime(min.isPresent()?df2.format(min.get()):"08:30:00");
-                    userFvTime.setEndTime(max.isPresent()?df2.format(max.get()):"17:30:00");
+                    userFvTime.setStartTime(df2.format(min));
+                    userFvTime.setEndTime(df2.format(max));
                     userFvTime.setUserId(first.get().getId());
                     userFvTime.setCompanyId(5978);
                     userFvTime.setWorkHours(workTime.floatValue());
@@ -2368,4 +2483,20 @@ public class TimingTask {
     public void cleanUselessData(){
         //TODO: 日报删除表report_delete,需要定期清理
     }
+
+    @Scheduled(cron = "0 15 0 1 * ?")
+    private void generateMonthlyFinanceReport() {
+        //为景昱生成上个月的财务审核报表
+        LocalDate now = LocalDate.now();
+        //获取上个月的第一天
+        LocalDate lastMonth = now.minusMonths(1).with(TemporalAdjusters.firstDayOfMonth());
+        Integer companyId = 5978;
+        FinancialAudit financialAudit = financialAuditService.getOne(new LambdaQueryWrapper<FinancialAudit>().eq(FinancialAudit::getCompanyId, companyId).eq(FinancialAudit::getReportYrmnth, lastMonth));
+        if(financialAudit==null){
+            financialAudit=new FinancialAudit();
+            financialAudit.setCompanyId(companyId);
+            financialAudit.setReportYrmnth(lastMonth);
+            financialAuditService.save(financialAudit);
+        }
+    }
 }

+ 12 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/DateTimeUtil.java

@@ -5,6 +5,7 @@ import org.apache.tomcat.jni.Local;
 import java.math.BigDecimal;
 import java.time.*;
 import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
 import java.time.temporal.TemporalAccessor;
 import java.util.Arrays;
 import java.util.Date;
@@ -37,6 +38,17 @@ public class DateTimeUtil {
         return hours;
     }
 
+    public static long calculateOverlap(LocalTime start1, LocalTime end1, LocalTime start2, LocalTime end2) {
+        if (start1.isAfter(end2) || start2.isAfter(end1)) {
+            return 0;
+        }
+
+        LocalTime overlapStart = start1.isBefore(start2) ? start2 : start1;
+        LocalTime overlapEnd = end1.isAfter(end2) ? end2 : end1;
+
+        return ChronoUnit.MINUTES.between(overlapStart, overlapEnd);
+    }
+
     /**
      * 返回四舍五入到整数的部分
      */

+ 21 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/FinancialAuditMapper.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.management.platform.mapper.FinancialAuditMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.management.platform.entity.FinancialAudit">
+        <id column="id" property="id" />
+        <result column="report_yrMnth" property="reportYrmnth" />
+        <result column="reviewer_id" property="reviewerId" />
+        <result column="reviewer_name" property="reviewerName" />
+        <result column="review_time" property="reviewTime" />
+        <result column="review_status" property="reviewStatus" />
+        <result column="company_id" property="companyId" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, report_yrMnth, reviewer_id, reviewer_name, review_time, review_status, company_id
+    </sql>
+
+</mapper>

+ 1 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportMapper.xml

@@ -980,7 +980,7 @@
     </select>
     <select id="getDeptWaitingApproveCnt" resultType="java.util.HashMap">
         select COUNT(1) as num, user.dingding_userid as auditorDDId ,user.corpwx_userid as corpwxUserid from report
-                                                                                                                 left join `user` on `user`.id = audit_dept_managerid
+        left join `user` on `user`.id = audit_dept_managerid
         where state = 0 and department_audit_state = 0 and is_dept_audit = 1
           and report.company_id =#{companyId}
           and `user`.is_active=1

File diff suppressed because it is too large
+ 3 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/TimeTypeMapper.xml


+ 5 - 0
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/controller/PlanController.java

@@ -125,6 +125,11 @@ public class PlanController {
         return planService.receivePlan(ids);
     }
 
+    @RequestMapping("/unReceivePlan")
+    public HttpRespMsg unReceivePlan(String ids){
+        return planService.unReceivePlan(ids);
+    }
+
     @RequestMapping("/cancellationReceive")
     public HttpRespMsg cancellationReceive(Integer id){
         return planService.cancellationReceive(id);

+ 24 - 24
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/controller/ReportController.java

@@ -1532,8 +1532,8 @@ public class ReportController {
 
     //人员工时工价表
     @RequestMapping("getPersonWorkHoursWagesList")
-    public HttpRespMsg getPersonWorkHoursWagesList(Integer deptId,String userId,String startDate,String endDate,Integer pageIndex,Integer pageSize){
-        return reportService.getPersonWorkHoursWagesList(deptId,userId,startDate,endDate,pageIndex,pageSize);
+    public HttpRespMsg getPersonWorkHoursWagesList(String deptIds,String userId,String startDate,String endDate,Integer pageIndex,Integer pageSize){
+        return reportService.getPersonWorkHoursWagesList(deptIds,userId,startDate,endDate,pageIndex,pageSize);
     }
 
     @RequestMapping("getPersonWorkHoursWagesDetail")
@@ -1542,48 +1542,48 @@ public class ReportController {
     }
 
     @RequestMapping("exportPersonWorkHoursWorkTime")
-    public HttpRespMsg exportPersonWorkHoursWorkTime(Integer deptId,String userId,String startDate,String endDate){
-        return reportService.exportPersonWorkHoursWorkTime(deptId,userId,startDate,endDate);
+    public HttpRespMsg exportPersonWorkHoursWorkTime(String deptIds,String userId,String startDate,String endDate){
+        return reportService.exportPersonWorkHoursWorkTime(deptIds,userId,startDate,endDate);
     }
 
     @RequestMapping("getProcedureRealTimeProgressList")
-    public HttpRespMsg getProcedureRealTimeProgressList(String deptId,String userId,String startDate,String endDate,Integer pageIndex,Integer pageSize){
-        return reportService.getProcedureRealTimeProgressList(deptId,userId,startDate,endDate,pageIndex,pageSize);
+    public HttpRespMsg getProcedureRealTimeProgressList(String deptIds,String userId,String startDate,String endDate,Integer pageIndex,Integer pageSize){
+        return reportService.getProcedureRealTimeProgressList(deptIds,userId,startDate,endDate,pageIndex,pageSize);
     }
 
     @RequestMapping("exportProcedureRealTimeProgressList")
-    public HttpRespMsg exportProcedureRealTimeProgressList(String deptId,String userId,String startDate,String endDate){
-        return reportService.exportProcedureRealTimeProgressList(deptId,userId,startDate,endDate);
+    public HttpRespMsg exportProcedureRealTimeProgressList(String deptIds,String userId,String startDate,String endDate){
+        return reportService.exportProcedureRealTimeProgressList(deptIds,userId,startDate,endDate);
     }
 
     @RequestMapping("/workReportQuery")
-    public HttpRespMsg workReportQuery(Integer productId,String vehicleNum,String steelNum,Integer deptId,String userId,String startDate,String endDate,Integer pageIndex,Integer pageSize){
-        return reportService.workReportQuery(productId,vehicleNum,steelNum,deptId,userId,startDate,endDate,pageIndex,pageSize);
+    public HttpRespMsg workReportQuery(Integer productId,String vehicleNum,String steelNum,String deptIds,String userId,String startDate,String endDate,Integer pageIndex,Integer pageSize){
+        return reportService.workReportQuery(productId,vehicleNum,steelNum,deptIds,userId,startDate,endDate,pageIndex,pageSize);
     }
 
     @RequestMapping("/exportWorkReportQuery")
-    public HttpRespMsg exportWorkReportQuery(Integer productId,String vehicleNum,String steelNum,Integer deptId,String userId,String startDate,String endDate){
-        return reportService.exportWorkReportQuery(productId,vehicleNum,steelNum,deptId,userId,startDate,endDate);
+    public HttpRespMsg exportWorkReportQuery(Integer productId,String vehicleNum,String steelNum,String deptIds,String userId,String startDate,String endDate){
+        return reportService.exportWorkReportQuery(productId,vehicleNum,steelNum,deptIds,userId,startDate,endDate);
     }
 
     @RequestMapping("getPlanRealTimeProgressList")
-    public HttpRespMsg getPlanRealTimeProgressList(String deptId,String userId,String startDate,String endDate,Integer pageIndex,Integer pageSize){
-        return reportService.getPlanRealTimeProgressList(deptId,userId,startDate,endDate,pageIndex,pageSize);
+    public HttpRespMsg getPlanRealTimeProgressList(String deptIds,String userId,String startDate,String endDate,Integer pageIndex,Integer pageSize){
+        return reportService.getPlanRealTimeProgressList(deptIds,userId,startDate,endDate,pageIndex,pageSize);
     }
 
     @RequestMapping("exportPlanRealTimeProgressList")
-    public HttpRespMsg exportPlanRealTimeProgressList(String deptId,String userId,String startDate,String endDate){
-        return reportService.exportPlanRealTimeProgressList(deptId,userId,startDate,endDate);
+    public HttpRespMsg exportPlanRealTimeProgressList(String deptIds,String userId,String startDate,String endDate){
+        return reportService.exportPlanRealTimeProgressList(deptIds,userId,startDate,endDate);
     }
 
     @RequestMapping("getDpetStatisticsProgressList")
-    public HttpRespMsg getDpetStatisticsProgressList(String deptId,String userId,String startDate,String endDate,Integer pageIndex,Integer pageSize){
-        return reportService.getDpetStatisticsProgressList(deptId,userId,startDate,endDate,pageIndex,pageSize);
+    public HttpRespMsg getDpetStatisticsProgressList(String deptIds,String userId,String startDate,String endDate,Integer pageIndex,Integer pageSize){
+        return reportService.getDpetStatisticsProgressList(deptIds,userId,startDate,endDate,pageIndex,pageSize);
     }
 
     @RequestMapping("exportDpetStatisticsProgressList")
-    public HttpRespMsg exportDpetStatisticsProgressList(String deptId,String userId,String startDate,String endDate){
-        return reportService.exportDpetStatisticsProgressList(deptId,userId,startDate,endDate);
+    public HttpRespMsg exportDpetStatisticsProgressList(String deptIds,String userId,String startDate,String endDate){
+        return reportService.exportDpetStatisticsProgressList(deptIds,userId,startDate,endDate);
     }
 
     /**
@@ -1624,13 +1624,13 @@ public class ReportController {
     }
 
     @RequestMapping("/getPlanDataWithStation")
-    public HttpRespMsg getPlanDataWithStation(@RequestParam(defaultValue = "0") Integer isFilterDept,Integer filterDeptId,Integer stationId,String startDate,String endDate,Integer pageIndex,Integer pageSize){
-        return reportService.getPlanDataWithStation(isFilterDept,filterDeptId,stationId,startDate,endDate,pageIndex,pageSize);
+    public HttpRespMsg getPlanDataWithStation(@RequestParam(defaultValue = "0") Integer isFilterDept,Integer filterDeptId,String stationIds,String startDate,String endDate,Integer pageIndex,Integer pageSize){
+        return reportService.getPlanDataWithStation(isFilterDept,filterDeptId,stationIds,startDate,endDate,pageIndex,pageSize);
     }
 
     @RequestMapping("/exportPlanDataWithStation")
-    public HttpRespMsg exportPlanDataWithStation(@RequestParam(defaultValue = "0") Integer isFilterDept,Integer filterDeptId,Integer stationId,String startDate,String endDate){
-        return reportService.exportPlanDataWithStation(isFilterDept,filterDeptId,stationId,startDate,endDate);
+    public HttpRespMsg exportPlanDataWithStation(@RequestParam(defaultValue = "0") Integer isFilterDept,Integer filterDeptId,String stationIds,String startDate,String endDate){
+        return reportService.exportPlanDataWithStation(isFilterDept,filterDeptId,stationIds,startDate,endDate);
     }
     
     @RequestMapping("/getPlanDataWithUserId")

+ 19 - 0
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/controller/WxCorpInfoController.java

@@ -79,5 +79,24 @@ public class WxCorpInfoController {
     public HttpRespMsg batchTransferLicense(HttpServletRequest request,String handoverId,String takeoverId) throws Exception {
         return wxCorpInfoService.batchTransferLicense(request,handoverId,takeoverId);
     }
+
+
+
+    @RequestMapping("/testGetApprovalList")
+    public HttpRespMsg testGetApprovalList(String startDate,String endDate) throws Exception {
+        HttpRespMsg msg=new HttpRespMsg();
+        JSONArray jsonArrayFilter = new JSONArray();
+        JSONObject filter1 = new JSONObject();
+        filter1.put("key","record_type");
+        filter1.put("value",1);
+        jsonArrayFilter.add(filter1);
+        JSONObject filter2 = new JSONObject();
+        filter2.put("key","sp_status ");
+        filter2.put("value",2);
+        jsonArrayFilter.add(filter2);
+        JSONArray approvalInfo = wxCorpInfoService.getApprovalInfo(7, startDate, endDate, "", jsonArrayFilter);
+        msg.setData(approvalInfo.toArray());
+        return msg;
+    }
 }
 

+ 1 - 1
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/entity/Plan.java

@@ -41,7 +41,7 @@ public class Plan extends Model<Plan> {
     private String productSchedulingNum;
 
     /**
-     * 产订单号
+     * 产订单号
      */
     @TableField("product_order_num")
     private String productOrderNum;

+ 14 - 0
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/entity/ProdProcedureTeam.java

@@ -4,6 +4,8 @@ import java.math.BigDecimal;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
 import com.baomidou.mybatisplus.annotation.TableId;
+
+import java.time.LocalDate;
 import java.time.LocalDateTime;
 import com.baomidou.mybatisplus.annotation.TableField;
 import java.io.Serializable;
@@ -89,6 +91,9 @@ public class ProdProcedureTeam extends Model<ProdProcedureTeam> {
     @TableField(exist = false)
     private User user;
 
+    @TableField(exist = false)
+    private String planProcedureIds;
+
     /**
      * 是否为更换人员动作
      */
@@ -102,6 +107,15 @@ public class ProdProcedureTeam extends Model<ProdProcedureTeam> {
     @TableField("steel_num_array")
     private String steelNumArray;
 
+
+    /**
+     * 分配日期
+     */
+    @TableField("distribute_date")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate distributeDate;
+
     @Override
     protected Serializable pkVal() {
         return this.id;

+ 6 - 0
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/entity/User.java

@@ -313,6 +313,12 @@ public class User extends Model<User> {
     @TableField(exist = false)
     private String  totalResult;
 
+    @TableField(exist = false)
+    private String  totalPlanResult;
+
+    @TableField(exist = false)
+    private String  totalSurplusResult;
+
     @Override
     protected Serializable pkVal() {
         return this.id;

+ 8 - 8
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/mapper/ReportMapper.java

@@ -186,21 +186,21 @@ public interface ReportMapper extends BaseMapper<Report> {
 
     List<Map<String, Object>> getPersonWorkHoursWagesDetail(String date, String userId, Integer companyId,String startDate,String endDate,Integer checkStatus,Integer detailStatus);
 
-    List<Map<String, Object>> getProcedureRealTimeProgressList(Integer companyId,String deptId, String foremanId,String userId, String startDate, String endDate, Integer pageStart, Integer pageSize);
+    List<Map<String, Object>> getProcedureRealTimeProgressList(Integer companyId,List<Integer> deptIds, String foremanId,String userId, String startDate, String endDate, Integer pageStart, Integer pageSize);
 
-    Integer getProcedureRealTimeProgressCount(Integer companyId, String deptId, String foremanId, String userId, String startDate, String endDate);
+    Integer getProcedureRealTimeProgressCount(Integer companyId, List<Integer> deptIds, String foremanId, String userId, String startDate, String endDate);
 
-    List<Map<String, Object>> workReportQuery(Integer companyId,Integer productId, String vehicleNum,String steelNum, Integer deptId, String foremanId, String userId, String startDate, String endDate,Integer pageStart, Integer pageSize);
+    List<Map<String, Object>> workReportQuery(Integer companyId,Integer productId, String vehicleNum,String steelNum, List<Integer> deptIds, String foremanId, String userId, String startDate, String endDate,Integer pageStart, Integer pageSize);
 
-    Integer selectCountForWorkQuery(Integer companyId, Integer productId, String vehicleNum, String steelNum, Integer deptId, String foremanId, String userId, String startDate, String endDate);
+    Integer selectCountForWorkQuery(Integer companyId, Integer productId, String vehicleNum, String steelNum, List<Integer> deptIds, String foremanId, String userId, String startDate, String endDate);
 
-    List<Map<String, Object>> getPlanRealTimeProgressList(Integer companyId, String deptId, String foremanId, String userId, String startDate, String endDate, Integer pageStart, Integer pageSize,@Param("list") List<Integer> planIds);
+    List<Map<String, Object>> getPlanRealTimeProgressList(Integer companyId, List<Integer> deptIds, String foremanId, String userId, String startDate, String endDate, Integer pageStart, Integer pageSize,@Param("list") List<Integer> planIds);
 
-    Integer getPlanRealTimeProgressCount(Integer companyId, String deptId, String foremanId, String userId, String startDate, String endDate);
+    Integer getPlanRealTimeProgressCount(Integer companyId, List<Integer> deptIds, String foremanId, String userId, String startDate, String endDate);
 
-    List<Map<String, Object>> getDpetStatisticsProgressList(Integer companyId, String deptId, String foremanId, String userId, String startDate, String endDate, Integer pageStart, Integer pageSize);
+    List<Map<String, Object>> getDpetStatisticsProgressList(Integer companyId, List<Integer> deptIds, String foremanId, String userId, String startDate, String endDate, Integer pageStart, Integer pageSize);
 
-    Integer getDpetStatisticsProgressCount(Integer companyId, String deptId, String foremanId, String userId, String startDate, String endDate);
+    Integer getDpetStatisticsProgressCount(Integer companyId, List<Integer> deptIds, String foremanId, String userId, String startDate, String endDate);
 
     List<Map<String,Object>> getReportList(String startDate, String endDate, Integer planId, Integer stateKey, Integer departmentId, Integer companyId);
 

+ 2 - 0
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/PlanService.java

@@ -58,4 +58,6 @@ public interface PlanService extends IService<Plan> {
     HttpRespMsg deletePlan(Integer id);
 
     HttpRespMsg allocationUser(Integer planId);
+
+    HttpRespMsg unReceivePlan(String ids);
 }

+ 12 - 12
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/ReportService.java

@@ -117,27 +117,27 @@ public interface ReportService extends IService<Report> {
 
     HttpRespMsg getChekerList(Integer checkType, Integer deptId);
 
-    HttpRespMsg getPersonWorkHoursWagesList(Integer deptId, String userId, String startDate, String endDate, Integer pageIndex, Integer pageSize);
+    HttpRespMsg getPersonWorkHoursWagesList(String deptIds, String userId, String startDate, String endDate, Integer pageIndex, Integer pageSize);
 
     HttpRespMsg getPersonWorkHoursWagesDetail(String date, String userId,String startDate,String endDate,Integer checkStatus,Integer detailStatus);
 
-    HttpRespMsg exportPersonWorkHoursWorkTime(Integer deptId, String userId, String startDate, String endDate);
+    HttpRespMsg exportPersonWorkHoursWorkTime(String deptIds, String userId, String startDate, String endDate);
 
-    HttpRespMsg getProcedureRealTimeProgressList(String deptId, String userId, String startDate, String endDate, Integer pageIndex, Integer pageSize);
+    HttpRespMsg getProcedureRealTimeProgressList(String deptIds, String userId, String startDate, String endDate, Integer pageIndex, Integer pageSize);
 
-    HttpRespMsg exportProcedureRealTimeProgressList(String deptId, String userId, String startDate, String endDate);
+    HttpRespMsg exportProcedureRealTimeProgressList(String deptIds, String userId, String startDate, String endDate);
 
-    HttpRespMsg workReportQuery(Integer productId, String vehicleNum, String steelNum, Integer deptId, String userId, String startDate, String endDate,Integer pageIndex,Integer pageSize);
+    HttpRespMsg workReportQuery(Integer productId, String vehicleNum, String steelNum, String deptIds, String userId, String startDate, String endDate,Integer pageIndex,Integer pageSize);
 
-    HttpRespMsg exportWorkReportQuery(Integer productId, String vehicleNum, String steelNum, Integer deptId, String userId, String startDate, String endDate);
+    HttpRespMsg exportWorkReportQuery(Integer productId, String vehicleNum, String steelNum, String deptIds, String userId, String startDate, String endDate);
 
-    HttpRespMsg getPlanRealTimeProgressList(String deptId, String userId, String startDate, String endDate, Integer pageIndex, Integer pageSize);
+    HttpRespMsg getPlanRealTimeProgressList(String deptIds, String userId, String startDate, String endDate, Integer pageIndex, Integer pageSize);
 
-    HttpRespMsg exportPlanRealTimeProgressList(String deptId, String userId, String startDate, String endDate);
+    HttpRespMsg exportPlanRealTimeProgressList(String deptIds, String userId, String startDate, String endDate);
 
-    HttpRespMsg getDpetStatisticsProgressList(String deptId, String userId, String startDate, String endDate, Integer pageIndex, Integer pageSize);
+    HttpRespMsg getDpetStatisticsProgressList(String deptIds, String userId, String startDate, String endDate, Integer pageIndex, Integer pageSize);
 
-    HttpRespMsg exportDpetStatisticsProgressList(String deptId, String userId, String startDate, String endDate);
+    HttpRespMsg exportDpetStatisticsProgressList(String deptIds, String userId, String startDate, String endDate);
 
     HttpRespMsg exportReport(String startDate, String endDate, Integer planId, Integer stateKey, Integer departmentId, HttpServletRequest request);
 
@@ -149,9 +149,9 @@ public interface ReportService extends IService<Report> {
 
  	Object fixSteelNumData();
 
- 	HttpRespMsg getPlanDataWithStation(Integer isFilterDept,Integer filterDeptId,Integer stationId, String startDate, String endDate, Integer pageIndex, Integer pageSize);
+ 	HttpRespMsg getPlanDataWithStation(Integer isFilterDept,Integer filterDeptId,String stationIds, String startDate, String endDate, Integer pageIndex, Integer pageSize);
 
-    HttpRespMsg exportPlanDataWithStation(Integer isFilterDept, Integer filterDeptId, Integer stationId, String startDate, String endDate);
+    HttpRespMsg exportPlanDataWithStation(Integer isFilterDept, Integer filterDeptId, String stationIds, String startDate, String endDate);
 
     HttpRespMsg getPlanDataWithUserId(String userId, String startDate, String endDate);
 

+ 5 - 0
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/WxCorpInfoService.java

@@ -1,5 +1,6 @@
 package com.management.platform.service;
 
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.management.platform.entity.User;
@@ -79,4 +80,8 @@ public interface WxCorpInfoService extends IService<WxCorpInfo> {
      * @throws Exception
      */
     public String getCorpAgentAccessToken(WxCorpInfo corpInfo) throws Exception;
+
+    JSONArray getApprovalInfo(Integer companyId, String startDate, String endDate,String newCursor, JSONArray jsonArrayFilter) throws Exception;
+
+    String getApprovalInfoDetail(Integer companyId, String spNo) throws Exception;
 }

+ 53 - 10
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/PlanServiceImpl.java

@@ -340,7 +340,13 @@ public class PlanServiceImpl extends ServiceImpl<PlanMapper, Plan> implements Pl
             TaskType taskType = taskTypeMapper.selectById(plan.getTaskTypeId());
             plan.setTaskTypeName(taskType.getTaskTypeName());
         }
-        List<ProdProcedure> procedureList = prodProcedureMapper.selectList(new QueryWrapper<ProdProcedure>().eq("company_id", companyId).eq("product_id",plan.getProductId()).orderByDesc("id"));
+        List<ProdProcedure> procedureList = prodProcedureMapper.selectList(
+                new QueryWrapper<ProdProcedure>()
+                        .lambda()
+                        .eq(plan.getProductId() != null, ProdProcedure::getProductId, plan.getProductId())
+                        .eq(user.getCompanyId()!=null,ProdProcedure::getCompanyId,user.getCompanyId()).orderByAsc(ProdProcedure::getSeq)
+
+        );
         if(plan.getPlanType()==0){
             if(procedureList.size()<=0){
                 msg.setError("当前产品工序配置未完成,请先完成工序配置");
@@ -351,7 +357,7 @@ public class PlanServiceImpl extends ServiceImpl<PlanMapper, Plan> implements Pl
         List<PlanProcedureTotal> oldPlanProcedureTotals=new ArrayList<>();
         List<ProdProcedure> list;
         if(plan.getId()==null){
-            list = procedureList.stream().filter(pl -> pl.getVersionNumber().equals(procedureList.get(0).getVersionNumber())).collect(Collectors.toList());
+            list = procedureList.stream().filter(pl -> pl.getVersionNumber().equals(procedureList.get(procedureList.size()-1).getVersionNumber())).collect(Collectors.toList());
             if(plan.getProductSchedulingNum()!=null){
                 if(count(new QueryWrapper<Plan>().eq("product_scheduling_num",plan.getProductSchedulingNum()))>0){
                     msg.setError("当前排产工单号已存在");
@@ -599,19 +605,25 @@ public class PlanServiceImpl extends ServiceImpl<PlanMapper, Plan> implements Pl
                         }
                     }
                     plan.setPlanType(0);
-                    //排产工单号 产品名称 钢印号 数量 主工序 工位 开工时间 完工时间 描述
+                    //排产工单号 产品名称 生产订单号 项目名称 列序号 钢印号 数量 主工序 工位 开工时间 完工时间 描述
                     XSSFCell productSchedulingNumCell = row.getCell(0);
                     XSSFCell productNameCell = row.getCell(1);
-                    XSSFCell steelStampNumberCell = row.getCell(2);
-                    XSSFCell numCell = row.getCell(3);
-                    XSSFCell mainProcessCell = row.getCell(4);
-                    XSSFCell stationNameCell = row.getCell(5);
-                    XSSFCell startDateCell = row.getCell(6);
-                    XSSFCell endDateCell = row.getCell(7);
-                    XSSFCell describtionCell = row.getCell(8);
+                    XSSFCell productOrderNumCell = row.getCell(2);
+                    XSSFCell projectNameCell = row.getCell(3);
+                    XSSFCell columnNumCell = row.getCell(4);
+                    XSSFCell steelStampNumberCell = row.getCell(5);
+                    XSSFCell numCell = row.getCell(6);
+                    XSSFCell mainProcessCell = row.getCell(7);
+                    XSSFCell stationNameCell = row.getCell(8);
+                    XSSFCell startDateCell = row.getCell(9);
+                    XSSFCell endDateCell = row.getCell(10);
+                    XSSFCell describtionCell = row.getCell(11);
 
                     if (productSchedulingNumCell != null) productSchedulingNumCell.setCellType(CellType.STRING);
                     if (productNameCell != null) productNameCell.setCellType(CellType.STRING);
+                    if (productOrderNumCell != null) productOrderNumCell.setCellType(CellType.STRING);
+                    if (projectNameCell != null) projectNameCell.setCellType(CellType.STRING);
+                    if (columnNumCell != null) columnNumCell.setCellType(CellType.STRING);
                     if (steelStampNumberCell != null) steelStampNumberCell.setCellType(CellType.STRING);
                     if (numCell != null) numCell.setCellType(CellType.NUMERIC);
                     if (mainProcessCell != null) mainProcessCell.setCellType(CellType.STRING);
@@ -635,6 +647,22 @@ public class PlanServiceImpl extends ServiceImpl<PlanMapper, Plan> implements Pl
                         }
                         plan.setProductSchedulingNum(productSchedulingNumCell.getStringCellValue());
                     }
+                    if(productOrderNumCell!=null&&!StringUtils.isEmpty(productOrderNumCell.getStringCellValue())){
+                        plan.setProductOrderNum(productOrderNumCell.getStringCellValue());
+                    }
+                    if(projectNameCell!=null&&!StringUtils.isEmpty(productNameCell.getStringCellValue())){
+                        plan.setProjectName(projectNameCell.getStringCellValue());
+                    }
+                    if(columnNumCell!=null&&StringUtils.isEmpty(columnNumCell.getStringCellValue())){
+                        String stringCellValue = columnNumCell.getStringCellValue();
+                        if(stringCellValue.contains("-")){
+                            String[] split = stringCellValue.split("-");
+                            if(split.length>1){
+                                plan.setColumnNumStart(Integer.valueOf(split[0]));
+                                plan.setColumnNumEnd(Integer.valueOf(split[1]));
+                            }
+                        }
+                    }
                     if(steelStampNumberCell!=null&&!StringUtils.isEmpty(steelStampNumberCell.getStringCellValue())){
                         String stringCellValue = steelStampNumberCell.getStringCellValue();
                         String[] split = stringCellValue.split("\\|");
@@ -1161,6 +1189,20 @@ public class PlanServiceImpl extends ServiceImpl<PlanMapper, Plan> implements Pl
         return msg;
     }
 
+    @Override
+    public HttpRespMsg unReceivePlan(String ids) {
+        HttpRespMsg msg=new HttpRespMsg();
+        if(StringUtils.isEmpty(ids)){
+            return msg;
+        }
+        List<String> idList =new ArrayList<>(Arrays.asList(ids.split(",")));
+        idList.add("-1");
+        if(!prodProcedureTeamService.removeByIds(idList)){
+            msg.setError("验证失败");
+        }
+        return msg;
+    }
+
     @Override
     public HttpRespMsg deletePeople(Integer id) {
         HttpRespMsg msg=new HttpRespMsg();
@@ -1257,6 +1299,7 @@ public class PlanServiceImpl extends ServiceImpl<PlanMapper, Plan> implements Pl
                 ProdProcedureTeam prodProcedureTeam=new ProdProcedureTeam();
                 prodProcedureTeam.setCompanyId(companyId);
                 prodProcedureTeam.setPlanProcedureId(planProcedureTotal.getId());
+                prodProcedureTeam.setDistributeDate(LocalDate.now());
                 prodProcedureTeam.setUserId(team[i]);
                 int finalI = i;
                 //已存在的人员更新处理

+ 4 - 1
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/ProdProcedureServiceImpl.java

@@ -111,19 +111,22 @@ public class ProdProcedureServiceImpl extends ServiceImpl<ProdProcedureMapper, P
                     this.updateBatchById(updateList);
                     //todo:更新产品工序单价
                     List<Integer> procedureIds = updateList.stream().map(ProdProcedure::getId).distinct().collect(Collectors.toList());
+                    procedureIds.add(-1);
                     //todo:找到用到当前工序的plan_procedure_total(计划指定工序总进度表) 更新 单价相关数据
                     List<PlanProcedureTotal> planProcedureTotals = planProcedureTotalService.list(new LambdaQueryWrapper<PlanProcedureTotal>().in(PlanProcedureTotal::getProdProcedureId, procedureIds));
                     if(planProcedureTotals.size()>0){
                         List<Integer> planIds = planProcedureTotals.stream().map(PlanProcedureTotal::getPlanId).distinct().collect(Collectors.toList());
                         List<Plan> planList = planService.list(new LambdaQueryWrapper<Plan>().in(Plan::getId, planIds));
                         List<Integer> totalIds = planProcedureTotals.stream().map(PlanProcedureTotal::getId).distinct().collect(Collectors.toList());
+                        totalIds.add(-1);
                         List<ProdProcedureTeam> allProdProcedureTeams = prodProcedureTeamService.list(new LambdaQueryWrapper<ProdProcedureTeam>().in(ProdProcedureTeam::getPlanProcedureId,totalIds));
                         List<Integer> teamIdList = allProdProcedureTeams.stream().map(ProdProcedureTeam::getId).distinct().collect(Collectors.toList());
+                        teamIdList.add(-1);
                         List<Report> allReports = reportService.list(new LambdaQueryWrapper<Report>().select(Report::getId,Report::getUserProcedureTeamId, Report::getProdProcedureId,Report::getFinishNum).in(Report::getUserProcedureTeamId, teamIdList));
                         List<ProdProcedureTeam> needUpdateTeamList=new ArrayList<>();
                         List<Report> needUpdateReportList=new ArrayList<>();
                         for (PlanProcedureTotal planProcedureTotal : planProcedureTotals) {
-                            Optional<ProdProcedure> first = updateList.stream().filter(u -> u.getId().equals(planProcedureTotal.getId())).findFirst();
+                            Optional<ProdProcedure> first = updateList.stream().filter(u -> u.getId().equals(planProcedureTotal.getProdProcedureId())).findFirst();
                             if(first.isPresent()){
                                 Optional<Plan> plan = planList.stream().filter(p -> p.getId().equals(planProcedureTotal.getPlanId())).findFirst();
                                 if(plan.isPresent()){

+ 6 - 0
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/ProductServiceImpl.java

@@ -269,6 +269,9 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
                 if(row==null){
                     continue;
                 }
+                if (ExcelUtil.isRowEmpty(row)) {
+                    continue;
+                }
 
                 //产品基本信息
                 XSSFCell nameCell = row.getCell(0);
@@ -380,6 +383,9 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
                 if(row==null){
                     continue;
                 }
+                if (ExcelUtil.isRowEmpty(row)) {
+                    continue;
+                }
 
                 //工序信息
                 XSSFCell productNameCell = row.getCell(0);

+ 227 - 68
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -277,7 +277,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         }
         planProcedureTotal.setTotalFillTime(workingTime);
         BigDecimal bigDecimal = new BigDecimal(workingTime);
-        bigDecimal=bigDecimal.divide(new BigDecimal(planProcedureTotal.getTotalWorkingHours()));
+        bigDecimal=bigDecimal.divide(new BigDecimal(planProcedureTotal.getTotalWorkingHours()),2,RoundingMode.HALF_UP);
         bigDecimal=bigDecimal.multiply(new BigDecimal(100)).setScale(0,RoundingMode.HALF_UP);
         planProcedureTotal.setTotalProgress(bigDecimal.intValue());
 //            planProcedureTotal.setTotalProgress((int)((workingTime / planProcedureTotal.getTotalWorkingHours()) * 100));
@@ -4046,7 +4046,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
 //    }
 
     @Override
-    public HttpRespMsg getPersonWorkHoursWagesList(Integer deptId, String userId, String startDate, String endDate, Integer pageIndex, Integer pageSize) {
+    public HttpRespMsg getPersonWorkHoursWagesList(String deptIds, String userId, String startDate, String endDate, Integer pageIndex, Integer pageSize) {
         HttpRespMsg httpRespMsg=new HttpRespMsg();
         HashMap resultMap=new HashMap();
         DateTimeFormatter dtf=DateTimeFormatter.ofPattern("yyyy-MM-dd");
@@ -4063,16 +4063,19 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         boolean canViewAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全部人员工时工价");
         QueryWrapper<User> queryWrapper=new QueryWrapper();
         queryWrapper.eq("company_id",companyId);
-        List<Integer> deptIds=new ArrayList<>();
-        if(deptId!=null){
-            deptIds = getBranchDepartment(Integer.valueOf(deptId), departmentList);
-            deptIds.add(Integer.valueOf(deptId));
-            queryWrapper.in("department_id",deptIds);
+        List<Integer> deptIdList=new ArrayList<>();
+        if(deptIds!=null&&!StringUtils.isEmpty(deptIds)){
+            String[] split = deptIds.split(",");
+            for (String deptId : split) {
+                List<Integer> branchDepartment = getBranchDepartment(Integer.valueOf(deptId), departmentList);
+                deptIdList.addAll(branchDepartment);
+            }
+            queryWrapper.in("department_id",deptIdList);
         }
         if(!StringUtils.isEmpty(userId)){
             queryWrapper.eq("id",userId);
         }
-        List<Map<String,Object>> personWorkHoursWagesList=reportMapper.getPersonWorkHoursWagesList(companyId,startDate,endDate,deptIds,userId);
+        List<Map<String,Object>> personWorkHoursWagesList=reportMapper.getPersonWorkHoursWagesList(companyId,startDate,endDate,deptIdList,userId);
         if(!canViewAll){
             /*作为工长看到的数据*/
             List<Plan> plans = planMapper.selectList(new QueryWrapper<Plan>().eq("foreman_id", user.getId()));
@@ -4109,16 +4112,126 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         }
 //        totalUser.setPersonWorkHoursWages(totalList);
         personWorkHoursWagesList.addAll(totalList);
-        userList.forEach(u->{
+        //日期范围内所有分配数据
+        List<ProdProcedureTeam> allProcedureTeamList = prodProcedureTeamMapper.selectList(new LambdaQueryWrapper<ProdProcedureTeam>().between(ProdProcedureTeam::getDistributeDate, startDate, endDate));
+        //日期范围内所有派工数据
+        List<Integer> ids = allProcedureTeamList.stream().map(ProdProcedureTeam::getPlanProcedureId).distinct().collect(Collectors.toList());
+        List<PlanProcedureTotal> planProcedureTotalList = planProcedureTotalMapper.selectList(new LambdaQueryWrapper<PlanProcedureTotal>().in(PlanProcedureTotal::getId, ids));
+        for (User u : userList) {
             List<Map<String, Object>> mapList = personWorkHoursWagesList.stream().filter(pl -> String.valueOf(pl.get("userId")).equals(u.getId())).collect(Collectors.toList());
+            for (String date : dataStringList) {
+                List<ProdProcedureTeam> targetTeams = allProcedureTeamList.stream().filter(a -> a.getDistributeDate().format(dtf1).equals(date) && u.getId().equals(a.getUserId())).collect(Collectors.toList());
+                //找到当前人员分组的
+                Optional<Map<String, Object>> createDateValue = mapList.stream().filter(m -> String.valueOf(m.get("crateDate")).equals(date)).findFirst();
+                if (createDateValue.isPresent()) {
+                    Map<String, Object> map = createDateValue.get();
+                    if (targetTeams.size() > 0) {
+                        //计算本人被分配数据
+                        double workTime = targetTeams.stream().mapToDouble(ProdProcedureTeam::getWorkTime).sum();
+                        double cost = targetTeams.stream().mapToDouble(i -> i.getJobOfMoney().doubleValue()).sum();
+                        map.put("planCost", String.format("%.2f", cost));
+                        map.put("planWorkTime", String.format("%.2f", workTime));
+                        List<Integer> totalIds = targetTeams.stream().map(ProdProcedureTeam::getPlanProcedureId).distinct().collect(Collectors.toList());
+                        //获取与本人分配相关的所有派工数据
+                        List<PlanProcedureTotal> targetPlanTotals = planProcedureTotalList.stream().filter(p -> totalIds.contains(p.getId())).collect(Collectors.toList());
+                        BigDecimal lastWorkTime = new BigDecimal(0);
+                        BigDecimal lastCost = new BigDecimal(0);
+                        for (PlanProcedureTotal targetPlanTotal : targetPlanTotals) {
+                            //不同的分配数据对应派工数据不同 需要分开计算
+                            //分别计算每个派工单的已填报和总预算
+                            List<ProdProcedureTeam> teamList = allProcedureTeamList.stream().filter(a -> targetPlanTotal.getId().equals(a.getPlanProcedureId())).collect(Collectors.toList());
+                            List<String> teamIds = teamList.stream().map(ProdProcedureTeam::getUserId).distinct().collect(Collectors.toList());
+                            //获当前分配日期下的所分配人员工时成本总和
+                            double totalWorkingHours = targetPlanTotal.getTotalWorkingHours();
+                            double totalWages = targetPlanTotal.getTotalWages();
+                            //获当前分配日期下的所填报人员工时成本总和
+                            double workTimeSum = targetPlanTotal.getTotalFillTime();
+                            BigDecimal decimal = new BigDecimal(targetPlanTotal.getTotalProgress());
+                            decimal = decimal.divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
+                            BigDecimal costSum = new BigDecimal(targetPlanTotal.getTotalWages());
+                            costSum = costSum.multiply(decimal).setScale(1, RoundingMode.HALF_UP);
+
+                            BigDecimal decimalCost = new BigDecimal(totalWages);
+                            decimalCost = decimalCost.subtract(costSum).setScale(1, RoundingMode.HALF_UP);
+                            BigDecimal decimalWorkTime = new BigDecimal(totalWorkingHours);
+                            decimalWorkTime = decimalWorkTime.subtract(new BigDecimal(workTimeSum)).setScale(1, RoundingMode.HALF_UP);
+                            //根据分配人数重新计算平均值
+                            decimalCost = decimalCost.divide(new BigDecimal(teamIds.size()), 1, RoundingMode.HALF_UP);
+                            decimalWorkTime = decimalWorkTime.divide(new BigDecimal(teamIds.size()), 1, RoundingMode.HALF_UP);
+                            lastWorkTime=lastWorkTime.add(decimalWorkTime);
+                            lastCost=lastCost.add(decimalCost);
+                        }
+                        if (lastWorkTime.doubleValue() >0 && lastCost.doubleValue() > 0) {
+                            map.put("surplusCost", lastCost.doubleValue());
+                            map.put("surplusTime", lastWorkTime.doubleValue());
+                        }
+                    }
+                } else {
+                    Map map = new HashMap();
+                    map.put("crateDate", date);
+                    map.put("cost", 0);
+                    map.put("workTime", 0);
+                    map.put("departmentName", u.getDepartmentName());
+                    if (targetTeams.size() > 0) {
+                        double workTime = targetTeams.stream().mapToDouble(ProdProcedureTeam::getWorkTime).sum();
+                        double cost = targetTeams.stream().mapToDouble(i -> i.getJobOfMoney().doubleValue()).sum();
+                        map.put("planCost", String.format("%.2f", cost));
+                        map.put("planWorkTime", String.format("%.2f", workTime));
+                        List<Integer> totalIds = targetTeams.stream().map(ProdProcedureTeam::getPlanProcedureId).distinct().collect(Collectors.toList());
+                        //获取与本人分配相关的所有派工数据
+                        List<PlanProcedureTotal> targetPlanTotals = planProcedureTotalList.stream().filter(p -> totalIds.contains(p.getId())).collect(Collectors.toList());
+                        BigDecimal lastWorkTime = new BigDecimal(0);
+                        BigDecimal lastCost = new BigDecimal(0);
+                        for (PlanProcedureTotal targetPlanTotal : targetPlanTotals) {
+                            //不同的分配数据对应派工数据不同 需要分开计算
+                            //分别计算每个派工单的已填报和总预算
+                            List<ProdProcedureTeam> teamList = allProcedureTeamList.stream().filter(a -> targetPlanTotal.getId().equals(a.getPlanProcedureId())).collect(Collectors.toList());
+                            List<String> teamIds = teamList.stream().map(ProdProcedureTeam::getUserId).distinct().collect(Collectors.toList());
+                            //获当前分配日期下的所分配人员工时成本总和
+                            double totalWorkingHours = targetPlanTotal.getTotalWorkingHours();
+                            double totalWages = targetPlanTotal.getTotalWages();
+                            //获当前分配日期下的所填报人员工时成本总和
+                            double workTimeSum = targetPlanTotal.getTotalFillTime();
+                            BigDecimal decimal = new BigDecimal(targetPlanTotal.getTotalProgress());
+                            decimal = decimal.divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
+                            BigDecimal costSum = new BigDecimal(targetPlanTotal.getTotalWages());
+                            costSum = costSum.multiply(decimal).setScale(1, RoundingMode.HALF_UP);
+
+                            BigDecimal decimalCost = new BigDecimal(totalWages);
+                            decimalCost = decimalCost.subtract(costSum).setScale(1, RoundingMode.HALF_UP);
+                            BigDecimal decimalWorkTime = new BigDecimal(totalWorkingHours);
+                            decimalWorkTime = decimalWorkTime.subtract(new BigDecimal(workTimeSum)).setScale(1, RoundingMode.HALF_UP);
+                            //根据分配人数重新计算平均值
+                            decimalCost = decimalCost.divide(new BigDecimal(teamIds.size()), 1, RoundingMode.HALF_UP);
+                            decimalWorkTime = decimalWorkTime.divide(new BigDecimal(teamIds.size()), 1, RoundingMode.HALF_UP);
+                            lastWorkTime=lastWorkTime.add(decimalWorkTime);
+                            lastCost=lastCost.add(decimalCost);
+                        }
+                        if (lastWorkTime.doubleValue() >0 && lastCost.doubleValue() > 0) {
+                            map.put("surplusCost", lastCost.doubleValue());
+                            map.put("surplusTime", lastWorkTime.doubleValue());
+                        }
+                    }
+                    map.put("userId", u.getId());
+                    map.put("userName", u.getName());
+                    mapList.add(map);
+                }
+            }
             u.setPersonWorkHoursWages(mapList);
-            u.setDepartmentCascade(u.getId().equals("0")?"小计":convertDepartmentIdToCascade(u.getDepartmentId(),departmentList));
+            u.setDepartmentCascade(u.getId().equals("0") ? "小计" : convertDepartmentIdToCascade(u.getDepartmentId(), departmentList));
             double workTime = mapList.stream().mapToDouble(mt -> Double.valueOf(String.valueOf(mt.get("workTime")))).sum();
-            BigDecimal bigDecimal=new BigDecimal(workTime);
-//            bigDecimal=bigDecimal.multiply(new BigDecimal(60)).setScale(2, BigDecimal.ROUND_HALF_UP);
-             double cost = mapList.stream().mapToDouble(mt -> Double.valueOf(String.valueOf(mt.get("cost")))).sum();
-            u.setTotalResult(String.valueOf(bigDecimal.doubleValue())+"分钟 "+String.format("%.2f",cost)+"元");
-        });
+            BigDecimal bigDecimal = new BigDecimal(workTime);
+            double cost = mapList.stream().mapToDouble(mt -> Double.valueOf(String.valueOf(mt.get("cost")))).sum();
+            double planWorkTime = mapList.stream().filter(mt -> mt.get("planWorkTime") != null).mapToDouble(mt -> Double.valueOf(String.valueOf(mt.get("planWorkTime")))).sum();
+            BigDecimal planBigDecimal = new BigDecimal(planWorkTime);
+            double planCost = mapList.stream().filter(mt -> mt.get("planCost") != null).mapToDouble(mt -> Double.valueOf(String.valueOf(mt.get("planCost")))).sum();
+            double surplusWorkTime = mapList.stream().filter(mt -> mt.get("surplusTime") != null).mapToDouble(mt -> Double.valueOf(String.valueOf(mt.get("surplusTime")))).sum();
+            BigDecimal surplusBigDecimal = new BigDecimal(surplusWorkTime);
+            double surplusCost = mapList.stream().filter(mt -> mt.get("surplusCost") != null).mapToDouble(mt -> Double.valueOf(String.valueOf(mt.get("surplusCost")))).sum();
+            u.setTotalResult(String.valueOf(bigDecimal.doubleValue()) + "分钟 " + String.format("%.2f", cost) + "元");
+            u.setTotalPlanResult(String.valueOf(planBigDecimal.doubleValue()) + "分钟 " + String.format("%.2f", planCost) + "元");
+            u.setTotalSurplusResult(String.valueOf(surplusBigDecimal.doubleValue()) + "分钟 " + String.format("%.2f", surplusCost) + "元");
+        }
         resultMap.put("total",userIPage.getTotal());
         resultMap.put("records",userList);
         httpRespMsg.setData(resultMap);
@@ -4271,8 +4384,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     }
 
     @Override
-    public HttpRespMsg exportPersonWorkHoursWorkTime(Integer deptId, String userId, String startDate, String endDate) {
-        HttpRespMsg respMsg = getPersonWorkHoursWagesList(deptId, userId, startDate, endDate, -1, -1);
+    public HttpRespMsg exportPersonWorkHoursWorkTime(String deptIds, String userId, String startDate, String endDate) {
+        HttpRespMsg respMsg = getPersonWorkHoursWagesList(deptIds, userId, startDate, endDate, -1, -1);
         Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
         HashMap resultMap= (HashMap) respMsg.data;
         List<User> mapList= (List<User>) resultMap.get("records");
@@ -4437,24 +4550,33 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     }
 
     @Override
-    public HttpRespMsg getProcedureRealTimeProgressList(String deptId, String userId, String startDate, String endDate, Integer pageIndex, Integer pageSize) {
+    public HttpRespMsg getProcedureRealTimeProgressList(String deptIds, String userId, String startDate, String endDate, Integer pageIndex, Integer pageSize) {
         HttpRespMsg httpRespMsg=new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("token"));
+        List<Department> departmentList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, user.getCompanyId()));
         boolean canViewAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全部工序实时进度");
         Integer pageStart = null;
         if (pageIndex!=null){
             pageStart = (pageIndex -1) * pageSize;
         }
         Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        List<Integer> deptIdList=new ArrayList<>();
+        if(!StringUtils.isEmpty(deptIds)){
+            String[] split = deptIds.split(",");
+            for (String deptId : split) {
+                List<Integer> branchDepartment = getBranchDepartment(Integer.valueOf(deptId), departmentList);
+                deptIdList.addAll(branchDepartment);
+            }
+        }
         HashMap map=new HashMap();
         List<Map<String, Object>> planRealTimeProgressList;
         Integer total;
         if(!canViewAll){
-            planRealTimeProgressList = reportMapper.getProcedureRealTimeProgressList(companyId, deptId,user.getId(), userId, startDate, endDate, pageStart, pageSize);
-            total=reportMapper.getProcedureRealTimeProgressCount(companyId, deptId,user.getId(), userId, startDate, endDate);
+            planRealTimeProgressList = reportMapper.getProcedureRealTimeProgressList(companyId, deptIdList,user.getId(), userId, startDate, endDate, pageStart, pageSize);
+            total=reportMapper.getProcedureRealTimeProgressCount(companyId, deptIdList,user.getId(), userId, startDate, endDate);
         }else {
-            planRealTimeProgressList = reportMapper.getProcedureRealTimeProgressList(companyId, deptId,null, userId, startDate, endDate, pageStart, pageSize);
-            total=reportMapper.getProcedureRealTimeProgressCount(companyId, deptId,null, userId, startDate, endDate);
+            planRealTimeProgressList = reportMapper.getProcedureRealTimeProgressList(companyId, deptIdList,null, userId, startDate, endDate, pageStart, pageSize);
+            total=reportMapper.getProcedureRealTimeProgressCount(companyId, deptIdList,null, userId, startDate, endDate);
         }
 
 
@@ -4465,9 +4587,9 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     }
 
     @Override
-    public HttpRespMsg exportProcedureRealTimeProgressList(String deptId, String userId, String startDate, String endDate) {
+    public HttpRespMsg exportProcedureRealTimeProgressList(String deptIds, String userId, String startDate, String endDate) {
         HttpRespMsg msg=new HttpRespMsg();
-        HttpRespMsg respMsg = getProcedureRealTimeProgressList(deptId, userId, startDate, endDate, null, null);
+        HttpRespMsg respMsg = getProcedureRealTimeProgressList(deptIds, userId, startDate, endDate, null, null);
         Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
         HashMap resultMap= (HashMap) respMsg.data;
         List<Map<String, Object>> mapList= (List<Map<String, Object>>) resultMap.get("records");
@@ -4498,7 +4620,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     }
 
     @Override
-    public HttpRespMsg workReportQuery(Integer productId, String vehicleNum, String steelNum, Integer deptId, String userId, String startDate, String endDate,Integer pageIndex,Integer pageSize) {
+    public HttpRespMsg workReportQuery(Integer productId, String vehicleNum, String steelNum, String deptIds, String userId, String startDate, String endDate,Integer pageIndex,Integer pageSize) {
         HttpRespMsg msg=new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("token"));
         boolean canViewAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全部报工");
@@ -4507,15 +4629,24 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             pageStart = (pageIndex -1) * pageSize;
         }
         Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        List<Department> departmentList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, companyId));
+        List<Integer> deptIdList=new ArrayList<>();
+        if(!StringUtils.isEmpty(deptIds)){
+            String[] split = deptIds.split(",");
+            for (String deptId : split) {
+                List<Integer> branchDepartment = getBranchDepartment(Integer.valueOf(deptId), departmentList);
+                deptIdList.addAll(branchDepartment);
+            }
+        }
         Map map=new HashMap();
         List<Map<String,Object>> mapList;
         Integer total;
         if(!canViewAll){
-            mapList=reportMapper.workReportQuery(companyId,productId,vehicleNum,steelNum,deptId,user.getId(),userId,startDate,endDate,pageStart,pageSize);
-            total = reportMapper.selectCountForWorkQuery(companyId, productId, vehicleNum, steelNum, deptId,user.getId(), userId, startDate, endDate);
+            mapList=reportMapper.workReportQuery(companyId,productId,vehicleNum,steelNum,deptIdList,user.getId(),userId,startDate,endDate,pageStart,pageSize);
+            total = reportMapper.selectCountForWorkQuery(companyId, productId, vehicleNum, steelNum, deptIdList,user.getId(), userId, startDate, endDate);
         }else {
-            mapList=reportMapper.workReportQuery(companyId,productId,vehicleNum,steelNum,deptId,null,userId,startDate,endDate,pageStart,pageSize);
-            total = reportMapper.selectCountForWorkQuery(companyId, productId, vehicleNum, steelNum, deptId,null, userId, startDate, endDate);
+            mapList=reportMapper.workReportQuery(companyId,productId,vehicleNum,steelNum,deptIdList,null,userId,startDate,endDate,pageStart,pageSize);
+            total = reportMapper.selectCountForWorkQuery(companyId, productId, vehicleNum, steelNum, deptIdList,null, userId, startDate, endDate);
         }
 
         map.put("records",mapList);
@@ -4525,9 +4656,9 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     }
 
     @Override
-    public HttpRespMsg exportWorkReportQuery(Integer productId, String vehicleNum, String steelNum, Integer deptId, String userId, String startDate, String endDate) {
+    public HttpRespMsg exportWorkReportQuery(Integer productId, String vehicleNum, String steelNum, String deptIds, String userId, String startDate, String endDate) {
         HttpRespMsg msg=new HttpRespMsg();
-        HttpRespMsg respMsg = workReportQuery(productId, vehicleNum, steelNum, deptId, userId, startDate,endDate,null,null);
+        HttpRespMsg respMsg = workReportQuery(productId, vehicleNum, steelNum, deptIds, userId, startDate,endDate,null,null);
         Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
         HashMap resultMap= (HashMap) respMsg.data;
         List<Map<String, Object>> mapList= (List<Map<String, Object>>) resultMap.get("records");
@@ -4564,7 +4695,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     }
 
     @Override
-    public HttpRespMsg getPlanRealTimeProgressList(String deptId, String userId, String startDate, String endDate, Integer pageIndex, Integer pageSize) {
+    public HttpRespMsg getPlanRealTimeProgressList(String deptIds, String userId, String startDate, String endDate, Integer pageIndex, Integer pageSize) {
         HttpRespMsg httpRespMsg=new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("token"));
         boolean canViewAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全部计划实时进度");
@@ -4575,15 +4706,24 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             pageStart = (pageIndex -1) * pageSize;
         }
         Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        List<Department> departmentList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, companyId));
+        List<Integer> deptIdList=new ArrayList<>();
+        if(!StringUtils.isEmpty(deptIds)){
+            String[] split = deptIds.split(",");
+            for (String deptId : split) {
+                List<Integer> branchDepartment = getBranchDepartment(Integer.valueOf(deptId), departmentList);
+                deptIdList.addAll(branchDepartment);
+            }
+        }
         List<Map<String, Object>> planRealTimeProgressList;
         Integer total;
         HashMap map=new HashMap();
         if(!canViewAll){
-            planRealTimeProgressList = reportMapper.getPlanRealTimeProgressList(companyId, deptId,user.getId(), userId, startDate, endDate, pageStart, pageSize,null);
-            total=reportMapper.getPlanRealTimeProgressCount(companyId, deptId,user.getId(), userId, startDate, endDate);
+            planRealTimeProgressList = reportMapper.getPlanRealTimeProgressList(companyId, deptIdList,user.getId(), userId, startDate, endDate, pageStart, pageSize,null);
+            total=reportMapper.getPlanRealTimeProgressCount(companyId, deptIdList,user.getId(), userId, startDate, endDate);
         }else {
-            planRealTimeProgressList = reportMapper.getPlanRealTimeProgressList(companyId, deptId,null, userId, startDate, endDate, pageStart, pageSize,null);
-            total=reportMapper.getPlanRealTimeProgressCount(companyId, deptId,null, userId, startDate, endDate);
+            planRealTimeProgressList = reportMapper.getPlanRealTimeProgressList(companyId, deptIdList,null, userId, startDate, endDate, pageStart, pageSize,null);
+            total=reportMapper.getPlanRealTimeProgressCount(companyId, deptIdList,null, userId, startDate, endDate);
         }
         planRealTimeProgressList.forEach(pt->{
             BigDecimal planWorkTime = new BigDecimal(pt.get("planWorkTime") == null ? 0 : Double.valueOf(String.valueOf(pt.get("planWorkTime"))));
@@ -4601,9 +4741,9 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     }
 
     @Override
-    public HttpRespMsg exportPlanRealTimeProgressList(String deptId, String userId, String startDate, String endDate) {
+    public HttpRespMsg exportPlanRealTimeProgressList(String deptIds, String userId, String startDate, String endDate) {
         HttpRespMsg msg=new HttpRespMsg();
-        HttpRespMsg respMsg = getPlanRealTimeProgressList(deptId, userId, startDate, endDate, null, null);
+        HttpRespMsg respMsg = getPlanRealTimeProgressList(deptIds, userId, startDate, endDate, null, null);
         Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
         HashMap resultMap= (HashMap) respMsg.data;
         List<Map<String, Object>> mapList= (List<Map<String, Object>>) resultMap.get("records");
@@ -4642,7 +4782,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     }
 
     @Override
-    public HttpRespMsg getDpetStatisticsProgressList(String deptId, String userId, String startDate, String endDate, Integer pageIndex, Integer pageSize) {
+    public HttpRespMsg getDpetStatisticsProgressList(String deptIds, String userId, String startDate, String endDate, Integer pageIndex, Integer pageSize) {
         HttpRespMsg httpRespMsg=new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("token"));
         boolean canViewAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全部部门生产统计");
@@ -4654,15 +4794,23 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         }
         Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
         List<Department> departmentList = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id", companyId));
+        List<Integer> deptIdList=new ArrayList<>();
+        if(!StringUtils.isEmpty(deptIds)){
+            String[] split = deptIds.split(",");
+            for (String deptId : split) {
+                List<Integer> branchDepartment = getBranchDepartment(Integer.valueOf(deptId), departmentList);
+                deptIdList.addAll(branchDepartment);
+            }
+        }
         HashMap map=new HashMap();
         List<Map<String, Object>> dpetStatisticsProgressList;
         Integer total;
         if(!canViewAll){
-            dpetStatisticsProgressList = reportMapper.getDpetStatisticsProgressList(companyId, deptId,user.getId(), userId, startDate, endDate, pageStart, pageSize);
-            total=reportMapper.getDpetStatisticsProgressCount(companyId, deptId,user.getId(), userId, startDate, endDate);
+            dpetStatisticsProgressList = reportMapper.getDpetStatisticsProgressList(companyId, deptIdList,user.getId(), userId, startDate, endDate, pageStart, pageSize);
+            total=reportMapper.getDpetStatisticsProgressCount(companyId, deptIdList,user.getId(), userId, startDate, endDate);
         }else {
-            dpetStatisticsProgressList = reportMapper.getDpetStatisticsProgressList(companyId, deptId,null, userId, startDate, endDate, pageStart, pageSize);
-            total=reportMapper.getDpetStatisticsProgressCount(companyId, deptId,null, userId, startDate, endDate);
+            dpetStatisticsProgressList = reportMapper.getDpetStatisticsProgressList(companyId, deptIdList,null, userId, startDate, endDate, pageStart, pageSize);
+            total=reportMapper.getDpetStatisticsProgressCount(companyId, deptIdList,null, userId, startDate, endDate);
         }
         dpetStatisticsProgressList.forEach(pt->{
             BigDecimal planWorkTime = new BigDecimal(pt.get("planWorkTime") == null ? 0 : Double.valueOf(String.valueOf(pt.get("planWorkTime"))));
@@ -4682,9 +4830,9 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     }
 
     @Override
-    public HttpRespMsg exportDpetStatisticsProgressList(String deptId, String userId, String startDate, String endDate) {
+    public HttpRespMsg exportDpetStatisticsProgressList(String deptIds, String userId, String startDate, String endDate) {
         HttpRespMsg msg=new HttpRespMsg();
-        HttpRespMsg respMsg = getDpetStatisticsProgressList(deptId, userId, startDate, endDate, null, null);
+        HttpRespMsg respMsg = getDpetStatisticsProgressList(deptIds, userId, startDate, endDate, null, null);
         Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
         HashMap resultMap= (HashMap) respMsg.data;
         List<Map<String, Object>> mapList= (List<Map<String, Object>>) resultMap.get("records");
@@ -4716,12 +4864,14 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         List<Map<String,Object>> reportList=reportMapper.getReportList(startDate,endDate,planId,stateKey,departmentId,companyId);
         List<List<String>> dataList=new ArrayList<>();
 //        String[] title={"员工","工号","所属部门","排除工单号/任务变更通知号","钢印号","工作时长","产品名称","工序名称","进度","质检类型","质检人","工作日期","填报日期"};
-        String[] title={"所属部门","工号","员工","排除工单号/任务变更通知号","钢印号","产品名称","工序名称","进度","工作件数", "工作时长","单价","工价","汇总",
-                "工作日期","填报日期","质检类型","质检人"};
+//        String[] title={"所属部门","工号","员工","排除工单号/任务变更通知号","钢印号","产品名称","工序名称","进度","工作件数", "工作时长","单价","工价","汇总",
+//                "工作日期","填报日期","质检类型","质检人"};
+        String[] title={"工位名称","项目名称","包名称","生产订单号","工序名称","零件编码","零件名称","零件图号","生产数量", "工时","单价","合计",
+                "作业人员","日期"};
         List<String> titleList=Arrays.asList(title);
         dataList.add(titleList);
 
-        int sumCostIndex = 12;
+        int sumCostIndex = 11;
         List<String> sumLine = null;
         String lastJobNum = null;
         for (Map<String, Object> map : reportList) {
@@ -4729,27 +4879,34 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             String departmentName = convertDepartmentIdToCascade(Integer.valueOf(String.valueOf(map.get("departmentId"))), departmentList);
             item.add(departmentName);
             String curJobBNum = String.valueOf(map.get("jobNumber"));
-            item.add(curJobBNum);
-            item.add(String.valueOf(map.get("userName")));
-            Integer planType = Integer.valueOf(String.valueOf(map.get("planType")));
-            if(planType==0){
-                item.add(map.get("productSchedulingNum")==null?"":String.valueOf(map.get("productSchedulingNum")));
-            }else {
-                item.add(map.get("taskChangeNoticeNum")==null?"":String.valueOf(map.get("taskChangeNoticeNum")));
-            }
-            item.add(map.get("steelNumArray")==null?"":String.valueOf(map.get("steelNumArray")));
-            item.add(String.valueOf(map.get("productName")));
+//            item.add(curJobBNum);
+//            item.add(String.valueOf(map.get("userName")));
+//            Integer planType = Integer.valueOf(String.valueOf(map.get("planType")));
+//            if(planType==0){
+//                item.add(map.get("productSchedulingNum")==null?"":String.valueOf(map.get("productSchedulingNum")));
+//            }else {
+//                item.add(map.get("taskChangeNoticeNum")==null?"":String.valueOf(map.get("taskChangeNoticeNum")));
+//            }
+//            item.add(map.get("steelNumArray")==null?"":String.valueOf(map.get("steelNumArray")));
+            item.add(map.get("projectName")==null?"":String.valueOf(map.get("projectName")));
+//            item.add(String.valueOf(map.get("productName")));
+            item.add("");
+            item.add(map.get("productOrderNum")==null?"":String.valueOf(map.get("productOrderNum")));
             item.add(String.valueOf(map.get("procedureName")));
-            item.add(String.valueOf(map.get("progress"))+"%");
+            item.add("");
+            item.add("");
+            item.add("");
+//            item.add(String.valueOf(map.get("progress"))+"%");
             item.add(String.valueOf(map.get("finishNum")));
             item.add(String.valueOf(map.get("workingTime")));
             item.add(String.valueOf(map.get("unitPrice")));
             String cost = String.valueOf(map.get("cost"));
-            item.add(cost);
+//            item.add(cost);
+            item.add(String.valueOf(map.get("userName")));
             item.add(String.valueOf(map.get("createDate")));
-            item.add(String.valueOf(map.get("reportTime")));
-            item.add(String.valueOf(map.get("checkType")));
-            item.add(map.get("checkerName")==null?"":String.valueOf(map.get("checkerName")));
+//            item.add(String.valueOf(map.get("reportTime")));
+//            item.add(String.valueOf(map.get("checkType")));
+//            item.add(map.get("checkerName")==null?"":String.valueOf(map.get("checkerName")));
             dataList.add(item);
             if (lastJobNum == null || !lastJobNum.equals(curJobBNum)) {
                 //换新的人了
@@ -5303,7 +5460,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     }
 
 	@Override
-    public HttpRespMsg getPlanDataWithStation(Integer isFilterDept,Integer filterDeptId,Integer stationId, String startDate, String endDate, Integer pageIndex, Integer pageSize) {
+    public HttpRespMsg getPlanDataWithStation(Integer isFilterDept,Integer filterDeptId,String stationIds, String startDate, String endDate, Integer pageIndex, Integer pageSize) {
         HttpRespMsg msg=new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("token"));
         NumberFormat format = NumberFormat.getPercentInstance();
@@ -5579,8 +5736,10 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         }
         lastList=list;
 
-        if(stationId!=null){
-            lastList=lastList.stream().filter(l->Integer.valueOf(String.valueOf(l.get("deptId"))).equals(stationId)).collect(Collectors.toList());
+        if(stationIds!=null&&!StringUtils.isEmpty(stationIds)){
+            String[] split = stationIds.split(",");
+            List<Integer> collect = Arrays.asList(split).stream().map(i -> Integer.valueOf(i)).collect(Collectors.toList());
+            lastList=lastList.stream().filter(l->collect.contains(Integer.valueOf(String.valueOf(l.get("deptId"))))).collect(Collectors.toList());
         }
         //得到的数据再根据部门过滤一下
         if(pageSize!=null&&pageSize>lastList.size()){
@@ -5595,10 +5754,10 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     }
 
     @Override
-    public HttpRespMsg exportPlanDataWithStation(Integer isFilterDept, Integer filterDeptId, Integer stationId, String startDate, String endDate) {
+    public HttpRespMsg exportPlanDataWithStation(Integer isFilterDept, Integer filterDeptId, String stationIds, String startDate, String endDate) {
         HttpRespMsg msg=new HttpRespMsg();
         Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
-        HttpRespMsg data = getPlanDataWithStation(isFilterDept, filterDeptId, stationId, startDate, endDate, null, null);
+        HttpRespMsg data = getPlanDataWithStation(isFilterDept, filterDeptId, stationIds, startDate, endDate, null, null);
         Map<String, Object> objectMap = (Map<String, Object>) data.data;
         boolean isViewUser = (boolean) objectMap.get("isViewUser");
         List<Map<String, Object>> mapList = (List<Map<String, Object>>) objectMap.get("records");

+ 76 - 0
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java

@@ -76,6 +76,13 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
     public static final String GET_CORP_TOKEN = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRET";
 
 
+    //批量获取企业审批单号
+    public static final String BATCH_GET_APPROVAL_INFO = "https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovalinfo?access_token=ACCESS_TOKEN";
+
+    //获取审批申请详情
+    public static final String GET_APPROVAL_DETAIL = "https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovaldetail?access_token=ACCESS_TOKEN";
+
+
     public static final int TEXT_CARD_MSG_BUSTRIP_WAITING_AUDIT = 0;//出差待审核
     public static final int TEXT_CARD_MSG_BUSTRIP_AGREE = 1;//出差审核通过
     public static final int TEXT_CARD_MSG_BUSTRIP_DENY = 2;//出差审核驳回
@@ -1980,4 +1987,73 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
         return msg;
     }
 
+
+
+    /**
+     * 批量获取审批单号
+     * PS:Integer recordType 1-请假;2-打卡补卡;3-出差;4-外出;5-加班; 6- 调班;7-会议室预定;8-退款审批;9-红包报销审批
+     *    Integer sp_status 1-审批中;2-已通过;3-已驳回;4-已撤销;6-通过后撤销;7-已删除;10-已支付
+     * */
+    @Override
+    public JSONArray getApprovalInfo(Integer companyId, String startDate, String endDate, String newCursor, JSONArray filterArray) throws Exception {
+        DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        LocalDateTime startDateTime = LocalDate.parse(startDate, df).atTime(LocalTime.MIN);
+        LocalDateTime endDateTime = LocalDate.parse(endDate, df).atTime(LocalTime.MAX);
+        long startTime = startDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli() -
+                LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
+        long endTime = endDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli() -
+                LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
+        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id",companyId));
+        String url=BATCH_GET_APPROVAL_INFO.replace("ACCESS_TOKEN",getCorpAccessToken(wxCorpInfo));
+        HttpHeaders headers = new HttpHeaders();
+        RestTemplate restTemplate = new RestTemplate();
+        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
+        headers.setContentType(type);
+        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
+        JSONObject requestMap = new JSONObject();
+        requestMap.put("starttime",startTime);
+        requestMap.put("endtime",endTime);
+        requestMap.put("new_cursor",newCursor);
+        requestMap.put("size",100);
+        requestMap.put("filters",filterArray);
+        HttpEntity<JSONObject> entity = new HttpEntity<>(requestMap, headers);
+        ResponseEntity<String> ResponseEntity = restTemplate.postForEntity(url, entity, String.class);
+        if (ResponseEntity.getStatusCode() == HttpStatus.OK) {
+            JSONArray jsonArray=new JSONArray();
+            String resp = ResponseEntity.getBody();
+            JSONObject jsonObject = JSONObject.parseObject(resp);
+            JSONArray sp_no_list = jsonObject.getJSONArray("sp_no_list");
+            jsonArray.addAll(sp_no_list);
+            if(jsonObject.containsKey("new_next_cursor")){
+                String new_next_cursor = jsonObject.getString("new_next_cursor");
+                JSONArray approvalInfo = getApprovalInfo(companyId, startDate, endDate, new_next_cursor, filterArray);
+                jsonArray.addAll(approvalInfo);
+            }
+            return jsonArray;
+        }
+        return null;
+    }
+
+
+    @Override
+    public String getApprovalInfoDetail(Integer companyId,String spNo) throws Exception {
+        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id",companyId));
+        String url=GET_APPROVAL_DETAIL.replace("ACCESS_TOKEN",getCorpAccessToken(wxCorpInfo));
+        HttpHeaders headers = new HttpHeaders();
+        RestTemplate restTemplate = new RestTemplate();
+        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
+        headers.setContentType(type);
+        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
+        JSONObject requestMap = new JSONObject();
+        requestMap.put("sp_no",spNo);
+        HttpEntity<JSONObject> entity = new HttpEntity<>(requestMap, headers);
+        ResponseEntity<String> ResponseEntity = restTemplate.postForEntity(url, entity, String.class);
+        if (ResponseEntity.getStatusCode() == HttpStatus.OK) {
+            String resp = ResponseEntity.getBody();
+            return resp;
+        }
+        return null;
+    }
+
+
 }

+ 2 - 1
fhKeeper/formulahousekeeper/management-workshop/src/main/resources/mapper/ProdProcedureTeamMapper.xml

@@ -17,11 +17,12 @@
         <result column="status" property="status" />
         <result column="is_change" property="isChange" />
         <result column="steel_num_array" property="steelNumArray" />
+        <result column="distribute_date" property="distributeDate" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, company_id, user_id, work_time, job_of_money, progress, checker_id, checker_name, update_time, plan_procedure_id, status, is_change, steel_num_array
+        id, company_id, user_id, work_time, job_of_money, progress, checker_id, checker_name, update_time, plan_procedure_id, status, is_change, steel_num_array, distribute_date
     </sql>
 
     <select id="getReportForWorkList" resultType="java.util.HashMap" >

+ 43 - 19
fhKeeper/formulahousekeeper/management-workshop/src/main/resources/mapper/ReportMapper.xml

@@ -135,7 +135,7 @@
     </select>
 
     <select id="getPersonWorkHoursWagesList" resultType="java.util.Map">
-        select b.id as userId,c.department_name as departmentName,b.name as userName,DATE_FORMAT(a.create_date,'%Y%m%d') as crateDate,IFNULL(SUM(a.cost),0) as cost,IFNULL(SUM(a.working_time),0) as workTime
+        select b.id AS userId,c.department_name AS departmentName,b.name AS userName,DATE_FORMAT(a.create_date,'%Y%m%d') AS crateDate,IFNULL(SUM(a.cost),0) AS cost,IFNULL(SUM(a.working_time),0) AS workTime
         from report a
         left join user b on a.creator_id=b.id
         left join department c on c.department_id=b.department_id
@@ -167,7 +167,7 @@
         left join plan on plan.id=r.plan_id
         left join user u on r.checker_id=u.id
         left join user u2 on r.creator_id=u2.id
-        where r.company_id=#{companyId}
+        where r.company_id=#{companyId}  and r.finish_num &gt; 0
         <if test="date!=null and date!=''">
             and r.create_date=#{date}
         </if>
@@ -196,8 +196,11 @@
         <if test="userId!=null and userId!=''">
             and b.foreman_id=#{userId}
         </if>
-        <if test="deptId!=null and deptId!=''">
-            and b.station_id=#{deptId}
+        <if test="deptIds!=null and deptIds.size()>0">
+            and b.station_id in
+            <foreach collection="deptIds" item="item" close=")" open="(" separator=",">
+                #{item}
+            </foreach>
         </if>
         <if test="foremanId!=null and foremanId!=''">
             and b.foreman_id=#{foremanId}
@@ -222,8 +225,11 @@
         <if test="userId!=null and userId!=''">
             and  b.foreman_id=#{userId}
         </if>
-        <if test="deptId!=null and deptId!=''">
-            and b.station_id=#{deptId}
+        <if test="deptIds!=null and deptIds.size()>0">
+            and b.station_id in
+            <foreach collection="deptIds" item="item" close=")" open="(" separator=",">
+                #{item}
+            </foreach>
         </if>
         <if test="foremanId!=null and foremanId!=''">
             and b.foreman_id=#{foremanId}
@@ -251,8 +257,11 @@
             <if test="vehicleNum!=null and vehicleNum!=''">
                 and #{vehicleNum} between pn.vehicle_num_start and pn.vehicle_num_end
             </if>
-            <if test="deptId!=null and deptId!=''">
-                and pn.station_id=#{deptId}
+            <if test="deptIds!=null and deptIds.size()>0">
+                and pn.station_id in
+                <foreach collection="deptIds" item="item" close=")" open="(" separator=",">
+                    #{item}
+                </foreach>
             </if>
             <if test="foremanId!=null and foremanId!=''">
                 and pn.foreman_id=#{foremanId}
@@ -291,8 +300,11 @@
             <if test="vehicleNum!=null and vehicleNum!=''">
                 and #{vehicleNum} between pn.vehicle_num_start and pn.vehicle_num_end
             </if>
-            <if test="deptId!=null and deptId!=''">
-                and pn.station_id=#{deptId}
+            <if test="deptIds!=null and deptIds.size()>0">
+                and pn.station_id in
+                <foreach collection="deptIds" item="item" close=")" open="(" separator=",">
+                    #{item}
+                </foreach>
             </if>
             <if test="foremanId!=null and foremanId!=''">
                 and pn.foreman_id=#{foremanId}
@@ -326,8 +338,11 @@
         <if test="userId!=null and userId!=''">
             and b.foreman_id=#{userId}
         </if>
-        <if test="deptId!=null and deptId!=''">
-            and b.station_id=#{deptId}
+        <if test="deptIds!=null and deptIds.size()>0">
+            and b.station_id in
+            <foreach collection="deptIds" item="item" close=")" open="(" separator=",">
+                #{item}
+            </foreach>
         </if>
         <if test="foremanId!=null and foremanId!=''">
             and b.foreman_id=#{foremanId}
@@ -361,8 +376,11 @@
         <if test="userId!=null and userId!=''">
             and b.foreman_id=#{userId}
         </if>
-        <if test="deptId!=null and deptId!=''">
-            and b.station_id=#{deptId}
+        <if test="deptIds!=null and deptIds.size()>0">
+            and b.station_id in
+            <foreach collection="deptIds" item="item" close=")" open="(" separator=",">
+                #{item}
+            </foreach>
         </if>
         <if test="foremanId!=null and foremanId!=''">
             and b.foreman_id=#{foremanId}
@@ -386,8 +404,11 @@
         <if test="userId!=null and userId!=''">
             and d.user_id=#{userId}
         </if>
-        <if test="deptId!=null and deptId!=''">
-            and p.station_id=#{deptId}
+        <if test="deptIds!=null and deptIds.size()>0">
+            and p.station_id in
+            <foreach collection="deptIds" item="item" close=")" open="(" separator=",">
+                #{item}
+            </foreach>
         </if>
         <if test="foremanId!=null and foremanId!=''">
             and p.foreman_id=#{foremanId}
@@ -414,8 +435,11 @@
         <if test="userId!=null and userId!=''">
             and d.user_id=#{userId}
         </if>
-        <if test="deptId!=null and deptId!=''">
-            and p.station_id=#{deptId}
+        <if test="deptIds!=null and deptIds.size()>0">
+            and p.station_id in
+            <foreach collection="deptIds" item="item" close=")" open="(" separator=",">
+                #{item}
+            </foreach>
         </if>
         <if test="foremanId!=null and foremanId!=''">
             and p.foreman_id=#{foremanId}
@@ -427,7 +451,7 @@
         ) as total
     </select>
     <select id="getReportList" resultType="java.util.Map">
-        select p.plan_type as planType,u.name as userName,u.job_number as jobNumber,d.department_id as departmentId,p.product_scheduling_num as productSchedulingNum,
+        select p.project_name as projectName,p.product_order_num as productOrderNum, p.plan_type as planType,u.name as userName,u.job_number as jobNumber,d.department_id as departmentId,p.product_scheduling_num as productSchedulingNum,
         p.task_change_notice_num as taskChangeNoticeNum,r.steel_num_array as steelNumArray,r.working_time as workingTime,p.product_name as productName,r.finish_num as finishNum,
         pp.name as procedureName,r.progress as progress,(CASE r.check_type WHEN 0 THEN '自检' WHEN 1 THEN '互检' ELSE '专检' END ) as checkType ,uu.name as checkerName,
         date_format(r.create_date,'%Y-%m-%d') as createDate,date_format(r.create_time,'%Y-%m-%d %T') as reportTime, pp.unit_price as unitPrice,r.cost  from report r

BIN
fhKeeper/formulahousekeeper/management-workshop/src/main/resources/upload/今日计划导入模板.xlsx


BIN
fhKeeper/formulahousekeeper/management-workshop/src/main/resources/upload/插单计划导入模板.xlsx


BIN
fhKeeper/formulahousekeeper/management-workshop/src/main/resources/upload/明日计划导入模板.xlsx


+ 2 - 2
fhKeeper/formulahousekeeper/plugIn/form-design-master/.vscode/settings.json

@@ -2,8 +2,8 @@
   "prettier.enable": false,
   "typescript.tsdk": "node_modules/typescript/lib",
   "editor.codeActionsOnSave": {
-    "source.fixAll.eslint": true,
-    "source.fixAll.stylelint": true
+    "source.fixAll.eslint": "explicit",
+    "source.fixAll.stylelint": "explicit"
   },
   "files.associations": {
     "*.css": "postcss"

+ 26 - 0
fhKeeper/formulahousekeeper/plugIn/form-design-master/src/components.d.ts

@@ -6,6 +6,32 @@ declare module 'vue' {
   export interface GlobalComponents {
     CodeEditor: typeof import('./components/CodeEditor.vue')['default']
     ComponentGroup: typeof import('./components/ComponentGroup.vue')['default']
+    ElButton: typeof import('element-plus/es')['ElButton']
+    ElCascader: typeof import('element-plus/es')['ElCascader']
+    ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
+    ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
+    ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
+    ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
+    ElDialog: typeof import('element-plus/es')['ElDialog']
+    ElDivider: typeof import('element-plus/es')['ElDivider']
+    ElForm: typeof import('element-plus/es')['ElForm']
+    ElFormItem: typeof import('element-plus/es')['ElFormItem']
+    ElImage: typeof import('element-plus/es')['ElImage']
+    ElInput: typeof import('element-plus/es')['ElInput']
+    ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
+    ElOption: typeof import('element-plus/es')['ElOption']
+    ElRadio: typeof import('element-plus/es')['ElRadio']
+    ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
+    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
+    ElRate: typeof import('element-plus/es')['ElRate']
+    ElSelect: typeof import('element-plus/es')['ElSelect']
+    ElSlider: typeof import('element-plus/es')['ElSlider']
+    ElSpace: typeof import('element-plus/es')['ElSpace']
+    ElSwitch: typeof import('element-plus/es')['ElSwitch']
+    ElTable: typeof import('element-plus/es')['ElTable']
+    ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
+    ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
+    ElUpload: typeof import('element-plus/es')['ElUpload']
   }
 }
 

+ 1 - 0
fhKeeper/formulahousekeeper/plugIn/form-design-master/src/design/WidgetFormItem.vue

@@ -156,6 +156,7 @@ const handleDeleteClick = () => {
           :max="element.options.max"
           :min="element.options.min"
           :disabled="element.options.disabled"
+          controls-position="right"
         />
       </template>
 

+ 11 - 0
fhKeeper/formulahousekeeper/plugIn/form-design-master/src/generate/GenerateForm.vue

@@ -17,6 +17,8 @@
         :config="data.config"
         :disabled="disabled"
         :request="request"
+        :widgetFormData="widgetForm.list"
+        @updateWidgetForm="updateWidgetForm"
       />
     </template>
   </el-form>
@@ -122,6 +124,14 @@ export default defineComponent({
       })
     }
 
+    const updateWidgetForm = (list: any[]) => {
+      // console.log(list, '<=====')
+      const listIndex = state.widgetForm.list.findIndex((item: any) => item.type === 'grid')
+      state.widgetForm.list[listIndex].columns = list
+      // console.log(state.widgetForm.list);
+      state.model = {...state.model, contactsId: ''}
+    }
+
     watch(
       () => props.data,
       (val) => {
@@ -159,6 +169,7 @@ export default defineComponent({
       ...toRefs(state),
       getData,
       reset,
+      updateWidgetForm
     }
   },
 })

+ 50 - 3
fhKeeper/formulahousekeeper/plugIn/form-design-master/src/generate/GenerateFormItem.vue

@@ -18,6 +18,8 @@
         :element="colItem"
         :config="config"
         :disabled="disabled"
+        :widgetFormData="element.columns"
+        @updateWidgetForm="updateWidgetForm"
       />
     </div>
   </div>
@@ -53,7 +55,7 @@
   >
     <template v-if="element.type === 'input'">
       <el-input
-        v-model="data"
+        v-model.trim="data"
         :style="{ width: element.options.width }"
         :placeholder="element.options.placeholder"
         :maxlength="parseInt(element.options.maxlength)"
@@ -86,7 +88,7 @@
 
     <template v-if="element.type === 'password'">
       <el-input
-        v-model="data"
+        v-model.trim="data"
         :style="{ width: element.options.width }"
         :placeholder="element.options.placeholder"
         :maxlength="parseInt(element.options.maxlength)"
@@ -120,7 +122,7 @@
 
     <template v-if="element.type === 'textarea'">
       <el-input
-        v-model="data"
+        v-model.trim="data"
         type="textarea"
         resize="none"
         :rows="element.options.rows"
@@ -142,6 +144,7 @@
         :max="element.options.max"
         :min="element.options.min"
         :disabled="disabled || element.options.disabled"
+        controls-position="right"
       />
     </template>
 
@@ -235,6 +238,7 @@
         :filterable="element.options.filterable"
         :disabled="disabled || element.options.disabled"
         :style="{ width: element.options.width }"
+        @change="(value: any) => specializedHandleSelect(value, element)"
       >
         <el-option
           v-for="item of element.options.remote
@@ -345,6 +349,7 @@ const props = defineProps<{
   updatedModel: any
   disabled: boolean
   request?: Function
+  widgetFormData?: any
 }>()
 const originData = props.model[props.element.model]
 const data = computed({
@@ -381,6 +386,48 @@ async function download(defaultValue: string, label: string) {
   a.download = `${label}.${defaultValue.split('.')[1]}`
   a.click()
 }
+
+const emits = defineEmits(['updateWidgetForm'])
+const specializedHandleSelect = (val: any, element: any) => {
+  const field = element.model
+  if(field == 'customerId') {
+    // console.log(props, '<===== props')
+    let list = JSON.parse(JSON.stringify(props.widgetFormData))
+    for(var i in list) {
+      if(list[i].list[0].model == 'contactsId') {
+        let item = list[i].list[0]
+        const token: any = sessionStorage.getItem('token')
+        // fetch(item.options.remoteFunc, {
+        fetch(`${item.options.remoteFunc}?customerId=${val}`, {
+          headers: {
+            "Content-type": " application/x-www-form-urlencoded; charset=UTF-8",
+            "Token": token
+          }
+        })
+          .then(resp => resp.json())
+          .then((json) => {
+            const res = json.data
+            if (res instanceof Array) {
+              item.options.remoteOptions = res.map(data => ({
+                label: data[item.options.props.label],
+                value: data[item.options.props.value],
+                children: data[item.options.props.children],
+              }))
+            }
+            list[i].list[0].options = {...list[i].list[0].options, disabled: false, defaultValue: ''}
+          })
+      }
+    }
+    setTimeout(() => {
+      console.log('开始执行')
+      updateWidgetForm(list)
+    }, 100)
+  }
+}
+
+const updateWidgetForm = (list: any) => {
+  emits('updateWidgetForm', list)
+}
 </script>
 <style scoped>
 :deep(.el-upload--picture-card) {

+ 1 - 0
fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/generate/GenerateForm.vue.d.ts

@@ -16,6 +16,7 @@ declare const _default: import("vue").DefineComponent<{
 }, {
     getData: () => Promise<unknown>;
     reset: () => void;
+    updateWidgetForm: (list: any[]) => void;
     generateForm: import("vue").Ref<any>;
     model: import("vue").Ref<any>;
     updatedModel: import("vue").Ref<any>;

+ 6 - 2
fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/generate/GenerateFormItem.vue.d.ts

@@ -6,14 +6,18 @@ declare const _default: import("vue").DefineComponent<__VLS_TypePropsToRuntimePr
     updatedModel: any;
     disabled: boolean;
     request?: Function | undefined;
-}>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, Record<string, any>, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
+    widgetFormData?: any;
+}>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "updateWidgetForm"[], "updateWidgetForm", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
     config: WidgetForm['config'];
     element: any;
     model: any;
     updatedModel: any;
     disabled: boolean;
     request?: Function | undefined;
-}>>>, {}>;
+    widgetFormData?: any;
+}>>> & {
+    onUpdateWidgetForm?: ((...args: any[]) => any) | undefined;
+}, {}>;
 export default _default;
 declare type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
 declare type __VLS_TypePropsToRuntimeProps<T> = {

File diff suppressed because it is too large
+ 1 - 1
fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/index.css


+ 69 - 16
fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/index.es.js

@@ -27558,7 +27558,7 @@ var _export_sfc = (sfc, props) => {
   }
   return target;
 };
-const _withScopeId = (n) => (pushScopeId("data-v-1a926725"), n = n(), popScopeId(), n);
+const _withScopeId = (n) => (pushScopeId("data-v-fd931432"), n = n(), popScopeId(), n);
 const _hoisted_1$6 = { key: 12 };
 const _hoisted_2$5 = {
   key: 1,
@@ -27575,9 +27575,11 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
     model: null,
     updatedModel: null,
     disabled: { type: Boolean },
-    request: null
+    request: null,
+    widgetFormData: null
   },
-  setup(__props) {
+  emits: ["updateWidgetForm"],
+  setup(__props, { emit: emits }) {
     const props = __props;
     const originData = props.model[props.element.model];
     const data2 = computed({
@@ -27609,6 +27611,41 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
       a2.download = `${label}.${defaultValue.split(".")[1]}`;
       a2.click();
     }
+    const specializedHandleSelect = (val, element) => {
+      const field = element.model;
+      if (field == "customerId") {
+        let list = JSON.parse(JSON.stringify(props.widgetFormData));
+        for (var i in list) {
+          if (list[i].list[0].model == "contactsId") {
+            let item = list[i].list[0];
+            const token = sessionStorage.getItem("token");
+            fetch(`${item.options.remoteFunc}?customerId=${val}`, {
+              headers: {
+                "Content-type": " application/x-www-form-urlencoded; charset=UTF-8",
+                "Token": token
+              }
+            }).then((resp) => resp.json()).then((json) => {
+              const res = json.data;
+              if (res instanceof Array) {
+                item.options.remoteOptions = res.map((data22) => ({
+                  label: data22[item.options.props.label],
+                  value: data22[item.options.props.value],
+                  children: data22[item.options.props.children]
+                }));
+              }
+              list[i].list[0].options = __spreadProps(__spreadValues({}, list[i].list[0].options), { disabled: false, defaultValue: "" });
+            });
+          }
+        }
+        setTimeout(() => {
+          console.log("\u5F00\u59CB\u6267\u884C");
+          updateWidgetForm(list);
+        }, 100);
+      }
+    };
+    const updateWidgetForm = (list) => {
+      emits("updateWidgetForm", list);
+    };
     return (_ctx, _cache) => {
       const _component_GenerateFormItem = resolveComponent("GenerateFormItem", true);
       const _component_el_table_column = ElTableColumn;
@@ -27651,8 +27688,10 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
                 "updated-model": __props.updatedModel,
                 element: colItem,
                 config: __props.config,
-                disabled: __props.disabled
-              }, null, 8, ["request", "model", "updated-model", "element", "config", "disabled"]);
+                disabled: __props.disabled,
+                widgetFormData: __props.element.columns,
+                onUpdateWidgetForm: updateWidgetForm
+              }, null, 8, ["request", "model", "updated-model", "element", "config", "disabled", "widgetFormData"]);
             }), 128))
           ], 4);
         }), 128))
@@ -27692,6 +27731,7 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
             key: 0,
             modelValue: unref(data2),
             "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isRef(data2) ? data2.value = $event : null),
+            modelModifiers: { trim: true },
             style: normalizeStyle({ width: __props.element.options.width }),
             placeholder: __props.element.options.placeholder,
             maxlength: parseInt(__props.element.options.maxlength),
@@ -27728,6 +27768,7 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
             key: 1,
             modelValue: unref(data2),
             "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => isRef(data2) ? data2.value = $event : null),
+            modelModifiers: { trim: true },
             style: normalizeStyle({ width: __props.element.options.width }),
             placeholder: __props.element.options.placeholder,
             maxlength: parseInt(__props.element.options.maxlength),
@@ -27765,6 +27806,7 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
             key: 2,
             modelValue: unref(data2),
             "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => isRef(data2) ? data2.value = $event : null),
+            modelModifiers: { trim: true },
             type: "textarea",
             resize: "none",
             rows: __props.element.options.rows,
@@ -27784,7 +27826,8 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
             style: normalizeStyle({ width: __props.element.options.width }),
             max: __props.element.options.max,
             min: __props.element.options.min,
-            disabled: __props.disabled || __props.element.options.disabled
+            disabled: __props.disabled || __props.element.options.disabled,
+            "controls-position": "right"
           }, null, 8, ["modelValue", "style", "max", "min", "disabled"])) : createCommentVNode("", true),
           __props.element.type === "radio" ? (openBlock(), createBlock(_component_el_radio_group, {
             key: 4,
@@ -27891,7 +27934,8 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
             clearable: __props.element.options.clearable,
             filterable: __props.element.options.filterable,
             disabled: __props.disabled || __props.element.options.disabled,
-            style: normalizeStyle({ width: __props.element.options.width })
+            style: normalizeStyle({ width: __props.element.options.width }),
+            onChange: _cache[10] || (_cache[10] = (value) => specializedHandleSelect(value, __props.element))
           }, {
             default: withCtx(() => [
               (openBlock(true), createElementBlock(Fragment, null, renderList(__props.element.options.remote ? __props.element.options.remoteOptions : __props.element.options.options, (item) => {
@@ -27907,7 +27951,7 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
           __props.element.type === "switch" ? (openBlock(), createBlock(_component_el_switch, {
             key: 10,
             modelValue: unref(data2),
-            "onUpdate:modelValue": _cache[10] || (_cache[10] = ($event) => isRef(data2) ? data2.value = $event : null),
+            "onUpdate:modelValue": _cache[11] || (_cache[11] = ($event) => isRef(data2) ? data2.value = $event : null),
             "active-text": __props.element.options.activeText,
             "inactive-text": __props.element.options.inactiveText,
             disabled: __props.disabled || __props.element.options.disabled
@@ -27915,7 +27959,7 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
           __props.element.type === "slider" ? (openBlock(), createBlock(_component_el_slider, {
             key: 11,
             modelValue: unref(data2),
-            "onUpdate:modelValue": _cache[11] || (_cache[11] = ($event) => isRef(data2) ? data2.value = $event : null),
+            "onUpdate:modelValue": _cache[12] || (_cache[12] = ($event) => isRef(data2) ? data2.value = $event : null),
             min: __props.element.options.min,
             max: __props.element.options.max,
             step: __props.element.options.step,
@@ -27962,7 +28006,7 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
             key: 14,
             style: { "margin-top": "-4px" },
             type: "text",
-            onClick: _cache[12] || (_cache[12] = ($event) => download(__props.element.options.defaultValue, __props.element.label))
+            onClick: _cache[13] || (_cache[13] = ($event) => download(__props.element.options.defaultValue, __props.element.label))
           }, {
             default: withCtx(() => [
               _hoisted_6$4
@@ -27972,7 +28016,7 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
           __props.element.type === "cascader" ? (openBlock(), createBlock(_component_el_cascader, {
             key: 15,
             modelValue: unref(data2),
-            "onUpdate:modelValue": _cache[13] || (_cache[13] = ($event) => isRef(data2) ? data2.value = $event : null),
+            "onUpdate:modelValue": _cache[14] || (_cache[14] = ($event) => isRef(data2) ? data2.value = $event : null),
             options: __props.element.options.remoteOptions,
             placeholder: __props.element.options.placeholder,
             filterable: __props.element.options.filterable,
@@ -27997,7 +28041,7 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
     };
   }
 });
-var GenerateFormItem = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["__scopeId", "data-v-1a926725"]]);
+var GenerateFormItem = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["__scopeId", "data-v-fd931432"]]);
 const _sfc_main$7 = defineComponent({
   name: "FormGenerate",
   components: {
@@ -28081,6 +28125,11 @@ const _sfc_main$7 = defineComponent({
         }
       });
     };
+    const updateWidgetForm = (list) => {
+      const listIndex2 = state.widgetForm.list.findIndex((item) => item.type === "grid");
+      state.widgetForm.list[listIndex2].columns = list;
+      state.model = __spreadProps(__spreadValues({}, state.model), { contactsId: "" });
+    };
     watch(() => props.data, (val) => {
       var _a3;
       state.widgetForm = (_a3 = val && JSON.parse(JSON.stringify(val))) != null ? _a3 : getWidgetForm();
@@ -28106,7 +28155,8 @@ const _sfc_main$7 = defineComponent({
     };
     return __spreadProps(__spreadValues({}, toRefs(state)), {
       getData,
-      reset
+      reset,
+      updateWidgetForm
     });
   }
 });
@@ -28132,8 +28182,10 @@ function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
           element: _ctx.widgetForm.list[index],
           config: _ctx.data.config,
           disabled: _ctx.disabled,
-          request: _ctx.request
-        }, null, 8, ["model", "updated-model", "element", "config", "disabled", "request"]);
+          request: _ctx.request,
+          widgetFormData: _ctx.widgetForm.list,
+          onUpdateWidgetForm: _ctx.updateWidgetForm
+        }, null, 8, ["model", "updated-model", "element", "config", "disabled", "request", "widgetFormData", "onUpdateWidgetForm"]);
       }), 128))
     ]),
     _: 1
@@ -28496,7 +28548,8 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
               style: normalizeStyle({ width: __props.element.options.width }),
               max: __props.element.options.max,
               min: __props.element.options.min,
-              disabled: __props.element.options.disabled
+              disabled: __props.element.options.disabled,
+              "controls-position": "right"
             }, null, 8, ["model-value", "style", "max", "min", "disabled"])) : createCommentVNode("", true),
             __props.element.type === "radio" ? (openBlock(), createBlock(_component_el_radio_group, {
               key: 4,

File diff suppressed because it is too large
+ 1 - 1
fhKeeper/formulahousekeeper/plugIn/form-design-master/update/dist/index.es.js.map


+ 3 - 0
fhKeeper/formulahousekeeper/timesheet-workshop-h5/src/views/planView/component/planComponent.vue

@@ -44,6 +44,9 @@
                 <div class="PlanItem">
                   <div>每辆数量:</div><span class="textBeyondHiding">{{ item.product.vehicleNumber }}</span>
                 </div>
+                <div class="PlanItem">
+                  <div>列序号:</div><span class="textBeyondHiding">{{ item.columnNumStart }}-{{ item.columnNumEnd }}</span>
+                </div>
                 <div class="PlanItemBtn">
                   <span class="text" @click="hidePlan(item.id,item.hideState)">
                     {{ jisuanDate(item.startDate)>30 ? '隐藏' : ''}}

+ 42 - 5
fhKeeper/formulahousekeeper/timesheet-workshop-h5/src/views/planView/todayPlan/distribution.vue

@@ -10,7 +10,7 @@
     <div class="distribution_con contentRoll">
       <div class="distribution_box" v-for="item,index in distributionList" :key="index">
         <div class="distribution_ItemBom">
-          <van-checkbox v-if="todayAndTomorrow" :disabled="item.checkboxDisabled"  v-model="item.prodProcedure.isSelected"  @click="itemChecked" shape="square">
+          <van-checkbox v-if="todayAndTomorrow" :disabled="item.checkboxDisabled  || item.teamNames.indexOf(user.name) == -1"  v-model="item.prodProcedure.isSelected"  @click="itemChecked" shape="square">
           </van-checkbox>
           <div class="PlanItem">
             <span>{{ item.prodProcedure.name }}</span>
@@ -55,7 +55,7 @@
                             <span class="" v-if="second_item.status==0&&beDeptList" @click="deletePeople(second_item.id)"  style="color: #1989fa;">删除</span>
                       </div>
                       <p style="margin-top:20px;">
-                        <span class="" v-if="beDeptList" @click="distributionProp(item,index,'add')"  style="color: #1989fa;">新增</span>
+                        <span class="" v-if="beDeptList && item.totalProgress<100" @click="distributionProp(item,index,'add')"  style="color: #1989fa;">新增</span>
                       </p>
                     </div>
                 </div>
@@ -72,7 +72,8 @@
   <div class="formBatch" v-if="todayAndTomorrow">
         <van-checkbox v-model="isAllChecked" :disabled="distributionList.length == 0" @click="allChecked" shape="square" style="padding-left:3vw"></van-checkbox>
         <div style="padding:1vh 2vw">
-        <van-button @click="batchReceive()" :disabled="!isCanAgree || distributionList.length == 0" type="info" size="small">批量接收</van-button>
+        <van-button style="margin-right: 10px;" @click="batchReceive()" :disabled="!isCanAgree || distributionList.length == 0" type="info" size="small">批量接收</van-button>
+        <van-button @click="batchUnReceive()" :disabled="!isCanAgree || distributionList.length == 0" type="info" size="small">批量拒收</van-button>
         <!-- <van-button @click="cancellationReceiveBatch()" :disabled="!isCanAgree || distributionList.length == 0" type="info" size="small">批量取消接收</van-button> -->
         <!-- <van-button @click="batchAgree(false)" :disabled="!isCanAgree || distributionList.length == 0" type="danger" size="small" style="margin-left:2vw">批量驳回</van-button> -->
         </div>
@@ -118,6 +119,7 @@ export default {
       ChooseSomeoneKey: 1,
 
       peopleListIdObj: null, // 杯换人的所有信息
+
     };
   },
   computed: {},
@@ -178,8 +180,9 @@ export default {
     allChecked(){
         if(this.isAllChecked){
             for(let i in this.distributionList){
-                this.distributionList[i].prodProcedure.isSelected = true
-                console.log('===============');
+                if(this.distributionList[i].teamNames.indexOf(this.user.name) == -1){
+                  this.distributionList[i].prodProcedure.isSelected = true
+                }
             }
             this.isCanAgree = true
         }else{
@@ -237,6 +240,40 @@ export default {
             }).catch(err => { this.$toast.clear(); })
         }
     },
+    batchUnReceive(bol){
+        let ids = ''
+        console.log(this.user)
+        let resArr=  this.distributionList.map(item=>{
+          if(item.prodProcedure.isSelected){
+            if(item.prodProcedureTeamList.filter(i=>i.userId==this.user.id).length>0){
+               return item.prodProcedureTeamList.filter(i=>i.userId==this.user.id)[0].id
+            }else{
+              return "-1"
+            }
+          }
+         })
+         console.log('res===============',resArr)
+         ids = resArr.join(",").trim()
+        if(resArr.length > 0){
+            this.$axios.post(
+              "/plan/unReceivePlan",
+              {
+                ids:ids
+              }
+            ).then(res => {
+              if (res.code === "ok") {
+                this.isAllChecked=false
+                this.isCanAgree=false
+                this.getDistributionList()
+                this.$toast.success('拒收成功');
+              } else {
+                this.$toast.clear();
+                console.log("bbb")
+                this.$toast.fail(res.msg);
+              }
+            }).catch(err => { this.$toast.clear(); })
+        }
+    },
     workShowHide(index) {
       this.distributionList[index].flg = !this.distributionList[index].flg;
       console.log('=========>',this.distributionList[index].flg)

+ 9 - 2
fhKeeper/formulahousekeeper/timesheet-workshop/src/views/plan/planComponent.vue

@@ -24,7 +24,7 @@
                 <el-option label="排产工单号" value="1"></el-option>
                 <el-option label="项目名称" value="2"></el-option>
                 <el-option label="产品名称" value="3"></el-option>
-                <el-option label="订单号" value="3"></el-option>
+                <el-option label="订单号" value="4"></el-option>
               </el-select>
               <el-button slot="append" icon="el-icon-search" @click="getTableData()"></el-button>
             </el-input>
@@ -95,6 +95,10 @@
               </div>
             </template>
           </el-table-column>
+          <el-table-column prop="productOrderNum" label="生产订单号" width="180">
+          </el-table-column>
+          <el-table-column prop="projectName" label="项目名称" width="180">
+          </el-table-column>
           <el-table-column prop="productName" label="产品名称" width="180">
           </el-table-column>
           <el-table-column prop="projectCode" label="项目代码" width="180">
@@ -144,6 +148,9 @@
           <el-form-item label="排产工单号" style="width: 100%" prop="productSchedulingNum">
             <el-input v-model="todayPlanForm.productSchedulingNum" maxlength="50"></el-input>
           </el-form-item>
+          <el-form-item label="生产订单号" style="width: 100%" prop="productOrderNum">
+            <el-input v-model="todayPlanForm.productOrderNum" maxlength="50"></el-input>
+          </el-form-item>
           <el-form-item label="产品名称" style="width: 100%" prop="productId">
             <el-select :disabled="todayPlanForm.id==null?false:true" v-model="todayPlanForm.productId" placeholder="请选择" class="w100" @change="setProductCode" filterable>
               <el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id">
@@ -153,7 +160,7 @@
           <el-form-item label="项目代码" style="width: 100%" prop="projectCode">
             <el-input :disabled="todayPlanForm.id==null?false:true" v-model="todayPlanForm.projectCode" maxlength="50" readonly></el-input>
           </el-form-item>
-          <el-form-item label="项目名称" style="width: 100%" prop="projectCode">
+          <el-form-item label="项目名称" style="width: 100%" prop="projectName">
             <el-input  v-model="todayPlanForm.projectName" maxlength="50" ></el-input>
           </el-form-item>
 

+ 4 - 0
fhKeeper/formulahousekeeper/timesheet-workshop/src/views/plan/planComponentDetil.vue

@@ -29,6 +29,10 @@
           :height="tableHight"
           v-if="TabIndex == 0" v-loading="tableDataLoading"
         >
+        <el-table-column
+          type="index"
+          width="50">
+        </el-table-column>
           <el-table-column label="工序名称" width="400">
             <template slot-scope="scope">
                 <div class="disFlexscope">

+ 10 - 1
fhKeeper/formulahousekeeper/timesheet-workshop/src/views/product/list.vue

@@ -238,7 +238,7 @@
                  <!--此处是录入工序的模块-->
 
 
-                <el-input placeholder="请输入工序版本号" v-model="procedureVersion" clearable maxlength="50" class="input-pM"></el-input>
+                <el-input placeholder="请输入工序版本号" v-model="procedureVersion" clearable maxlength="50" class="input-pM" @change="getProdProcedureListWithVersion(productId,procedureVersion)"></el-input>
                 <el-table :data="procedureLit" style="width: 100%">
                     <el-table-column prop="name" label="工序名称"  width="350">
                         <template slot-scope="scope">
@@ -1218,6 +1218,15 @@ export default {
                     })
             }
 
+        },
+        getProdProcedureListWithVersion(id,version) {
+            if (version != null && version != '') {
+                this.http.post("/prod-procedure/getInfo", { version: version, productId: id },
+                    res => {
+                        this.procedureLit=res.data
+                    })
+            }
+
         },
         getProdMaterialVersion(id, index) {
             if (this.prodMaterialVersion != null && this.prodMaterialVersion != '') {

+ 57 - 17
fhKeeper/formulahousekeeper/timesheet-workshop/src/views/statistic/index.vue

@@ -39,7 +39,7 @@
       <div class="headScreen" :style="'width:72%'">
           <!-- 部门筛选 -->
           <el-cascader v-if="ins!=5 && !isViewUser" v-model="departmentIdArray" :options="departmentList" :placeholder="$t('qing-xuan-ze-bu-men')"
-            :props="{ checkStrictly: true,expandTrigger: 'hover' }" collapse-tags :show-all-levels="false" clearable
+            :props="{ multiple: true, checkStrictly: true,expandTrigger: 'hover' }" collapse-tags :show-all-levels="false" clearable
             @change="selcts()" size="small" style="margin-bottom: 10px;width:180px"
           ></el-cascader>
 
@@ -90,15 +90,20 @@
                     <template slot-scope="scope">
                         <div v-for="(items, indexs) in scope.row.personWorkHoursWages" :key="indexs" @click="showReportDetail(scope.row,item,0)" :class="`${scope.row.departmentCascade== '小计' ? '' : 'colorText'}`">
                             <div v-if="items.crateDate == item">
-                               <div> {{items.workTime}}分钟 </div> 
-                               <div>{{items.cost}}元</div>
+                              <div  style="color: black;" v-if="items.planWorkTime">平均 {{items.planWorkTime}}分钟  {{items.planCost}}元</div>
+                               <div>已填 {{items.workTime}}分钟  {{items.cost}}元</div> 
+                               <div style="color: red;" v-if="items.surplusTime">剩余 {{items.surplusTime}}分钟  {{items.surplusCost}}元</div>
                             </div>
                         </div>
                     </template>
                 </el-table-column>
-                <el-table-column align="center" prop="totalResult" label="合计" min-width="150">
+                <el-table-column align="center" prop="totalResult" label="合计" min-width="180">
                    <template slot-scope="scope" >
-                    <span :class="`${'colorText'}`" @click="showReportDetail(scope.row,item,1)">{{scope.row.totalResult}}</span>
+                    <div @click="showReportDetail(scope.row,item,1)">
+                      <div  style="color: black;">平均 {{scope.row.totalPlanResult}}</div>
+                      <div style="color: #02a7f0;"  @click="showReportDetail(scope.row,item,1)">已填 {{scope.row.totalResult}}</div> 
+                      <div style="color: red;">剩余 {{scope.row.totalSurplusResult}}</div>
+                    </div>
                   </template>
                 </el-table-column>
             </el-table>
@@ -889,13 +894,18 @@ export default {
     },
     //人员工时工价表数据
     getPersonWorkHoursWagesList(){
+        let deptArr = []
+        for(var i in this.departmentIdArray){
+          let itemList = this.departmentIdArray[i] 
+          deptArr.push(itemList[itemList.length - 1])
+        }
         this.listLoading=true
         this.http.post( "/report/getPersonWorkHoursWagesList", {
             startDate:this.rangeDatas[0],
             endDate:this.rangeDatas[1],
             pageIndex: this.page,
             pageSize: this.size,
-            deptId:this.departmentIdArray[this.departmentIdArray.length - 1],
+            deptIds:deptArr.join(','),
             userId:this.userId
         },
         res => {
@@ -962,12 +972,17 @@ export default {
     //工序实际工时表
     getProcedureRealTimeProgressList(){
       this.listLoading=true
+      let deptArr = []
+        for(var i in this.departmentIdArray){
+          let itemList = this.departmentIdArray[i] 
+          deptArr.push(itemList[itemList.length - 1])
+        }
         this.http.post( "/report/getProcedureRealTimeProgressList", {
             startDate:this.rangeDatas[0],
             endDate:this.rangeDatas[1],
             pageIndex: this.page,
             pageSize: this.size,
-            deptId:this.departmentIdArray[this.departmentIdArray.length - 1],
+            deptIds:deptArr.join(','),
             userId:this.userId
         },
         res => {
@@ -991,12 +1006,17 @@ export default {
     //部门生产统计表
     getDpetStatisticsProgressList(){
       this.listLoading=true
+      let deptArr = []
+        for(var i in this.departmentIdArray){
+          let itemList = this.departmentIdArray[i] 
+          deptArr.push(itemList[itemList.length - 1])
+        }
         this.http.post( "/report/getDpetStatisticsProgressList", {
             startDate:this.rangeDatas[0],
             endDate:this.rangeDatas[1],
             pageIndex: this.page,
             pageSize: this.size,
-            deptId:this.departmentIdArray[this.departmentIdArray.length - 1],
+            deptIds:deptArr.join(','),
         },
         res => {
           if (res.code == "ok") {
@@ -1019,12 +1039,17 @@ export default {
     //计划实际工时表
     getPlanRealTimeProgressList(){
       this.listLoading=true
+      let deptArr = []
+        for(var i in this.departmentIdArray){
+          let itemList = this.departmentIdArray[i] 
+          deptArr.push(itemList[itemList.length - 1])
+        }
         this.http.post( "/report/getPlanRealTimeProgressList", {
             startDate:this.rangeDatas[0],
             endDate:this.rangeDatas[1],
             pageIndex: this.page,
             pageSize: this.size,
-            deptId:this.departmentIdArray[this.departmentIdArray.length - 1],
+            deptIds:deptArr.join(','),
             userId:this.userId
         },
         res => {
@@ -1048,12 +1073,17 @@ export default {
     //人员工时工价表数据
     getWorkReportQuery(){
       this.listLoading=true
+      let deptArr = []
+        for(var i in this.departmentIdArray){
+          let itemList = this.departmentIdArray[i] 
+          deptArr.push(itemList[itemList.length - 1])
+        }
         this.http.post( "/report/workReportQuery", {
             startDate:this.rangeDatas[0],
             endDate:this.rangeDatas[1],
             pageIndex: this.page,
             pageSize: this.size,
-            deptId:this.departmentIdArray[this.departmentIdArray.length - 1],
+            deptIds:deptArr.join(','),
             userId:this.userId,
             productId:this.productId,
             vehicleNum:this.vehicleNum,
@@ -1107,12 +1137,17 @@ export default {
     },
     //车间工位计划表
     getPlanDataWithStation(deptId){
+      let deptArr = []
+        for(var i in this.departmentIdArray){
+          let itemList = this.departmentIdArray[i] 
+          deptArr.push(itemList[itemList.length - 1])
+        }
       let param={
         startDate:this.rangeDatas[0],
         endDate:this.rangeDatas[1],
         pageIndex: this.page,
         pageSize: this.size,
-        stationId:this.departmentIdArray[this.departmentIdArray.length - 1],
+        stationIds:deptArr.join(','),
       }
       if(deptId){
         this.exportDeptId=deptId
@@ -1327,26 +1362,31 @@ export default {
     var url = "/report";
     var fName = "";
     var sl = {}
+    let deptArr = []
+    for(var i in this.departmentIdArray){
+      let itemList = this.departmentIdArray[i] 
+      deptArr.push(itemList[itemList.length - 1])
+    }
     if (this.ins == 0) {  
         fName = '人员工时工价表_' + '.xlsx';
         url += "/exportPersonWorkHoursWorkTime";
         sl.startDate=this.rangeDatas[0];
         sl.endDate=this.rangeDatas[1];
-        sl.deptId=this.departmentIdArray[this.departmentIdArray.length-1];
+        sl.deptIds=deptArr.join(',');
         sl.userId=this.userId;
     } else if (this.ins == 1) {
         fName = '工序实时进度表_' + '.xlsx';
         url += "/exportProcedureRealTimeProgressList";
         sl.startDate=this.rangeDatas[0];
         sl.endDate=this.rangeDatas[1];
-        sl.deptId=this.departmentIdArray[this.departmentIdArray.length-1];
+        sl.deptIds=deptArr.join(',');
         sl.userId=this.userId;
     }else if (this.ins == 2) {
         fName = '报工详情表_' + '.xlsx';
         url += "/exportWorkReportQuery";
         sl.startDate=this.rangeDatas[0];
         sl.endDate=this.rangeDatas[1];
-        sl.deptId=this.departmentIdArray[this.departmentIdArray.length-1];
+        sl.deptIds=deptArr.join(',');
         sl.userId=this.userId;
         sl.vehicleNum=this.vehicleNum;
         sl.steelNum=this.steelNum;
@@ -1356,14 +1396,14 @@ export default {
         url += "/exportPlanRealTimeProgressList";
         sl.startDate=this.rangeDatas[0];
         sl.endDate=this.rangeDatas[1];
-        sl.deptId=this.departmentIdArray[this.departmentIdArray.length-1];
+        sl.deptIds=deptArr.join(',');
         sl.userId=this.userId;
     } else if (this.ins == 4) {
         fName = '部门生产统计表_' + '.xlsx';
         url += "/exportDpetStatisticsProgressList";
         sl.startDate=this.rangeDatas[0];
         sl.endDate=this.rangeDatas[1];
-        sl.deptId=this.departmentIdArray[this.departmentIdArray.length-1];
+        sl.deptIds=deptArr.join(',');
     }
     else if (this.ins == 5) {
         fName = '月度生产件数表_' + '.xlsx';
@@ -1378,7 +1418,7 @@ export default {
         sl.endDate=this.rangeDatas[1];
         if(!this.personnelFlag){
           url += "/exportPlanDataWithStation";
-          sl.deptId=this.departmentIdArray[this.departmentIdArray.length-1];
+          sl.deptIds=deptArr.join(',');
           if(this.exportDeptId){
           sl.filterDeptId=this.exportDeptId;
           sl.isFilterDept=1

+ 235 - 0
fhKeeper/formulahousekeeper/timesheet/src/components/cascadeSelection.vue

@@ -0,0 +1,235 @@
+<template>
+    <div class='cascadeSelection'>
+        <!-- 框框 -->
+        <div ref="focusDiv" tabindex="0" :class="`input ${size} ${disabled ? 'inputDisabled' : ''}`"
+            :style="`width: ${width}`" @focus="handleFocus" @blur="handleBlur">
+            <!-- 默认提示文字 -->
+            <span class="placeholderColor" v-if="resultText.length == 0">请选择</span>
+            <!-- 选中数据 -->
+            <div v-if="resultText.length > 0" class="textEllipsisNowrap">
+                <template v-for="(item, index) in resultText[0]">
+                    <TranslationOpenDataText type='departmentName' :openid='item'></TranslationOpenDataText>
+                    <span v-if="index < resultText[0].length - 1" class="textSpan">/</span>
+                </template>
+            </div>
+
+            <i v-if="resultText.length > 0" class="el-icon-circle-close iostu" @click.stop="clearDelete"></i>
+
+            <!-- 级联面板 -->
+            <div class="absoluteWeight" v-if="isFocused" :style="`top: ${sizeTop[size]}`">
+                <el-cascader-panel v-model="modelValue" ref="cascaderPanelRef" :options="options" :props="props"
+                    @change="panelChange">
+                    <template slot-scope="{ node, data }">
+                        <TranslationOpenDataText type='departmentName' :openid='data.label'></TranslationOpenDataText>
+                    </template>
+                </el-cascader-panel>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    name: '',
+    components: {},
+    props: {
+        modelValue: {
+            type: Array,
+            default: () => []
+        },
+        size: {
+            type: String,
+            default: 'default',
+        },
+        width: {
+            type: String,
+            default: '100%',
+        },
+        options: {
+            type: Array,
+            default: () => [],
+        },
+        props: {
+            type: Object,
+            default: () => {
+                return { checkStrictly: true, expandTrigger: 'hover' }
+            }
+        },
+        disabled: {
+            type: Boolean,
+            default: false
+        }
+    },
+    data() {
+        return {
+            isFocused: false,
+            resultText: [],
+            sizeTop: {
+                default: '40px',
+                medium: '36px',
+                small: '32px',
+                mini: '24px'
+            }
+        }
+    },
+    computed: {},
+    watch: {},
+    created() { },
+    mounted() {
+        setTimeout(() => {
+            if ((this.modelValue || []).length > 0) {
+                this.resultText = this.findDepartmentNames(this.options, this.props.multiple ? this.modelValue : [this.modelValue]);
+            }
+        }, 500)
+    },
+    model: {
+        prop: 'modelValue',
+        event: 'getValue'
+    },
+    methods: {
+        panelChange(val) {
+            this.resultText = this.findDepartmentNames(this.options, this.props.multiple ? val : [val]);
+            this.updateModelValue()
+        },
+        findDepartmentNames(data, values) {
+            const findLabels = (valueList) => {
+                return valueList.map(value => {
+                    const findLabel = (data, value) => {
+                        for (let item of data) {
+                            if (item.value === value) {
+                                return item.label;
+                            }
+                            if (item.children) {
+                                const label = findLabel(item.children, value);
+                                if (label) return label;
+                            }
+                        }
+                        return null;
+                    };
+                    return findLabel(data, value);
+                }).filter(label => label !== null);
+            };
+            return values.map(valueList => findLabels(valueList));
+        },
+        handleFocus() {
+            if(this.disabled) {
+                return
+            }
+            this.isFocused = true
+            this.$refs.focusDiv.classList.add('focused');
+        },
+        handleBlur(event) {
+            if(this.disabled) {
+                return
+            }
+            if (this.$refs.focusDiv.contains(event.relatedTarget)) {
+                this.$refs.focusDiv.focus();
+                event.preventDefault();
+                return;
+            }
+            this.isFocused = false
+            this.$refs.focusDiv.classList.remove('focused');
+        },
+        clearDelete() {
+            this.$refs.focusDiv.blur()
+            this.resultText = [];
+            this.$emit('getValue', []);
+            this.$emit('change', []);
+        },
+        updateModelValue() {
+            this.$emit('getValue', this.modelValue);
+            this.$emit('change', this.modelValue);
+        }
+    },
+}
+</script>
+<style scoped lang='scss'>
+.cascadeSelection {
+    position: relative;
+    max-height: 40px;
+
+    .default {
+        height: 40px;
+        line-height: 40px;
+    }
+
+    .medium {
+        height: 36px;
+        line-height: 36px;
+    }
+
+    .small {
+        height: 32px;
+        line-height: 32px;
+    }
+
+    .mini {
+        height: 28px;
+        line-height: 28px;
+    }
+
+    .input {
+        position: relative;
+        font-size: 14px;
+        background-color: #FFF;
+        background-image: none;
+        border-radius: 4px;
+        border: 1px solid #DCDFE6;
+        box-sizing: border-box;
+        color: #606266;
+        display: inline-block;
+        outline: 0;
+        padding: 0 15px;
+        -webkit-transition: border-color .2s cubic-bezier(.645, .045, .355, 1);
+        transition: border-color .2s cubic-bezier(.645, .045, .355, 1);
+        width: 100%;
+    }
+
+    .input:focus {
+        border-color: #409EFF;
+    }
+
+    .placeholderColor {
+        color: #C0C4CC;
+    }
+
+    .absoluteWeight {
+        position: absolute;
+        z-index: 99;
+        background: #fff;
+        left: 0;
+    }
+
+    .textSpan {
+        display: inline-block;
+        padding: 0 3px
+    }
+
+    .textEllipsisNowrap {
+        width: 100%;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+    }
+
+    .iostu {
+        position: absolute;
+        top: 50%;
+        margin-top: -4px;
+        right: 8px;
+        color: #C0C4CC;
+        transition: All 0.2s ease-in-out;
+    }
+
+    .iostuHover {
+        transform: rotate(-180deg);
+    }
+
+    .inputDisabled {
+        background-color: #f5f7fa !important;
+        border-color: #e4e7ed !important;
+        color: #c0c4cc !important;
+        cursor: not-allowed !important;
+    }
+}
+</style>

+ 10 - 10
fhKeeper/formulahousekeeper/timesheet/src/components/select.vue

@@ -276,7 +276,7 @@ export default {
                     }
                 }
             }
-            console.log(this.options, this.subjectId)
+            // console.log(this.options, this.subjectId)
             if(this.multiSelect) { 
                 for(var i in this.options) {
                     for(var j in this.subjectId) {
@@ -288,7 +288,7 @@ export default {
                 }
             }
         }
-        console.log(this.subject, this.subjectId)
+        // console.log(this.subject, this.subjectId)
 
         var thats = this
         var phoneArr = []
@@ -300,7 +300,7 @@ export default {
         }, 500)
         
         thats.fistArrList = phoneArr
-        console.log(thats.fistArrList)
+        // console.log(thats.fistArrList)
         this.dailyListIndex = this.idx
     },
     methods: {
@@ -315,9 +315,9 @@ export default {
                     "selectedDepartmentIds": [],// 非必填,已选部门ID列表。用于多次选人时可重入,single模式下请勿填入多个id
                     "selectedUserIds": []// 非必填,已选用户ID列表。用于多次选人时可重入,single模式下请勿填入多个id
                         },function(res){
-                            console.log(res)
+                            // console.log(res)
                             if (res.err_msg == "selectEnterpriseContact:ok"){
-                                console.log(res, '数据来源')
+                                // console.log(res, '数据来源')
                                 if(typeof res.result == 'string'){
                                     res.result = JSON.parse(res.result) //由于目前各个终端尚未完全兼容,需要开发者额外判断result类型以保证在各个终端的兼容性
                                 }
@@ -328,7 +328,7 @@ export default {
                                         var user = selectedUserList[i];
                                         userId = user.id; // 已选的单个成员ID
                                         userName = user.name;// 已选的单个成员名称
-                                        console.log(userId, userName)
+                                        // console.log(userId, userName)
                                 }
                                 for(var s in that.options) {
                                     if(that.options[s].name == userId) {
@@ -349,7 +349,7 @@ export default {
                 other: this.other,
                 name: this.selectName
             }
-            console.log(obj)
+            // console.log(obj)
             this.$emit("selectCal", obj)
         },
         selectCli() {
@@ -400,11 +400,11 @@ export default {
             this.transitionBoxLiIdx = index
         },
         liClick(item, itemIndex) {
-            console.log(item, '进来的')
+            // console.log(item, '进来的')
             let nameId = item.auditorId || item.id
             this.selectName = item.auditorName || item.name
             if(!this.multiSelect) {
-                console.log('我进来了', this.flg)
+                // console.log('我进来了', this.flg)
                 if(this.flgs) {
                     let obj = {
                         id: nameId,
@@ -540,7 +540,7 @@ export default {
                         }
                     })
                     // this.options = arr
-                    console.log('将要赋值')
+                    // console.log('将要赋值')
                     var newArr = arr.length > 0 ? arr : res.data.records
                     this.$set(this, 'options', newArr)
                     this.cursor = res.data.nextCursor

+ 2 - 1
fhKeeper/formulahousekeeper/timesheet/src/i18n/en.json

@@ -26,7 +26,8 @@
     "basicDataManagemen": "Basic Data Managemen",
     "basicSystemSettings": "Basic System Settings",
     "roleRightsManagement": "Role Rights Management",
-    "gongshitongji":"工时统计表"
+    "gongshitongji":"工时统计表",
+    "caiwushenhe":"财务审核"
   },
   "role": {
     "ordinaryEmployees": "Ordinary employees",

+ 2 - 1
fhKeeper/formulahousekeeper/timesheet/src/i18n/zh.json

@@ -28,7 +28,8 @@
     "roleRightsManagement": "角色权限管理",
     "projectFormSettings": "项目表单设置",
     "budgetReview":"预估工时审核",
-    "gongshitongji":"工时统计表"
+    "gongshitongji":"工时统计表",
+    "caiwushenhe":"财务审核"
   },
   "role": {
     "ordinaryEmployees": "普通员工",

+ 16 - 0
fhKeeper/formulahousekeeper/timesheet/src/routes.js

@@ -93,6 +93,9 @@ import projectForm from './views/project/projectForm'
 // 预算工时审核
 import budgetReview from './views/project/budgetReview'
 
+// 财务审核
+import financeAudit from './views/financeAudit/financeAudit.vue'
+
 Vue.use(Router)
 
 export const fixedRouter = [
@@ -457,6 +460,19 @@ export const allRouters = [//组织架构
         // 其他信息
         meta: { text: 'navigation.approvalFlowSettings' } 
     },
+    {
+        
+        path: '/',
+        component: Home,
+        name: '财务报告审核',
+        iconCls: 'iconfont firerock-iconcaiwu',
+        leaf: true,//只有一个节点
+        children: [
+            { path: '/financeAudit', component: financeAudit, name: '财务报告审核' },
+        ],
+        // 其他信息
+        meta: { text: 'navigation.caiwushenhe' } 
+    },
     //设置时间类型
     // {
         

+ 5 - 2
fhKeeper/formulahousekeeper/timesheet/src/views/Home.vue

@@ -193,8 +193,8 @@
 
             <section class="content-container">
                 <div class="contentMask" v-if="vTourFlg"></div>
-                <div class="grid-content bg-purple-light">
-                    <el-col :span="24" class="content-wrapper">
+                <div class="grid-content h-full bg-purple-light">
+                    <el-col :span="24" class="content-wrapper h-full">
                         <transition name="fade" mode="out-in">
                             <router-view></router-view>
                         </transition>
@@ -1127,6 +1127,9 @@
             top: 60px;
             bottom: 0px;
             overflow: hidden;
+            .h-full {
+                height: 100%;
+            }
             aside {
                 flex: 0 0 230px;
                 width: 230px;

+ 212 - 0
fhKeeper/formulahousekeeper/timesheet/src/views/financeAudit/financeAudit.vue

@@ -0,0 +1,212 @@
+<template>
+    <div class='financeAudit'>
+        <div class="fAd_hrader">
+            <div class="items">
+                <div class="label">年月:</div>
+                <div class="value">
+                    <el-date-picker v-model="tableForm.dates" type="monthrange" range-separator="至" start-placeholder="开始日期"
+                        @change="getFinanceAuditTableData()" size="small" value-format="yyyy-MM" end-placeholder="结束日期" :clearable="false">
+                    </el-date-picker>
+                </div>
+            </div>
+            <div class="items">
+                <div class="label">审核状态:</div>
+                <div class="value">
+                    <el-select v-model="tableForm.status" placeholder="请选择" size="small"
+                        @change="getFinanceAuditTableData()">
+                        <el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value">
+                        </el-option>
+                    </el-select>
+                </div>
+            </div>
+        </div>
+        <div class="fAd_content">
+            <el-table :data="financeAuditTableData" border style="width: 100%;height: 100%;"
+                v-loading="allLoading.tableLoading">
+                <el-table-column prop="reportYrmnth" label="日报年月" align="center">
+                    <template slot-scope="scope">
+                        <el-button type="text" @click="toDetail(scope.row)">{{ scope.row.reportYrmnth }}</el-button>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="reviewerName" label="审核人" align="center"></el-table-column>
+                <el-table-column prop="reviewTime" label="审核时间" align="center"></el-table-column>
+                <el-table-column prop="reviewStatus" label="状态" align="center">
+                    <template slot-scope="scope">
+                        {{ scope.row.reviewStatus == 1 ? '未审核' : '已审核' }}
+                    </template>
+                </el-table-column>
+                <el-table-column label="操作" align="center" fixed="right">
+                    <template slot-scope="scope">
+                        <el-button @click="audit(scope.row)" type="text" v-if="scope.row.reviewStatus == 1">审核</el-button>
+                        <el-button type="text" @click="toDetail(scope.row)">查看详情</el-button>
+                    </template>
+                </el-table-column>
+            </el-table>
+        </div>
+        <div class="fAd_footer">
+            <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
+                :current-page="paging.pageIndex" :page-sizes="[50, 100, 200, 500]" :page-size="paging.pageSize"
+                layout="total, prev, pager, next, sizes" :total="paging.total">
+            </el-pagination>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    name: '',
+    components: {},
+    props: {},
+    data() {
+        return {
+            tableForm: {
+                dates: [],
+                status: 0,
+            },
+            financeAuditTableData: [],
+            statusOptions: [
+                { value: 0, label: '全部' },
+                { value: 1, label: '未审核' },
+                { value: 2, label: '已审核' },
+            ],
+            paging: {
+                pageSize: 50,
+                pageIndex: 1,
+                total: 0
+            },
+            allLoading: {
+                tableLoading: false
+            }
+        }
+    },
+    computed: {},
+    watch: {},
+    created() { },
+    mounted() {
+        let firstMonth = this.dayjs().startOf('year').format('YYYY-MM')
+        let currentMonth = this.dayjs().format('YYYY-MM')
+        this.tableForm.dates = [firstMonth, currentMonth]
+        this.getFinanceAuditTableData()
+    },
+    methods: {
+        toDetail(item) {
+            this.$router.push({
+                path: '/cost',
+                query: {
+                    startDate: item.reportYrmnth,
+                    endDate: item.reportYrmnth
+                }
+            })
+        },
+        audit(item) {
+            this.$confirm(`您确定要审核通过${item.reportYrmnth}月的工时报告吗?`, '财务审核提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning'
+            }).then(() => {
+                this.postData('/financial-audit/audit', { id: item.id }).then(res => {
+                    this.$message({
+                        type: 'success',
+                        message: '审核成功!'
+                    });
+                    this.getFinanceAuditTableData();
+                });
+            }).catch(() => {});
+        },
+        getFinanceAuditTableData() {
+            this.allLoading.tableLoading = true
+            let param = {
+                pageSize: this.paging.pageSize,
+                pageIndex: this.paging.pageIndex,
+                startDate: this.tableForm.dates[0] + '-01' || '',
+                endDate: this.tableForm.dates[1] + '-01' || '',
+                status: this.tableForm.status,
+            }
+            this.postData('/financial-audit/list', param).then(({ data }) => {
+                const { total, records } = data
+                this.financeAuditTableData = records
+                this.paging.total = total
+            }).finally(() => {
+                this.allLoading.tableLoading = false
+            })
+        },
+        handleSizeChange(val) {
+            this.paging.pageSize = val
+            this.paging.pageIndex = 1
+            this.getFinanceAuditTableData()
+        },
+        handleCurrentChange(val) {
+            this.paging.pageIndex = val
+            this.getFinanceAuditTableData()
+        },
+        // 单独封装请求
+        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)
+                    }
+                )
+            });
+        }
+    },
+}
+</script>
+<style scoped lang='scss'>
+* {
+    box-sizing: border-box;
+}
+
+.financeAudit {
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+
+    .fAd_hrader {
+        background-color: #F2F2F2;
+        padding: 10px 15px;
+        display: flex;
+
+        .items {
+            display: flex;
+            align-items: center;
+            margin-right: 20px;
+
+            &:last-child {
+                margin-right: 0;
+            }
+
+            .label {
+                margin-right: 10px;
+            }
+        }
+    }
+
+    .fAd_content {
+        flex: 1;
+    }
+
+    .fAd_footer {
+        background: #F2F2F2;
+        padding: 10px 20px;
+        display: flex;
+        justify-content: flex-end;
+    }
+}
+</style>

+ 5 - 0
fhKeeper/formulahousekeeper/timesheet/src/views/project/cost.vue

@@ -1472,6 +1472,11 @@
                 }
                 this.exportParam.dateRange = this.dateRange;
             }
+            if(this.$route.query && this.$route.query.endDate && this.$route.query.startDate) {
+                const { endDate, startDate } = this.$route.query
+                const lastDay = this.dayjs(`${endDate}-01`).endOf('month').format('YYYY-MM-DD');
+                this.dateRange = [startDate+'-01', lastDay];
+            }
             this.radio = this.$t('other.project')
             this.getEchart();
             var _this = this;

+ 37 - 53
fhKeeper/formulahousekeeper/timesheet/src/views/project/list.vue

@@ -268,46 +268,12 @@
 
             <el-table-column prop="participator" :label="$t('participants')" :min-width="user.company.packageCustomer != 1 ? '100' : '300'" sortable v-if="user.company.packageProject==0">
                 <template slot-scope="scope">
-                    <!-- <v-for v-for="par in scope.row.participator" :key="par.id" >
-                        <el-link style="margin-right:10px;" type="primary" @click="showUser(par.id)">{{par.name}}</el-link>
-                    </v-for> -->
-                    <div v-if="scope.row.participator.length > 5">
-                        <el-popover placement="top" width="500" trigger="hover" v-if="scope.row.participator.length > 0">
-                            <span v-for="par in scope.row.participator" :key="par.id">
-                                <el-link style="margin-right:10px;" :underline="false" type="primary" @click="showUser(par.id)">
-                                    <span v-if="user.userNameNeedTranslate != 1">
-                                        {{par.name}}
-                                    </span>
-                                    <span v-if="user.userNameNeedTranslate == 1">
-                                        <TranslationOpenDataText type='userName' :openid='par.name'></TranslationOpenDataText>
-                                    </span>
-                                </el-link>
-                            </span>
-                            <div slot="reference" class="addss">
-                                <span v-for="par in scope.row.participator" :key="par.id">
-                                    <el-link style="margin-right:10px;" :underline="false" type="primary" @click="showUser(par.id)">
-                                        <span v-if="user.userNameNeedTranslate != 1">
-                                            {{par.name}}
-                                        </span>
-                                        <span v-if="user.userNameNeedTranslate == 1">
-                                            <TranslationOpenDataText type='userName' :openid='par.name'></TranslationOpenDataText>
-                                        </span>
-                                    </el-link>
-                                </span>
-                            </div>
-                        </el-popover>
-                    </div>
-                    <div v-else>
-                        <span v-for="par in scope.row.participator" :key="par.id" >
-                            <el-link style="margin-right:10px;" type="primary" :underline="false" @click="showUser(par.id)" v-if="user.userNameNeedTranslate != 1">
-                                {{par.name}}
-                            </el-link>
-                            <el-link style="margin-right:10px;" type="primary" :underline="false" @click="showUser(par.id)" v-if="user.userNameNeedTranslate == 1">
-                                <TranslationOpenDataText type='userName' :openid='par.name'></TranslationOpenDataText>
-                            </el-link>
-                        </span>
-                    </div>
-                    
+                    <span v-if="(scope.row.participator || []).length > 0">
+                        <el-link type="primary" @click="showAllparticipator(scope.row)">
+                            <TranslationOpenDataText type='userName' :openid='scope.row.participator[0].name'></TranslationOpenDataText>
+                            <span v-if="scope.row.participator.length > 1">...</span>
+                        </el-link>
+                    </span>
                 </template>
             </el-table-column>
             <!-- 客户管理 -->
@@ -505,13 +471,13 @@
                             </el-select>
                         </div>
                     </el-form-item>
-
                     <el-form-item :label="$t('subordinatedepartments')" :prop="user.companyId == 936 ? 'deptId' : false" :class="title == $t('newproject') && user.companyId == 936 ? 'wpgCssClass' : ''" v-if="user.timeType.projectWithDept">
                         <el-cascader v-model="addForm.deptId" :options="departmentList" :placeholder="$t('defaultText.pleaseChoose')" :disabled="canOnlyModParticipator"
                             :props="{ checkStrictly: true, expandTrigger: 'hover' }" clearable filterable @change="cascaderChange" style="width: 100%"
-                            v-if="user.userNameNeedTranslate != 1">
+                            v-if="user.userNameNeedTranslate != 1"
                         ></el-cascader>
-                        <vueCascader :size="'medium'" :widthStr="'430'" :filterable="true" :clearable="true" :subject="departmentList" :subjectId="addForm.deptId" :radios="true" :distinction="'20'" :disabled="canOnlyModParticipator" @vueCasader="vueCasader" v-if="user.userNameNeedTranslate == 1" ></vueCascader>
+                        <!-- <vueCascader :size="'medium'" :widthStr="'430'" :filterable="true" :clearable="true" :subject="departmentList" :subjectId="addForm.deptId" :radios="true" :distinction="'20'" :disabled="canOnlyModParticipator" @vueCasader="vueCasader" v-if="user.userNameNeedTranslate == 1" ></vueCascader> -->
+                        <vueCascadeSelection v-model="addForm.deptId" :options="departmentList" :props="{ checkStrictly: true, expandTrigger: 'hover' }" :disabled="canOnlyModParticipator" v-if="user.userNameNeedTranslate == 1"></vueCascadeSelection>
                     </el-form-item>
 
                     <!-- 供应商 -->
@@ -543,25 +509,25 @@
                     </el-form-item> -->
                     <el-form-item :label="$t('Allparticipants')" v-show="addForm.isPublic == 0" :class="title == $t('newproject') && user.companyId == 936 ? 'wpgCssClass' : ''">
                         <el-tooltip placement="top" effect="light" v-if="user.userNameNeedTranslate != 1">
-
                             <div slot="content" style="width:780px">{{addForm.userNames}}</div>
                             <el-input  @focus="showChooseMembTree" v-model="addForm.userNames"></el-input>
                         </el-tooltip>
 
                         <el-tooltip placement="top" effect="light" v-if="user.userNameNeedTranslate == 1">
-                            <div slot="content" style="width:780px">
+                            <div slot="content" style="max-width: 780px;max-height: 400px;overflow-y: auto;">
                                 <span v-for="(item, index) in addFormUserNames" :key="index">
-                                    <!-- {{item}} -->
                                     <TranslationOpenDataText type='userName' :openid='item'></TranslationOpenDataText>
                                     <span v-if="index < addFormUserNames.length - 1">,</span>
                                 </span>
                             </div>
                             <div @click="showChooseMembTree" style="width: 800px;overflow:hidden;white-space:nowrap;height:40px;border: 1px solid #DCDFE6;border-radius: 4px;box-sizing: border-box;padding: 0 10px">
-                                <span v-for="(item, index) in addFormUserNames" :key="index">
-                                    <!-- {{item}} -->
-                                    <TranslationOpenDataText type='userName' :openid='item'></TranslationOpenDataText>
-                                    <span v-if="index < addFormUserNames.length - 1">,</span>
-                                </span>
+                                <template v-for="(item, index) in addFormUserNames">
+                                    <template v-if="index <= 13">
+                                        <TranslationOpenDataText type='userName' :openid='item'></TranslationOpenDataText>
+                                        <span v-if="index < addFormUserNames.length - 1">,</span>
+                                        <span v-if="(addFormUserNames || []).length > 13 && index == 13">...</span>
+                                    </template>
+                                </template>
                             </div>
                         </el-tooltip>
                     </el-form-item>
@@ -572,7 +538,7 @@
                                 <span style="float: right; color: #8492a6;" v-if="user.companyId == 936">{{ item.jobNumber }}</span>
                             </el-option>
                         </el-select>
-                        <selectCat v-if="user.userNameNeedTranslate == 1" :size="'medium'" :subject="participator" :subjectId="addForm.inchargerId" :distinction="'3'" @selectCal="selectCal" :disabled="canOnlyModParticipator || projectManagerEdit || isShowProjectName"></selectCat>
+                        <selectCat v-if="user.userNameNeedTranslate == 1" :filterable="true" :size="'medium'" :subject="participator" :subjectId="addForm.inchargerId" :distinction="'3'" @selectCal="selectCal" :disabled="canOnlyModParticipator || projectManagerEdit || isShowProjectName"></selectCat>
                     </el-form-item>
 
                     <span v-if="user.companyId != 469">
@@ -1749,6 +1715,15 @@
                 </div>
             </el-dialog>
         </el-dialog>
+
+        <!-- 参与人 -->
+        <el-dialog :title="participatorVisibleTitle" :visible.sync="participatorVisible" width="50%" :before-close="handleClose">
+            <div>
+                <el-link type="primary" style="margin-right:10px;" v-for="(item, index) in participatorValue" :key="index" @click="showUser(item.id)">
+                    <TranslationOpenDataText type='userName' :openid='item.name'></TranslationOpenDataText>
+                </el-link>
+            </div>
+        </el-dialog>
     </section>
 </template>
 <style scoped>
@@ -1784,11 +1759,13 @@ a {
     // 自定义select组件
     import selectCat from "@/components/select.vue"
     import vueCascader from "@/components/cascader.vue"
+    import vueCascadeSelection from "@/components/cascadeSelection.vue"
     export default {
         components:{
             projectgantt,
             selectCat,
             vueCascader,
+            vueCascadeSelection
         },
         data() {
             return {
@@ -2057,6 +2034,8 @@ a {
                 setTemplateDialog: false,
                 selectedGroup:{},
                 changeParticipation:false,
+                participatorVisible: false,
+                participatorValue: []
             };
         },
         // 过滤器
@@ -2108,6 +2087,11 @@ a {
             })
         },
         methods: {
+            showAllparticipator(item) {
+                this.participatorVisibleTitle = item.projectName + ' -- 参与人'
+                this.participatorValue = item.participator || []
+                this.participatorVisible = true
+            },
             // 批量导入任务
             importTask(item) {
                 //首先判断文件类型
@@ -4690,7 +4674,7 @@ a {
                         var findUser = list[0];    
                         this.participator.push(findUser);
                     } else {
-                        console.log('未找到用户: '+u);
+                        // console.log('未找到用户: '+u);
                     }
                     
                 })

+ 18 - 3
fhKeeper/formulahousekeeper/timesheet/src/views/settings/timetype.vue

@@ -224,9 +224,15 @@
                             <el-option v-for="item in alertDayRange" :label="item" :value="item" :key="item"></el-option>
                         </el-select>
                         号)</span>
+                        <span v-if="timeType.alertType == 4" style="color:#606266;">(每
+                        <el-select v-model="timeType.alertDay" style="width:80px;">
+                            <el-option v-for="item in alertWeekDayRange" :label="item.label" :value="item.value" :key="item.value"></el-option>
+                        </el-select>
+                        提醒)</span>
                     </el-form-item>
-                    <el-form-item v-if="timeType.alertType != 3" :label="$t('remindertext')" prop="alertMsg" style="width: 50%;margin-left:10px;">
-                            <el-input :placeholder="$t('peaseenterthe')" v-model="timeType.alertMsg" clearable class="apu" maxlength="20"></el-input>
+                    <el-form-item v-if="timeType.alertType != 3" :label="$t('remindertext')" prop="alertMsg" style="margin-left:10px;">
+                            <el-input :placeholder="$t('peaseenterthe')" v-model="timeType.alertMsg" clearable class="apu" maxlength="50"></el-input>
+                            <span v-if="timeType.alertType == 4" style="color:orange;margin-left:10px;">(可用{0}表示漏填日期,例如:{0}将被替换为05/24,05/25。)</span>
                     </el-form-item>
                     
                     </el-form>
@@ -256,6 +262,14 @@
                                     end: '23:30'
                                     }">
                                 </el-time-picker>
+                                <span v-if="timeType.alertType == 4" style="color:#606266;margin-left:20px;">(每
+                                <el-select v-model="timeType.alertCheckDay" style="width:80px;">
+                                    <el-option v-for="item in alertWeekDayRange" :label="item.label" :value="item.value" :key="item.value"></el-option>
+                                </el-select>
+                                提醒)<span style="margin-left:20px;">提醒文本</span>
+                                <el-input :placeholder="$t('peaseenterthe')" v-model="timeType.alertCheckMsg" clearable class="apu" maxlength="50"></el-input>
+                                <span style="color:orange;margin-left:10px;">(可用{0}表示待审核条数,例如:{0}将被替换为10。)</span>
+                            </span>
                         </div>
 
                     </div>
@@ -789,6 +803,7 @@
                     onNextStep: this.myCustomNextStepCallback
                 },
                 alertDayRange: ['1','2','3','4','5','6','7','8','9','10','11','12','13','14','15'],
+                alertWeekDayRange: [{value:1,label:'周一'},{value:2,label:'周二'},{value:3,label:'周三'},{value:4,label:'周四'},{value:5,label:'周五'}],
                 pushParam:{
                     day:'05',
                     hour:'01',
@@ -1874,7 +1889,7 @@
     box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04)
 }
 .underpanel{
-    width: 900px;
+    // width: 900px;
     // height: 140px;
     border-top: 1px solid #eee;
     position: relative;

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

@@ -14,7 +14,9 @@
                             <span v-for="(item,index) in allDate" :id="'day'+index" class="date_item"
                             @click="choseDate(index, item)" :key="index" :style="'padding:0 6px;display: inline-block;width: 55px;text-align: center;' + (canClick(index,item) == false && user.timeType.fillAhead == 0 ? 'color:#c0c0c0;cursor:not-allowed;' : '') ">
                             <div :style="'display:inline-block;text-align: center;'+(item.state == null?'':'')" >
-                                <div style="text-align:center;"><span :class="statusStyle[item.state]">{{item.showDate}}</span>
+                                <div style="text-align:center;">
+                                    <span v-if="item.missReport" class="RejectStyle">{{item.showDate}}</span>
+                                    <span v-else :class="statusStyle[item.state]">{{item.showDate}}</span>
                                 <br>
                                 <span style="font-size:10px;text-align:center;color:#999;">{{item.weekDay}}</span>
                                 <span class="chooseDate" v-if="index == choseDay"></span>
@@ -22,6 +24,9 @@
                                 <el-tooltip v-if="user.companyId == 5978 && item.exceedCardTime == 1" effect="dark" content="填报时长异常" placement="top-start">
                                 <i class="el-icon-warning" style="color:red;"></i>
                                 </el-tooltip>
+                                <el-tooltip v-if="item.missReport" effect="dark" content="漏填" placement="top-start">
+                                <i class="el-icon-warning" style="color:red;"></i>
+                                </el-tooltip>
                                 </div>
                             </div>
                             </span>
@@ -133,7 +138,10 @@
                                     <el-link v-if="reportTimeType.type != 0 && user.companyId != yuzhongCompId && user.timeType.enableNewWeeklyfill != 1 && user.companyId != 3092" type="primary" style="margin-right:10px;" :underline="false" @click="isSubstitude=false;fillInReportss()">{{$t('textLink.fillInAWeek')}}</el-link>
                                     <el-link v-if="user.timeType.enableNewWeeklyfill == 1" type="primary" style="margin-right:10px;" :underline="false" @click="isSubstitude=false;fillInReportCustom()">按周填报</el-link>
                                     <!-- <el-link type="primary" style="margin-right:10px;" :underline="false" @click="isSubstitude=false;fillInReportCustom()">按周填报</el-link> -->
-                                    <el-link type="primary" v-if="permissions.reportsFillOut && user.timeType.enableNewWeeklyfill != 1" style="margin-right:10px;" :underline="false" @click="isSubstitude=true; fillInReport(-1,2)">{{$t('textLink.helpToFillIn')}}</el-link>
+                                    <el-link type="primary" v-if="user.companyId != 5978 && permissions.reportsFillOut && user.timeType.enableNewWeeklyfill != 1" style="margin-right:10px;" :underline="false" @click="isSubstitude=true; fillInReport(-1,2)">{{$t('textLink.helpToFillIn')}}</el-link>
+                                    <!-- 苏州景昱,按周填报的模式进行代填日报 -->
+                                    <el-link type="primary" v-if="user.companyId == 5978 && permissions.reportsFillOut && user.timeType.enableNewWeeklyfill != 1" style="margin-right:10px;" :underline="false" @click="isSubstitude=true; fillInReportss();">{{$t('textLink.helpToFillIn')}}</el-link>
+                                    
                                     <el-link type="primary" v-if="permissions.reportBatch && user.timeType.enableNewWeeklyfill != 1" style="margin-right:10px;" :underline="false" @click="isSubstitude=false;fillInReport(-1,1)">{{$t('textLink.batchFillIn')}}</el-link>
                                     <el-link type="primary" v-if="user.companyId != yuzhongCompId && (permissions.importReport || user.manageDeptId != 0)" style="margin-right:10px;" :underline="false" @click="imports()">{{$t('textLink.workHoursImport')}}</el-link>
                                     <el-link type="primary" style="margin-right:10px;" :underline="false" @click="showExportDialog" v-if="permissions.reportExport">{{$t('textLink.exportWork')}}</el-link>
@@ -143,7 +151,6 @@
                                     <el-link type="primary" v-if="user.timeType.pushReportData == 1 && user.companyId==3092 && permissions.reportPush" :underline="false" @click="pushWorkTimeLogDig=true,getPushWorkLogData()">工时推送日志</el-link>
                                     <el-link type="primary" v-if="user.roleName == '超级管理员' && user.companyId==839" :underline="false" @click="reportLogCheckDialog=true">日报审核修改</el-link>
                                     <!-- <el-button v-if="user.timeType.pushReportData == 1 && permissions.reportPush" style="margin-left:10px;" icon="iconfont firerock-icontuisong" size="mini" @click="pushWorkTime"></el-button> -->
-
                                 </span>
                             </div>
                             <div :style="'height:'+(tableHeight-50)+'px;overflow:scroll;padding-top:10px;'">
@@ -935,6 +942,7 @@
 
         <!-- 按周填报 -->
         <el-dialog :title="$t('textLink.fillInAWeek')" :visible.sync="fillWeekDialogVisi" width="1200px" :close-on-click-modal="false" @closed="guanbi(),closeAddWeeklyReport()">
+            
             <!-- 按周填报-已填工时-点击 -->
             <el-dialog append-to-body :title="$t('lable.filledReport')" :visible.sync="weeklyFilledTimeDialog" width="50%" :close-on-click-modal="false">
                 <el-table :data="weeklyFilledTimeList" v-loading="weeklyFilledTimeLoading">
@@ -943,24 +951,33 @@
                     <el-table-column prop="state" :label="$t('state.states')">
                         <template slot-scope="scope">{{workReportStateString[scope.row.state]}}</template>
                     </el-table-column>
-                    <!-- <el-table-column label="操作">
-                        <template slot-scope="scope">
-                            <el-button v-if="scope.row.state == 2 || scope.row.state == 3" size="small" @click="weeklyFilledTimeDelete(scope.row)">删除</el-button>
-                        </template>
-                    </el-table-column> -->
                 </el-table>
                 <span slot="footer" class="dialog-footer">
                     <el-button @click="weeklyFilledTimeDelete()" size="small" type="danger" v-if="weeklyFilledTimeCanDelete">{{$t('btn.delete')}}</el-button>
                 </span>
             </el-dialog>
-            <el-form ref="WeekWorkForm" :model="workForm" :rules="workRules" label-width="100px">
+            <div v-if="isSubstitude && substitudeStep == 1" style="width:300px;margin:0 auto;" >
+                <el-input v-if="user.userNameNeedTranslate != 1" @focus="showChooseMembTree" v-model="workForm.userNames" size="small"
+                        :placeholder="$t('defaultText.pleaseSelectAsubstitute')" ></el-input>
+                <div  @click="showChooseMembTree" v-if="user.userNameNeedTranslate == 1" >
+                    <span class="spnn" v-if="workForm.userNames">
+                        <span v-for="(item, index) in workForm.userNames" :key="index">
+                            <span><TranslationOpenDataText type='userName' :openid='item'></TranslationOpenDataText></span>
+                            <span v-if="index < workForm.userNames.length - 1">,</span>
+                        </span>
+                    </span>
+                    <span class="spnn hover" v-else>
+                        {{$t('defaultText.pleaseSelectAsubstitute')}}
+                    </span>
+                </div>
+                <el-button @click="substitudeStep = 2; getCurrentWeek();" style="margin-top:10px;margin-left:100px" type="primary">下一步</el-button>    
+            </div>
+            <el-form ref="WeekWorkForm" :model="workForm" :rules="workRules" label-width="100px" v-if="!isSubstitude || (substitudeStep == 2 && isSubstitude && workForm.userNames && workForm.userNames.length>0)">
                 <el-form-item style="height:30px;margin-top:-72px;">
                      <!-- <el-date-picker v-model="weekDateRange" size="small" format="yyyy-MM-dd" value-format="yyyy-MM-dd" @change="initWeekFormData()" type="daterange" :range-separator="$t('other.to')" :start-placeholder="$t('time.startDate')" :end-placeholder="$t('time.endDate')" style="margin-right: 18px" :clearable="false"></el-date-picker> -->
                      <el-button @click="handleGetPrevWeek()" size="small">&lt;&lt;</el-button>
                      <el-button @click="getCurrentWeek()" size="small">{{$t('time.thisWeek')}}</el-button>
                      <el-button @click="handleGetNextvWeek()" size="small">&gt;&gt;</el-button>
-                     <!-- <el-button @click="newDates()" size="small">{{$t('time.addedDate')}}</el-button> -->
-                     
                      <el-select v-model="selCon" size="small" multiple :placeholder="$t('defaultText.pleaseChoose')" @change="onSelProjectChange()" filterable style="margin-right:50px;float:right;width:50%;" collapse-tags>
                         <el-option
                         v-for="item in fillProjectList"
@@ -1024,7 +1041,8 @@
                 </el-table>
             </el-form>
 
-            <span slot="footer" class="dialog-footer" >
+            <span slot="footer" class="dialog-footer" v-if="!isSubstitude || substitudeStep == 2">
+                <span v-if="isSubstitude" style="float:left;color:orange;">*正在为【{{workForm.userNames}}】代填</span>
                 <!-- <el-button @click="zhoAddlast()" style="float:left;" class="el-icon-back">{{$t('defaultText.selectProject')}}</el-button> -->
                 <el-button @click="closeAddWeeklyReport()" :loading="submitingReport">{{$t('btn.cancel')}}</el-button>
                 <el-button @click="submitWeekReport(1)" :loading="submitingReport" >{{$t('btn.temporaryStorage')}}</el-button>
@@ -1436,7 +1454,7 @@
             <div style="float: left; height:32px; padding-top:10px;">
               <span style="width:20px;height:20px;background-color: orange;padding:5px 8px;">待审核</span>
               <span style="width:20px;height:20px;background-color: #32CD32;padding:5px 8px;margin-left:10px;">已通过</span>
-              <span style="width:20px;height:20px;background-color: red;padding:5px 8px;margin-left:10px;">已驳回</span>
+              <span style="width:20px;height:20px;background-color: red;padding:5px 8px;margin-left:10px;">已驳回/漏填</span>
               <span style="width:20px;height:20px;background-color: #E0E0E0;padding:5px 8px;margin-left:10px;">未提交</span>
             </div>
             <div style="float: right; vertical-align: middle;height:32px">
@@ -2173,6 +2191,7 @@
         },
         data() {
             return {
+                substitudeStep: 1,
                 showHidden: false,
                 pageIndex: 0,
                 hasMore: true,
@@ -2578,23 +2597,22 @@
                     const times = this.reportTimeType.allday
                     const filterData = worktimeList.filter(item => item.createDate == dateSingle)
 
-                    const isWorkDate = filterData[0] && filterData[0].workingTime
+                    const isWorkDate = filterData[0] && filterData[0].workingTime;
+                    const missReport = filterData[0] && filterData[0].missReport;
                     const state = filterData[0] && filterData[0].state
-                    if (state == 0 || state == -1) {
-                        return "backgroundColor: orange"
-                    } else if (state == 1) {
-                        //审核通过
-                        return "backgroundColor: #32CD32"
-                    } else if (state == 2) {
+                    if (missReport) {
                         return "backgroundColor: red"
                     } else {
-                        return "backgroundColor: #E0E0E0"
-                        // if(isWorkDate < times) {
-                        //     return "backgroundColor: #FC3D49"
-                        // }
-                        // if(isWorkDate > times) {
-                        //     return "backgroundColor: #20a0ff"
-                        // }
+                        if (state == 0 || state == -1) {
+                            return "backgroundColor: orange"
+                        } else if (state == 1) {
+                            //审核通过
+                            return "backgroundColor: #32CD32"
+                        } else if (state == 2) {
+                            return "backgroundColor: red"
+                        } else {
+                            return "backgroundColor: #E0E0E0"
+                        }
                     }
                     
                 }
@@ -4545,6 +4563,7 @@
                                     }
                                     if (d1 == d2) {
                                         d.state = s.state;
+                                        d.missReport = s.missReport;//是否漏填
                                         d.exceedCardTime = s.exceedCardTime
                                     }
                                 })
@@ -5883,11 +5902,18 @@
                         type: "error"
                     });
                 } else {
+                    const loading = this.$loading({
+                        lock: true,
+                        text: '正在导入修改中,请耐心等待。',
+                        spinner: 'el-icon-loading',
+                        background: 'rgba(0, 0, 0, 0.7)'
+                    });
                     let formData = new FormData();
                     formData.append("multipartFile", item.file);
                     this.http.uploadFile('/report-log/importReportLogChange', formData,
                     res => {
                         this.$refs.upload.clearFiles();
+                        loading.close();
                         if (res.code == "ok") {
                             this.$message({
                             message: res.msg,
@@ -5902,6 +5928,7 @@
                     },
                     error => {
                         this.$refs.upload.clearFiles();
+                        loading.close();
                         this.$message({
                             message: error,
                             type: "error"
@@ -6615,8 +6642,14 @@
             fillInReportss() {
                 window.addEventListener('scroll', this.handleScroll, true)
                 // this.jiazai()
-                this.fillWeekDialogVisi = true
-                this.getCurrentWeek();
+                this.fillWeekDialogVisi = true;
+                if (this.isSubstitude) {
+                    this.substitudeStep = 1;
+                    this.getSubstitudeUserDeptList();
+                } else {
+                    this.getCurrentWeek();
+                }
+                
                 if (!this.timeBasecostList || this.timeBasecostList.length == 0) {
                     //重新获取工时预警类型的预算项
                     this.http.post('/project-basecost-setting/getReportBasecostList', {
@@ -6961,9 +6994,14 @@
                 for (var p in this.fillProjectList) {
                     this.fillProjectList[p].canCancel = 1;
                 }
-                this.http.post('/report/getWeeklyReportData',{
+                var param = {
                     targetDate: util.formatDate.format(this.targetWeekDate, "yyyy-MM-dd")
-                },res => {
+                };
+                if (this.isSubstitude) {
+                    //传代填人的userId
+                    param.targetUserId = this.workForm.userId[0];
+                }
+                this.http.post('/report/getWeeklyReportData',param,res => {
                     this.weekDataLoading = false;
                     if(res.code == 'ok'){
                         let projectList = res.data.projectList;
@@ -7172,6 +7210,9 @@
                                     flgs = true
                                     // formData.append("degreeId", "-1");
                                     formData.append("id", '-1');
+                                    if (this.isSubstitude) {
+                                        formData.append('targetUids',this.workForm.userId[0]);
+                                    }
                                     for(var s in this.projectList) {
                                         if(j == this.projectList[s].projectName) {
                                             formData.append("projectId", this.projectList[s].id);
@@ -7274,6 +7315,9 @@
                                         flgs = true
                                         // formData.append("degreeId", "-1");
                                         formData.append("id", zhoD[j].id==null?'-1':zhoD[j].id);
+                                        if (this.isSubstitude) {
+                                            formData.append('targetUids',this.workForm.userId[0]);
+                                        }
                                         for(var s in this.projectList) {
                                             if(j == this.projectList[s].projectName) {
                                                 formData.append("projectId", this.projectList[s].id);
@@ -7359,6 +7403,9 @@
                                         // formData.append("degreeId", "-1");
                                         console.log('进入了workFpppp==='+j);
                                         formData.append("id", zhoD[j].id==null?'-1':zhoD[j].id);
+                                        if (this.isSubstitude) {
+                                            formData.append('targetUids',this.workForm.userId[0]);
+                                        }
                                         for(var s in this.projectList) {
                                             if(j == this.projectList[s].projectName) {
                                                 formData.append("projectId", this.projectList[s].id);

+ 49 - 22
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/list_import.vue

@@ -42,7 +42,7 @@
                     <el-button @click="approveAll" style="margin-left:10px;" :disabled="list.length==0" size="small">{{ $t('throughwithoneclick') }}</el-button>
                 </el-form-item>
                 <el-form-item style="margin-left:20px;" v-if="permissions.importAudit">
-                   <el-link type="primary" @click="recordList(),recordDialogVisible = true,pageIndexList = 1,pageSizeList = 20">{{ $t('Auditrecords') }}</el-link>
+                   <el-link type="primary" @click="recordList(),showRecordDialogVisible()">{{ $t('Auditrecords') }}</el-link>
                 </el-form-item>
             </el-form>
         </el-col>
@@ -167,9 +167,9 @@
         </el-col>
 
         <!-- 审核记录弹窗 -->
-        <el-dialog :title="$t('Auditrecords')" :visible.sync="recordDialogVisible" width="800px" :before-close="handleClose">
-            <div style="height: 430px">
-                <el-table :data="recordLists" style="width: 100%" height="400" v-loading="recordLoading">
+        <el-dialog :title="$t('Auditrecords')" :visible.sync="recordDialogVisible" width="80vw" top="7.8vh" :before-close="handleClose">
+            <div style="height: 65vh" ref="recordListsDivRef" v-loading="recordLoading">
+                <el-table :data="recordLists" style="width: 100%;" :height="recordListsTableHeight">
                     <el-table-column prop="userName" :label="$t('other.operator')" width="150">
                         <template slot-scope="scope">
                             <div>
@@ -184,21 +184,21 @@
                         <template slot-scope="scope">
                             <div>
                                 <div v-if="scope.row.membdateList.length > 1">
-                                    <el-popover placement="top" width="400" trigger="hover">
-                                    <div>
-                                        <span v-for="(item, index) in scope.row.membdateList" :key="index">
-                                            <span v-if="user.userNameNeedTranslate == '1'"><TranslationOpenDataText type='userName' :openid='item.userName'></TranslationOpenDataText></span>
-                                            <span v-if="user.userNameNeedTranslate != '1'">{{item.userName}}</span>
-                                            /{{item.createDate}} <span v-if="scope.row.membdateList.length > 1 && scope.row.membdateList.length - 1 != index">,</span>
-                                        </span>
-                                    </div>
-                                    <div slot="reference" style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width: 180px;">
-                                        <span v-for="(item, index) in scope.row.membdateList" :key="index">
-                                            <span v-if="user.userNameNeedTranslate == '1'"><TranslationOpenDataText type='userName' :openid='item.userName'></TranslationOpenDataText></span>
-                                            <span v-if="user.userNameNeedTranslate != '1'">{{item.userName}}</span>
-                                            /{{item.createDate}} <span v-if="scope.row.membdateList.length > 1 && scope.row.membdateList.length - 1 != index">,</span>
-                                        </span>
-                                    </div>
+                                    <el-popover placement="top" width="500" trigger="hover">
+                                        <div class="popoverDiv">
+                                            <div v-for="(item, index) in scope.row.membdateList" :key="index" class="popoverDivItem">
+                                                <span v-if="user.userNameNeedTranslate == '1'"><TranslationOpenDataText type='userName' :openid='item.userName'></TranslationOpenDataText></span>
+                                                <span v-if="user.userNameNeedTranslate != '1'">{{item.userName}}</span>
+                                                /{{item.createDate}}
+                                            </div>
+                                        </div>
+                                        <div slot="reference" style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width: 180px;">
+                                            <span v-for="(item, index) in scope.row.membdateList" :key="index">
+                                                <span v-if="user.userNameNeedTranslate == '1'"><TranslationOpenDataText type='userName' :openid='item.userName'></TranslationOpenDataText></span>
+                                                <span v-if="user.userNameNeedTranslate != '1'">{{item.userName}}</span>
+                                                /{{item.createDate}} <span v-if="scope.row.membdateList.length > 1 && scope.row.membdateList.length - 1 != index">,</span>
+                                            </span>
+                                        </div>
                                     </el-popover>
                                 </div>
                                 <div style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width: 180px;" v-else>
@@ -272,11 +272,23 @@
                 totals: 0,
                 pageIndexList: 1,
                 pageSizeList: 20,
-                recordLoading: false
+                recordLoading: false,
+                recordListsTableHeight: '400'
 
             };
         },
         methods: {
+            showRecordDialogVisible() {
+                this.recordDialogVisible = true
+                this.pageIndexList = 1
+                this.pageSizeList = 20
+                setTimeout(() => {
+                    let element = this.$refs.recordListsDivRef.offsetHeight
+                    this.recordListsTableHeight = element - 55
+                    console.log(this.recordListsTableHeight, '<=== 高度')
+                }, 1000)
+                
+            },
             // 获取审核记录
             recordList() {
                 // this.recordDialogVisible = true
@@ -287,7 +299,9 @@
                     pageSize: this.pageSizeList
                 },
                 res => {
-                    this.recordLoading = false
+                    setTimeout(() => {
+                        this.recordLoading = false
+                    }, 1000)
                     if (res.code == "ok") {
                         console.log(res.data, '数据')
                         this.recordLists = res.data.records
@@ -300,7 +314,9 @@
                     }
                 },
                 error => {
-                    this.recordLoading = false
+                    setTimeout(() => {
+                        this.recordLoading = false
+                    }, 1000)
                     this.$message({
                         message: error,
                         type: "error"
@@ -629,4 +645,15 @@
     padding-left: 20px;
 }
 
+.popoverDiv {
+    display: flex;
+    flex-wrap: wrap;
+    max-height: 400px;
+    overflow-y: auto;
+    .popoverDivItem {
+        width: 33%;
+        text-align: center;
+    }
+}
+
 </style>

+ 1 - 1
fhKeeper/formulahousekeeper/timesheet_h5/src/views/edit/weekEdit.vue

@@ -362,7 +362,7 @@
                                 placeholder="请输入加班时长" style="width: 5rem"></van-field>
                                 <span :class="'overListTime'">小时</span>    
                             </div>
-                            <van-tag v-if="user.companyId != 4281&& isCorpWX&&canEdit"  style="position:absolute;right:10px;" v-if="isCorpWX" type="primary" size="large" @click="takePhoto(index)">拍照上传</van-tag>
+                            <van-tag v-if="user.companyId != 4281&& isCorpWX&&canEdit"  style="position:absolute;right:10px;" type="primary" size="large" @click="takePhoto(index)">拍照上传</van-tag>
                         </div>
                         <div style="padding:5px;text-align:center;" v-if="!isIOSystem">
                             <span v-for="(p, index) in item.pics"  :key="p" style="margin-right:15px;">

+ 11 - 4
fhKeeper/formulahousekeeper/timesheet_h5/src/views/view/calendar.vue

@@ -24,7 +24,7 @@
                 hasWaiting: false,
                 state: 0,
                 user: JSON.parse(localStorage.userInfo),
-                minDate: new Date(2010, 0, 1),
+                minDate: new Date(2020, 0, 1),
                 maxDate: new Date(new Date().getFullYear(),new Date().getMonth()+1,new Date().getDate()),
                 currentDate: new Date(),
                 nowTime: this.format(new Date(new Date()),"yyyy-MM-dd"),
@@ -59,8 +59,13 @@
                 let targetDate = this.format(day.date);
                 this.report.forEach(r=>{
                     if (r.createDate == targetDate) {
-                        day.bottomInfo = this.statusTxt[r.state];
-                        day.className = this.statusStyle[r.state];
+                        if (r.missReport) {
+                            day.bottomInfo = '漏填';
+                            day.className = 'RejectStyle';
+                        } else {
+                            day.bottomInfo = this.statusTxt[r.state];
+                            day.className = this.statusStyle[r.state];
+                        }
                     }
                 })
                 
@@ -110,7 +115,9 @@
                     forbidClick: true,
                     duration: 0
                 });
-                this.$axios.post("/report/getReportFillStatus", {startDate: this.format(this.minDate), endDate:this.format(this.maxDate), userId: this.user.id})
+                var startDate = new Date();
+                startDate.setMonth(startDate.getMonth() -2);
+                this.$axios.post("/report/getReportFillStatus", {startDate: this.format(startDate), endDate:this.format(this.maxDate), userId: this.user.id})
                 .then(res => {
                     if(res.code == "ok") {
                         this.$toast.clear();