Przeglądaj źródła

Merge remote-tracking branch 'origin/master'

ysm 10 miesięcy temu
rodzic
commit
ee56e1ad72
100 zmienionych plików z 35687 dodań i 13535 usunięć
  1. BIN
      fhKeeper/formulahousekeeper/customerBuler-crm/node_modules.zip
  2. 33 3
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/analysis/index.vue
  3. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/index.vue
  4. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/type.d.ts
  5. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/api.ts
  6. 5 5
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/component/information.vue
  7. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/index.vue
  8. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/index.vue
  9. 2 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/detail/components/information.vue
  10. 30882 11721
      fhKeeper/formulahousekeeper/management-crm/crm.log
  11. 70 47
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/BusinessOpportunityController.java
  12. 92 18
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/ClueController.java
  13. 51 57
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/CustomController.java
  14. 45 10
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/SalesOrderController.java
  15. 2 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/BusinessOpportunity.java
  16. 9 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Clue.java
  17. 1 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/ClueService.java
  18. 2 2
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/SalesOrderService.java
  19. 148 78
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/BusinessOpportunityServiceImpl.java
  20. 108 132
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ClueServiceImpl.java
  21. 140 65
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/CustomServiceImpl.java
  22. 16 3
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ProductServiceImpl.java
  23. 56 47
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/SalesOrderServiceImpl.java
  24. 3 3
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/BusinessOpportunityMapper.xml
  25. 6 6
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/ClueMapper.xml
  26. 6 6
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/CustomMapper.xml
  27. 1 1
      fhKeeper/formulahousekeeper/management-platform-import/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  28. 2 2
      fhKeeper/formulahousekeeper/management-platform-import/src/main/resources/application.yml
  29. 28 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java
  30. 34 3
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java
  31. 66 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportWriteOffController.java
  32. 14 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserController.java
  33. 38 236
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserWithBeisenController.java
  34. 10 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Project.java
  35. 66 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ReportWriteOff.java
  36. 1 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/OvertimeListVO.java
  37. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/DepartmentMapper.java
  38. 5 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectMapper.java
  39. 3 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ReportMapper.java
  40. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ReportWriteOffMapper.java
  41. 9 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java
  42. 4 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ReportService.java
  43. 17 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ReportWriteOffService.java
  44. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/UserWithBeisenService.java
  45. 72 79
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DepartmentServiceImpl.java
  46. 207 14
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  47. 135 12
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  48. 26 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportWriteOffServiceImpl.java
  49. 314 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserWithBeisenServiceImpl.java
  50. 9 255
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java
  51. 22 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/DepartmentMapper.xml
  52. 85 27
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml
  53. 58 7
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportMapper.xml
  54. 20 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportWriteOffMapper.xml
  55. 7 7
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/controller/ReportController.java
  56. 29 14
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/controller/WxCorpInfoController.java
  57. 5 0
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/mapper/PlanMapper.java
  58. 5 1
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/mapper/ReportMapper.java
  59. 1 1
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/ReportService.java
  60. 10 5
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/PlanServiceImpl.java
  61. 6 0
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/ProdProcedureServiceImpl.java
  62. 68 28
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  63. 1 0
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java
  64. 23 8
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/task/TimingTask.java
  65. 69 4
      fhKeeper/formulahousekeeper/management-workshop/src/main/resources/mapper/ReportMapper.xml
  66. BIN
      fhKeeper/formulahousekeeper/management-workshop/workshop_print.2024-06-24.log.gz
  67. 3 3
      fhKeeper/formulahousekeeper/timesheet-workshop-h5/src/views/planView/todayPlan/distribution.vue
  68. 53 9
      fhKeeper/formulahousekeeper/timesheet-workshop/src/views/statistic/index.vue
  69. 42 13
      fhKeeper/formulahousekeeper/timesheet-workshop/src/views/workReport/daily.vue
  70. 11 10
      fhKeeper/formulahousekeeper/timesheet/.vscode/settings.json
  71. 1 0
      fhKeeper/formulahousekeeper/timesheet/index.html
  72. 5 0
      fhKeeper/formulahousekeeper/timesheet/src/App.vue
  73. 204 0
      fhKeeper/formulahousekeeper/timesheet/src/components/departmentSelectionPersonnel.vue
  74. 59 0
      fhKeeper/formulahousekeeper/timesheet/src/components/echartsEchar.vue
  75. 18 18
      fhKeeper/formulahousekeeper/timesheet/src/components/taskComponent.vue
  76. 4 0
      fhKeeper/formulahousekeeper/timesheet/src/http.js
  77. 669 6
      fhKeeper/formulahousekeeper/timesheet/src/i18n/en.json
  78. 664 5
      fhKeeper/formulahousekeeper/timesheet/src/i18n/zh.json
  79. 2 2
      fhKeeper/formulahousekeeper/timesheet/src/views/404.vue
  80. 6 7
      fhKeeper/formulahousekeeper/timesheet/src/views/Expire.vue
  81. 36 28
      fhKeeper/formulahousekeeper/timesheet/src/views/Home.vue
  82. 9 9
      fhKeeper/formulahousekeeper/timesheet/src/views/Login.vue
  83. 23 23
      fhKeeper/formulahousekeeper/timesheet/src/views/Register.vue
  84. 17 17
      fhKeeper/formulahousekeeper/timesheet/src/views/awayOffice/awayOffice.vue
  85. 3 22
      fhKeeper/formulahousekeeper/timesheet/src/views/centerManage/centerManage.vue
  86. 25 25
      fhKeeper/formulahousekeeper/timesheet/src/views/contract/index.vue
  87. 87 0
      fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/echartsData.js
  88. 333 177
      fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue
  89. 2 2
      fhKeeper/formulahousekeeper/timesheet/src/views/customer/list.vue
  90. 32 32
      fhKeeper/formulahousekeeper/timesheet/src/views/desktop/detail.vue
  91. 17 17
      fhKeeper/formulahousekeeper/timesheet/src/views/desktop/index.vue
  92. 17 17
      fhKeeper/formulahousekeeper/timesheet/src/views/desktop/unusual.vue
  93. 83 83
      fhKeeper/formulahousekeeper/timesheet/src/views/expense/expense.vue
  94. 20 20
      fhKeeper/formulahousekeeper/timesheet/src/views/financeAudit/financeAudit.vue
  95. 21 21
      fhKeeper/formulahousekeeper/timesheet/src/views/leave/list.vue
  96. 17 17
      fhKeeper/formulahousekeeper/timesheet/src/views/market/list.vue
  97. 7 7
      fhKeeper/formulahousekeeper/timesheet/src/views/message.vue
  98. 18 18
      fhKeeper/formulahousekeeper/timesheet/src/views/profession/list.vue
  99. 6 6
      fhKeeper/formulahousekeeper/timesheet/src/views/project/CostBaseline.vue
  100. 0 0
      fhKeeper/formulahousekeeper/timesheet/src/views/project/budgetReview.vue

BIN
fhKeeper/formulahousekeeper/customerBuler-crm/node_modules.zip


+ 33 - 3
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/analysis/index.vue

@@ -199,7 +199,17 @@ watchEffect(() => {
                   start-placeholder="开始日期"
                   end-placeholder="结束日期"
                 />
-                <el-button size="small" type="primary" @click="select1?.blur">确认</el-button>
+                <el-button
+                  size="small"
+                  type="primary"
+                  @click="
+                    () => {
+                      select1?.blur();
+                      bulletinPrompt.date = 'ignore';
+                    }
+                  "
+                  >确认</el-button
+                >
               </div>
             </el-option>
           </el-select>
@@ -294,7 +304,17 @@ watchEffect(() => {
                       start-placeholder="开始日期"
                       end-placeholder="结束日期"
                     />
-                    <el-button size="small" type="primary" @click="select2?.blur">确认</el-button>
+                    <el-button
+                      size="small"
+                      type="primary"
+                      @click="
+                        () => {
+                          select2?.blur();
+                          summaryPrompt.date = 'ignore';
+                        }
+                      "
+                      >确认</el-button
+                    >
                   </div>
                 </el-option>
               </el-select>
@@ -387,7 +407,17 @@ watchEffect(() => {
                       start-placeholder="开始日期"
                       end-placeholder="结束日期"
                     />
-                    <el-button size="small" type="primary" @click="select3?.blur">确认</el-button>
+                    <el-button
+                      size="small"
+                      type="primary"
+                      @click="
+                        () => {
+                          select3?.blur();
+                          stagePrompt.date = 'ignore';
+                        }
+                      "
+                      >确认</el-button
+                    >
                   </div>
                 </el-option>
               </el-select>

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

@@ -16,7 +16,7 @@
               <el-input v-model="businessOpportunityForm.customerName" clearable placeholder="请输入"></el-input>
             </el-form-item>
             <el-form-item label="联系人">
-              <el-input v-model="businessOpportunityForm.contactPerson" clearable placeholder="请输入"></el-input>
+              <el-input v-model="businessOpportunityForm.contactsName" clearable placeholder="请输入"></el-input>
             </el-form-item>
             <el-form-item label="产品">
               <el-select v-model="businessOpportunityForm.product" placeholder="请选择" clearable>
@@ -242,7 +242,7 @@ const businessOpportunityForm = reactive<businessOpportunityFormType>({
   name: '',
   stageId: '',
   customerName: '',
-  contactPerson: '',
+  contactsName: '',
   product: '',
   inchargerId: '',
   startTime: getFirstDayOfMonth(new Date()),

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

@@ -3,7 +3,7 @@ interface businessOpportunityFormType {
   name: string;
   stageId: string | number;
   customerName: string;
-  contactPerson: string;
+  contactsName: string;
   product: string | number;
   inchargerId: string | number;
   startTime: string | number;

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/api.ts

@@ -45,5 +45,5 @@ export const tableColumns: TableColumn[] = [
 export const paymentStatus = [
     { value: 0, label: '未回款' },
     { value: 1, label: '已回款' },
-    { value: 2, label: '完全回款' },
+    { value: 2, label: '完全回款' },
 ]

+ 5 - 5
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/component/information.vue

@@ -190,7 +190,7 @@ const formItems = reactive([
     { label: '客户名称', key: 'customName', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
     { label: '商机名称', key: 'businessOpportunityName', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
     { label: '订单金额', key: 'price', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
-    { label: '回款状态', key: 'statusValue', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '回款状态', key: 'receivedStatus', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
     { label: '已回款金额', key: 'receivedPayment', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
     { label: '未回款', key: 'unReceivedPayment', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
     { label: '订单类型', key: 'type', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
@@ -200,8 +200,8 @@ const formItems = reactive([
     { label: '负责人', key: 'inchargerName', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
     { label: '创建人', key: 'creatorName', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
     { label: '创建时间', key: 'createTime', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
-    { label: '客户签约人', key: 'customSigner', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
-    { label: '公司签约人', key: 'companySigner', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '客户签约人', key: 'customSignerName', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
+    { label: '公司签约人', key: 'companySignerName', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '48%' },
     { label: '备注', key: 'remark', value: '', labelClass: 'w-[115px] text-right text-gray-500', width: '100%' },
 ])
 
@@ -209,8 +209,8 @@ watchEffect(() => {
     const { data } = props
     info.value = data
     formItems.forEach(item => {
-        if (item.key === 'statusValue') {
-            const status = info.value['status'];
+        if (item.key === 'receivedStatus') {
+            const status = info.value['receivedStatus'];
             item.value = status !== '' && status !== null ? (paymentStatus.find(p => p.value === status)?.label || '') : '';
         } else {
             item.value = info.value[item.key] || '';

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/order/index.vue

@@ -166,7 +166,7 @@ const selectData = reactive({ // 下拉数据
   Personnel: [] as personnelInterface[],
   Customer: [] as any[], // 客户名称
   OrderType: [] as any[], // 订单类型
-  RemittanceStatus: [{ id: 0, name: '已回款' }, { id: 1, name: '未回款' }, { id: 2, name: '已完全回款' }] as any[], // 回款状态
+  RemittanceStatus: [{ id: 0, name: '未回款' }, { id: 1, name: '已回款' }, { id: 2, name: '已完全回款' }] as any[], // 回款状态
   AllProduct: [] as any[] // 所有产品
 })
 const formTablePaging = reactive({ // 分页条件

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/index.vue

@@ -247,7 +247,7 @@ function editProduct(item: any) {
   dialogVisible.editProductVisible = true
   allLoading.generateFormLading = true
   if (item) {
-    genereditForm.value = item
+    genereditForm.value = { ...item, status: String(item.status) }
     allText.editClueText = '编辑产品'
   }
   if (!item) {

+ 2 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/detail/components/information.vue

@@ -209,6 +209,8 @@ function transferBusiness() {
             delete item.id
         })
         let newForm = {
+            clueId: information.value.id,
+            ...generateFormVal.value,
             ...res,
             expectedTransactionDate: res.expectedTransactionDate ? formatDateTime(new Date(res.expectedTransactionDate)) : '',
             businessItemProductList: productTableListData ? JSON.stringify(productTableListData) : []

Plik diff jest za duży
+ 30882 - 11721
fhKeeper/formulahousekeeper/management-crm/crm.log


+ 70 - 47
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/BusinessOpportunityController.java

@@ -6,8 +6,10 @@ import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.management.platform.entity.*;
 import com.management.platform.mapper.BusinessOpportunityMapper;
+import com.management.platform.mapper.ClueMapper;
 import com.management.platform.mapper.SysFormMapper;
 import com.management.platform.mapper.UserMapper;
 import com.management.platform.service.*;
@@ -24,6 +26,7 @@ import org.springframework.web.multipart.MultipartFile;
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.text.SimpleDateFormat;
 import java.util.*;
 
 /**
@@ -41,6 +44,8 @@ public class BusinessOpportunityController {
     private ExcelExportServiceImpl excelExportService;
     @Resource
     private SysFormMapper sysFormMapper;
+    @Resource
+    private ClueMapper clueMapper;
     @Autowired
     private WxCorpInfoService wxCorpInfoService;
     @Resource
@@ -95,61 +100,75 @@ public class BusinessOpportunityController {
         JSONArray configObJSONArray = configOb.getJSONArray("list");
         List<List<String>> dataList=new ArrayList<>();
         List<String> titleList=new ArrayList<>();
+        List<String> modelList=new ArrayList<>();
         for (int i = 0; i < configObJSONArray.size(); i++) {
             JSONObject item = configObJSONArray.getJSONObject(i);
-            titleList.add(item.getString("label"));
+            String type = item.getString("type");
+            if (type.equals("grid")){
+                JSONArray columns = item.getJSONArray("columns");
+                for (int j = 0; j < columns.size(); j++) {
+                    JSONObject columnsJSONObject = columns.getJSONObject(j);
+                    JSONArray listJsonArray = columnsJSONObject.getJSONArray("list");
+                    for (int k = 0; k < listJsonArray.size(); k++) {
+                        JSONObject listJsonArrayJSONObject = listJsonArray.getJSONObject(k);
+                        titleList.add(listJsonArrayJSONObject.getString("label"));
+                        modelList.add(listJsonArrayJSONObject.getString("model"));
+                    }
+                }
+            }
+            else {
+                titleList.add(item.getString("label"));
+                modelList.add(item.getString("model"));
+            }
         }
         dataList.add(titleList);
-        HttpRespMsg msg = list(bo, request);
-        Map<String, Object> msgData = (Map<String, Object>) msg.getData();
-        List<BusinessOpportunity> bos = (List<BusinessOpportunity>) msgData.get("data");
-        for (BusinessOpportunity bo1 : bos) {
+
+        HttpRespMsg respMsg = list(bo,request);
+        Map<String, Object> msgData = (Map<String, Object>) respMsg.getData();
+        List<BusinessOpportunity> list = (List<BusinessOpportunity>) msgData.get("data");
+
+        for (BusinessOpportunity data : list) {
             List<String> item=new ArrayList<>();
-            for (int i = 0; i < configObJSONArray.size(); i++) {
-                JSONObject target = configObJSONArray.getJSONObject(i);
-                if(target.getString("type").equals("grid")){
-                    JSONArray columns = target.getJSONArray("columns");
-                    for (int i1 = 0; i1 < columns.size(); i1++) {
-                        JSONObject columnsJSONObject = columns.getJSONObject(i1);
-                        JSONArray list = columnsJSONObject.getJSONArray("list");
-                        for (int i2 = 0; i2 < list.size(); i2++) {
-                            JSONObject object = list.getJSONObject(i2);
-                            String model = object.getString("model");
-                            String targetName = model.substring(0, 1).toUpperCase() + model.substring(1);
-                            Class<? extends BusinessOpportunity> aClass = bo1.getClass();
-                            String value = String.valueOf(aClass.getMethod("get" + targetName).invoke(bo1)==null?"":aClass.getMethod("get" + targetName).invoke(bo1));
-                            if(model.equals("inchargerId")){
-                                if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
-                                    value = "$userName"+String.valueOf(aClass.getMethod("getInchargerName").invoke(bo1))+"$";
-                                }else {
-                                    value = String.valueOf(aClass.getMethod("getInchargerName").invoke(bo1));
-                                }
-                            }
-                            item.add(value);
-                        }
+            for (int i = 0; i < modelList.size(); i++) {
+
+                String model = modelList.get(i);
+                String targetName = model.substring(0, 1).toUpperCase() + model.substring(1);
+                Class<? extends BusinessOpportunity> aClass = data.getClass();
+                String value = "";
+
+                if(model.equals("inchargerId")){
+                    if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                        value = "$userName"+String.valueOf(aClass.getMethod("getInchargerName").invoke(data))+"$";
+                    }else {
+                        value = String.valueOf(aClass.getMethod("getInchargerName").invoke(data)).equals("null") ? "" :String.valueOf(aClass.getMethod("getInchargerName").invoke(data));
                     }
                 }else {
-                    String model = target.getString("model");
-                    String targetName = model.substring(0, 1).toUpperCase() + model.substring(1);
-                    Class<? extends BusinessOpportunity> aClass = bo1.getClass();
-                    Object o = aClass.getMethod("get" + targetName).invoke(bo1) == null ? "" : aClass.getMethod("get" + targetName).invoke(bo1);
-                    String value = String.valueOf(o);
-                    if(model.equals("inchargerId")){
-                        if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
-                            value = "$userName"+String.valueOf(aClass.getMethod("getInchargerName").invoke(bo1))+"$";
-                        }else {
-                            value = String.valueOf(aClass.getMethod("getInchargerName").invoke(bo1));
-                        }
-                    }
-                    if(model.equals("contactsId")){
-                        if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
-                            value = "$userName"+String.valueOf(aClass.getMethod("getContactsName").invoke(bo1))+"$";
-                        }else {
-                            value = String.valueOf(aClass.getMethod("getContactsName").invoke(bo1));
-                        }
-                    }
-                    item.add(value);
+                    value= String.valueOf(aClass.getMethod("get" + targetName).invoke(data)==null?"":aClass.getMethod("get" + targetName).invoke(data));
                 }
+
+                if(model.equals("contactsId")){
+                    value = String.valueOf(aClass.getMethod("getContactsName").invoke(data));
+                }
+                if(model.equals("customerId")){
+                    value = String.valueOf(aClass.getMethod("getCustomerName").invoke(data));
+                }
+                if(model.equals("expectedTransactionDate")){
+                    Date date = (Date) aClass.getMethod("getExpectedTransactionDate").invoke(data);
+                    // 如果日期不为空,格式化日期
+                    if (date != null) {
+                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+                        value = sdf.format(date);
+                    } else {
+                        value = "";
+                }                }
+                if(model.equals("stageId")){
+                    value = String.valueOf(aClass.getMethod("getStageValue").invoke(data));
+                }
+                if(model.equals("creatorId")){
+                    value = String.valueOf(aClass.getMethod("getCreatorName").invoke(data));
+                }
+
+                item.add(value);
             }
             dataList.add(item);
         }
@@ -217,6 +236,10 @@ public class BusinessOpportunityController {
         HttpRespMsg msg = new HttpRespMsg();
         if (bo.getId() == null){
             //新增
+            if (bo.getClueId()!= null ){
+
+                clueMapper.update(null, new UpdateWrapper<Clue>().eq("id",bo.getClueId()).set("is_bo",1));
+            }
             bo.setCompanyId(user.getCompanyId());
             bo.setCreatorId(user.getId());
             bo.setUserId(user.getId());

+ 92 - 18
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/ClueController.java

@@ -1,20 +1,20 @@
 package com.management.platform.controller;
 
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.management.platform.entity.Clue;
-import com.management.platform.entity.SysDict;
-import com.management.platform.entity.UploadFile;
-import com.management.platform.entity.User;
-import com.management.platform.mapper.ClueMapper;
-import com.management.platform.mapper.SysDictMapper;
-import com.management.platform.mapper.SysFunctionMapper;
-import com.management.platform.mapper.UserMapper;
-import com.management.platform.service.ClueService;
-import com.management.platform.service.SysFunctionService;
-import com.management.platform.service.UserService;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.management.platform.entity.*;
+import com.management.platform.entity.vo.ContactsVo;
+import com.management.platform.mapper.*;
+import com.management.platform.service.*;
 import com.management.platform.util.HttpRespMsg;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 
@@ -53,6 +53,8 @@ public class ClueController {
 
     @Resource
     private SysDictMapper sysDictMapper;
+    @Autowired
+    private ExcelExportService excelExportService;
 
     @RequestMapping("getAll")
     public Object getAll(HttpServletRequest request) {
@@ -116,7 +118,7 @@ public class ClueController {
 
 
     @RequestMapping("listClue")
-    public Object list(Clue clue, HttpServletRequest request) {
+    public HttpRespMsg list(Clue clue, HttpServletRequest request) {
         User user = userMapper.selectById(request.getHeader("Token"));
         clue.setCompanyId(user.getCompanyId());
         clue.setIsDelete(0);
@@ -179,14 +181,86 @@ public class ClueController {
     }
 
     @RequestMapping("/importData")
-    public HttpRespMsg importData(MultipartFile multipartFile){
-        return clueService.importData(multipartFile);
+    public HttpRespMsg importData(MultipartFile multipartFile,HttpServletRequest request){
+        return clueService.importData(multipartFile, request);
     }
-
-
+    @Value(value = "${upload.path}")
+    private String path;
+    @Autowired
+    private SysFormMapper sysFormMapper;
+    @Autowired
+    private WxCorpInfoService wxCorpInfoService;
     @RequestMapping("/exportData")
-    public HttpRespMsg exportData(Clue clue) throws Exception {
-        return clueService.exportData(clue);
+    public HttpRespMsg exportData(Clue clue ,HttpServletRequest request) throws Exception {
+        User user = userMapper.selectById(request.getHeader("token"));
+        SysForm sysForm = sysFormMapper.selectOne(new LambdaQueryWrapper<SysForm>().eq(SysForm::getCompanyId, user.getCompanyId()).eq(SysForm::getCode, "Thread").eq(SysForm::getIsCurrent, 1));
+        WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, user.getCompanyId()));
+        String config = sysForm.getConfig();
+        JSONObject configOb = JSON.parseObject(config);
+        JSONArray configObJSONArray = configOb.getJSONArray("list");
+        List<List<String>> dataList=new ArrayList<>();
+        List<String> titleList=new ArrayList<>();
+        List<String> modelList=new ArrayList<>();
+        for (int i = 0; i < configObJSONArray.size(); i++) {
+            JSONObject item = configObJSONArray.getJSONObject(i);
+            String type = item.getString("type");
+            if (type.equals("grid")){
+                JSONArray columns = item.getJSONArray("columns");
+                for (int j = 0; j < columns.size(); j++) {
+                    JSONObject columnsJSONObject = columns.getJSONObject(j);
+                    JSONArray listJsonArray = columnsJSONObject.getJSONArray("list");
+                    for (int k = 0; k < listJsonArray.size(); k++) {
+                        JSONObject listJsonArrayJSONObject = listJsonArray.getJSONObject(k);
+                        titleList.add(listJsonArrayJSONObject.getString("label"));
+                        modelList.add(listJsonArrayJSONObject.getString("model"));
+                    }
+                }
+            }
+            else {
+                titleList.add(item.getString("label"));
+                modelList.add(item.getString("model"));
+            }
+        }
+        dataList.add(titleList);
+
+        HttpRespMsg respMsg = list(clue,request);
+        Map<String, Object> msgData = (Map<String, Object>) respMsg.getData();
+        List<Clue> list = (List<Clue>) msgData.get("data");
+
+        for (Clue data : list) {
+            List<String> item=new ArrayList<>();
+            for (int i = 0; i < modelList.size(); i++) {
+
+                String model = modelList.get(i);
+                String targetName = model.substring(0, 1).toUpperCase() + model.substring(1);
+                Class<? extends Clue> aClass = data.getClass();
+                String value = "";
+
+                if(model.equals("inchargerId")){
+                    if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                        value = "$userName"+String.valueOf(aClass.getMethod("getInchargerName").invoke(data))+"$";
+                    }else {
+                        value = String.valueOf(aClass.getMethod("getInchargerName").invoke(data)).equals("null") ? "" :String.valueOf(aClass.getMethod("getInchargerName").invoke(data));
+                    }
+                }else {
+                    value= String.valueOf(aClass.getMethod("get" + targetName).invoke(data)==null?"":aClass.getMethod("get" + targetName).invoke(data));
+                }
+
+                if(model.equals("clueSourceId")){
+                    value = String.valueOf(aClass.getMethod("getClueSourceValue").invoke(data));
+                }
+                if(model.equals("customerLevelId")){
+                    value = String.valueOf(aClass.getMethod("getCustomerLevelValue").invoke(data));
+                }
+                if(model.equals("customerIndustryId")){
+                    value = String.valueOf(aClass.getMethod("getCustomerIndustryValue").invoke(data));
+                }
+                item.add(value);
+            }
+            dataList.add(item);
+        }
+        String fileName="线索表导出_"+ System.currentTimeMillis();
+        return excelExportService.exportGeneralExcelByTitleAndList(wxCorpInfo,fileName,dataList,path);
     }
 
 

+ 51 - 57
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/CustomController.java

@@ -114,67 +114,62 @@ public class CustomController {
         JSONArray configObJSONArray = configOb.getJSONArray("list");
         List<List<String>> dataList=new ArrayList<>();
         List<String> titleList=new ArrayList<>();
+        List<String> modelList=new ArrayList<>();
         for (int i = 0; i < configObJSONArray.size(); i++) {
             JSONObject item = configObJSONArray.getJSONObject(i);
-            titleList.add(item.getString("label"));
+            String type = item.getString("type");
+            if (type.equals("grid")){
+                JSONArray columns = item.getJSONArray("columns");
+                for (int j = 0; j < columns.size(); j++) {
+                    JSONObject columnsJSONObject = columns.getJSONObject(j);
+                    JSONArray listJsonArray = columnsJSONObject.getJSONArray("list");
+                    for (int k = 0; k < listJsonArray.size(); k++) {
+                        JSONObject listJsonArrayJSONObject = listJsonArray.getJSONObject(k);
+                        titleList.add(listJsonArrayJSONObject.getString("label"));
+                        modelList.add(listJsonArrayJSONObject.getString("model"));
+                    }
+                }
+            }
+            else {
+                titleList.add(item.getString("label"));
+                modelList.add(item.getString("model"));
+            }
         }
         dataList.add(titleList);
-        HttpRespMsg msg = list(custom, request);
-        Map<String, Object> msgData = (Map<String, Object>) msg.getData();
-        List<Custom> bos = (List<Custom>) msgData.get("data");
-        for (Custom bo1 : bos) {
+
+        HttpRespMsg respMsg = list(custom,request);
+        Map<String, Object> msgData = (Map<String, Object>) respMsg.getData();
+        List<Custom> list = (List<Custom>) msgData.get("data");
+
+        for (Custom data : list) {
             List<String> item=new ArrayList<>();
-            for (int i = 0; i < configObJSONArray.size(); i++) {
-                JSONObject target = configObJSONArray.getJSONObject(i);
-                if(target.getString("type").equals("grid")){
-                    JSONArray columns = target.getJSONArray("columns");
-                    for (int i1 = 0; i1 < columns.size(); i1++) {
-                        JSONObject columnsJSONObject = columns.getJSONObject(i1);
-                        JSONArray list = columnsJSONObject.getJSONArray("list");
-                        for (int i2 = 0; i2 < list.size(); i2++) {
-                            JSONObject object = list.getJSONObject(i2);
-                            String model = object.getString("model");
-                            String targetName = model.substring(0, 1).toUpperCase() + model.substring(1);
-                            Class<? extends Custom> aClass = bo1.getClass();
-                            String value = String.valueOf(aClass.getMethod("get" + targetName).invoke(bo1)==null?"":aClass.getMethod("get" + targetName).invoke(bo1));
-                            if(model.equals("inchargerId")){
-                                if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
-                                    value = "$userName"+String.valueOf(aClass.getMethod("getInchargerName").invoke(bo1))+"$";
-                                }else {
-                                    value = String.valueOf(aClass.getMethod("getInchargerName").invoke(bo1));
-                                }
-                            }
-                            if(model.equals("customSourceValue")){
-                                if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
-                                    value = "$userName"+String.valueOf(aClass.getMethod("getCustomSourceValue").invoke(bo1))+"$";
-                                }else {
-                                    value = String.valueOf(aClass.getMethod("getCustomSourceValue").invoke(bo1)).equals("null") ?"" :String.valueOf(aClass.getMethod("getCustomSourceValue").invoke(bo1));
-                                }
-                            }
-                            item.add(value);
-                        }
+            for (int i = 0; i < modelList.size(); i++) {
+
+                String model = modelList.get(i);
+                String targetName = model.substring(0, 1).toUpperCase() + model.substring(1);
+                Class<? extends Custom> aClass = data.getClass();
+                String value = "";
+
+                if(model.equals("inchargerId")){
+                    if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                        value = "$userName"+String.valueOf(aClass.getMethod("getInchargerName").invoke(data))+"$";
+                    }else {
+                        value = String.valueOf(aClass.getMethod("getInchargerName").invoke(data)).equals("null") ? "" :String.valueOf(aClass.getMethod("getInchargerName").invoke(data));
                     }
                 }else {
-                    String model = target.getString("model");
-                    String targetName = model.substring(0, 1).toUpperCase() + model.substring(1);
-                    Class<? extends Custom> aClass = bo1.getClass();
-                    String value = String.valueOf(aClass.getMethod("get" + targetName).invoke(bo1)==null?"":aClass.getMethod("get" + targetName).invoke(bo1));
-                    if(model.equals("inchargerId")){
-                        if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
-                            value = "$userName"+String.valueOf(aClass.getMethod("getInchargerName").invoke(bo1))+"$";
-                        }else {
-                            value = String.valueOf(aClass.getMethod("getInchargerName").invoke(bo1));
-                        }
-                    }
-                    if(model.equals("contactsId")){
-                        if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
-                            value = "$userName"+String.valueOf(aClass.getMethod("getContactsName").invoke(bo1))+"$";
-                        }else {
-                            value = String.valueOf(aClass.getMethod("getContactsName").invoke(bo1));
-                        }
-                    }
-                    item.add(value);
+                    value= String.valueOf(aClass.getMethod("get" + targetName).invoke(data)==null?"":aClass.getMethod("get" + targetName).invoke(data));
+                }
+
+                if(model.equals("clueSourceId")){
+                    value = String.valueOf(aClass.getMethod("getClueSourceValue").invoke(data));
+                }
+                if(model.equals("customerLevelId")){
+                    value = String.valueOf(aClass.getMethod("getCustomerLevelValue").invoke(data));
                 }
+                if(model.equals("customerIndustryId")){
+                    value = String.valueOf(aClass.getMethod("getCustomerIndustryValue").invoke(data));
+                }
+                item.add(value);
             }
             dataList.add(item);
         }
@@ -251,11 +246,10 @@ public class CustomController {
 
     @RequestMapping("getAll")
     public Object getAll(HttpServletRequest request) {
-        User user = userMapper.selectById(request.getHeader("Token"));
+        HttpRespMsg list = list(new Custom(), request);
+        Map<String, Object> data = (Map<String, Object>) list.getData();
         HttpRespMsg msg = new HttpRespMsg();
-        msg.setMsg("操作成功");
-        msg.setData(
-                customMapper.selectList(new QueryWrapper<Custom>().eq("company_id", user.getCompanyId()))
+        msg.setData(data.get("data")
         );
         return msg;
     }

+ 45 - 10
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/SalesOrderController.java

@@ -90,7 +90,7 @@ public class SalesOrderController {
         Integer companyId = user.getCompanyId();
         order.setCompanyId(companyId);
         order.setCreatorId(user.getId());
-        if(order.getReceivedPayment()!=null){
+        if(order.getReceivedPayment()!=null&&order.getReceivedPayment().intValue()!=0){
             BigDecimal price = order.getPrice();
             if(order.getPrice().doubleValue()!=order.getReceivedPayment().doubleValue()){
                 order.setReceivedStatus(1);
@@ -100,6 +100,9 @@ public class SalesOrderController {
             order.setUnReceivedPayment(price.subtract(order.getReceivedPayment()));
         }else {
             order.setUnReceivedPayment(order.getPrice());
+            order.setReceivedStatus(0);
+            //修改已退回金额为0 是否要删除所有回款数据
+            salesOrderPaymentService.remove(new LambdaQueryWrapper<SalesOrderPayment>().eq(SalesOrderPayment::getOrderId,order.getId()));
         }
         int countCode;
         int countName;
@@ -387,8 +390,8 @@ public class SalesOrderController {
     * @Date: 2024/5/16
     */
     @RequestMapping("/dataSummary")
-    public HttpRespMsg dataSummary(Integer queryType,Integer dateType){
-        return salesOrderService.dataSummary(queryType,dateType);
+    public HttpRespMsg dataSummary(Integer queryType,Integer dateType,String startDate,String endDate){
+        return salesOrderService.dataSummary(queryType,dateType,startDate,endDate);
     }
 
     /**
@@ -406,8 +409,12 @@ public class SalesOrderController {
         SalesOrderPayment salesOrderPayment=new SalesOrderPayment();
         salesOrderPayment.setMoney(new BigDecimal(money));
         salesOrderPayment.setOrderId(orderId);
-        if(money>salesOrder.getUnReceivedPayment().doubleValue()){
-            msg.setError("回款金额不能大于当前未回款金额");
+        if(salesOrder.getReceivedStatus()==2){
+            msg.setError("当前订单已完全回款");
+            return msg;
+        }
+        if(money>salesOrder.getPrice().doubleValue()){
+            msg.setError("回款金额不能大于订单金额");
             return msg;
         }
         List<SalesOrderPayment> list = salesOrderPaymentService.list(new LambdaQueryWrapper<SalesOrderPayment>().eq(SalesOrderPayment::getOrderId, orderId));
@@ -449,8 +456,8 @@ public class SalesOrderController {
     * @Date: 2024/5/21
     */
     @RequestMapping("/businessOpportunityStage")
-    public HttpRespMsg businessOpportunityStage(Integer queryType,Integer dateType){
-        return salesOrderService.businessOpportunityStage(queryType,dateType);
+    public HttpRespMsg businessOpportunityStage(Integer queryType,Integer dateType,String startDate,String endDate){
+        return salesOrderService.businessOpportunityStage(queryType,dateType,startDate,endDate);
     }
 
     /**
@@ -489,22 +496,44 @@ public class SalesOrderController {
         HttpRespMsg msg=new HttpRespMsg();
         SalesOrderPayment payment = salesOrderPaymentService.getById(paymentId);
         SalesOrder salesOrder = salesOrderService.getById(payment.getOrderId());
-        List<SalesOrderPayment> list = salesOrderPaymentService.list(new LambdaQueryWrapper<SalesOrderPayment>().eq(SalesOrderPayment::getOrderId, salesOrder.getId()).orderByDesc(SalesOrderPayment::getCreateTime));
+        List<SalesOrderPayment> list = salesOrderPaymentService.list(new LambdaQueryWrapper<SalesOrderPayment>().eq(SalesOrderPayment::getOrderId, salesOrder.getId()).orderByAsc(SalesOrderPayment::getCreateTime));
         int i = list.indexOf(payment);
         if(money!=null){
+            if(salesOrder.getReceivedStatus()==2){
+                msg.setError("当前订单已完全回款");
+                return msg;
+            }
+            if(money>salesOrder.getPrice().doubleValue()){
+                msg.setError("回款金额不能大于订单金额");
+                return msg;
+            }
+            double sum = list.stream().mapToDouble(s -> s.getMoney().doubleValue()).sum();
+            if((sum)>salesOrder.getPrice().doubleValue()){
+                msg.setError("总回款金额不能大于订单金额");
+                return msg;
+            }
             //找到原回款数据
             BigDecimal nowMoney = new BigDecimal(money);
             BigDecimal oldMoney = payment.getMoney();
             //离当前回款数据最近一次回款的未回款数据作为依据
-            SalesOrderPayment salesOrderPayment = list.get(i + 1);
+            SalesOrderPayment salesOrderPayment =list.size()>1?list.get(i-1):list.get(i);
             BigDecimal unReceivedPayment = salesOrderPayment.getUnReceivedPayment();
-            unReceivedPayment=unReceivedPayment.subtract(nowMoney);
+            unReceivedPayment=unReceivedPayment.add(oldMoney).subtract(nowMoney);
             payment.setMoney(new BigDecimal(money));
             payment.setUnReceivedPayment(unReceivedPayment);
             if(!salesOrderPaymentService.updateById(payment)){
                 msg.setError("验证失败");
                 return msg;
             }
+            if(money>0){
+                //回款金额大于0的情况下才能算一次回款
+                if(unReceivedPayment.doubleValue()<=0){
+                    //未回款金额小于等于0 说明完全回款修改状态
+                    salesOrder.setReceivedStatus(2);
+                }else {
+                    salesOrder.setReceivedStatus(1);
+                }
+            }
             //订单上的已回款金额
             BigDecimal receivedPayment = salesOrder.getReceivedPayment();
             receivedPayment=receivedPayment.subtract(oldMoney).add(nowMoney);
@@ -538,6 +567,12 @@ public class SalesOrderController {
         unReceivedPayment=unReceivedPayment.add(oldMoney);
         salesOrder.setReceivedPayment(receivedPayment);
         salesOrder.setUnReceivedPayment(unReceivedPayment);
+        if(unReceivedPayment.doubleValue()>0){
+            salesOrder.setReceivedStatus(1);
+        }
+        if(receivedPayment.intValue()==0){
+            salesOrder.setReceivedStatus(0);
+        }
         if(!salesOrderService.updateById(salesOrder)){
             msg.setError("验证失败");
             return msg;

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

@@ -39,6 +39,8 @@ public class BusinessOpportunity extends Model<BusinessOpportunity> {
 
     @TableField(exist = false)
     private String productName;
+    @TableField(exist = false)
+    private Integer clueId;
 
     /**
      * 商机名称

+ 9 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Clue.java

@@ -10,6 +10,8 @@ import java.util.List;
 
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
 import lombok.experimental.Accessors;
 
 /**
@@ -23,6 +25,8 @@ import lombok.experimental.Accessors;
 @Data
 @EqualsAndHashCode(callSuper = false)
 @Accessors(chain = true)
+@Setter
+@Getter
 public class Clue extends Model<Clue> {
 
     private static final long serialVersionUID=1L;
@@ -34,7 +38,11 @@ public class Clue extends Model<Clue> {
      * 公司id
      */
     @TableField("company_id")
-    private Integer companyId;
+    private Integer companyId;/**
+     * 公司id
+     */
+    @TableField("is_bo")
+    private Integer isBo;
     //创建人
     @TableField("create_id")
     private String createId;

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

@@ -54,7 +54,7 @@ public interface ClueService extends IService<Clue> {
 
     Object downFile(UploadFile file, HttpServletRequest request, HttpServletResponse response);
 
-    HttpRespMsg importData(MultipartFile multipartFile);
+    HttpRespMsg importData(MultipartFile multipartFile,HttpServletRequest request);
 
     HttpRespMsg exportData(Clue clue) throws Exception;
 

+ 2 - 2
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/SalesOrderService.java

@@ -25,9 +25,9 @@ public interface SalesOrderService extends IService<SalesOrder> {
 
     HttpRespMsg salesKit(Integer queryType,Integer dateType, String startDate, String endDate);
 
-    HttpRespMsg dataSummary(Integer queryType, Integer dateType);
+    HttpRespMsg dataSummary(Integer queryType, Integer dateType,String startDate,String endDate);
 
-    HttpRespMsg businessOpportunityStage(Integer queryType, Integer dateType);
+    HttpRespMsg businessOpportunityStage(Integer queryType, Integer dateType,String startDate,String endDate);
 
     HttpRespMsg productWithOrder(Integer id);
 

+ 148 - 78
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/BusinessOpportunityServiceImpl.java

@@ -38,6 +38,9 @@ import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.math.BigDecimal;
 import java.net.URLEncoder;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.ZoneId;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -82,6 +85,9 @@ public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportun
     @Resource
     private SysDictMapper sysDictMapper;
 
+    @Resource
+    private StageMapper stageMapper;
+
     @Override
     public List<BusinessOpportunity> getAll(BusinessOpportunity bo) {
         return bOMapper.selectAllList(bo);
@@ -432,16 +438,28 @@ public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportun
         bOMapper.deleteBatchIds(ids);
     }
 
+
+    @Autowired
+    private ContactsMapper contactsMapper;
+    @Autowired
+    private CustomMapper customMapper;
     @Override
     public HttpRespMsg importData(MultipartFile multipartFile) {
-        HttpRespMsg msg = new HttpRespMsg();
+        HttpRespMsg msg=new HttpRespMsg();
+        if(!multipartFile.getOriginalFilename().endsWith(".xlsx")){
+            msg.setError("文件格式错误,请使用.xlsx格式的Excel文件进行导入");
+            return msg;
+        }
         String fileName = multipartFile.getOriginalFilename();
         File file = new File(fileName == null ? "file" : fileName);
         User user = userMapper.selectById(request.getHeader("token"));
         Integer companyId = user.getCompanyId();
         WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, companyId));
         List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
-        List<SysDict> sysDictOfClueSources = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "ClueSources"));
+        List<Stage> stage = stageMapper.selectList(null);
+        List<Contacts> contacts = contactsMapper.selectList(new LambdaQueryWrapper<Contacts>().eq(Contacts::getCompanyId, user.getCompanyId()).eq(Contacts::getIsDelete, 0).orderByDesc(Contacts::getId));
+        List<Custom> customs = customMapper.selectList(new LambdaQueryWrapper<Custom>().eq(Custom::getCompanyId, user.getCompanyId()).eq(Custom::getIsDelete, 0).orderByDesc(Custom::getId));
+
         InputStream inputStream = null;
         OutputStream outputStream = null;
         try {
@@ -461,17 +479,36 @@ public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportun
             //由于第一行需要指明列对应的标题
             int rowNum = sheet.getLastRowNum();
             //获取当前表单模板 校验规则
-            SysForm sysForm = sysFormMapper.selectOne(new LambdaQueryWrapper<SysForm>().eq(SysForm::getCode, "Thread").eq(SysForm::getCompanyId, companyId).eq(SysForm::getIsCurrent, 1));
-            if (sysForm == null) {
+            SysForm sysForm = sysFormMapper.selectOne(new LambdaQueryWrapper<SysForm>().eq(SysForm::getCode, "business").eq(SysForm::getCompanyId, companyId).eq(SysForm::getIsCurrent, 1));
+            if(sysForm==null){
                 msg.setError("当前模块未配置自定义模板,需先完成配置");
                 return msg;
             }
             String config = sysForm.getConfig();
             JSONObject configOb = JSON.parseObject(config);
             JSONArray configObJSONArray = configOb.getJSONArray("list");
-            List<String> userNameList = new ArrayList<>();
-            HttpRespMsg respMsg = new HttpRespMsg();
-            for (int rowIndex = 0; rowIndex <= rowNum; rowIndex++) {
+            //可能存在栅格布局的情况需要特殊处理
+            List<String> modelNameList=new ArrayList<>();
+            for (int i = 0; i < configObJSONArray.size(); i++) {
+                JSONObject jsonObject = configObJSONArray.getJSONObject(i);
+                if(jsonObject.getString("type").equals("grid")){
+                    JSONArray columns = jsonObject.getJSONArray("columns");
+                    for (int i1 = 0; i1 < columns.size(); i1++) {
+                        JSONObject columnsJSONObject = columns.getJSONObject(i1);
+                        JSONArray list = columnsJSONObject.getJSONArray("list");
+                        for (int i2 = 0; i2 < list.size(); i2++) {
+                            JSONObject object = list.getJSONObject(i2);
+                            modelNameList.add(object.getString("model"));
+                        }
+                    }
+                }else {
+                    modelNameList.add(jsonObject.getString("model"));
+                }
+            }
+            List<BusinessOpportunity> importProductList = new ArrayList<>();
+            List<String> userNameList=new ArrayList<>();
+            HttpRespMsg respMsg=new HttpRespMsg();
+            for (int rowIndex = 1; rowIndex <= rowNum; rowIndex++) {
                 XSSFRow row = sheet.getRow(rowIndex);
                 if (row == null) {
                     continue;
@@ -483,37 +520,25 @@ public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportun
                 //获取到当前行的列数据
                 int cellNum = row.getLastCellNum();
                 for (int i = 0; i < cellNum; i++) {
-                    JSONObject item = configObJSONArray.getJSONObject(i);
-                    String modelName = item.getString("model");
+                    String modelName = modelNameList.get(i);
                     XSSFCell cell = row.getCell(i);
-                    if (cell != null) {
-                        switch (item.getString("type")) {
-//                            case "time":cell.setCellType(CellType.NUMERIC);
-//                                break;
-                            default:
-                                cell.setCellType(CellType.STRING);
-                        }
-                    }
-                    if (modelName.equals("inchargerId")) {
-                        System.out.println("=====");
-                        System.out.println(modelName);
-                        System.out.println(cell.toString());
-                        if (!StringUtils.isEmpty(cell.getStringCellValue())) {
+                    if(modelName.equals("inchargerId")){
+                        if(!org.springframework.util.StringUtils.isEmpty(cell.getStringCellValue())){
                             userNameList.add(cell.getStringCellValue());
                         }
                     }
 
                 }
             }
-            System.out.println("参与搜索的人员列表" + userNameList + userNameList.size());
-            if (wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1 && userNameList.size() > 0) {
-                respMsg = wxCorpInfoService.getBatchSearchUserInfo(wxCorpInfo, userNameList, null);
-                if (respMsg.code.equals("0")) {
-                    msg.setError("姓名为[" + String.valueOf(respMsg.data) + "]的人员存在重复,请使用工号!");
+            System.out.println("参与搜素的人员列表"+userNameList + userNameList.size());
+            if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1&&userNameList.size()>0){
+                respMsg = wxCorpInfoService.getBatchSearchUserInfo(wxCorpInfo, userNameList,null);
+                if(respMsg.code.equals("0")){
+                    msg.setError("姓名为["+String.valueOf(respMsg.data)+"]的人员存在重复,请使用工号!");
                     return msg;
                 }
             }
-            List<User> targetUserList = (List<User>) respMsg.data;
+            List<User> targetUserList= (List<User>) respMsg.data;
             //直接忽略空行 从row1开始
             for (int rowIndex = 1; rowIndex <= rowNum; rowIndex++) {
                 XSSFRow row = sheet.getRow(rowIndex);
@@ -526,89 +551,134 @@ public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportun
                 }
                 //获取到当前行的列数据
                 int cellNum = row.getLastCellNum();
-                BusinessOpportunity bo = new BusinessOpportunity();
-                bo.setCompanyId(companyId);
-                bo.setCreateTime(new Date());
-                bo.setCreatorId(user.getId());
+                BusinessOpportunity product=new BusinessOpportunity();
+                product.setCompanyId(companyId);
+                product.setCreatorId(user.getId());
+                product.setCreateTime(new Date());
+                JSONArray objects=new JSONArray();
+                for (int i = 0; i < configObJSONArray.size(); i++) {
+                    JSONObject jsonObject = configObJSONArray.getJSONObject(i);
+                    if(jsonObject.getString("type").equals("grid")){
+                        JSONArray columns = jsonObject.getJSONArray("columns");
+                        for (int i1 = 0; i1 < columns.size(); i1++) {
+                            JSONObject jsonObject1 = columns.getJSONObject(i1).getJSONArray("list").getJSONObject(0);
+                            objects.add(jsonObject1);
+                        }
+                    }else {
+                        objects.add(jsonObject);
+                    }
+                }
                 for (int i = 0; i < cellNum; i++) {
-                    JSONObject item = configObJSONArray.getJSONObject(i);
+                    JSONObject item = objects.getJSONObject(i);
                     String modelName = item.getString("model");
                     String className = modelName.substring(0, 1).toUpperCase() + modelName.substring(1);
-                    String getter = "get" + className;
-                    String setter = "set" + className;
+                    String getter="get"+className;
+                    String setter="set"+className;
                     XSSFCell cell = row.getCell(i);
-                    if (cell != null) {
-                        switch (item.getString("type")) {
+                    if(cell!=null){
+                        switch (item.getString("type")){
 //                            case "time":cell.setCellType(CellType.NUMERIC);
 //                                break;
-                            default:
-                                cell.setCellType(CellType.STRING);
+                            //默认读取所有数据都是文本格式
+                            default:cell.setCellType(CellType.STRING);
                         }
                     }
-                    //校验当前列是否为必填
-                    JSONObject options = item.getJSONObject("options");
-                    JSONObject rules = options.getJSONObject("rules");
-                    Boolean required = rules.getBoolean("required");
-                    if (required) {
-                        if (StringUtils.isEmpty(cell.getStringCellValue())) {
-                            msg.setError(item.getString("label") + "值不能为空值");
-                            return msg;
-                        }
-                    }
-                    if (modelName.equals("inchargerId")) {
-                        if (!StringUtils.isEmpty(cell.getStringCellValue())) {
+                    if(modelName.equals("inchargerId")){
+                        if(!org.springframework.util.StringUtils.isEmpty(cell.getStringCellValue())){
                             String userName = cell.getStringCellValue();
                             Optional<User> first;
-                            if (wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1) {
+                            if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
                                 Optional<User> optional = targetUserList.stream().filter(tl -> tl.getName().equals(userName)).findFirst();
-                                first = userList.stream().filter(u -> (u.getJobNumber() != null && u.getJobNumber().equals(userName)) || (optional.isPresent() && u.getCorpwxUserid() != null && u.getCorpwxUserid().equals(optional.get().getCorpwxUserid()))).findFirst();
-                            } else {
-                                first = userList.stream().filter(u -> u.getName().equals(userName) || (u.getJobNumber() != null && u.getJobNumber().equals(userName))).findFirst();
+                                first= userList.stream().filter(u ->(u.getJobNumber()!=null&&u.getJobNumber().equals(userName))||(optional.isPresent()&&u.getCorpwxUserid()!=null&&u.getCorpwxUserid().equals(optional.get().getCorpwxUserid()))).findFirst();
+                            }else {
+                                first= userList.stream().filter(u -> u.getName().equals(userName)||(u.getJobNumber()!=null&&u.getJobNumber().equals(userName))).findFirst();
                             }
                             if (first.isPresent()) {
-                                bo.setInchargerId(first.get().getId());
+                                product.setInchargerId(first.get().getId());
                             } else {
-                                msg.setError("负责人[" + userName + "]在系统中不存在");
+                                msg.setError("负责人["+userName+"]在系统中不存在");
                                 return msg;
                             }
                         }
-                    } else if (modelName.equals("contactsId")) {
-                        if (!StringUtils.isEmpty(cell.getStringCellValue())) {
-                            String userName = cell.getStringCellValue();
-                            Optional<User> first;
-                            if (wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1) {
-                                Optional<User> optional = targetUserList.stream().filter(tl -> tl.getName().equals(userName)).findFirst();
-                                first = userList.stream().filter(u -> (u.getJobNumber() != null && u.getJobNumber().equals(userName)) || (optional.isPresent() && u.getCorpwxUserid() != null && u.getCorpwxUserid().equals(optional.get().getCorpwxUserid()))).findFirst();
-                            } else {
-                                first = userList.stream().filter(u -> u.getName().equals(userName) || (u.getJobNumber() != null && u.getJobNumber().equals(userName))).findFirst();
-                            }
-                            if (first.isPresent()) {
-                                bo.setContactsId(Integer.parseInt(first.get().getId()));
-                            } else {
-                                msg.setError("负责人[" + userName + "]在系统中不存在");
+                    }else if(modelName.equals("stageId")){
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Optional<Stage> first = stage.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
+                            if(first.isPresent()){
+                                product.setStageId(first.get().getId());
+                            }else {
+                                msg.setError("阶段["+cell.getStringCellValue()+"]不存在,请在阶段设置中增加");
                                 return msg;
                             }
                         }
-                    } else {
-                        if (!StringUtils.isEmpty(cell.getStringCellValue())) {
-                            Class<Clue> clueClass = Clue.class;
-                            Method method = clueClass.getMethod(setter, String.class);
-                            method.invoke(bo, cell.getStringCellValue());
+                    }else if(modelName.equals("contactsId")){
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Optional<Contacts> first = contacts.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
+                            product.setContactsId(first.get().getId());
+                        }
+                    }else if(modelName.equals("customerId")){
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Optional<Custom> first = customs.stream().filter(s -> s.getCustomName().equals(cell.getStringCellValue())).findFirst();
+                            product.setCustomerId(first.get().getId());
+                        }
+                    }else if(modelName.equals("expectedTransactionDate")){
+                        if(cell != null && cell.getCellTypeEnum() != CellType.BLANK){
+                            if(!org.apache.commons.lang3.StringUtils.isEmpty(cell.getStringCellValue())){
+                                try {
+                                    // 假设 cell 是一个代表 Excel 单元格的对象
+                                    String dateString = cell.getStringCellValue();
+
+                                    // 定义日期格式
+                                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
+
+                                    // 解析字符串为 Date 类型
+                                    Date parsedDate = dateFormat.parse(dateString);
+
+                                    // 设置到对象中
+                                    product.setExpectedTransactionDate(parsedDate);
+
+                                } catch (Exception e) {
+                                    System.out.println("日期时间格式不正确, 应该是yyyy/MM/dd");
+                                    msg.setError("日期时间格式不正确, 应该是yyyy/MM/dd");
+                                    return msg;
+                                }
+                            }
+                        }
+                    }else {
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Class<BusinessOpportunity> productClass = BusinessOpportunity.class;
+                            Method method = productClass.getMethod(setter,String.class);
+                            method.invoke(product,cell.getStringCellValue());
                         }
                     }
 
                 }
-                bOMapper.insert(bo);
+                importProductList.add(product);
+            }
+            if(importProductList.size()>0){
+                if(!saveOrUpdateBatch(importProductList)){
+                    msg.setError("验证失败,请检验数据格式是否正确");
+                    return msg;
+                }
+//                List<ActionLog> ads = new ArrayList<>();
+                for (BusinessOpportunity bo : importProductList) {
+                    ActionLog actionLog = new ActionLog();
+                    actionLog.setName("新增了商机");
+                    actionLog.setItemId(bo.getId());
+                    actionLog.setCode("business");
+                    actionLog.setUserId(user.getId());
+                    actionLogMapper.insert(actionLog);
+                }
             }
         } catch (IOException | NoSuchMethodException e) {
             e.printStackTrace();
+            msg.setError("验证失败,请检验数据格式是否正确");
         } catch (IllegalAccessException e) {
             e.printStackTrace();
         } catch (InvocationTargetException e) {
             e.printStackTrace();
         } catch (Exception e) {
             e.printStackTrace();
-            msg.setError("验证失败");
+            msg.setError("验证失败,请检验数据格式是否正确");
             return msg;
         }
         return msg;

+ 108 - 132
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ClueServiceImpl.java

@@ -37,6 +37,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.beans.Transient;
 import java.io.*;
+import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.math.BigDecimal;
@@ -45,6 +46,9 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -278,7 +282,6 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
 
         updateWrapper.set("incharger_id", inchargerId);
         clueMapper.update(null, updateWrapper);
-
     }
 
     @Override
@@ -289,15 +292,10 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
     @Override
     public int getTotal2(Clue clue, User user) {
         return clueMapper.getTotal2(clue, user.getId());
-
     }
 
-
-
-
     @Value(value = "${upload.path}")
     private String filePath;
-
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Object uploadFile(Clue clue, HttpServletRequest request, MultipartFile file) {
@@ -402,18 +400,22 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public HttpRespMsg importData(MultipartFile multipartFile) {
+    public HttpRespMsg importData(MultipartFile multipartFile,HttpServletRequest request) {
         HttpRespMsg msg=new HttpRespMsg();
+        if(!multipartFile.getOriginalFilename().endsWith(".xlsx")){
+            msg.setError("文件格式错误,请使用.xlsx格式的Excel文件进行导入");
+            return msg;
+        }
         String fileName = multipartFile.getOriginalFilename();
         File file = new File(fileName == null ? "file" : fileName);
         User user = userMapper.selectById(request.getHeader("token"));
         Integer companyId = user.getCompanyId();
         WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, companyId));
-//        List<Clue> clueList = clueMapper.selectList(new LambdaQueryWrapper<Clue>().eq(Clue::getCompanyId, companyId));
         List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
-        List<SysDict> sysDictOfClueSources = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "ClueSources"));
-        List<SysDict> sysDictOfCustomLevel = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "CustomLevel"));
-        List<SysDict> sysDictOfCustomIndustry = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "CustomIndustry"));
+        List<SysDict> sysSources = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "ClueSources"));
+        List<SysDict> sysIndutryId = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "CustomIndustry"));
+        List<SysDict> levels = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "CustomLevel"));
+
         InputStream inputStream = null;
         OutputStream outputStream = null;
         try {
@@ -441,10 +443,28 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
             String config = sysForm.getConfig();
             JSONObject configOb = JSON.parseObject(config);
             JSONArray configObJSONArray = configOb.getJSONArray("list");
-//            List<Clue> importClueList=new ArrayList<>();
+            //可能存在栅格布局的情况需要特殊处理
+            List<String> modelNameList=new ArrayList<>();
+            for (int i = 0; i < configObJSONArray.size(); i++) {
+                JSONObject jsonObject = configObJSONArray.getJSONObject(i);
+                if(jsonObject.getString("type").equals("grid")){
+                    JSONArray columns = jsonObject.getJSONArray("columns");
+                    for (int i1 = 0; i1 < columns.size(); i1++) {
+                        JSONObject columnsJSONObject = columns.getJSONObject(i1);
+                        JSONArray list = columnsJSONObject.getJSONArray("list");
+                        for (int i2 = 0; i2 < list.size(); i2++) {
+                            JSONObject object = list.getJSONObject(i2);
+                            modelNameList.add(object.getString("model"));
+                        }
+                    }
+                }else {
+                    modelNameList.add(jsonObject.getString("model"));
+                }
+            }
+            List<Clue> importProductList = new ArrayList<>();
             List<String> userNameList=new ArrayList<>();
             HttpRespMsg respMsg=new HttpRespMsg();
-            for (int rowIndex = 0; rowIndex <= rowNum; rowIndex++) {
+            for (int rowIndex = 1; rowIndex <= rowNum; rowIndex++) {
                 XSSFRow row = sheet.getRow(rowIndex);
                 if (row == null) {
                     continue;
@@ -456,28 +476,17 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
                 //获取到当前行的列数据
                 int cellNum = row.getLastCellNum();
                 for (int i = 0; i < cellNum; i++) {
-                    JSONObject item = configObJSONArray.getJSONObject(i);
-                    String modelName = item.getString("model");
+                    String modelName = modelNameList.get(i);
                     XSSFCell cell = row.getCell(i);
-                    if(cell!=null){
-                        switch (item.getString("type")){
-//                            case "time":cell.setCellType(CellType.NUMERIC);
-//                                break;
-                            default:cell.setCellType(CellType.STRING);
-                        }
-                    }
                     if(modelName.equals("inchargerId")){
-                        System.out.println("=====");
-                        System.out.println(modelName);
-                        System.out.println(cell.toString());
-                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                        if(!org.springframework.util.StringUtils.isEmpty(cell.getStringCellValue())){
                             userNameList.add(cell.getStringCellValue());
                         }
                     }
 
                 }
             }
-            System.out.println("参与搜的人员列表"+userNameList + userNameList.size());
+            System.out.println("参与搜的人员列表"+userNameList + userNameList.size());
             if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1&&userNameList.size()>0){
                 respMsg = wxCorpInfoService.getBatchSearchUserInfo(wxCorpInfo, userNameList,null);
                 if(respMsg.code.equals("0")){
@@ -498,12 +507,25 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
                 }
                 //获取到当前行的列数据
                 int cellNum = row.getLastCellNum();
-                Clue clue =new Clue();
-                clue.setCompanyId(companyId);
-                clue.setCreateTime(new Date());
-                clue.setCreateId(user.getId());
+                Clue product=new Clue();
+                product.setCompanyId(companyId);
+                product.setCreateId(user.getId());
+                product.setCreateTime(new Date());
+                JSONArray objects=new JSONArray();
+                for (int i = 0; i < configObJSONArray.size(); i++) {
+                    JSONObject jsonObject = configObJSONArray.getJSONObject(i);
+                    if(jsonObject.getString("type").equals("grid")){
+                        JSONArray columns = jsonObject.getJSONArray("columns");
+                        for (int i1 = 0; i1 < columns.size(); i1++) {
+                            JSONObject jsonObject1 = columns.getJSONObject(i1).getJSONArray("list").getJSONObject(0);
+                            objects.add(jsonObject1);
+                        }
+                    }else {
+                        objects.add(jsonObject);
+                    }
+                }
                 for (int i = 0; i < cellNum; i++) {
-                    JSONObject item = configObJSONArray.getJSONObject(i);
+                    JSONObject item = objects.getJSONObject(i);
                     String modelName = item.getString("model");
                     String className = modelName.substring(0, 1).toUpperCase() + modelName.substring(1);
                     String getter="get"+className;
@@ -513,21 +535,12 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
                         switch (item.getString("type")){
 //                            case "time":cell.setCellType(CellType.NUMERIC);
 //                                break;
+                            //默认读取所有数据都是文本格式
                             default:cell.setCellType(CellType.STRING);
                         }
                     }
-                    //校验当前列是否为必填
-                    JSONObject options = item.getJSONObject("options");
-                    JSONObject rules = options.getJSONObject("rules");
-                    Boolean required = rules.getBoolean("required");
-                    if(required){
-                        if(StringUtils.isEmpty(cell.getStringCellValue())){
-                            msg.setError(item.getString("label")+"值不能为空值");
-                            return msg;
-                        }
-                    }
-                   if(modelName.equals("inchargerId")){
-                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                    if(modelName.equals("inchargerId")){
+                        if(!org.springframework.util.StringUtils.isEmpty(cell.getStringCellValue())){
                             String userName = cell.getStringCellValue();
                             Optional<User> first;
                             if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
@@ -537,125 +550,88 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
                                 first= userList.stream().filter(u -> u.getName().equals(userName)||(u.getJobNumber()!=null&&u.getJobNumber().equals(userName))).findFirst();
                             }
                             if (first.isPresent()) {
-                                clue.setInchargerId(first.get().getId());
+                                product.setInchargerId(first.get().getId());
                             } else {
                                 msg.setError("负责人["+userName+"]在系统中不存在");
                                 return msg;
                             }
                         }
-                    }else if(modelName.equals("customLevelId")){
+                    }else if(modelName.equals("clueSourceId")){
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Optional<SysDict> first = sysSources.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
+                            if(first.isPresent()){
+                                product.setClueSourceId(first.get().getId());
+                            }else {
+                                msg.setError("线索来源["+cell.getStringCellValue()+"]不存在,请在系统字典中增加");
+                                return msg;
+                            }
+                        }
+                    }else if(modelName.equals("customerIndustryId")){
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Optional<SysDict> first = sysIndutryId.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
+                            if(first.isPresent()){
+                                product.setCustomerIndustryId(first.get().getId());
+                            }else {
+                                msg.setError("客户行业["+cell.getStringCellValue()+"]不存在,请在系统字典中增加");
+                                return msg;
+                            }
+                        }
+                    }else if(modelName.equals("customerLevelId")){
                         if(!StringUtils.isEmpty(cell.getStringCellValue())){
-                            Optional<SysDict> first = sysDictOfCustomLevel.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
+                            Optional<SysDict> first = levels.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
                             if(first.isPresent()){
-                                clue.setCustomerLevelId(first.get().getId());
+                                product.setCustomerLevelId(first.get().getId());
                             }else {
-                                throw new Exception("客户级别["+cell.getStringCellValue()+"不存在,请在系统字典中增加");
+                                msg.setError("客户级别["+cell.getStringCellValue()+"]不存在,请在系统字典中增加");
+                                return msg;
                             }
                         }
-                    }else if(modelName.equals("clueSourcesId")){
-                       if(!StringUtils.isEmpty(cell.getStringCellValue())){
-                           Optional<SysDict> first = sysDictOfClueSources.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
-                           if(first.isPresent()){
-                               Integer id = first.get().getId();
-                               clue.setClueSourceId(id);
-                           }else {
-                               throw new Exception("线索来源["+cell.getStringCellValue()+"不存在,请在系统字典中增加");
-                           }
-                       }
-                   }else if(modelName.equals("customIndustryId")){
-                       if(!StringUtils.isEmpty(cell.getStringCellValue())){
-                           Optional<SysDict> first = sysDictOfCustomIndustry.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
-                           if(first.isPresent()){
-                               clue.setCustomerIndustryId(first.get().getId());
-                           }else {
-                               throw new Exception("线索来源["+cell.getStringCellValue()+"不存在,请在系统字典中增加");
-                           }
-                       }
-                   }else {
+                    }else {
+                        String stringCellValue = cell.getStringCellValue();
+                        System.out.println(stringCellValue+"=============");
                         if(!StringUtils.isEmpty(cell.getStringCellValue())){
-                            Class<Clue> clueClass = Clue.class;
-                            Method method = clueClass.getMethod(setter,String.class);
-                            method.invoke(clue,cell.getStringCellValue());
+                            Class<Clue> productClass = Clue.class;
+                            Method method = productClass.getMethod(setter,String.class);
+                            method.invoke(product,cell.getStringCellValue());
                         }
                     }
 
                 }
-                clueMapper.insert(clue);
+                importProductList.add(product);
+            }
+            if(importProductList.size()>0){
+                if(!saveOrUpdateBatch(importProductList)){
+                    msg.setError("验证失败,请检验数据格式是否正确");
+                    return msg;
+                }
+                for (Clue bo : importProductList) {
+                    ActionLog actionLog = new ActionLog();
+                    actionLog.setName("新增了商机");
+                    actionLog.setItemId(bo.getId());
+                    actionLog.setCode("clue");
+                    actionLog.setUserId(user.getId());
+                    actionLogMapper.insert(actionLog);
+                }
             }
         } catch (IOException | NoSuchMethodException e) {
             e.printStackTrace();
+            msg.setError("验证失败,请检验数据格式是否正确");
         } catch (IllegalAccessException e) {
             e.printStackTrace();
         } catch (InvocationTargetException e) {
             e.printStackTrace();
         } catch (Exception e) {
             e.printStackTrace();
-            msg.setError("验证失败");
+            msg.setError("验证失败,请检验数据格式是否正确");
             return msg;
         }
         return msg;
     }
 
+
     @Override
     public HttpRespMsg exportData(Clue clue) throws Exception {
-        User user = userMapper.selectById(request.getHeader("token"));
-        SysForm sysForm = sysFormMapper.selectOne(new LambdaQueryWrapper<SysForm>().eq(SysForm::getCompanyId, user.getCompanyId()).eq(SysForm::getCode, "Thread").eq(SysForm::getIsCurrent, 1));
-        WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, user.getCompanyId()));
-        String config = sysForm.getConfig();
-        JSONObject configOb = JSON.parseObject(config);
-        JSONArray configObJSONArray = configOb.getJSONArray("list");
-        List<List<String>> dataList=new ArrayList<>();
-        List<String> titleList=new ArrayList<>();
-        for (int i = 0; i < configObJSONArray.size(); i++) {
-            JSONObject item = configObJSONArray.getJSONObject(i);
-            titleList.add(item.getString("label"));
-        }
-        dataList.add(titleList);
-        List<Clue> list1 = getList(clue);
-        for (Clue clue1 : list1) {
-            List<String> item=new ArrayList<>();
-            for (int i = 0; i < configObJSONArray.size(); i++) {
-                JSONObject target = configObJSONArray.getJSONObject(i);
-                if(target.getString("type").equals("grid")){
-                    JSONArray columns = target.getJSONArray("columns");
-                    for (int i1 = 0; i1 < columns.size(); i1++) {
-                        JSONObject columnsJSONObject = columns.getJSONObject(i1);
-                        JSONArray list = columnsJSONObject.getJSONArray("list");
-                        for (int i2 = 0; i2 < list.size(); i2++) {
-                            JSONObject object = list.getJSONObject(i2);
-                            String model = object.getString("model");
-                            String targetName = model.substring(0, 1).toUpperCase() + model.substring(1);
-                            Class<? extends Clue> aClass = clue1.getClass();
-                            String value = String.valueOf(aClass.getMethod("get" + targetName).invoke(clue1)==null?"":aClass.getMethod("get" + targetName).invoke(clue1));
-                            if(model.equals("inchargerId")){
-                                if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
-                                    value = "$userName"+String.valueOf(aClass.getMethod("getInchargerName").invoke(clue1))+"$";
-                                }else {
-                                    value = String.valueOf(aClass.getMethod("getInchargerName").invoke(clue1));
-                                }
-                            }
-                            item.add(value);
-                        }
-                    }
-                }else {
-                    String model = target.getString("model");
-                    String targetName = model.substring(0, 1).toUpperCase() + model.substring(1);
-                    Class<? extends Clue> aClass = clue1.getClass();
-                    String value = String.valueOf(aClass.getMethod("get" + targetName).invoke(clue1)==null?"":aClass.getMethod("get" + targetName).invoke(clue1));
-                    if(model.equals("inchargerId")){
-                        if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
-                            value = "$userName"+String.valueOf(aClass.getMethod("getInchargerName").invoke(clue1))+"$";
-                        }else {
-                            value = String.valueOf(aClass.getMethod("getInchargerName").invoke(clue1));
-                        }
-                    }
-                    item.add(value);
-                }
-            }
-            dataList.add(item);
-        }
-        String fileName="线索表导出_"+ System.currentTimeMillis();
-        return excelExportService.exportGeneralExcelByTitleAndList(wxCorpInfo,fileName,dataList,path);
+       return  null;
     }
 
     @Override

+ 140 - 65
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/CustomServiceImpl.java

@@ -117,6 +117,12 @@ public class CustomServiceImpl extends ServiceImpl<CustomMapper, Custom> impleme
             ) > 0) {
                 msg.setError("电话号码重复了");
                 return msg;
+            } if (customMapper.selectCount(new QueryWrapper<Custom>()
+                    .eq("company_phone", custom.getCompanyPhone())
+                    .ne("company_phone", custom1.getCompanyPhone())
+            ) > 0) {
+                msg.setError("电话号码重复了");
+                return msg;
             }
             ActionLog actionLog = new ActionLog();
             actionLog.setCode("custom");
@@ -341,7 +347,9 @@ public class CustomServiceImpl extends ServiceImpl<CustomMapper, Custom> impleme
         custom.setIsDelete(0);
         custom.setUserId(user.getId());
         custom.setEndTime(custom.getEndTime() + " 23:59:59");
-        custom.setPageIndex((custom.getPageIndex() - 1) * custom.getPageFrom());
+        if (custom.getPageIndex()!=null){
+            custom.setPageIndex((custom.getPageIndex() - 1) * custom.getPageFrom());
+        }
         boolean isAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全部客户");
         boolean isNotAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看负责部门客户");
         List<Custom> list = new ArrayList<>();
@@ -616,14 +624,21 @@ public class CustomServiceImpl extends ServiceImpl<CustomMapper, Custom> impleme
 
     @Override
     public HttpRespMsg importData(MultipartFile multipartFile) {
-        HttpRespMsg msg = new HttpRespMsg();
+        HttpRespMsg msg=new HttpRespMsg();
+        if(!multipartFile.getOriginalFilename().endsWith(".xlsx")){
+            msg.setError("文件格式错误,请使用.xlsx格式的Excel文件进行导入");
+            return msg;
+        }
         String fileName = multipartFile.getOriginalFilename();
         File file = new File(fileName == null ? "file" : fileName);
         User user = userMapper.selectById(request.getHeader("token"));
         Integer companyId = user.getCompanyId();
         WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, companyId));
         List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
-        List<SysDict> sysDictOfClueSources = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "ClueSources"));
+        List<SysDict> sysSources = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "ClueSources"));
+        List<SysDict> sysIndutryId = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "CustomIndustry"));
+        List<SysDict> levels = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "CustomLevel"));
+
         InputStream inputStream = null;
         OutputStream outputStream = null;
         try {
@@ -644,16 +659,35 @@ public class CustomServiceImpl extends ServiceImpl<CustomMapper, Custom> impleme
             int rowNum = sheet.getLastRowNum();
             //获取当前表单模板 校验规则
             SysForm sysForm = sysFormMapper.selectOne(new LambdaQueryWrapper<SysForm>().eq(SysForm::getCode, "Customer").eq(SysForm::getCompanyId, companyId).eq(SysForm::getIsCurrent, 1));
-            if (sysForm == null) {
+            if(sysForm==null){
                 msg.setError("当前模块未配置自定义模板,需先完成配置");
                 return msg;
             }
             String config = sysForm.getConfig();
             JSONObject configOb = JSON.parseObject(config);
             JSONArray configObJSONArray = configOb.getJSONArray("list");
-            List<String> userNameList = new ArrayList<>();
-            HttpRespMsg respMsg = new HttpRespMsg();
-            for (int rowIndex = 0; rowIndex <= rowNum; rowIndex++) {
+            //可能存在栅格布局的情况需要特殊处理
+            List<String> modelNameList=new ArrayList<>();
+            for (int i = 0; i < configObJSONArray.size(); i++) {
+                JSONObject jsonObject = configObJSONArray.getJSONObject(i);
+                if(jsonObject.getString("type").equals("grid")){
+                    JSONArray columns = jsonObject.getJSONArray("columns");
+                    for (int i1 = 0; i1 < columns.size(); i1++) {
+                        JSONObject columnsJSONObject = columns.getJSONObject(i1);
+                        JSONArray list = columnsJSONObject.getJSONArray("list");
+                        for (int i2 = 0; i2 < list.size(); i2++) {
+                            JSONObject object = list.getJSONObject(i2);
+                            modelNameList.add(object.getString("model"));
+                        }
+                    }
+                }else {
+                    modelNameList.add(jsonObject.getString("model"));
+                }
+            }
+            List<Custom> importProductList = new ArrayList<>();
+            List<String> userNameList=new ArrayList<>();
+            HttpRespMsg respMsg=new HttpRespMsg();
+            for (int rowIndex = 1; rowIndex <= rowNum; rowIndex++) {
                 XSSFRow row = sheet.getRow(rowIndex);
                 if (row == null) {
                     continue;
@@ -665,37 +699,25 @@ public class CustomServiceImpl extends ServiceImpl<CustomMapper, Custom> impleme
                 //获取到当前行的列数据
                 int cellNum = row.getLastCellNum();
                 for (int i = 0; i < cellNum; i++) {
-                    JSONObject item = configObJSONArray.getJSONObject(i);
-                    String modelName = item.getString("model");
+                    String modelName = modelNameList.get(i);
                     XSSFCell cell = row.getCell(i);
-                    if (cell != null) {
-                        switch (item.getString("type")) {
-//                            case "time":cell.setCellType(CellType.NUMERIC);
-//                                break;
-                            default:
-                                cell.setCellType(CellType.STRING);
-                        }
-                    }
-                    if (modelName.equals("inchargerId")) {
-                        System.out.println("=====");
-                        System.out.println(modelName);
-                        System.out.println(cell.toString());
-                        if (!StringUtils.isEmpty(cell.getStringCellValue())) {
+                    if(modelName.equals("inchargerId")){
+                        if(!org.springframework.util.StringUtils.isEmpty(cell.getStringCellValue())){
                             userNameList.add(cell.getStringCellValue());
                         }
                     }
 
                 }
             }
-            System.out.println("参与搜索的人员列表" + userNameList + userNameList.size());
-            if (wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1 && userNameList.size() > 0) {
-                respMsg = wxCorpInfoService.getBatchSearchUserInfo(wxCorpInfo, userNameList, null);
-                if (respMsg.code.equals("0")) {
-                    msg.setError("姓名为[" + String.valueOf(respMsg.data) + "]的人员存在重复,请使用工号!");
+            System.out.println("参与搜素的人员列表"+userNameList + userNameList.size());
+            if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1&&userNameList.size()>0){
+                respMsg = wxCorpInfoService.getBatchSearchUserInfo(wxCorpInfo, userNameList,null);
+                if(respMsg.code.equals("0")){
+                    msg.setError("姓名为["+String.valueOf(respMsg.data)+"]的人员存在重复,请使用工号!");
                     return msg;
                 }
             }
-            List<User> targetUserList = (List<User>) respMsg.data;
+            List<User> targetUserList= (List<User>) respMsg.data;
             //直接忽略空行 从row1开始
             for (int rowIndex = 1; rowIndex <= rowNum; rowIndex++) {
                 XSSFRow row = sheet.getRow(rowIndex);
@@ -708,71 +730,124 @@ public class CustomServiceImpl extends ServiceImpl<CustomMapper, Custom> impleme
                 }
                 //获取到当前行的列数据
                 int cellNum = row.getLastCellNum();
-                Custom custom = new Custom();
-                custom.setCompanyId(companyId);
-                custom.setCreateTime(new Date());
-                custom.setCreatorId(user.getId());
+                Custom product=new Custom();
+                product.setCompanyId(companyId);
+                product.setCreatorId(user.getId());
+                product.setIsDelete(0);
+
+                product.setCreateTime(new Date());
+                JSONArray objects=new JSONArray();
+                for (int i = 0; i < configObJSONArray.size(); i++) {
+                    JSONObject jsonObject = configObJSONArray.getJSONObject(i);
+                    if(jsonObject.getString("type").equals("grid")){
+                        JSONArray columns = jsonObject.getJSONArray("columns");
+                        for (int i1 = 0; i1 < columns.size(); i1++) {
+                            JSONObject jsonObject1 = columns.getJSONObject(i1).getJSONArray("list").getJSONObject(0);
+                            objects.add(jsonObject1);
+                        }
+                    }else {
+                        objects.add(jsonObject);
+                    }
+                }
                 for (int i = 0; i < cellNum; i++) {
-                    JSONObject item = configObJSONArray.getJSONObject(i);
+                    JSONObject item = objects.getJSONObject(i);
                     String modelName = item.getString("model");
                     String className = modelName.substring(0, 1).toUpperCase() + modelName.substring(1);
-                    String getter = "get" + className;
-                    String setter = "set" + className;
+                    String getter="get"+className;
+                    String setter="set"+className;
                     XSSFCell cell = row.getCell(i);
-                    if (cell != null) {
-                        switch (item.getString("type")) {
-
-                            default:
-                                cell.setCellType(CellType.STRING);
-                        }
-                    }
-                    //校验当前列是否为必填
-                    JSONObject options = item.getJSONObject("options");
-                    JSONObject rules = options.getJSONObject("rules");
-                    Boolean required = rules.getBoolean("required");
-                    if (required) {
-                        if (StringUtils.isEmpty(cell.getStringCellValue())) {
-                            msg.setError(item.getString("label") + "值不能为空值");
-                            return msg;
+                    if(cell!=null){
+                        switch (item.getString("type")){
+//                            case "time":cell.setCellType(CellType.NUMERIC);
+//                                break;
+                            //默认读取所有数据都是文本格式
+                            default:cell.setCellType(CellType.STRING);
                         }
                     }
-                    if (modelName.equals("inchargerId")) {
-                        if (!StringUtils.isEmpty(cell.getStringCellValue())) {
+                    if(modelName.equals("inchargerId")){
+                        if(!org.springframework.util.StringUtils.isEmpty(cell.getStringCellValue())){
                             String userName = cell.getStringCellValue();
                             Optional<User> first;
-                            if (wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1) {
+                            if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
                                 Optional<User> optional = targetUserList.stream().filter(tl -> tl.getName().equals(userName)).findFirst();
-                                first = userList.stream().filter(u -> (u.getJobNumber() != null && u.getJobNumber().equals(userName)) || (optional.isPresent() && u.getCorpwxUserid() != null && u.getCorpwxUserid().equals(optional.get().getCorpwxUserid()))).findFirst();
-                            } else {
-                                first = userList.stream().filter(u -> u.getName().equals(userName) || (u.getJobNumber() != null && u.getJobNumber().equals(userName))).findFirst();
+                                first= userList.stream().filter(u ->(u.getJobNumber()!=null&&u.getJobNumber().equals(userName))||(optional.isPresent()&&u.getCorpwxUserid()!=null&&u.getCorpwxUserid().equals(optional.get().getCorpwxUserid()))).findFirst();
+                            }else {
+                                first= userList.stream().filter(u -> u.getName().equals(userName)||(u.getJobNumber()!=null&&u.getJobNumber().equals(userName))).findFirst();
                             }
                             if (first.isPresent()) {
-                                custom.setInchargerId(first.get().getId());
+                                product.setInchargerId(first.get().getId());
                             } else {
-                                msg.setError("负责人[" + userName + "]在系统中不存在");
+                                msg.setError("负责人["+userName+"]在系统中不存在");
                                 return msg;
                             }
                         }
-                    } else {
-                        if (!StringUtils.isEmpty(cell.getStringCellValue())) {
-                            Class<Clue> clueClass = Clue.class;
-                            Method method = clueClass.getMethod(setter, String.class);
-                            method.invoke(custom, cell.getStringCellValue());
+                    }else if(modelName.equals("customSourceId")){
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Optional<SysDict> first = sysSources.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
+                            if(first.isPresent()){
+                                product.setCustomSourceId(first.get().getId());
+                            }else {
+                                msg.setError("线索来源["+cell.getStringCellValue()+"]不存在,请在系统字典中增加");
+                                return msg;
+                            }
+                        }
+                    }else if(modelName.equals("customerIndustryId")){
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Optional<SysDict> first = sysIndutryId.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
+                            if(first.isPresent()){
+                                product.setCustomerIndustryId(first.get().getId());
+                            }else {
+                                msg.setError("客户行业["+cell.getStringCellValue()+"]不存在,请在系统字典中增加");
+                                return msg;
+                            }
+                        }
+                    }else if(modelName.equals("customerLevelId")){
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Optional<SysDict> first = levels.stream().filter(s -> s.getName().equals(cell.getStringCellValue())).findFirst();
+                            if(first.isPresent()){
+                                product.setCustomerLevelId(first.get().getId());
+                            }else {
+                                msg.setError("客户级别["+cell.getStringCellValue()+"]不存在,请在系统字典中增加");
+                                return msg;
+                            }
+                        }
+                    }else {
+                        String stringCellValue = cell.getStringCellValue();
+                        System.out.println(stringCellValue+"=============");
+                        if(!StringUtils.isEmpty(cell.getStringCellValue())){
+                            Class<Custom> productClass = Custom.class;
+                            Method method = productClass.getMethod(setter,String.class);
+                            method.invoke(product,cell.getStringCellValue());
                         }
                     }
 
                 }
-                customMapper.insert(custom);
+                importProductList.add(product);
+            }
+            if(importProductList.size()>0){
+                if(!saveOrUpdateBatch(importProductList)){
+                    msg.setError("验证失败,请检验数据格式是否正确");
+                    return msg;
+                }
+                for (Custom bo : importProductList) {
+                    ActionLog actionLog = new ActionLog();
+                    actionLog.setName("新增了商机");
+                    actionLog.setItemId(bo.getId());
+                    actionLog.setCode("custom");
+                    actionLog.setUserId(user.getId());
+                    actionLogMapper.insert(actionLog);
+                }
             }
         } catch (IOException | NoSuchMethodException e) {
             e.printStackTrace();
+            msg.setError("验证失败,请检验数据格式是否正确");
         } catch (IllegalAccessException e) {
             e.printStackTrace();
         } catch (InvocationTargetException e) {
             e.printStackTrace();
         } catch (Exception e) {
             e.printStackTrace();
-            msg.setError("验证失败");
+            msg.setError("验证失败,请检验数据格式是否正确");
             return msg;
         }
         return msg;

+ 16 - 3
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ProductServiceImpl.java

@@ -98,8 +98,8 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
         if(!hasPriviledgeAll){
             //判断查看负责部门的权限
             if(!hasPriviledgeDept){
-                //都没有就只能看自己创建的
-                queryWrapper.eq(Product::getCreatorId,targetUsr.getId());
+                //都没有就只能看自己创建的或者负责的
+                queryWrapper.and(wrapper->wrapper.eq(Product::getCreatorId,targetUsr.getId()).or().eq(Product::getInchargerId,targetUsr.getId()));
             }else {
                 List<Department> departmentList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getManagerId, targetUsr.getId()));
                 List<DepartmentOtherManager> otherManagerList = departmentOtherManagerMapper.selectList(new LambdaQueryWrapper<DepartmentOtherManager>().eq(DepartmentOtherManager::getOtherManagerId, targetUsr.getId()));
@@ -289,8 +289,21 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
                 Product product=new Product();
                 product.setCompanyId(companyId);
                 product.setCreatorId(user.getId());
+                JSONArray objects=new JSONArray();
+                for (int i = 0; i < configObJSONArray.size(); i++) {
+                    JSONObject jsonObject = configObJSONArray.getJSONObject(i);
+                    if(jsonObject.getString("type").equals("grid")){
+                        JSONArray columns = jsonObject.getJSONArray("columns");
+                        for (int i1 = 0; i1 < columns.size(); i1++) {
+                            JSONObject jsonObject1 = columns.getJSONObject(i1).getJSONArray("list").getJSONObject(0);
+                            objects.add(jsonObject1);
+                        }
+                    }else {
+                        objects.add(jsonObject);
+                    }
+                }
                 for (int i = 0; i < cellNum; i++) {
-                    JSONObject item = configObJSONArray.getJSONObject(i);
+                    JSONObject item = objects.getJSONObject(i);
                     String modelName = item.getString("model");
                     String className = modelName.substring(0, 1).toUpperCase() + modelName.substring(1);
                     String getter="get"+className;

+ 56 - 47
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/SalesOrderServiceImpl.java

@@ -408,8 +408,21 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
                 SalesOrder order=new SalesOrder();
                 order.setCompanyId(companyId);
                 order.setCreatorId(user.getId());
+                JSONArray objects=new JSONArray();
+                for (int i = 0; i < configObJSONArray.size(); i++) {
+                    JSONObject jsonObject = configObJSONArray.getJSONObject(i);
+                    if(jsonObject.getString("type").equals("grid")){
+                        JSONArray columns = jsonObject.getJSONArray("columns");
+                        for (int i1 = 0; i1 < columns.size(); i1++) {
+                            JSONObject jsonObject1 = columns.getJSONObject(i1).getJSONArray("list").getJSONObject(0);
+                            objects.add(jsonObject1);
+                        }
+                    }else {
+                        objects.add(jsonObject);
+                    }
+                }
                 for (int i = 0; i < cellNum; i++) {
-                    JSONObject item = configObJSONArray.getJSONObject(i);
+                    JSONObject item = objects.getJSONObject(i);
                     String modelName = item.getString("model");
                     String className = modelName.substring(0, 1).toUpperCase() + modelName.substring(1);
                     String getter="get"+className;
@@ -766,17 +779,17 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
             switch (queryType){
                 case 0:
                     //仅本人
-                    customLambdaQueryWrapper.eq(Custom::getCreatorId,user.getId());
-                    contactsLambdaQueryWrapper.eq(Contacts::getCreatorId,user.getId());
-                    businessOpportunityLambdaQueryWrapper.eq(BusinessOpportunity::getCreatorId,user.getId());
-                    salesOrderLambdaQueryWrapper.eq(SalesOrder::getCreatorId,user.getId());
-                    clueLambdaQueryWrapper.eq(Clue::getCreateId,user.getId());
+                    customLambdaQueryWrapper.eq(Custom::getInchargerId,user.getId());
+                    contactsLambdaQueryWrapper.eq(Contacts::getOwnerId,user.getId());
+                    businessOpportunityLambdaQueryWrapper.eq(BusinessOpportunity::getInchargerId,user.getId());
+                    salesOrderLambdaQueryWrapper.eq(SalesOrder::getInchargerId,user.getId());
+                    clueLambdaQueryWrapper.eq(Clue::getInchargerId,user.getId());
 
-                    customLambdaQueryWrapper1.eq(Custom::getCreatorId,user.getId());
-                    contactsLambdaQueryWrapper1.eq(Contacts::getCreatorId,user.getId());
-                    businessOpportunityLambdaQueryWrapper1.eq(BusinessOpportunity::getCreatorId,user.getId());
-                    salesOrderLambdaQueryWrapper1.eq(SalesOrder::getCreatorId,user.getId());
-                    clueLambdaQueryWrapper1.eq(Clue::getCreateId,user.getId());
+                    customLambdaQueryWrapper1.eq(Custom::getInchargerId,user.getId());
+                    contactsLambdaQueryWrapper1.eq(Contacts::getOwnerId,user.getId());
+                    businessOpportunityLambdaQueryWrapper1.eq(BusinessOpportunity::getInchargerId,user.getId());
+                    salesOrderLambdaQueryWrapper1.eq(SalesOrder::getInchargerId,user.getId());
+                    clueLambdaQueryWrapper1.eq(Clue::getInchargerId,user.getId());
                     break;
                 case 1:
                     //本人及下属
@@ -786,17 +799,17 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
                     List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().in(User::getDepartmentId, deptIds));
                     List<String> userIds = userList.stream().map(User::getId).distinct().collect(Collectors.toList());
                     userIds.add(user.getId());
-                    customLambdaQueryWrapper.in(Custom::getCreatorId,userIds);
-                    contactsLambdaQueryWrapper.in(Contacts::getCreatorId,userIds);
-                    businessOpportunityLambdaQueryWrapper.in(BusinessOpportunity::getCreatorId,userIds);
-                    salesOrderLambdaQueryWrapper.in(SalesOrder::getCreatorId,userIds);
-                    clueLambdaQueryWrapper.in(Clue::getCreateId,userIds);
+                    customLambdaQueryWrapper.in(Custom::getInchargerId,userIds);
+                    contactsLambdaQueryWrapper.in(Contacts::getOwnerId,userIds);
+                    businessOpportunityLambdaQueryWrapper.in(BusinessOpportunity::getInchargerId,userIds);
+                    salesOrderLambdaQueryWrapper.in(SalesOrder::getInchargerId,userIds);
+                    clueLambdaQueryWrapper.in(Clue::getInchargerId,userIds);
 
-                    customLambdaQueryWrapper1.in(Custom::getCreatorId,userIds);
-                    contactsLambdaQueryWrapper1.in(Contacts::getCreatorId,userIds);
-                    businessOpportunityLambdaQueryWrapper1.in(BusinessOpportunity::getCreatorId,userIds);
-                    salesOrderLambdaQueryWrapper1.in(SalesOrder::getCreatorId,userIds);
-                    clueLambdaQueryWrapper1.in(Clue::getCreateId,userIds);
+                    customLambdaQueryWrapper1.in(Custom::getInchargerId,userIds);
+                    contactsLambdaQueryWrapper1.in(Contacts::getOwnerId,userIds);
+                    businessOpportunityLambdaQueryWrapper1.in(BusinessOpportunity::getInchargerId,userIds);
+                    salesOrderLambdaQueryWrapper1.in(SalesOrder::getInchargerId,userIds);
+                    clueLambdaQueryWrapper1.in(Clue::getInchargerId,userIds);
                     break;
                 case 2:
                     //仅本部门
@@ -804,17 +817,17 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
                     List<User> users = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getDepartmentId, targetDeptId));
                     List<String> targetUserIds = users.stream().map(User::getId).distinct().collect(Collectors.toList());
                     targetUserIds.add(user.getId());
-                    customLambdaQueryWrapper.in(Custom::getCreatorId,targetUserIds);
-                    contactsLambdaQueryWrapper.in(Contacts::getCreatorId,targetUserIds);
-                    businessOpportunityLambdaQueryWrapper.in(BusinessOpportunity::getCreatorId,targetUserIds);
-                    salesOrderLambdaQueryWrapper.in(SalesOrder::getCreatorId,targetUserIds);
-                    clueLambdaQueryWrapper.in(Clue::getCreateId,targetUserIds);
+                    customLambdaQueryWrapper.in(Custom::getInchargerId,targetUserIds);
+                    contactsLambdaQueryWrapper.in(Contacts::getOwnerId,targetUserIds);
+                    businessOpportunityLambdaQueryWrapper.in(BusinessOpportunity::getInchargerId,targetUserIds);
+                    salesOrderLambdaQueryWrapper.in(SalesOrder::getInchargerId,targetUserIds);
+                    clueLambdaQueryWrapper.in(Clue::getInchargerId,targetUserIds);
 
-                    customLambdaQueryWrapper1.in(Custom::getCreatorId,targetUserIds);
-                    contactsLambdaQueryWrapper1.in(Contacts::getCreatorId,targetUserIds);
-                    businessOpportunityLambdaQueryWrapper1.in(BusinessOpportunity::getCreatorId,targetUserIds);
-                    salesOrderLambdaQueryWrapper1.in(SalesOrder::getCreatorId,targetUserIds);
-                    clueLambdaQueryWrapper1.in(Clue::getCreateId,targetUserIds);
+                    customLambdaQueryWrapper1.in(Custom::getInchargerId,targetUserIds);
+                    contactsLambdaQueryWrapper1.in(Contacts::getOwnerId,targetUserIds);
+                    businessOpportunityLambdaQueryWrapper1.in(BusinessOpportunity::getInchargerId,targetUserIds);
+                    salesOrderLambdaQueryWrapper1.in(SalesOrder::getInchargerId,targetUserIds);
+                    clueLambdaQueryWrapper1.in(Clue::getInchargerId,targetUserIds);
                     break;
                 case 3:
                     //本部门及下属部门
@@ -823,17 +836,17 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
                     List<User> users1 = userMapper.selectList(new LambdaQueryWrapper<User>().in(User::getDepartmentId, branchDepartment));
                     List<String> targetUserIds1 = users1.stream().map(User::getId).distinct().collect(Collectors.toList());
                     targetUserIds1.add(user.getId());
-                    customLambdaQueryWrapper.in(Custom::getCreatorId,targetUserIds1);
-                    contactsLambdaQueryWrapper.in(Contacts::getCreatorId,targetUserIds1);
-                    businessOpportunityLambdaQueryWrapper.in(BusinessOpportunity::getCreatorId,targetUserIds1);
-                    salesOrderLambdaQueryWrapper.in(SalesOrder::getCreatorId,targetUserIds1);
-                    clueLambdaQueryWrapper.in(Clue::getCreateId,targetUserIds1);
+                    customLambdaQueryWrapper.in(Custom::getInchargerId,targetUserIds1);
+                    contactsLambdaQueryWrapper.in(Contacts::getOwnerId,targetUserIds1);
+                    businessOpportunityLambdaQueryWrapper.in(BusinessOpportunity::getInchargerId,targetUserIds1);
+                    salesOrderLambdaQueryWrapper.in(SalesOrder::getInchargerId,targetUserIds1);
+                    clueLambdaQueryWrapper.in(Clue::getInchargerId,targetUserIds1);
 
-                    customLambdaQueryWrapper1.in(Custom::getCreatorId,targetUserIds1);
-                    contactsLambdaQueryWrapper1.in(Contacts::getCreatorId,targetUserIds1);
-                    businessOpportunityLambdaQueryWrapper1.in(BusinessOpportunity::getCreatorId,targetUserIds1);
-                    salesOrderLambdaQueryWrapper1.in(SalesOrder::getCreatorId,targetUserIds1);
-                    clueLambdaQueryWrapper1.in(Clue::getCreateId,targetUserIds1);
+                    customLambdaQueryWrapper1.in(Custom::getInchargerId,targetUserIds1);
+                    contactsLambdaQueryWrapper1.in(Contacts::getOwnerId,targetUserIds1);
+                    businessOpportunityLambdaQueryWrapper1.in(BusinessOpportunity::getInchargerId,targetUserIds1);
+                    salesOrderLambdaQueryWrapper1.in(SalesOrder::getInchargerId,targetUserIds1);
+                    clueLambdaQueryWrapper1.in(Clue::getInchargerId,targetUserIds1);
                     break;
             }
         }
@@ -891,7 +904,7 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
     }
 
     @Override
-    public HttpRespMsg dataSummary(Integer queryType, Integer dateType) {
+    public HttpRespMsg dataSummary(Integer queryType, Integer dateType,String startDate,String endDate) {
         HttpRespMsg msg=new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("token"));
         DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
@@ -899,8 +912,6 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
         List<Department> allDeptList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, companyId));
         String userId=null;
         List<String> targetUserIds=new ArrayList<>();
-        String startDate=null;
-        String endDate=null;
         if(dateType!=null){
             switch (dateType){
                 case 0:
@@ -1008,7 +1019,7 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
     }
 
     @Override
-    public HttpRespMsg businessOpportunityStage(Integer queryType, Integer dateType) {
+    public HttpRespMsg businessOpportunityStage(Integer queryType, Integer dateType,String startDate,String endDate) {
         HttpRespMsg msg=new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("token"));
         DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
@@ -1016,8 +1027,6 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
         List<Department> allDeptList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, companyId));
         String userId=null;
         List<String> targetUserIds=new ArrayList<>();
-        String startDate=null;
-        String endDate=null;
         if(dateType!=null){
             switch (dateType){
                 case 0:

+ 3 - 3
fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/BusinessOpportunityMapper.xml

@@ -45,7 +45,7 @@
         <if test="name != null and name != ''">
             and `name` LIKE CONCAT('%', #{name}, '%')
         </if>
-        <if test="inchargerId != null and inchargerId == '' ">
+        <if test="inchargerId != null and inchargerId != '' ">
             and incharger_id = #{inchargerId}
         </if>
         <if test="startTime != null and endTime != null ">
@@ -55,7 +55,7 @@
             and contacts_id in (select id from contacts where `name`LIKE CONCAT('%', #{contactsName}, '%'))
         </if>
         <if test="customerName != null and customerName != ''">
-            and customer_id in (select id from custom where `name`LIKE CONCAT('%', #{customerName}, '%'))
+            and customer_id in (select id from custom where `custom_name`LIKE CONCAT('%', #{customerName}, '%'))
         </if>
         <if test="stageId != null ">
             and stage_id = #{stageId}
@@ -75,7 +75,7 @@
         <if test="name != null and name != ''">
             and `name` LIKE CONCAT('%', #{name}, '%')
         </if>
-        <if test="inchargerId != null ">
+        <if test="inchargerId != null and inchargerId != ''">
             and incharger_id = #{inchargerId}
         </if>
         <if test="startTime != null and endTime != null ">

+ 6 - 6
fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/ClueMapper.xml

@@ -59,7 +59,7 @@
         from clue c
         left join sys_dict sd on c.customer_level_id = sd.id
         where
-            c.company_id = #{companyId} and is_delete = #{isDelete}
+            c.company_id = #{companyId} and is_delete = #{isDelete} and c.is_bo = 0
         <if test="inchargerId != null and inchargerId != ''  ">
            and c.incharger_id =#{inchargerId}
         </if>
@@ -130,7 +130,7 @@
         from clue c
         left join sys_dict sd on c.customer_level_id = sd.id
         where
-        c.company_id = #{clue.companyId} and is_delete = #{clue.isDelete}
+        c.company_id = #{clue.companyId} and c.is_delete = #{clue.isDelete} and c.is_bo = 0
         and (c.incharger_id in
         (SELECT id from `user` WHERE department_id = (SELECT department_id from `user` WHERe id = #{userId}))
         or c.incharger_id is null)
@@ -204,7 +204,7 @@
         from clue c
         left join sys_dict sd on c.customer_level_id = sd.id
         where
-        c.company_id = #{clue.companyId} and c.is_delete = #{clue.isDelete}
+        c.company_id = #{clue.companyId} and c.is_delete = #{clue.isDelete} and c.is_bo = 0
         and (c.incharger_id = #{userId} or c.incharger_id is null)
         <if test="clue.inchargerId != null and clue.inchargerId != ''  ">
           and c.incharger_id =#{clue.inchargerId}
@@ -251,7 +251,7 @@
         select count(*)
         from clue c
         where
-        company_id = #{companyId} and is_delete = #{isDelete}
+        company_id = #{companyId} and is_delete = #{isDelete} and is_bo = 0
         <if test="inchargerId != null and inchargerId != ''  ">
             and incharger_id = #{inchargerId}
         </if>
@@ -282,7 +282,7 @@
         COUNT(c.id)
         from clue c
         where
-        c.company_id = #{clue.companyId} and is_delete = #{clue.isDelete}
+        c.company_id = #{clue.companyId} and c.is_delete = #{clue.isDelete} and c.is_bo = 0
         and c.incharger_id in
         (SELECT id from `user` WHERE department_id = (SELECT department_id from `user` WHERe id = #{userId}))
         and c.incharger_id is null
@@ -316,7 +316,7 @@
             count(c.id)
         from clue c
         where
-        c.company_id = #{clue.companyId} and c.is_delete = #{clue.isDelete}
+        c.company_id = #{clue.companyId} and c.is_delete = #{clue.isDelete} and c.is_bo = 0
         and (c.incharger_id = #{userId} or c.incharger_id is null)
         <if test="clue.inchargerId != null and clue.inchargerId != ''  ">
             and c.incharger_id =#{clue.inchargerId}

+ 6 - 6
fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/CustomMapper.xml

@@ -82,7 +82,7 @@
             and c.email LIKE CONCAT('%', #{email}, '%')
         </if>
         <if test="companyPhone != null and companyPhone != '' ">
-            and c.company_phone = #{companyPhone}
+            and c.company_phone LIKE CONCAT('%', #{companyPhone}, '%')
         </if>
         <if test="customerLevelId != null ">
             and c.customer_level_id = #{customerLevelId}
@@ -130,7 +130,7 @@
             and email = #{email}
         </if>
         <if test="companyPhone != null ">
-            and company_phone = #{companyPhone}
+            and company_phone LIKE CONCAT('%', #{companyPhone}, '%')
         </if>
         <if test="customerLevelId != null ">
             and customer_level_id = #{customerLevelId}
@@ -184,7 +184,7 @@
             and c.email LIKE CONCAT('%', #{email}, '%')
         </if>
         <if test="companyPhone != null ">
-            and c.company_phone = #{companyPhone}
+            and c.company_phone LIKE CONCAT('%', #{companyPhone}, '%')
         </if>
         <if test="customerLevelId != null ">
             and c.customer_level_id = #{customerLevelId}
@@ -235,7 +235,7 @@
             and email = #{email}
         </if>
         <if test="companyPhone != null ">
-            and company_phone = #{companyPhone}
+            and company_phone LIKE CONCAT('%', #{companyPhone}, '%')
         </if>
         <if test="customerLevelId != null ">
             and customer_level_id = #{customerLevelId}
@@ -287,7 +287,7 @@
             and email LIKE CONCAT('%', #{email}, '%')
         </if>
         <if test="companyPhone != null ">
-            and company_phone = #{companyPhone}
+            and company_phone LIKE CONCAT('%', #{companyPhone}, '%')
         </if>
         <if test="customerLevelId != null ">
             and customer_level_id = #{customerLevelId}
@@ -323,7 +323,7 @@
             and email = #{email}
         </if>
         <if test="companyPhone != null ">
-            and company_phone = #{companyPhone}
+            and company_phone LIKE CONCAT('%', #{companyPhone}, '%')
         </if>
         <if test="customerLevelId != null ">
             and customer_level_id = #{customerLevelId}

+ 1 - 1
fhKeeper/formulahousekeeper/management-platform-import/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -3987,7 +3987,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     }
                     Optional<SubProject> subProject = allSubProjectList.stream().filter(al -> al.getName().equals(row.getCell(4).getStringCellValue())&&al.getProjectId().equals(project.get().getId())).findFirst();
                     if(!subProject.isPresent()){
-                        msg.setError("子项目["+subProject.get().getName()+"]不属于项目["+project.get().getProjectName()+"]");
+                        msg.setError("子项目["+row.getCell(4).getStringCellValue()+"]不属于项目["+project.get().getProjectName()+"]");
                         return msg;
                     }
                     subP=subProject.get();

+ 2 - 2
fhKeeper/formulahousekeeper/management-platform-import/src/main/resources/application.yml

@@ -15,9 +15,9 @@ spring:
       location: C:/upload/
   datasource:
     driver-class-name: com.mysql.cj.jdbc.Driver
-    url: jdbc:mysql://47.101.180.183:3306/man_import?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&useSSL=false
+    url: jdbc:mysql://47.101.180.183:17089/man_import?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&useSSL=false
     username: root
-    password: HuoshiDB@2022
+    password: P011430@Huoshi*
     hikari:
       maximum-pool-size: 60
       minimum-idle: 10

+ 28 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java

@@ -172,7 +172,9 @@ public class ProjectController {
                                    Double outputValue,
                                    Integer deptId,
                                    @RequestParam(defaultValue = "false") boolean onlyChangeParticipate,
-                                   String buId,Double manDay,String  manDayStartDate,String plate1,
+                                   String buId,Double manDay,String  manDayStartDate,
+                                   String reviwerId,
+                                   String plate1,
                                    String plate2,
                                    String plate3,
                                    String plate4,
@@ -185,7 +187,7 @@ public class ProjectController {
         return projectService.editProject(id, name, code, userId, inchargerId, isPublic, planStartDate, planEndDate, level, contractAmount,changeContractReason,
                 projectBaseCostData,projectKeyNodesData,
                  budget,customerId,chosenLeaders, associateDegrees, associateDegreeNames,
-                taskGpIncharge,auditUserIds, ccUserIds, category, projectDesc,projectMainId, providerIds, providerNames, request,projectSeparate,outputValue,deptId,onlyChangeParticipate,buId,manDay,manDayStartDate,plate1,plate2,plate3,plate4,plate5,plate6,plate7,plate8,plate9,plate10);
+                taskGpIncharge,auditUserIds, ccUserIds, category, projectDesc,projectMainId, providerIds, providerNames, request,projectSeparate,outputValue,deptId,onlyChangeParticipate,buId,manDay,manDayStartDate,reviwerId, plate1,plate2,plate3,plate4,plate5,plate6,plate7,plate8,plate9,plate10);
     }
 
     @RequestMapping("/adjustBase")
@@ -1475,6 +1477,12 @@ public class ProjectController {
         return projectService.groupExpendProcessList(startDate,endDate,projectId,pageIndex,pageSize);
     }
 
+    //依斯倍定制 分组耗用进度表
+    @RequestMapping("/groupExpendProcessListForChart")
+    public HttpRespMsg groupExpendProcessListForChart(String startDate,String endDate,String projectIds,String groupNames){
+        return projectService.groupExpendProcessListForChart(startDate,endDate,projectIds,groupNames);
+    }
+
     //依斯倍定制 导出分组耗用进度表
     @RequestMapping("/exportGroupExpendProcessList")
     public HttpRespMsg exportGroupExpendProcessList(String startDate,String endDate,Integer projectId){
@@ -1512,5 +1520,23 @@ public class ProjectController {
         msg.data = projectService.list(new QueryWrapper<Project>().select("id","project_code", "project_name").eq("company_id", companyId));
         return msg;
     }
+
+    @RequestMapping("/batchChangeStage")
+    public HttpRespMsg batchChangeStage(@RequestParam String projectIdArray, @RequestParam Integer stageId,
+                                        @RequestParam String stageName,HttpServletRequest request) {
+        return projectService.batchChangeStage(projectIdArray, stageId, stageName, request);
+    }
+
+    /**
+    * @Description:批量设置项目任务执行人
+    * @Param: [projectIds, userIds]
+    * @return: java.lang.Object
+    * @Author: yurk
+    * @Date: 2024/7/15
+    */
+    @RequestMapping("/batchSetProjectTaskExecutor")
+    public HttpRespMsg batchSetProjectTaskExecutor(@RequestParam String projectIds,@RequestParam String userIds){
+        return projectService.batchSetProjectTaskExecutor(projectIds,userIds);
+    }
 }
 

+ 34 - 3
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java

@@ -623,7 +623,7 @@ public class ReportController {
         } else {
             //自动填充项目审核人
             for (int i=0;i<projectAuditorId.length; i++) {
-                if (projectAuditorId[i] == null) {
+                if (projectAuditorId[i] == null || comTimeType.getReportAuditType() == 8) {
                     final int index = i;
                     projectAuditorId[i] = projectList.stream().filter(p->p.getId().equals(projectId[index])).findFirst().get().getInchargerId();
                 }
@@ -1507,6 +1507,11 @@ public class ReportController {
                     }
                 }
             }
+        } else if (comTimeType.getReportAuditType() == 8) {
+            //默认是第一步审核
+            for (Report report : reportList) {
+                report.setIsFinalAudit(0);
+            }
         }
 
 
@@ -1979,10 +1984,12 @@ public class ReportController {
     }
 
     private void setReportWorkflowAuditor(List<AuditWorkflowTimeSetting> auditWorkflowList, List<Department> allDeptList, Report report, TimeType comTimeType) {
-        if (auditWorkflowList.size() == 0) {
+        if (comTimeType.getReportAuditType() > 1 || auditWorkflowList.size() == 0) {
             //没有自定义审核流,默认的直接是项目负责人审核
             report.setIsDeptAudit(0);
-            report.setIsFinalAudit(1);
+            if (comTimeType.getReportAuditType() != 8) {
+                report.setIsFinalAudit(1);
+            }
         } else {
             //取第一个审核节点
             AuditWorkflowTimeSetting firstNode = auditWorkflowList.get(0);
@@ -2730,5 +2737,29 @@ public class ReportController {
     public HttpRespMsg cancelReminder(String createDate,String userId) throws Exception {
         return reportService.cancelReminder(request,createDate,userId);
     }
+
+    /**
+    * @Description:获取转移工时数据的列表
+    * @Param: [startDate, endDate, userId, projectId, pageIndex, pageSize]
+    * @return: com.management.platform.util.HttpRespMsg
+    * @Author: yurk
+    * @Date: 2024/7/17
+    */
+    @RequestMapping("/getReportListWithTransfer")
+    public HttpRespMsg getReportListWithTransfer(String startDate,String endDate,String userIds,Integer projectId,Integer pageIndex,Integer pageSize){
+        return reportService.getReportListWithTransfer(startDate,endDate,userIds,projectId,pageIndex,pageSize);
+    }
+
+    /**
+    * @Description:提供转移工时数据
+    * @Param: [reportIds, projectId, groupId, stageId]
+    * @return: com.management.platform.util.HttpRespMsg
+    * @Author: yurk
+    * @Date: 2024/7/17
+    */
+    @RequestMapping("/transferReport")
+    public HttpRespMsg transferReport(String reportIds,@RequestParam Integer projectId,@RequestParam Integer groupId,@RequestParam Integer stageId){
+        return reportService.transferReport(reportIds,projectId,groupId,stageId);
+    }
 }
 

+ 66 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportWriteOffController.java

@@ -0,0 +1,66 @@
+package com.management.platform.controller;
+
+
+import com.management.platform.entity.ReportWriteOff;
+import com.management.platform.entity.User;
+import com.management.platform.mapper.UserMapper;
+import com.management.platform.service.ReportWriteOffService;
+import com.management.platform.util.HttpRespMsg;
+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.time.LocalDateTime;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-07-17
+ */
+@RestController
+@RequestMapping("/report-write-off")
+public class ReportWriteOffController {
+
+    @Resource
+    private ReportWriteOffService reportWriteOffService;
+    @Resource
+    private HttpServletRequest request;
+    @Resource
+    private UserMapper userMapper;
+
+
+    /**
+     * @Description:核销日报加班 传值 1-表示核销操作 0-恢复操作
+     * @Param: [reportId, type]
+     * @return: com.management.platform.util.HttpRespMsg
+     * @Author: yurk
+     * @Date: 2024/7/17
+     */
+    @RequestMapping("/writeOffReport")
+    public HttpRespMsg writeOffReport(@RequestParam Integer reportId, @RequestParam Integer type,String reason){
+        HttpRespMsg msg=new HttpRespMsg();
+        User user = userMapper.selectById(request.getHeader("token"));
+        ReportWriteOff reportWriteOff = reportWriteOffService.getById(reportId);
+        if(reportWriteOff==null){
+            reportWriteOff=new ReportWriteOff();
+            reportWriteOff.setReportId(reportId);
+            reportWriteOff.setCreatorId(user.getId());
+            reportWriteOff.setCreatorName(user.getName());
+        }
+        reportWriteOff.setWriteOff(type);
+        reportWriteOff.setReason(reason);
+        reportWriteOff.setCreateTime(LocalDateTime.now());
+        if(!reportWriteOffService.saveOrUpdate(reportWriteOff)){
+            msg.setError("验证失败");
+        }
+        return msg;
+    }
+
+}
+

+ 14 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserController.java

@@ -882,6 +882,13 @@ public class UserController {
         return httpRespMsg;
     }
 
+    /**
+    * @Description:ldap获取组织架构
+    * @Param: []
+    * @return: com.management.platform.util.HttpRespMsg
+    * @Author: yurk
+    * @Date: 2024/7/19
+    */
     @RequestMapping("/getOU")
     public HttpRespMsg getOU() throws NamingException {
         HttpRespMsg httpRespMsg=new HttpRespMsg();
@@ -889,6 +896,13 @@ public class UserController {
         return httpRespMsg;
     }
 
+    /**
+    * @Description:ldap获取人员
+    * @Param: []
+    * @return: com.management.platform.util.HttpRespMsg
+    * @Author: yurk
+    * @Date: 2024/7/19
+    */
     @RequestMapping("/getUser")
     public HttpRespMsg getUser() throws Exception {
         HttpRespMsg httpRespMsg=new HttpRespMsg();

+ 38 - 236
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserWithBeisenController.java

@@ -148,223 +148,56 @@ public class UserWithBeisenController {
     @RequestMapping("/syncAttendanceFromBeisen")
     @Transactional(rollbackFor = Exception.class)
     public HttpRespMsg syncAttendanceFromBeisen(String startDate,String endDate){
+        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        return userWithBeisenService.syncAttendanceFromBeisen(startDate,endDate,companyId);
+    }
+
+
+    @RequestMapping("/getAttendanceStatisticWithUser")
+    public HttpRespMsg getAttendanceStatisticWithUser(String userId,String createDate){
         HttpRespMsg msg=new HttpRespMsg();
         DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
         DateTimeFormatter df1=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
         DateTimeFormatter df2=DateTimeFormatter.ofPattern("HH:mm");
         DateTimeFormatter df3=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
         DateTimeFormatter df4=DateTimeFormatter.ofPattern("HH:mm:ss");
-        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        if(StringUtils.isEmpty(userId)){
+            userId=request.getHeader("token");
+        }
+        User user = userMapper.selectById(userId);
+        Integer companyId = user.getCompanyId();
         TimeType timeType = timeTypeMapper.selectById(companyId);
         List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
         List<UserWithBeisen> userWithBeisenList = userWithBeisenService.list(new LambdaQueryWrapper<UserWithBeisen>().eq(UserWithBeisen::getCompanyId, companyId));
         BeisenConfig beisenConfig = beisenConfigMapper.selectById(companyId);
-        //获取特殊节假日设置
-        List<HolidaySetting> holidaySettings = holidaySettingService.list(new LambdaQueryWrapper<HolidaySetting>().eq(HolidaySetting::getCompanyId, companyId));
         if(beisenConfig==null){
             msg.setError("北森基础数据配置未完成,请联系服务商完成配置");
             return msg;
         }
+        Optional<UserWithBeisen> withBeisen = userWithBeisenList.stream().filter(u ->u.getJobNumber()!=null&& u.getJobNumber().equals(user.getJobNumber())).findFirst();
+        if(!withBeisen.isPresent()){
+            msg.setError("当前员工在北森系统中不存在,请完成录入员工信息");
+            return msg;
+        }
         //todo 获取到指定日期的考勤数据
-        JSONArray attendanceStatistics=new JSONArray();
+        JSONObject item = BeiSenUtils.getAttendanceStatisticWithUser(createDate,withBeisen.get().getUserId(), beisenConfig.getAppKey(), beisenConfig.getAppSecret());
         //todo 获取到指定日期的加班数据
-        List<LocalDate> workDaysListInRange = WorkDayCalculateUtils.getWorkDaysListInRange(startDate, endDate, 1);
-        JSONArray allOverTimeList=new JSONArray();
-        JSONArray allVacationList=new JSONArray();
-        List<LeaveSheet> leaveSheetList=new ArrayList<>();
-        List<UserFvTime> userFvTimeList=new ArrayList<>();
-        for (LocalDate localDate : workDaysListInRange) {
-            JSONArray statisticList = BeiSenUtils.getAttendanceStatistics(df.format(localDate), df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(), 1, 100);
-            JSONArray overTimeList = BeiSenUtils.getOverTimeList(df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(), 1, 100);
-            JSONArray vacationList = BeiSenUtils.getVacationList(df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(),1,100);
-            allOverTimeList.addAll(overTimeList);
-            attendanceStatistics.addAll(statisticList);
-            allVacationList.addAll(vacationList);
-        }
-        for (LocalDate localDate : workDaysListInRange) {
-            Stream<JSONObject> swipingCardsStream = attendanceStatistics.stream().map(item -> (JSONObject) item);
-            //todo: 获取当天的考勤数据
-            List<JSONObject> swipingCardDateList = swipingCardsStream.filter(i -> LocalDateTime.parse(i.getString("SwipingCardDate"),df1).toLocalDate().equals(localDate)).collect(Collectors.toList());
-            for (JSONObject item : swipingCardDateList) {
-                //获取当前数据下的人员工号对应到工时管家
-                String cardNumber = item.getString("CardNumber");
-                Optional<User> first = userList.stream().filter(f -> f.getJobNumber().equals(cardNumber)).findFirst();
-                //todo: 获取考勤打卡时间集合
-                JSONArray times = item.getJSONArray("Times");
-                Stream<JSONObject> timeStream = times.stream().map(time -> (JSONObject) time);
-                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> 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> maxOp = maxLocalTimeList.stream().max(LocalTime::compareTo);
-                if(first.isPresent()){
-                    boolean workDay = WorkDayCalculateUtils.isWorkDay(localDate);
-                    //todo:针对景昱 工作日默认以8小时工作制度加上加班时长 非工作日以加班时长为准
-                    Double workTime;
-                    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;
-                        }
-                    }
-                    Stream<JSONObject> overTimeStream = allOverTimeList.stream().map(elment -> (JSONObject) elment);
-                    Stream<JSONObject> vacationStream = allVacationList.stream().map(elment -> (JSONObject) elment);
-                    Optional<UserWithBeisen> beisen = userWithBeisenList.stream().filter(u -> u.getJobNumber() != null && u.getJobNumber().equals(first.get().getJobNumber())).findFirst();
-                    if(beisen.isPresent()){
-                        //todo:之前的逻辑
-//                        List<JSONObject> overTimeList = overTimeStream.filter(a -> a.getString("StaffId").equals(beisen.get().getUserId())
-//                                && (a.getIntValue("ApproveStatus") == 2||a.getIntValue("ApproveStatus") == 1)
-//                                &&LocalDateTime.parse(a.getString("StartDate"),df1).toLocalDate().isEqual(localDate)).collect(Collectors.toList());
-                        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);
-                        //计算加班时长 工作日打卡超过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())){
-                                    //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
-                                    //对比打卡体现的加班时长和加班单时长取小
-                                    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+round(divide.doubleValue(),0.5);
-                                    }
-                                }else {
-                                    //开始日期和结束日期是不相同的情况 说明是加班区间存在加班到第二天的情况
-                                    LocalDateTime start = LocalDateTime.parse(o.getString("StartDate"), df1);
-                                    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_DOWN);
-                                    double l = decimal.doubleValue();
-                                    //对比打卡体现的加班时长和加班单时长取小
-                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
-                                    if(divide.doubleValue()>l){
-                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
-                                        workTime=workTime+l;
-                                    }else {
-                                        workTime=workTime+round(divide.doubleValue(),0.5);
-                                    }
-                                }
-                            }else if(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate().isEqual(localDate)){
-                                //存在结束日期为当天的数据
-                                if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate())){
-                                    //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
-                                    //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
-                                    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+round(divide.doubleValue(),0.5);
-                                    }
-                                }else {
-                                    //开始日期和结束日期是不相同的情况 说明是加班区间存在加班到第二天的情况
-                                    LocalDateTime stop = LocalDateTime.parse(o.getString("StopDate"), df1);
-                                    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_DOWN);
-                                    double l = decimal.doubleValue();
-                                    //对比打卡体现的加班时长和加班单时长取小
-                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
-                                    if(divide.doubleValue()>l){
-                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
-                                        workTime=workTime+l;
-                                    }else {
-                                        workTime=workTime+round(divide.doubleValue(),0.5);
-                                    }
-                                }
-                            }
-                        }
-                        //处理修改
-                        List<JSONObject> vacationList = vacationStream.filter(a ->{
-                            LocalDate vacationStartDate = LocalDateTime.parse(a.getString("VacationStartDateTime"), df3).toLocalDate();
-                            LocalDate vacationStopDate = LocalDateTime.parse(a.getString("VacationStopDateTime"), df3).toLocalDate();
-                            boolean b=false;
-                            if((localDate.isAfter(vacationStartDate)||localDate.isEqual(vacationStartDate))
-                                    &&(localDate.isBefore(vacationStopDate)||localDate.isEqual(vacationStopDate))){
-                                b=true;
-                            }
-                            if(a.getString("StaffId").equals(beisen.get().getUserId())
-                                    && b
-                                    &&a.getString("DocumentType").equals("请假")
-                                    &&  (a.getString("ApproveStatus").equals("通过") || a.getString("ApproveStatus").equals("审批中"))){
-                                return true;
-                            }
-                            return false;
-                        }).collect(Collectors.toList());
-                        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_DOWN);
-//                            //可能存在休假多天 只减去一天
-                            if(decimal.doubleValue()>=8){
-                                workTime= workTime-8;
-                            }else {
-                                workTime= workTime-decimal.doubleValue();
-                            }
-                        }
-                    }
-                    UserFvTime userFvTime=new UserFvTime();
-                    userFvTime.setWorkDate(localDate);
-                    userFvTime.setStartTime(df2.format(min));
-                    userFvTime.setEndTime(df2.format(max));
-                    userFvTime.setUserId(first.get().getId());
-                    userFvTime.setCompanyId(companyId);
-                    userFvTime.setWorkHours(workTime.floatValue());
-                    UserFvTime one = userFvTimeService.getOne(new LambdaQueryWrapper<UserFvTime>().eq(UserFvTime::getCompanyId, companyId).eq(UserFvTime::getUserId, first.get().getId()).eq(UserFvTime::getWorkDate, localDate));
-                    if(one!=null){
-                        userFvTime.setId(one.getId());
-                    }
-                    userFvTimeList.add(userFvTime);
-                }
-            }
-        }
-        if(userFvTimeList.size()>0){
-            if(!userFvTimeService.saveOrUpdateBatch(userFvTimeList)){
-                msg.setError("同步验证失败");
-            }
-        }
+        JSONArray allOverTimeList = BeiSenUtils.getOverTimeList(createDate,beisenConfig.getAppKey(),beisenConfig.getAppSecret(),1,100);
+        //todo 获取到指定日期的休假数据
+        JSONArray vacationList = BeiSenUtils.getVacationList(createDate, beisenConfig.getAppKey(), beisenConfig.getAppSecret(),1,100);
         //同步休假数据到工时管家
-        for (int i = 0; i < allVacationList.size(); i++) {
-            JSONObject jsonObject = allVacationList.getJSONObject(i);
-            Optional<UserWithBeisen> beisen = userWithBeisenList.stream().filter(b -> b.getUserId().equals(jsonObject.getString("StaffId"))).findFirst();
-            if(beisen.isPresent()){
-                Optional<User> first = userList.stream().filter(u -> u.getJobNumber().equals(beisen.get().getJobNumber())).findFirst();
-                if(first.isPresent()){
+        List<LeaveSheet> leaveSheetList=new ArrayList<>();
+        for (int i = 0; i < vacationList.size(); i++) {
+            JSONObject jsonObject = vacationList.getJSONObject(i);
+            Optional<UserWithBeisen> beisen1 = userWithBeisenList.stream().filter(b -> b.getUserId().equals(jsonObject.getString("StaffId"))).findFirst();
+            if(beisen1.isPresent()){
+                Optional<User> first1 = userList.stream().filter(u -> u.getJobNumber().equals(beisen1.get().getJobNumber())).findFirst();
+                if(first1.isPresent()){
                     LeaveSheet leaveSheet=new LeaveSheet();
                     leaveSheet.setCompanyId(beisenConfig.getCompanyId());
                     leaveSheet.setStatus(0);
-                    leaveSheet.setOwnerId(first.get().getId());
-                    leaveSheet.setOwnerName(first.get().getName());
+                    leaveSheet.setOwnerId(first1.get().getId());
+                    leaveSheet.setOwnerName(first1.get().getName());
                     leaveSheet.setStartDate(LocalDateTime.parse(String.valueOf(jsonObject.get("VacationStartDateTime")),df3).toLocalDate());
                     leaveSheet.setEndDate(LocalDateTime.parse(String.valueOf(jsonObject.get("VacationStopDateTime")),df3).toLocalDate());
                     leaveSheet.setTimeType(1);
@@ -392,10 +225,10 @@ public class UserWithBeisenController {
                     }
                     leaveSheet.setLeaveType(leaveType);
                     leaveSheet.setRemark(jsonObject.getString("Reason"));
-                    leaveSheet.setStatus(jsonObject.getString("ApproveStatus").equals("通过")?0:jsonObject.getString("Reason").equals("审批中")?1:2);
+                    leaveSheet.setStatus(jsonObject.getString("ApproveStatus").equals("通过")?0:jsonObject.getString("ApproveStatus").equals("审批中")?1:2);
                     leaveSheet.setProcinstId(jsonObject.getString("VacationId"));
-                    LeaveSheet one = leaveSheetService.getOne(new LambdaQueryWrapper<LeaveSheet>().eq(LeaveSheet::getProcinstId,leaveSheet.getProcinstId()).eq(LeaveSheet::getOwnerId, first.get().getId()).eq(LeaveSheet::getStartDate, leaveSheet.getStartDate()).eq(LeaveSheet::getEndDate, leaveSheet.getEndDate()));
-                    if(one==null){
+                    LeaveSheet one1 = leaveSheetService.getOne(new LambdaQueryWrapper<LeaveSheet>().eq(LeaveSheet::getOwnerId, first1.get().getId()).eq(LeaveSheet::getStartDate, leaveSheet.getStartDate()).eq(LeaveSheet::getProcinstId,leaveSheet.getProcinstId()).eq(LeaveSheet::getEndDate, leaveSheet.getEndDate()));
+                    if(one1==null){
                         leaveSheetList.add(leaveSheet);
                     }
                 }
@@ -404,42 +237,6 @@ public class UserWithBeisenController {
         if(leaveSheetList.size()>0){
             leaveSheetService.saveOrUpdateBatch(leaveSheetList);
         }
-        return msg;
-    }
-
-
-    @RequestMapping("/getAttendanceStatisticWithUser")
-    public HttpRespMsg getAttendanceStatisticWithUser(String userId,String createDate){
-        HttpRespMsg msg=new HttpRespMsg();
-        DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
-        DateTimeFormatter df1=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-        DateTimeFormatter df2=DateTimeFormatter.ofPattern("HH:mm");
-        DateTimeFormatter df3=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
-        DateTimeFormatter df4=DateTimeFormatter.ofPattern("HH:mm:ss");
-        if(StringUtils.isEmpty(userId)){
-            userId=request.getHeader("token");
-        }
-        User user = userMapper.selectById(userId);
-        Integer companyId = user.getCompanyId();
-        TimeType timeType = timeTypeMapper.selectById(companyId);
-        List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
-        List<UserWithBeisen> userWithBeisenList = userWithBeisenService.list(new LambdaQueryWrapper<UserWithBeisen>().eq(UserWithBeisen::getCompanyId, companyId));
-        BeisenConfig beisenConfig = beisenConfigMapper.selectById(companyId);
-        if(beisenConfig==null){
-            msg.setError("北森基础数据配置未完成,请联系服务商完成配置");
-            return msg;
-        }
-        Optional<UserWithBeisen> withBeisen = userWithBeisenList.stream().filter(u ->u.getJobNumber()!=null&& u.getJobNumber().equals(user.getJobNumber())).findFirst();
-        if(!withBeisen.isPresent()){
-            msg.setError("当前员工在北森系统中不存在,请完成录入员工信息");
-            return msg;
-        }
-        //todo 获取到指定日期的考勤数据
-        JSONObject item = BeiSenUtils.getAttendanceStatisticWithUser(createDate,withBeisen.get().getUserId(), beisenConfig.getAppKey(), beisenConfig.getAppSecret());
-        //todo 获取到指定日期的加班数据
-        JSONArray allOverTimeList = BeiSenUtils.getOverTimeList(createDate,beisenConfig.getAppKey(),beisenConfig.getAppSecret(),1,100);
-        //todo 获取到指定日期的休假数据
-        JSONArray vacationList = BeiSenUtils.getVacationList(createDate, beisenConfig.getAppKey(), beisenConfig.getAppSecret(),1,100);
         //获取当前数据下的人员工号对应到工时管家
         Optional<User> first = userList.stream().filter(f -> f.getJobNumber().equals(withBeisen.get().getJobNumber())).findFirst();
         System.out.println("考勤数据:"+item.toString());
@@ -573,6 +370,11 @@ public class UserWithBeisenController {
                     return false;
                 }).collect(Collectors.toList());
                 if(lastVacationList.size()>0){
+                    for (int i = 0; i < lastVacationList.size(); i++) {
+                        JSONObject vacation = lastVacationList.get(i);
+                        String vacationStartDateTime = vacation.getString("VacationStartDateTime");
+                        String VacationStopDateTime = vacation.getString("VacationStopDateTime");
+                    }
                     double vacationDuration = lastVacationList.stream().mapToDouble(i -> i.getDouble("VacationDuration")).sum();
                     BigDecimal decimal = new BigDecimal(vacationDuration);
                     decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_DOWN);

+ 10 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Project.java

@@ -26,7 +26,7 @@ import org.springframework.format.annotation.DateTimeFormat;
  * </p>
  *
  * @author Seyason
- * @since 2023-11-19
+ * @since 2024-07-11
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -477,6 +477,15 @@ public class Project extends Model<Project> {
 
     @TableField(exist = false)
     private String groupName;
+    /**
+     * 项目复审人
+     */
+    @TableField("reviwer_id")
+    private String reviwerId;
+
+    @TableField(exist = false)
+    private String reviwerName;
+
 
     @Override
     protected Serializable pkVal() {

+ 66 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ReportWriteOff.java

@@ -0,0 +1,66 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-07-17
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class ReportWriteOff extends Model<ReportWriteOff> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId("report_id")
+    private Integer reportId;
+
+    /**
+     * 0-正常 1-已核销
+     */
+    @TableField("write_off")
+    private Integer writeOff;
+
+    /**
+     * 核销人id
+     */
+    @TableField("creator_id")
+    private String creatorId;
+
+    /**
+     * 核销人
+     */
+    @TableField("creator_name")
+    private String creatorName;
+
+    /**
+     * 核销时间
+     */
+    @TableField("create_time")
+    private LocalDateTime createTime;
+
+    /**
+     * 核销原因
+     */
+    @TableField("reason")
+    private String reason;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.reportId;
+    }
+
+}

+ 1 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/OvertimeListVO.java

@@ -16,4 +16,5 @@ public class OvertimeListVO {
     private String startDate;
     private String endDate;
     private Integer[] departmentId;
+    private Integer writeOffValue;
 }

+ 2 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/DepartmentMapper.java

@@ -21,6 +21,8 @@ public interface DepartmentMapper extends BaseMapper<Department> {
 
     List<Map<String, Object>> getCostByUser(@Param("departmentIds") List departmentIds, String startDate, String endDate, Integer companyId, List<String> userIds);
 
+    List<Map<String, Object>> getCostByUserSum(@Param("departmentIds") List departmentIds, String startDate, String endDate, Integer companyId);
+
     List<Map<String, Object>> getCustomDataByUser(@Param("departmentIds") List departmentIds, String startDate, String endDate, Integer companyId, List<String> userIds);
     @Update("update department set manager_id = null where department_id = #{departmentId}")
     void updateNullManager(Integer departmentId);

+ 5 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectMapper.java

@@ -90,7 +90,7 @@ public interface ProjectMapper extends BaseMapper<Project> {
     //获取按照项目分组导出的项目数据
     List<HashMap<String, Object>> getExportGroupData(String projectCategorySub,Integer companyId);
 
-    List<Map<String, Object>> getOvertimeDetail(String userId, Integer companyId, String startDate, String endDate, Integer projectId,List<Integer> branchDepartment,List<Integer> deptIds);
+    List<Map<String, Object>> getOvertimeDetail(String userId, Integer companyId, String startDate, String endDate, Integer projectId,List<Integer> branchDepartment,List<Integer> deptIds,Integer writeOffValue);
 
     //获取项目的成本预警和实际工时表
     List<HashMap> getProjectCostAlarm(Integer companyId, Integer pageStart, Integer pageSize, Integer projectId);
@@ -182,4 +182,8 @@ public interface ProjectMapper extends BaseMapper<Project> {
     List<Map<String, Object>> userTaskProcessList(Integer deptId, String userId, Integer projectId, Integer companyId, @Param("list") List<Integer> deptIds,String startDate,String endDate,@Param("listSecond") List<Integer> regularDeptIds, Integer start, Integer size);
 
     Long userTaskProcessListCount(Integer deptId, String userId, Integer projectId, Integer companyId, @Param("list") List<Integer> deptIds,String startDate,String endDate,@Param("listSecond") List<Integer> regularDeptIds);
+    @Update("update project set reviwer_id=null where id=#{id}")
+    void removeReviwer(Integer id);
+
+    List<Map<String, Object>> groupExpendProcessListForChart(String userId, Integer companyId, String startDate, String endDate,@Param("list") List<Integer> deptIds,@Param("listSecond") List<Integer> regularDeptIds,@Param("listThird") List<Integer> projectIdList,@Param("listFour") List<String> groupNameList);
 }

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

@@ -219,4 +219,7 @@ public interface ReportMapper extends BaseMapper<Report> {
 
     List<Map<String, Object>> getUserDailyWorkTimeReminder(Integer companyId,String startDate, String endDate,@Param("list") List<Integer> deptIds,Integer deptId,String leaderId);
 
+    List<Map<String, Object>> getReportListWithTransfer(Integer companyId, String startDate, String endDate,@Param("list") List<String> userIdList, Integer projectId, Integer start, Integer size);
+
+    Integer getReportListWithTransferCount(Integer companyId, String startDate, String endDate,@Param("list") List<String> userIdList, Integer projectId);
 }

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

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

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

@@ -49,7 +49,9 @@ public interface ProjectService extends IService<Project> {
                             String providerIds,
                             String providerNames,
                             HttpServletRequest request,
-                            ProjectSeparate projectSeparate,Double outputValue,Integer deptId,boolean onlyChangeParticipate,String buId,Double manDay,String manDayStartDate,String plate1,
+                            ProjectSeparate projectSeparate,Double outputValue,Integer deptId,boolean onlyChangeParticipate,String buId,Double manDay,String manDayStartDate,
+                            String reviwerId,
+                            String plate1,
                             String plate2,
                             String plate3,
                             String plate4,
@@ -292,4 +294,10 @@ public interface ProjectService extends IService<Project> {
     HttpRespMsg exportUserTaskProcessList(Integer deptId, String userId, Integer projectId,String startDate,String endDate);
 
     HttpRespMsg exportEffectiveLaborHourRate(String startDate, String endDate);
+
+    HttpRespMsg batchChangeStage(String projectIdArray, Integer stageId, String stageName, HttpServletRequest request);
+
+    HttpRespMsg batchSetProjectTaskExecutor(String projectIds, String userIds);
+
+    HttpRespMsg groupExpendProcessListForChart(String startDate, String endDate, String projectIds, String groupNames);
 }

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

@@ -161,4 +161,8 @@ public interface ReportService extends IService<Report> {
     HttpRespMsg cancelReminder(HttpServletRequest request, String createDate, String userId);
 
     HttpRespMsg cancelHasPushForSap(String uuids);
+
+    HttpRespMsg getReportListWithTransfer(String startDate, String endDate, String userIds, Integer projectId, Integer pageIndex, Integer pageSize);
+
+    HttpRespMsg transferReport(String reportIds, Integer projectId, Integer groupId, Integer stageId);
 }

+ 17 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ReportWriteOffService.java

@@ -0,0 +1,17 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.ReportWriteOff;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.management.platform.util.HttpRespMsg;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-07-17
+ */
+public interface ReportWriteOffService extends IService<ReportWriteOff> {
+
+}

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

@@ -2,6 +2,7 @@ package com.management.platform.service;
 
 import com.management.platform.entity.UserWithBeisen;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.management.platform.util.HttpRespMsg;
 
 /**
  * <p>
@@ -13,4 +14,5 @@ import com.baomidou.mybatisplus.extension.service.IService;
  */
 public interface UserWithBeisenService extends IService<UserWithBeisen> {
 
+    HttpRespMsg syncAttendanceFromBeisen(String startDate, String endDate,Integer companyId);
 }

+ 72 - 79
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DepartmentServiceImpl.java

@@ -452,90 +452,83 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
     @Override
     public HttpRespMsg getDepartmentStatistics(Integer parentDeptId, String startDate, String endDate, HttpServletRequest request) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
-        try {
-            User targetUser = userMapper.selectById(request.getHeader("Token"));
-            Integer companyId =targetUser.getCompanyId();
-            //当前用户管理部门
-            List<Integer> deptIds=null;
-            List<Department> departmentList = departmentMapper.selectList(new QueryWrapper<Department>().eq("manager_id", targetUser.getId()).eq("company_id", companyId));
-            List<DepartmentOtherManager> departmentOtherManagerList = departmentOtherManagerMapper.selectList(new QueryWrapper<DepartmentOtherManager>().eq("other_manager_id", targetUser.getId()));
-            List<SysRichFunction> functionAllList = sysFunctionMapper.getRoleFunctions(targetUser.getRoleId(), "查看全公司");
-            List<SysRichFunction> functionDpartList = sysFunctionMapper.getRoleFunctions(targetUser.getRoleId(), "查看负责部门");
-            List<SysRichFunction> functionTimeList = sysFunctionMapper.getRoleFunctions(targetUser.getRoleId(), "查看工时统计");
-            List<SysRichFunction> functionCostList = sysFunctionMapper.getRoleFunctions(targetUser.getRoleId(), "查看成本统计");
-            //判断查看权限
-            if(functionAllList.size()==0){
-                deptIds=new ArrayList<>();
-                //是不是要加
-                deptIds.add(-1);
-                if(functionDpartList.size()>0){
-                    if(functionTimeList.size()>0||functionCostList.size()>0){
-                        List<Integer> collect = departmentList.stream().map(dp -> dp.getDepartmentId()).distinct().collect(Collectors.toList());
-                        List<Integer> otherCollect = departmentOtherManagerList.stream().map(dom -> dom.getDepartmentId()).distinct().collect(Collectors.toList());
-                        collect.addAll(otherCollect);
-                        deptIds.addAll(collect);
-                    }
-                }
-            }
-            QueryWrapper<Department> queryWrapper = new QueryWrapper<Department>()
-                    .eq("company_id", companyId);
-            if (parentDeptId == null) {
-                if (deptIds == null) {
-                    //查看全公司的
-                    queryWrapper.isNull("superior_id");
-                }else {
-                    queryWrapper.in("department_id",deptIds);
-                }
-            } else {
-                queryWrapper.eq("superior_id", parentDeptId);
-            }
-            //获取第一级部门
-            System.out.println(deptIds);
-            List<Department> masterList = departmentMapper.selectList(queryWrapper);
-            System.out.println(masterList);
-            Map<String, Object> resultMap = new HashMap<>();
-            List<DepartmentMasterVO> list = new ArrayList<>();
-            BigDecimal totalCostMoney = new BigDecimal(0);
-            List<Department> allDeptList = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id", companyId));
-
-            for (Department department : masterList) {
-                DepartmentMasterVO departmentMasterVO = new DepartmentMasterVO();
-                BeanUtils.copyProperties(department, departmentMasterVO);
-                Map<String, Object> map = departmentMapper.getCostByDepartment(
-                        getBranchDepartment(department.getDepartmentId(), allDeptList), startDate, endDate);
-                Double time = map == null ? new Double(0) : (Double) map.get("time");
-                BigDecimal money = map == null ? new BigDecimal(0) : (BigDecimal) map.get("money");
-                totalCostMoney = totalCostMoney.add(money);
-                departmentMasterVO.setCostTime(time);
-                departmentMasterVO.setCostMoney(money);
-                departmentMasterVO.setType("departmentName");
-                //检查是否有子部门
-                if (allDeptList.stream().anyMatch(dept->department.getDepartmentId().equals(dept.getSuperiorId()))) {
-                    departmentMasterVO.setHasSubDept(true);
+        User targetUser = userMapper.selectById(request.getHeader("Token"));
+        Integer companyId =targetUser.getCompanyId();
+        //当前用户管理部门
+        List<Integer> deptIds=null;
+        List<Department> departmentList = departmentMapper.selectList(new QueryWrapper<Department>().eq("manager_id", targetUser.getId()).eq("company_id", companyId));
+        List<DepartmentOtherManager> departmentOtherManagerList = departmentOtherManagerMapper.selectList(new QueryWrapper<DepartmentOtherManager>().eq("other_manager_id", targetUser.getId()));
+        List<SysRichFunction> functionAllList = sysFunctionMapper.getRoleFunctions(targetUser.getRoleId(), "查看全公司");
+        List<SysRichFunction> functionDpartList = sysFunctionMapper.getRoleFunctions(targetUser.getRoleId(), "查看负责部门");
+        List<SysRichFunction> functionTimeList = sysFunctionMapper.getRoleFunctions(targetUser.getRoleId(), "查看工时统计");
+        List<SysRichFunction> functionCostList = sysFunctionMapper.getRoleFunctions(targetUser.getRoleId(), "查看成本统计");
+        //判断查看权限
+        if(functionAllList.size()==0){
+            deptIds=new ArrayList<>();
+            //是不是要加
+            deptIds.add(-1);
+            if(functionDpartList.size()>0){
+                if(functionTimeList.size()>0||functionCostList.size()>0){
+                    List<Integer> collect = departmentList.stream().map(dp -> dp.getDepartmentId()).distinct().collect(Collectors.toList());
+                    List<Integer> otherCollect = departmentOtherManagerList.stream().map(dom -> dom.getDepartmentId()).distinct().collect(Collectors.toList());
+                    collect.addAll(otherCollect);
+                    deptIds.addAll(collect);
                 }
-                list.add(departmentMasterVO);
             }
-            //对部门排序
-            list.sort(Comparator.comparing(l->l.getSeq()));
-            resultMap.put("totalCostMoney", totalCostMoney);
-            resultMap.put("costList", list);
-            if(functionCostList.size()==0){
-                resultMap.put("totalCostMoney",new BigDecimal(0));
-                list.forEach(li->{
-                    li.setCostMoney(new BigDecimal(0));
-                });
+        }
+        QueryWrapper<Department> queryWrapper = new QueryWrapper<Department>()
+                .eq("company_id", companyId);
+        if (parentDeptId == null) {
+            if (deptIds == null) {
+                //查看全公司的
+                queryWrapper.isNull("superior_id");
+            }else {
+                queryWrapper.in("department_id",deptIds);
             }
-            if(functionTimeList.size()==0){
-                list.forEach(li->{
-                    li.setCostTime(0.0);
-                });
+        } else {
+            queryWrapper.eq("superior_id", parentDeptId);
+        }
+        //获取第一级部门
+        System.out.println(deptIds);
+        List<Department> masterList = departmentMapper.selectList(queryWrapper);
+        Map<String, Object> resultMap = new HashMap<>();
+        List<DepartmentMasterVO> list = new ArrayList<>();
+        BigDecimal totalCostMoney = new BigDecimal(0);
+        List<Department> allDeptList = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id", companyId));
+
+        for (Department department : masterList) {
+            DepartmentMasterVO departmentMasterVO = new DepartmentMasterVO();
+            BeanUtils.copyProperties(department, departmentMasterVO);
+            Map<String, Object> map = departmentMapper.getCostByDepartment(
+                    getBranchDepartment(department.getDepartmentId(), allDeptList), startDate, endDate);
+            Double time = map == null ? new Double(0) : (Double) map.get("time");
+            BigDecimal money = map == null ? new BigDecimal(0) : (BigDecimal) map.get("money");
+            totalCostMoney = totalCostMoney.add(money);
+            departmentMasterVO.setCostTime(time);
+            departmentMasterVO.setCostMoney(money);
+            departmentMasterVO.setType("departmentName");
+            //检查是否有子部门
+            if (allDeptList.stream().anyMatch(dept->department.getDepartmentId().equals(dept.getSuperiorId()))) {
+                departmentMasterVO.setHasSubDept(true);
             }
-            httpRespMsg.data = resultMap;
-        } catch (NullPointerException e) {
-            //httpRespMsg.setError("验证失败");
-            httpRespMsg.setError(MessageUtils.message("access.verificationError"));
-            return httpRespMsg;
+            list.add(departmentMasterVO);
+        }
+        //对部门排序
+        list.sort(Comparator.comparing(l->l.getSeq()));
+        resultMap.put("totalCostMoney", totalCostMoney);
+        resultMap.put("costList", list);
+        if(functionCostList.size()==0){
+            resultMap.put("totalCostMoney",new BigDecimal(0));
+            list.forEach(li->{
+                li.setCostMoney(new BigDecimal(0));
+            });
+        }
+        if(functionTimeList.size()==0){
+            list.forEach(li->{
+                li.setCostTime(0.0);
+            });
         }
+        httpRespMsg.data = resultMap;
         return httpRespMsg;
     }
 

+ 207 - 14
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java

@@ -29,6 +29,7 @@ import org.apache.poi.hssf.usermodel.HSSFRow;
 import org.apache.poi.hssf.usermodel.HSSFSheet;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.ss.formula.functions.T;
 import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.xssf.streaming.SXSSFCell;
@@ -704,7 +705,9 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                                    String providerIds,
                                    String providerNames,
                                    HttpServletRequest request,
-                                   ProjectSeparate projectSeparate,Double outputValue,Integer deptId,boolean onlyChangeParticipate,String buId,Double manDay,String  manDayStartDate,String plate1,
+                                   ProjectSeparate projectSeparate,Double outputValue,Integer deptId,boolean onlyChangeParticipate,String buId,Double manDay,String  manDayStartDate,
+                                   String reviwerId,
+                                   String plate1,
                                    String plate2,
                                    String plate3,
                                    String plate4,
@@ -745,6 +748,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         }
         boolean inchargerChanged = false;
         String oldInchargerId = null;
+        Project oldProject = null;
         if (id == null) {
             //新增项目
             if (name == null) {
@@ -780,6 +784,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                                     convertDepartmentIdToCascade(0) :
                                     convertDepartmentIdToCascade(deptId))
                             .setProviderNames(providerNames)
+                            .setReviwerId(reviwerId)
                             .setPlate1(plate1)
                             .setPlate2(plate2)
                             .setPlate3(plate3)
@@ -885,7 +890,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                 }
             }
         } else {
-            Project oldProject = projectMapper.selectById(id);
+            oldProject = projectMapper.selectById(id);
             isNew = false;
             //修改项目
             //检查项目编号不能重复
@@ -897,10 +902,9 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                 //httpRespMsg.setError("提交失败:项目编号已存在");
                 httpRespMsg.setError(MessageUtils.message("project.submitFailByNoRepeat"));
             } else {
-                Project project = projectMapper.selectById(id);
-                if (inchargerId != null && !inchargerId.equals(project.getInchargerId())) {
+                if (inchargerId != null && !inchargerId.equals(oldProject.getInchargerId())) {
                     inchargerChanged = true;
-                    oldInchargerId = project.getInchargerId();
+                    oldInchargerId = oldProject.getInchargerId();
                 }
                 Project p = new Project();
                 p.setProjectName(name).setId(id).setCompanyId(companyId).setProjectCode(code != null?code.trim():null).setInchargerId(inchargerId)
@@ -920,6 +924,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                                 convertDepartmentIdToCascade(0) :
                                 convertDepartmentIdToCascade(deptId))
                         .setProviderNames(providerNames)
+                        .setReviwerId(reviwerId)
                         .setPlate1(plate1)
                         .setPlate2(plate2)
                         .setPlate3(plate3)
@@ -996,10 +1001,10 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                     }
                 }
                 //编辑项目合同修改 添加记录
-                if(contractAmount!=null&&project.getContractAmount().doubleValue()!=contractAmount){
+                if(contractAmount!=null&&oldProject.getContractAmount().doubleValue()!=contractAmount){
                     ContractModifyRecord contractModifyRecord=new ContractModifyRecord();
                     contractModifyRecord.setEditUserId(user.getId());
-                    contractModifyRecord.setOldContractAmount(project.getContractAmount());
+                    contractModifyRecord.setOldContractAmount(oldProject.getContractAmount());
                     contractModifyRecord.setNewContractAmount(contractAmount);
                     contractModifyRecord.setProjectId(id);
                     contractModifyRecord.setReason(changeContractReason);
@@ -1049,6 +1054,10 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                         //去掉客户
                         projectMapper.removeProjectCustomer(id);
                     }
+                    if (timeType.getReportAuditType() == 8 && oldProject.getReviwerId() != null && reviwerId == null) {
+                        //清空复核人
+                        projectMapper.removeReviwer(id);
+                    }
                     //修改项目相关表
                     ProjectTimer timer = new ProjectTimer();
                     timer.setProjectName(name);
@@ -1276,6 +1285,19 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                         }
                     }
 
+                    //有项目复核人的情况
+                    if (timeType.getReportAuditType() == 8) {
+                        if (oldProject.getReviwerId() != null && reviwerId != null && !oldProject.getReviwerId().equals(reviwerId)) {
+                            //发生变化,查找日报中待审核状态下的
+                            QueryWrapper<Report> queryWrapper = new QueryWrapper<Report>().eq("company_id", companyId).eq("project_id", id).eq("state",0).eq("project_auditor_id", oldProject.getReviwerId());
+                            int count = reportMapper.selectCount(queryWrapper);
+                            if (count > 0) {
+                                //更新日报的审核人
+                                Report upR = new Report().setProjectAuditorId(reviwerId);
+                                reportMapper.update(upR, queryWrapper);
+                            }
+                        }
+                    }
                 }
             }
             //针对启用了简单非项目模式的情况,确保项目经理,级别,合同金额,开始日期,截止日期,预估工时都是null
@@ -2284,6 +2306,12 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                 project.setInchargerName(incharger.getName());
             }
         }
+        if (project.getReviwerId() != null) {
+            User reviewer = userMapper.selectById(project.getReviwerId());
+            if (reviewer != null) {
+                project.setReviwerName(reviewer.getName());
+            }
+        }
         Optional<Department> first = departmentList.stream().filter(dt -> dt.getDepartmentId().equals(project.getDeptId())).findFirst();
         if(first.isPresent()){
             project.setDepartmentName(first.get().getDepartmentName());
@@ -4069,6 +4097,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         String endDate = overtimeListVO.getEndDate();
         String userId = overtimeListVO.getUserId();
         Integer[] deptId = overtimeListVO.getDepartmentId();
+        Integer writeOffValue = overtimeListVO.getWriteOffValue();
         ArrayList<Integer> departmentId = null;
         HttpRespMsg msg = new HttpRespMsg();
         String token = request.getHeader("TOKEN");
@@ -4101,7 +4130,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                 branchDepartment.addAll(getBranchDepartment(dept, allDepartmentList));
             }
         }
-        List<Map<String, Object>> list = projectMapper.getOvertimeDetail(userId, user.getCompanyId(), startDate, endDate, projectId,branchDepartment,deptIds);
+        List<Map<String, Object>> list = projectMapper.getOvertimeDetail(userId, user.getCompanyId(), startDate, endDate, projectId,branchDepartment,deptIds,writeOffValue);
         boolean hasViewSalary = sysFunctionService.hasPriviledge(user.getRoleId(), "查看加班成本");
         if (!hasViewSalary) {
             //去掉权限
@@ -4130,6 +4159,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         String endDate = overtimeListVO.getEndDate();
         Integer projectId = overtimeListVO.getProjectId();
         Integer[] deptId = overtimeListVO.getDepartmentId();
+        Integer writeOffValue = overtimeListVO.getWriteOffValue();
         try {
             String token = request.getHeader("TOKEN");
             User user = userMapper.selectById(token);
@@ -4164,7 +4194,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                     branchDepartment.addAll(getBranchDepartment(dept, allDepartmentList));
                 }
             }
-            List<Map<String, Object>> list = projectMapper.getOvertimeDetail(userId, user.getCompanyId(), startDate, endDate, projectId,branchDepartment,deptIds);
+            List<Map<String, Object>> list = projectMapper.getOvertimeDetail(userId, user.getCompanyId(), startDate, endDate, projectId,branchDepartment,deptIds,writeOffValue);
             boolean hasViewSalary = sysFunctionService.hasPriviledge(user.getRoleId(), "查看加班成本");
             BigDecimal totalMoneyCost = BigDecimal.valueOf(0);
             List<String> headList = new ArrayList<String>();
@@ -5284,6 +5314,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                     }
                     if(timeType.getMainProjectState()==1){
                         participatorCell = row.getCell(5+c);
+                        System.out.println(c);
                         inchargerCell = row.getCell(6+c);
                         if(timeType.getReportAuditType()==0||timeType.getReportAuditType()==4||timeType.getReportAuditType()==6){
                             i++;
@@ -5309,10 +5340,27 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                     if (inchargerCell != null)inchargerCell.setCellType(CellType.STRING);
                     if (reportAuditorsCell != null)reportAuditorsCell.setCellType(CellType.STRING);
                     if (reportCcCell != null)reportCcCell.setCellType(CellType.STRING);
-                    String part = participatorCell.getStringCellValue().trim();
-                    String inchargerName = inchargerCell.getStringCellValue().trim();
-                    String reportAuditors = reportAuditorsCell.getStringCellValue().trim();
-                    String reportCc = reportCcCell.getStringCellValue().trim();
+                    String part = "";
+                    String inchargerName = "";
+                    String reportAuditors = "";
+                    String reportCc = "";
+                    if (participatorCell!=null) {
+                        participatorCell.setCellType(CellType.STRING);
+                        part = participatorCell.getStringCellValue().trim();
+                    }
+                    if (inchargerCell != null) {
+                        inchargerCell.setCellType(CellType.STRING);
+                        inchargerName = inchargerCell.getStringCellValue().trim();
+                    }
+                    if (reportAuditorsCell!=null) {
+                        reportAuditorsCell.setCellType(CellType.STRING);
+                        reportAuditors = reportAuditorsCell.getStringCellValue().trim();
+                    }
+                    if (reportCcCell!=null) {
+                        participatorCell.setCellType(CellType.STRING);
+                        reportCc = participatorCell.getStringCellValue().trim();
+                    }
+                    //兼容繁体
                     if(part.equals("参与人") || part.equals("參與人")){
                         continue;
                     }
@@ -6777,6 +6825,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         headList.add(MessageUtils.message("entry.projectType"));
         headList.add(MessageUtils.message("entry.publicProject"));
         headList.add(MessageUtils.message("entry.projectName"));
+        headList.add(MessageUtils.message("entry.projectStage"));
         headList.add(MessageUtils.message("excel.charge"));
         headList.add(MessageUtils.message("entry.Participants"));
         headList.add(MessageUtils.message("entry.startData"));
@@ -6877,6 +6926,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
             //rowData.add(("1".equals(projectVO.getIsPublic())?"是":"否"));
             rowData.add(("1".equals(projectVO.getIsPublic())?MessageUtils.message("excel.yes"):MessageUtils.message("excel.no")));
             rowData.add(projectVO.getProjectName());
+            rowData.add(projectVO.getCurrentStageName());
             if((wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1)||(dingding!=null&&dingding.getContactNeedTranslate()==1)){
                 if(projectVO.getInchargerId()!=null){
                     User us = userList.stream().filter(ul -> ul.getId().equals(projectVO.getInchargerId())).findFirst().get();
@@ -7439,7 +7489,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
 
             }
         }
-        List<Map<String, Object>> list = projectMapper.getOvertimeDetail(userId, user.getCompanyId(), startDate, endDate, projectId,null,deptIds);
+        List<Map<String, Object>> list = projectMapper.getOvertimeDetail(userId, user.getCompanyId(), startDate, endDate, projectId,null,deptIds,null);
         boolean hasViewSalary = sysFunctionService.hasPriviledge(user.getRoleId(), "查看加班成本");
         if (!hasViewSalary) {
             //去掉权限
@@ -12790,6 +12840,26 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         return null;
     }
 
+    @Override
+    public HttpRespMsg batchChangeStage(String projectIdArray, Integer stageId, String stageName, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        List<Integer> ids = JSONArray.parseArray(projectIdArray, Integer.class);
+        List<Project> projectList = new ArrayList<>();
+        for (Integer id : ids) {
+            Project p = new Project();
+            p.setId(id);
+            p.setCurrentStageId(stageId);
+            p.setCurrentStageName(stageName);
+            projectList.add(p);
+        }
+        if (projectList.size() > 0) {
+            updateBatchById(projectList);
+        } else {
+            msg.setError("请选择项目");
+        }
+        return msg;
+    }
+
     @Override
     public HttpRespMsg getProjectFillTime(HttpServletRequest request, Integer projectId) {
         //待审核和已通过的总工时
@@ -14213,4 +14283,127 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         httpRespMsg.data ="/upload/"+fileName;
         return httpRespMsg;
     }
+
+    @Override
+    public HttpRespMsg batchSetProjectTaskExecutor(String projectIds, String userIds) {
+        HttpRespMsg msg=new HttpRespMsg();
+        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
+        if(!StringUtils.isEmpty(projectIds)){
+            String[] split = projectIds.split(",");
+            List<Integer> projectIdList = Arrays.asList(split).stream().map(i -> Integer.valueOf(i)).collect(Collectors.toList());
+            List<Task> taskList = taskService.list(new LambdaQueryWrapper<Task>().in(Task::getProjectId, projectIdList).eq(Task::getTaskStatus,0));
+            List<TaskExecutor> taskExecutorList=new ArrayList<>();
+            List<Task> tasks=new ArrayList<>();
+            for (Integer projectId : projectIdList) {
+                List<Task> targetTaskList = taskList.stream().filter(t -> t.getProjectId().equals(projectId)).collect(Collectors.toList());
+                if(!StringUtils.isEmpty(userIds)){
+                    String[] split1 = userIds.split(",");
+                    targetTaskList.forEach(t->{
+                        //获取到原有的执行人
+                        StringBuilder executorId =new StringBuilder( t.getExecutorId()==null?"":t.getExecutorId());
+                        StringBuilder executorName = new StringBuilder( t.getExecutorName()==null?"":t.getExecutorName());
+                        StringBuilder executorColor = new StringBuilder( t.getExecutorColor()==null?"":t.getExecutorColor());
+                        for (String userId : split1) {
+                            List<String> list = Arrays.asList(executorId.toString().split(","));
+                            if(list.contains(userId)){
+                                continue;
+                            }
+                            Optional<User> first = userList.stream().filter(u -> u.getId().equals(userId)).findFirst();
+                            if(first.isPresent()){
+                                TaskExecutor taskExecutor=new TaskExecutor();
+                                taskExecutor.setExecutorColor(first.get().getColor());
+                                taskExecutor.setExecutorId(first.get().getId());
+                                taskExecutor.setExecutorName(first.get().getName());
+                                taskExecutor.setProjectId(projectId);
+                                taskExecutor.setTaskId(t.getId());
+                                if(executorId.length()>0){
+                                    executorId.append(",").append(taskExecutor.getExecutorId());
+                                    executorName.append(",").append(taskExecutor.getExecutorName());
+                                    executorColor.append(",").append(taskExecutor.getExecutorColor());
+                                }else {
+                                    executorId.append(taskExecutor.getExecutorId());
+                                    executorName.append(taskExecutor.getExecutorName());
+                                    executorColor.append(taskExecutor.getExecutorColor());
+                                }
+                                taskExecutorList.add(taskExecutor);
+                            }
+                        }
+                        t.setExecutorId(executorId.toString());
+                        t.setExecutorName(executorName.toString());
+                        t.setExecutorColor(executorColor.toString());
+                        tasks.add(t);
+                    });
+                }
+            }
+            if(tasks.size()>0){
+                taskService.saveOrUpdateBatch(tasks);
+            }
+            if(taskExecutorList.size()>0){
+                taskExecutorService.saveBatch(taskExecutorList);
+            }
+        }
+        return msg;
+    }
+
+    @Override
+    public HttpRespMsg groupExpendProcessListForChart(String startDate, String endDate, String projectIds, String groupNames) {
+        HttpRespMsg msg=new HttpRespMsg();
+        User user = userMapper.selectById(request.getHeader("token"));
+        NumberFormat percentFormat = NumberFormat.getPercentInstance();
+        percentFormat.setMaximumFractionDigits(2);
+        Integer companyId = user.getCompanyId();
+        List<String> groupNameList=new ArrayList<>();
+        List<Integer> projectIdList=new ArrayList<>();
+        if(!StringUtils.isEmpty(groupNames)){
+            groupNameList = Arrays.asList(groupNames.split(","));
+        }
+        if(!StringUtils.isEmpty(projectIds)){
+            projectIdList=Arrays.asList(projectIds.split(",")).stream().map(i->Integer.valueOf(i)).collect(Collectors.toList());
+        }
+        boolean viewAll = sysFunctionService.hasPriviledge(user.getRoleId(), "全部分组耗用进度表");
+        boolean incharger = sysFunctionService.hasPriviledge(user.getRoleId(), "负责部门分组耗用进度表");
+        List<Department> allDeptList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, companyId));
+        List<Map<String,Object>> resultList;
+        //是否具有查看全部数据的权限
+        //针对依斯呗 指定部门
+        List<Integer> regularDeptIds=new ArrayList<>();
+        if(user.getCompanyId()==3092){
+            List<String> nameString=new ArrayList<>();
+            nameString.add("4");
+            nameString.add("46");
+            nameString.add("45");
+            List<Department> departmentList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, user.getCompanyId()).in(Department::getDepartmentName, nameString));
+            List<Integer> theCollect = departmentList.stream().map(dm -> dm.getDepartmentId()).distinct().collect(Collectors.toList());
+            theCollect.add(-1);
+            for (Integer integer : theCollect) {
+                List<Integer> branchDepartment = getBranchDepartment(integer, allDeptList);
+                regularDeptIds.addAll(branchDepartment);
+            }
+        }
+        if(!viewAll){
+            if(!incharger){
+                //只能查看本人的数据
+                resultList=projectMapper.groupExpendProcessListForChart(user.getId(),companyId,startDate,endDate,null,null,projectIdList,groupNameList);
+            }else {
+                List<Department> departmentList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().select(Department::getDepartmentId).eq(Department::getManagerId, user.getId()));
+                List<DepartmentOtherManager> departmentOtherManagerList = departmentOtherManagerMapper.selectList(new QueryWrapper<DepartmentOtherManager>().eq("other_manager_id", user.getId()));
+                List<Integer> deptIds=new ArrayList<>();
+                List<Integer> theCollect = departmentList.stream().map(dm -> dm.getDepartmentId()).distinct().collect(Collectors.toList());
+                theCollect.add(-1);
+                List<Integer> otherCollect = departmentOtherManagerList.stream().map(dom -> dom.getDepartmentId()).distinct().collect(Collectors.toList());
+                otherCollect.add(-1);
+                theCollect.addAll(otherCollect);
+                for (Integer integer : theCollect) {
+                    List<Integer> branchDepartment = getBranchDepartment(integer, allDeptList);
+                    deptIds.addAll(branchDepartment);
+                }
+                resultList=projectMapper.groupExpendProcessListForChart(null,companyId,startDate,endDate,deptIds,regularDeptIds,projectIdList,groupNameList);
+            }
+        }else {
+            resultList=projectMapper.groupExpendProcessListForChart(null,companyId,startDate,endDate,null,regularDeptIds,projectIdList,groupNameList);
+        }
+        msg.setData(resultList);
+        return msg;
+    }
 }

+ 135 - 12
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -1894,15 +1894,6 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                                     item.put("key","审核人");
                                     item.put("value",wxCorpInfo.getSaasSyncContact() == 1?("$userName="+user.getName()+"$"): user.getName());
                                     dataJson.add(item);
-//                                    if(timeType.getNeedEvaluate()==1){
-//                                        JSONObject item1=new JSONObject();
-//                                        item1.put("key","评价");
-//                                        item1.put("value",StringUtils.isEmpty(report.getEvaluate())?"":report.getEvaluate());
-//                                        dataJson.add(item1);
-//                                        json.put("template_id","tty9TkCAAAWoUyhGnXRCZuhkgCqw_Uow");
-//                                    }else {
-//                                        json.put("template_id","tty9TkCAAANpvEtLrkPUGeOEd1-U7W2w");
-//                                    }
                                     json.put("template_id","tty9TkCAAANpvEtLrkPUGeOEd1-U7W2w");
                                     JSONObject item2=new JSONObject();
                                     item2.put("key","日期");
@@ -1929,7 +1920,6 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             ReportAuditLog log = new ReportAuditLog();
             log.setAuditChannel(channel);
             log.setCompanyId(company.getId());
-            //log.setResult("通过");
             log.setResult(MessageUtils.message("profession.approved"));
             log.setUserId(user.getId());
             log.setUserName(user.getName());
@@ -2243,7 +2233,48 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 if (updateReportList.size() > 0) {
                     updateBatchById(updateReportList);
                 }
-            }else {
+            } else if (timeType.getReportAuditType() == 8) {
+                //项目经理先审核,复核人后审核
+                boolean hasAuditAllPri = sysFunctionService.hasPriviledge(user.getRoleId(), "审核全员日报");
+                List<Report> updateReportList = new ArrayList<>();
+                List<Report> reportList = reportMapper.selectList(new QueryWrapper<Report>().select("id, state, creator_id, create_date, project_id, project_auditor_id, is_final_audit").in("id", ids));
+                for (Report r : reportList) {
+                    //直属领导审核或者部门负责人审核
+                    Report newReport = new Report();
+                    newReport.setId(r.getId());
+                    if (hasAuditAllPri) {
+                        newReport.setState(1);
+                        newReport.setProjectAuditState(1);
+                        newReport.setProjectAuditTime(LocalDateTime.now());
+                    } else {
+                        if (r.getProjectAuditorId().equals(user.getId())) {
+                            if (r.getIsFinalAudit() == 0) {
+                                //当前是项目经理审核,判断是否有复核人
+
+                                String reviwerId = projectMapper.selectById(r.getProjectId()).getReviwerId();
+                                if (reviwerId == null) {
+                                    r.setIsFinalAudit(1);
+                                    newReport.setIsFinalAudit(1);
+                                } else {
+                                    newReport.setProjectAuditorId(reviwerId);
+                                }
+                            }
+                            //上面可能处理为最终审核了
+                            if (r.getIsFinalAudit() == 1) {
+                                newReport.setProjectAuditState(1);
+                                newReport.setState(1);
+                            } else {
+                                newReport.setIsFinalAudit(1);
+                            }
+                            newReport.setProjectAuditTime(LocalDateTime.now());
+                        }
+                    }
+                    updateReportList.add(newReport);
+                }
+                if (updateReportList.size() > 0) {
+                    updateBatchById(updateReportList);
+                }
+            } else {
                 //之前的流程逻辑,综合了一层项目审核,或者一层任务分组审核。 可叠加部门审批流(部门审批时,本部门的负责人是否由上级部门负责人审核,可配置)
                 List<AuditWorkflowTimeSetting> settings = auditWorkflowTimeSettingMapper.selectList(
                         new QueryWrapper<AuditWorkflowTimeSetting>().eq("dept_id", auditTargetUser.getDepartmentId())
@@ -3513,6 +3544,48 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 if (updateReportList.size() > 0) {
                     updateBatchById(updateReportList);
                 }
+            } else if (timeType.getReportAuditType() == 8) {
+                //项目经理先审核,复核人后审核
+                boolean hasAuditAllPri = sysFunctionService.hasPriviledge(user.getRoleId(), "审核全员日报");
+                List<Report> updateReportList = new ArrayList<>();
+                List<Report> reportList = reportMapper.selectList(new QueryWrapper<Report>().select("id, state, group_audit_state, creator_id, create_date, project_id,audit_dept_managerid,department_audit_state,project_audit_state, project_auditor_id, is_dept_audit, is_final_audit").in("id", ids));
+                allUsers = userMapper.selectList(new QueryWrapper<User>().select("id, name, department_id").eq("company_id", company.getId()));
+                allReports = reportList;
+                for (Report r : reportList) {
+                    //直属领导审核或者部门负责人审核
+                    Report newReport = new Report();
+                    newReport.setId(r.getId());
+                    if (hasAuditAllPri) {
+                        newReport.setState(1);
+                        newReport.setProjectAuditState(1);
+                        newReport.setProjectAuditTime(LocalDateTime.now());
+                    } else {
+                        if (r.getProjectAuditorId().equals(user.getId())) {
+                            if (r.getIsFinalAudit() == 0) {
+                                //当前是项目经理审核,判断是否有复核人
+                                String reviwerId = projectMapper.selectById(r.getProjectId()).getReviwerId();
+                                if (reviwerId == null) {
+                                    newReport.setIsFinalAudit(1);
+                                    r.setIsFinalAudit(1);
+                                } else {
+                                    newReport.setProjectAuditorId(reviwerId);
+                                }
+                            }
+                            //上面可能处理为最终审核了
+                            if (r.getIsFinalAudit() == 1) {
+                                newReport.setProjectAuditState(1);
+                                newReport.setState(1);
+                            } else {
+                                newReport.setIsFinalAudit(1);
+                            }
+                            newReport.setProjectAuditTime(LocalDateTime.now());
+                        }
+                    }
+                    updateReportList.add(newReport);
+                }
+                if (updateReportList.size() > 0) {
+                    updateBatchById(updateReportList);
+                }
             } else {
                 List<AuditWorkflowTimeSetting> settings = auditWorkflowTimeSettingMapper.selectList(
                         new QueryWrapper<AuditWorkflowTimeSetting>().eq("company_id", company.getId())
@@ -4441,7 +4514,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         List<UserMonthWork> userMonthWorks = new ArrayList<UserMonthWork>();
         //获取所有同步的企业微信数据
 //        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()));
+        List<UserCorpwxTime> userCorpwxTimeList = userCorpwxTimeMapper.selectList(new QueryWrapper<UserCorpwxTime>().between("create_date", LocalDate.parse(startDate, df), LocalDate.parse(endDate, df)).eq("company_id", user.getCompanyId()));
         String lastUserId = null;
         UserMonthWork lastUserData = null;
         for (Map<String, Object> data : list) {
@@ -5535,6 +5608,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             titles.add("部门主要负责人");
             titles.add(MessageUtils.message("entry.projectId"));
             titles.add(MessageUtils.message("entry.projectName"));
+            titles.add(MessageUtils.message("entry.projectStage"));
             if(companyId==936){
                 titles.add("项目状态");
                 titles.add("自主项目类别");
@@ -5840,6 +5914,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 }
                 item.add((String) map.get("projectCode"));
                 item.add((String) map.get("project"));
+                item.add(map.get("stageName")==null?"":(String) map.get("stageName"));
                 if(companyId==936){
                     String projectStatus="";
                     switch (Integer.valueOf(String.valueOf(map.get("projectStatus")))){
@@ -9527,4 +9602,52 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         cancelReportPushSap(uuids,user);
         return msg;
     }
+
+    @Override
+    public HttpRespMsg getReportListWithTransfer(String startDate, String endDate, String userIds, Integer projectId, Integer pageIndex, Integer pageSize) {
+        HttpRespMsg msg=new HttpRespMsg();
+        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        Integer start=null;
+        Integer size=null;
+        if(pageIndex!=null&&pageSize!=null){
+            size=pageSize;
+            start=(pageIndex-1)*size;
+        }
+        List<String> userIdList=new ArrayList<>();
+        if(!StringUtils.isEmpty(userIds)){
+            userIdList = Arrays.asList(userIds.split(","));
+        }
+        List<Map<String,Object>> resultList=reportMapper.getReportListWithTransfer(companyId,startDate,endDate,userIdList,projectId,start,size);
+        Integer count=reportMapper.getReportListWithTransferCount(companyId,startDate,endDate,userIdList,projectId);
+        Map<String,Object> map=new HashMap<>();
+        map.put("result",resultList);
+        map.put("count",count);
+        msg.setData(map);
+        return msg;
+    }
+
+    @Override
+    public HttpRespMsg transferReport(String reportIds, Integer projectId, Integer groupId, Integer stageId) {
+        HttpRespMsg msg=new HttpRespMsg();
+        if(!StringUtils.isEmpty(reportIds)){
+            List<String> reportIdList = Arrays.asList(reportIds.split(","));
+            List<Report> transferReportList=new ArrayList<>();
+            String stagesName = stagesMapper.selectById(stageId).getStagesName();
+            for (String reportIdStr : reportIdList) {
+                Integer reportId = Integer.valueOf(reportIdStr);
+                Report report = new Report();
+                report.setId(reportId);
+                report.setProjectId(projectId);
+                report.setGroupId(groupId);
+                report.setStage(stagesName);
+                transferReportList.add(report);
+            }
+            if(transferReportList.size()>0){
+                if(!reportService.updateBatchById(transferReportList)){
+                    msg.setError("验证失败");
+                }
+            }
+        }
+        return msg;
+    }
 }

+ 26 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportWriteOffServiceImpl.java

@@ -0,0 +1,26 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.ReportWriteOff;
+import com.management.platform.mapper.ReportWriteOffMapper;
+import com.management.platform.service.ReportWriteOffService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.management.platform.util.HttpRespMsg;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-07-17
+ */
+@Service
+public class ReportWriteOffServiceImpl extends ServiceImpl<ReportWriteOffMapper, ReportWriteOff> implements ReportWriteOffService {
+
+    @Resource
+    private ReportWriteOffMapper reportWriteOffMapper;
+
+}

+ 314 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserWithBeisenServiceImpl.java

@@ -1,11 +1,38 @@
 package com.management.platform.service.impl;
 
-import com.management.platform.entity.UserWithBeisen;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.management.platform.entity.*;
+import com.management.platform.mapper.BeisenConfigMapper;
+import com.management.platform.mapper.TimeTypeMapper;
+import com.management.platform.mapper.UserMapper;
 import com.management.platform.mapper.UserWithBeisenMapper;
+import com.management.platform.service.HolidaySettingService;
+import com.management.platform.service.LeaveSheetService;
+import com.management.platform.service.UserFvTimeService;
 import com.management.platform.service.UserWithBeisenService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+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.stereotype.Service;
 
+import javax.servlet.http.HttpServletRequest;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
 /**
  * <p>
  *  服务实现类
@@ -17,4 +44,290 @@ import org.springframework.stereotype.Service;
 @Service
 public class UserWithBeisenServiceImpl extends ServiceImpl<UserWithBeisenMapper, UserWithBeisen> implements UserWithBeisenService {
 
+    private UserFvTimeService userFvTimeService;
+    private UserMapper userMapper;
+    private TimeTypeMapper timeTypeMapper;
+    private HttpServletRequest request;
+    private UserWithBeisenService userWithBeisenService;
+    private BeisenConfigMapper beisenConfigMapper;
+    private HolidaySettingService holidaySettingService;
+    private LeaveSheetService leaveSheetService;
+
+    @Override
+    public HttpRespMsg syncAttendanceFromBeisen(String startDate, String endDate,Integer companyId) {
+        HttpRespMsg msg=new HttpRespMsg();
+        DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        DateTimeFormatter df1=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        DateTimeFormatter df2=DateTimeFormatter.ofPattern("HH:mm");
+        DateTimeFormatter df3=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
+        DateTimeFormatter df4=DateTimeFormatter.ofPattern("HH:mm:ss");
+        TimeType timeType = timeTypeMapper.selectById(companyId);
+        List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
+        List<UserWithBeisen> userWithBeisenList = userWithBeisenService.list(new LambdaQueryWrapper<UserWithBeisen>().eq(UserWithBeisen::getCompanyId, companyId));
+        BeisenConfig beisenConfig = beisenConfigMapper.selectById(companyId);
+        //获取特殊节假日设置
+        List<HolidaySetting> holidaySettings = holidaySettingService.list(new LambdaQueryWrapper<HolidaySetting>().eq(HolidaySetting::getCompanyId, companyId));
+        if(beisenConfig==null){
+            msg.setError("北森基础数据配置未完成,请联系服务商完成配置");
+            return msg;
+        }
+        //todo 获取到指定日期的考勤数据
+        JSONArray attendanceStatistics=new JSONArray();
+        //todo 获取到指定日期的加班数据
+        List<LocalDate> workDaysListInRange = WorkDayCalculateUtils.getWorkDaysListInRange(startDate, endDate, 1);
+        JSONArray allOverTimeList=new JSONArray();
+        JSONArray allVacationList=new JSONArray();
+        List<LeaveSheet> leaveSheetList=new ArrayList<>();
+        //同步休假数据到工时管家
+        for (int i = 0; i < allVacationList.size(); i++) {
+            JSONObject jsonObject = allVacationList.getJSONObject(i);
+            Optional<UserWithBeisen> beisen = userWithBeisenList.stream().filter(b -> b.getUserId().equals(jsonObject.getString("StaffId"))).findFirst();
+            if(beisen.isPresent()){
+                Optional<User> first = userList.stream().filter(u -> u.getJobNumber().equals(beisen.get().getJobNumber())).findFirst();
+                if(first.isPresent()){
+                    LeaveSheet leaveSheet=new LeaveSheet();
+                    leaveSheet.setCompanyId(beisenConfig.getCompanyId());
+                    leaveSheet.setStatus(0);
+                    leaveSheet.setOwnerId(first.get().getId());
+                    leaveSheet.setOwnerName(first.get().getName());
+                    leaveSheet.setStartDate(LocalDateTime.parse(String.valueOf(jsonObject.get("VacationStartDateTime")),df3).toLocalDate());
+                    leaveSheet.setEndDate(LocalDateTime.parse(String.valueOf(jsonObject.get("VacationStopDateTime")),df3).toLocalDate());
+                    leaveSheet.setTimeType(1);
+                    leaveSheet.setTimeDays(jsonObject.getFloatValue("DayValueOfDuration"));
+                    leaveSheet.setTimeHours(jsonObject.getFloatValue("VacationDuration")/60);
+                    Integer leaveType;
+                    switch (jsonObject.getString("VacationType")){
+                        case "事假":leaveType=0;
+                            break;
+                        case "病假":leaveType=1;
+                            break;
+                        case "年假":leaveType=2;
+                            break;
+                        case "产假":leaveType=3;
+                            break;
+                        case "婚假":leaveType=4;
+                            break;
+                        case "丧假":leaveType=5;
+                            break;
+                        case "调休":leaveType=6;
+                            break;
+                        case "陪产假":leaveType=7;
+                            break;
+                        default:leaveType=8;
+                    }
+                    leaveSheet.setLeaveType(leaveType);
+                    leaveSheet.setRemark(jsonObject.getString("Reason"));
+                    leaveSheet.setStatus(jsonObject.getString("ApproveStatus").equals("通过")?0:jsonObject.getString("ApproveStatus").equals("审批中")?1:2);
+                    leaveSheet.setProcinstId(jsonObject.getString("VacationId"));
+                    LeaveSheet one = leaveSheetService.getOne(new LambdaQueryWrapper<LeaveSheet>().eq(LeaveSheet::getProcinstId,leaveSheet.getProcinstId()).eq(LeaveSheet::getOwnerId, first.get().getId()).eq(LeaveSheet::getStartDate, leaveSheet.getStartDate()).eq(LeaveSheet::getEndDate, leaveSheet.getEndDate()));
+                    if(one==null){
+                        leaveSheetList.add(leaveSheet);
+                    }
+                }
+            }
+        }
+        if(leaveSheetList.size()>0){
+            leaveSheetService.saveOrUpdateBatch(leaveSheetList);
+        }
+        List<UserFvTime> userFvTimeList=new ArrayList<>();
+        for (LocalDate localDate : workDaysListInRange) {
+            JSONArray statisticList = BeiSenUtils.getAttendanceStatistics(df.format(localDate), df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(), 1, 100);
+            JSONArray overTimeList = BeiSenUtils.getOverTimeList(df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(), 1, 100);
+            JSONArray vacationList = BeiSenUtils.getVacationList(df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(),1,100);
+            allOverTimeList.addAll(overTimeList);
+            attendanceStatistics.addAll(statisticList);
+            allVacationList.addAll(vacationList);
+        }
+        for (LocalDate localDate : workDaysListInRange) {
+            Stream<JSONObject> swipingCardsStream = attendanceStatistics.stream().map(item -> (JSONObject) item);
+            //todo: 获取当天的考勤数据
+            List<JSONObject> swipingCardDateList = swipingCardsStream.filter(i -> LocalDateTime.parse(i.getString("SwipingCardDate"),df1).toLocalDate().equals(localDate)).collect(Collectors.toList());
+            for (JSONObject item : swipingCardDateList) {
+                //获取当前数据下的人员工号对应到工时管家
+                String cardNumber = item.getString("CardNumber");
+                Optional<User> first = userList.stream().filter(f -> f.getJobNumber().equals(cardNumber)).findFirst();
+                //todo: 获取考勤打卡时间集合
+                JSONArray times = item.getJSONArray("Times");
+                Stream<JSONObject> timeStream = times.stream().map(time -> (JSONObject) time);
+                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> 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> maxOp = maxLocalTimeList.stream().max(LocalTime::compareTo);
+                if(first.isPresent()){
+                    boolean workDay = WorkDayCalculateUtils.isWorkDay(localDate);
+                    //todo:针对景昱 工作日默认以8小时工作制度加上加班时长 非工作日以加班时长为准
+                    Double workTime;
+                    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;
+                        }
+                    }
+                    Stream<JSONObject> overTimeStream = allOverTimeList.stream().map(elment -> (JSONObject) elment);
+                    Stream<JSONObject> vacationStream = allVacationList.stream().map(elment -> (JSONObject) elment);
+                    Optional<UserWithBeisen> beisen = userWithBeisenList.stream().filter(u -> u.getJobNumber() != null && u.getJobNumber().equals(first.get().getJobNumber())).findFirst();
+                    if(beisen.isPresent()){
+                        //todo:之前的逻辑
+//                        List<JSONObject> overTimeList = overTimeStream.filter(a -> a.getString("StaffId").equals(beisen.get().getUserId())
+//                                && (a.getIntValue("ApproveStatus") == 2||a.getIntValue("ApproveStatus") == 1)
+//                                &&LocalDateTime.parse(a.getString("StartDate"),df1).toLocalDate().isEqual(localDate)).collect(Collectors.toList());
+                        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);
+                        //计算加班时长 工作日打卡超过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())){
+                                    //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
+                                    //对比打卡体现的加班时长和加班单时长取小
+                                    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+round(divide.doubleValue(),0.5);
+                                    }
+                                }else {
+                                    //开始日期和结束日期是不相同的情况 说明是加班区间存在加班到第二天的情况
+                                    LocalDateTime start = LocalDateTime.parse(o.getString("StartDate"), df1);
+                                    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_DOWN);
+                                    double l = decimal.doubleValue();
+                                    //对比打卡体现的加班时长和加班单时长取小
+                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
+                                    if(divide.doubleValue()>l){
+                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
+                                        workTime=workTime+l;
+                                    }else {
+                                        workTime=workTime+round(divide.doubleValue(),0.5);
+                                    }
+                                }
+                            }else if(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate().isEqual(localDate)){
+                                //存在结束日期为当天的数据
+                                if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate())){
+                                    //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
+                                    //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
+                                    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+round(divide.doubleValue(),0.5);
+                                    }
+                                }else {
+                                    //开始日期和结束日期是不相同的情况 说明是加班区间存在加班到第二天的情况
+                                    LocalDateTime stop = LocalDateTime.parse(o.getString("StopDate"), df1);
+                                    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_DOWN);
+                                    double l = decimal.doubleValue();
+                                    //对比打卡体现的加班时长和加班单时长取小
+                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
+                                    if(divide.doubleValue()>l){
+                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
+                                        workTime=workTime+l;
+                                    }else {
+                                        workTime=workTime+round(divide.doubleValue(),0.5);
+                                    }
+                                }
+                            }
+                        }
+                        //处理修改
+                        List<JSONObject> vacationList = vacationStream.filter(a ->{
+                            LocalDate vacationStartDate = LocalDateTime.parse(a.getString("VacationStartDateTime"), df3).toLocalDate();
+                            LocalDate vacationStopDate = LocalDateTime.parse(a.getString("VacationStopDateTime"), df3).toLocalDate();
+                            boolean b=false;
+                            if((localDate.isAfter(vacationStartDate)||localDate.isEqual(vacationStartDate))
+                                    &&(localDate.isBefore(vacationStopDate)||localDate.isEqual(vacationStopDate))){
+                                b=true;
+                            }
+                            if(a.getString("StaffId").equals(beisen.get().getUserId())
+                                    && b
+                                    &&a.getString("DocumentType").equals("请假")
+                                    &&  (a.getString("ApproveStatus").equals("通过") || a.getString("ApproveStatus").equals("审批中"))){
+                                return true;
+                            }
+                            return false;
+                        }).collect(Collectors.toList());
+                        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_DOWN);
+//                            //可能存在休假多天 只减去一天
+                            if(decimal.doubleValue()>=8){
+                                workTime= workTime-8;
+                            }else {
+                                workTime= workTime-decimal.doubleValue();
+                            }
+                        }else {
+//                            //在工时管家已经同步到的请假数据中找到当前人员的所有请假数据
+//                            List<LeaveSheet> list = leaveSheetService.list(new LambdaQueryWrapper<LeaveSheet>().eq(LeaveSheet::getOwnerId, beisen.get().getUserId()));
+//                            //当前考勤日期在工时同步到的请假数据开始请假和结束日期区间的数据
+//                            List<LeaveSheet> sheets = list.stream().filter(l -> (l.getStartDate().isBefore(localDate) || l.getStartDate().isEqual(localDate)) && (l.getEndDate().isAfter(localDate) || l.getEndDate().isEqual(localDate))).collect(Collectors.toList());
+//                            double sum = sheets.stream().mapToDouble(LeaveSheet::getTimeHours).sum();
+//                            if(sum>=8){
+//                                workTime= workTime-8;
+//                            }else {
+//                                workTime= workTime-sum;
+//                            }
+                        }
+                    }
+                    UserFvTime userFvTime=new UserFvTime();
+                    userFvTime.setWorkDate(localDate);
+                    userFvTime.setStartTime(df2.format(min));
+                    userFvTime.setEndTime(df2.format(max));
+                    userFvTime.setUserId(first.get().getId());
+                    userFvTime.setCompanyId(companyId);
+                    userFvTime.setWorkHours(workTime.floatValue());
+                    UserFvTime one = userFvTimeService.getOne(new LambdaQueryWrapper<UserFvTime>().eq(UserFvTime::getCompanyId, companyId).eq(UserFvTime::getUserId, first.get().getId()).eq(UserFvTime::getWorkDate, localDate));
+                    if(one!=null){
+                        userFvTime.setId(one.getId());
+                    }
+                    userFvTimeList.add(userFvTime);
+                }
+            }
+        }
+        if(userFvTimeList.size()>0){
+            if(!userFvTimeService.saveOrUpdateBatch(userFvTimeList)){
+                msg.setError("同步验证失败");
+            }
+        }
+        return msg;
+    }
+
+    public static double round( double num, double multipleOf) {
+        if (num%multipleOf == 0){
+            return num;
+        }
+        return Math.floor(num / multipleOf) * multipleOf;
+    }
 }

+ 9 - 255
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java

@@ -770,8 +770,15 @@ public class TimingTask {
         }
     }
 
+    /**
+    * @Description:定时任务同步ladp组织架构数据
+    * @Param: []
+    * @return: void
+    * @Author: yurk
+    * @Date: 2024/7/19
+    */
     @Scheduled(cron = "0 10 1 ? * *")
-    private void synAd() throws Exception {
+    private void syncAd() throws Exception {
         if (isDev) return;
         if(!isPrivateDeploy) return;
         List<TimeType> timeTypeList = timeTypeMapper.selectList(new QueryWrapper<TimeType>().eq("sync_ad", 1));
@@ -2261,260 +2268,7 @@ public class TimingTask {
             startDate=LocalDate.now().minusDays(3).format(df);
             endDate=LocalDate.now().plusDays(1).format(df);
         }
-
-
-        List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, 5978));
-        List<UserWithBeisen> userWithBeisenList = userWithBeisenService.list(new LambdaQueryWrapper<UserWithBeisen>().eq(UserWithBeisen::getCompanyId, 5978));
-        BeisenConfig beisenConfig = beisenConfigMapper.selectById(5978);
-        //获取特殊节假日设置
-        List<HolidaySetting> holidaySettings = holidaySettingService.list(new LambdaQueryWrapper<HolidaySetting>().eq(HolidaySetting::getCompanyId, 5978));
-        if(beisenConfig==null){
-            return;
-        }
-        //todo 获取到指定日期的加班数据
-        List<LocalDate> workDaysListInRange = WorkDayCalculateUtils.getWorkDaysListInRange(startDate, endDate, 1);
-        JSONArray allOverTimeList=new JSONArray();
-        JSONArray attendanceStatistics=new JSONArray();
-        JSONArray allVacationList=new JSONArray();
-        List<UserFvTime> userFvTimeList=new ArrayList<>();
-        List<LeaveSheet> leaveSheetList=new ArrayList<>();
-        for (LocalDate localDate : workDaysListInRange) {
-            JSONArray overTimeList = BeiSenUtils.getOverTimeList(df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(), 1, 100);
-            //todo 获取到指定日期的考勤数据
-            JSONArray attendanceStatisticList = BeiSenUtils.getAttendanceStatistics(df.format(localDate), df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(), 1, 100);
-            JSONArray vacationList = BeiSenUtils.getVacationList(df.format(localDate), beisenConfig.getAppKey(), beisenConfig.getAppSecret(),1,100);
-            allOverTimeList.addAll(overTimeList);
-            attendanceStatistics.addAll(attendanceStatisticList);
-            allVacationList.addAll(vacationList);
-        }
-        for (LocalDate localDate : workDaysListInRange) {
-            Stream<JSONObject> swipingCardsStream = attendanceStatistics.stream().map(item -> (JSONObject) item);
-            //todo: 获取当天的考勤数据
-            List<JSONObject> swipingCardDateList = swipingCardsStream.filter(i -> LocalDateTime.parse(i.getString("SwipingCardDate"),df1).toLocalDate().equals(localDate)).collect(Collectors.toList());
-            for (JSONObject item : swipingCardDateList) {
-                //获取当前数据下的人员工号对应到工时管家
-                String cardNumber = item.getString("CardNumber");
-                Optional<User> first = userList.stream().filter(f -> f.getJobNumber().equals(cardNumber)).findFirst();
-                //todo: 获取考勤打卡时间集合
-                JSONArray times = item.getJSONArray("Times");
-                Stream<JSONObject> timeStream = times.stream().map(time -> (JSONObject) time);
-                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> 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> maxOp = maxLocalTimeList.stream().max(LocalTime::compareTo);
-                //获取最晚下班时间
-                if(first.isPresent()){
-                    boolean workDay = WorkDayCalculateUtils.isWorkDay(localDate);
-                    //todo:针对景昱 工作日默认以8小时工作制度加上加班时长 非工作日以加班时长为准
-                    Double workTime;
-                    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;
-                        }
-                    }
-                    Stream<JSONObject> overTimeStream = allOverTimeList.stream().map(elment -> (JSONObject) elment);
-                    Stream<JSONObject> vacationStream = allVacationList.stream().map(elment -> (JSONObject) elment);
-                    Optional<UserWithBeisen> beisen = userWithBeisenList.stream().filter(u -> u.getJobNumber() != null && u.getJobNumber().equals(first.get().getJobNumber())).findFirst();
-                    if(beisen.isPresent()){
-                        //todo:之前的逻辑
-//                        List<JSONObject> overTimeList = overTimeStream.filter(a -> a.getString("StaffId").equals(beisen.get().getUserId())
-//                                && (a.getIntValue("ApproveStatus") == 2||a.getIntValue("ApproveStatus") == 1)
-//                                &&LocalDateTime.parse(a.getString("StartDate"),df1).toLocalDate().isEqual(localDate)).collect(Collectors.toList());
-                        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);
-                        //计算加班时长 工作日打卡超过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())){
-                                    //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
-                                    //对比打卡体现的加班时长和加班单时长取小
-                                    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+round(divide.doubleValue(),0.5);
-                                    }
-                                }else {
-                                    //开始日期和结束日期是不相同的情况 说明是加班区间存在加班到第二天的情况
-                                    LocalDateTime start = LocalDateTime.parse(o.getString("StartDate"), df1);
-                                    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_DOWN);
-                                    double l = decimal.doubleValue();
-                                    //对比打卡体现的加班时长和加班单时长取小
-                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
-                                    if(divide.doubleValue()>l){
-                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
-                                        workTime=workTime+l;
-                                    }else {
-                                        workTime=workTime+round(divide.doubleValue(),0.5);
-                                    }
-                                }
-                            }else if(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate().isEqual(localDate)){
-                                //存在结束日期为当天的数据
-                                if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(LocalDateTime.parse(o.getString("StopDate"),df1).toLocalDate())){
-                                    //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
-                                    //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
-                                    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+round(divide.doubleValue(),0.5);
-                                    }
-                                }else {
-                                    //开始日期和结束日期是不相同的情况 说明是加班区间存在加班到第二天的情况
-                                    LocalDateTime stop = LocalDateTime.parse(o.getString("StopDate"), df1);
-                                    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_DOWN);
-                                    double l = decimal.doubleValue();
-                                    //对比打卡体现的加班时长和加班单时长取小
-                                    BigDecimal divide = overTimeBigDecimal.divide(new BigDecimal(60), 1, RoundingMode.HALF_DOWN);
-                                    if(divide.doubleValue()>l){
-                                        //打卡获取到的加班时长大于加班单时长 需要在打卡体现的时长-打卡体现的加班时长+加班单时长
-                                        workTime=workTime+l;
-                                    }else {
-                                        workTime=workTime+round(divide.doubleValue(),0.5);
-                                    }
-                                }
-                            }
-                        }
-                        List<JSONObject> vacationList = vacationStream.filter(a ->{
-                            LocalDate vacationStartDate = LocalDateTime.parse(a.getString("VacationStartDateTime"), df3).toLocalDate();
-                            LocalDate vacationStopDate = LocalDateTime.parse(a.getString("VacationStopDateTime"), df3).toLocalDate();
-                            boolean b=false;
-                            if((localDate.isAfter(vacationStartDate)||localDate.isEqual(vacationStartDate))
-                                    &&(localDate.isBefore(vacationStopDate)||localDate.isEqual(vacationStopDate))){
-                                b=true;
-                            }
-                            if(a.getString("StaffId").equals(beisen.get().getUserId())
-                                    && b
-                                    &&a.getString("DocumentType").equals("请假")
-                                    &&  (a.getString("ApproveStatus").equals("通过") || a.getString("ApproveStatus").equals("审批中"))){
-                                return true;
-                            }
-                            return false;
-                        }).collect(Collectors.toList());
-                        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_DOWN);
-//                            //可能存在休假多天 只减去一天
-                            if(decimal.doubleValue()>=8){
-                                workTime= workTime-8;
-                            }else {
-                                workTime= workTime-decimal.doubleValue();
-                            }
-                        }
-                    }
-                    UserFvTime userFvTime=new UserFvTime();
-                    userFvTime.setWorkDate(localDate);
-                    userFvTime.setStartTime(df2.format(min));
-                    userFvTime.setEndTime(df2.format(max));
-                    userFvTime.setUserId(first.get().getId());
-                    userFvTime.setCompanyId(5978);
-                    userFvTime.setWorkHours(workTime.floatValue());
-                    UserFvTime one = userFvTimeService.getOne(new LambdaQueryWrapper<UserFvTime>().eq(UserFvTime::getCompanyId, 5978).eq(UserFvTime::getUserId, first.get().getId()).eq(UserFvTime::getWorkDate, localDate));
-                    if(one!=null){
-                        userFvTime.setId(one.getId());
-                    }
-                    userFvTimeList.add(userFvTime);
-                }
-            }
-        }
-        if(userFvTimeList.size()>0){
-            userFvTimeService.saveOrUpdateBatch(userFvTimeList);
-        }
-        //同步休假数据到工时管家
-        for (int i = 0; i < allVacationList.size(); i++) {
-            JSONObject jsonObject = allVacationList.getJSONObject(i);
-            Optional<UserWithBeisen> beisen = userWithBeisenList.stream().filter(b -> b.getUserId().equals(jsonObject.getString("StaffId"))).findFirst();
-            if(beisen.isPresent()){
-                Optional<User> first = userList.stream().filter(u -> u.getJobNumber().equals(beisen.get().getJobNumber())).findFirst();
-                if(first.isPresent()){
-                    LeaveSheet leaveSheet=new LeaveSheet();
-                    leaveSheet.setCompanyId(beisenConfig.getCompanyId());
-                    leaveSheet.setStatus(0);
-                    leaveSheet.setOwnerId(first.get().getId());
-                    leaveSheet.setOwnerName(first.get().getName());
-                    leaveSheet.setStartDate(LocalDateTime.parse(String.valueOf(jsonObject.get("VacationStartDateTime")),df3).toLocalDate());
-                    leaveSheet.setEndDate(LocalDateTime.parse(String.valueOf(jsonObject.get("VacationStopDateTime")),df3).toLocalDate());
-                    leaveSheet.setTimeType(1);
-                    leaveSheet.setTimeDays(jsonObject.getFloatValue("DayValueOfDuration"));
-                    leaveSheet.setTimeHours(jsonObject.getFloatValue("VacationDuration")/60);
-                    Integer leaveType;
-                    switch (jsonObject.getString("VacationType")){
-                        case "事假":leaveType=0;
-                            break;
-                        case "病假":leaveType=1;
-                            break;
-                        case "年假":leaveType=2;
-                            break;
-                        case "产假":leaveType=3;
-                            break;
-                        case "婚假":leaveType=4;
-                            break;
-                        case "丧假":leaveType=5;
-                            break;
-                        case "调休":leaveType=6;
-                            break;
-                        case "陪产假":leaveType=7;
-                            break;
-                        default:leaveType=8;
-                    }
-                    leaveSheet.setLeaveType(leaveType);
-                    leaveSheet.setRemark(jsonObject.getString("Reason"));
-                    leaveSheet.setStatus(jsonObject.getString("ApproveStatus").equals("通过")?0:jsonObject.getString("Reason").equals("审批中")?1:2);
-                    leaveSheet.setProcinstId(jsonObject.getString("VacationId"));
-                    LeaveSheet one = leaveSheetService.getOne(new LambdaQueryWrapper<LeaveSheet>().eq(LeaveSheet::getOwnerId, first.get().getId()).eq(LeaveSheet::getStartDate, leaveSheet.getStartDate()).eq(LeaveSheet::getProcinstId,leaveSheet.getProcinstId()).eq(LeaveSheet::getEndDate, leaveSheet.getEndDate()));
-                    if(one==null){
-                        leaveSheetList.add(leaveSheet);
-                    }
-                }
-            }
-        }
-        if(leaveSheetList.size()>0){
-            leaveSheetService.saveOrUpdateBatch(leaveSheetList);
-        }
-    }
-
-    public static double round( double num, double multipleOf) {
-        if (num%multipleOf == 0){
-            return num;
-        }
-        return Math.floor(num / multipleOf) * multipleOf;
+        userWithBeisenService.syncAttendanceFromBeisen(startDate,endDate,5978);
     }
 
 

+ 22 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/DepartmentMapper.xml

@@ -68,6 +68,28 @@
         GROUP BY b.project_id, a.id order by a.department_id
     </select>
 
+    <!--根据人员获取成本-->
+    <select id="getCostByUserSum" resultType="java.util.Map">
+        SELECT a.id as id, a.name AS user,a.corpwx_userid as corpwxUserId, a.job_number as jobNumber, ifnull(SUM(b.working_time),0) AS time, ifnull(SUM(b.cost),0) AS
+        money
+        FROM user AS a
+        LEFT JOIN report AS b ON a.id = b.creator_id
+        WHERE b.state = 1
+        <if test="departmentIds != null and departmentIds.size()>0">
+            AND b.dept_id IN
+            <foreach collection="departmentIds" item="departmentId" index="index" open="(" close=")" separator=",">
+                #{departmentId}
+            </foreach>
+        </if>
+        <if test="companyId != null">
+            AND a.company_id = #{companyId}
+        </if>
+        <if test="startDate != null and endDate != null">
+            AND b.create_date between #{startDate} and #{endDate}
+        </if>
+        GROUP BY a.id order by a.department_id
+    </select>
+
     <!-- 根据人员获取自定义的日报数值 -->
     <select id="getCustomDataByUser" resultType="java.util.Map">
         SELECT a.id as id, a.name AS user,a.corpwx_userid as corpwxUserid, a.job_number as jobNumber,c.project_name AS project, IFNULL(SUM(b.custom_data),0) AS cost

Plik diff jest za duży
+ 85 - 27
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml


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

@@ -70,7 +70,7 @@
         , reject_reason as rejectReason, reject_username as rejectUsername, reject_userid as rejectUserid, degree_id as degree_id,report_extra_degree.name as degreeName,task_group.name as groupName,a.group_id as groupId,a.custom_data as customData
         ,u.name as projectAuditorName,u.corpwx_userid as projectAuditorCorpwxUserId, a.project_auditor_id as projectAuditorId, department.department_name as departmentName,dp2.department_name as buDepartmentName,department.department_id as departmentId, a.overtime_hours as overtimeHours, a.custom_text as customText,a.project_audit_time  as projectAuditTime,project_main.name as projectMainName,
         a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3, a.batch_id as batchId,a.sap_service_id as sapServiceId,b.status as projectStatus,DATE_FORMAT(b.finish_date,'%Y-%m-%d') as finishDate,ps.project_category_sub as projectCategorySub
-        ,u2.name as projectManagerName,u2.corpwx_userid as projectManagerCorpwxUserId, multi_degr_id as multiDegrId
+        ,u2.name as projectManagerName,u2.corpwx_userid as projectManagerCorpwxUserId, multi_degr_id as multiDegrId,b.current_stage_name as stageName
         FROM report AS a
         JOIN project AS b ON a.project_id=b.id
         LEFT JOIN project_separate AS ps on b.id=ps.id
@@ -127,7 +127,7 @@
         , reject_reason as rejectReason, reject_username as rejectUsername, reject_userid as rejectUserid, degree_id as degree_id,report_extra_degree.name as degreeName,task_group.name as groupName,a.group_id as groupId,a.custom_data as customData
         ,u.name as projectAuditorName,u.corpwx_userid as projectAuditorCorpwxUserId, a.project_auditor_id as projectAuditorId, department.department_name as departmentName,dp2.department_name as buDepartmentName,department.department_id as departmentId, a.overtime_hours as overtimeHours, a.custom_text as customText,a.project_audit_time  as projectAuditTime,project_main.name as projectMainName,
         GROUP_CONCAT(rlog.operator_id,'@', rlog.operate_date,'@', rlog.msg SEPARATOR '❤') AS logMsg,a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3,a.batch_id as batchId,a.sap_service_id as sapServiceId,b.status as projectStatus,DATE_FORMAT(b.finish_date,'%Y-%m-%d') as finishDate,ps.project_category_sub as projectCategorySub
-        ,u2.name as projectManagerName,u2.corpwx_userid as projectManagerCorpwxUserId, multi_degr_id as multiDegrId
+        ,u2.name as projectManagerName,u2.corpwx_userid as projectManagerCorpwxUserId, multi_degr_id as multiDegrId,b.current_stage_name as stageName
         FROM report AS a
         JOIN project AS b ON a.project_id=b.id
         LEFT JOIN project_separate AS ps on b.id=ps.id
@@ -211,7 +211,7 @@
         departmentName,dp2.department_name as buDepartmentName,department.department_id as departmentId, a.overtime_hours as overtimeHours, a.custom_text as customText, a.project_audit_time as
         projectAuditTime,project_main.name as projectMainName,a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3, a.batch_id as batchId,a.sap_service_id as sapServiceId,b.status as projectStatus,
         DATE_FORMAT(b.finish_date,'%Y-%m-%d') as finishDate,ps.project_category_sub as projectCategorySub
-        ,u2.name as projectManagerName,u2.corpwx_userid as projectManagerCorpwxUserId, multi_degr_id as multiDegrId
+        ,u2.name as projectManagerName,u2.corpwx_userid as projectManagerCorpwxUserId, multi_degr_id as multiDegrId,b.current_stage_name as stageName
         FROM report AS a
         JOIN project AS b ON a.project_id=b.id
         LEFT JOIN project_separate AS ps on b.id=ps.id
@@ -279,7 +279,7 @@
         departmentName,dp2.department_name as buDepartmentName,department.department_id as departmentId, a.overtime_hours as overtimeHours, a.custom_text as customText, a.project_audit_time as
         projectAuditTime,project_main.name as projectMainName,b.status as projectStatus,DATE_FORMAT(b.finish_date,'%Y-%m-%d') as finishDate,ps.project_category_sub as projectCategorySub,
         GROUP_CONCAT(rlog.operator_id,'@', rlog.operate_date,'@', rlog.msg SEPARATOR '❤') AS logMsg,a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3
-        , a.batch_id as batchId,a.sap_service_id as sapServiceId,u2.name as projectManagerName,u2.corpwx_userid as projectManagerCorpwxUserId, multi_degr_id as multiDegrId
+        , a.batch_id as batchId,a.sap_service_id as sapServiceId,u2.name as projectManagerName,u2.corpwx_userid as projectManagerCorpwxUserId, multi_degr_id as multiDegrId,b.current_stage_name as stageName
         FROM report AS a
         JOIN project AS b ON a.project_id=b.id
         LEFT JOIN project_separate AS ps on b.id=ps.id
@@ -342,7 +342,7 @@
         , reject_reason as rejectReason, reject_username as rejectUsername, reject_userid as rejectUserid, degree_id as degree_id,report_extra_degree.name as degreeName,task_group.name as groupName,a.group_id as groupId, a.custom_data as customData
         ,u.name as projectAuditorName,u.corpwx_userid as projectAuditorCorpwxUserId, a.project_auditor_id as projectAuditorId, department.department_name as departmentName,dp2.department_name as buDepartmentName,department.department_id as departmentId, a.overtime_hours as overtimeHours, a.custom_text as customText, a.project_audit_time as projectAuditTime,project_main.name as projectMainName
         ,a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3, a.batch_id as batchId,a.sap_service_id as sapServiceId,b.status as projectStatus,DATE_FORMAT(b.finish_date,'%Y-%m-%d') as finishDate,ps.project_category_sub as projectCategorySub
-        ,u2.name as projectManagerName,u2.corpwx_userid as projectManagerCorpwxUserId, multi_degr_id as multiDegrId
+        ,u2.name as projectManagerName,u2.corpwx_userid as projectManagerCorpwxUserId, multi_degr_id as multiDegrId,b.current_stage_name as stageName
         FROM report AS a
         JOIN project AS b ON a.project_id=b.id
         LEFT JOIN project_separate AS ps on b.id=ps.id
@@ -966,14 +966,16 @@
         )
     </select>
     <select id="getMyOvertime"  resultType="java.lang.Double">
-        select IFNULL(sum(overtime_hours),0) from report where creator_id=#{userId}
+        SELECT IFNULL(SUM(overtime_hours),0) FROM report
+        LEFT JOIN report_write_off rwo ON rwo.`report_id`=report.id
+        WHERE report.creator_id=#{userId} AND (rwo.`write_off` IS NULL OR rwo.`write_off`=0)
         <if test="startDate != null">
             and create_date &gt;= #{startDate}
         </if>
     </select>
     <select id="getProWaitingApproveCnt" 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 = project_auditor_id
+        left join `user` on `user`.id = project_auditor_id
         where state = 0 and project_audit_state = 0 and is_dept_audit = 0
           and report.company_id = #{companyId}
           and `user`.is_active=1
@@ -1287,4 +1289,53 @@
         GROUP BY r.create_date,r.creator_id
         order by u.id,r.create_date
     </select>
+
+    <select id="getReportListWithTransfer" resultType="java.util.Map">
+        SELECT r.id AS reportId,u.`job_number` AS jobNumber,u.name AS userName,d.`department_name` AS deptName,
+        p.`project_code` AS projectCode,p.`project_name` AS projectName,date_format(r.`create_date`,'%Y-%m-%d') AS createDate,r.`working_time` AS workingTime,
+        tg.`name` AS groupName,r.`stage` AS stageName FROM report r
+        LEFT JOIN `user` u ON r.`creator_id`=u.`id`
+        LEFT JOIN project p ON r.`project_id`=p.`id`
+        LEFT JOIN task_group tg ON tg.`id`=r.`group_id`
+        LEFT JOIN department d ON d.`department_id`=u.`department_id`
+        WHERE r.company_id=#{companyId}
+        <if test="startDate!=null and startDate!='' and endDate!=null and endDate!=''">
+            AND r.create_date BETWEEN #{startDate} AND #{endDate}
+        </if>
+        <if test="list!=null and list.size()>0">
+            AND r.creator_id in
+            <foreach collection="list" separator="," open="(" close=")" item="item">
+                #{item}
+            </foreach>
+        </if>
+        <if test="projectId!=null">
+            AND p.id=#{projectId}
+        </if>
+        <if test="start!=null and size!=null">
+            limit #{start},#{size}
+        </if>
+    </select>
+
+    <select id="getReportListWithTransferCount" resultType="java.lang.Integer">
+        select count(1) from (
+        SELECT r.id AS reportId FROM report r
+        LEFT JOIN `user` u ON r.`creator_id`=u.`id`
+        LEFT JOIN project p ON r.`project_id`=p.`id`
+        LEFT JOIN task_group tg ON tg.`id`=r.`group_id`
+        LEFT JOIN department d ON d.`department_id`=u.`department_id`
+        WHERE r.company_id=#{companyId}
+        <if test="startDate!=null and startDate!='' and endDate!=null and endDate!=''">
+            AND r.create_date BETWEEN #{startDate} AND #{endDate}
+        </if>
+        <if test="list!=null and list.size()>0">
+            AND r.creator_id in
+            <foreach collection="list" separator="," open="(" close=")" item="item">
+                #{item}
+            </foreach>
+        </if>
+        <if test="projectId!=null">
+            AND p.id=#{projectId}
+        </if>
+        ) as total
+    </select>
 </mapper>

+ 20 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportWriteOffMapper.xml

@@ -0,0 +1,20 @@
+<?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.ReportWriteOffMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.management.platform.entity.ReportWriteOff">
+        <id column="report_id" property="reportId" />
+        <result column="write_off" property="writeOff" />
+        <result column="creator_id" property="creatorId" />
+        <result column="creator_name" property="creatorName" />
+        <result column="create_time" property="createTime" />
+        <result column="reason" property="reason" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        report_id, write_off, creator_id, creator_name, create_time, reason
+    </sql>
+
+</mapper>

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

@@ -1601,18 +1601,18 @@ public class ReportController {
      * date 日期 格式yyyy-mm-dd
      */
     @RequestMapping("/exportReport")
-    public HttpRespMsg exportReport(String startDate, String endDate, Integer planId,@RequestParam(defaultValue = "0") Integer stateKey,Integer departmentId) {
+    public HttpRespMsg exportReport(String startDate, String endDate, Integer planId,@RequestParam(defaultValue = "0") Integer stateKey,String deptIds) {
         //startDate和endDate间隔不得超过1年
         DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
         LocalDate start = LocalDate.parse(startDate, dateTimeFormatter);
         LocalDate end = LocalDate.parse(endDate, dateTimeFormatter);
-        if (start.until(end, ChronoUnit.DAYS) > 365) {
-            HttpRespMsg httpRespMsg = new HttpRespMsg();
-            httpRespMsg.setError("导出日报时间间隔不得超过1年");
-            return httpRespMsg;
-        }
+//        if (start.until(end, ChronoUnit.DAYS) > 365) {
+//            HttpRespMsg httpRespMsg = new HttpRespMsg();
+//            httpRespMsg.setError("导出日报时间间隔不得超过1年");
+//            return httpRespMsg;
+//        }
 
-        return reportService.exportReport(startDate, endDate, planId,stateKey,departmentId, request);
+        return reportService.exportReport(startDate, endDate, planId,stateKey,deptIds, request);
     }
     /**
      * 删除报告

+ 29 - 14
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/controller/WxCorpInfoController.java

@@ -109,11 +109,11 @@ public class WxCorpInfoController {
         JSONArray jsonArrayFilter = new JSONArray();
         JSONObject filter1 = new JSONObject();
         filter1.put("key","record_type");
-        filter1.put("value",1);
+        filter1.put("value","1");
         jsonArrayFilter.add(filter1);
         JSONObject filter2 = new JSONObject();
         filter2.put("key","sp_status");
-        filter2.put("value",2);
+        filter2.put("value","2");
         jsonArrayFilter.add(filter2);
         List<String> approvalInfo = wxCorpInfoService.getApprovalInfo(7, startDate, endDate, "", jsonArrayFilter);
         List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId,7));
@@ -126,6 +126,11 @@ public class WxCorpInfoController {
                 JSONObject info = approvalInfoDetail.getJSONObject("info");
                 JSONObject applyer = info.getJSONObject("applyer");
                 String userid = applyer.getString("userid");
+                //过滤审核状态只需要审核通过的数据
+                int sp_status = info.getIntValue("sp_status");
+                if(sp_status!=2){
+                    continue;
+                }
                 Optional<User> first = userList.stream().filter(u ->u.getCorpwxRealUserid()!=null&&u.getCorpwxRealUserid().equals(userid)).findFirst();
                 if(!first.isPresent()){
                     continue;
@@ -219,7 +224,7 @@ public class WxCorpInfoController {
         jsonArrayFilter.add(filter1);
         JSONObject filter2 = new JSONObject();
         filter2.put("key","sp_status");
-        filter2.put("value",2);
+        filter2.put("value","2");
         jsonArrayFilter.add(filter2);
         List<String> approvalInfo = wxCorpInfoService.getApprovalInfo(7, startDate, endDate, "", jsonArrayFilter);
         List<Department> departmentList = departmentService.list(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, 7));
@@ -233,6 +238,11 @@ public class WxCorpInfoController {
                 JSONObject info = approvalInfoDetail.getJSONObject("info");
                 JSONObject applyer = info.getJSONObject("applyer");
                 String userid = applyer.getString("userid");
+                //过滤审核状态只需要审核通过的数据
+                int sp_status = info.getIntValue("sp_status");
+                if(sp_status!=2){
+                    continue;
+                }
                 Optional<User> first = userList.stream().filter(u ->u.getCorpwxRealUserid()!=null&&u.getCorpwxRealUserid().equals(userid)).findFirst();
                 if(!first.isPresent()){
                     continue;
@@ -246,6 +256,7 @@ public class WxCorpInfoController {
                 plan.setCreateTime(LocalDateTime.now());
                 plan.setPlanType(1);
                 plan.setCreateId(first.get().getId());
+                plan.setTaskChangeNoticeNum(info.getString("sp_no"));
                 //参与人员列表
                 List<String> userTeams=new ArrayList<>();
                 //初始化 单价(元/小时)
@@ -296,12 +307,12 @@ public class WxCorpInfoController {
                             plan.setTaskName(text);
                         }
                     }
-                    if(title.getJSONObject(0).getString("text").equals("审批编号")){
-                        if(control.equals("Text")||control.equals("Textarea")){
-                            String text = value.getString("text");
-                            plan.setTaskChangeNoticeNum(text);
-                        }
-                    }
+//                    if(title.getJSONObject(0).getString("text").equals("审批编号")){
+//                        if(control.equals("Text")||control.equals("Textarea")){
+//                            String text = value.getString("text");
+//                            plan.setTaskChangeNoticeNum(text);
+//                        }
+//                    }
                     //先处理多个人员 公用此单据非工时部分内容
                     if(title.getJSONObject(0).getString("text").equals("参与人员")){
                         if(control.equals("Contact")){
@@ -366,16 +377,20 @@ public class WxCorpInfoController {
                     }
                     if(title.getJSONObject(0).getString("text").contains("单价")){
                         if(control.equals("Number")){
-                            Double new_money = value.getDouble("new_number");
-                            plan.setMoneyOfJob(new BigDecimal(new_money));
-                            price=new BigDecimal(new_money);
+                            if(!value.getString("new_number").equals("")){
+                                Double new_money = value.getDouble("new_number");
+                                plan.setMoneyOfJob(new BigDecimal(new_money==null?0:new_money));
+                                price=new BigDecimal(new_money);
+                            }
                         }
                     }
                     if(title.getJSONObject(0).getString("text").contains("结算总额")){
                         if(control.equals("Formula")){
                             JSONObject formula = value.getJSONObject("formula");
-                            double formulaDoubleValue = formula.getDoubleValue("value");
-                            plan.setMoneyOfJob(new BigDecimal(formulaDoubleValue));
+                            if(!formula.getString("value").equals("")){
+                                double formulaDoubleValue = formula.getDoubleValue("value");
+                                plan.setMoneyOfJob(new BigDecimal(formulaDoubleValue));
+                            }
                         }
                     }
                     if(title.getJSONObject(0).getString("text").equals("备注")){

+ 5 - 0
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/mapper/PlanMapper.java

@@ -1,7 +1,10 @@
 package com.management.platform.mapper;
 
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.management.platform.entity.Plan;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Update;
+import org.springframework.test.context.jdbc.Sql;
 
 /**
  * <p>
@@ -13,4 +16,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  */
 public interface PlanMapper extends BaseMapper<Plan> {
 
+    @Update("update plan set real_end_date = null,hide_state=0 where id = #{id}")
+    void setToNormalState(Integer id);
 }

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

@@ -204,7 +204,7 @@ public interface ReportMapper extends BaseMapper<Report> {
 
     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);
+    List<Map<String,Object>> getReportList(String startDate, String endDate, Integer planId, Integer stateKey,@Param("list") List<Integer> deptIdList, Integer companyId);
 
     List<Map<String,Object>> getPlanDataWithStation(Integer companyId, String startDate, String endDate, String foremanId, Integer pageStart, Integer pageSize);
 
@@ -223,4 +223,8 @@ public interface ReportMapper extends BaseMapper<Report> {
     List<Map<String, Object>> findFinishNumErrorData();
 
     List<Map<String, Object>> getPersonWorkHoursWagesDetailForTemp(String date, String userId, Integer companyId, String startDate, String endDate);
+
+    List<Map<String, Object>> getPersonWorkHoursWagesWithNotReport(String date, String userId, Integer companyId, String startDate, String endDate,Integer checkStatus,Integer detailStatus);
+
+    List<Map<String, Object>> getPersonWorkHoursWagesWithHasReport(String date, String userId, Integer companyId, String startDate, String endDate,Integer checkStatus,Integer detailStatus);
 }

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

@@ -139,7 +139,7 @@ public interface ReportService extends IService<Report> {
 
     HttpRespMsg exportDpetStatisticsProgressList(String deptIds, String userId, String startDate, String endDate);
 
-    HttpRespMsg exportReport(String startDate, String endDate, Integer planId, Integer stateKey, Integer departmentId, HttpServletRequest request);
+    HttpRespMsg exportReport(String startDate, String endDate, Integer planId, Integer stateKey, String deptIds, HttpServletRequest request);
 
     HttpRespMsg deleteReport(String id);
 

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

@@ -628,7 +628,7 @@ public class PlanServiceImpl extends ServiceImpl<PlanMapper, Plan> implements Pl
                     if (describtionCell != null) describtionCell.setCellType(CellType.STRING);
                     plan.setStartDate(planType==0?LocalDate.now():LocalDate.now().plusDays(1));
                     if(productSchedulingNumCell!=null){
-                        Plan one = getOne(new QueryWrapper<Plan>().eq("product_scheduling_num", productSchedulingNumCell.getStringCellValue()));
+                        Plan one = getOne(new QueryWrapper<Plan>().eq("product_scheduling_num", productSchedulingNumCell.getStringCellValue()).eq("product_name",productOrderNumCell.getStringCellValue()));
                         if(one!=null){
                             plan.setId(one.getId());
                         }
@@ -1127,7 +1127,12 @@ public class PlanServiceImpl extends ServiceImpl<PlanMapper, Plan> implements Pl
             return msg;
         }
         List<String> idList=new ArrayList<>(Arrays.asList(ids.split(",")));
-        List<ProdProcedureTeam> prodProcedureTeams = prodProcedureTeamService.list(new QueryWrapper<ProdProcedureTeam>().in("plan_procedure_id", idList));
+        List<ProdProcedureTeam> prodProcedureTeams = prodProcedureTeamService.list(new QueryWrapper<ProdProcedureTeam>().in("id", idList));
+        List<Report> reports = reportMapper.selectList(new LambdaQueryWrapper<Report>().in(Report::getUserProcedureTeamId, idList));
+        if(reports.size()>0){
+            msg.setError("存在以报工计划,请重新选择");
+            return msg;
+        }
         if(prodProcedureTeams.size()>0){
             List<ProdProcedureTeam> procedureTeams = prodProcedureTeams.stream().filter(ps -> ps.getUserId().equals(userId)).collect(Collectors.toList());
             if(procedureTeams.size()>0){
@@ -1146,7 +1151,7 @@ public class PlanServiceImpl extends ServiceImpl<PlanMapper, Plan> implements Pl
     public HttpRespMsg cancellationReceive(Integer id) {
         HttpRespMsg msg=new HttpRespMsg();
         String userId = request.getHeader("token");
-        List<ProdProcedureTeam> prodProcedureTeams = prodProcedureTeamService.list(new QueryWrapper<ProdProcedureTeam>().eq("plan_procedure_id", id));
+        List<ProdProcedureTeam> prodProcedureTeams = prodProcedureTeamService.list(new QueryWrapper<ProdProcedureTeam>().eq("id", id));
         if(prodProcedureTeams.size()>0){
             Optional<ProdProcedureTeam> first = prodProcedureTeams.stream().filter(ps -> ps.getUserId().equals(userId)).findFirst();
             if(first.isPresent()){
@@ -1385,7 +1390,7 @@ public class PlanServiceImpl extends ServiceImpl<PlanMapper, Plan> implements Pl
                                 }
                             });
                             ps.setProdProcedureTeamList(procedureTeamList);
-                            if(procedureTeamList.stream().anyMatch(pl->pl.getStatus()==0&&pl.getUserId().equals(userId))){
+                            if(procedureTeamList.stream().anyMatch(pl->pl.getUserId()!=null&&pl.getStatus()==0&&pl.getUserId().equals(userId))){
                                 ps.setCanReceive(true);
                             }
                             if(!StringUtils.isEmpty(ps.getTeamIds())){
@@ -1402,7 +1407,7 @@ public class PlanServiceImpl extends ServiceImpl<PlanMapper, Plan> implements Pl
                             if(procedureTeamList.stream().anyMatch(pl->pl.getProgress()>0&&pl.getStatus()==4)){
                                 ps.setNeedAddCircle(true);
                             }
-                            if(procedureTeamList.stream().anyMatch(pl->pl.getUserId().equals(userId)&&pl.getStatus()==1)){
+                            if(procedureTeamList.stream().anyMatch(pl->pl.getUserId()!=null&&pl.getUserId().equals(userId)&&pl.getStatus()==1)){
                                 ps.setCancellationReceive(true);
                             }
                         }

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

@@ -137,6 +137,12 @@ public class ProdProcedureServiceImpl extends ServiceImpl<ProdProcedureMapper, P
                                     BigDecimal totalWorkingHours=new BigDecimal(String.valueOf(first.get().getWorkingTime()));
                                     totalWorkingHours=totalWorkingHours.multiply(new BigDecimal(plan.get().getNum()));
                                     planProcedureTotal.setTotalWorkingHours(totalWorkingHours.doubleValue());
+                                    if(planProcedureTotal.getTotalProgress()!=0){
+                                        BigDecimal decimal = new BigDecimal(planProcedureTotal.getTotalProgress());
+                                        decimal = decimal.divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
+                                        BigDecimal multiply = decimal.multiply(new BigDecimal(planProcedureTotal.getTotalWorkingHours()));
+                                        planProcedureTotal.setTotalFillTime(multiply.doubleValue());
+                                    }
                                     //todo:找到用到当前工序的prod_procedure_team (计划分配表) 更新 单价相关数据
                                     List<ProdProcedureTeam> prodProcedureTeams =allProdProcedureTeams.stream().filter(a->a.getPlanProcedureId().equals(planProcedureTotal.getId())).collect(Collectors.toList());
                                     prodProcedureTeams = prodProcedureTeams.stream().sorted(Comparator.comparing(ProdProcedureTeam::getId)).collect(Collectors.toList());

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

@@ -4297,10 +4297,10 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             double tempWorkTime = mapList.stream().filter(mt -> mt.get("tempWorkTime") != null).mapToDouble(mt -> Double.valueOf(String.valueOf(mt.get("tempWorkTime")))).sum();
             BigDecimal tempBigDecimal = new BigDecimal(tempWorkTime);
             double tempCost = mapList.stream().filter(mt -> mt.get("tempCost") != null).mapToDouble(mt -> Double.valueOf(String.valueOf(mt.get("tempCost")))).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) + "元");
-            u.setTotalTempResult(String.valueOf(tempBigDecimal.doubleValue()) + "分钟 " + String.format("%.2f", tempCost) + "元");
+            u.setTotalResult(String.format("%.2f",bigDecimal.doubleValue()) + "分钟 " + String.format("%.2f", cost) + "元");
+            u.setTotalPlanResult(String.format("%.2f",planBigDecimal.doubleValue()) + "分钟 " + String.format("%.2f", planCost) + "元");
+            u.setTotalSurplusResult(String.format("%.2f",surplusBigDecimal.doubleValue()) + "分钟 " + String.format("%.2f", surplusCost) + "元");
+            u.setTotalTempResult(String.format("%.2f",tempBigDecimal.doubleValue()) + "小时 " + String.format("%.2f", tempCost) + "元");
         }
         resultMap.put("total",userIPage.getTotal());
         resultMap.put("records",userList);
@@ -4352,12 +4352,28 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         deptIds.addAll(otherDeptIds);
         //日期范围内所有请假数据
         List<LeaveSheet> leaveSheetList = leaveSheetService.list(new LambdaQueryWrapper<LeaveSheet>().le(LeaveSheet::getStartDate, endDate).ge(LeaveSheet::getEndDate, startDate).eq(LeaveSheet::getOwnerId,userId));
-        List<Map<String,Object>> mapList=reportMapper.getPersonWorkHoursWagesDetail(date,userId,user.getCompanyId(),startDate,endDate,null,null);
+        //获取未填报的分配数据
+        List<Map<String,Object>> mapListNoReport=reportMapper.getPersonWorkHoursWagesWithNotReport(date,userId,user.getCompanyId(),startDate,endDate,null,null);
+        mapListNoReport.forEach(m->{
+            m.put("colorType","black");
+        });
+        //获取已填报的分配数据
+        List<Map<String,Object>> mapListHasReport=reportMapper.getPersonWorkHoursWagesWithHasReport(date,userId,user.getCompanyId(),startDate,endDate,null,null);
+        mapListHasReport.forEach(m->{
+            m.put("colorType","blue");
+        });
+        //获取临时报工数据
+        List<Map<String,Object>> mapListTempReport=reportMapper.getPersonWorkHoursWagesDetailForTemp(date,userId,user.getCompanyId(),startDate,endDate);
+        mapListTempReport.forEach(m->{
+            m.put("colorType","green");
+        });
+        mapListHasReport.addAll(mapListTempReport);
+        mapListHasReport.addAll(mapListNoReport);
         HttpRespMsg httpRespMsg=new HttpRespMsg();
         HashMap map=new HashMap();
-        map.put("record",mapList);
-        map.put("totalWorkingTime",mapList.stream().filter(i->i.get("working_time")!=null).mapToDouble(mt->Double.valueOf(String.valueOf(mt.get("working_time")))).sum());
-        map.put("totalCost",mapList.stream().filter(i->i.get("cost")!=null).mapToDouble(mt->Double.valueOf(String.valueOf(mt.get("cost")))).sum());
+        map.put("record",mapListHasReport);
+//        map.put("totalWorkingTime",mapList.stream().filter(i->i.get("working_time")!=null).mapToDouble(mt->Double.valueOf(String.valueOf(mt.get("working_time")))).sum());
+//        map.put("totalCost",mapList.stream().filter(i->i.get("cost")!=null).mapToDouble(mt->Double.valueOf(String.valueOf(mt.get("cost")))).sum());
         httpRespMsg.setData(map);
         return httpRespMsg;
     }
@@ -4857,6 +4873,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         titleList.add("工长");
         titleList.add("计划件数");
         titleList.add("产品名称");
+        titleList.add("项目名称");
         titleList.add("开始日期");
         titleList.add("完工日期");
         titleList.add("工位");
@@ -4870,6 +4887,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             itemMap.add(String.valueOf(map.get("userName")==null?"":map.get("userName")));
             itemMap.add(String.valueOf(map.get("planNum")==null?"":map.get("planNum")));
             itemMap.add(String.valueOf(map.get("productName")==null?"":map.get("productName")));
+            itemMap.add(String.valueOf(map.get("projectName")==null?"":map.get("projectName")));
             itemMap.add(String.valueOf(map.get("startDate")==null?"":map.get("startDate")));
             itemMap.add(String.valueOf(map.get("endDate")==null?"":map.get("endDate")));
             itemMap.add(String.valueOf(map.get("statinoName")==null?"":map.get("statinoName")));
@@ -4961,11 +4979,20 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     }
 
     @Override
-    public HttpRespMsg exportReport(String startDate, String endDate, Integer planId, Integer stateKey, Integer departmentId, HttpServletRequest request) {
+    public HttpRespMsg exportReport(String startDate, String endDate, Integer planId, Integer stateKey, String deptIds, HttpServletRequest request) {
         HttpRespMsg msg=new HttpRespMsg();
         Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
         List<Department> departmentList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, companyId));
-        List<Map<String,Object>> reportList=reportMapper.getReportList(startDate,endDate,planId,stateKey,departmentId,companyId);
+        List<Integer> departmentIdList=new ArrayList<>();
+        if(!StringUtils.isEmpty(deptIds)){
+            List<Integer> list = Arrays.asList(deptIds.split(",")).stream().map(i -> Integer.valueOf(i)).collect(Collectors.toList());
+            departmentIdList.addAll(list);
+            for (Integer integer : list) {
+                List<Integer> branchDepartment = getBranchDepartment(integer, departmentList);
+                departmentIdList.addAll(branchDepartment);
+            }
+        }
+        List<Map<String,Object>> reportList=reportMapper.getReportList(startDate,endDate,planId,stateKey,departmentIdList,companyId);
         List<List<String>> dataList=new ArrayList<>();
 //        String[] title={"员工","工号","所属部门","排产工单号/任务变更通知号","钢印号","工作时长","产品名称","工序名称","进度","质检类型","质检人","工作日期","填报日期"};
 //        String[] title={"所属部门","工号","员工","排产工单号/任务变更通知号","钢印号","产品名称","工序名称","进度","工作件数", "工作时长","单价","工价","汇总",
@@ -4994,21 +5021,28 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
 //            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(map.get("productSchedulingNum")==null?"":String.valueOf(map.get("productSchedulingNum")));
             if(planType==0){
-                item.add(map.get("productSchedulingNum")==null?"":String.valueOf(map.get("productSchedulingNum")));
+                item.add(map.get("productOrderNum")==null?"":String.valueOf(map.get("productOrderNum")));
             }else {
                 item.add(map.get("taskChangeNoticeNum")==null?"":String.valueOf(map.get("taskChangeNoticeNum")));
             }
-            item.add(map.get("productOrderNum")==null?"":String.valueOf(map.get("productOrderNum")));
-            item.add(String.valueOf(map.get("procedureName")));
+            if(planType==0){
+                item.add(map.get("procedureName")==null?"":String.valueOf(map.get("procedureName")));
+            }else {
+                item.add("临时报工");
+            }
             item.add(map.get("steelNumArray")==null?"":String.valueOf(map.get("steelNumArray")));
-            item.add("");
+            item.add(map.get("productName")==null?"":String.valueOf(map.get("productName")));
             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"));
+            BigDecimal finishNum = new BigDecimal(map.get("finishNum")==null?String.valueOf(0):String.valueOf(map.get("finishNum")));
+            finishNum=finishNum.multiply(new BigDecimal(map.get("unitPrice")==null?String.valueOf(0):String.valueOf(map.get("unitPrice")))).setScale(2,RoundingMode.HALF_UP);
+            item.add(String.valueOf(finishNum.doubleValue()));
 //            item.add(cost);
             item.add(String.valueOf(map.get("userName")));
             item.add(String.valueOf(map.get("createDate")));
@@ -5016,20 +5050,20 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
 //            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)) {
-                //换新的人了
-                sumLine = item;
-                sumLine.add(sumCostIndex, cost);
-                lastJobNum = curJobBNum;
-            } else {
-                //当前这行的该列设置为空
-                item.add(sumCostIndex, "");
-                //更新第一行的数据
-                BigDecimal sumCost = new BigDecimal(sumLine.get(sumCostIndex));
-                sumCost = sumCost.add(new BigDecimal(cost));
-                sumLine.remove(sumCostIndex);
-                sumLine.add(sumCostIndex, sumCost.toString());
-            }
+//            if (lastJobNum == null || !lastJobNum.equals(curJobBNum)) {
+//                //换新的人了
+//                sumLine = item;
+//                sumLine.add(sumCostIndex, cost);
+//                lastJobNum = curJobBNum;
+//            } else {
+//                //当前这行的该列设置为空
+//                item.add(sumCostIndex, "");
+//                //更新第一行的数据
+//                BigDecimal sumCost = new BigDecimal(sumLine.get(sumCostIndex));
+//                sumCost = sumCost.add(new BigDecimal(cost));
+//                sumLine.remove(sumCostIndex);
+//                sumLine.add(sumCostIndex, sumCost.toString());
+//            }
         }
         Company company = companyMapper.selectById(companyId);
         String fileName=("日报统计导出_")+company.getCompanyName()+System.currentTimeMillis();
@@ -5076,6 +5110,12 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
 //            planProcedureTotal.setTotalProgress((int)((workingTime / planProcedureTotal.getTotalWorkingHours()) * 100));
             System.out.println("planProcedureTotal.getId()=="+planProcedureTotal.getId()+"--进度 2 workingTime:"+workingTime+" totalWorkingHours:"+planProcedureTotal.getTotalWorkingHours()+" totalProgress:"+planProcedureTotal.getTotalProgress());
             planProcedureTotalMapper.updateById(planProcedureTotal);
+
+            //如果之前是完成状态,要撤销完成状态
+            Plan plan = planMapper.selectById(report.getPlanId());
+            if (plan.getHideState() == 1) {
+                planMapper.setToNormalState(report.getPlanId());
+            }
             return new HttpRespMsg();
         }
     }

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

@@ -2031,6 +2031,7 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
         requestMap.put("new_cursor",newCursor);
         requestMap.put("size",100);
         requestMap.put("filters",filterArray);
+        System.out.println("Print Request:"+requestMap);
         HttpEntity<JSONObject> entity = new HttpEntity<>(requestMap, headers);
         ResponseEntity<String> ResponseEntity = restTemplate.postForEntity(url, entity, String.class);
         if (ResponseEntity.getStatusCode() == HttpStatus.OK) {

+ 23 - 8
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/task/TimingTask.java

@@ -242,11 +242,11 @@ public class TimingTask {
         JSONArray jsonArrayFilter = new JSONArray();
         JSONObject filter1 = new JSONObject();
         filter1.put("key","record_type");
-        filter1.put("value",1);
+        filter1.put("value","1");
         jsonArrayFilter.add(filter1);
         JSONObject filter2 = new JSONObject();
         filter2.put("key","sp_status");
-        filter2.put("value",2);
+        filter2.put("value","2");
         for (WxCorpInfo wxCorpInfo : list) {
             List<String> approvalInfo = wxCorpInfoService.getApprovalInfo(wxCorpInfo.getCompanyId(), df.format(start), df.format(end), "", jsonArrayFilter);
             List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, wxCorpInfo.getCompanyId()));
@@ -259,6 +259,11 @@ public class TimingTask {
                     JSONObject info = approvalInfoDetail.getJSONObject("info");
                     JSONObject applyer = info.getJSONObject("applyer");
                     String userid = applyer.getString("userid");
+                    //过滤审核状态只需要审核通过的数据
+                    int sp_status = info.getIntValue("sp_status");
+                    if(sp_status!=2){
+                        continue;
+                    }
                     Optional<User> first = userList.stream().filter(u ->u.getCorpwxRealUserid()!=null&& u.getCorpwxRealUserid().equals(userid)).findFirst();
                     if(!first.isPresent()){
                         continue;
@@ -361,7 +366,7 @@ public class TimingTask {
         jsonArrayFilter.add(filter1);
         JSONObject filter2 = new JSONObject();
         filter2.put("key","sp_status");
-        filter2.put("value",2);
+        filter2.put("value","2");
         jsonArrayFilter.add(filter2);
         List<String> approvalInfo = wxCorpInfoService.getApprovalInfo(7, df.format(start), df.format(end), "", jsonArrayFilter);
         List<Department> departmentList = departmentService.list(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, 7));
@@ -375,6 +380,11 @@ public class TimingTask {
                 JSONObject info = approvalInfoDetail.getJSONObject("info");
                 JSONObject applyer = info.getJSONObject("applyer");
                 String userid = applyer.getString("userid");
+                //过滤审核状态只需要审核通过的数据
+                int sp_status = info.getIntValue("sp_status");
+                if(sp_status!=2){
+                    continue;
+                }
                 Optional<User> first = userList.stream().filter(u ->u.getCorpwxRealUserid()!=null&&u.getCorpwxRealUserid().equals(userid)).findFirst();
                 if(!first.isPresent()){
                     continue;
@@ -388,6 +398,7 @@ public class TimingTask {
                 plan.setCreateTime(LocalDateTime.now());
                 plan.setPlanType(1);
                 plan.setCreateId(first.get().getId());
+                plan.setTaskChangeNoticeNum(info.getString("sp_no"));
                 //参与人员列表
                 List<String> userTeams=new ArrayList<>();
                 //初始化 单价(元/小时)
@@ -507,16 +518,20 @@ public class TimingTask {
                     }
                     if(title.getJSONObject(0).getString("text").contains("单价")){
                         if(control.equals("Number")){
-                            Double new_money = value.getDouble("new_number");
-                            plan.setMoneyOfJob(new BigDecimal(new_money));
-                            price=new BigDecimal(new_money);
+                            if(!value.getString("new_number").equals("")){
+                                Double new_money = value.getDouble("new_number");
+                                plan.setMoneyOfJob(new BigDecimal(new_money==null?0:new_money));
+                                price=new BigDecimal(new_money);
+                            }
                         }
                     }
                     if(title.getJSONObject(0).getString("text").contains("结算总额")){
                         if(control.equals("Formula")){
                             JSONObject formula = value.getJSONObject("formula");
-                            double formulaDoubleValue = formula.getDoubleValue("value");
-                            plan.setMoneyOfJob(new BigDecimal(formulaDoubleValue));
+                            if(!formula.getString("value").equals("")){
+                                double formulaDoubleValue = formula.getDoubleValue("value");
+                                plan.setMoneyOfJob(new BigDecimal(formulaDoubleValue));
+                            }
                         }
                     }
                     if(title.getJSONObject(0).getString("text").equals("备注")){

+ 69 - 4
fhKeeper/formulahousekeeper/management-workshop/src/main/resources/mapper/ReportMapper.xml

@@ -193,7 +193,7 @@
     <select id="getPersonWorkHoursWagesDetailForTemp" resultType="java.util.Map">
         select r.cost,r.working_time,r.finish_num, r.creator_id,DATE_FORMAT(r.create_date,'%Y%m%d') as createDate,
         p.name as productName,DATE_FORMAT(plan.start_date,'%Y%m%d') as planStartDate,DATE_FORMAT(plan.end_date,'%Y%m%d') as planEndDate ,
-        plan.task_change_notice_num as taskChangeNoticeNum,plan.plan_type as planType,u.name as checkerName,u2.name as creatorName,plan.task_name as taskName
+        plan.task_change_notice_num as taskChangeNoticeNum,plan.plan_type as planType,u.name as checkerName,u2.name as creatorName,plan.task_name as taskName,plan.task_type_name
         from report r
         left join product p on p.id=r.product_id
         left join plan on plan.id=r.plan_id
@@ -243,6 +243,68 @@
         </if>
     </select>
 
+    <select id="getPersonWorkHoursWagesWithNotReport" resultType="java.util.Map">
+        select ppt.total_progress AS progress,pp.name AS procedureName,(CASE  WHEN pp.check_type=0 THEN '自检' WHEN pp.check_type=1 THEN '互检' ELSE '专检' END) AS checkType,
+        p.name AS productName,DATE_FORMAT(plan.start_date,'%Y%m%d') AS planStartDate,DATE_FORMAT(plan.end_date,'%Y%m%d') AS planEndDate ,
+        plan.task_change_notice_num AS taskName,plan.plan_type AS planType,plan.product_scheduling_num
+        FROM prod_procedure_team ppt2
+        LEFT JOIN plan_procedure_total ppt ON ppt.id=ppt2.plan_procedure_id
+        LEFT JOIN plan ON plan.id=ppt.plan_id
+        LEFT JOIN (SELECT SUM(working_time) AS sumReport,user_procedure_team_id,create_date FROM report GROUP BY user_procedure_team_id,create_date) AS r ON r.user_procedure_team_id=ppt2.id  AND r.create_date=ppt2.distribute_date
+        LEFT JOIN prod_procedure pp ON ppt.prod_procedure_id=pp.id
+        LEFT JOIN product p ON p.id=plan.product_id
+        WHERE ppt2.company_id=#{companyId}
+        AND r.sumReport &lt; ppt2.work_time
+        <if test="date!=null and date!=''">
+            and ppt2.distribute_date=#{date}
+        </if>
+        <if test="userId!=null and userId!=''">
+            <choose>
+                <when test="checkStatus!=null and checkStatus==1 and detailStatus==null">
+                    and plan.foreman_id=#{userId}
+                </when>
+                <otherwise>
+                    and ppt2.user_id=#{userId}
+                </otherwise>
+            </choose>
+        </if>
+        <if test="startDate!=null and endDate!=null">
+            and ppt2.distribute_date between #{startDate} and #{endDate}
+        </if>
+        GROUP BY ppt2.id
+    </select>
+
+    <select id="getPersonWorkHoursWagesWithHasReport" resultType="java.util.Map">
+        select r.cost,r.working_time,r.finish_num AS finish_num, r.creator_id,ppt.total_progress AS progress,DATE_FORMAT(r.create_date,'%Y%m%d') AS createDate,pp.name AS procedureName,(CASE  WHEN pp.check_type=0 THEN '自检' WHEN pp.check_type=1 THEN '互检' ELSE '专检' END) AS checkType,
+        p.name AS productName,DATE_FORMAT(plan.start_date,'%Y%m%d') AS planStartDate,DATE_FORMAT(plan.end_date,'%Y%m%d') AS planEndDate ,
+        plan.task_change_notice_num AS taskName,plan.plan_type AS planType,u.name AS checkerName,u2.name AS creatorName,plan.product_scheduling_num,r.finish_num AS finishNum
+        FROM prod_procedure_team ppt2
+        LEFT JOIN plan_procedure_total ppt ON ppt.id=ppt2.plan_procedure_id
+        LEFT JOIN plan ON plan.id=ppt.plan_id
+        LEFT JOIN report r ON r.user_procedure_team_id=ppt2.id AND r.finish_num>0
+        LEFT JOIN prod_procedure pp ON ppt.prod_procedure_id=pp.id
+        LEFT JOIN product p ON p.id=plan.product_id
+        LEFT JOIN `user` u ON r.checker_id=u.id
+        LEFT JOIN `user` u2 ON r.creator_id=u2.id
+        WHERE ppt2.company_id=#{companyId}
+        <if test="date!=null and date!=''">
+            and r.create_date=#{date}
+        </if>
+        <if test="userId!=null and userId!=''">
+            <choose>
+                <when test="checkStatus!=null and checkStatus==1 and detailStatus==null">
+                    and plan.foreman_id=#{userId}
+                </when>
+                <otherwise>
+                    and ppt2.user_id=#{userId}
+                </otherwise>
+            </choose>
+        </if>
+        <if test="startDate!=null and endDate!=null">
+            and r.create_date between #{startDate} and #{endDate}
+        </if>
+    </select>
+
     <select id="getProcedureRealTimeProgressList" resultType="java.util.Map">
         select a.id as pptId,b.id as planId,b.plan_type as planType,(Case when b.plan_type=0 then b.product_scheduling_num else b.task_change_notice_num end) as taskName,
         c.name as procedureName,a.total_working_hours as planWorkTime,a.total_fill_time as nowWorkTime,a.total_progress as progress
@@ -511,7 +573,7 @@
         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
+        date_format(r.create_date,'%Y-%m-%d') as createDate,date_format(r.create_time,'%Y-%m-%d %T') as reportTime,(CASE WHEN p.plan_type=0 THEN pp.unit_price ELSE p.money_of_job END) as unitPrice,r.cost  from report r
         left join plan p on p.id=r.plan_id
         left join department d on d.department_id=p.station_id
         left join user u on r.creator_id=u.id
@@ -521,8 +583,11 @@
         <if test="startDate!=null and startDate!='' and endDate!=null and endDate!=''">
             and r.create_date between  #{startDate} and #{endDate}
         </if>
-        <if test="departmentId!=null">
-            and p.station_id=#{departmentId}
+        <if test="list!=null and list.size()>0">
+            and p.station_id in
+            <foreach collection="list" open="(" close=")" item="item" separator=",">
+                #{item}
+            </foreach>
         </if>
         <if test="planId!=null">
             and r.plan_id=#{planId}

BIN
fhKeeper/formulahousekeeper/management-workshop/workshop_print.2024-06-24.log.gz


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

@@ -14,7 +14,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  || item.teamNames.indexOf(user.name) == -1"  v-model="item.prodProcedure.isSelected"  @click="itemChecked" shape="square">
+          <van-checkbox v-if="todayAndTomorrow" :disabled="item.checkboxDisabled  || (item.teamNames&&item.teamNames.indexOf(user.name) == -1)"  v-model="item.prodProcedure.isSelected"  @click="itemChecked" shape="square">
           </van-checkbox>
           <div class="PlanItem">
             <span>{{item.prodProcedure.seq}}. {{ item.prodProcedure.name }}</span>
@@ -153,7 +153,7 @@ export default {
         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].planProcedureId
+               return item.prodProcedureTeamList.filter(i=>i.userId==this.user.id)[0].id
             }else{
               return "-1"
             }
@@ -357,7 +357,7 @@ export default {
           for(var i in arr) {
             arr[i].checkboxDisabled = true
             if(arr[i].prodProcedureTeamList&&arr[i].prodProcedureTeamList.length > 0) {
-              let arrList = arr[i].prodProcedureTeamList.filter(item => item.status == 0 && item.userId==this.user.id)
+              let arrList = arr[i].prodProcedureTeamList.filter(item => (item.status == 0||item.status == 1) && item.userId==this.user.id)
               console.log(arrList, 'arrList')
               if(arrList.length > 0) {
                 arr[i].checkboxDisabled = false

+ 53 - 9
fhKeeper/formulahousekeeper/timesheet-workshop/src/views/statistic/index.vue

@@ -89,10 +89,12 @@
                 <el-table-column v-for="(item, index) in personWorkHoursWagesHead" :key="index" :label="item" align="center" min-width="150">
                     <template slot-scope="scope">
                         <div v-for="(items, indexs) in scope.row.personWorkHoursWages" :key="indexs" :class="`${scope.row.departmentCascade== '小计' ? '' : 'colorText'}`">
-                            <div v-if="items.crateDate == item">
+                            <div v-if="items.crateDate == item" @click.stop="showReportDetail(scope.row,item,0)">
                               <div  style="color: black;" v-if="items.planWorkTime">平均 {{items.planWorkTime}}分钟  {{items.planCost}}元</div>
-                              <div @click.stop="showReportDetail(scope.row,item,0)" v-if="items.workTime>0">已填 {{items.workTime}}分钟  {{items.cost}}元 </div>{{items.leave}}
-                              <div style="color: green;" @click.stop="showTempReportDetail(scope.row,item,0)" v-if="items.tempWorkTime>0||items.tempCost>0">临时报工 {{items.tempWorkTime}}分钟  {{items.tempCost}}元</div>
+                              <!-- <div @click.stop="showReportDetail(scope.row,item,0)" v-if="items.workTime>0">已填 {{items.workTime}}分钟  {{items.cost}}元 </div>{{items.leave}}
+                              <div style="color: green;" @click.stop="showTempReportDetail(scope.row,item,0)" v-if="items.tempWorkTime>0||items.tempCost>0">临时报工 {{items.tempWorkTime}}分钟  {{items.tempCost}}元</div> -->
+                              <div  v-if="items.workTime>0">已填 {{items.workTime}}分钟  {{items.cost}}元 </div>{{items.leave}}
+                              <div style="color: green;" v-if="items.tempWorkTime>0||items.tempCost>0">临时报工 {{items.tempWorkTime}}小时  {{items.tempCost}}元</div>
                               <div style="color: red;" v-if="items.surplusTime">剩余 {{items.surplusTime}}分钟  {{items.surplusCost}}元</div>
                             </div>
                         </div>
@@ -100,10 +102,14 @@
                 </el-table-column>
                 <el-table-column align="center" prop="totalResult" label="合计" min-width="180">
                    <template slot-scope="scope" >
-                    <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: green;"  @click="showTempReportDetail(scope.row,item,1)">临时报工 {{scope.row.totalTempResult}}</div> 
-                      <div style="color: red;">剩余 {{scope.row.totalSurplusResult}}</div>
+                    <div @click="showReportDetail(scope.row,item,1)">
+                      <div style="color: black;">{{scope.row.totalPlanResult | formatStr('平均') }}</div>
+                      <!-- <div style="color: #02a7f0;"  @click="showReportDetail(scope.row,item,1)"> {{scope.row.totalResult | formatStr('已填')}}</div> 
+                      <div style="color: green;"  @click="showTempReportDetail(scope.row,item,1)">{{scope.row.totalTempResult | formatStr('临时报工')}}</div>  -->
+                      <div style="color: #02a7f0;" > {{scope.row.totalResult | formatStr('已填')}}</div> 
+                      <div style="color: green;" >{{scope.row.totalTempResult | formatStr('临时报工')}}</div> 
+                      <div style="color: red;">{{scope.row.totalSurplusResult | formatStr('剩余') }}</div>
+                    </div>
                   </template>
                 </el-table-column>
             </el-table>
@@ -360,7 +366,10 @@
           <div>
             <el-table
               :data="personWorkHoursWagesDetail"
-              style="width: 100%">
+              style="width: 100%"
+              :row-class-name="tableRowClassName"
+              height="500"
+              >
               <el-table-column
                 prop="date"
                 label="计划(开始-结束日期)"
@@ -372,6 +381,8 @@
               <el-table-column prop="productName" label="产品名称" width="180"></el-table-column>
               <el-table-column prop="product_scheduling_num" label="排产工单号" width="180"></el-table-column>
               <el-table-column prop="procedureName" label="工序名称" width="180"></el-table-column>
+              <el-table-column prop="taskName" label="任务名称" width="250"></el-table-column>
+              <el-table-column prop="task_type_name" label="任务类型" width="180"></el-table-column>
               <el-table-column prop="finishNum" label="完成件数" width="80">
                 <template slot-scope="scope">
                   {{scope.row.finishNum?scope.row.finishNum:''}}
@@ -382,7 +393,7 @@
               <el-table-column prop="checkerName" label="质检人" width="180"></el-table-column>
               <el-table-column prop="working_time" label="工作时长" width="180">
                 <template slot-scope="scope" v-if="scope.row.working_time">
-                  {{scope.row.working_time}}分钟
+                  {{scope.row.working_time}}{{scope.row.planType==0?'分钟':'小时'}}
                 </template>
               </el-table-column>
             </el-table>
@@ -742,6 +753,13 @@ export default {
       personWorkHoursWorkTime(value) {
         let val = +((value ? value : 0) * 60).toFixed(2) + 0
         return val
+      },
+      formatStr(val, str) {
+        if(!val) {
+          return ''
+        }
+        let relut = val.replace(/\b0\.\d+\S*\s*/g, '')
+        return`${relut ? str : ''} ${relut}`
       }
   },
   methods: {
@@ -834,6 +852,17 @@ export default {
           });
       });
     },
+    //处理列类别
+    tableRowClassName({row}) {
+      if (row.colorType == "blue") {
+        return 'blue-row';
+      } else if (row.colorType == "black") {
+        return 'black-row';
+      }else if(row.colorType == "green"){
+        return 'green-row';
+      }
+      return '';
+    },
     getUserList(e) {
       let param={}
       if(e){
@@ -1583,6 +1612,8 @@ export default {
     }else{
       this.getUserList()
     }
+    this.page=1
+    this.size=20
     console.log(this.userId,'==============')
     this.getList(true)
     },
@@ -1847,3 +1878,16 @@ export default {
 }
 
 </style>
+<style>
+.el-table .blue-row {
+  color: #02a7f0;
+}
+
+.el-table .black-row {
+  color: black;
+}
+
+.el-table .green-row {
+  color: green;
+}
+</style>

+ 42 - 13
fhKeeper/formulahousekeeper/timesheet-workshop/src/views/workReport/daily.vue

@@ -669,11 +669,13 @@
                         <el-option v-for="item in allPlanList"  :key="item.id" :label="item.productName" :value="item.id"></el-option>
                     </el-select>
                 </el-form-item> -->
-                <el-form-item prop="departmentId" :label="'选择工位'" v-if="permissions.reportsCompany">
+                <el-form-item :label="'选择工位'" v-if="permissions.reportsCompany">
 
-                    <el-cascader v-if="user.userNameNeedTranslate != 1" v-model="exportParam.departmentId" :placeholder="$t('other.allDepartments')" :options="departmentList" :props="{ checkStrictly: true, value: 'id' }" clearable style="width: 350px;"></el-cascader>
-
-                    <vueCascader :size="'medium'" :widthStr="'350'" :clearable="true" :subject="departmentList" :radios="true" :distinction="'1'" @vueCasader="vueCasader" v-if="user.userNameNeedTranslate == 1" :selectNameChuan="$t('other.allDepartments')"></vueCascader>
+                    <!-- 部门筛选 -->
+                    <el-cascader  v-model="departmentIdArray" :options="departmentList" :placeholder="$t('qing-xuan-ze-bu-men')"
+                        :props="{ multiple: true, checkStrictly: true,expandTrigger: 'hover' }" collapse-tags :show-all-levels="false" clearable
+                        size="small" style="margin-bottom: 10px;width:180px"
+                    ></el-cascader>
 
                 </el-form-item>
                 <el-form-item prop="projectId" :label="$t('time.dateRange')">
@@ -1379,7 +1381,7 @@
         },
         data() {
             return {
-                
+                props:{ multiple: true },
                 checkTypeTxt:['自检','互检','专检'],
                 modItemDataId: null,
                 modImportTime: null,
@@ -1465,7 +1467,7 @@
                 weekDay : [this.$t('weekDay.sunday'), this.$t('weekDay.monday'), this.$t('weekDay.tuesday'), this.$t('weekDay.wednesday'), this.$t('weekDay.thursday'), this.$t('weekDay.friday'), this.$t('weekDay.saturday')],
                 statusStyle:["waiting", "filledReportStyle", "RejectStyle", "waitSubmitStyle"],
                 fillStatusList: [],
-                exportParam:{projectId: null, dateRange:[], departmentId: null},
+                exportParam:{projectId: null, dateRange:[], deptIds: null},
                 exportDialog:false,
                 timeFields:['timeType', 'workingTime', 'startTime', 'progress'],
                 subProjectList:[],
@@ -1653,6 +1655,7 @@
                 totalReportHours: 0, // 合计的工时
 
                 allPlanList: [], // 所有计划
+                departmentIdArray:[],
             };
         },
         watch: {
@@ -1697,7 +1700,7 @@
             this.exportParam.dateRange = [startStr,t];
             this.getAllDate(1);
             this.getReportList();
-            
+            this.getDepartmentList()
             // this.getFillProjectList();
             // this.getTimeType();
             this.getDepartment();
@@ -3856,7 +3859,25 @@
                         });
                 }
             },
-            
+            getDepartmentList() {
+            this.http.post( this.port.manage.depList, {},
+                res => {
+                if (res.code == "ok") {
+                    let dptlist = JSON.parse(JSON.stringify(res.data));
+                    this.departmentList = this.changeArr(dptlist);
+                } else {
+                    this.$message({
+                    message: res.msg,
+                    type: "error"
+                    });
+                }
+                },error => {
+                this.$message({
+                    message: error,
+                    type: "error"
+                });
+                });
+            },
             // 获取部门列表
             getDepartment() {
                 let day = (this.choseDay+1) > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
@@ -3871,7 +3892,7 @@
                             // })
                             return
                         }
-                        this.departmentList = JSON.parse(JSON.stringify(res.data))
+                        // this.departmentList = JSON.parse(JSON.stringify(res.data))
                         var list = res.data , list1 = JSON.parse(JSON.stringify(res.data));
                         // let noAllData = JSON.parse(JSON.stringify(res.data));
                         // if (this.user.role > 0) {
@@ -4311,20 +4332,28 @@
             //导出日报
             exportReport() {
                 this.listLoading = true;
+                var fName ='日报统计表_' + '.xlsx';
                 var param = {};
                 const { dateRange, departmentId } = this.exportParam
                 param.startDate = dateRange[0]
                 param.endDate = dateRange[1]
-                console.log(departmentId)
-                if(departmentId && departmentId.length > 0) {
-                    param.departmentId = departmentId[departmentId.length - 1]
+                let deptArr = []
+                for(var i in this.departmentIdArray){
+                let itemList = this.departmentIdArray[i] 
+                deptArr.push(itemList[itemList.length - 1])
                 }
+                param.deptIds = deptArr.join(',')
                 this.http.post('/report/exportReport', param,
                 res => {
                     this.listLoading = false;
                     if (res.code == "ok") {
-                        location.href = res.data;
+                        var filePath = res.data;
                         this.exportDialog = false;
+                        const a = document.createElement('a'); // 创建a标签
+                        a.setAttribute('download', fName);// download属性
+                        a.setAttribute('href', filePath);// href链接
+                        a.click(); //自执行点击事件
+                        a.remove();
                     } else {
                         this.$message({
                             message: res.msg,

+ 11 - 10
fhKeeper/formulahousekeeper/timesheet/.vscode/settings.json

@@ -1,11 +1,12 @@
 {
-    // Vue: i18n-ally 插件如下须要本身配置
-    "i18n-ally.localesPaths": ["src/i18n"], // 翻译的语言路径
-    "i18n-ally.enabledParsers": ["json", "js"], // 翻译支持的语言文件格式
-    "i18n-ally.encoding": "utf-8", // 翻译文件的编码
-    "i18n-ally.sourceLanguage": "zh", // 根据此 cn 语言文件翻译其他语言文件的 变量和内容
-    "i18n-ally.displayLanguage": "zh", // 组件中显示的语言
-    "i18n-ally.keystyle": "flat",
-    "vue-i18n.i18nPaths": "src\\i18n", // 翻译后变量的格式, flat(扁平式即对象属性路径变成一个长字符串), nested(嵌套式即对象属性变量可以进行相互之间的嵌套)
-    // 注意: 如果 i18n-ally 检测不出来框架, 或 提示错误, 可能是版本太高的缘故
-}
+  // Vue: i18n-ally 插件如下须要本身配置
+  "i18n-ally.localesPaths": ["src/i18n"], // 翻译的语言路径
+  "i18n-ally.enabledParsers": ["json", "js"], // 翻译支持的语言文件格式
+  "i18n-ally.encoding": "utf-8", // 翻译文件的编码
+  "i18n-ally.sourceLanguage": "zh", // 根据此 cn 语言文件翻译其他语言文件的 变量和内容
+  "i18n-ally.displayLanguage": "zh", // 组件中显示的语言
+  "i18n-ally.keystyle": "flat",
+  "i18n-ally.enabledFrameworks": ["vue"],
+  "vue-i18n.i18nPaths": "src\\i18n" // 翻译后变量的格式, flat(扁平式即对象属性路径变成一个长字符串), nested(嵌套式即对象属性变量可以进行相互之间的嵌套)
+  // 注意: 如果 i18n-ally 检测不出来框架, 或 提示错误, 可能是版本太高的缘故
+}

+ 1 - 0
fhKeeper/formulahousekeeper/timesheet/index.html

@@ -2,6 +2,7 @@
 <html>
   <head>
     <meta charset="utf-8" />
+    <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
     <!-- 尝试清除打包缓存 -->
     <!-- <meta http-equiv="pragram" content="no-cache">
         <meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate">

+ 5 - 0
fhKeeper/formulahousekeeper/timesheet/src/App.vue

@@ -94,4 +94,9 @@
         opacity: 0;
     }
 
+    .resetElEmtClass {
+        .el-dialog__body {
+            padding: 0 !important;
+        }
+    }
 </style>

+ 204 - 0
fhKeeper/formulahousekeeper/timesheet/src/components/departmentSelectionPersonnel.vue

@@ -0,0 +1,204 @@
+<template>
+    <el-dialog :title="$t('selectingParticipants')" :visible.sync="participantsVisible" :close-on-click-modal="false"
+        customClass="customWidth" width="500px" :before-close="changeVisable">
+        <div class="tree" style="height:400px">
+            <el-scrollbar style="height:100%">
+                <el-input v-if="user.userNameNeedTranslate != 1" :placeholder="$t('keywordfiltering')"
+                    v-model="participantsFilterText">
+                </el-input>
+
+                <div v-if="user.userNameNeedTranslate == '1'">
+                    <el-input :placeholder="$t('qingShuShuRuGuanJianZiGuoLv')" v-model.trim="participantsFilterText"
+                        class="input-with-select" @keyup.enter.native="echartDepartment()">
+                        <el-button slot="append" icon="el-icon-search" @click="echartDepartment()"></el-button>
+                    </el-input>
+                </div>
+
+                <el-tree :data="deptMembData" show-checkbox :props="defaultProps" node-key="id" ref="chooseMembTree2"
+                    @check-change="onTreeItemChange" :default-checked-keys="alreadyPartArray" highlight-current
+                    :filter-node-method="filterNode" v-loading="filterNodeFlag">
+                    <span class="custom-tree-node" slot-scope="{ node, data }">
+                        <span v-if="user.userNameNeedTranslate == '1'">
+                            <span v-if="node.data.children">
+                                <TranslationOpenDataText type='departmentName' :openid='node.label'>
+                                </TranslationOpenDataText>
+                            </span>
+                            <span v-else>
+                                <TranslationOpenDataText type='userName' :openid='node.label'></TranslationOpenDataText>
+                            </span>
+                        </span>
+                        <span v-if="user.userNameNeedTranslate != '1'">
+                            {{ node.label }}
+                        </span>
+                    </span>
+                </el-tree>
+            </el-scrollbar>
+        </div>
+        <div>{{ $t('btn.choose') }}&nbsp;{{ chosenMembCount }}&nbsp;{{ $t('other.people') }}</div>
+        <div slot="footer" class="dialog-footer">
+            <el-button @click="changeVisable()">{{ $t('btn.cancel') }}</el-button>
+            <el-button type="primary" @click="submitData()">{{ $t('btn.determine') }}</el-button>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+export default {
+    name: '',
+    components: {},
+    props: {
+        visible: {
+            type: Boolean,
+            default: false
+        }
+    },
+    data() {
+        return {
+            participantsFilterText: '',
+            participantsVisible: false,
+            filterNodePersonnel: [],
+            chosenMembCount: 0,
+            alreadyPartArray: [], // 已参与的人员
+            filterNodeFlag: false,
+            user: JSON.parse(sessionStorage.getItem("user")),
+            permissions: JSON.parse(sessionStorage.getItem("permissions")),
+            deptMembData: [
+                {
+                    id: 0,
+                    label: this.$t('lable.unassigned'),
+                }
+            ],
+            defaultProps: {
+                children: 'children',
+                label: 'label'
+            },
+        }
+    },
+    computed: {},
+    watch: {
+        visible(val) {
+            console.log('执行')
+            this.participantsVisible = val
+        },
+        participantsFilterText(val) {
+            let { userNameNeedTranslate } = JSON.parse(sessionStorage.getItem("user"))
+            if (userNameNeedTranslate != 1) {
+                this.$refs.chooseMembTree2.filter(val);
+            }
+            if (!val) {
+                this.$refs.chooseMembTree2.filter(val);
+            }
+        }
+    },
+    created() { },
+    mounted() {
+        this.getDepartmentList()
+    },
+    methods: {
+        submitData() {
+            let chosenList = this.$refs.chooseMembTree2.getCheckedNodes();
+            let chose2 = chosenList.filter(item => item.isUser == 1)
+            if((chose2 || []).length == 0) {
+                this.$message({
+                    message: this.$t('pleaseselectpersonnel'),
+                    type: "error"
+                });
+                return
+            }
+            this.$refs.chooseMembTree2.setCheckedKeys([]);
+            this.$emit("submitParticipant", chose2)
+        },
+        changeVisable(done) {
+            this.$refs.chooseMembTree2.setCheckedKeys([]);
+            this.$emit("changeParticipant", false)
+            if (done) {
+                done()
+            }
+        },
+        // 筛选逻辑
+        filterNode(value, data) {
+            let { userNameNeedTranslate } = this.user
+            if (!value) return true;
+            if (userNameNeedTranslate != '1') {
+                return data.label.indexOf(value) !== -1;
+            } else {
+                return this.filterNodePersonnel.some(item => item.includes(data.label))
+            }
+        },
+        // 选中改变
+        onTreeItemChange() {
+            var chosenList = this.$refs.chooseMembTree2.getCheckedNodes();
+            var list = chosenList.filter(item => item.isUser == 1);
+            this.chosenMembCount = list.length;
+        },
+        echartDepartment() {
+            if (this.participantsFilterText != '') {
+                this.filterNodeFlag = true
+                this.http.post("/user/getEmployeeList", {
+                    keyword: this.participantsFilterText,
+                    cursor: '',
+                    departmentId: -1,
+                    pageIndex: 1,
+                    pageSize: 1000
+                },
+                    res => {
+                        if (res.code == "ok") {
+                            this.filterNodePersonnel = res.data.records.map(item => item.name)
+                            this.$refs.chooseMembTree2.filter(this.participantsFilterText);
+                        } else {
+                            this.$message({
+                                message: res.msg,
+                                type: "error"
+                            });
+                        }
+                        this.filterNodeFlag = false
+                    },
+                    error => {
+                        this.filterNodeFlag = false
+                        this.$message({
+                            message: error,
+                            type: "error"
+                        });
+                    });
+            }
+        },
+        getDepartmentList() {
+            this.http.post('/department/listAllMemb', {
+            }, res => {
+                if (res.code == 'ok') {
+                    let list = res.data
+                    this.haveUsersList(list)
+                    this.deptMembData = JSON.parse(JSON.stringify(list))
+                } else {
+                    this.$message({
+                        message: res.msg,
+                        type: 'error'
+                    })
+                }
+            }, error => {
+                this.$message({
+                    message: error,
+                    type: 'error'
+                })
+            })
+        },
+        haveUsersList(list) {
+            for (var i in list) {
+                if (list[i].children != null) {
+                    this.haveUsersList(list[i].children);
+                }
+                if (list[i].userList != null) {
+                    if (list[i].children == null) {
+                        list[i].children = [];
+                    }
+                    list[i].userList.forEach(element => {
+                        var obj = { id: element.id, label: element.name, parentId: element.departmentId, isUser: 1 };
+                        list[i].children.push(obj);
+                    });
+                }
+            }
+        },
+    },
+}
+</script>
+<style scoped lang='scss'></style>

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

@@ -0,0 +1,59 @@
+<template>
+  <div :id="uuid" :style="style"></div>
+</template>
+
+<script>
+import * as echarts from "echarts";
+export default {
+  props: {
+    height: {
+      type: String,
+      default: "100%",
+    },
+    width: {
+      type: String,
+      default: "100%",
+    },
+    options: {
+      type: Object,
+      default: null,
+    },
+  },
+  components: {},
+  data() {
+    return {
+      uuid: null,
+      myChart: null,
+    };
+  },
+  computed: {
+    style() {
+      return {
+        height: this.height,
+        width: this.width,
+      };
+    },
+  },
+  watch: {
+    options() {
+      if (this.myChart) {
+        this.myChart.setOption(this.options);
+      }
+    },
+  },
+  created() {
+    this.uuid = this.idGen();
+  },
+  mounted() {
+    this.myChart = echarts.init(document.getElementById(this.uuid));
+    this.myChart.setOption(this.options);
+  },
+  methods: {
+    idGen() {
+      return new Date().getTime();
+    },
+  },
+};
+</script>
+
+<style scoped lang="scss"></style>

+ 18 - 18
fhKeeper/formulahousekeeper/timesheet/src/components/taskComponent.vue

@@ -2,7 +2,7 @@
   <div>
     <div style="height: 72vh;overflow: auto;">
         <el-form ref="form1" :model="addForm" :rules="taskRules" label-width="120px">
-            <el-form-item label="所属项目" v-if="showOrNot" prop="projectId">
+            <el-form-item :label="$t('subordinatetotheproject')" v-if="showOrNot" prop="projectId">
                 <el-select v-model="addForm.projectId" :placeholder="$t('defaultText.pleaseChoose')" @change="agentCreatesEvents(1)" filterable="true" style="width:100%;">
                     <el-option-group v-for="group in integrationProjectList" :key="group.label" :label="group.label">
                         <el-option v-for="item in group.peojectList" :key="item.id" :label="item.projectName + '\u3000' + item.projectCode" :value="item.id">
@@ -12,12 +12,12 @@
                     </el-option-group>
                 </el-select>
             </el-form-item>
-            <el-form-item label="所属任务分组" v-if="showOrNot" prop="groupId">
+            <el-form-item :label="$t('suoShuRenWuFenZu')" v-if="showOrNot" prop="groupId">
                 <el-select v-model="addForm.groupId" :placeholder="$t('defaultText.pleaseChoose')" @change="agentCreatesEvents(2)" filterable="true" style="width:100%;">
                     <el-option v-for="item in groupList" :key="item.id" :label="item.name" :value="item.id"></el-option>
                 </el-select>
             </el-form-item>
-            <el-form-item label="所属任务列表" v-if="showOrNot" prop="stagesId">
+            <el-form-item :label="$t('suoShuRenWuLieBiao')" v-if="showOrNot" prop="stagesId">
                 <el-select v-model="addForm.stagesId" :placeholder="$t('defaultText.pleaseChoose')" filterable="true" style="width:100%;">
                     <el-option v-for="item in stageList" :key="item.id" :label="item.stagesName" :value="item.id"></el-option>
                 </el-select>
@@ -28,7 +28,7 @@
                     <el-option v-for="item in stageList" :key="item.id" :label="item.stagesName" :value="item.id"></el-option>
                 </el-select>
             </el-form-item>
-            <el-form-item label="前置任务" prop="aheadTidList" >
+            <el-form-item :label="$t('qianZhiRenWu')" prop="aheadTidList" >
                 <el-select v-model="addForm.aheadTidList" style="width:100%;" multiple filterable @change="$forceUpdate()">
                     <el-option v-for="item in relationdata" :key="item.id" :label="item.name" :value="item.id"></el-option>
                 </el-select>
@@ -81,8 +81,8 @@
                             </div>
                             <!-- 项目服务 -->
                             <div v-if="user.companyId==3092">
-                                <span style="margin-left:30px;margin-right:10px;">{{'项目服务'}}</span>
-                                <el-select  clearable collapse-tags  filterable  v-model="executorItem.serviceId" size="small" placeholder="请选择项目服务" style="width: 300px" @change="serviceIdChange()" :disabled="(addForm.id != null && user.id != addForm.createrId && currentProject.inchargerId != user.id) && !permissions.projectManagement && !permissions.editAnyTask && !(groupResponsibleId == user.id)">
+                                <span style="margin-left:30px;margin-right:10px;">{{ $t('xiangMuFuWu') }}</span>
+                                <el-select  clearable collapse-tags  filterable  v-model="executorItem.serviceId" size="small" :placeholder="$t('qingXuanZeXiangMuFuWu')" style="width: 300px" @change="serviceIdChange()" :disabled="(addForm.id != null && user.id != addForm.createrId && currentProject.inchargerId != user.id) && !permissions.projectManagement && !permissions.editAnyTask && !(groupResponsibleId == user.id)">
                                     <el-option
                                     v-for="item in sapServiceList"
                                     :key="item.id"
@@ -111,7 +111,7 @@
             <el-link type="primary" v-if="(((addForm.executorListFront == null || addForm.executorListFront.length<100) && 
             (addForm.id == null|| user.id == addForm.createrId || currentProject.inchargerId == user.id || permissions.projectManagement || permissions.editAnyTask)) || 
             groupResponsibleId == user.id)" 
-            style="margin:0 0 10px 35px;position: relative;z-index: 999;" @click.stop="addExecutorLine">添加执行人</el-link>
+            style="margin:0 0 10px 35px;position: relative;z-index: 999;" @click.stop="addExecutorLine">{{ $t('addinganexecutor') }}</el-link>
             </div>
             <el-form-item :label="$t('priority')">
                 <el-select v-model="addForm.taskLevel" style="width:100%;" >
@@ -408,7 +408,7 @@
     </div>
     <div slot="footer" class="dialog-footer foooot">
         <el-button v-if="(user.id == addForm.createrId || currentProject.inchargerId == user.id || currentProject.creatorId == user.id || permissions.projectManagement) && canAddTask" @click.native="deleteTask()" style="float:left;">{{ $t('btn.delete') }}</el-button>
-        <el-button type="primary" v-if="user.userNameNeedTranslate == 1 && !meetingId && !integrationTask.stage && addForm.executorListFront[0].executorId" @click="meetingCli()">发起会议</el-button>
+        <el-button type="primary" v-if="user.userNameNeedTranslate == 1 && !meetingId && !integrationTask.stage && addForm.executorListFront[0].executorId" @click="meetingCli()">{{ $t('faQiHuiYi') }}</el-button>
         <el-button @click.native="closeBounceds()">{{ $t('btn.cancel') }}</el-button>
         <el-button type="primary" @click="submitInsert" :loading="addLoading">{{ $t('btn.submit') }}</el-button>
     </div>
@@ -476,8 +476,8 @@
                                     </p>
                                     <p style="display: inline-block;padding: 0;margin: 0;" v-if="user.userNameNeedTranslate != 1">{{item.content}}</p>
                                     <!-- 重启原因和责任人 -->
-                                    <span class="commentSpan" v-if="user.timeType.restartTaskNeedReason == 1 && item.reason != ''">重启原因:{{item.reason}}</span>
-                                    <span class="commentSpan" v-if="user.timeType.restartTaskNeedReason == 1 && item.taskPersonLiableList.length > 0">责任人: 
+                                    <span class="commentSpan" v-if="user.timeType.restartTaskNeedReason == 1 && item.reason != ''">{{ $t('zhongQiYuanYin') }}:{{item.reason}}</span>
+                                    <span class="commentSpan" v-if="user.timeType.restartTaskNeedReason == 1 && item.taskPersonLiableList.length > 0">{{ $t('zeRenRen') }}
                                         <span v-for="responsibility, responsibilityIndex in item.taskPersonLiableList" :key="responsibilityIndex">
                                             <span v-if="user.userNameNeedTranslate == 1">
                                                 <TranslationOpenDataText type='userName' :openid='responsibility.userName'></TranslationOpenDataText>
@@ -756,10 +756,10 @@ export default {
         },
         taskRules : {
             name: [{ required: true, message: this.$t('enterthetaskcontent'), trigger: "blur" }],
-            serviceId: [{ required: true, message: '请选择服务', trigger: "blur" }],
-            projectId: [{ required: true, message: '请选择所属项目', trigger: "blur" }],
-            groupId: [{ required: true, message: '请选择所属任务分组', trigger: "blur" }],
-            stagesId: [{ required: true, message: '请选择所属任务列表', trigger: "blur" }],
+            serviceId: [{ required: true, message: this.$t('qingXuanZeFuWu'), trigger: "blur" }],
+            projectId: [{ required: true, message: this.$t('qingXuanZeSuoShuXiangMu'), trigger: "blur" }],
+            groupId: [{ required: true, message: this.$t('qingXuanZeSuoShuRenWuFenZu'), trigger: "blur" }],
+            stagesId: [{ required: true, message: this.$t('qingXuanZeSuoShuRenWuLieBiao'), trigger: "blur" }],
         },
         formGrouping: {
             name: [{ required: true, message: this.$t('pleaseenteragroupname'), trigger: "blur" }],
@@ -1015,11 +1015,11 @@ export default {
         this.http.post('/project/nearProject',{},res => {
             if(res.code == 'ok'){
                 let topObj = {
-                    label: '最近选择项目',
+                    label: this.$t('zuiJinXuanZeXiangMu'),
                     peojectList: res.data 
                 }
                 let botomObj = {
-                    label: '全部项目',
+                    label: this.$t('other.allProject'),
                     peojectList: this.projectList
                 }
                 this.integrationProjectList = [topObj, botomObj]
@@ -1486,7 +1486,7 @@ export default {
                 if (findSameUser) {
                     return this.$message({
                         showClose: true,
-                        message: '同一个执行人,服务不能相同',
+                        message: this.$t('tongYiGeZhiHangRenFuWuBuNengXiangTong'),
                         type: 'error'
                     });
                 }
@@ -1923,7 +1923,7 @@ export default {
     },
     // 列表的删除按钮
     taskFileDelete(eid){
-        this.$confirm('是否移除此文件?', this.$t('other.prompts'), {
+        this.$confirm(this.$t('shiFouYiChuCiWenJian'), this.$t('other.prompts'), {
             confirmButtonText: this.$t('btn.determine'),
             cancelButtonText: this.$t('btn.cancel'),
             type: 'warning'

+ 4 - 0
fhKeeper/formulahousekeeper/timesheet/src/http.js

@@ -59,6 +59,8 @@ export default {
         }
         if(localStorage.getItem('lang') == 'en') {
             data.lang = 'english'
+        } else {
+            data.lang = 'zh'
         }
         axios({
             method: 'post',
@@ -109,6 +111,8 @@ export default {
         }
         if(localStorage.getItem('lang') == 'en') {
             data.lang = 'english'
+        } else {
+            data.lang = 'zh'
         }
         axios({
             method: 'post',

+ 669 - 6
fhKeeper/formulahousekeeper/timesheet/src/i18n/en.json

@@ -23,11 +23,13 @@
     "supplierManagement": "Supplier Management",
     "organizationalStructure": "Organizational structure",
     "approvalFlowSettings": "Approval flow Settings",
-    "basicDataManagemen": "Basic Data Managemen",
     "basicSystemSettings": "Basic System Settings",
     "roleRightsManagement": "Role Rights Management",
-    "gongshitongji":"工时统计表",
-    "caiwushenhe":"财务审核"
+    "gongshitongji": "Work hour statistics table",
+    "caiwushenhe": "Financial review",
+    "basicDataManagement": "Basic data management",
+    "budgetReview": "Estimated working hours review",
+    "projectFormSettings": "Project Form Settings"
   },
   "role": {
     "ordinaryEmployees": "Ordinary employees",
@@ -205,6 +207,7 @@
     "waitForTheProjectReviewer": "Waiting for project reviewers",
     "audit": "review",
     "projectAuditor": "project reviewer",
+    "projectReviwer": "secondary reviewer",
     "reviewer": "Reviewer",
     "await": "await",
     "importWaitingForReview": "Import waiting for review",
@@ -525,7 +528,7 @@
   "todaytask": "today's task",
   "jin-ji": "urgent",
   "yi-ban": "generally",
-  "AuditProcess":"AuditProcessSet",
+  "AuditProcess": "AuditProcessSet",
   "zhong-yao": "important",
   "makesuretodeletethesubproject": "Are you sure you want to delete the subproject",
   "ma": "?",
@@ -1092,7 +1095,6 @@
   "pleaseenterthedepartmentname": "Please enter department name",
   "pleaseinputcost": "Please enter cost",
   "pleaseselectroles": "Please select a role",
-  "areyousuretosynchronize ": "Are you sure to sync address book from Dingding? \n(It may take some time to load, please be patient)",
   "booksecret": "Please enter address book secret",
   "synchronizingtheassociation": "Syncing associations, please wait...",
   "synchronoussuccesss": "Sync complete",
@@ -1521,5 +1523,666 @@
   "que-ding-yao-shan-chu-gai-he-tong-ma": "Are you sure you want to delete this contract ?",
   "que-ding-yao-shan-chu-gai-wen-jian-ma": "Are you sure you want to delete this file ?",
   "he-tong-guan-li-dao-ru-mo-ban": "Contract Management Template",
-  "minMaxCheck": "report time min value should not be greater than the max value"
+  "minMaxCheck": "report time min value should not be greater than the max value",
+  "budget": "general budget",
+  "areyousuretosynchronize": "Are you sure to synchronize your contacts from DingTalk? (It may take some loading time, please be patient.)",
+  "expenses": "Expense reporting",
+  "chu-cha-shen-he": "Business trip review",
+  "bo-hui-le-qing-jia-shen-qing": "Rejected leave application",
+  "que-ding-yao-che-hui-gai-chu-cha-shen-qing-ma": "Are you sure you want to withdraw this business trip application",
+  "yi-cun-zai-zhong-fu-bu-men": "Duplicate department already exists",
+  "yi-cun-zai-zhong-fu-ren-yuan": "There are already duplicate personnel present",
+  "zhi-shao-xuan-ze-yi-ge-bu-men-huo-zhe-ren-yuan-zuo-wei-shen-he-ren": "Select at least one department or personnel as the reviewer",
+  "zhong-xin-ti-jiao": "Resubmit",
+  "zhu-yao-fu-ze-ren": "(Main person in charge)",
+  "qing-shu-ru-guan-jian-ming-cheng": "Please enter the key name",
+  "sou-suo": "search",
+  "he-tong-lei-xing-zui-duo-zhi-neng-chuang-jian-20-ge": "A maximum of 20 contract types can be created",
+  "hui-kuan-ji-hua": "Collection plan",
+  "hui-kuan-jin-e": "Collection amount",
+  "hui-kuan-jinebu-neng-wei-0": "The payment amount cannot be 0",
+  "hui-kuan-ri-qi": "Payment date",
+  "hui-kuan-ri-qi-bu-neng-wei-kong": "The payment date cannot be empty",
+  "que-ren-shen-he-tong-guo-ma-tong-guo-hou-he-tong-ji-ben-xin-xi-wu-fa-xiu-gai": "Are you sure the review has been approved? Once approved, the basic information of the contract cannot be modified",
+  "shi-fou-yi-hui-kuan": "Has the payment been received",
+  "wei-hui-kuan": "Unpaid payments",
+  "xia-bi-hui-kuan-jin-e": "Next payment amount",
+  "xia-bi-hui-kuan-ri-qi": "Date of next payment collection",
+  "yi-hui-kuan": "Received payment",
+  "yi-hui-kuan-jin-du": "Progress of payments received",
+  "yi-hui-kuan-jin-e": "Received amount",
+  "zong-hui-kuan-jinebu-de-da-yu-he-tong-jin-e": "The total payment amount shall not exceed the contract amount",
+  "fenLeiGongShiMingXiBiao": "Classification of Work Hours Details",
+  "fenZuHaoYongJinDuBiao": "Group Consumption Schedule",
+  "fteBaoBiao": "FTE report",
+  "renWuZhongQiBiao": "Task restart table",
+  "xiangMuFenLeiGongShiZhanBiBiao": "Table of proportion of project classification working hours",
+  "xiangMuHaoYongJinDuBiao": "Project Consumption Schedule",
+  "xiangMuYuGuGongShiBiao": "Project Estimated Work Hours Table",
+  "youXiaoGongShiShuaiBiao": "Effective working hour rate table",
+  "yuanGongRenWuJinDuBiao": "Employee Task Schedule",
+  "yuanGongRenWuWanChengQingKuangBiao": "Employee Task Completion Status Table",
+  "yuanGongXiangMuJinDuBiao": "Employee Project Schedule",
+  "ziXiangMuGongShiChengBenBiao": "Subproject Labor Cost Table",
+  "anShiWanChengShuLiang": "Complete quantity on time",
+  "anShiWanChengShuai": "On time completion rate",
+  "baoJiaXiangMu": "Quotation project",
+  "buZuGongShi": "Make up for working hours",
+  "canYuYuanGong": "Participating employees",
+  "dangQianZhuangTai": "current state",
+  "diYu": "lower than",
+  "feiYongBaoXiaoMingXiBiaoXlsx": "Expense Reimbursement Details Table. xlsx",
+  "fenPeiGongShiH": "Allocated working hours (h)",
+  "fenZuShiJiGongShiH": "Group actual working hours (h)",
+  "fenZuYuGuGongShiH": "Group estimated working hours (h)",
+  "fteGongShiDangYueGongShiJiShu": "FTE (Hours/Month Work Base)",
+  "fteGongShiGuDingGongShiJiShu_163125": "FTE (Hours/Fixed Hours Base (163.125))",
+  "fuWuXiangMu": "Service Items",
+  "fuXiangMuBianHao": "Parent Project Number",
+  "fuXiangMuMingCheng": "Parent Project Name",
+  "fuZeBuMen": "Responsible department",
+  "fuZeZuChang": "Responsible team leader",
+  "gaoYu": "higher than",
+  "gongShiHaoYongShuai": "Labor consumption rate",
+  "heJiGongShiChengBen": "Total labor cost",
+  "heJiGongShiH": "Total working hours (h)",
+  "heTongLiRun": "Contract profit",
+  "heTongLiRunShuai": "Contract profit margin",
+  "jiDuXlsx": "Quarterly). xlsx",
+  "jiHuaGongShiCaiWu": "Planned working hours (finance)",
+  "jiHuaGongShiH": "Planned working hours (h)",
+  "jiaBanGongShiH": "Overtime working hours (h)",
+  "qingXuanZeTiXingFenLei": "Please select reminder category",
+  "qingXuanZeYuanGongLeiXing": "Please select employee type",
+  "qingXuanZeZiZhuXiangMuLeiBie": "Please select the category of autonomous projects",
+  "quXiao": "Cancel",
+  "quanBuBuZu": "Make up for it all",
+  "queDing": "determine",
+  "renMing": "name",
+  "renWuZongShuLiang": "Total number of tasks",
+  "riBiaoZhunGongShi": "Daily standard working hours",
+  "sheZhiYuJing": "Set up alerts",
+  "sheZhiZhanBi": "Set proportion:",
+  "shengYuGongShiH": "Remaining working hours (h)",
+  "shiBaoGongShiXiaoShi": "Actual reported working hours (hours)",
+  "shiJiChengBen": "actual cost",
+  "shiJiGongShiChengBen": "Actual labor cost",
+  "shouHouBaoJiaXiangMu": "After sales quotation project",
+  "tYihuikuanlirun": "$t('yiHuiKuanLiRun')",
+  "tiXingFenLei": "Reminder classification:",
+  "wanChengRiQi": "Completion date",
+  "weiFenLei": "Unclassified",
+  "weiWanChengShuLiang": "Unfinished quantity",
+  "weiWanChengShuai": "Unfinished rate",
+  "xiangMuHao": "Project number",
+  "xiangMuJieZhiShiJian": "Project deadline",
+  "xiangMuKaiShiShiJian": "Project start time",
+  "xiangMuRenWu": "Project tasks",
+  "xiaoHaoGongShiH": "Consumed working hours (h)",
+  "xuanZeGuanXi": "Select Relationship:",
+  "yanChiWanChengShuLiang": "Delayed completion quantity",
+  "yanFaXiangMu": "R&D projects",
+  "yiHuiKuanLiRun": "Recovered profits",
+  "yiHuiKuanLiRunShuai": "Recovered profit margin",
+  "yiWanChengShuLiang": "Completed quantity",
+  "yiXiaoHaoGongShiChengBen": "Cost of consumed labor hours (¥)",
+  "yiXiaoHaoGongShiH": "Consumed working hours (h)",
+  "yingBaoGongShi": "Reported working hours",
+  "yingBaoGongShiTianShu": "Number of working hours to be reported",
+  "yingGongShiXiaoShi": "Expected working hours (hours)",
+  "youXiaoGongShiShuai": "Effective working hours rate",
+  "yuGuGongShi": "Estimated working hours",
+  "yuanGong": "staff",
+  "yuanGongLeiXing": "Employee type",
+  "yuanGongRenWuShuJu": "Employee task data",
+  "zaiZhiRenShu": "Number of employees",
+  "zeRenRen": "person liable",
+  "zengBuGongShiH": "Additional working hours (h)",
+  "zhengChangGongShiH": "Normal working hours (h)",
+  "zhongQiShiJian": "Restart time",
+  "zhongQiYuanYin": "Reason for restart",
+  "ziXiangMuChengBen": "Sub project cost",
+  "ziXiangMuGongShi": "Sub project working hours",
+  "ziXiangMuMingCheng": "Sub project name",
+  "keHuLieBiaoXlsx": "Customer List. xlsx",
+  "gongZuoShiChangFenPei": "Allocation of working hours",
+  "jinRiGongZuoShiChang": "Today's working hours:",
+  "kanXiaoShuo": "Read novels",
+  "liaoTian": "chat",
+  "meiGong": "art designer",
+  "qiTaGongZuo": "Other work",
+  "shangWang": "surf the internet",
+  "sheJi": "Design",
+  "shiChangDanWeiH": "Duration (in hours)",
+  "tingYinLe": "Listen to the music",
+  "weiZhi": "unknown",
+  "wenDang": "file",
+  "yanFa": "research and development",
+  "yingShiYuLe": "Film and entertainment",
+  "yunYing": "operate",
+  "jinRiZanWuJieTuDianJiChaKanJinQi": "There are currently no screenshots available today. Click to view recent updates",
+  "keHuDuanXiaZai": "Client Download",
+  "suoYouJieTu": "All screenshots",
+  "yuanGongAnZhuangKeHuDuanLingDaoJiKeChaKanGongZuoZhuoMianYuanChengJianGuan": "(Employees can install the client, and leaders can view remote supervision of the work desktop)",
+  "feiGongZuoQingKuangTongJi": "Non work statistics",
+  "hangWei": "behavior",
+  "tuPian": "picture",
+  "benYeJineheJi": "Total amount on this page",
+  "cunZaiDaiShenHeHuoYiBoHuiDeDanJu": "There are pending or rejected documents",
+  "daYin": "Printing",
+  "daiDiErShenHeRenShenHe": "To be reviewed by the second reviewer",
+  "daiDiYiShenHeRenShenHe": "To be reviewed by the first reviewer",
+  "danJuDaoChu": "Document export",
+  "duiYingChengBenXiang": "Corresponding cost items",
+  "faFang": "grant",
+  "faFangFangShi": "Distribution method",
+  "faFangZhuangTai": "Distribution status",
+  "feiYongBaoXiaoDanJuLieBiao": "List of expense reimbursement documents",
+  "feiYongJinE": "Cost amount",
+  "feiYongJineHanShui": "Cost amount (including tax)",
+  "feiYongLeiXing": "Cost type:",
+  "feiYongLeiXingDaLeiGuanLi": "Cost Category Management",
+  "feiYongZhuLeiXing": "Cost main type",
+  "feiYongZhuLeiXingGuanLi": "Cost Main Type Management",
+  "guanBi": "close",
+  "qingTianXieWanZheng": "Please fill it out completely",
+  "qingTianXieWanZhengFeiYongJinE": "Please fill in the complete fee amount",
+  "qingXuanZeDiErShenHeRen": "Please select the second reviewer",
+  "qingXuanZeDiYiShenHeRen": "Please select the first reviewer",
+  "qingXuanZeWeiFaFangDeDanJu": "Please select documents that have not been issued",
+  "qingXuanZeYiFaFangDeDanJu": "Please select the issued documents",
+  "qingXuanZeZhiFuFangShi": "Please select payment method",
+  "quXiaoFaFang": "Cancel distribution",
+  "shenHeWanCheng": "Review completed",
+  "tianBaoShiJian": "Filling time",
+  "weiFaFang": "unissued",
+  "xiangMuShenHeZhuangTai": "Project (Review Status)",
+  "yiFaFang": "Issued",
+  "zhang": "Zhang",
+  "zhiFuFangShi": "Payment method",
+  "caiWuShenHeTiShi": "Financial audit prompt",
+  "nianYue": "years:",
+  "ninQueDingYaoShenHeTongGuo": "Are you sure you want to pass the review",
+  "riBaoNianYue": "Daily Report Year Month",
+  "shenHeChengGong": "Review successful!",
+  "shenHeZhuangTai": "Review status:",
+  "weiShenHe": "Unaudited",
+  "yiShenHe": "Approved",
+  "yueDeGongShiBaoGaoMa": "Is there a monthly work hour report?",
+  "boHuiLeQingJiaShenQing": "Rejected leave application",
+  "chaKanYuanYin": "View reasons",
+  "qingJiaDan": "Leave application form",
+  "qingJiaShenHe": "Leave Review",
+  "queDingYaoCheHuiGaiQingJiaShenQingMa": "Are you sure you want to withdraw the leave application",
+  "shengYuJiaQi": "Remaining vacation",
+  "yiCheHui": "Withdrawn",
+  "fanKuiJieGuo": "Feedback results",
+  "gongSiLieBiao": "Company List",
+  "gongSiMingCheng": "corporate name",
+  "keHuFanKui": "Customer feedback",
+  "lianXiFangShi": "contact information",
+  "qingShuRuKeHuFanKui": "Please enter customer feedback",
+  "shiFouLianXi": "Whether to contact",
+  "tiJiao": "Submit",
+  "tianXieChengGong": "Completed successfully",
+  "tianXieFanKui": "Fill in feedback",
+  "weiLianXi": "Not contacted",
+  "yiLianXi": "Contacted",
+  "zhuCeShiJian": "Registration time",
+  "gongChengZhuanYeLieBiao": "List of Engineering Majors",
+  "qingShuRuZhuanYeMingCheng": "Please enter the professional name",
+  "qingShuRuZhuanYeMingChengGuanJianZi": "Please enter the keyword of professional name",
+  "queDingYaoZhuanYe": "Make sure to be professional",
+  "shanChuZhuanYe": "Delete major",
+  "xinZengZhuanYe": "Newly added majors",
+  "xiuGaiZhuanYe": "Modify major",
+  "bianGengHouYuGuGongShi": "Estimated working hours after change",
+  "bianGengLiYou": "Reason for change",
+  "bianGengQianYuGuGongShi": "Estimated working hours before change",
+  "boHuiLiYou": "Reason for rejection",
+  "qingShuRuBoHuiLiYou": "Please enter the reason for rejection",
+  "qingXuanZeZhuangTai": "Please select a status",
+  "quXiaoBoHui": "Cancel rejection",
+  "renTian": "Human nature",
+  "shenHeRen": "Reviewed by:",
+  "tiJiaoRen": "submitter",
+  "tiJiaoShiJian": "Submission time",
+  "xiangMu": "project",
+  "yuGuGongShiBianGeng": "Estimated working hours change",
+  "chenBenTongJi": "Cost statistics",
+  "daoChuNeiRon": "Export Content",
+  "gongHhiZhanbiXmu": "Including the proportion of project working hours",
+  "gongShiHeChengBen": "Working hours and costs",
+  "hanZhuXiangMu": "Including the main project",
+  "jingChenBen": "Cost only",
+  "jingGongShi": "Only working hours",
+  "liMian": "inside",
+  "waiMian": "outside",
+  "baoXiaoHeJi": "Total reimbursement",
+  "feiYongBaoXiaoChengBen": "Expense reimbursement cost",
+  "gongShiChengBen": "Labor cost",
+  "gongShiHeJi": "Total working hours",
+  "riQiQuJian": "Date range:",
+  "buMenChengBen": "Departmental costs:",
+  "gongShi": "Working hours:",
+  "gongZuoChengBen": "Work cost:",
+  "xiangMuMingCheng": "Project Name:",
+  "bianJiMoRenMoBan": "Edit default template",
+  "jieDian": "node",
+  "moBanMa": "Is it a template",
+  "moRenWenJianJia": "Default folder",
+  "qingShuRuJieDianMingCheng": "Please enter the node name",
+  "queDingShanChu": "Confirm deletion",
+  "tongBuXiuGaiQiTaXiangMuZhongDeTongMingWenJianJia": "Synchronize and modify folders with the same name in other projects",
+  "xinZengJieDian": "Add nodes",
+  "ziDingYiMingCheng": "Custom Name",
+  "jianCeDaoYou": "Detected presence",
+  "mingYiTianGongShiRenYuanZaiXinZiBiaoZhongWuJiLuBuCanYuChengBenFenTan": "Personnel with completed working hours have no record in the salary table and will not participate in cost allocation",
+  "paiChuBuFenXiangMu": "Exclude some items",
+  "quanBuYiTianBaoXiangMu": "All reported projects",
+  "shangChuan": "upload",
+  "wuXinZiRenYuanLieBiao": "List of unpaid personnel",
+  "xuanZeBuFenXiangMu": "Select some projects",
+  "yiShangRenYuanDangYueYiTianXieGongShiQingDaoRuTaMenDeXinZi": "*The above personnel have already filled in their working hours for the current month. Please import their salaries.",
+  "10Yue": "October",
+  "11Yue": "November",
+  "12Yue": "December",
+  "1Yue": "January",
+  "2Yue": "February",
+  "3Yue": "March",
+  "4Yue": "April",
+  "5Yue": "May",
+  "6Yue": "June",
+  "7Yue": "July",
+  "8Yue": "August",
+  "9Yue": "September",
+  "anRenYuanChaKan": "View by Personnel",
+  "baYue": "August",
+  "chiXuShiJian": "Duration",
+  "erYue": "February",
+  "fenZhong": "minute",
+  "guanLian": "relation",
+  "jiangBeiShanChu": "place it on clipboard",
+  "jieShu": "(End)",
+  "jinTian": "today",
+  "jiuYue": "September",
+  "kaiShi": "(Start)",
+  "liuYue": "June",
+  "nian": "year",
+  "qiYue": "July",
+  "qingQueRenShiFouCheXiaoXiuGai": "Please confirm if the modification has been revoked!",
+  "renWuMing": "Task Name",
+  "ri": "day",
+  "sanYue": "March",
+  "shiErYue": "December",
+  "shiFouShanChuRiCheng": "Do you want to delete the schedule?",
+  "shiJianFanWei": "time frame",
+  "shiYiYue": "November",
+  "shiYue": "October",
+  "siYue": "April",
+  "thisTWuyue": "this.$t('wuYue')",
+  "wuYue": "May",
+  "xiangXi": "detailed",
+  "xinJianRiCheng": "New Schedule",
+  "xingQiEr": "Tuesday",
+  "xingQiLiu": "Saturday",
+  "xingQiRi": "Sunday",
+  "xingQiSan": "Wednesday",
+  "xingQiSi": "Thursday",
+  "xingQiWu": "Friday",
+  "xingQiYi": "Monday",
+  "yiYue": "January",
+  "zhou": "week",
+  "jiHuaJieShuRiQi": "Plan End Date",
+  "shiJiYuGuGongShi": "Actual/estimated working hours:",
+  "ciCaoZuoJiangYongJiuShanChuGaiWenJianShiFouJiXu": "This operation will permanently delete the file. Do you want to continue?",
+  "congGaiRiQiQiTianBaoGongShiKaiShiZhanYongYuSuanRenTianGongShi": "Starting from this date, the reported working hours will occupy the budgeted person day working hours",
+  "feiBiTian": "Not mandatory",
+  "feiXiangMuGongShi": "Non project working hours",
+  "fenZuFuZeRen": "Group leader:",
+  "fenZuGongShiBuZuShi": "When group working hours are insufficient",
+  "fenZuGongShiShengYuTiXingBaiFenBi": "Group Work Remaining Reminder Percentage",
+  "fenZuMingCheng": "Group name:",
+  "fuZhiDaoQiTaXiangMu": "Copy to other projects",
+  "genJuXiTongJiChuSheZhiMeiRiZhengChangGongZuoShiChangJiSuan_1RenTianWeiYiGeMeiRiZhengChangGongZuoShiChang": "According to the basic system settings, the daily normal working hours are calculated, and 1 person day is a daily normal working hour",
+  "gongShiLeiXing": "Work hour type",
+  "gongShiXiTongChuangJianDeXiangMuBiTian": "Items created by the working hours system must be filled in",
+  "gongShiXiTongHeWaiBuTongBuDeXiangMuDuBiTian": "Both the work hour system and external synchronization projects are mandatory",
+  "gongZuoNeiRong": "job content",
+  "gongZuoZhiZe": "operating duty",
+  "guanBiChengGong": "Closed successfully",
+  "guanKongKaiShiRiQi": "Control start date",
+  "jinZhiTianBao": "Prohibit reporting",
+  "kaiQiChengGong": "Successfully opened",
+  "keYiTianBaoJinTiXing": "Can be filled out, only reminder",
+  "piLiangSheZhiFenZuFuZeRen": "Batch setting of group leaders",
+  "piLiangSheZhiRenWuFenZuFuZeRen": "Batch set task group leader",
+  "piLiangZengJiaRenWuFenZu": "Batch adding task groups",
+  "qingTianXieFenZuMingCheng": "Please fill in the group name",
+  "qingTianXieGongZuoNeiRong": "Please fill in the job description",
+  "qingXuanZeChaoSongRen": "Please select a CC recipient",
+  "qingXuanZeFenZuFuZeRen": "Please select the group leader",
+  "qingXuanZeJpgHuoJpegWenJian": "Please select a. jpg or. jpeg file",
+  "qingXuanZeSuoShuBuMen": "Please select the department you belong to",
+  "queRenTongBuXiangMuShuJu": "Confirm synchronizing project data?",
+  "renTianYuGuGongShi": "Man day (estimated working hours:",
+  "riBaoChaoSongRen": "Daily copy recipient",
+  "shengYuYuGuGongShi": "Remaining estimated working hours",
+  "tianJiaYiHang": "Add a row",
+  "weiTongBuXiangMu": "Unsynchronized items",
+  "xiaZaiDuoXiangMuRenWuMoBan": "Download multi project task templates",
+  "xiangMuDaoChuZhongQingShaoHou": "Project export in progress, please wait",
+  "xiangMuFuWuTongBu": "Project service synchronization",
+  "xiangMuGongShi": "Project working hours",
+  "xiangMuGongShiBuZuShi": "When project hours are insufficient",
+  "xiangMuGongShiShengYuTiXingBaiFenBi": "Remaining reminder percentage of project hours",
+  "xiangMuRenTian": "Project person day",
+  "xiangMuShenHeRenShenHe": "Project Reviewer Review",
+  "xiangMuSuoShuBuFuZeRenShenHe": "Reviewed by the BU responsible person for the project",
+  "xiangMuTongBuChengGong": "Project synchronization successful",
+  "xiangMuYuGuGongShiPeiZhi": "Project estimated working hours configuration",
+  "xuanZeYaoFuZhiDaoDeMuBiaoXiangMu": "Select the target project to copy to",
+  "yiTongBuXiangMu": "Synchronized project",
+  "yuGuGongShiBuNengWei_0": "Estimated working hours cannot be 0",
+  "yuGuGongShiShiFouBiTian": "Is estimated working hours mandatory",
+  "zhengZaiTongBuZhongQingNaiXinDengDai": "Syncing in progress, please be patient.",
+  "zhiNengFenGongSheZhi": "Functional division of labor setting",
+  "bianJiBiaoDanZiDuan": "Edit Form Fields",
+  "bianJiShiBai": "Editing failed:",
+  "qingShuRuZiDingYiMingCheng": "Please enter a custom name",
+  "shanChuShiBai": "Delete failed:",
+  "tianJiaBiaoDanZiDuan": "Add form fields",
+  "tianJiaShiBai": "Add failed:",
+  "wenBen": "text",
+  "zuiDuoZhiNengCunZaiShiGeZiDingYiZiDuan": "Up to ten custom fields can exist",
+  "dangQianXiangMuYuGuGongShiWei": "The estimated working hours for the current project are:",
+  "qingShuRuBianGengLiYou": "Please enter the reason for the change",
+  "qingShuRuYuGuGongShi": "Please enter estimated working hours",
+  "qingShuShuRuGuanJianZiGuoLv": "Please enter keywords for filtering",
+  "ruXuXiuGaiQingXianLianXiGuanLiYuan": "If you need to make modifications, please contact the administrator first",
+  "sheZhiFenZuYuGuGongShi": "Set group estimated working hours",
+  "shiFouYiChuCiWenJian": "Do you want to remove this file?",
+  "yinCangYiWanChengRenWu": "Hide completed tasks",
+  "yuGuGongShiRenTian": "Estimated working hours (person days)",
+  "yuGuGongShiXiaoShi": "Estimated working hours (hours)",
+  "yuGuGongShiXiuGai": "Estimated working hours modification",
+  "yuanYuGuGongShi": "Original estimated working hours",
+  "caoZuoJiLu": "Operation records",
+  "leRiBao": "The Daily News",
+  "liXiangDaoChuXlsx": "Project proposal export. xlsx",
+  "liXiangDaoRu": "Project initiation import",
+  "liXiangDaoRuJieGuo": "Project initiation import results",
+  "liXiangDaoRuMoBanXlsx": "Project Import Template. xlsx",
+  "liXiangShuJu": "Project proposal data",
+  "queDingYaoShanChuLiXiang": "Confirm to delete the project proposal",
+  "shanChuLiXiang": "Delete project proposal",
+  "anZhaoQiYeQingKuangTiaoZheng": "Adjust according to the situation of the enterprise",
+  "buFenChengYuan": "Some members",
+  "buMenHeXiangMuRiBaoShenHeRenBingHangShenHe": "Department and project daily report reviewers conduct parallel reviews",
+  "eWaiGongZuoRiSheZhi": "Extra working days setting:",
+  "feiGongZuoRiHanZhouMoWeiFaDingGongZuoRiJinZhiTianBao": "Non working days (including weekends as legal working days) are prohibited from filling in",
+  "fenZuFuZeRenShenHe": "Group leader review",
+  "gongZuoRiTianXieJiaBanShiChangBuDeChaoGuoZongGongZuoShiChangZhengChangGongZuoShiChang": "On weekdays, overtime hours must not exceed the total working hours minus normal working hours",
+  "guanBiRiBaoTianBaoGongNeng": "Turn off the daily report filling function",
+  "hao": "number",
+  "haoHanQianTianBao": "Fill in before (including) the number.",
+  "jiaBanShiChangXiaoYan": "Overtime duration verification",
+  "kaiQiHouChaoGuoXiangMuJiHuaJieShuRiQiDeRiBaoJiangBuKeTianBao": "Daily reports that exceed the end date of the project plan after opening will not be able to be filled in",
+  "keYong_0BiaoShiDaiShenHeTiaoShuLiRu_0JiangBeiTiHuanWei_10": "({0} can be used to represent the number of pending reviews, for example: {0} will be replaced with 10.)",
+  "keYong_0BiaoShiLouTianRiQiLiRu_0JiangBeiTiHuanWei_05240525": "(You can use {0} to indicate a missing date, for example: {0} will be replaced with 05/24, 05/25.)",
+  "mei": "each",
+  "meiYue": "monthly",
+  "piLiangDaiTianHanZhouMo": "Batch/proxy filling including weekends",
+  "qiTaFaDingJieRi": "Other statutory holidays",
+  "qingShuRuMingZiSouSuo": "Please enter your name to search",
+  "qingXianDianJiXiTongJiChuSheZhi": "Please click on the system basic settings first",
+  "quanGongSi": "Whole company",
+  "queDingShanChuZheTiaoShuJuMa": "Are you sure to delete this data?",
+  "renWuShiFouBiTian": "Is the task required",
+  "riBaoShenHeMoShi": "Daily report review mode",
+  "ruXuXiuGaiWeiQiTaShenHeMoShiQingLianXiKeFu": "If you need to modify to other review modes, please contact customer service",
+  "teShuJieJiaRiLieBiao": "List of Special Holidays",
+  "teShuJieJiaRiSheZhi": "Special holiday settings",
+  "tiXing": "remind",
+  "tianBaoRiBaoShiFouYinCangJieDuan": "Is the stage hidden when filling out daily reports",
+  "tianBaoRiBaoShiFouYinCangRenWu": "Is the task hidden when filling out the daily report",
+  "tianBaoShiKeDuoXuan": "Multiple choices are allowed when filling out the form",
+  "tiaoGuo": "skip",
+  "xianFenZuFuZeRenShenHeZaiXiangMuJingLiShenHe": "First, the group leader will review and then the project manager will review",
+  "xiangMuChaoQiHouBuKeTianBao": "The project cannot be filled out after the deadline",
+  "xiangMuSuoShuBuShenHe": "BU review to which the project belongs",
+  "youXiaoBuMen": "Effective department",
+  "youXiaoFanWei": "Effective range",
+  "youXiaoRenYuan": "Effective personnel",
+  "yuCiYue": "In the following month",
+  "yuanGongZiYouXuanZeShenPiRen": "Employees are free to choose approvers",
+  "zhiShuHuoBuMenFuZeRenShenHeXiangMuRiBaoShenHeRenShenHe": "Direct or department head review ->Project daily report review by reviewer",
+  "zhiShuShenHeRenHuoBuMenFuZeRenShenHe": "Reviewed by the direct reviewer or department head",
+  "chengGongFaQiHuiYi": "Successfully initiated the meeting",
+  "daiBanRenWuDaoChuXlsx": "To Do Task Export.xlsx",
+  "faQiHuiYi": "sponsor a conference",
+  "huiYiJieShuShiJian": "Meeting end time",
+  "huiYiKaiShiShiJian": "Meeting start time",
+  "qingXuanZeZeRenRen": "Please select the responsible person",
+  "xinJianRenWu": "New Task",
+  "xuanZeRiQiShiJian": "Select date and time",
+  "zhongQiRenWu": "Restart task",
+  "buFenGongShi": "Partial working hours",
+  "caoZuoChengGong": "Operation successful:",
+  "caoZuoShiJian": "Operation time",
+  "cuoWuXinXi": "error message",
+  "dangQianYuanGongYouDaiShenHeRiBaoQueRenTingYongBingBoHuiRiBaoMa": "Is the current employee awaiting review of the daily report, confirming its discontinuation and rejecting it?",
+  "gaiYuanGong": "The employee",
+  "jiangGaiYuanGongDeGongShiShuJuCanYuDeXiangMuYuRenWuZhuanYiZhi": "Transfer the employee's working hours data, projects and tasks they have participated in to",
+  "keJianFanWeiSheZhi": "Visible range setting",
+  "keTianBaoBuMen": "Department that can be filled in",
+  "keZhuanRang": "Transferable",
+  "liZhiRiQi": "Resignation date",
+  "liangCengShenHe": "Two level review",
+  "luJingGuanLiQiYeYingYongGuanLiGongShiGuanJiaKeJianFanWei": "Path: Manage Enterprise - Application Management - Hour Manager - Visible Range",
+  "piLiangQiYongYuanGong": "Batch enable employees",
+  "qiTaCuoWu": "Other errors",
+  "qingXuanZeJieShouRen": "Please select recipient",
+  "quanBuGongShi": "All working hours",
+  "queDingShanChuGaiYuanGongMa": "Are you sure to delete this employee?",
+  "queDingYaoShanChuGaiBuMenMa": "Are you sure you want to delete this department?",
+  "renYuanSuoZaiBuMenYuDingDingTongXunLuBaoChiYiZhi": "The department where the personnel are located should be consistent with the DingTalk contact list",
+  "shenHeCengJi": "Review hierarchy",
+  "shiFouShanChuGaiJiLu": "Do you want to delete this record?",
+  "tiaoYongRenShenFenBuFuHe": "The caller's identity does not match",
+  "tiaoZhengBuMen": "Adjusting departments",
+  "tongBuQianQingLianXiQiYeWeiXinGuanLiYuanJianChaYingYongShouQuanDeKeJianFanWei": "Please contact the enterprise WeChat administrator to check the visible range of application authorization before synchronization",
+  "tongBuRiZhi": "Synchronize logs",
+  "tongBuZhong": "Synchronizing",
+  "tuiSongZhiSap": "Push to SAP",
+  "weiSheZhiShiYouSuoShuBuMenFuZeRenShenHe": "When not set, it shall be reviewed by the department head",
+  "xiuZhengGongShi": "Correction of working hours",
+  "xiuZhengGongShiSuoShuBuMen": "Revise the department to which the working hours belong",
+  "yiCengShenHe": "First level review",
+  "yiQuXiao": "Canceled",
+  "yingYongLeiXingBuFuHeYaoQiu": "The application type does not meet the requirements",
+  "yingYongXinXiHuoQuShiBai": "Application information retrieval failed",
+  "zhuanYiDao": "Transfer to",
+  "caoZuoChengGong-0": "Operation successful!",
+  "dangQianBuMenCunZaiDaiShenHeBaoGao": "There are pending reports in the current department for review",
+  "dangQianBuMenCunZaiDaiShenHeBaoGaoShiFouQuanBuZhuanWeiTongGuo": "Are all pending reports in the current department approved?",
+  "bianGengTiXing": "Change Reminder",
+  "buKeChaoQianTianBao": "Cannot be filled in advance",
+  "chengGongDaoRu": "Successfully imported",
+  "cuiBan": "Urgent processing",
+  "daiShenHeZhuangTaiBuKeXiuGaiQingFanHuiDaoChaKanRiBaoZhongXianCheHui": "Pending review status cannot be modified. Please return to the daily report for review and withdraw first",
+  "daiTian": "Fill in on behalf of others",
+  "dangRiGongShiBuZu": "Insufficient working hours on the day",
+  "daoChuFangShi": "Export method",
+  "daoChuRiBaoShenHeJiLuShuJu": "Export daily audit record data",
+  "daoChuYuanGongTianBaoGongShiZhanBi": "Export the proportion of employee reported working hours",
+  "daoRuKaoQinShiChang": "Import attendance duration",
+  "daoRuKaoQinShiChangChengGong": "Successfully imported attendance duration",
+  "daoRuRiBaoShenHeJiLuXiuGaiShuJu": "Import daily audit records and modify data",
+  "deGongShi": "The working hours?",
+  "fuWu": "service",
+  "gongShiTuiSongRiZhi": "Work hour push log",
+  "gongShiYiChangMingXi": "Details of abnormal working hours",
+  "gongZuoNeiRongBiTianQingJianCha": "Job responsibilities are mandatory, please check",
+  "gongZuoZhiZeBiTianQingJianCha": "Job responsibilities are required, please check",
+  "heJiGongShi": "Total working hours",
+  "huLveBingTiJiao": "Ignore and submit",
+  "jiaZaiGengDuoRiBao": "Load more daily reports",
+  "jiaoSeBiTianQingJianCha": "Role required, please check",
+  "jiaoSeXuanZe": "Role selection",
+  "jingJianDaoChu": "Refine export",
+  "jingJianRiBaoBuHanGongZuoShiXiangHeShenPiXinXiShuJuLiangGengXiaoDaoChuGengKuai": "The streamlined daily report does not include work items and approval information, resulting in smaller data volume and faster export.",
+  "kaiShiRiQiBuNengDaYuJieShuRiQi": "The start date cannot be greater than the end date",
+  "kaiShiShanChu": "Start deleting",
+  "kaoQinGongShi": "Attendance hours",
+  "meiCiJinZhiChiDaiTianYiGeRen": "Only one person is supported to fill in at a time",
+  "meiYouGengDuoShuJuLe": "There's no more data left",
+  "ninQueDingYaoShanChuGaiShiJianDuanNeiDeRiBaoMaShanChuHouJiangBuKeHuiFu": "Are you sure you want to delete the daily report within this time period? Deleting it will be irreversible",
+  "ninQueDingYaoShanChuGaiTiaoJiLuMa": "Are you sure you want to delete this record?",
+  "ninQueDingYaoShenHeTongGuoGaiShiJianDuanNeiQuanBuDeRiBaoMa": "Are you sure you want to approve all daily reports within this time period?",
+  "piLiangShanChuRiBao": "Batch delete daily reports",
+  "piLiangShenHeRiBao": "Batch audit daily report",
+  "qingTianXieRenWuFenZu": "Please fill in the task grouping",
+  "qingXuanZeBuMenHuoRenYuan": "Please select department or personnel",
+  "qingXuanZeDaiTianDeYuanGong": "Please select the employee to fill in on behalf of",
+  "qingXuanZeFuWu": "Please choose a service",
+  "qingXuanZeNianYue": "Please select year and month:",
+  "qingXuanZeRenWuLiChengBei": "Please select task/milestone",
+  "qingXuanZeRiQiFanWei": "Please select a date range",
+  "qingXuanZeYuanGong": "Please select employee",
+  "quXiaoYiChang": "Cancel Exception",
+  "queRen": "confirm",
+  "queRenTuiSong": "Confirm push",
+  "queRenTuiSongDangQianGongShi": "Confirm the current working hours for push notifications?",
+  "renWuFenZuBiTianQingJianCha": "Task grouping is required, please check",
+  "renWuFenZuHeJieDuanBiTianQingJianCha": "Task grouping and stages are required, please check",
+  "renWuLiChengBei": "Tasks/Milestones",
+  "riBaoShenHeXiuGai": "Daily report review and modification",
+  "shenPiTongGuo": "Approved",
+  "shiBai": "fail",
+  "shiFouYiChang": "Is it abnormal",
+  "tTuisongshijian": "$t('tuiSongShiJian')",
+  "tianBaoBuMen": "Reporting department",
+  "tianBaoGongShi": "Fill in working hours",
+  "tuPianShangChuan": "Image upload",
+  "tuiSongChengGong": "Push successful!",
+  "tuiSongFangShi": "Push method",
+  "tuiSongGongShi": "Push working hours",
+  "tuiSongJieGuo": "Push results",
+  "tuiSongMingCheng": "Push name",
+  "tuiSongShiJian": "Push time",
+  "wanZhengDaoChu": "Complete export",
+  "weiTiJiao": "Unsubmitted",
+  "weiTiJiaoRenYuanLieBiao": "List of personnel not submitted",
+  "xiaZaiTianBaoGongShiZhanBiBiao": "Download and fill in the proportion of working hours table",
+  "xiangMuXiaDeRenWuFenZu": "Task grouping under the project",
+  "xiaoShiShiFouQueDingTiJiao": "Hour, are you sure to submit?",
+  "xiuGaiDaoRuJiLu": "Modify import records",
+  "xuanZeDaoRuRenYuan": "Select import personnel:",
+  "yiBoHuiLouTian": "Rejected/Omitted",
+  "yiTongGuoZhuangTaiBuKeXiuGai": "Passed status cannot be modified",
+  "yueDeGongShi": "Monthly working hours?",
+  "zhengZaiDaoRuXiuGaiZhongQingNaiXinDengDai": "Importing modifications, please be patient.",
+  "zhengZaiTuiSongZhongQingNaiXinDengDai": "Pushing, please be patient.",
+  "zhengZaiWei": "*Currently working for",
+  "zhiNengTianBao": "Intelligent filling",
+  "zhongDe": "Middle",
+  "ziXiangMuBiTianQingJianCha": "Subitem is required, please check",
+  "zuiJinXuanZeXiangMu": "Recently selected project",
+  "shenHeLiuCheng": "Review process:",
+  "daiShen": "Pending review",
+  "fenZu": "grouping",
+  "fenZuWeiSheZhiQingLianXiGaiXiangMuGuanLiRenYuan": "Grouping not set, please contact the project management personnel",
+  "fenZuWeiSheZhiShenPiRenQingLianXiGaiXiangMuGuanLiRenYuan": "No approver has been set for the group, please contact the project management personnel",
+  "juJue": "refuse",
+  "qingShuRuZhouZongJie": "Please enter the weekly summary",
+  "shiJianXiaoShi": "Time (hours)",
+  "tiJiaoShiBai": "Submission failed:",
+  "tianXieGongShiHeJiFei": "Fill in the total working hours",
+  "zanCun": "Temporary storage",
+  "zanCunShiBai": "Temporary storage failed:",
+  "banBenGuoDiQingShengJi": "Version too low, please upgrade",
+  "bangZhuZhongXin": "Help Center",
+  "baoYang": "maintain",
+  "changDuWei_120GeZiFu": "The length is 1-20 characters",
+  "dianJiChaKanCaoZuoShouCe": "Click to view the operation manual",
+  "faSongChengGong": "Sending successful",
+  "faSongYanZhengMa": "Send verification code",
+  "fanHuiShouYe": "Return to homepage",
+  "feiChangBaoQianNiFangWenDeYeMianBuCunZai": "Sorry, the page you visited does not exist!!!",
+  "fen": "branch",
+  "gongChengGuanLiZhuanYeBan": "Engineering Management Professional Edition",
+  "gongShiTongJiJiChuBan": "Basic version of working hour statistics",
+  "gongSiMing": "Company name",
+  "huo": "or",
+  "jiChuBan": "Basic version",
+  "jianZhuGongChengBan": "Construction Engineering Edition",
+  "jingGao": "warning",
+  "liangCiShuRuDeMiMaBuYiZhi": "The passwords entered twice are inconsistent",
+  "miMaChangDuBuNengShaoYu_6Wei": "The password length cannot be less than 6 characters",
+  "miao": "second",
+  "muQianZanWuXiaoXi": "There is currently no news available",
+  "ninHaoNinGouMaiDeBanBenYiDaoQi": "Hello, the version you purchased has expired!",
+  "qiJianBan": "Flagship Edition",
+  "qiYeBanGongQiJianBan": "Enterprise Office Flagship Edition",
+  "qiYeWeiXinSaoMaDengLu": "Scan the QR code to log in to Enterprise WeChat",
+  "qingSheZhiMiMaChangDuBuDiYu_6Wei": "Please set a password with a length of no less than 6 characters",
+  "qingShuRuGongHao": "Please enter the job number",
+  "qingShuRuGongSiMing": "Please enter the company name",
+  "qingShuRuGongSiMingCheng": "Please enter the company name",
+  "qingShuRuYanZhengMa": "Please enter the verification code",
+  "qingYongQiYeWeiXinSaoMaTianJiaKeFu": "Please scan the code on Enterprise WeChat to add customer service",
+  "qingZhongFuShuRuMiMa": "Please re-enter the password",
+  "ruoXuJiXuShiYongQingQianWangQiYeWeiXinYingYongShiChangXuFeiGeiGuiGongSiDaiLaiBuBianJingQingLiangJie": "If you need to continue using it, please go to the enterprise WeChat application market to renew. We apologize for any inconvenience caused to your company. Thank you for your understanding!",
+  "saoMaTianJiaQiYeWeiXinKeFu": "Scan the code to add enterprise WeChat customer service",
+  "sheZhiMiMaChangDuBuDiYu_6Wei": "Set a password with a length of no less than 6 characters",
+  "shenPi": "Approval",
+  "shi": "Time",
+  "shouJiHaoMaGeShiBuZhengQue": "Incorrect phone number format",
+  "wanShanGongHao": "Improve job ID",
+  "wanShanXingMing": "Complete Name",
+  "wuQuanFangWenQingLianXiGuanLiYuanWeiNinFenPeiQuanXian": "Unauthorized access, please contact the administrator to assign permissions for you",
+  "xiangMuGuanLiZhuanYeBan": "Project Management Professional Edition",
+  "xiuGaiGongSiMingCheng": "Change company name",
+  "xuanZeBanBen": "Select version:",
+  "yanZhengMa": "Verification Code",
+  "yiDaoQi": "Expired",
+  "zhengZaiJinRuXiTong": "Entering the system",
+  "zhongFuMiMa": "Duplicate password",
+  "zhuCe": "register",
+  "zhuCeChengGong": "registered successfully",
+  "zhuanYeBan": "professional edition",
+  "zunJingDeYongHuNinGouMaiDeBanBen": "Dear user! The version you purchased",
+  "qianZhiRenWu": "Pre task",
+  "qingXuanZeSuoShuRenWuFenZu": "Please select the task group to which you belong",
+  "qingXuanZeSuoShuRenWuLieBiao": "Please select the task list to which you belong",
+  "qingXuanZeSuoShuXiangMu": "Please select the project to which you belong",
+  "qingXuanZeXiangMuFuWu": "Please select project service",
+  "suoShuRenWuFenZu": "Task group to which it belongs",
+  "suoShuRenWuLieBiao": "Task List",
+  "tongYiGeZhiHangRenFuWuBuNengXiangTong": "The same executor cannot provide the same service",
+  "xiangMuFuWu": "Project Services",
+  "buShuYuNingDeQuanXianNei": "Not within your permission",
+  "piLiangXiuGaiXiangMuJieDuan": "Batch modification project phase",
+  "piLiangCaoZuo": "Batch operation",
+  "piLiangTianJiaRenWuChanYuRen": "Batch add task participants",
+  "heXiao": "Write off",
+  "heXiaoGongShiShu": "Write off work hours",
+  "heXiaoRen": "Verification personnel",
+  "heXiaoShiJian": "Verification time",
+  "heXiaoYanYing": "Reason for verification",
+  "heXiaoZhuangTai": "Verification status",
+  "huiFu": "recovery",
+  "jiaBanHeXiao": "Overtime verification",
+  "qingJiaJiWeiTianBaoJiShi": "Leave calculation for timely reporting",
+  "qingShuRuHeXiaoYuanYing": "Please enter the reason for verification",
+  "wuXiaoJiaBan": "Invalid overtime",
+  "yiFaFangJIaBanGongShi": "Overtime pay has been paid",
+  "gongJiGongShi": "Total working hours",
+  "queRenZhuanYi": "Confirm transfer",
+  "tiaoShuJu": "Article data",
+  "yiXuanZe": "Selected",
+  "zhuanYIGongShi": "Transfer of working hours",
+  "zhuanYiChengGong": "Transfer successful",
+  "zhuanYiZhi": "Transfer to"
 }

+ 664 - 5
fhKeeper/formulahousekeeper/timesheet/src/i18n/zh.json

@@ -27,9 +27,9 @@
     "basicSystemSettings": "系统基础设置",
     "roleRightsManagement": "角色权限管理",
     "projectFormSettings": "项目表单设置",
-    "budgetReview":"预估工时审核",
-    "gongshitongji":"工时统计表",
-    "caiwushenhe":"财务审核"
+    "budgetReview": "预估工时审核",
+    "gongshitongji": "工时统计表",
+    "caiwushenhe": "财务审核"
   },
   "role": {
     "ordinaryEmployees": "普通员工",
@@ -207,6 +207,7 @@
     "waitForTheProjectReviewer": "待项目审核人",
     "audit": "审核",
     "projectAuditor": "项目审核人",
+    "projectReviwer": "项目复审人",
     "reviewer": "审核人",
     "await": "待",
     "importWaitingForReview": "导入待审核",
@@ -527,7 +528,7 @@
   "taskthatisoverdue": "已超期的任务",
   "yi-ban": "一般",
   "zhong-yao": "重要",
-  "AuditProcess":"审核流程设置",
+  "AuditProcess": "审核流程设置",
   "jin-ji": "紧急",
   "makesuretodeletethesubproject": "确定要删除子项目",
   "ma": "吗?",
@@ -1525,5 +1526,663 @@
   "que-ding-yao-shan-chu-gai-he-tong-ma": "确定要删除该合同吗?",
   "que-ding-yao-shan-chu-gai-wen-jian-ma": "确定要删除该文件吗?",
   "he-tong-guan-li-dao-ru-mo-ban": "合同管理导入模板",
-  "minMaxCheck": "工时下限不得大于上限"
+  "minMaxCheck": "工时下限不得大于上限",
+  "chu-cha-shen-he": "出差审核",
+  "zhu-yao-fu-ze-ren": "(主要负责人)",
+  "zhong-xin-ti-jiao": "重新提交",
+  "bo-hui-le-qing-jia-shen-qing": "驳回了请假申请",
+  "que-ding-yao-che-hui-gai-chu-cha-shen-qing-ma": "确定要撤回该出差申请吗",
+  "zhi-shao-xuan-ze-yi-ge-bu-men-huo-zhe-ren-yuan-zuo-wei-shen-he-ren": "至少选择一个部门或者人员做为审核人",
+  "yi-cun-zai-zhong-fu-bu-men": "已存在重复部门",
+  "yi-cun-zai-zhong-fu-ren-yuan": "已存在重复人员",
+  "qing-shu-ru-guan-jian-ming-cheng": "请输入关键名称",
+  "sou-suo": "搜索",
+  "xia-bi-hui-kuan-ri-qi": "下笔回款日期",
+  "yi-hui-kuan-jin-e": "已回款金额",
+  "yi-hui-kuan-jin-du": "已回款进度",
+  "xia-bi-hui-kuan-jin-e": "下笔回款金额",
+  "hui-kuan-ji-hua": "回款计划",
+  "yi-hui-kuan": "已回款",
+  "shi-fou-yi-hui-kuan": "是否已回款",
+  "hui-kuan-ri-qi": "回款日期",
+  "hui-kuan-jin-e": "回款金额",
+  "wei-hui-kuan": "未回款",
+  "he-tong-lei-xing-zui-duo-zhi-neng-chuang-jian-20-ge": "合同类型最多只能创建20个",
+  "que-ren-shen-he-tong-guo-ma-tong-guo-hou-he-tong-ji-ben-xin-xi-wu-fa-xiu-gai": "确认审核通过吗,通过后合同基本信息无法修改",
+  "hui-kuan-ri-qi-bu-neng-wei-kong": "回款日期不能为空",
+  "hui-kuan-jinebu-neng-wei-0": "回款金额不能为0",
+  "zong-hui-kuan-jinebu-de-da-yu-he-tong-jin-e": "总回款金额不得大于合同金额",
+  "ziXiangMuGongShiChengBenBiao": "子项目工时成本表",
+  "renWuZhongQiBiao": "任务重启表",
+  "fteBaoBiao": "FTE报表",
+  "youXiaoGongShiShuaiBiao": "有效工时率表",
+  "xiangMuFenLeiGongShiZhanBiBiao": "项目分类工时占比表",
+  "fenLeiGongShiMingXiBiao": "分类工时明细表",
+  "yuanGongXiangMuJinDuBiao": "员工项目进度表",
+  "fenZuHaoYongJinDuBiao": "分组耗用进度表",
+  "xiangMuHaoYongJinDuBiao": "项目耗用进度表",
+  "yuanGongRenWuJinDuBiao": "员工任务进度表",
+  "xiangMuYuGuGongShiBiao": "项目预估工时表",
+  "yuanGongRenWuWanChengQingKuangBiao": "员工任务完成情况表",
+  "qingXuanZeZiZhuXiangMuLeiBie": "请选择自主项目类别",
+  "qingXuanZeYuanGongLeiXing": "请选择员工类型",
+  "quanBuBuZu": "全部补足",
+  "sheZhiYuJing": "设置预警",
+  "shiJiChengBen": "实际成本",
+  "fenZuYuGuGongShiH": "分组预估工时(h)",
+  "fenZuShiJiGongShiH": "分组实际工时(h)",
+  "yiHuiKuanLiRun": "已回款利润",
+  "yiHuiKuanLiRunShuai": "已回款利润率",
+  "tYihuikuanlirun": "$t('yiHuiKuanLiRun')",
+  "heTongLiRun": "合同利润",
+  "heTongLiRunShuai": "合同利润率",
+  "buZuGongShi": "补足工时",
+  "fuXiangMuBianHao": "父项目编号",
+  "fuXiangMuMingCheng": "父项目名称",
+  "ziXiangMuMingCheng": "子项目名称",
+  "ziXiangMuGongShi": "子项目工时",
+  "ziXiangMuChengBen": "子项目成本",
+  "zhongQiYuanYin": "重启原因",
+  "zeRenRen": "责任人",
+  "zhongQiShiJian": "重启时间",
+  "renMing": "人名",
+  "fteGongShiDangYueGongShiJiShu": "FTE(工时/当月工时基数)",
+  "fteGongShiGuDingGongShiJiShu_163125": "FTE(工时/固定工时基数(163.125))",
+  "shiBaoGongShiXiaoShi": "实报工时(小时)",
+  "yingGongShiXiaoShi": "应工时(小时)",
+  "zaiZhiRenShu": "在职人数",
+  "yingBaoGongShiTianShu": "应报工时天数",
+  "riBiaoZhunGongShi": "日标准工时",
+  "yingBaoGongShi": "应报工时",
+  "youXiaoGongShiShuai": "有效工时率",
+  "yuanGongLeiXing": "员工类型",
+  "xiangMuHao": "项目号",
+  "shengYuGongShiH": "剩余工时(h)",
+  "fuZeBuMen": "负责部门",
+  "jiHuaGongShiCaiWu": "计划工时(财务)",
+  "shiJiGongShiChengBen": "实际工时成本",
+  "zengBuGongShiH": "增补工时(h)",
+  "zhengChangGongShiH": "正常工时(h)",
+  "jiaBanGongShiH": "加班工时(h)",
+  "heJiGongShiH": "合计工时(h)",
+  "heJiGongShiChengBen": "合计工时成本",
+  "gongShiHaoYongShuai": "工时耗用率",
+  "fenPeiGongShiH": "分配工时(h)",
+  "yiXiaoHaoGongShiH": "已消耗工时(h)",
+  "yiXiaoHaoGongShiChengBen": "已消耗工时成本(¥)",
+  "fuZeZuChang": "负责组长",
+  "canYuYuanGong": "参与员工",
+  "xiangMuRenWu": "项目任务",
+  "jiHuaGongShiH": "计划工时(h)",
+  "xiaoHaoGongShiH": "消耗工时(h)",
+  "xiangMuKaiShiShiJian": "项目开始时间",
+  "xiangMuJieZhiShiJian": "项目截止时间",
+  "yuGuGongShi": "预估工时",
+  "yuanGong": "员工",
+  "renWuZongShuLiang": "任务总数量",
+  "yiWanChengShuLiang": "已完成数量",
+  "weiWanChengShuLiang": "未完成数量",
+  "weiWanChengShuai": "未完成率",
+  "anShiWanChengShuLiang": "按时完成数量",
+  "yanChiWanChengShuLiang": "延迟完成数量",
+  "anShiWanChengShuai": "按时完成率",
+  "tiXingFenLei": "提醒分类:",
+  "qingXuanZeTiXingFenLei": "请选择提醒分类",
+  "xuanZeGuanXi": "选择关系:",
+  "diYu": "低于",
+  "gaoYu": "高于",
+  "sheZhiZhanBi": "设置占比:",
+  "quXiao": "取 消",
+  "queDing": "确 定",
+  "yuanGongRenWuShuJu": "员工任务数据",
+  "dangQianZhuangTai": "当前状态",
+  "wanChengRiQi": "完成日期",
+  "fuWuXiangMu": "服务项目",
+  "feiYongBaoXiaoMingXiBiaoXlsx": "费用报销明细表.xlsx",
+  "jiDuXlsx": "季度).xlsx",
+  "weiFenLei": "未分类",
+  "baoJiaXiangMu": "报价项目",
+  "shouHouBaoJiaXiangMu": "售后报价项目",
+  "yanFaXiangMu": "研发项目",
+  "keHuLieBiaoXlsx": "客户列表.xlsx",
+  "jinRiGongZuoShiChang": "今日工作时长:",
+  "gongZuoShiChangFenPei": "工作时长分配",
+  "yanFa": "研发",
+  "shangWang": "上网",
+  "wenDang": "文档",
+  "sheJi": "设计",
+  "kanXiaoShuo": "看小说",
+  "yingShiYuLe": "影视娱乐",
+  "liaoTian": "聊天",
+  "qiTaGongZuo": "其他工作",
+  "shiChangDanWeiH": "时长(单位:h)",
+  "meiGong": "美工",
+  "yunYing": "运营",
+  "tingYinLe": "听音乐",
+  "weiZhi": "未知",
+  "yuanGongAnZhuangKeHuDuanLingDaoJiKeChaKanGongZuoZhuoMianYuanChengJianGuan": "(员工安装客户端,领导即可查看工作桌面远程监管)",
+  "keHuDuanXiaZai": "客户端下载",
+  "jinRiZanWuJieTuDianJiChaKanJinQi": "今日暂无截图,点击查看近期",
+  "suoYouJieTu": "所有截图",
+  "feiGongZuoQingKuangTongJi": "非工作情况统计",
+  "hangWei": "行为",
+  "tuPian": "图片",
+  "feiYongZhuLeiXingGuanLi": "费用主类型管理",
+  "feiYongZhuLeiXing": "费用主类型",
+  "faFangZhuangTai": "发放状态",
+  "weiFaFang": "未发放",
+  "yiFaFang": "已发放",
+  "danJuDaoChu": "单据导出",
+  "faFang": "发放",
+  "quXiaoFaFang": "取消发放",
+  "daiDiYiShenHeRenShenHe": "待第一审核人审核",
+  "daiDiErShenHeRenShenHe": "待第二审核人审核",
+  "shenHeWanCheng": "审核完成",
+  "zhiFuFangShi": "支付方式",
+  "feiYongLeiXingDaLeiGuanLi": "费用类型大类管理",
+  "duiYingChengBenXiang": "对应成本项",
+  "tianBaoShiJian": "填报时间",
+  "zhang": "张",
+  "feiYongLeiXing": "费用类型:",
+  "xiangMuShenHeZhuangTai": "项目(审核状态)",
+  "feiYongJineHanShui": "费用金额(含税)",
+  "daYin": "打 印",
+  "guanBi": "关 闭",
+  "faFangFangShi": "发放方式",
+  "qingXuanZeZhiFuFangShi": "请选择支付方式",
+  "qingTianXieWanZhengFeiYongJinE": "请填写完整费用金额",
+  "qingXuanZeDiYiShenHeRen": "请选择第一审核人",
+  "qingXuanZeDiErShenHeRen": "请选择第二审核人",
+  "feiYongJinE": "费用金额",
+  "qingTianXieWanZheng": "请填写完整",
+  "benYeJineheJi": "本页金额合计",
+  "feiYongBaoXiaoDanJuLieBiao": "费用报销单据列表",
+  "cunZaiDaiShenHeHuoYiBoHuiDeDanJu": "存在待审核或已驳回的单据",
+  "qingXuanZeWeiFaFangDeDanJu": "请选择未发放的单据",
+  "qingXuanZeYiFaFangDeDanJu": "请选择已发放的单据",
+  "nianYue": "年月:",
+  "shenHeZhuangTai": "审核状态:",
+  "riBaoNianYue": "日报年月",
+  "weiShenHe": "未审核",
+  "yiShenHe": "已审核",
+  "caiWuShenHeTiShi": "财务审核提示",
+  "ninQueDingYaoShenHeTongGuo": "您确定要审核通过",
+  "yueDeGongShiBaoGaoMa": "月的工时报告吗?",
+  "shenHeChengGong": "审核成功!",
+  "qingJiaShenHe": "请假审核",
+  "chaKanYuanYin": "查看原因",
+  "yiCheHui": "已撤回",
+  "boHuiLeQingJiaShenQing": "驳回了请假申请",
+  "qingJiaDan": "请假单",
+  "shengYuJiaQi": "剩余假期",
+  "queDingYaoCheHuiGaiQingJiaShenQingMa": "确定要撤回该请假申请吗",
+  "gongSiLieBiao": "公司列表",
+  "gongSiMingCheng": "公司名称",
+  "zhuCeShiJian": "注册时间",
+  "lianXiFangShi": "联系方式",
+  "shiFouLianXi": "是否联系",
+  "yiLianXi": "已联系",
+  "weiLianXi": "未联系",
+  "keHuFanKui": "客户反馈",
+  "tianXieFanKui": "填写反馈",
+  "fanKuiJieGuo": "反馈结果",
+  "tiJiao": "提 交",
+  "qingShuRuKeHuFanKui": "请输入客户反馈",
+  "tianXieChengGong": "填写成功",
+  "gongChengZhuanYeLieBiao": "工程专业列表",
+  "qingShuRuZhuanYeMingChengGuanJianZi": "请输入专业名称关键字",
+  "xinZengZhuanYe": "新增专业",
+  "qingShuRuZhuanYeMingCheng": "请输入专业名称",
+  "xiuGaiZhuanYe": "修改专业",
+  "queDingYaoZhuanYe": "确定要专业",
+  "shanChuZhuanYe": "删除专业",
+  "xiangMu": "项目:",
+  "shenHeRen": "审核人:",
+  "qingXuanZeZhuangTai": "请选择状态",
+  "tiJiaoRen": "提交人",
+  "tiJiaoShiJian": "提交时间",
+  "bianGengQianYuGuGongShi": "变更前预估工时",
+  "renTian": "人天",
+  "yuGuGongShiBianGeng": "预估工时变更",
+  "bianGengHouYuGuGongShi": "变更后预估工时",
+  "bianGengLiYou": "变更理由",
+  "boHuiLiYou": "驳回理由",
+  "qingShuRuBoHuiLiYou": "请输入驳回理由",
+  "quXiaoBoHui": "取消驳回",
+  "daoChuNeiRon": "导出内容",
+  "gongShiHeChengBen": "工时和成本",
+  "jingGongShi": "仅工时",
+  "jingChenBen": "仅成本",
+  "gongHhiZhanbiXmu": "含项目工时占比",
+  "hanZhuXiangMu": "含主项目",
+  "chenBenTongJi": "成本统计",
+  "liMian": "里面",
+  "waiMian": "外面",
+  "riQiQuJian": "日期区间:",
+  "gongShiChengBen": "工时成本",
+  "gongShiHeJi": "工时合计",
+  "feiYongBaoXiaoChengBen": "费用报销成本",
+  "baoXiaoHeJi": "报销合计",
+  "buMenChengBen": "部门成本:",
+  "gongShi": "工时 :",
+  "xiangMuMingCheng": "项目名称:",
+  "gongZuoChengBen": "工作成本 :",
+  "moRenWenJianJia": "默认文件夹",
+  "ziDingYiMingCheng": "自定义名称",
+  "tongBuXiuGaiQiTaXiangMuZhongDeTongMingWenJianJia": "同步修改其他项目中的同名文件夹",
+  "bianJiMoRenMoBan": "编辑默认模板",
+  "xinZengJieDian": "新增节点",
+  "qingShuRuJieDianMingCheng": "请输入节点名称",
+  "queDingShanChu": "确定删除",
+  "moBanMa": "模板吗",
+  "jieDian": "节点",
+  "jianCeDaoYou": "检测到有",
+  "mingYiTianGongShiRenYuanZaiXinZiBiaoZhongWuJiLuBuCanYuChengBenFenTan": "名已填工时人员在薪资表中无记录,不参与成本分摊",
+  "shangChuan": "上传",
+  "wuXinZiRenYuanLieBiao": "无薪资人员列表",
+  "yiShangRenYuanDangYueYiTianXieGongShiQingDaoRuTaMenDeXinZi": "*以上人员当月已填写工时,请导入他们的薪资。",
+  "quanBuYiTianBaoXiangMu": "全部已填报项目",
+  "xuanZeBuFenXiangMu": "选择部分项目",
+  "paiChuBuFenXiangMu": "排除部分项目",
+  "yiYue": "一月",
+  "erYue": "二月",
+  "sanYue": "三月",
+  "siYue": "四月",
+  "wuYue": "五月",
+  "liuYue": "六月",
+  "qiYue": "七月",
+  "baYue": "八月",
+  "thisTWuyue": "this.$t('wuYue')",
+  "jiuYue": "九月",
+  "shiYue": "十月",
+  "shiYiYue": "十一月",
+  "shiErYue": "十二月",
+  "1Yue": "1月",
+  "2Yue": "2月",
+  "3Yue": "3月",
+  "4Yue": "4月",
+  "5Yue": "5月",
+  "6Yue": "6月",
+  "7Yue": "7月",
+  "8Yue": "8月",
+  "9Yue": "9月",
+  "10Yue": "10月",
+  "11Yue": "11月",
+  "12Yue": "12月",
+  "xingQiRi": "星期日",
+  "xingQiYi": "星期一",
+  "xingQiEr": "星期二",
+  "xingQiSan": "星期三",
+  "xingQiSi": "星期四",
+  "xingQiWu": "星期五",
+  "xingQiLiu": "星期六",
+  "ri": "日",
+  "jinTian": "今天",
+  "zhou": "周",
+  "xinJianRiCheng": "新建日程",
+  "xiangXi": "详细",
+  "qingQueRenShiFouCheXiaoXiuGai": "请确认是否撤销修改!",
+  "shiFouShanChuRiCheng": "是否删除日程?",
+  "shiJianFanWei": "时间范围",
+  "renWuMing": "任务名",
+  "chiXuShiJian": "持续时间",
+  "guanLian": "关联",
+  "jiangBeiShanChu": "将被删除",
+  "kaiShi": "(开始)",
+  "jieShu": "(结束)",
+  "fenZhong": "分钟",
+  "nian": "年",
+  "anRenYuanChaKan": "按人员查看",
+  "shiJiYuGuGongShi": "实际/预估工时:",
+  "jiHuaJieShuRiQi": "计划结束日期",
+  "shengYuYuGuGongShi": "剩余预估工时",
+  "piLiangZengJiaRenWuFenZu": "批量增加任务分组",
+  "piLiangSheZhiFenZuFuZeRen": "批量设置分组负责人",
+  "riBaoChaoSongRen": "日报抄送人",
+  "qingXuanZeChaoSongRen": "请选择抄送人",
+  "xiangMuRenTian": "项目人天",
+  "renTianYuGuGongShi": "人天(预估工时:",
+  "genJuXiTongJiChuSheZhiMeiRiZhengChangGongZuoShiChangJiSuan_1RenTianWeiYiGeMeiRiZhengChangGongZuoShiChang": "根据系统基础设置每日正常工作时长计算,1人天为一个每日正常工作时长",
+  "guanKongKaiShiRiQi": "管控开始日期",
+  "congGaiRiQiQiTianBaoGongShiKaiShiZhanYongYuSuanRenTianGongShi": "从该日期起,填报工时开始占用预算人天工时",
+  "fuZhiDaoQiTaXiangMu": "复制到其他项目",
+  "xuanZeYaoFuZhiDaoDeMuBiaoXiangMu": "选择要复制到的目标项目",
+  "xiangMuYuGuGongShiPeiZhi": "项目预估工时配置",
+  "yuGuGongShiShiFouBiTian": "预估工时是否必填",
+  "feiBiTian": "非必填",
+  "gongShiXiTongChuangJianDeXiangMuBiTian": "工时系统创建的项目必填",
+  "gongShiXiTongHeWaiBuTongBuDeXiangMuDuBiTian": "工时系统和外部同步的项目都必填",
+  "xiangMuGongShiShengYuTiXingBaiFenBi": "项目工时剩余提醒百分比",
+  "xiangMuGongShiBuZuShi": "项目工时不足时",
+  "jinZhiTianBao": "禁止填报",
+  "keYiTianBaoJinTiXing": "可以填报,仅提醒",
+  "fenZuGongShiShengYuTiXingBaiFenBi": "分组工时剩余提醒百分比",
+  "fenZuGongShiBuZuShi": "分组工时不足时",
+  "xiangMuShenHeRenShenHe": "项目审核人审核",
+  "xiangMuSuoShuBuFuZeRenShenHe": "项目所属BU负责人审核",
+  "zhiNengFenGongSheZhi": "职能分工设置",
+  "gongShiLeiXing": "工时类型",
+  "gongZuoZhiZe": "工作职责",
+  "gongZuoNeiRong": "工作内容",
+  "tianJiaYiHang": "添加一行",
+  "piLiangSheZhiRenWuFenZuFuZeRen": "批量设置任务分组负责人",
+  "fenZuMingCheng": "分组名称:",
+  "fenZuFuZeRen": "分组负责人:",
+  "xiangMuFuWuTongBu": "项目服务同步",
+  "yiTongBuXiangMu": "已同步项目",
+  "weiTongBuXiangMu": "未同步项目",
+  "xiaZaiDuoXiangMuRenWuMoBan": "下载多项目任务模板",
+  "qingXuanZeSuoShuBuMen": "请选择所属部门",
+  "xiangMuGongShi": "项目工时",
+  "feiXiangMuGongShi": "非项目工时",
+  "qingXuanZeJpgHuoJpegWenJian": "请选择.jpg或.jpeg文件",
+  "qingTianXieFenZuMingCheng": "请填写分组名称",
+  "qingXuanZeFenZuFuZeRen": "请选择分组负责人",
+  "xiangMuDaoChuZhongQingShaoHou": "项目导出中、请稍后...",
+  "queRenTongBuXiangMuShuJu": "确认同步项目数据?",
+  "zhengZaiTongBuZhongQingNaiXinDengDai": "正在同步中,请耐心等待。",
+  "xiangMuTongBuChengGong": "项目同步成功",
+  "yuGuGongShiBuNengWei_0": "预估工时不能为0",
+  "kaiQiChengGong": "开启成功",
+  "guanBiChengGong": "关闭成功",
+  "ciCaoZuoJiangYongJiuShanChuGaiWenJianShiFouJiXu": "此操作将永久删除该文件, 是否继续?",
+  "qingTianXieGongZuoNeiRong": "请填写工作内容",
+  "tianJiaBiaoDanZiDuan": "添加表单字段",
+  "wenBen": "文本",
+  "bianJiBiaoDanZiDuan": "编辑表单字段",
+  "qingShuRuZiDingYiMingCheng": "请输入自定义名称",
+  "zuiDuoZhiNengCunZaiShiGeZiDingYiZiDuan": "最多只能存在十个自定义字段",
+  "tianJiaShiBai": "添加失败:",
+  "bianJiShiBai": "编辑失败:",
+  "shanChuShiBai": "删除失败:",
+  "ruXuXiuGaiQingXianLianXiGuanLiYuan": "如需修改,请先联系管理员",
+  "yinCangYiWanChengRenWu": "隐藏已完成任务",
+  "qingShuShuRuGuanJianZiGuoLv": "请输输入关键字过滤",
+  "sheZhiFenZuYuGuGongShi": "设置分组预估工时",
+  "yuGuGongShiRenTian": "预估工时(人天)",
+  "yuGuGongShiXiaoShi": "预估工时(小时)",
+  "dangQianXiangMuYuGuGongShiWei": "当前项目预估工时为:",
+  "yuanYuGuGongShi": "原预估工时",
+  "yuGuGongShiXiuGai": "预估工时修改",
+  "qingShuRuYuGuGongShi": "请输入预估工时",
+  "shiFouYiChuCiWenJian": "是否移除此文件?",
+  "qingShuRuBianGengLiYou": "请输入变更理由",
+  "caoZuoJiLu": "操作记录",
+  "leRiBao": "了日报",
+  "liXiangDaoRu": "立项导入",
+  "liXiangDaoRuMoBanXlsx": "立项导入模板.xlsx",
+  "liXiangDaoRuJieGuo": "立项导入结果",
+  "queDingYaoShanChuLiXiang": "确定要删除立项",
+  "shanChuLiXiang": "删除立项",
+  "liXiangShuJu": "立项数据",
+  "liXiangDaoChuXlsx": "立项导出.xlsx",
+  "jiaBanShiChangXiaoYan": "加班时长校验",
+  "gongZuoRiTianXieJiaBanShiChangBuDeChaoGuoZongGongZuoShiChangZhengChangGongZuoShiChang": "工作日填写加班时长不得超过总工作时长-正常工作时长",
+  "meiYue": "每月",
+  "hao": "号",
+  "mei": "每",
+  "tiXing": "提醒",
+  "keYong_0BiaoShiLouTianRiQiLiRu_0JiangBeiTiHuanWei_05240525": "(可用{0}表示漏填日期,例如:{0}将被替换为05/24,05/25。)",
+  "keYong_0BiaoShiDaiShenHeTiaoShuLiRu_0JiangBeiTiHuanWei_10": "(可用{0}表示待审核条数,例如:{0}将被替换为10。)",
+  "eWaiGongZuoRiSheZhi": "额外工作日设置:",
+  "qiTaFaDingJieRi": "其他法定节日",
+  "guanBiRiBaoTianBaoGongNeng": "关闭日报填报功能",
+  "feiGongZuoRiHanZhouMoWeiFaDingGongZuoRiJinZhiTianBao": "非工作日(含周末为法定工作日)禁止填报",
+  "piLiangDaiTianHanZhouMo": "批量/代填含周末",
+  "yuCiYue": "于次月",
+  "haoHanQianTianBao": "号(含)前填报。",
+  "riBaoShenHeMoShi": "日报审核模式",
+  "ruXuXiuGaiWeiQiTaShenHeMoShiQingLianXiKeFu": "如需修改为其他审核模式,请联系客服",
+  "xiangMuChaoQiHouBuKeTianBao": "项目超期后不可填报",
+  "kaiQiHouChaoGuoXiangMuJiHuaJieShuRiQiDeRiBaoJiangBuKeTianBao": "开启后超过项目计划结束日期的日报将不可填报",
+  "tianBaoShiKeDuoXuan": "填报时可多选",
+  "tianBaoRiBaoShiFouYinCangJieDuan": "填报日报是否隐藏阶段",
+  "tianBaoRiBaoShiFouYinCangRenWu": "填报日报是否隐藏任务",
+  "renWuShiFouBiTian": "任务是否必填",
+  "teShuJieJiaRiLieBiao": "特殊节假日列表",
+  "youXiaoFanWei": "有效范围",
+  "youXiaoBuMen": "有效部门",
+  "quanGongSi": "全公司",
+  "buFenChengYuan": "部分成员",
+  "youXiaoRenYuan": "有效人员",
+  "teShuJieJiaRiSheZhi": "特殊节假日设置",
+  "qingShuRuMingZiSouSuo": "请输入名字搜索",
+  "fenZuFuZeRenShenHe": "分组负责人审核",
+  "xianFenZuFuZeRenShenHeZaiXiangMuJingLiShenHe": "先分组负责人审核再项目经理审核",
+  "yuanGongZiYouXuanZeShenPiRen": "员工自由选择审批人",
+  "xiangMuSuoShuBuShenHe": "项目所属BU审核",
+  "zhiShuShenHeRenHuoBuMenFuZeRenShenHe": "直属审核人或部门负责人审核",
+  "zhiShuHuoBuMenFuZeRenShenHeXiangMuRiBaoShenHeRenShenHe": "直属或部门负责人审核->项目日报审核人审核",
+  "buMenHeXiangMuRiBaoShenHeRenBingHangShenHe": "部门和项目日报审核人并行审核",
+  "anZhaoQiYeQingKuangTiaoZheng": "按照企业情况调整",
+  "qingXianDianJiXiTongJiChuSheZhi": "请先点击系统基础设置",
+  "tiaoGuo": "跳过",
+  "queDingShanChuZheTiaoShuJuMa": "确定删除这条数据吗?",
+  "xinJianRenWu": "新建任务",
+  "zhongQiRenWu": "重启任务",
+  "qingXuanZeZeRenRen": "请选择责任人",
+  "faQiHuiYi": "发起会议",
+  "huiYiKaiShiShiJian": "会议开始时间",
+  "xuanZeRiQiShiJian": "选择日期时间",
+  "huiYiJieShuShiJian": "会议结束时间",
+  "chengGongFaQiHuiYi": "成功发起会议",
+  "daiBanRenWuDaoChuXlsx": "待办任务导出.xlsx",
+  "tiaoZhengBuMen": "调整部门",
+  "xiuZhengGongShiSuoShuBuMen": "修正工时所属部门",
+  "piLiangQiYongYuanGong": "批量启用员工",
+  "xiuZhengGongShi": "修正工时",
+  "quanBuGongShi": "全部工时",
+  "buFenGongShi": "部分工时",
+  "tuiSongZhiSap": "推送至SAP",
+  "keTianBaoBuMen": "可填报部门",
+  "shenHeCengJi": "审核层级",
+  "liangCengShenHe": "两层审核",
+  "yiCengShenHe": "一层审核",
+  "weiSheZhiShiYouSuoShuBuMenFuZeRenShenHe": "未设置时由所属部门负责人审核",
+  "liZhiRiQi": "离职日期",
+  "queDingShanChuGaiYuanGongMa": "确定删除该员工吗?",
+  "jiangGaiYuanGongDeGongShiShuJuCanYuDeXiangMuYuRenWuZhuanYiZhi": "将该员工的工时数据、参与的项目与任务转移 至",
+  "renYuanSuoZaiBuMenYuDingDingTongXunLuBaoChiYiZhi": "人员所在部门与钉钉通讯录保持一致",
+  "tongBuRiZhi": "同步日志",
+  "caoZuoShiJian": "操作时间",
+  "cuoWuXinXi": "错误信息",
+  "tongBuQianQingLianXiQiYeWeiXinGuanLiYuanJianChaYingYongShouQuanDeKeJianFanWei": "同步前请联系企业微信管理员检查应用授权的可见范围",
+  "luJingGuanLiQiYeYingYongGuanLiGongShiGuanJiaKeJianFanWei": "路径:管理企业-应用管理-工时管家-可见范围",
+  "keJianFanWeiSheZhi": "可见范围设置",
+  "zhuanYiDao": "转移到",
+  "shiFouShanChuGaiJiLu": "是否删除该记录?",
+  "keZhuanRang": "可转让",
+  "qingXuanZeJieShouRen": "请选择接收人",
+  "tongBuZhong": "同步中",
+  "dangQianYuanGongYouDaiShenHeRiBaoQueRenTingYongBingBoHuiRiBaoMa": "当前员工有待审核日报,确认停用并驳回日报吗?",
+  "yiQuXiao": "已取消",
+  "gaiYuanGong": "该员工",
+  "queDingYaoShanChuGaiBuMenMa": "确定要删除该部门吗?",
+  "tiaoYongRenShenFenBuFuHe": "调用人身份不符合",
+  "yingYongXinXiHuoQuShiBai": "应用信息获取失败",
+  "yingYongLeiXingBuFuHeYaoQiu": "应用类型不符合要求",
+  "qiTaCuoWu": "其它错误",
+  "caoZuoChengGong": "操作成功:",
+  "caoZuoChengGong-0": "操作成功!",
+  "dangQianBuMenCunZaiDaiShenHeBaoGao": "当前部门存在待审核报告",
+  "dangQianBuMenCunZaiDaiShenHeBaoGaoShiFouQuanBuZhuanWeiTongGuo": "当前部门存在待审核报告, 是否全部转为通过?",
+  "tuiSongGongShi": "推送工时",
+  "gongShiTuiSongRiZhi": "工时推送日志",
+  "riBaoShenHeXiuGai": "日报审核修改",
+  "fuWu": "服务",
+  "jiaZaiGengDuoRiBao": "加载更多日报",
+  "tuiSongShiJian": "推送时间",
+  "tTuisongshijian": "$t('tuiSongShiJian')",
+  "tuiSongMingCheng": "推送名称",
+  "tuiSongFangShi": "推送方式",
+  "tuiSongJieGuo": "推送结果",
+  "shiBai": "失败",
+  "zhiNengTianBao": "智能填报",
+  "tianBaoBuMen": "填报部门",
+  "jiaoSeXuanZe": "角色选择",
+  "qingXuanZeFuWu": "请选择服务",
+  "tuPianShangChuan": "图片上传",
+  "heJiGongShi": "合计工时",
+  "buKeChaoQianTianBao": "不可超前填报",
+  "zhengZaiWei": "*正在为",
+  "daiTian": "代填",
+  "renWuLiChengBei": "任务 / 里程碑",
+  "daoChuFangShi": "导出方式",
+  "wanZhengDaoChu": "完整导出",
+  "jingJianDaoChu": "精简导出",
+  "jingJianRiBaoBuHanGongZuoShiXiangHeShenPiXinXiShuJuLiangGengXiaoDaoChuGengKuai": "精简日报不含工作事项和审批信息,数据量更小导出更快。",
+  "daoChuRiBaoShenHeJiLuShuJu": "导出日报审核记录数据",
+  "daoRuRiBaoShenHeJiLuXiuGaiShuJu": "导入日报审核记录修改数据",
+  "yiBoHuiLouTian": "已驳回/漏填",
+  "weiTiJiao": "未提交",
+  "weiTiJiaoRenYuanLieBiao": "未提交人员列表",
+  "gongShiYiChangMingXi": "工时异常明细",
+  "shiFouYiChang": "是否异常",
+  "bianGengTiXing": "变更提醒",
+  "tianBaoGongShi": "填报工时",
+  "kaoQinGongShi": "考勤工时",
+  "cuiBan": "催办",
+  "quXiaoYiChang": "取消异常",
+  "xiuGaiDaoRuJiLu": "修改导入记录",
+  "xiaZaiTianBaoGongShiZhanBiBiao": "下载填报工时占比表",
+  "daoRuKaoQinShiChang": "导入考勤时长",
+  "piLiangShanChuRiBao": "批量删除日报",
+  "piLiangShenHeRiBao": "批量审核日报",
+  "qingXuanZeYuanGong": "请选择员工",
+  "kaiShiShanChu": "开始删除",
+  "shenPiTongGuo": "审批通过",
+  "xuanZeDaoRuRenYuan": "选择导入人员:",
+  "queRen": "确认",
+  "daoChuYuanGongTianBaoGongShiZhanBi": "导出员工填报工时占比",
+  "qingXuanZeNianYue": "请选择年月:",
+  "ninQueDingYaoShanChuGaiTiaoJiLuMa": "您确定要删除该条记录吗?",
+  "qingXuanZeRiQiFanWei": "请选择日期范围",
+  "ninQueDingYaoShenHeTongGuoGaiShiJianDuanNeiQuanBuDeRiBaoMa": "您确定要审核通过该时间段内全部的日报吗?",
+  "qingXuanZeBuMenHuoRenYuan": "请选择部门或人员",
+  "ninQueDingYaoShanChuGaiShiJianDuanNeiDeRiBaoMaShanChuHouJiangBuKeHuiFu": "您确定要删除该时间段内的日报吗,删除后将不可恢复",
+  "zuiJinXuanZeXiangMu": "最近选择项目",
+  "daoRuKaoQinShiChangChengGong": "导入考勤时长成功",
+  "chengGongDaoRu": "成功导入",
+  "queRenTuiSongDangQianGongShi": "确认推送当前工时?",
+  "queRenTuiSong": "确认推送",
+  "deGongShi": "的工时?",
+  "zhengZaiTuiSongZhongQingNaiXinDengDai": "正在推送中,请耐心等待。",
+  "yueDeGongShi": "月的工时?",
+  "tuiSongChengGong": "推送成功!",
+  "meiCiJinZhiChiDaiTianYiGeRen": "每次仅支持代填一个人",
+  "qingXuanZeDaiTianDeYuanGong": "请选择代填的员工",
+  "meiYouGengDuoShuJuLe": "没有更多数据了",
+  "zhengZaiDaoRuXiuGaiZhongQingNaiXinDengDai": "正在导入修改中,请耐心等待。",
+  "daiShenHeZhuangTaiBuKeXiuGaiQingFanHuiDaoChaKanRiBaoZhongXianCheHui": "待审核状态不可修改,请返回到查看日报中先撤回",
+  "yiTongGuoZhuangTaiBuKeXiuGai": "已通过状态不可修改",
+  "renWuFenZuHeJieDuanBiTianQingJianCha": "任务分组和阶段必填,请检查",
+  "renWuFenZuBiTianQingJianCha": "任务分组必填,请检查",
+  "ziXiangMuBiTianQingJianCha": "子项目必填,请检查",
+  "huLveBingTiJiao": "忽略并提交",
+  "qingTianXieRenWuFenZu": "请填写任务分组",
+  "kaiShiRiQiBuNengDaYuJieShuRiQi": "开始日期不能大于结束日期",
+  "dangRiGongShiBuZu": "当日工时不足",
+  "xiaoShiShiFouQueDingTiJiao": "小时,是否确定提交?",
+  "jiaoSeBiTianQingJianCha": "角色必填,请检查",
+  "gongZuoZhiZeBiTianQingJianCha": "工作职责必填,请检查",
+  "gongZuoNeiRongBiTianQingJianCha": "工作内容必填,请检查",
+  "qingXuanZeRenWuLiChengBei": "请选择 任务/里程碑",
+  "xiangMuXiaDeRenWuFenZu": "项目下的任务分组",
+  "zhongDe": "中的",
+  "shenHeLiuCheng": "审核流程:",
+  "fenZu": "分组",
+  "shiJianXiaoShi": "时间(小时)",
+  "daiShen": "待审",
+  "juJue": "拒绝",
+  "qingShuRuZhouZongJie": "请输入周总结",
+  "zanCun": "暂 存",
+  "tianXieGongShiHeJiFei": "填写工时合计非",
+  "zanCunShiBai": "暂存失败:",
+  "tiJiaoShiBai": "提交失败:",
+  "fenZuWeiSheZhiShenPiRenQingLianXiGaiXiangMuGuanLiRenYuan": "分组未设置审批人,请联系该项目管理人员",
+  "fenZuWeiSheZhiQingLianXiGaiXiangMuGuanLiRenYuan": "分组未设置,请联系该项目管理人员",
+  "feiChangBaoQianNiFangWenDeYeMianBuCunZai": "非常抱歉你访问的页面不存在!!!",
+  "fanHuiShouYe": "返回首页",
+  "ninHaoNinGouMaiDeBanBenYiDaoQi": "您好,您购买的版本已到期!",
+  "qingYongQiYeWeiXinSaoMaTianJiaKeFu": "请用企业微信扫码添加客服",
+  "jiChuBan": "基础版",
+  "zhuanYeBan": "专业版",
+  "qiJianBan": "旗舰版",
+  "jianZhuGongChengBan": "建筑工程版",
+  "zunJingDeYongHuNinGouMaiDeBanBen": "尊敬的用户! 您购买的版本",
+  "ruoXuJiXuShiYongQingQianWangQiYeWeiXinYingYongShiChangXuFeiGeiGuiGongSiDaiLaiBuBianJingQingLiangJie": "若需继续使用请前往企业微信应用市场续费,给贵公司带来不便,敬请谅解!",
+  "yiDaoQi": "已到期",
+  "bangZhuZhongXin": "帮助中心",
+  "saoMaTianJiaQiYeWeiXinKeFu": "扫码添加企业微信客服",
+  "dianJiChaKanCaoZuoShouCe": "点击查看操作手册",
+  "xiuGaiGongSiMingCheng": "修改公司名称",
+  "wanShanGongHao": "完善工号",
+  "wanShanXingMing": "完善姓名",
+  "qingShuRuGongSiMingCheng": "请输入公司名称",
+  "changDuWei_120GeZiFu": "长度为1-20个字符",
+  "qingShuRuGongHao": "请输入工号",
+  "shi": "时",
+  "fen": "分",
+  "miao": "秒",
+  "banBenGuoDiQingShengJi": "版本过低请升级",
+  "huo": "或",
+  "qiYeWeiXinSaoMaDengLu": "企业微信扫码登陆",
+  "zhengZaiJinRuXiTong": "正在进入系统...",
+  "wuQuanFangWenQingLianXiGuanLiYuanWeiNinFenPeiQuanXian": "无权访问,请联系管理员为您分配权限",
+  "shenPi": "审批",
+  "muQianZanWuXiaoXi": "目前暂无消息",
+  "jingGao": "警告",
+  "baoYang": "保养",
+  "zhuCe": "注册",
+  "gongSiMing": "公司名",
+  "yanZhengMa": "验证码",
+  "faSongYanZhengMa": "发送验证码",
+  "sheZhiMiMaChangDuBuDiYu_6Wei": "设置密码,长度不低于6位",
+  "zhongFuMiMa": "重复密码",
+  "xuanZeBanBen": "选择版本:",
+  "gongShiTongJiJiChuBan": "工时统计基础版",
+  "xiangMuGuanLiZhuanYeBan": "项目管理专业版",
+  "qiYeBanGongQiJianBan": "企业办公旗舰版",
+  "gongChengGuanLiZhuanYeBan": "工程管理专业版",
+  "qingShuRuGongSiMing": "请输入公司名",
+  "qingShuRuYanZhengMa": "请输入验证码",
+  "qingSheZhiMiMaChangDuBuDiYu_6Wei": "请设置密码,长度不低于6位",
+  "qingZhongFuShuRuMiMa": "请重复输入密码",
+  "shouJiHaoMaGeShiBuZhengQue": "手机号码格式不正确",
+  "faSongChengGong": "发送成功",
+  "miMaChangDuBuNengShaoYu_6Wei": "密码长度不能少于6位",
+  "liangCiShuRuDeMiMaBuYiZhi": "两次输入的密码不一致",
+  "zhuCeChengGong": "注册成功",
+  "suoShuRenWuFenZu": "所属任务分组",
+  "suoShuRenWuLieBiao": "所属任务列表",
+  "qianZhiRenWu": "前置任务",
+  "xiangMuFuWu": "项目服务",
+  "qingXuanZeXiangMuFuWu": "请选择项目服务",
+  "qingXuanZeSuoShuXiangMu": "请选择所属项目",
+  "qingXuanZeSuoShuRenWuFenZu": "请选择所属任务分组",
+  "qingXuanZeSuoShuRenWuLieBiao": "请选择所属任务列表",
+  "tongYiGeZhiHangRenFuWuBuNengXiangTong": "同一个执行人,服务不能相同",
+  "piLiangXiuGaiXiangMuJieDuan": "批量修改项目阶段",
+  "buShuYuNingDeQuanXianNei": "不属于您的权限内",
+  "piLiangCaoZuo": "批量操作",
+  "piLiangTianJiaRenWuChanYuRen": "批量添加任务参与人",
+  "heXiaoZhuangTai": "核销状态",
+  "heXiaoRen": "核销人",
+  "heXiaoShiJian": "核销时间",
+  "heXiaoYanYing": "核销原因",
+  "huiFu": "恢复",
+  "heXiao": "核销",
+  "qingJiaJiWeiTianBaoJiShi": "请假计为填报及时",
+  "heXiaoGongShiShu": "核销工时数",
+  "jiaBanHeXiao": "加班核销",
+  "qingShuRuHeXiaoYuanYing": "请输入核销原因",
+  "yiFaFangJIaBanGongShi": "已发放加班工资",
+  "wuXiaoJiaBan": "无效加班",
+  "zhuanYIGongShi": "转移工时",
+  "yiXuanZe": "已选择",
+  "tiaoShuJu": "条数据",
+  "gongJiGongShi": "共计工时",
+  "zhuanYiZhi": "转移至",
+  "queRenZhuanYi": "确认转移",
+  "zhuanYiChengGong": "转移成功"
 }

+ 2 - 2
fhKeeper/formulahousekeeper/timesheet/src/views/404.vue

@@ -3,8 +3,8 @@
         <div class="page-img">
             <img src="../assets/image/404.png" />
         </div>
-        <p class="page-container"><b>Error</b> 非常抱歉你访问的页面不存在!!!</p>        <div class="page-button">
-            <el-button type="primary" round @click="back" icon="el-icon-s-promotion">返回首页</el-button>
+        <p class="page-container"><b>Error</b> {{ $t('feiChangBaoQianNiFangWenDeYeMianBuCunZai') }}</p>        <div class="page-button">
+            <el-button type="primary" round @click="back" icon="el-icon-s-promotion">{{ $t('fanHuiShouYe') }}</el-button>
         </div>
     </div>
 </template>

+ 6 - 7
fhKeeper/formulahousekeeper/timesheet/src/views/Expire.vue

@@ -3,17 +3,16 @@
         <div class="expire_par">
             <div class="expire_container">
                 <img class="expire_logo" src="../assets/image/login_logo.png" />
-                <p class="expire_title">工时管家</p>
-                <p class="expire_tips">您好,您购买的版本已到期!</p>
+                <p class="expire_title">{{ $t('workingHoursHousekeeper') }}</p>
+                <p class="expire_tips">{{ $t('ninHaoNinGouMaiDeBanBenYiDaoQi') }}</p>
                 <p class="expire_text">
-                    尊敬的用户! 您购买的版本[{{versionList[versionId]}}] 已到期(到期日期{{expDate}})
-                    ,若需继续使用请前往企业微信应用市场续费,给贵公司带来不便,敬请谅解!
+                    {{ $t('zunJingDeYongHuNinGouMaiDeBanBen') }} [{{versionList[versionId]}}] {{ $t('yiDaoQi') }}({{ $t('time.dueDate') }}{{expDate}})
+                    ,{{ $t('ruoXuJiXuShiYongQingQianWangQiYeWeiXinYingYongShiChangXuFeiGeiGuiGongSiDaiLaiBuBianJingQingLiangJie') }} 
                 </p>
                 <!-- <p class="expire_kf">联系客服</p> -->
                 <div class="expire_service">
                     <p style="color: #333">
-                        请用企业微信扫码添加客服
-                    </p>
+                        {{ $t('qingYongQiYeWeiXinSaoMaTianJiaKeFu') }} </p>
                     <img src="../assets/image/qwcode.png" />
                     <p>
                         <span style="color: #333">QQ:</span
@@ -30,7 +29,7 @@ export default {
     data() {
         return {
           versionId: 0,
-          versionList: ['verson','基础版','专业版','旗舰版','建筑工程版'],
+          versionList: ['verson',this.$t('jiChuBan'),this.$t('zhuanYeBan'),this.$t('qiJianBan'),this.$t('jianZhuGongChengBan')],
           expDate: 'date',
         };
     },

+ 36 - 28
fhKeeper/formulahousekeeper/timesheet/src/views/Home.vue

@@ -36,7 +36,7 @@
                     <span class="el-dropdown-link userinfo-inner">
                         <i class="el-icon-user" style="font-size:18px" ></i>
                         <!-- {{$t('other.customerService')}} -->
-                        帮助中心
+                        {{ $t('bangZhuZhongXin') }} 
                     </span> 
                     <el-dropdown-menu slot="dropdown">
                         <el-dropdown-item >
@@ -49,14 +49,14 @@
                                 src="../assets/image/code.jpg" />
                             </div>
                             <div v-if="isCorpWX">
-                                <div>扫码添加企业微信客服</div>
+                                <div>{{ $t('saoMaTianJiaQiYeWeiXinKeFu') }}</div>
                                 <img
                                 style="width: 153px; height: 153px"
                                 src="../assets/image/qwcode.png" />
                             </div>
                             <div>
                                 <div>
-                                    <el-link type="primary" :underline="false" href="https://www.ttkuaiban.com/download/%E5%B7%A5%E6%97%B6%E7%AE%A1%E5%AE%B6%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E%E4%B9%A6.pdf">点击查看操作手册</el-link>
+                                    <el-link type="primary" :underline="false" href="https://www.ttkuaiban.com/download/%E5%B7%A5%E6%97%B6%E7%AE%A1%E5%AE%B6%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E%E4%B9%A6.pdf">{{ $t('dianJiChaKanCaoZuoShouCe') }}</el-link>
                                 </div>
                             </div>
                         </el-dropdown-item>
@@ -155,7 +155,7 @@
                         <el-menu-item v-if="item.leaf && item.children.length > 0" :index="item.children[0].path" :data-v-step="item.children[0].path">
                             <i :class="item.iconCls"></i> 
                             <!-- {{item.children[0].name}} -->
-                            <span class="bosx" v-if="$t(item.meta.text).length < 16">{{$t(item.meta.text)}}</span>
+                            <span class="bosx" v-if="$t(item.meta.text).length <= 16">{{$t(item.meta.text)}}</span>
                             <el-tooltip class="itemName bosx"  v-if="$t(item.meta.text).length > 16" effect="dark" :content="$t(item.meta.text)" placement="top">
                                 <span>{{$t(item.meta.text)}}</span>
                             </el-tooltip>
@@ -236,43 +236,43 @@
                 </el-dialog>
 
                 <el-dialog
-                    title="修改公司名称"
+                    :title="$t('xiuGaiGongSiMingCheng')"
                     :visible.sync="editCompanyNamedialog"
                     width="30%">
                     <el-form :model="companyForm" :rules="rules" ref="companyForm" label-width="100px" class="demo-ruleForm">
-                        <el-form-item label="公司名称" prop="name">
+                        <el-form-item :label="$t('gongSiMingCheng')" prop="name">
                             <el-input v-model.trim="companyForm.name"></el-input>
                         </el-form-item>
                     </el-form>
                     <span slot="footer" class="dialog-footer">
-                        <el-button @click="editCompanyNamedialog = false">取 消</el-button>
-                        <el-button type="primary" @click="editCompanyName('companyForm')">确 定</el-button>
+                        <el-button @click="editCompanyNamedialog = false">{{ $t('quXiao') }}</el-button>
+                        <el-button type="primary" @click="editCompanyName('companyForm')">{{ $t('queDing') }}</el-button>
                     </span>
                 </el-dialog>
             </section>
         </el-col>
 
         <!-- 完善工号弹窗 -->
-        <el-dialog title="完善工号" :visible.sync="perfectJobNumber" width="500px" :show-close="false">
+        <el-dialog :title="$t('wanShanGongHao')" :visible.sync="perfectJobNumber" width="500px" :show-close="false">
             <el-form :model="perfectForm" :rules="rules" ref="perfectForm" label-width="80px" class="demo-ruleForm">
-                <el-form-item label="工号" prop="jobNumber">
+                <el-form-item :label="$t('Worknumber')" prop="jobNumber">
                     <el-input v-model.trim="perfectForm.jobNumber"></el-input>
                 </el-form-item>
             </el-form>
             <span slot="footer" class="dialog-footer">
-                <el-button type="primary" @click="editPerfectJobNumber('perfectForm')">确 定</el-button>
+                <el-button type="primary" @click="editPerfectJobNumber('perfectForm')">{{ $t('queDing') }}</el-button>
             </span>
         </el-dialog>
 
         <!-- 完善名称弹窗 -->
-        <el-dialog title="完善姓名" :visible.sync="perfectName" width="500px" :show-close="false">
+        <el-dialog :title="$t('wanShanXingMing')" :visible.sync="perfectName" width="500px" :show-close="false">
             <el-form :model="perfectFormName" :rules="rules" ref="perfectFormName" label-width="80px" class="demo-ruleForm">
-                <el-form-item label="姓名" prop="userName">
+                <el-form-item :label="$t('lable.name')" prop="userName">
                     <el-input v-model.trim="perfectFormName.userName"></el-input>
                 </el-form-item>
             </el-form>
             <span slot="footer" class="dialog-footer">
-                <el-button type="primary" @click="editPerfectName('perfectFormName')">确 定</el-button>
+                <el-button type="primary" @click="editPerfectName('perfectFormName')">{{$t('queDing')}}</el-button>
             </span>
         </el-dialog>
     </el-row>
@@ -285,6 +285,7 @@
         inject:['reloads'],
         data() {
             return {
+                textLength: 16,
                 companyForm:{
                     name: '',
                 },
@@ -296,14 +297,14 @@
                 },
                 rules: {
                     name: [
-                        { required: true, message: '请输入公司名称', trigger: 'blur' },
-                        { min: 1, max: 20, message: '长度为1-20个字符', trigger: 'blur' }
+                        { required: true, message: this.$t('qingShuRuGongSiMingCheng'), trigger: 'blur' },
+                        { min: 1, max: 20, message: this.$t('changDuWei_120GeZiFu'), trigger: 'blur' }
                     ],
                     jobNumber: [
-                        { required: true, message: '请输入工号', trigger: 'blur' }
+                        { required: true, message: this.$t('qingShuRuGongHao'), trigger: 'blur' }
                     ],
                     userName: [
-                        { required: true, message: '请输入姓名', trigger: 'blur' }
+                        { required: true, message: this.$t('defaultText.PleaseEnterYourName'), trigger: 'blur' }
                     ]
                 },
                 tourFlg: false,
@@ -359,10 +360,10 @@
                     startTimeout: 1000,   //1秒后执行
                     highlight: true,
                     labels: {
-                        buttonSkip: '跳过',
-                        buttonPrevious: '上一步',
-                        buttonNext: '下一步',
-                        buttonStop: '关闭'
+                        buttonSkip: this.$t('tiaoGuo'),
+                        buttonPrevious: this.$t('btn.previousstep'),
+                        buttonNext: this.$t('btn.nextStep'),
+                        buttonStop: this.$t('Shutdown')
                     }
                 },
                 myCallbacks: {
@@ -642,7 +643,7 @@
                 var h = util.formatDate.cdTime(new Date(new Date().getTime() + this.user.remainingTime), new Date(), 'h');
                 var m = util.formatDate.cdTime(new Date(new Date().getTime() + this.user.remainingTime), new Date(), 'm');
                 var s = util.formatDate.cdTime(new Date(new Date().getTime() + this.user.remainingTime), new Date(), 's');
-                this.remainingTime = d+'天'+h+'时'+m+'分'+s+'秒';
+                this.remainingTime = d+this.$t('time.day')+h+this.$t('shi')+m+this.$t('fen')+s+this.$t('miao');
             },
 
             // 加载消息
@@ -825,7 +826,7 @@
                                             fail: function (res) {
                                                 console.log('查看错误信息', res)
                                                 if (res.errMsg.indexOf('function not exist') > -1) {
-                                                    alert('版本过低请升级')
+                                                    alert(that.$t('banBenGuoDiQingShengJi'))
                                                 }
                                             },
                                         })
@@ -833,7 +834,7 @@
                                 }, (error) => {
                                     console.log('查看错误信息' + res)
                                     if (error.errMsg.indexOf('function not exist') > -1) {
-                                        alert('版本过低请升级')
+                                        alert(that.$t('banBenGuoDiQingShengJi'))
                                     }
                                 })
                         });
@@ -861,7 +862,7 @@
                                 }
                                 sessionStorage.setItem('user', JSON.stringify(nerUser));
                                 this.$message({
-                                    message: '操作成功',
+                                    message: this.$t('operationissuccessful'),
                                     type: "success"
                                 });
                             } else {
@@ -898,7 +899,7 @@
                                 }
                                 sessionStorage.setItem('user', JSON.stringify(nerUser));
                                 this.$message({
-                                    message: '操作成功',
+                                    message: this.$t('operationissuccessful'),
                                     type: "success"
                                 });
                             } else {
@@ -976,7 +977,7 @@
             }
 
             // 判断是否为新用户
-            if(this.user.isFirstLogin == 1 && this.user.roleName == '超级管理员' && this.firstTourFalse != 'false' && this.user.createTime[0] > '2022') {
+            if(this.user.isFirstLogin == 1 && this.user.roleName == this.$t('role.superAdministrator') && this.firstTourFalse != 'false' && this.user.createTime[0] > '2022') {
                 var thats = this
                 this.tourFlg = true
                 setTimeout(() => {
@@ -999,6 +1000,13 @@
             if(this.user.dingdingUserid) {
                 this.setDDOpenData()
             }
+
+            // 中英文显示字符长度
+            if(this.language == '中文') {
+                this.textLength = 16
+            } else {
+                this.textLength = 17
+            }
         },
     };
 </script>

+ 9 - 9
fhKeeper/formulahousekeeper/timesheet/src/views/Login.vue

@@ -17,7 +17,7 @@
                         <el-button type="primary" style="width:100%;" @click.native.prevent="handleSubmit" :loading="logining">{{ $t('login') }}</el-button>
                     </el-form-item>
                     <div class="additional" v-if="wxHrefFlg">
-                        <el-divider content-position="center"></el-divider>
+                        <el-divider content-position="center">{{ $t('huo') }}</el-divider>
                     </div>
                     <div class="externalLanding" v-if="wxHrefFlg">
                         <div class="externalLanding_img" @click="wxworkCli()">
@@ -51,7 +51,7 @@
                             target="_blank">工时管家使用说明_普通员工.docx</a></p> -->
                 
             </el-dialog>
-            <el-dialog title="企业微信扫码登陆" :visible.sync="wxworkFlg" width="500px">
+            <el-dialog :title="$t('qiYeWeiXinSaoMaDengLu')" :visible.sync="wxworkFlg" width="500px">
                 <div>
                     <div id="wxcode"></div>
                 </div>
@@ -59,7 +59,7 @@
         </div>
         <!-- 绑定企业微信的话显示这个 -->
         <div class="qiweix" v-if="bindingqywx">
-            正在进入系统...
+            {{ $t('zhengZaiJinRuXiTong') }} 
         </div>
     </div>
 </template>
@@ -156,7 +156,7 @@
                                 this.$router.push({ path: user.moduleList[0].path })
                             } else {
                                 //没有授权任何模块,需要提示用户
-                                alert('无权访问,请联系管理员为您分配权限');
+                                alert(this.$t('wuQuanFangWenQingLianXiGuanLiYuanWeiNinFenPeiQuanXian'));
                             }
                         }
                     } else if (href.indexOf('errorMsg=') > 0) {
@@ -194,7 +194,7 @@
                             this.$router.push({ path: user.moduleList[0].path })
                         } else {
                             //没有授权任何模块,需要提示用户
-                            alert('无权访问,请联系管理员为您分配权限');
+                            alert(this.$t('wuQuanFangWenQingLianXiGuanLiYuanWeiNinFenPeiQuanXian'));
                         }
                     }
                 } else {
@@ -408,7 +408,7 @@
                                     }
                                 } else {
                                     //没有授权任何模块,需要提示用户
-                                    alert('无权访问,请联系管理员为您分配权限');
+                                    alert(this.$t('wuQuanFangWenQingLianXiGuanLiYuanWeiNinFenPeiQuanXian'));
                                 }
                             } else {
                                 this.$message({
@@ -437,7 +437,7 @@
                                     this.$router.push({ path: user.moduleList[0].path })
                                 }else {
                                     //没有授权任何模块,需要提示用户
-                                    alert('无权访问,请联系管理员为您分配权限');
+                                    alert(this.$t('wuQuanFangWenQingLianXiGuanLiYuanWeiNinFenPeiQuanXian'));
                                 }
                             } else {
                                 this.$message({
@@ -544,7 +544,7 @@
                                 sessionStorage.setItem('autoRoute',user.moduleList[0].path)
                             } else {
                                 //没有授权任何模块,需要提示用户
-                                alert('无权访问,请联系管理员为您分配权限');
+                                alert(this.$t('wuQuanFangWenQingLianXiGuanLiYuanWeiNinFenPeiQuanXian'));
                             }
                         }
                     } else {
@@ -576,7 +576,7 @@
                             this.$router.push({ path: user.moduleList[0].path })
                         } else {
                             //没有授权任何模块,需要提示用户
-                            alert('无权访问,请联系管理员为您分配权限');
+                            alert(this.$t('wuQuanFangWenQingLianXiGuanLiYuanWeiNinFenPeiQuanXian'));
                         }
                     } else {
                         this.$message({

+ 23 - 23
fhKeeper/formulahousekeeper/timesheet/src/views/Register.vue

@@ -5,40 +5,40 @@
                 <!-- <div class="login-logo">
                     <img src="../assets/image/login_logo.png" style="width:80px;height:80px;"/>
                 </div> -->
-                <h3 class="title">注册</h3>
+                <h3 class="title">{{ $t('zhuCe') }}</h3>
                 <el-form-item class="login-input" prop="companyName">
-                    <el-input type="text" v-model="ruleForm.companyName" autocomplete="off" placeholder="公司名" clearable prefix-icon="el-icon-s-home"></el-input>
+                    <el-input type="text" v-model="ruleForm.companyName" autocomplete="off" :placeholder="$t('gongSiMing')" clearable prefix-icon="el-icon-s-home"></el-input>
                 </el-form-item>
                 <el-form-item class="login-input" prop="name">
-                    <el-input type="text" v-model="ruleForm.name" autocomplete="off" placeholder="姓名" clearable prefix-icon="el-icon-user-solid"></el-input>
+                    <el-input type="text" v-model="ruleForm.name" autocomplete="off" :placeholder="$t('lable.name')" clearable prefix-icon="el-icon-user-solid"></el-input>
                 </el-form-item>
                 <el-form-item class="login-input" prop="phone">
-                    <el-input type="text" v-model="ruleForm.phone" autocomplete="off" placeholder="手机号" clearable prefix-icon="el-icon-mobile-phone"></el-input>
+                    <el-input type="text" v-model="ruleForm.phone" autocomplete="off" :placeholder="$t('lable.phone')" clearable prefix-icon="el-icon-mobile-phone"></el-input>
                 </el-form-item>
                 <el-form-item class="login-input" prop="vcode">
-                    <el-input type="text" v-model="ruleForm.vcode" autocomplete="off" placeholder="验证码" @keyup.enter.native="sendVcode()" clearable prefix-icon="iconfont firerock-iconyanzhengma">
-                        <el-button slot="append" @click="sendVcode" :disabled="ruleForm.phone=='' || showTimer">发送验证码<span v-if="showTimer">({{countNum}})</span></el-button>
+                    <el-input type="text" v-model="ruleForm.vcode" autocomplete="off" :placeholder="$t('yanZhengMa')" @keyup.enter.native="sendVcode()" clearable prefix-icon="iconfont firerock-iconyanzhengma">
+                        <el-button slot="append" @click="sendVcode" :disabled="ruleForm.phone=='' || showTimer">{{ $t('faSongYanZhengMa') }}<span v-if="showTimer">({{countNum}})</span></el-button>
                     </el-input>
                 </el-form-item>
                 <el-form-item class="login-input" prop="password">
-                    <el-input type="password" v-model="ruleForm.password" autocomplete="off" placeholder="设置密码,长度不低于6位" clearable prefix-icon="iconfont firerock-iconmima">
+                    <el-input type="password" v-model="ruleForm.password" autocomplete="off" :placeholder="$t('sheZhiMiMaChangDuBuDiYu_6Wei')" clearable prefix-icon="iconfont firerock-iconmima">
                     </el-input>
                 </el-form-item>
                 <el-form-item class="login-input" prop="repwd">
-                    <el-input type="password" v-model="ruleForm.repwd" autocomplete="off" placeholder="重复密码" clearable prefix-icon="iconfont firerock-iconmima">
+                    <el-input type="password" v-model="ruleForm.repwd" autocomplete="off" :placeholder="$t('zhongFuMiMa')" clearable prefix-icon="iconfont firerock-iconmima">
                     </el-input>
                 </el-form-item>
                 
                 <el-form-item class="login-input" prop="type" style="text-align:center;">
                     <el-divider ></el-divider>
                     <div style="margin-top:10px;">
-                    <span>选择版本: </span><el-select v-model="ruleForm.type" style="width:250px;">
+                    <span>{{ $t('xuanZeBanBen') }} </span><el-select v-model="ruleForm.type" style="width:250px;">
                         <el-option v-for="item in typeList" :value="item.id" :label="item.name" :key="item.id"></el-option>
                     </el-select>
                     </div>
                 </el-form-item>
                 <div class="login-button" style="width:100%;margin-top:20px;">
-                    <el-button type="primary" style="width:100%;" @click.native.prevent="handleSubmit" :loading="logining">注册</el-button>
+                    <el-button type="primary" style="width:100%;" @click.native.prevent="handleSubmit" :loading="logining">{{ $t('zhuCe') }}</el-button>
                 </div>
             </el-form>
         </div>
@@ -49,8 +49,8 @@
     export default {
         data() {
             return {
-                typeList:[{id:1,name:'工时统计基础版'},
-                {id:2,name:'项目管理专业版'},{id:3,name:'企业办公旗舰版'},{id:4,name:'工程管理专业版'}],
+                typeList:[{id:1,name:this.$t('gongShiTongJiJiChuBan')},
+                {id:2,name:this.$t('xiangMuGuanLiZhuanYeBan')},{id:3,name:this.$t('qiYeBanGongQiJianBan')},{id:4,name:this.$t('gongChengGuanLiZhuanYeBan')}],
                 logining: false,
                 showTimer: false,
                 countNum: 60,
@@ -62,12 +62,12 @@
                     type:2,
                 },
                 rules: {
-                    companyName: [{ required: true, message: '请输入公司名', trigger: 'blur' },],
-                    name: [{ required: true, message: '请输入姓名', trigger: 'blur' },],
-                    phone: [{ required: true, message: '请输入手机号', trigger: 'blur' },],
-                    vcode: [{ required: true, message: '请输入验证码', trigger: 'blur' },],
-                    password: [{ required: true, message: '请设置密码,长度不低于6位', trigger: 'blur' },],
-                    repwd: [{ required: true, message: '请重复输入密码', trigger: 'blur' },]
+                    companyName: [{ required: true, message: this.$t('qingShuRuGongSiMing'), trigger: 'blur' },],
+                    name: [{ required: true, message: this.$t('defaultText.PleaseEnterYourName'), trigger: 'blur' },],
+                    phone: [{ required: true, message: this.$t('defaultText.PleaseEnterYourPhone'), trigger: 'blur' },],
+                    vcode: [{ required: true, message: this.$t('qingShuRuYanZhengMa'), trigger: 'blur' },],
+                    password: [{ required: true, message: this.$t('qingSheZhiMiMaChangDuBuDiYu_6Wei'), trigger: 'blur' },],
+                    repwd: [{ required: true, message: this.$t('qingZhongFuShuRuMiMa'), trigger: 'blur' },]
                 },
             };
         },
@@ -87,7 +87,7 @@
             sendVcode() {
                 if (this.ruleForm.phone.length != 11) {
                     this.$message({
-                                    message: '手机号码格式不正确',
+                                    message: this.$t('shouJiHaoMaGeShiBuZhengQue'),
                                     type: 'error'
                                 });
                 } else {
@@ -95,7 +95,7 @@
                             this.logining = false;
                             if (res.code == "ok") {
                                 this.$message({
-                                    message: '发送成功',
+                                    message: this.$t('faSongChengGong'),
                                     type: 'success'
                                 });
                                 this.showTimer = true;
@@ -125,7 +125,7 @@
                     if (valid) {
                         if (this.ruleForm.password.length < 6) {
                             this.$message({
-                                    message: '密码长度不能少于6位',
+                                    message: this.$t('miMaChangDuBuNengShaoYu_6Wei'),
                                     type: 'error'
                                 });
                             return;
@@ -133,7 +133,7 @@
                         //检查两次密码是否一致
                         if (this.ruleForm.password != this.ruleForm.repwd) {
                             this.$message({
-                                    message: '两次输入的密码不一致',
+                                    message: this.$t('liangCiShuRuDeMiMaBuYiZhi'),
                                     type: 'error'
                                 });
                             return;
@@ -151,7 +151,7 @@
                             this.logining = false;
                             if (res.code == "ok") {
                                 this.$message({
-                                    message: '注册成功',
+                                    message: this.$t('zhuCeChengGong'),
                                     type: 'success'
                                 });
                                 this.$router.push({ path: '/login' });

+ 17 - 17
fhKeeper/formulahousekeeper/timesheet/src/views/awayOffice/awayOffice.vue

@@ -11,7 +11,7 @@
                 </el-menu-item>
                 <el-menu-item index="2" @select="bills" @click="auditList()" v-if="permissions.awayOfficeAudit">
                 <i class="iconfont firerock-iconshenhe"></i>
-                <span slot="title">出差审核</span>
+                <span slot="title">{{ $t('chu-cha-shen-he') }}</span>
                 </el-menu-item>
                 <el-menu-item index="3" @select="bills" @click="bills(false, 2)" >
                 <i class="iconfont firerock-iconbaoxiaodan"></i>
@@ -141,16 +141,16 @@
                             <el-input type="textarea" v-model="addform.remark" :rows="3" style="width: 100%" maxlength="100" show-word-limit></el-input>
                         </el-form-item>
                         <!--流程显示-->
-                        <el-form-item label="审批流程" style="width: 100%;color:#606266" >
+                        <el-form-item :label="$t('other.approvalProcess')" style="width: 100%;color:#606266" >
                         <span v-for="(item, index) in curWorkflowList" :key="item.id" >
                             <span v-if="index>0"><i class="el-icon-right"></i></span>
                             <span><i class="el-icon-s-custom"></i></span>
                             <span v-if="user.userNameNeedTranslate == 1">
-                            <span v-if="item.auditorType == 1"><TranslationOpenDataText type='departmentName' :openid='item.auditDeptName' ></TranslationOpenDataText>(主要负责人)</span>
+                            <span v-if="item.auditorType == 1"><TranslationOpenDataText type='departmentName' :openid='item.auditDeptName' ></TranslationOpenDataText>{{ $t('zhu-yao-fu-ze-ren') }}</span>
                             <TranslationOpenDataText type='userName' :openid='item.userName' v-if="item.auditorType == 2"></TranslationOpenDataText>
                             </span>
                             <span v-if="user.userNameNeedTranslate == 0">
-                            {{item.auditorType == 1?(item.auditDeptName+'(主要负责人)'):item.userName}}
+                            {{item.auditorType == 1?(item.auditDeptName+$t('zhu-yao-fu-ze-ren')):item.userName}}
                             </span>
                         </span>
                         </el-form-item>
@@ -295,9 +295,9 @@
                             <el-button icon="el-icon-close" circle size="mini"  @click.stop.native="deny(scope.row)"></el-button>
                         </div>
                         <div v-if="!isAuditList && ((scope.row.status != 0 && scope.row.ownerId == user.id) || permissions.awayOfficeAll)">
-                            <el-button size="mini" v-if="scope.row.status == 3 ||scope.row.status == 2" @click.stop.native="deletes(scope.row)" >删除</el-button>
-                            <el-button size="mini" v-if="scope.row.status == 1" @click.stop.native="cancel(scope.row)">撤回</el-button>
-                            <el-button size="mini" v-if="scope.row.status == 3 ||scope.row.status == 2 " type="primary" @click.stop.native="editor(scope.row)">重新提交</el-button>
+                            <el-button size="mini" v-if="scope.row.status == 3 ||scope.row.status == 2" @click.stop.native="deletes(scope.row)" >{{ $t('btn.delete') }}</el-button>
+                            <el-button size="mini" v-if="scope.row.status == 1" @click.stop.native="cancel(scope.row)">{{ $t('btn.withdraw') }}</el-button>
+                            <el-button size="mini" v-if="scope.row.status == 3 ||scope.row.status == 2 " type="primary" @click.stop.native="editor(scope.row)">{{ $t('zhong-xin-ti-jiao') }}</el-button>
                         </div>
                         </template>
                     </el-table-column>
@@ -735,8 +735,8 @@
                 <el-timeline-item v-for="item in auditLogList" :key="item.id" :timestamp="item.indate">
                   <span v-if="user.userNameNeedTranslate == 1"><TranslationOpenDataText type='userName' :openid='item.auditorName'></TranslationOpenDataText> </span>
                   <span v-if="user.userNameNeedTranslate == 0">{{item.auditorName}}</span>
-                  <span> {{item.isPass==0?"驳回了请假申请。":"审核通过。"}}</span>
-                  <span v-if="item.isPass == 0">原因:{{item.denyReason}}</span>
+                  <span> {{item.isPass==0?`${$t('bo-hui-le-qing-jia-shen-qing')}`:`${$t('state.approved')}`}}</span>
+                  <span v-if="item.isPass == 0">{{ $t('other.reason') }}:{{item.denyReason}}</span>
                   </el-timeline-item>
             </el-timeline>
         </div>
@@ -1503,7 +1503,7 @@ export default {
                 if (res.code == "ok") {
                     this.auditList();
                     this.$message({
-                        message: '操作成功',
+                        message: this.$t('operationissuccessful'),
                         type: "success"
                         });
                 } else {
@@ -1533,7 +1533,7 @@ export default {
                     this.auditList();
                     this.denyDialogV = false;
                     this.$message({
-                        message: '操作成功',
+                        message: this.$t('operationissuccessful'),
                         type: "success"
                         });
                 } else {
@@ -1551,7 +1551,7 @@ export default {
             });
         },
         cancel(e) {
-            this.$confirm('确定要撤回该出差申请吗', this.$t('other.prompts'), {
+            this.$confirm(this.$t('que-ding-yao-che-hui-gai-chu-cha-shen-qing-ma'), this.$t('other.prompts'), {
                 //type: 'warning'
             }).then(() => {
                 this.http.post('/business-trip/cancel', {id:e.id},
@@ -1559,7 +1559,7 @@ export default {
                     if (res.code == "ok") {
                         this.bills();
                         this.$message({
-                            message: '操作成功',
+                            message: this.$t('operationissuccessful'),
                             type: "success"
                         });
                     } else {
@@ -1889,7 +1889,7 @@ export default {
                 });
             } else {
                 this.$message({
-                    message: '至少选择一个部门或者人员做为审核人',
+                    message: this.$t('zhi-shao-xuan-ze-yi-ge-bu-men-huo-zhe-ren-yuan-zuo-wei-shen-he-ren'),
                     type: "error"
                 });
             }
@@ -1926,12 +1926,12 @@ export default {
               if(!flgUserRadio) {
                 if(node.type == 'dep') {
                   this.$message({
-                      message: '已存在重复部门',
+                      message: this.$t('yi-cun-zai-zhong-fu-bu-men'),
                       type: "error"
                   });
                 } else {
                   this.$message({
-                      message: '已存在重复人员',
+                      message: this.$t('yi-cun-zai-zhong-fu-ren-yuan'),
                       type: "error"
                   });
                 }
@@ -2018,7 +2018,7 @@ export default {
                 res => {
                     if (res.code == "ok") {
                         this.projectList = res.data;
-                        console.log("项目列表",this.projectList);
+                        console.log(this.$t('listofitems'),this.projectList);
                     } else {
                         this.$message({
                             message: res.msg,

+ 3 - 22
fhKeeper/formulahousekeeper/timesheet/src/views/centerManage/centerManage.vue

@@ -1,15 +1,11 @@
 <template>
     <section>
-        <el-select v-model="value" filterable placeholder="请选择" :filter-method="aabbcc()">
-            <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
-            </el-option>
-        </el-select>
         <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
             <el-form :inline="true">
                 <el-form-item :label="user.timeType.customDegreeName + $t('guan-li')">
-                    <el-input placeholder="请输入关键名称" v-model.trim="searchNameVal" clearable class="input-with-select"
+                    <el-input :placeholder="$t('qing-shu-ru-guan-jian-ming-cheng')" v-model.trim="searchNameVal" clearable class="input-with-select"
                         style="margin-left: 50px" @keyup.enter.native="searchName()">
-                        <el-button slot="append" @click="searchName()">搜索</el-button>
+                        <el-button slot="append" @click="searchName()">{{ $t('sou-suo') }}</el-button>
                     </el-input>
                 </el-form-item>
 
@@ -121,22 +117,7 @@ export default {
             subProjectList: [],//子项目列表
             subProjectListArr: [], // 备用列表
             searchNameVal: '',
-            options: [{
-                value: '选项1',
-                label: '黄金糕'
-            }, {
-                value: '选项2',
-                label: '双皮奶'
-            }, {
-                value: '选项3',
-                label: '蚵仔煎'
-            }, {
-                value: '选项4',
-                label: '龙须面'
-            }, {
-                value: '选项5',
-                label: '北京烤鸭'
-            }],
+            options: [],
             value: ''
         };
     },

+ 25 - 25
fhKeeper/formulahousekeeper/timesheet/src/views/contract/index.vue

@@ -46,7 +46,7 @@
           ></el-date-picker>
         </el-form-item>
         <el-form-item>
-          <span style="margin-left:5px;margin-right:5px;color:#606266;">下笔回款日期</span>
+          <span style="margin-left:5px;margin-right:5px;color:#606266;">{{ $t('xia-bi-hui-kuan-ri-qi') }}</span>
           <el-date-picker
             style="width:240px;"
             v-model="paymentDate"
@@ -81,30 +81,30 @@
     <el-table :data="contractList" v-loading="listLoading" :height="tableHeight" border highlight-current-row>
       <el-table-column prop="number" :label="$t('contractno')" min-width="190"></el-table-column>
       <el-table-column prop="name" :label="$t('he-tong-ming-cheng')" min-width="190"></el-table-column>
-      <el-table-column prop="amounts" :label="$t('contractamount')" min-width="130" align="right" header-align="center">
+      <el-table-column prop="amounts" :label="$t('contractamount')" min-width="135" align="right" header-align="center">
         <span slot-scope="scope">¥ {{scope.row.amounts ? scope.row.amounts.toFixed(2) : '0.00'}}</span>
       </el-table-column>
-      <el-table-column prop="payment" label="已回款金额" min-width="130" align="right" header-align="center">
+      <el-table-column prop="payment" :label="$t('yi-hui-kuan-jin-e')" min-width="140" align="right" header-align="center">
         <span slot-scope="scope">¥ {{scope.row.payment ? scope.row.payment.toFixed(2) : '0.00'}}</span>
       </el-table-column>
-      <el-table-column prop="payment" label="已回款进度" min-width="130" align="right" header-align="center">
+      <el-table-column prop="payment" :label="$t('yi-hui-kuan-jin-du')" min-width="170" align="right" header-align="center">
         <span slot-scope="scope">{{scope.row.payment ? (100*scope.row.payment/scope.row.amounts).toFixed(1) + '%': '0%'}}</span>
       </el-table-column>
-      <el-table-column prop="nextPaymentDate" label="下笔回款日期" min-width="130" align="right" header-align="center">
+      <el-table-column prop="nextPaymentDate" :label="$t('xia-bi-hui-kuan-ri-qi')" min-width="170" align="right" header-align="center">
         <span slot-scope="scope">{{scope.row.nextPaymentDate ? scope.row.nextPaymentDate : '-'}}</span>
       </el-table-column>
-      <el-table-column prop="nextPaymentAmount" label="下笔回款金额" min-width="130" align="right" header-align="center">
+      <el-table-column prop="nextPaymentAmount" :label="$t('xia-bi-hui-kuan-jin-e')" min-width="120" align="right" header-align="center">
         <span slot-scope="scope">{{scope.row.nextPaymentAmount?'¥'+scope.row.nextPaymentAmount.toFixed(2) : '-'}}</span>
       </el-table-column>
       
       <el-table-column prop="typeName" :label="$t('he-tong-lei-xing')" min-width="140" align="center"></el-table-column>
-      <el-table-column prop="status" :label="$t('state.states')" min-width="100" align="center">
+      <el-table-column prop="status" :label="$t('state.states')" min-width="120" align="center">
         <template slot-scope="scope">
           <span :style="statusList[scope.row.status].color">{{statusList[scope.row.status].label}}</span>
         </template>
       </el-table-column>
-      <el-table-column prop="indate" :label="$t('creationtime')" min-width="100" align="center"></el-table-column>
-      <el-table-column width="300" :label="$t('operation')" align="left" fixed="right">
+      <el-table-column prop="indate" :label="$t('creationtime')" min-width="130" align="center"></el-table-column>
+      <el-table-column width="340" :label="$t('operation')" align="left" fixed="right">
         <template slot-scope="scope">
           <el-button v-if="permissions.contractView || permissions.contractManagement" size="mini" @click="lookover(scope.row)">{{$t('cha-kan')}}</el-button>
           <el-button v-if="permissions.contractManagement" size="mini" @click="editContract(scope.row)" type="primary">{{$t('bian-ji')}}</el-button>
@@ -131,7 +131,7 @@
         <el-form ref="contractForm" :model="contractForm" :rules="rules" label-width="120px" class="contractForm">
           <el-form-item :label="$t('contractno')">
             <el-input v-model="contractForm.number" :disabled="contractForm.status == 0" :maxlength="50" style="width:260px;" show-word-limit :placeholder="$t('peaseenterthe')" clearable @input="searchProject"></el-input>
-            <span style="margin-left:20px;">关联项目</span>
+            <span style="margin-left:20px;">{{ $t('rselatedprojects') }}</span>
             <el-select v-model="contractForm.projectId" filterable clearable style="width:300px;" :disabled="contractForm.status == 0">
               <el-option v-for="item in projectList" :key="item.id" :label="item.projectName  + '\u3000' + (item.projectCode == null?'':item.projectCode)" :value="item.id" >
                     <span style="float: left; color: #8492a6; font-size: 13px;">{{ item.projectCode }}</span>
@@ -176,23 +176,23 @@
           <el-form-item :label="$t('bei-zhu')">
             <el-input v-model="contractForm.remarks" :disabled="contractForm.status == 0" :placeholder="$t('peaseenterthe')" type="textarea" :rows="3" clearable></el-input>
           </el-form-item>
-          <el-form-item label="回款计划">
+          <el-form-item :label="$t('hui-kuan-ji-hua')">
             <el-table :data="contractPaymentList" size="small" :key="Math.random()" :height="'300px'" show-header="false" style="margin-top:10px;">
                   <el-table-column prop="isPayed" >
                       <template slot-scope="scope">
-                          <el-checkbox v-model="scope.row.isPayed" >已回款</el-checkbox>
+                          <el-checkbox v-model="scope.row.isPayed" >{{ $t('yi-hui-kuan') }}</el-checkbox>
                       </template>
                       <template slot="header" >
-                          <span style="font-size:14px;font-weight:normal;">是否已回款</span>
+                          <span style="font-size:14px;font-weight:normal;">{{ $t('shi-fou-yi-hui-kuan') }}</span>
                       </template>
                   </el-table-column>
-                  <el-table-column prop="payDate"  label="回款日期" width="210">
+                  <el-table-column prop="payDate"  :label="$t('hui-kuan-ri-qi')" width="210">
                       <template slot-scope="scope">
                           <div><el-date-picker type="date" v-model="scope.row.payDate" style="width:200px;" :placeholder="$t('optiondate')" value-format="yyyy-MM-dd"></el-date-picker></div>
                       </template>
                   </el-table-column>
                   
-                  <el-table-column prop="amount" label="回款金额">
+                  <el-table-column prop="amount" :label="$t('hui-kuan-jin-e')">
                       <template slot-scope="scope">
                         <el-input v-model="scope.row.amount" :id="'payment_amount'+scope.$index" :placeholder="$t('peaseenterthe')" maxlength="10" clearable>
                           <span slot="prefix">¥</span>
@@ -290,23 +290,23 @@
           <el-form-item style="width:100%" :label="$t('bei-zhu')">
             {{contractForm.remarks}}
           </el-form-item>
-          <el-form-item style="width:100%" label="回款计划">
+          <el-form-item style="width:100%" :label="$t('hui-kuan-ji-hua')">
             <el-table :data="contractPaymentList" size="small" :key="Math.random()" :height="'300px'" show-header="false" style="margin-top:10px;">
                   <el-table-column prop="isPayed" >
                       <template slot-scope="scope">
-                        {{ scope.row.isPayed?'已回款':'未回款' }}
+                        {{ scope.row.isPayed?$t('yi-hui-kuan'):$t('wei-hui-kuan') }}
                       </template>
                       <template slot="header" >
-                          <span style="font-size:14px;font-weight:normal;">是否已回款</span>
+                          <span style="font-size:14px;font-weight:normal;">{{ $t('shi-fou-yi-hui-kuan') }}</span>
                       </template>
                   </el-table-column>
-                  <el-table-column prop="payDate"  label="回款日期" width="210">
+                  <el-table-column prop="payDate"  :label="$t('hui-kuan-ri-qi')" width="210">
                       <template slot-scope="scope">
                           <div>{{ scope.row.payDate }}</div>
                       </template>
                   </el-table-column>
                   
-                  <el-table-column prop="amount" label="回款金额">
+                  <el-table-column prop="amount" :label="$t('hui-kuan-jin-e')">
                       <template slot-scope="scope">
                         <div>{{ scope.row.amount }}</div>
                       </template>
@@ -650,7 +650,7 @@ export default {
     typeItemAdd(){
       if(this.typeList.length == 20){
         this.$message({
-          message: '合同类型最多只能创建20个',
+          message: this.$t('he-tong-lei-xing-zui-duo-zhi-neng-chuang-jian-20-ge'),
           type: 'error'
         })
         return
@@ -823,7 +823,7 @@ export default {
           status: status
         }
       }
-      this.$confirm('确认审核通过吗,通过后合同基本信息无法修改', this.$t('other.prompts'), {
+      this.$confirm(this.$t('que-ren-shen-he-tong-guo-ma-tong-guo-hou-he-tong-ji-ben-xin-xi-wu-fa-xiu-gai'), this.$t('other.prompts'), {
         confirmButtonText: this.$t('btn.determine'),
         cancelButtonText: this.$t('btn.cancel'),
         type: 'warning'
@@ -893,14 +893,14 @@ export default {
           for (var i = 0; i < this.contractPaymentList.length; i++) {
             if (!this.contractPaymentList[i].payDate) {
               this.$message({
-                message: '回款日期不能为空',
+                message: this.$t('hui-kuan-ri-qi-bu-neng-wei-kong'),
                 type: 'error'
               })
               return;
             }
             if (!this.contractPaymentList[i].amount) {
               this.$message({
-                message: '回款金额不能为0',
+                message: this.$t('hui-kuan-jinebu-neng-wei-0'),
                 type: 'error'
               })
               return;
@@ -909,7 +909,7 @@ export default {
           }
           if (totalPayment > parseFloat(this.contractForm.amounts)) {
             this.$message({
-                message: '总回款金额不得大于合同金额',
+                message: this.$t('zong-hui-kuan-jinebu-de-da-yu-he-tong-jin-e'),
                 type: 'error'
               })
               return;

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

@@ -0,0 +1,87 @@
+export function getGroupConsumption(nameList = [], actualPlan = [], actualSupplement = [], summary = [], realHourList = []) {
+  let num1 = actualPlan.reduce((accumulator, currentValue) => accumulator + currentValue, 0)
+  let num2 = actualSupplement.reduce((accumulator, currentValue) => accumulator + currentValue, 0)
+  let num3 = realHourList.reduce((accumulator, currentValue) => accumulator + currentValue, 0)
+  return {
+    title: {
+      text: `求和项:合计工时:${num3}(h) 实际工时: ${num1}(h)  实际增补: ${num2}(h)`,
+      top: 20
+    },
+    tooltip: {},
+    toolbox: {},
+    grid: {
+      top: 80,
+      left: 80,
+      right: 80,
+      bottom: 120,
+    },
+    legend: {
+      data: ["实际计划", "实际增补", "汇总"],
+      top: 20,
+      right: 100
+    },
+    xAxis: [
+      {
+        data: nameList,
+        axisPointer: {
+          type: "shadow",
+        },
+        axisLabel: {
+          rotate: 45,
+        },
+      },
+    ],
+    yAxis: [
+      {
+        type: "value",
+        axisLabel: {
+          formatter: "{value} (h)",
+        },
+      },
+      {
+        type: "value",
+        axisLabel: {
+          formatter: "{value} (h)",
+        },
+      },
+    ],
+    series: [
+      {
+        name: "实际计划",
+        type: "bar",
+        stack: "one",
+        barWidth: 40,
+        itemStyle: {
+          normal: {
+            color: "#5B9BD5",
+          },
+        },
+        data: actualPlan,
+      },
+      {
+        name: "实际增补",
+        type: "bar",
+        stack: "one",
+        barWidth: 40,
+        itemStyle: {
+          normal: {
+            color: "#ED7D31",
+          },
+        },
+        data: actualSupplement,
+      },
+      {
+        name: "汇总",
+        type: "line",
+        yAxisIndex: 1,
+        lineStyle: {
+          normal: {
+            width: 3,
+            color: "#5B9BD5",
+          },
+        },
+        data: summary,
+      },
+    ],
+  }
+}

Plik diff jest za duży
+ 333 - 177
fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue


+ 2 - 2
fhKeeper/formulahousekeeper/timesheet/src/views/customer/list.vue

@@ -16,7 +16,7 @@
                 <el-form-item style="float:right;">
                     <el-link type="primary" :underline="false" @click="handleAdd(-1,null)">{{ $t('newcustomer') }}</el-link>
                     <el-link type="primary" :underline="false" @click="intocustomerRatio">{{ $t('importingCustomersinBatches') }}</el-link>
-                    <el-link type="primary" :underline="false" @click="exportData()">{{'导出'}}</el-link>
+                    <el-link type="primary" :underline="false" @click="exportData()">{{ $t('export.export') }}</el-link>
                 </el-form-item>
             </el-form>
         </el-col>
@@ -582,7 +582,7 @@
                     if (res.code == "ok") {
                         var filePath = res.data;
                         const a = document.createElement('a'); // 创建a标签
-                        a.setAttribute('download', '客户列表.xlsx');// download属性
+                        a.setAttribute('download', this.$t('keHuLieBiaoXlsx'));// download属性
                         a.setAttribute('href', filePath);// href链接
                         a.click(); //自执行点击事件
                         a.remove();

+ 32 - 32
fhKeeper/formulahousekeeper/timesheet/src/views/desktop/detail.vue

@@ -4,14 +4,14 @@
     <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
       <el-form :inline="true">
         <el-form-item>
-          <el-button type="text" @click="backToList" icon="el-icon-back" class="back">返回</el-button>
+          <el-button type="text" @click="backToList" icon="el-icon-back" class="back">{{ $t('fan-hui') }}</el-button>
         </el-form-item>
         <el-form-item class="divLine"></el-form-item>
         <el-form-item>
           <span class="workName">{{uName}} / {{date}}</span>
         </el-form-item>
         <el-form-item style="float:right;">
-          今日工作时长:
+          {{ $t('jinRiGongZuoShiChang') }} 
           <span class="workHours">{{uHours}}h</span>
         </el-form-item>
       </el-form>
@@ -139,7 +139,7 @@ export default {
       this.myChart = myChart;
       var option = {
         title: {
-          text: "工作时长分配",
+          text: this.$t('gongZuoShiChangFenPei'),
           left: "left"
         },
         tooltip: {
@@ -153,17 +153,17 @@ export default {
           top: 30,
           bottom: 20,
           data: [
-            "研发",
-            "上网",
-            "文档",
-            "设计",
+            this.$t('yanFa'),
+            this.$t('shangWang'),
+            this.$t('wenDang'),
+            this.$t('sheJi'),
             // "美工",
             // "运营",
-            "看小说",
-            "影视娱乐",
+            this.$t('kanXiaoShuo'),
+            this.$t('yingShiYuLe'),
             // "听音乐",
-            "聊天",
-            "其他工作"
+            this.$t('liaoTian'),
+            this.$t('qiTaGongZuo')
           ]
         },
         toolbox: {
@@ -181,19 +181,19 @@ export default {
         },
         series: [
           {
-            name: "时长(单位:h)",
+            name: this.$t('shiChangDanWeiH'),
             type: "pie",
             radius: [30, 110],
             roseType: "area",
             data: [
-              { value: (this.timeList[1] / 3600).toFixed(2), name: "研发" },
-              { value: (this.timeList[2] / 3600).toFixed(2), name: "上网" },
-              { value: (this.timeList[3] / 3600).toFixed(2), name: "文档" },
-              { value: (this.timeList[4] / 3600).toFixed(2), name: "设计" },
-              { value: (this.timeList[7] / 3600).toFixed(2), name: "看小说" },
-              { value: (this.timeList[8] / 3600).toFixed(2), name: "影视娱乐" },
-              { value: (this.timeList[10] / 3600).toFixed(2), name: "聊天" },
-              { value: (this.timeList[0] / 3600).toFixed(2), name: "其他工作" }
+              { value: (this.timeList[1] / 3600).toFixed(2), name: this.$t('yanFa') },
+              { value: (this.timeList[2] / 3600).toFixed(2), name: this.$t('shangWang') },
+              { value: (this.timeList[3] / 3600).toFixed(2), name: this.$t('wenDang') },
+              { value: (this.timeList[4] / 3600).toFixed(2), name: this.$t('sheJi') },
+              { value: (this.timeList[7] / 3600).toFixed(2), name: this.$t('kanXiaoShuo') },
+              { value: (this.timeList[8] / 3600).toFixed(2), name: this.$t('yingShiYuLe') },
+              { value: (this.timeList[10] / 3600).toFixed(2), name: this.$t('liaoTian') },
+              { value: (this.timeList[0] / 3600).toFixed(2), name: this.$t('qiTaGongZuo') }
             ]
           }
         ]
@@ -209,29 +209,29 @@ export default {
     converType(type) {
       switch (type) {
         case 0:
-          return "其他工作";
+          return this.$t('qiTaGongZuo');
         case 1:
-          return "研发";
+          return this.$t('yanFa');
         case 2:
-          return "上网";
+          return this.$t('shangWang');
         case 3:
-          return "文档";
+          return this.$t('wenDang');
         case 4:
-          return "设计";
+          return this.$t('sheJi');
         case 5:
-          return "美工";
+          return this.$t('meiGong');
         case 6:
-          return "运营";
+          return this.$t('yunYing');
         case 7:
-          return "看小说";
+          return this.$t('kanXiaoShuo');
         case 8:
-          return "影视娱乐";
+          return this.$t('yingShiYuLe');
         case 9:
-          return "听音乐";
+          return this.$t('tingYinLe');
         case 10:
-          return "聊天";
+          return this.$t('liaoTian');
         default:
-          return "未知";
+          return this.$t('weiZhi');
       }
     }
   },

+ 17 - 17
fhKeeper/formulahousekeeper/timesheet/src/views/desktop/index.vue

@@ -16,12 +16,12 @@
                         @change="getDesktopList"
                         :clearable="false"
                         type="date"
-                        placeholder="选择日期"
+                        :placeholder="this.$t('optiondate')"
                     ></el-date-picker>
                 </el-form-item>
                 <el-form-item style="float:right;">
-                    <span style="color:#aaa;font-size:12px;">(员工安装客户端,领导即可查看工作桌面远程监管)</span>
-                    <el-link type="primary" :underline="false" href="http://gsgj.ttkuaiban.com/download.html" target="_blank">客户端下载</el-link>
+                    <span style="color:#aaa;font-size:12px;">{{ $t('yuanGongAnZhuangKeHuDuanLingDaoJiKeChaKanGongZuoZhuoMianYuanChengJianGuan') }}</span>
+                    <el-link type="primary" :underline="false" href="http://gsgj.ttkuaiban.com/download.html" target="_blank">{{ $t('keHuDuanXiaZai') }}</el-link>
                 </el-form-item>
             </el-form>
         </el-col>
@@ -29,7 +29,7 @@
         <!-- 卡片列表 -->
         <div>
             <el-col :span="24" v-if="desktopList.length == 0" style="padding: 200px 0;text-align:center;cursor:pointer">
-                <el-link :underline="false" type="primary" @click="getHavePic">今日暂无截图,点击查看近期</el-link>
+                <el-link :underline="false" type="primary" @click="getHavePic">{{ $t('jinRiZanWuJieTuDianJiChaKanJinQi') }}</el-link>
             </el-col>
             <el-col :span="6" v-for="(item, index) in desktopList" :key="index" class="one_div">
                 <el-card :body-style="{ padding: '0px' }" shadow="hover" class="one_card">
@@ -41,7 +41,7 @@
                     </el-image>
                     <div :id="'over'+index" class="over">
                     <el-button type="primary" plain @click.native="jumpTo(item.id)">
-                        <i class="fa fa-link"></i> 所有截图
+                        <i class="fa fa-link"></i> {{ $t('suoYouJieTu') }}
                     </el-button>
                     </div>
                 </div>
@@ -149,29 +149,29 @@
             converType(type) {
                 switch (type) {
                     case 0:
-                    return "其他工作";
+                    return this.$t('qiTaGongZuo');
                     case 1:
-                    return "研发";
+                    return this.$t('yanFa');
                     case 2:
-                    return "上网";
+                    return this.$t('shangWang');
                     case 3:
-                    return "文档";
+                    return this.$t('wenDang');
                     case 4:
-                    return "设计";
+                    return this.$t('sheJi');
                     case 5:
-                    return "美工";
+                    return this.$t('meiGong');
                     case 6:
-                    return "运营";
+                    return this.$t('yunYing');
                     case 7:
-                    return "看小说";
+                    return this.$t('kanXiaoShuo');
                     case 8:
-                    return "影视娱乐";
+                    return this.$t('yingShiYuLe');
                     case 9:
-                    return "听音乐";
+                    return this.$t('tingYinLe');
                     case 10:
-                    return "聊天";
+                    return this.$t('liaoTian');
                     default:
-                    return "未知";
+                    return this.$t('weiZhi');
                 }
             }
         },

+ 17 - 17
fhKeeper/formulahousekeeper/timesheet/src/views/desktop/unusual.vue

@@ -2,7 +2,7 @@
   <section>
     <!--工具条-->
     <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
-      <div class="nowTime">非工作情况统计</div>
+      <div class="nowTime">{{ $t('feiGongZuoQingKuangTongJi') }}</div>
     </el-col>
 
     <!--列表-->
@@ -14,11 +14,11 @@
       style="width: 100%;"
     >
         <el-table-column type="index" width="60"></el-table-column>
-        <el-table-column prop="name" label="姓名" width="140" sortable></el-table-column>
-        <el-table-column label="行为">
+        <el-table-column prop="name" :label="$t('lable.name')" width="140" sortable></el-table-column>
+        <el-table-column :label="$t('hangWei')">
             <template slot-scope="scope">{{converType(scope.row.type+1)}}</template>
         </el-table-column>
-        <el-table-column label="图片" width="200">
+        <el-table-column :label="$t('tuPian')" width="200">
             <template slot-scope="scope">
                 <el-image :src="scope.row.picUrl" :preview-src-list="getSrcList(index)">
                     <div slot="error" class="image-slot">
@@ -27,8 +27,8 @@
                 </el-image>
             </template>
         </el-table-column>
-        <el-table-column prop="time" label="时间" width="140" sortable></el-table-column>
-        <el-table-column prop="date" label="日期" width="140" sortable></el-table-column>
+        <el-table-column prop="time" :label="$t('time.times')" width="140" sortable></el-table-column>
+        <el-table-column prop="date" :label="$t('weekDay.date')" width="140" sortable></el-table-column>
     </el-table>
 
     <!--工具条-->
@@ -109,27 +109,27 @@ export default {
     converType(type) {
       switch (type) {
         case 0:
-          return "其他工作";
+          return this.$t('qiTaGongZuo');
         case 1:
-          return "研发";
+          return this.$t('yanFa');
         case 2:
-          return "上网";
+          return this.$t('shangWang');
         case 3:
-          return "文档";
+          return this.$t('wenDang');
         case 4:
-          return "设计";
+          return this.$t('sheJi');
         case 5:
-          return "美工";
+          return this.$t('meiGong');
         case 6:
-          return "运营";
+          return this.$t('yunYing');
         case 7:
-          return "看小说";
+          return this.$t('kanXiaoShuo');
         case 8:
-          return "影视娱乐";
+          return this.$t('yingShiYuLe');
         case 9:
-          return "听音乐";
+          return this.$t('tingYinLe');
         default:
-          return "未知";
+          return this.$t('weiZhi');
       }
     },
     getSrcList(index) {

+ 83 - 83
fhKeeper/formulahousekeeper/timesheet/src/views/expense/expense.vue

@@ -50,7 +50,7 @@
     <div class="contents">
       <div v-if="!displayTable" class="headine" ref="headine">
         <!-- <h3 ref="headHe" style="padding-left: 220px">{{shuz[ins]}}</h3> -->
-        <h3 ref="headHe" style="padding-left: 220px">费用填报</h3>
+        <h3 ref="headHe" style="padding-left: 220px">{{ $t('expenses') }}</h3>
         <p style="float: right;margin-right: 25px;"><el-button type="primary" @click="submits" size="mini">{{
           $t('btn.submit') }}</el-button></p>
         <p style="float: right;margin-right: 25px;"><el-button type="primary" @click="submitUpload" size="mini">{{
@@ -58,7 +58,7 @@
         <p style="float: right;margin-right: 25px;"><el-button type="primary" @click="customTypeOp" size="mini"
             v-if="permissions.costAll">{{ $t('expensetypemanagement') }}</el-button></p>
         <p style="float: right;margin-right: 25px;"><el-button type="primary" @click="expenseTypeOp" size="mini"
-            v-if="permissions.costAll">费用主类型管理</el-button></p>
+            v-if="permissions.costAll">{{ $t('feiYongZhuLeiXingGuanLi') }}</el-button></p>
       </div>
       <!-- 上面部分 -->
       <div ref="staff" style="margin: 20px 20px 0 220px; width: 81.5%">
@@ -95,16 +95,16 @@
                 <el-input v-model="addForm.ticketNum" style="width: 150px"></el-input>
               </el-form-item>
               <!-- 费用主类型 -->
-              <el-form-item :label="'费用主类型'">
+              <el-form-item :label="$t('feiYongZhuLeiXing')">
                 <el-select v-model="expenseMainTypeValue" style="width: 150px" @change="this.getExpList">
                   <el-option v-for="item in expenseMainTypes" :key="item.id" :label="item.name"
                     :value="item.id"></el-option>
                 </el-select>
               </el-form-item>
               <!-- 第一审核人 -->
-              <el-form-item label="第一审核人" v-if="auditTypeItem.auditType == 2">
+              <el-form-item :label="$t('di-yi-shen-he-ren')" v-if="auditTypeItem.auditType == 2">
                 <el-select v-if="user.userNameNeedTranslate != '1'" v-model="addForm.firstCheckerId"
-                  :placeholder="'请选择审核人'" style="width: 150px"
+                  :placeholder="$t('message.Pleaseselectareviewer')" style="width: 150px"
                   filterable="true">
                   <span v-for="(item, index) in usersNoInfo" :key="index">
                     <el-option :label="item.name" :value="item.id"></el-option>
@@ -116,9 +116,9 @@
                   @selectCal="selectCal"></selectCat>
               </el-form-item>
               <!-- 第一审核人 -->
-              <el-form-item label="第二审核人" v-if="auditTypeItem.auditType == 2">
+              <el-form-item :label="$t('di-er-shen-he-ren')" v-if="auditTypeItem.auditType == 2">
                 <el-select v-if="user.userNameNeedTranslate != '1'" v-model="addForm.secondCheckerId"
-                  :placeholder="'请选择审核人'" style="width: 150px"
+                  :placeholder="$t('message.Pleaseselectareviewer')" style="width: 150px"
                   filterable="true">
                   <span v-for="(item, index) in usersNoInfo" :key="index">
                     <el-option :label="item.name" :value="item.id"></el-option>
@@ -229,10 +229,10 @@
                 -->
                   <div>
                     <div v-if="scope.row.pic && scope.row.pic.length > 0">
-                      <el-button size="small" @click="viewDetailsImage(scope.$index)">查看详情</el-button>
+                      <el-button size="small" @click="viewDetailsImage(scope.$index)">{{ $t('Checkthedetails') }}</el-button>
                     </div>
                     <div v-else>
-                      <el-button type="primary" size="small" @click="performCustomization(scope.$index)" :loading="listLoading">点击上传</el-button>
+                      <el-button type="primary" size="small" @click="performCustomization(scope.$index)" :loading="listLoading">{{ $t('clickupload') }}</el-button>
                     </div>
                   </div>
                 </template>
@@ -252,7 +252,7 @@
     </div>
 
     <!-- 多张图片查看详情 -->
-    <el-dialog title="查看详情" :visible.sync="dialogVisibleImage" width="745px" :before-close="handleClose">
+    <el-dialog :title="$t('Checkthedetails')" :visible.sync="dialogVisibleImage" width="745px" :before-close="handleClose">
       <div class="dayImge">
         <div class="dayImgeItem" v-if="dialogVisibleImageList">
           <viewer :images="dialogVisibleImageList" v-viewer="viewerOptions" class="dayImgeItem">
@@ -304,8 +304,8 @@
                   style="width: 120px"></el-input>
               </el-form-item>
               <!-- 费用主类型 -->
-              <el-form-item :label="'费用主类型'">
-                <el-select size="small" v-model="queryExpenseMainType" style="width: 150px" clearable placeholder="全部类型">
+              <el-form-item :label="$t('feiYongZhuLeiXing')">
+                <el-select size="small" v-model="queryExpenseMainType" style="width: 150px" clearable :placeholder="$t('typesof')">
                   <el-option v-for="item in expenseMainTypes" :key="item.id" :label="item.name"
                     :value="item.id"></el-option>
                   <!-- <el-option :label="$t('yi-ban')" :value="0"></el-option>
@@ -313,16 +313,16 @@
                 <el-option :label="$t('wai-bao')" :value="2"></el-option> -->
                 </el-select>
               </el-form-item>
-              <el-form-item :label="'发放状态'" v-if="permissions.costExpenseRelease">
+              <el-form-item :label="$t('faFangZhuangTai')" v-if="permissions.costExpenseRelease">
                 <el-select v-model="sendState" size="small" style="width: 150px"
                   clearable>
-                  <el-option :label="'未发放'" :value="0"></el-option>
-                  <el-option :label="'已发放'" :value="1"></el-option>
+                  <el-option :label="$t('weiFaFang')" :value="0"></el-option>
+                  <el-option :label="$t('yiFaFang')" :value="1"></el-option>
                 </el-select>
               </el-form-item>
               <!-- 填报日期 -->
               <div style="display: inline-block;">
-                <el-form-item :label="'项目'">
+                <el-form-item :label="$t('other.project')">
                   <el-select v-model="selectProject" size="small" style="width: 162px" clearable filterable>
                     <el-option v-for="item in projectList" :label="item.projectName" :value="item.id" :key="item.id">
                       <span style="float: left">{{ item.projectName }}</span>
@@ -340,13 +340,13 @@
                   <el-button @click="getList" size="small">{{ $t('find') }}</el-button>
                 </el-form-item>
                 <el-form-item v-if="currentClick == '2-1'">
-                  <el-button @click="exportDocument()" size="small">单据导出</el-button>
+                  <el-button @click="exportDocument()" size="small">{{ $t('danJuDaoChu') }}</el-button>
                 </el-form-item>
                 <el-form-item v-if="currentClick == '2-1' && permissions.costExpenseRelease">
-                  <el-button @click="documentIssuance(1)" size="small">发放</el-button>
+                  <el-button @click="documentIssuance(1)" size="small">{{ $t('faFang') }}</el-button>
                 </el-form-item>
                 <el-form-item v-if="currentClick == '2-1' && permissions.costExpenseRelease">
-                  <el-button @click="documentIssuance(0)" size="small">取消发放</el-button>
+                  <el-button @click="documentIssuance(0)" size="small">{{ $t('quXiaoFaFang') }}</el-button>
                 </el-form-item>
                 <!-- <span>审核模式:{{ auditTypeItem.auditType }}</span> -->
               </div>
@@ -397,11 +397,11 @@
                 <span v-if="scope.row.status == 0 || scope.row.status == 3">{{ statusTxt[scope.row.status] }}</span>
               </template>
             </el-table-column>
-            <el-table-column prop="reviewProcess" :label="'审核流程'" width="180" v-if="auditTypeItem.auditType == 2">
+            <el-table-column prop="reviewProcess" :label="$t('title.reviewProcess')" width="180" v-if="auditTypeItem.auditType == 2">
               <template slot-scope="scope">
-                <span v-if="scope.row.reviewProcess == 0">待第一审核人审核</span>
-                <span v-if="scope.row.reviewProcess == 1">待第二审核人审核</span>
-                <span v-if="scope.row.reviewProcess == 2">审核完成</span>
+                <span v-if="scope.row.reviewProcess == 0">{{ $t('daiDiYiShenHeRenShenHe') }}</span>
+                <span v-if="scope.row.reviewProcess == 1">{{ $t('daiDiErShenHeRenShenHe') }}</span>
+                <span v-if="scope.row.reviewProcess == 2">{{ $t('shenHeWanCheng') }}</span>
               </template>
             </el-table-column>
             <!-- <el-table-column prop="denyReason" :label="$t('dismissreason')" width="180">
@@ -409,13 +409,13 @@
                   <span style="font-size:12px;">{{scope.row.denyReason}}</span>
                 </template>
               </el-table-column> -->
-            <el-table-column prop="sendState" label="发放状态" width="80" v-if="permissions.costExpenseRelease">
+            <el-table-column prop="sendState" :label="$t('faFangZhuangTai')" width="80" v-if="permissions.costExpenseRelease">
               <template slot-scope="scope">
-                <span :style="`color: ${scope.row.sendState == 0 ? '#FFA500' : ''}`">{{ scope.row.sendState == 1 ? '已发放' :
+                <span :style="`color: ${scope.row.sendState == 0 ? '#FFA500' : ''}`">{{ scope.row.sendState == 1 ? $t('yiFaFang') :
                   '未发放' }}</span>
               </template>
             </el-table-column>
-            <el-table-column prop="payWayName" label="支付方式" width="80" v-if="permissions.costExpenseRelease">
+            <el-table-column prop="payWayName" :label="$t('zhiFuFangShi')" width="80" v-if="permissions.costExpenseRelease">
             </el-table-column>
             <el-table-column fixed="right" :label="$t('operation')" :width="isAuditList ? 220 : 160">
               <template slot-scope="scope">
@@ -438,7 +438,7 @@
                       $t('btn.rejected') }}</el-button>
                   </div>
                   <div v-if="auditTypeItem.auditType == 1">
-                    <el-button size="mini" @click.stop.native="approve(scope.row)">审核</el-button>
+                    <el-button size="mini" @click.stop.native="approve(scope.row)">{{ $t('other.audit') }}</el-button>
                   </div>
                 </div>
               </template>
@@ -455,7 +455,7 @@
       </div>
     </div>
     <!-- 我的单据报销展示 -->
-    <el-dialog title="报销凭证详情" :visible.sync="dialog" width="1000px">
+    <el-dialog :title="$t('detailsofReimbursementvoucher')" :visible.sync="dialog" width="1000px">
       <!-- 内容主体 -->
       <div class="informant"><!--  报销人 -->
         <el-form :model="ParticularsList" label-width="100px">
@@ -477,9 +477,9 @@
 
           </el-form-item>
           <!-- 第一审核人 -->
-          <el-form-item label="第一审核人" v-if="auditTypeItem.auditType == 2">
+          <el-form-item :label="$t('di-yi-shen-he-ren')" v-if="auditTypeItem.auditType == 2">
             <el-select v-if="user.userNameNeedTranslate != '1'" v-model="ParticularsList.firstCheckerId"
-              :placeholder="'请选择审核人'" style="width: 150px" :disabled="ParticularsList.reviewProcess > 0"
+              :placeholder="$t('message.Pleaseselectareviewer')" style="width: 150px" :disabled="ParticularsList.reviewProcess > 0"
               filterable="true">
               <span v-for="(item, index) in users" :key="index">
                 <el-option :label="item.name" :value="item.id"></el-option>
@@ -491,9 +491,9 @@
               @selectCal="selectCal"></selectCat>
           </el-form-item>
           <!-- 第二审核人 -->
-          <el-form-item label="第二审核人" v-if="auditTypeItem.auditType == 2">
+          <el-form-item :label="$t('di-er-shen-he-ren')" v-if="auditTypeItem.auditType == 2">
             <el-select v-if="user.userNameNeedTranslate != '1'" v-model="ParticularsList.secondCheckerId"
-              :placeholder="'请选择审核人'" style="width: 150px" :disabled="ParticularsList.reviewProcess > 1"
+              :placeholder="$t('message.Pleaseselectareviewer')" style="width: 150px" :disabled="ParticularsList.reviewProcess > 1"
               filterable="true">
               <span v-for="(item, index) in users" :key="index">
                 <el-option :label="item.name" :value="item.id"></el-option>
@@ -530,14 +530,14 @@
           }}</span>
         </div>
         <el-table :data="ParticularsList.invoiceList" border style="width: 100%">
-          <el-table-column prop="status" label="审核状态" width="172" v-if="auditTypeItem.auditType == 1">
+          <el-table-column prop="status" :label="$t('other.approvalStatus')" width="172" v-if="auditTypeItem.auditType == 1">
             <template slot-scope="scope">
               <span v-if="scope.row.status == 1" class="waiting">{{ statusTxt[scope.row.status] }}</span>
               <span v-if="scope.row.status == 2" class="rejected">{{ statusTxt[scope.row.status] }}</span>
               <span v-if="scope.row.status == 0 || scope.row.status == 3">{{ statusTxt[scope.row.status] }}</span>
             </template>
           </el-table-column>
-          <el-table-column v-if="auditTypeItem.auditType == 1" width="172" label="审核人">
+          <el-table-column v-if="auditTypeItem.auditType == 1" width="172" :label="$t('other.reviewer')">
             <template slot-scope="scope">
               <span v-if="user.userNameNeedTranslate == 1">
                 <TranslationOpenDataText type='userName' :openid='scope.row.projectManagerName'></TranslationOpenDataText>
@@ -648,10 +648,10 @@
               </div> -->
               <div>
                 <div v-if="scope.row.pic && scope.row.pic.length > 0">
-                  <el-button size="small" @click="viewDetailsImage(scope.$index, 'ParticularsList', 'invoiceList')">查看详情</el-button>
+                  <el-button size="small" @click="viewDetailsImage(scope.$index, 'ParticularsList', 'invoiceList')">{{ $t('Checkthedetails') }}</el-button>
                 </div>
                 <div v-else>
-                  <el-button type="primary" size="small" @click="performCustomization(scope.$index, 2)" :loading="listLoading">点击上传</el-button>
+                  <el-button type="primary" size="small" @click="performCustomization(scope.$index, 2)" :loading="listLoading">{{ $t('clickupload') }}</el-button>
                 </div>
               </div>
             </template>
@@ -663,12 +663,12 @@
                 @click="delec(scope.$index)">{{ $t('btn.delete') }}</el-button>
             </template>
           </el-table-column>
-          <el-table-column prop="status" label="审核" width="172" v-if="auditTypeItem.auditType == 1 && showSingleAudit"
+          <el-table-column prop="status" :label="$t('other.audit')" width="172" v-if="auditTypeItem.auditType == 1 && showSingleAudit"
             fixed="right">
             <template slot-scope="scope">
               <el-button v-if="scope.row.isIncharger && scope.row.status == 1"
-                @click="approveSingle(scope.row)">通过</el-button><el-button
-                v-if="scope.row.isIncharger && scope.row.status == 1" @click="denySingle(scope.row)">驳回</el-button>
+                @click="approveSingle(scope.row)">{{ $t('btn.through') }}</el-button><el-button
+                v-if="scope.row.isIncharger && scope.row.status == 1" @click="denySingle(scope.row)">{{ $t('btn.rejected') }}</el-button>
             </template>
           </el-table-column>
         </el-table>
@@ -711,15 +711,15 @@
 
 
     <!-- 主费用类型自定义 -->
-    <el-dialog title="费用类型大类管理" v-if="expenseTypeDialog" :visible.sync="expenseTypeDialog" customClass="customWidth"
+    <el-dialog :title="$t('feiYongLeiXingDaLeiGuanLi')" v-if="expenseTypeDialog" :visible.sync="expenseTypeDialog" customClass="customWidth"
       width="600px">
       <el-table :data="expenseMainTypes" style="width:100%" height="400" :loading="expenseTypeListLoading">
-        <el-table-column :label="'类型名称'" min-width="150">
+        <el-table-column :label="$t('typename ')" min-width="150">
           <template slot-scope="scope">
             <span>{{ scope.row.name }}</span>
           </template>
         </el-table-column>
-        <el-table-column :label="'对应成本项'" min-width="150">
+        <el-table-column :label="$t('duiYingChengBenXiang')" min-width="150">
           <template slot-scope="scope">
             <span>{{ scope.row.basecostSettingName }}</span>
           </template>
@@ -747,7 +747,7 @@
               :placeholder="$t('customizethfeetypename')" style="width:90%"
               @keyup.native="editExpenseTypeDataInput('editExpenseTypeDataInput')"></el-input>
           </el-form-item>
-          <el-form-item label="对应成本项" style="margin:30px 0" prop="basecostSettingId">
+          <el-form-item :label="$t('duiYingChengBenXiang')" style="margin:30px 0" prop="basecostSettingId">
             <el-select v-model="editExpenseTypeData.basecostSettingId" size="medium" style="width:90%" clearable>
               <el-option v-for="item in basecostSettingList" :key="item.id" :label="item.name" :value="item.id"
                 :disabled="item.alarmType == 1"></el-option>
@@ -819,11 +819,11 @@
     </el-dialog>
 
     <!-- 详情查看弹出框 -->
-    <el-dialog title="报销凭证详情" :visible.sync="detailDialog" width="1100px" :before-close="handleClose">
+    <el-dialog :title="$t('detailsofReimbursementvoucher')" :visible.sync="detailDialog" width="1100px" :before-close="handleClose">
       <div ref="printContent" class="printContent">
         <div class="printContent-detail">
           <div class="detail-item">
-            <span class="detail-item-title"> <span class="printBox">报销人</span> </span>
+            <span class="detail-item-title"> <span class="printBox">{{ $t('peopleconcerned') }}</span> </span>
             <span class="detail-item-content">
               <span v-if="user.userNameNeedTranslate == 1">
                 <TranslationOpenDataText type='userName' :openid='ParticularsList.ownerName'></TranslationOpenDataText>
@@ -832,23 +832,23 @@
             </span>
           </div>
           <div class="detail-item">
-            <span class="detail-item-title"><span class="printBox">填报时间</span></span>
+            <span class="detail-item-title"><span class="printBox">{{ $t('tianBaoShiJian') }}</span></span>
             <span class="detail-item-content">{{ ParticularsList.createDate }}</span>
           </div>
           <div class="detail-item">
-            <span class="detail-item-title"><span class="printBox">发票张数</span></span>
-            <span class="detail-item-content">{{ ParticularsList.ticketNum }} </span>
+            <span class="detail-item-title"><span class="printBox">{{ $t('invoicenumber') }}</span></span>
+            <span class="detail-item-content">{{ ParticularsList.ticketNum }} {{ $t('zhang') }}</span>
           </div>
           <div class="detail-item">
-            <span class="detail-item-title"><span class="printBox">费用类型:</span></span>
+            <span class="detail-item-title"><span class="printBox">{{ $t('feiYongLeiXing') }}</span></span>
             <span class="detail-item-content">{{ detaExpenseMainTypeName }}</span>
           </div>
           <div class="detail-item">
-            <span class="detail-item-title"><span class="printBox">总费用</span></span>
+            <span class="detail-item-title"><span class="printBox">{{ $t('totalcostos') }}</span></span>
             <span class="detail-item-content">¥ {{ ParticularsList.totalAmount | numberToCurrency }}</span>
           </div>
           <div class="detail-item" style="width: 100%">
-            <span class="detail-item-title"><span class="printBox">备注</span></span>
+            <span class="detail-item-title"><span class="printBox">{{ $t('bei-zhu') }}</span></span>
             <span class="detail-item-content">{{ ParticularsList.remark }}</span>
           </div>
         </div>
@@ -978,7 +978,7 @@
         <div class="conter-box">
           <div class="conter-border" v-for="item, index in ParticularsList.invoiceList" :key="index">
             <div class="detail-item" v-if="auditTypeItem.auditType != 1">
-              <span class="detail-item-title"> <span class="printBox">项目</span> </span>
+              <span class="detail-item-title"> <span class="printBox">{{ $t('other.project') }}</span> </span>
               <span class="detail-item-content">
                 {{ item.projectName }}
                 <!-- <el-select size="small" v-if="!flg" v-model="item.projectId" :placeholder="$t('other.project')"
@@ -997,7 +997,7 @@
               </span>
             </div>
             <div class="detail-item" v-if="auditTypeItem.auditType == 1">
-              <span class="detail-item-title"> <span class="printBox">项目(审核状态)</span> </span>
+              <span class="detail-item-title"> <span class="printBox">{{ $t('xiangMuShenHeZhuangTai') }}</span> </span>
               <span class="detail-item-content">
                 <span v-if="item.status == 1" class="waiting">{{ statusTxt[item.status] }}</span>
                 <span v-if="item.status == 2" class="rejected">{{ statusTxt[item.status] }}</span>
@@ -1005,39 +1005,39 @@
               </span>
             </div>
             <div class="detail-item">
-              <span class="detail-item-title"> <span class="printBox">费用日期</span> </span>
+              <span class="detail-item-title"> <span class="printBox">{{ $t('forthedate') }}</span> </span>
               <span class="detail-item-content">{{ item.happenDate }}</span>
             </div>
             <div class="detail-item">
-              <span class="detail-item-title"> <span class="printBox">发票种类</span> </span>
+              <span class="detail-item-title"> <span class="printBox">{{ $t('invoices') }}</span> </span>
               <span class="detail-item-content">{{ typeInvoic[item.invoiceType] }}</span>
             </div>
             <div class="detail-item">
-              <span class="detail-item-title"> <span class="printBox">费用类型</span> </span>
+              <span class="detail-item-title"> <span class="printBox">{{ $t('costtype') }}</span> </span>
               <span class="detail-item-content">{{ item.expenseType }}</span>
             </div>
             <div class="detail-item">
-              <span class="detail-item-title single"> <span class="printBox">费用金额(含税)</span> </span>
+              <span class="detail-item-title single"> <span class="printBox">{{ $t('feiYongJineHanShui') }}</span> </span>
               <span class="detail-item-content">{{ item.amount }}</span>
             </div>
             <div class="detail-item">
-              <span class="detail-item-title"> <span class="printBox">发票号</span> </span>
+              <span class="detail-item-title"> <span class="printBox">{{ $t('invoiceno') }}</span> </span>
               <span class="detail-item-content">{{ item.invoiceNo }}</span>
             </div>
             <div class="detail-item">
-              <span class="detail-item-title"> <span class="printBox">税率%</span> </span>
+              <span class="detail-item-title"> <span class="printBox">{{ $t('shui-shuai') }}</span> </span>
               <span class="detail-item-content">{{ item.taxValue }}</span>
             </div>
             <div class="detail-item">
-              <span class="detail-item-title"> <span class="printBox">税额</span> </span>
+              <span class="detail-item-title"> <span class="printBox">{{ $t('taxs') }}</span> </span>
               <span class="detail-item-content">{{ item.taxValue ? `¥${item.taxValue}` : '' }}</span>
             </div>
             <div class="detail-item">
-              <span class="detail-item-title"> <span class="printBox">备注</span> </span>
+              <span class="detail-item-title"> <span class="printBox">{{ $t('bei-zhu') }}</span> </span>
               <span class="detail-item-content">{{ item.remark }}</span>
             </div>
             <div class="detail-item" style="display: flex">
-              <span class="detail-item-title"> <span class="printBox">报销凭证</span> </span>
+              <span class="detail-item-title"> <span class="printBox">{{ $t('expensereimbursementvoucher') }}</span> </span>
               <div class="detail-item-content">
                 <div v-if="item.pic" style="display: inline-block;">
                   <div class="tups">
@@ -1058,8 +1058,8 @@
         </div>
       </div>
       <span slot="footer" class="dialog-footer">
-        <el-button @click="print()">打 印</el-button>
-        <el-button @click="detailDialog = false">关 闭</el-button>
+        <el-button @click="print()">{{ $t('daYin') }}</el-button>
+        <el-button @click="detailDialog = false">{{ $t('guanBi') }}</el-button>
       </span>
     </el-dialog>
 
@@ -1069,15 +1069,15 @@
     </div>
 
     <!-- 发放支付方式 -->
-    <el-dialog title="发放方式" :visible.sync="dialogVisibleRelease" width="400px" :before-close="handleClose">
+    <el-dialog :title="$t('faFangFangShi')" :visible.sync="dialogVisibleRelease" width="400px" :before-close="handleClose">
       <div>
-        <el-select v-model="releaseData.id" placeholder="请选择支付方式" style="width: 100%" clearable>
+        <el-select v-model="releaseData.id" :placeholder="$t('qingXuanZeZhiFuFangShi')" style="width: 100%" clearable>
           <el-option v-for="item in sendStateList" :key="item.id" :label="item.name" :value="item.id"></el-option>
         </el-select>
       </div>
       <span slot="footer" class="dialog-footer">
-        <el-button @click="dialogVisibleRelease = false">取 消</el-button>
-        <el-button type="primary" @click="callingInterface(1, releaseData.data)">确 定</el-button>
+        <el-button @click="dialogVisibleRelease = false">{{ $t('quXiao') }}</el-button>
+        <el-button type="primary" @click="callingInterface(1, releaseData.data)">{{ $t('queDing') }}</el-button>
       </span>
     </el-dialog>
   </section>
@@ -1737,7 +1737,7 @@ export default {
       let noAmount = paramData.invoiceList.filter(item => !item.amount)
       if(noAmount.length > 0) {
         this.$message({
-          message: '请填写完整费用金额',
+          message: this.$t('qingTianXieWanZhengFeiYongJinE'),
           type: "error"
         });
         return;
@@ -1812,7 +1812,7 @@ export default {
         if (valid) {
           if(this.auditTypeItem.auditType == 2 && (!this.addForm.firstCheckerId || !this.addForm.secondCheckerId)) {
             this.$message({
-              message: !this.addForm.firstCheckerId ? '请选择第一审核人' : '请选择第二审核人',
+              message: !this.addForm.firstCheckerId ? this.$t('qingXuanZeDiYiShenHeRen') : this.$t('qingXuanZeDiErShenHeRen'),
               type: "error"
             });
             return;
@@ -1834,7 +1834,7 @@ export default {
           }
           for (var i in this.invoiceList) {
             if (!this.invoiceList[i].projectId) {
-              strObj.project = '所属项目'
+              strObj.project = this.$t('subordinatetotheproject')
               strObj.flg = true
             }
             // if(!this.invoiceList[i].invoiceType || this.invoiceList[i].invoiceType == '') {
@@ -1842,21 +1842,21 @@ export default {
             //   strObj.flg = true
             // }
             if (!this.invoiceList[i].expenseType || this.invoiceList[i].expenseType == '') {
-              strObj.fyType = '费用类型'
+              strObj.fyType = this.$t('costtype')
               strObj.flg = true
             }
             if (!this.invoiceList[i].happenDate || this.invoiceList[i].happenDate == '') {
-              strObj.datas = '费用日期'
+              strObj.datas = this.$t('forthedate')
               strObj.flg = true
             }
             if (!this.invoiceList[i].amount || this.invoiceList[i].amount == '') {
-              strObj.rmb = '费用金额'
+              strObj.rmb = this.$t('feiYongJinE')
               strObj.flg = true
             }
           }
           if (strObj.flg) {
             this.$message({
-              message: `${strObj.project} ${strObj.fptype} ${strObj.fyType} ${strObj.datas} ${strObj.rmb} 请填写完整`,
+              message: `${strObj.project} ${strObj.fptype} ${strObj.fyType} ${strObj.datas} ${strObj.rmb} ${this.$t('qingTianXieWanZheng')}`,
               type: "error"
             });
             return;
@@ -2075,7 +2075,7 @@ export default {
                     name: item,
                     url: `/upload/${item}`,
                     // url: `http://47.101.180.183/upload/${item}`,
-                    title: '报销凭证'
+                    title: this.$t('expensereimbursementvoucher')
                   }
                 })
               }
@@ -2336,7 +2336,7 @@ export default {
       const sums = [];
       columns.forEach((column, index) => {
         if (index === 1) {
-          sums[index] = '本页金额合计';//this.$t('other.totals');
+          sums[index] = this.$t('benYeJineheJi');//this.$t('other.totals');
           return;
         }
         if (index === 2) {
@@ -2407,7 +2407,7 @@ export default {
           if (res.code == "ok") {
             var filePath = res.data;
             const a = document.createElement('a'); // 创建a标签
-            a.setAttribute('download', '费用报销单据列表');// download属性
+            a.setAttribute('download', this.$t('feiYongBaoXiaoDanJuLieBiao'));// download属性
             a.setAttribute('href', filePath);// href链接
             a.click(); //自执行点击事件
             a.remove();
@@ -2439,17 +2439,17 @@ export default {
       };
 
       if (newList.length > 0) {
-        showMessage('存在待审核或已驳回的单据', 'warning');
+        showMessage(this.$t('cunZaiDaiShenHeHuoYiBoHuiDeDanJu'), 'warning');
         return;
       }
 
       if (type == 1 && unissueds.length == 0) {
-        showMessage('请选择未发放的单据', 'warning');
+        showMessage(this.$t('qingXuanZeWeiFaFangDeDanJu'), 'warning');
         return;
       }
 
       if (type == 0 && Issueds.length == 0) {
-        showMessage('请选择已发放的单据', 'warning');
+        showMessage(this.$t('qingXuanZeYiFaFangDeDanJu'), 'warning');
         return;
       }
 
@@ -2473,7 +2473,7 @@ export default {
           this.dialogVisibleRelease = false
           if (res.code == "ok") {
             this.$message({
-              message: '操作成功',
+              message: this.$t('operationissuccessful'),
               type: "success"
             });
             this.getList()
@@ -2552,7 +2552,7 @@ export default {
                 name: item,
                 url: '/upload/' + item,
                 // url: `http://47.101.180.183/upload/${item}`,
-                title: '报销凭证'
+                title: this.$t('expensereimbursementvoucher')
               }
             })
             if(this.imgLoadType == 1) {

+ 20 - 20
fhKeeper/formulahousekeeper/timesheet/src/views/financeAudit/financeAudit.vue

@@ -2,17 +2,17 @@
     <div class='financeAudit'>
         <div class="fAd_hrader">
             <div class="items">
-                <div class="label">年月:</div>
+                <div class="label">{{ $t('nianYue') }}</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 v-model="tableForm.dates" type="monthrange" :range-separator="$t('other.to')" :start-placeholder="$t('time.startDate')"
+                        @change="getFinanceAuditTableData()" size="small" value-format="yyyy-MM" :end-placeholder="$t('time.endDate')" :clearable="false">
                     </el-date-picker>
                 </div>
             </div>
             <div class="items">
-                <div class="label">审核状态:</div>
+                <div class="label">{{ $t('shenHeZhuangTai') }}</div>
                 <div class="value">
-                    <el-select v-model="tableForm.status" placeholder="请选择" size="small"
+                    <el-select v-model="tableForm.status" :placeholder="$t('defaultText.pleaseChoose')" size="small"
                         @change="getFinanceAuditTableData()">
                         <el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value">
                         </el-option>
@@ -23,22 +23,22 @@
         <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">
+                <el-table-column prop="reportYrmnth" :label="$t('riBaoNianYue')" 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">
+                <el-table-column prop="reviewerName" :label="$t('other.reviewer')" align="center"></el-table-column>
+                <el-table-column prop="reviewTime" :label="$t('AuditTime')" align="center"></el-table-column>
+                <el-table-column prop="reviewStatus" :label="$t('state.states')" align="center">
                     <template slot-scope="scope">
-                        {{ scope.row.reviewStatus == 1 ? '未审核' : '已审核' }}
+                        {{ scope.row.reviewStatus == 1 ? $t('weiShenHe') : $t('yiShenHe') }}
                     </template>
                 </el-table-column>
-                <el-table-column label="操作" align="center" fixed="right">
+                <el-table-column :label="$t('operation')" 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>
+                        <el-button @click="audit(scope.row)" type="text" v-if="scope.row.reviewStatus == 1">{{ $t('other.audit') }}</el-button>
+                        <el-button type="text" @click="toDetail(scope.row)">{{ $t('Checkthedetails') }}</el-button>
                     </template>
                 </el-table-column>
             </el-table>
@@ -65,9 +65,9 @@ export default {
             },
             financeAuditTableData: [],
             statusOptions: [
-                { value: 0, label: '全部' },
-                { value: 1, label: '未审核' },
-                { value: 2, label: '已审核' },
+                { value: 0, label: this.$t('all') },
+                { value: 1, label: this.$t('weiShenHe') },
+                { value: 2, label: this.$t('yiShenHe') },
             ],
             paging: {
                 pageSize: 50,
@@ -100,15 +100,15 @@ export default {
             })
         },
         audit(item) {
-            this.$confirm(`您确定要审核通过${item.reportYrmnth}月的工时报告吗?`, '财务审核提示', {
-                confirmButtonText: '确定',
-                cancelButtonText: '取消',
+            this.$confirm(`${this.$t('ninQueDingYaoShenHeTongGuo')}${item.reportYrmnth} ${this.$t('yueDeGongShiBaoGaoMa')}`, this.$t('caiWuShenHeTiShi'), {
+                confirmButtonText: this.$t('btn.determine'),
+                cancelButtonText: this.$t('btn.cancel'),
                 type: 'warning'
             }).then(() => {
                 this.postData('/financial-audit/audit', { id: item.id }).then(res => {
                     this.$message({
                         type: 'success',
-                        message: '审核成功!'
+                        message: this.$t('shenHeChengGong')
                     });
                     this.getFinanceAuditTableData();
                 });

+ 21 - 21
fhKeeper/formulahousekeeper/timesheet/src/views/leave/list.vue

@@ -31,7 +31,7 @@
 
           <el-menu-item index="2" @select="bills" @click="auditList()" v-if="permissions.leaveAudit">
               <i class="iconfont firerock-iconshenhe"></i>
-              <span slot="title">请假审核</span>
+              <span slot="title">{{ $t('qingJiaShenHe') }}</span>
             </el-menu-item>
             <el-menu-item index="3" @select="bills" @click="bills(false, 2)" >
               <i class="iconfont firerock-iconbaoxiaodan"></i>
@@ -164,16 +164,16 @@
                     <el-input type="textarea" v-model="addForm.remark" :rows="5" style="width: 550px" maxlength="100" show-word-limit></el-input>
                 </el-form-item>
                 <!--请假流程显示-->
-                <el-form-item label="审批流程" style="width: 100%;color:#606266" >
+                <el-form-item :label="$t('other.approvalProcess')" style="width: 100%;color:#606266" >
                   <span v-for="(item, index) in curWorkflowList" :key="item.id" >
                     <span v-if="index>0"><i class="el-icon-right"></i></span>
                     <span><i class="el-icon-s-custom"></i></span>
                     <span v-if="user.userNameNeedTranslate == 1">
-                      <span v-if="item.auditorType == 1"><TranslationOpenDataText type='departmentName' :openid='item.auditDeptName' ></TranslationOpenDataText>(主要负责人)</span>
+                      <span v-if="item.auditorType == 1"><TranslationOpenDataText type='departmentName' :openid='item.auditDeptName' ></TranslationOpenDataText>{{ $t('zhu-yao-fu-ze-ren') }}</span>
                       <TranslationOpenDataText type='userName' :openid='item.userName' v-if="item.auditorType == 2"></TranslationOpenDataText>
                     </span>
                     <span v-if="user.userNameNeedTranslate == 0">
-                      {{item.auditorType == 1?(item.auditDeptName+'(主要负责人)'):item.userName}}
+                      {{item.auditorType == 1 ? (`${item.auditDeptName} ${$t('zhu-yao-fu-ze-ren')}`) : item.userName}}
                     </span>
                   </span>
                 </el-form-item>
@@ -277,8 +277,8 @@
                           <TranslationOpenDataText type='userName' :openid='scope.row.auditorName'></TranslationOpenDataText>
                         </span>
                       </div>
-                      <div v-if="scope.row.status == 2" style="color: red">{{ $t('btn.rejected') }}<el-link style="margin-left:5px;" @click="showDenyReason(scope.row.id)">查看原因</el-link></div>
-                      <div v-if="scope.row.status == 3" style="color: #666666">已撤回</div>
+                      <div v-if="scope.row.status == 2" style="color: red">{{ $t('btn.rejected') }}<el-link style="margin-left:5px;" @click="showDenyReason(scope.row.id)">{{ $t('chaKanYuanYin') }}</el-link></div>
+                      <div v-if="scope.row.status == 3" style="color: #666666">{{ $t('yiCheHui') }}</div>
                     </div>
                     <div v-else>
                       <span>{{ $t('norequestforleaveatpresent') }}</span>
@@ -305,9 +305,9 @@
                     <template slot-scope="scope">
                       <!-- <div v-if="(scope.row.status != 0 && scope.row.ownerId == user.id) || permissions.leaveAll"> -->
                       <div v-if="(scope.row.status != 0 || permissions.leaveAll) && scope.row.ownerId == user.id">
-                        <el-button size="mini" v-if="scope.row.status == 3 ||scope.row.status == 2" @click.stop.native="deletes(scope.row)" >删除</el-button>
-                        <el-button size="mini" v-if="scope.row.status == 1" @click.stop.native="cancel(scope.row)">撤回</el-button>
-                        <el-button size="mini" v-if="scope.row.status == 3 ||scope.row.status == 2 " type="primary" @click.stop.native="editor(scope.row)">重新提交</el-button>
+                        <el-button size="mini" v-if="scope.row.status == 3 ||scope.row.status == 2" @click.stop.native="deletes(scope.row)" >{{ $t('btn.delete') }}</el-button>
+                        <el-button size="mini" v-if="scope.row.status == 1" @click.stop.native="cancel(scope.row)">{{ $t('btn.withdraw') }}</el-button>
+                        <el-button size="mini" v-if="scope.row.status == 3 ||scope.row.status == 2 " type="primary" @click.stop.native="editor(scope.row)">{{ $t('zhong-xin-ti-jiao') }}</el-button>
                       </div>
                     </template>
                 </el-table-column>
@@ -731,8 +731,8 @@
                 <el-timeline-item v-for="item in auditLogList" :key="item.id" :timestamp="item.indate">
                   <span v-if="user.userNameNeedTranslate == 1"><TranslationOpenDataText type='userName' :openid='item.auditorName'></TranslationOpenDataText> </span>
                   <span v-if="user.userNameNeedTranslate == 0">{{item.auditorName}}</span>
-                  <span> {{item.isPass==0?"驳回了请假申请。":"审核通过。"}}</span>
-                  <span v-if="item.isPass == 0">原因:{{item.denyReason}}</span>
+                  <span> {{item.isPass==0?$t('boHuiLeQingJiaShenQing'):$t('state.approved')}}</span>
+                  <span v-if="item.isPass == 0">{{ $t('other.reason') }} :{{item.denyReason}}</span>
                   </el-timeline-item>
             </el-timeline>
         </div>
@@ -1025,7 +1025,7 @@ export default {
         if(res.code == 'ok'){
           var filePath = res.data;
           const a = document.createElement('a'); // 创建a标签
-          a.setAttribute('download', '请假单');// download属性
+          a.setAttribute('download', this.$t('qingJiaDan'));// download属性
           a.setAttribute('href', filePath);// href链接
           a.click(); //自执行点击事件
           a.remove();
@@ -1065,7 +1065,7 @@ export default {
         if(res.code == 'ok'){
           var filePath = res.data;
           const a = document.createElement('a'); // 创建a标签
-          a.setAttribute('download', '剩余假期');// download属性
+          a.setAttribute('download', this.$t('shengYuJiaQi'));// download属性
           a.setAttribute('href', filePath);// href链接
           a.click(); //自执行点击事件
           a.remove();
@@ -1466,12 +1466,12 @@ export default {
               if(!flgUserRadio) {
                 if(node.type == 'dep') {
                   this.$message({
-                      message: '已存在重复部门',
+                      message: this.$t('yi-cun-zai-zhong-fu-bu-men'),
                       type: "error"
                   });
                 } else {
                   this.$message({
-                      message: '已存在重复人员',
+                      message: this.$t('yi-cun-zai-zhong-fu-ren-yuan'),
                       type: "error"
                   });
                 }
@@ -1544,7 +1544,7 @@ export default {
           });
       } else {
         this.$message({
-            message: '至少选择一个部门或者人员做为审核人',
+            message: this.$t('zhi-shao-xuan-ze-yi-ge-bu-men-huo-zhe-ren-yuan-zuo-wei-shen-he-ren'),
             type: "error"
         });
       }
@@ -1559,7 +1559,7 @@ export default {
             if (res.code == "ok") {
                 this.auditList();
                 this.$message({
-                        message: '操作成功',
+                        message: this.$t('operationissuccessful'),
                         type: "success"
                         });
             } else {
@@ -1587,7 +1587,7 @@ export default {
         res => {
             if (res.code == "ok") {
                 this.$message({
-                        message: '操作成功',
+                        message: this.$t('operationissuccessful'),
                         type: "success"
                 });
             } else {
@@ -1614,7 +1614,7 @@ export default {
                 this.auditList();
                 this.denyDialogV = false;
                 this.$message({
-                        message: '操作成功',
+                        message: this.$t('operationissuccessful'),
                         type: "success"
                         });
             } else {
@@ -2102,7 +2102,7 @@ export default {
       // console.log(this.addForm)
     },
     cancel(e) {
-      this.$confirm('确定要撤回该请假申请吗', this.$t('other.prompts'), {
+      this.$confirm(this.$t('queDingYaoCheHuiGaiQingJiaShenQingMa'), this.$t('other.prompts'), {
           //type: 'warning'
       }).then(() => {
           this.http.post('/leave-sheet/cancel', {id:e.id},
@@ -2110,7 +2110,7 @@ export default {
               if (res.code == "ok") {
                   this.bills();
                   this.$message({
-                      message: '操作成功',
+                      message: this.$t('operationissuccessful'),
                       type: "success"
                   });
               } else {

+ 17 - 17
fhKeeper/formulahousekeeper/timesheet/src/views/market/list.vue

@@ -3,7 +3,7 @@
         <!--工具条-->
         <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
             <el-form :inline="true">
-                <el-form-item label="公司列表">
+                <el-form-item :label="$t('gongSiLieBiao')">
                     
                 </el-form-item>
             </el-form>
@@ -16,20 +16,20 @@
                         {{scope.$index+1+(page-1)*size}}
                     </template>
             </el-table-column>
-            <el-table-column prop="companyName" label="公司名称"  ></el-table-column>
-            <el-table-column prop="cTime" label="注册时间"  ></el-table-column>
-            <el-table-column prop="name" label="联系人" ></el-table-column>
-            <el-table-column prop="phone" label="联系方式"  width="150"></el-table-column>
-            <el-table-column prop="contacted" label="是否联系" >
+            <el-table-column prop="companyName" :label="$t('gongSiMingCheng')"  ></el-table-column>
+            <el-table-column prop="cTime" :label="$t('zhuCeShiJian')"  ></el-table-column>
+            <el-table-column prop="name" :label="$t('contact')" ></el-table-column>
+            <el-table-column prop="phone" :label="$t('lianXiFangShi')"  width="150"></el-table-column>
+            <el-table-column prop="contacted" :label="$t('shiFouLianXi')" >
                 <template slot-scope="scope">
-                    <font v-if="scope.row.contacted" color="green">已联系</font>
-                    <font v-if="!scope.row.contacted" color="red">未联系</font>
+                    <font v-if="scope.row.contacted" color="green">{{ $t('yiLianXi') }}</font>
+                    <font v-if="!scope.row.contacted" color="red">{{ $t('weiLianXi') }}</font>
                 </template>
             </el-table-column>
-            <el-table-column prop="feedback" label="客户反馈" ></el-table-column>
-            <el-table-column label="操作" width="290">
+            <el-table-column prop="feedback" :label="$t('keHuFanKui')" ></el-table-column>
+            <el-table-column :label="$t('operation')" width="290">
                 <template slot-scope="scope">
-                    <el-button size="small" type="primary" @click="handleAdd(scope.$index, scope.row)">填写反馈</el-button>
+                    <el-button size="small" type="primary" @click="handleAdd(scope.$index, scope.row)">{{ $t('tianXieFanKui') }}</el-button>
                 </template>
             </el-table-column>
         </el-table>
@@ -51,16 +51,16 @@
         <el-dialog :title="title" v-if="addFormVisible" :visible.sync="addFormVisible" :close-on-click-modal="false" customClass="customWidth" width="600px">
             <el-form ref="form1" :model="addForm" :rules="rules" label-width="100px">
                 
-                <el-form-item label="公司名称" prop="companyName">
+                <el-form-item :label="$t('gongSiMingCheng')" prop="companyName">
                     {{addForm.companyName}}
                 </el-form-item>
-                <el-form-item label="反馈结果">
+                <el-form-item :label="$t('fanKuiJieGuo')">
                     <el-input type="area" v-model="addForm.feedback"></el-input>
                 </el-form-item>
             </el-form>
             <div slot="footer" class="dialog-footer">
-                <el-button @click.native="addFormVisible = false">取消</el-button>
-                <el-button type="primary" @click="submitInsert" :loading="addLoading">提交</el-button>
+                <el-button @click.native="addFormVisible = false">{{ $t('quXiao') }}</el-button>
+                <el-button type="primary" @click="submitInsert" :loading="addLoading">{{ $t('tiJiao') }}</el-button>
             </div>
         </el-dialog>
 
@@ -113,7 +113,7 @@
                     feedback:null,
                 },
                 rules: {
-                    feedback: [{ required: true, message: "请输入客户反馈", trigger: "blur" }],
+                    feedback: [{ required: true, message: this.$t('qingShuRuKeHuFanKui'), trigger: "blur" }],
                 }
             };
         },
@@ -194,7 +194,7 @@
                             this.addLoading = false;
                             if (res.code == "ok") {
                                 this.$message({
-                                    message: "填写成功",
+                                    message: this.$t('tianXieChengGong'),
                                     type: "success"
                                 });
                                 this.addFormVisible = false;

+ 7 - 7
fhKeeper/formulahousekeeper/timesheet/src/views/message.vue

@@ -4,7 +4,7 @@
     <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
       <el-form :inline="true">
         <el-col :span="2">
-          <el-form-item>消息中心</el-form-item>
+          <el-form-item>{{ $t('other.messageCenter') }}</el-form-item>
         </el-col>
       </el-form>
     </el-col>
@@ -12,9 +12,9 @@
     <!--选项卡-->
     <el-col :span="24">
       <el-tabs v-model="activePage" @tab-click="handleClick" type="card">
-        <el-tab-pane name="0" label="审批">
+        <el-tab-pane name="0" :label="$t('shenPi')">
           <div :style="heightString">
-            <span v-if="messages[0].length == 0">目前暂无消息</span>
+            <span v-if="messages[0].length == 0">{{ $t('muQianZanWuXiaoXi') }}</span>
             <div
               class="message-div"
               v-for="item,index in messages[0]"
@@ -42,9 +42,9 @@
             ></el-pagination>
           </el-col>
         </el-tab-pane>
-        <el-tab-pane name="1" label="警告">
+        <el-tab-pane name="1" :label="$t('jingGao')">
           <div :style="heightString">
-            <span v-if="messages[1].length == 0">目前暂无消息</span>
+            <span v-if="messages[1].length == 0">{{ $t('muQianZanWuXiaoXi') }}</span>
             <div
               class="message-div"
               v-for="item,index in messages[1]"
@@ -72,9 +72,9 @@
             ></el-pagination>
           </el-col>
         </el-tab-pane>
-        <el-tab-pane name="2" label="保养">
+        <el-tab-pane name="2" :label="$t('baoYang')">
           <div :style="heightString">
-            <span v-if="messages[2].length == 0">目前暂无消息</span>
+            <span v-if="messages[2].length == 0">{{ $t('muQianZanWuXiaoXi') }}</span>
             <div
               class="message-div"
               v-for="item,index in messages[2]"

+ 18 - 18
fhKeeper/formulahousekeeper/timesheet/src/views/profession/list.vue

@@ -3,18 +3,18 @@
         <!--工具条-->
         <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
             <el-form :inline="true">
-                <el-form-item label="工程专业列表">
+                <el-form-item :label="$t('gongChengZhuanYeLieBiao')">
                     
                 </el-form-item>
                 <el-form-item >
                     <div>
-                    <el-input style="float:left;" v-model="keyword" class="input-with-select" placeholder="请输入专业名称关键字" clearable="true" @keyup.enter.native="searchList()">
+                    <el-input style="float:left;" v-model="keyword" class="input-with-select" :placeholder="$t('qingShuRuZhuanYeMingChengGuanJianZi')" clearable="true" @keyup.enter.native="searchList()">
                         <el-button slot="append" @click="searchList" icon="el-icon-search"></el-button>
                     </el-input>
                     </div>
                 </el-form-item>
                 <el-form-item style="float:right;">
-                    <el-link type="primary" :underline="false" @click="handleAdd(-1,null)">新增专业</el-link>
+                    <el-link type="primary" :underline="false" @click="handleAdd(-1,null)">{{ $t('xinZengZhuanYe') }}</el-link>
                 </el-form-item>
             </el-form>
         </el-col>
@@ -26,13 +26,13 @@
                         {{scope.$index+1+(page-1)*size}}
                     </template>
             </el-table-column>
-            <el-table-column prop="name" label="专业名称" >
+            <el-table-column prop="name" :label="$t('nameprofessional')" >
             </el-table-column>
             
-            <el-table-column label="操作" width="150">
+            <el-table-column :label="$t('operation')" width="150">
                 <template slot-scope="scope">
-                    <el-button size="mini" type="primary" @click="handleAdd(scope.$index, scope.row)">编辑</el-button>
-                    <el-button size="mini"  @click="deletePro(scope.$index, scope.row)">删除</el-button>
+                    <el-button size="mini" type="primary" @click="handleAdd(scope.$index, scope.row)">{{ $t('bian-ji') }}</el-button>
+                    <el-button size="mini"  @click="deletePro(scope.$index, scope.row)">{{ $t('btn.delete') }}</el-button>
                 </template>
             </el-table-column>
         </el-table>
@@ -53,13 +53,13 @@
         <!--新增界面-->
         <el-dialog :title="title" v-if="addFormVisible" :visible.sync="addFormVisible" :close-on-click-modal="false" customClass="customWidth" width="600px">
             <el-form ref="form1" :model="addForm" :rules="rules" label-width="120px">
-                <el-form-item label="专业名称" prop="name">
-                    <el-input v-model="addForm.name" :max="20" placeholder="请输入专业名称" clearable></el-input>
+                <el-form-item :label="$t('nameprofessional')" prop="name">
+                    <el-input v-model="addForm.name" :max="20" :placeholder="$t('qingShuRuZhuanYeMingCheng')" clearable></el-input>
                 </el-form-item>
             </el-form>
             <div slot="footer" class="dialog-footer;">
-                <el-button @click.native="addFormVisible = false">取消</el-button>
-                <el-button type="primary" @click="submitInsert" :loading="addLoading">提交</el-button>
+                <el-button @click.native="addFormVisible = false">{{ $t('btn.cancel') }}</el-button>
+                <el-button type="primary" @click="submitInsert" :loading="addLoading">{{ $t('btn.submit') }}</el-button>
             </div>
         </el-dialog>
     </section>
@@ -105,7 +105,7 @@
                     name: ''
                 },
                 rules: {
-                    name: [{ required: true, message: "请输入专业名称", trigger: "blur" }],
+                    name: [{ required: true, message: this.$t('qingShuRuZhuanYeMingCheng'), trigger: "blur" }],
                 }
             };
         },
@@ -186,11 +186,11 @@
             //显示新增界面
             handleAdd(i, item) {
                 if(i == -1) {
-                    this.title = "新增专业";
+                    this.title = this.$t('xinZengZhuanYe');
                     this.addForm = {
                     }
                 } else {
-                    this.title = "修改专业";
+                    this.title = this.$t('xiuGaiZhuanYe');
                     this.addForm = JSON.parse(JSON.stringify(item));
                 }
                 this.addFormVisible = true;
@@ -227,9 +227,9 @@
             // 删除
             deletePro(i, item) {
                 console.log(item, '要删除的')
-                this.$confirm("确定要专业" + item.name + "吗?","删除专业", {
-                    confirmButtonText: "确定",
-                    cancelButtonText: "取消",
+                this.$confirm(this.$t('queDingYaoZhuanYe') + item.name + this.$t('ma'),this.$t('shanChuZhuanYe'), {
+                    confirmButtonText: this.$t('btn.determine'),
+                    cancelButtonText: this.$t('btn.cancel'),
                     type: "warning"
                 })
                 .then(() => {
@@ -241,7 +241,7 @@
                         this.listLoading = false;
                         if (res.code == "ok") {
                             this.$message({
-                                message: "删除成功",
+                                message: this.$t('message.successfullyDeleted'),
                                 type: "success"
                             });
                             this.getList();

+ 6 - 6
fhKeeper/formulahousekeeper/timesheet/src/views/project/CostBaseline.vue

@@ -77,7 +77,7 @@
                 <el-col :span="24">
                     <div class="box">
                         <div class="box_head">
-                            日期区间:
+                            {{ $t('riQiQuJian') }} 
                             <el-date-picker
                             v-model="dateSelect"
                             type="daterange"
@@ -95,23 +95,23 @@
                             <div class="boxBoxMax_con">
                                 <el-card class="box-card">
                                     <div slot="header" class="clearfix">
-                                        工时成本
+                                        {{ $t('gongShiChengBen') }} 
                                     </div>
                                     <div class="text item boxBoxMax_con_one">
-                                        <span>工时合计</span> {{ chengbenData.workingTime }} h 
+                                        <span>{{ $t('gongShiHeJi') }}</span> {{ chengbenData.workingTime }} h 
                                     </div>
                                     <div class="text item">
-                                        <span style="letter-spacing: 26px;">成本</span>¥ {{ chengbenData.cost }} 
+                                        <span style="letter-spacing: 26px;">{{ $t('costof') }}</span>¥ {{ chengbenData.cost }} 
                                     </div>
                                 </el-card>
                             </div>
                             <div class="boxBoxMax_con" v-if="user.company.packageExpense">
                                 <el-card class="box-card">
                                     <div slot="header" class="clearfix">
-                                        费用报销成本
+                                        {{ $t('feiYongBaoXiaoChengBen') }} 
                                     </div>
                                     <div class="text item boxBoxMax_con_two">
-                                       <span>报销合计 </span>¥ {{ chengbenData.expense }} 
+                                       <span>{{ $t('baoXiaoHeJi') }} </span>¥ {{ chengbenData.expense }} 
                                     </div>
                                 </el-card>
                             </div>

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


Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików