Pārlūkot izejas kodu

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

zhouyy 5 mēneši atpakaļ
vecāks
revīzija
40017ada68
15 mainītis faili ar 305 papildinājumiem un 41 dzēšanām
  1. 9 2
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/components/common/pullDownSelector.vue
  2. 2 1
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/hooks/useApi.js
  3. 60 3
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/business/businessInfo.vue
  4. 22 5
      fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/tasks/addEditor.vue
  5. 16 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ExpenseSheetController.java
  6. 3 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Contract.java
  7. 3 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ExpenseSheetService.java
  8. 11 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ContractServiceImpl.java
  9. 116 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ExpenseSheetServiceImpl.java
  10. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FinanceExcludeProjectServiceImpl.java
  11. 14 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FinanceServiceImpl.java
  12. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java
  13. 36 25
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/FileZipUtil.java
  14. 1 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserMapper.xml
  15. 10 0
      fhKeeper/formulahousekeeper/timesheet/src/views/contract/components/contractManagement.vue

+ 9 - 2
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/components/common/pullDownSelector.vue

@@ -70,7 +70,7 @@ const props = defineProps({
   },
   value: {
     type: [String, Array],
-    default: () => null,
+    default: () => [],
   },
   doYouNeedTranslation: {
     type: Boolean,
@@ -86,7 +86,7 @@ const emit = defineEmits(["change"]);
 const fixedData = useFixedData();
 
 const listLoading = ref(false);
-const selectChecked = ref();
+const selectChecked = ref([]);
 const checkboxRefs = ref([]);
 const searchForValue = ref("");
 const allOptions = ref([]);
@@ -105,6 +105,10 @@ watch(() => props.options, (newValue) => {
   }
 })
 
+watch(() => props.value, (newValue) => {
+  selectChecked.value = newValue
+})
+
 function searchOptions(val) {
   listLoading.value = true
   if (!props.doYouNeedTranslation) {
@@ -178,5 +182,8 @@ onMounted(() => {
   } else {
     obtainPersonnelData();
   }
+  if(props.value) {
+    selectChecked.value = props.multipleChoice ? props.value.split(',') : props.value
+  }
 });
 </script>

+ 2 - 1
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/hooks/useApi.js

@@ -56,4 +56,5 @@ export const OBTAIN_ORDER_RELATED_PRODUCTS = `/order/productWithOrder` // 获取
 
 export const SELL_AND_OBTAIN_RELATED_PRODUCTS = `/product/orderWithProduct` // 销售订单关联产品
 
-export const GET_CONTACTS_WITH_MORE_I_DS = `/contacts/getAllContacts` // 更具Id获取联系人
+export const GET_CONTACTS_WITH_MORE_I_DS = `/contacts/getAllContacts` // 更具Id获取联系人
+export const CONTACT_PERSON_ASSOCIATED_WITH_BUSINESS_OPPORTUNITY = `/business-opportunity/saveContactsId` // 联系人关联商机

+ 60 - 3
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/business/businessInfo.vue

@@ -19,7 +19,8 @@
       <van-cell title="备注" :value="info.remark" />
     </div>
     <div class="bottomButton">
-      <van-button type="primary" class="w-full block">关联联系人</van-button>
+      <van-button type="primary" class="w-full block" v-if="!info.contactsName"
+        @click="shoContactDialag()">关联联系人</van-button>
       <van-button type="warning" class="w-full block" v-if="info.inchargerName"
         @click="showDialogCli()">转移商机</van-button>
       <van-button type="primary" class="w-full block" v-if="!info.inchargerName"
@@ -37,17 +38,30 @@
       <div class="themeTextColor text-size-small pl-4 pt-2 pb-2">转移后,将看不到此商机了</div>
     </van-dialog>
 
+    <van-dialog v-model:show="showContactDialog" :title="`关联联系人`" show-cancel-button @confirm="relatedContacts"
+      :before-close="dialogCloseBefo">
+      <van-cell title="联系人" is-link @click="showContactSelect = true">
+        <template #value>
+          {{ dialogSelection.label }}
+        </template>
+      </van-cell>
+    </van-dialog>
+
     <!-- select 选择器 -->
     <van-popup v-model:show="showSelect" destroy-on-close position="bottom" :style="{ height: '80%' }">
       <PullDownSelector @change="selectChange" />
     </van-popup>
+
+    <van-popup v-model:show="showContactSelect" destroy-on-close position="bottom" :style="{ height: '80%' }">
+      <PullDownSelector :options="allContactsList" :doYouNeedTranslation="false" @change="selectChange" />
+    </van-popup>
   </div>
 </template>
 
 <script setup>
 import { ref } from 'vue';
 import { useLifecycle } from '@hooks/useCommon.js';
-import { BUSINESS_OPPORTUNITY_TRANSFER } from '@hooks/useApi'
+import { BUSINESS_OPPORTUNITY_TRANSFER, GET_CONTACTS_WITH_MORE_I_DS, CONTACT_PERSON_ASSOCIATED_WITH_BUSINESS_OPPORTUNITY } from '@hooks/useApi'
 import requests from "@common/requests";
 import useShowToast from '@hooks/useToast'
 import useInfoStore from '@store/useInfoStore'
@@ -64,7 +78,30 @@ const props = defineProps({
 
 const showDialog = ref(false);
 const showSelect = ref(false);
+const showContactSelect = ref(false);
+const showContactDialog = ref(false)
 const dialogSelection = ref({});
+const allContactsList = ref([]);
+
+function shoContactDialag() {
+  dialogSelection.value = {}
+  showContactDialog.value = true
+}
+
+function relatedContacts() {
+  if (!dialogSelection.value.label) {
+    return toastText('请选择要关联的联系人')
+  }
+
+  requests.post(CONTACT_PERSON_ASSOCIATED_WITH_BUSINESS_OPPORTUNITY, {
+    id: props.info.id,
+    contactsId: dialogSelection.value.value
+  }).then((res) => {
+    props.info.contactsName = dialogSelection.value.label
+    showContactDialog.value = false
+    toastSuccess('关联成功')
+  })
+}
 
 function confirmTransfer() {
   if (!dialogSelection.value.label) {
@@ -98,9 +135,11 @@ function selectChange(value, label) {
     value, label
   }
   showSelect.value = false
+  showContactSelect.value = false
 }
 
 function showDialogCli() {
+  dialogSelection.value = {}
   showDialog.value = true
 }
 
@@ -112,9 +151,27 @@ function dialogCloseBefo(val) {
   return true
 }
 
+function getAllContactsList() {
+  requests.get(`${GET_CONTACTS_WITH_MORE_I_DS}?customerId=${props.info.customerId}`).then(({ data = [] }) => {
+    let list = data.map(item => {
+      return {
+        label: item.name,
+        value: item.id,
+      }
+    })
+    if (!list.length) {
+      list = [{}]
+    }
+    allContactsList.value = list
+  })
+}
+
 useLifecycle({
   load: () => {
-    // 添加加载逻辑
+    getAllContactsList()
+  },
+  init: () => {
+    getAllContactsList()
   }
 });
 </script>

+ 22 - 5
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/pageComponents/tasks/addEditor.vue

@@ -63,7 +63,7 @@
           </template>
         </van-field>
         <van-field v-model="vantFormVal.executorId" name="executorId" label="执行人" placeholder="请选择" is-link readonly class="resetStyles"
-          @click="showSelectionBox('executorId', allContactsList)">
+          @click="showSelectionToBox('executorId')">
           <template #input v-if="vantFormVal.executorIdName && vantFormVal.executorIdName.length > 0">
             <TranslationComponent :openId="vantFormVal.executorIdName" />
           </template>
@@ -165,7 +165,11 @@
     <div>
       <!-- 下拉框选择 -->
       <van-popup v-model:show="showSelectionFlag" destroy-on-close position="bottom" :style="{ height: '80%' }">
-        <PullDownSelector :options="showSelectionArray" :doYouNeedTranslation="false" @change="selectChange" :multiple-choice="selectMultipleChoice" />
+        <PullDownSelector :options="showSelectionArray" :doYouNeedTranslation="false" @change="selectChange" />
+      </van-popup>
+
+      <van-popup v-model:show="showSelectionToFlag" destroy-on-close position="bottom" :style="{ height: '80%' }">
+        <PullDownSelector :value="showSelectionToValue" @change="selectChange" :multiple-choice="true" />
       </van-popup>
 
       <!-- 选择日期 -->
@@ -216,7 +220,8 @@ const showDatePicker = ref(false)
 const showDatePickerVal = ref(dayjs().format("YYYY-MM-DD").split("-"))
 const showDatePickerFiled = ref('')
 const customeDate = ref([])
-const selectMultipleChoice = ref(false)
+const showSelectionToFlag = ref(false)
+const showSelectionToValue = ref([])
 const taskTypeFiled = ['customId', 'businessOpportunityId', 'orderId', 'clueId']
 
 const contactDisabled = computed(() => {
@@ -293,6 +298,12 @@ function selectChange(value, label) {
   showSelectionFlag.value = false
 }
 
+function showSelectionToBox(filed) {
+  showSelectionFiled.value = filed
+  showSelectionToValue.value = vantFormVal.value[filed] || []
+  showSelectionToFlag.value = true
+}
+
 function showSelectionBox(filed, list = [], event) {
   if (taskTypeFiled.includes(filed)) {
     const fileds = taskTypeFiled.filter(item => item !== filed)
@@ -303,7 +314,6 @@ function showSelectionBox(filed, list = [], event) {
     vantFormVal.value.contactsId = ''
     vantFormVal.value[`contactsIdName`] = ''
   }
-  selectMultipleChoice.value = filed == 'executorId' ? true : false
   showSelectionFiled.value = filed
   showSelectionArray.value = filed == 'executorId' ? [] : list
   showSelectionFlag.value = true
@@ -348,7 +358,7 @@ function getContactData(filed, value) {
         value: item.id,
       }
     })
-    if (!allContactsList.value.length) {
+    if (!list.length) {
       list = [{}]
     }
     allContactsList.value = list
@@ -429,6 +439,13 @@ function initializeData() {
     }
   })
   formVal.value = props.formValue
+  if((taskType || taskType == 0) && taskType != 3) {
+    const filed = taskType == 0 ? 'customId' : taskType == 1 ? 'businessOpportunityId' : taskType == 2 ? 'orderId' : 'clueId'
+    const value = taskType == 0 ? customId : taskType == 1 ? businessOpportunityId : taskType == 2 ? orderId : clueId
+    if(value) {
+      getContactData(filed, value)
+    }
+  }
 }
 
 useLifecycle({

+ 16 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ExpenseSheetController.java

@@ -21,6 +21,7 @@ import org.springframework.web.multipart.MultipartFile;
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -94,8 +95,21 @@ public class ExpenseSheetController {
      * 导出
      */
     @RequestMapping("/export")
-    public void getExport(HttpServletResponse response) throws Exception {
-        FileZipUtil.exportZip(response,uploadPath , "报销凭证压缩包", ".zip");
+    public void getExport(ExpenseSheet sheet,Integer sendState,Integer projectId,String startDate, String endDate,HttpServletResponse response) throws Exception {
+        String token = request.getHeader("TOKEN");
+        User user = userMapper.selectById(token);
+        List<SysRichFunction> functionList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "查看全部报销单");
+        if (functionList.size() == 0) {
+            //普通员工只能看自己的
+            if (sheet.getStatus() == null) {
+                sheet.setOwnerId(user.getId());
+            }
+        }
+        sheet.setCompanyId(user.getCompanyId());
+        List<String> fileNames= expenseSheetService.queryExportFileZipList(sheet,projectId, startDate, endDate);
+        if (!fileNames.isEmpty()){
+            FileZipUtil.exportZip(response,uploadPath ,fileNames, "报销凭证压缩包", ".zip");
+        }else return;
     }
 
 

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

@@ -178,6 +178,9 @@ public class Contract extends Model<Contract> {
     @TableField(exist = false)
     private String secTypeName;
 
+    @TableField(exist = false)
+    private String projectName;
+
 
     @Override
     protected Serializable pkVal() {

+ 3 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ExpenseSheetService.java

@@ -6,6 +6,7 @@ import com.management.platform.util.HttpRespMsg;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletRequest;
+import java.util.List;
 
 /**
  * <p>
@@ -38,4 +39,6 @@ public interface ExpenseSheetService extends IService<ExpenseSheet> {
     HttpRespMsg approveSingleProject(Integer id);
 
     HttpRespMsg denySingleProject(Integer id, String denyReason);
+
+    List<String> queryExportFileZipList(ExpenseSheet sheet, Integer projectId, String startDate, String endDate);
 }

+ 11 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ContractServiceImpl.java

@@ -88,6 +88,8 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> i
     private ContractTypeSecMapper contractTypeSecMapper;
     @Autowired
     private ContractPayCustomizedMapper contractPayCustomizedMapper;
+    @Autowired
+    private ProjectMapper projectMapper;
 
     /**
      * 分页查询合同
@@ -168,6 +170,12 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> i
             List<Map<String, Object>> contractLogs = contractLogMapper.selectMsg(user.getCompanyId());
             List<ContractCustom> customList = contractCustomMapper.selectList(new QueryWrapper<ContractCustom>().in("contract_id", contractCollect));
             List<ContractTypeSec> secTypeList = contractTypeSecMapper.selectList(new QueryWrapper<ContractTypeSec>().eq("company_id", user.getCompanyId()));
+            //关联项目
+            List<Project> projectList = new ArrayList<>();
+            if (contracts.size() > 0) {
+                projectList = projectMapper.selectList(new QueryWrapper<Project>().select("id, project_name").in("id", contracts.stream().map(Contract::getProjectId).collect(Collectors.toList())));
+            }
+
             for (Contract contract : contracts) {
                 ContractPageVO contractPageVO = new ContractPageVO();
                 List<ContractDocument> files = new ArrayList<>();
@@ -190,6 +198,9 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> i
                 contractPageVO.setRemarks(contract.getRemarks());
                 contractPageVO.setAmounts(contract.getAmounts());
                 contractPageVO.setProjectId(contract.getProjectId());
+                if (contract.getProjectId() != null) {
+                    projectList.stream().filter(project -> project.getId().equals(contract.getProjectId())).findFirst().ifPresent(project -> contractPageVO.setProjectName(project.getProjectName()));
+                }
                 contractPageVO.setPayment(contract.getPayment());
                 contractPageVO.setNextPaymentDate(contract.getNextPaymentDate());
                 contractPageVO.setNextPaymentAmount(contract.getNextPaymentAmount());

+ 116 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ExpenseSheetServiceImpl.java

@@ -1335,4 +1335,120 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
         saveNotifyToApplier(sheet, user);
         return new HttpRespMsg();
     }
+
+    @Override
+    public List<String> queryExportFileZipList(ExpenseSheet sheet, Integer projectId, String startDate, String endDate) {
+        QueryWrapper<ExpenseSheet> queryWrapper = new QueryWrapper<ExpenseSheet>();
+        //当前用户
+        String token = request.getHeader("TOKEN");
+        queryWrapper.eq("company_id", sheet.getCompanyId()).orderByDesc("id");
+        ExpenseAuditSetting expenseAuditSetting = expenseAuditSettingMapper.selectById(sheet.getCompanyId());
+        ArrayList<String> fileNameList = new ArrayList<>();
+        if (!StringUtils.isEmpty(sheet.getCode())) {
+            queryWrapper.eq("code", sheet.getCode());
+        }
+        //增加状态
+        if (sheet.getStatus() != null) {
+            queryWrapper.eq("status", sheet.getStatus());
+        }
+        if(sheet.getSendState()!=null){
+            queryWrapper.eq("send_state",sheet.getSendState());
+        }
+
+        if (expenseAuditSetting == null || expenseAuditSetting.getAuditType() == 0) {
+            if (sheet.getStatus() != null &&  sheet.getStatus() == 1) {
+                //待审核列表,检查是否有权限
+                User user = userMapper.selectById(token);
+                List<SysRichFunction> functionList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "费用审核");
+                if (functionList.size() == 0) {
+                    //无权查看待审核
+                    queryWrapper.eq("id", -1);
+                }
+            } else {
+                if (!StringUtils.isEmpty(sheet.getOwnerId())) {
+                    queryWrapper.eq("owner_id", sheet.getOwnerId());
+                }
+            }
+        } else if(expenseAuditSetting.getAuditType() == 1){
+            //增加按项目经理审核模式下,项目经理可以查看相关费用报销单的条件
+            if (sheet.getStatus() != null) {
+                //取待审核的
+                //项目经理审核模式下,只能查看自己项目的费用报销单
+                List<Integer> projectIds = projectMapper.selectList(new QueryWrapper<Project>().eq("incharger_id", token)).stream().map(Project::getId).collect(Collectors.toList());
+                System.out.println("项目经理的项目id"+projectIds);
+                if (projectIds.size() > 0) {
+                    List<Integer> expenseIds = expenseItemMapper.selectList(new QueryWrapper<ExpenseItem>().in("project_id", projectIds)).stream().map(ExpenseItem::getExpenseId).distinct().collect(Collectors.toList());
+                    System.out.println("项目经理的项目的费用报销单id"+expenseIds);
+                    queryWrapper.in("id", expenseIds);
+                } else {
+                    //没有项目的项目经理,不显示任何数据
+                    queryWrapper.eq("id", -1);
+                }
+                //按选择的人员过滤
+                if (!StringUtils.isEmpty(sheet.getOwnerId())) {
+                    queryWrapper.eq("owner_id", sheet.getOwnerId());
+                }
+            } else {
+                //按人员过滤
+                if (!StringUtils.isEmpty(sheet.getOwnerId())) {
+                    queryWrapper.eq("owner_id", sheet.getOwnerId());
+                }
+            }
+        }else if(expenseAuditSetting.getAuditType() == 2){
+            if (sheet.getStatus() != null) {
+                //增加多层审核人审核模式 过滤第一或者第二审核人为当前用户的数据
+                queryWrapper.and(wrapper->wrapper.and(wr->wr.eq("first_checker_id",token).eq("review_process",0)).or(wr->wr.eq("second_checker_id",token).eq("review_process",1)));
+                if (!StringUtils.isEmpty(sheet.getOwnerId())) {
+                    queryWrapper.eq("owner_id", sheet.getOwnerId());
+                }
+            }else {
+                //按人员过滤
+                if (!StringUtils.isEmpty(sheet.getOwnerId())) {
+                    queryWrapper.eq("owner_id", sheet.getOwnerId());
+                }
+            }
+        }
+
+        if (!StringUtils.isEmpty(sheet.getType())) {
+            queryWrapper.eq("type", sheet.getType());
+        }
+        if (!StringUtils.isEmpty(startDate) && !StringUtils.isEmpty(endDate)) {
+            queryWrapper.between("create_date", startDate, endDate);
+        }
+        if (projectId!=null){
+            QueryWrapper<ExpenseItem> q = new QueryWrapper<ExpenseItem>();
+            q.eq("project_id",projectId);
+            List<ExpenseItem> expenseItems = expenseItemMapper.selectList(q);
+            if (expenseItems.size()==0){
+                return new ArrayList<String>();
+            }else {
+                List<Integer> expenseIds = expenseItems.stream().map(ExpenseItem::getExpenseId).collect(Collectors.toList());
+                queryWrapper.in("id",expenseIds);
+                return getStrings(queryWrapper);
+            }
+        }else {
+            return getStrings(queryWrapper);
+        }
+    }
+
+    private ArrayList<String> getStrings(QueryWrapper<ExpenseSheet> queryWrapper) {
+        List<ExpenseSheet> records= expenseSheetMapper.selectList(queryWrapper);
+        ArrayList<String> fileNames = new ArrayList<>();
+        if (!records.isEmpty()){
+            List<Integer> sheetIdList = records.stream().map(ExpenseSheet::getId).distinct().collect(Collectors.toList());
+            if (!sheetIdList.isEmpty()){
+                QueryWrapper<ExpenseItem> itemQueryWrapper = new QueryWrapper<ExpenseItem>().in("expense_id", sheetIdList);
+                List<ExpenseItem> items = expenseItemMapper.selectList(itemQueryWrapper);
+                if (!items.isEmpty()){
+                    for (ExpenseItem item : items) {
+                        if (org.apache.commons.lang3.StringUtils.isNotEmpty(item.getPic())){
+                            String[] picNames = item.getPic().split(",");
+                            fileNames.addAll(Arrays.asList(picNames));
+                        }
+                    }
+                }
+            }
+        }
+        return fileNames;
+    }
 }

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

@@ -63,7 +63,7 @@ public class FinanceExcludeProjectServiceImpl extends ServiceImpl<FinanceExclude
 
         List<FinanceExcludeProject> resList = financeExcludeProjectMapper
                 .selectList(new LambdaQueryWrapper<FinanceExcludeProject>()
-                        .eq(FinanceExcludeProject::getProjectId,user.getCompanyId())
+                        .eq(FinanceExcludeProject::getCompanyId,user.getCompanyId())
                         .eq(FinanceExcludeProject::getUseYM,useYM));
         if(projectCount == resList.size()){
             map.put("isAll",1);

+ 14 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FinanceServiceImpl.java

@@ -184,8 +184,12 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
             //获取人员该月份填写的日报的总时长
             List<Map<String, Object>> userTimeList = null;
             if (syncUserCost || syncHistoryReport) {
-//                userTimeList = reportMapper.getUserWorkingTimeByRange(companyId, startStr, endStr);
                 userTimeList = reportMapper.getUserWorkingTimeByRangeWithExclude(companyId, yearMonth,startStr, endStr);
+                if (userTimeList.size() == 0) {
+                    msg.setError("当月没有相关项目的日报数据,请检查是否设置了不参与项目");
+                    return msg;
+                }
+
             }
 
             //设置财务核算薪资模板配置
@@ -384,6 +388,7 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                 }
 
                 if (first != null && first.isPresent()) {
+                    System.out.println("匹配到的人员:"+first.get().getName());
                     finance.setUserId(first.get().getId());
                     BigDecimal total = new BigDecimal(0);
                     if (salaryCell != null) {
@@ -512,14 +517,22 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                             BigDecimal db = timeType.getMonthDays().multiply(new BigDecimal(timeType.getAllday()));
                             localUser.setCost(total.divide(db, 6, BigDecimal.ROUND_HALF_UP));
                         } else {
+                            boolean find = false;
                             for (int i=0;i<userTimeList.size(); i++) {
                                 Map<String, Object> map = userTimeList.get(i);
                                 if (map.get("creatorId").equals(finance.getUserId())) {
+                                    find = true;
                                     double time = (Double)map.get("workingTime");
                                     localUser.setCost(total.divide(new BigDecimal(time), 6, BigDecimal.ROUND_HALF_UP));
                                     break;
                                 }
                             }
+                            if (!find) {
+                                //没有找到对应的工时,按标准工时来
+                                System.out.println("没有找到对应的工时,按标准工时来, userId="+finance.getUserId()+", jobNumber="+finance.getJobNumber());
+                                BigDecimal db = timeType.getMonthDays().multiply(new BigDecimal(timeType.getAllday()));
+                                localUser.setCost(total.divide(db, 6, BigDecimal.ROUND_HALF_UP));
+                            }
                         }
 
                         updateUserList.add(localUser);

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

@@ -1684,7 +1684,7 @@ public class TimingTask {
         if (isDev) {
             return;
         }
-        //针对钉钉提醒类型是0或者1的情况,发送提醒。(当天提醒或者今天提醒昨天漏填)
+        //针对钉钉提醒类型是0或者1的情况,发送提醒。(当天提醒或者今天提醒昨天漏填),getPushDingdingUserList内部获取数据根据alert_type=0 or 1做了判断
         List<Map<String, Object>> dingdingUserList = userMapper.getPushDingdingUserList(str, date);
         //钉钉平台的用批量发送, 每分钟5000个
         int minuteSize = 5000;

+ 36 - 25
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/FileZipUtil.java

@@ -8,7 +8,9 @@ import javax.servlet.http.HttpServletResponse;
 import java.io.*;
 import java.net.URLEncoder;
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
 import java.util.Date;
+import java.util.List;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
 
@@ -21,7 +23,7 @@ public class FileZipUtil {
      * @param fileName 下载时的文件名称
      * @param postfix 下载时的文件后缀 .zip/.rar
      */
-    public static void exportZip(HttpServletResponse response, String sourceFilePath, String fileName, String postfix) {
+    public static void exportZip(HttpServletResponse response, String sourceFilePath, List<String> fileNames, String fileName, String postfix) {
         // 默认文件名以时间戳作为前缀
         if(StringUtils.isBlank(fileName)){
             SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
@@ -32,7 +34,7 @@ public class FileZipUtil {
         try {
             OutputStream os = response.getOutputStream();
             // 接收压缩包字节
-            byte[] data = createZip(sourceFilePath);
+            byte[] data = createZip(sourceFilePath,fileNames);
             response.reset();
             response.setCharacterEncoding("UTF-8");
             response.addHeader("Access-Control-Allow-Origin", "*");
@@ -56,12 +58,12 @@ public class FileZipUtil {
      * @return byte[]
      * @throws Exception
      */
-    private static byte[] createZip(String sourceFilePath) throws Exception{
+    private static byte[] createZip(String sourceFilePath,List<String> fileNames) throws Exception{
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
         ZipOutputStream zip = new ZipOutputStream(outputStream);
         // 将目标文件打包成zip导出
         File file = new File(sourceFilePath);
-        handlerFile(zip, file,"");
+        handlerFile(zip, file,"",fileNames);
         // 无异常关闭流,它将无条件的关闭一个可被关闭的对象而不抛出任何异常。
         IOUtils.closeQuietly(zip);
         return outputStream.toByteArray();
@@ -74,32 +76,41 @@ public class FileZipUtil {
      * @param dir
      * @throws Exception
      */
-    private static void handlerFile(ZipOutputStream zip, File file, String dir) throws Exception {
-        // 如果当前的是文件夹,则循环里面的内容继续处理
-        if (file.isDirectory()) {
-            //得到文件列表信息
-            File[] fileArray = file.listFiles();
-            if (fileArray == null) {
-                return;
+    private static void handlerFile(ZipOutputStream zip, File file, String dir,List<String> fileNames) throws Exception {
+        // 得到文件列表信息
+        File[] fileArray = file.listFiles();
+
+        if (fileArray == null) {
+            extracted(zip, file, dir);
+        } else {
+            // 过滤出与 fileNames 匹配的文件
+            for (File f : fileArray) {
+                if (fileNames.contains(f.getName())) { // 使用 contains 方法检查
+                    extracted(zip, f, dir + f.getName()); // 打包处理匹配的文件
+                } else if (f.isDirectory()) {
+                    // 递归处理子目录
+                    handlerFile(zip, f, dir + f.getName() + "/", fileNames);
+                }
             }
-            //将文件夹添加到下一级打包目录
+        }
+
+            /*//将文件夹添加到下一级打包目录
             zip.putNextEntry(new ZipEntry(dir + "/"));
             dir = dir.length() == 0 ? "" : dir + "/";
             // 递归将文件夹中的文件打包
             for (File f : fileArray) {
-                handlerFile(zip, f, dir + f.getName());
-            }
-        } else {
-            // 如果当前的是文件,打包处理
-            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
-            ZipEntry entry = new ZipEntry(dir);
-            zip.putNextEntry(entry);
-            zip.write(FileUtils.readFileToByteArray(file));
-            IOUtils.closeQuietly(bis);
-            zip.flush();
-            zip.closeEntry();
-        }
-    }
+                handlerFile(zip, f, dir + f.getName(),fileNames);
+            }*/
 
+    }
 
+    private static void extracted(ZipOutputStream zip, File file, String dir) throws IOException {
+        // 如果当前的是文件,打包处理
+        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
+        ZipEntry entry = new ZipEntry(dir); // 使用完整路径(包含文件名)
+        zip.putNextEntry(entry);
+        zip.write(FileUtils.readFileToByteArray(file));
+        IOUtils.closeQuietly(bis);
+        zip.closeEntry(); // 关闭当前条目
+    }
 }

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

@@ -180,6 +180,7 @@
         WHERE a.dingding_userid is not null and time_type.alert_time = #{alertTime}
         AND a.is_active = 1
         AND a.report_status=0
+        AND (time_type.`alert_type` = 0 OR time_type.`alert_type` = 1)
         AND company.expiration_date >= NOW()
         AND NOT EXISTS(SELECT 1 FROM report WHERE report.`creator_id` = a.id AND ((report.`create_date` = DATE_FORMAT(date_sub(NOW(),interval 1 day), '%Y-%m-%d') and time_type.alert_type=1)or(report.`create_date` = DATE_FORMAT(NOW(), '%Y-%m-%d') and time_type.alert_type=0)))
         <if test="date != null">

+ 10 - 0
fhKeeper/formulahousekeeper/timesheet/src/views/contract/components/contractManagement.vue

@@ -81,6 +81,7 @@
     <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="projectName" :label="$t('rselatedprojects')" min-width="190"></el-table-column>
       <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>
@@ -256,6 +257,10 @@
           <el-form-item :label="$t('he-tong-ming-cheng')">
             {{contractForm.name}}
           </el-form-item>
+          <el-form-item :label="$t('rselatedprojects')">
+            {{contractForm.projectName}}
+          </el-form-item>
+          
           <el-form-item :label="$t('contractamount')">
             ¥ {{contractForm.amounts}}
           </el-form-item>
@@ -917,6 +922,11 @@ export default {
           }
           this.submitLoading = true
           delete this.contractForm.files
+          delete this.contractForm.msg
+          delete this.contractForm.nextPaymentDate
+          delete this.contractForm.nextPaymentAmount
+          delete this.contractForm.payCustomizedData
+          delete this.contractForm.checkerId
           this.contractForm.paymentListStr = JSON.stringify(this.contractPaymentList);
           this.http.post(this.dialogTitle == this.$t('add') ? '/contract/addContract' : '/contract/editContract',this.contractForm,
           res => {