From 46ebe72425492b61fe48626f46596dd44a13c43f Mon Sep 17 00:00:00 2001 From: guoshengxiong <1923636941@qq.com> Date: Wed, 22 Jan 2025 10:20:30 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8C=85=E5=A4=B4=E8=BD=A6=E8=BE=86=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/zhgd/mybatis/DataScopeHandler.java | 4 +- .../com/zhgd/xmgl/call/HikvisionCall.java | 2 +- .../ContractorMonthlyController.java | 11 +- .../plan/entity/PlanChooseCategory.java | 23 +-- .../mapper/xml/PlanChooseCategoryMapper.xml | 3 + .../car/controller/CarInfoController.java | 21 +++ .../zhgd/xmgl/modules/car/entity/CarInfo.java | 25 ++- .../modules/car/service/ICarInfoService.java | 7 + .../car/service/impl/CarInfoServiceImpl.java | 156 +++++++++++++++++- .../ProjectEnterpriseController.java | 4 +- .../service/IProjectEnterpriseService.java | 2 +- .../impl/ProjectEnterpriseServiceImpl.java | 2 +- .../worker/service/IWorkerTypeService.java | 2 + .../service/impl/WorkerInfoServiceImpl.java | 99 ++++++----- .../zhgd/xmgl/security/WebSecurityConfig.java | 1 + src/main/java/com/zhgd/xmgl/task/JzgTask.java | 3 +- .../java/com/zhgd/xmgl/util/ExcelUtils.java | 61 ++++++- src/main/resources/excel/人员导入模板.xlsx | Bin 14328 -> 14305 bytes src/main/resources/excel/车辆导入模板.xlsx | Bin 0 -> 14361 bytes 19 files changed, 332 insertions(+), 94 deletions(-) create mode 100644 src/main/resources/excel/车辆导入模板.xlsx diff --git a/src/main/java/com/zhgd/mybatis/DataScopeHandler.java b/src/main/java/com/zhgd/mybatis/DataScopeHandler.java index e2db65b09..a540109d1 100644 --- a/src/main/java/com/zhgd/mybatis/DataScopeHandler.java +++ b/src/main/java/com/zhgd/mybatis/DataScopeHandler.java @@ -361,7 +361,7 @@ public class DataScopeHandler implements DataPermissionHandler { } //合作单位ids设备 - //and (FIND_IN_SET(100,xxx.enterprise_ids) or FIND_IN_SET(102,xxx.enterprise_ids)) + //and (FIND_IN_SET(100,xxx.enterprise_ids) or FIND_IN_SET(102,xxx.enterprise_ids)) or xxx.enterprise_ids = "" List filterEnterpriseIds = getNeedFilterLeftExpression(plainSelect, this.getFieldEnterpriseIdsTables(), ds); if (CollUtil.isNotEmpty(filterEnterpriseIds)) { List enterpriseIds = userEnterpriseService.getEnterpriseIdsIfSubProject(); @@ -369,7 +369,7 @@ public class DataScopeHandler implements DataPermissionHandler { for (String filterEnterpriseId : filterEnterpriseIds) { List list1 = enterpriseIds.stream().map(s -> "FIND_IN_SET(" + s + "," + filterEnterpriseId + ")").collect(Collectors.toList()); String s1 = StrUtil.join(" or ", list1); - String sql = " (" + s1 + ")"; + String sql = " (" + s1 + ") or " + filterEnterpriseId + " = \"\""; Expression expression = null; try { expression = CCJSqlParserUtil.parseCondExpression(sql); diff --git a/src/main/java/com/zhgd/xmgl/call/HikvisionCall.java b/src/main/java/com/zhgd/xmgl/call/HikvisionCall.java index 83574464a..d2b27a4c1 100644 --- a/src/main/java/com/zhgd/xmgl/call/HikvisionCall.java +++ b/src/main/java/com/zhgd/xmgl/call/HikvisionCall.java @@ -2498,7 +2498,7 @@ public class HikvisionCall { public String saveToLocal(String url) { String fileName = IdUtil.simpleUUID() + ".png"; UrlUtil.saveToLocal(url, PathUtil.getBasePath(), fileName); - minioUtils.downloadFile(fileName); + minioUtils.uploadBySameName(fileName, false); return fileName; } diff --git a/src/main/java/com/zhgd/xmgl/modules/baotou/controller/ContractorMonthlyController.java b/src/main/java/com/zhgd/xmgl/modules/baotou/controller/ContractorMonthlyController.java index 92f1b1090..c3c89bb19 100644 --- a/src/main/java/com/zhgd/xmgl/modules/baotou/controller/ContractorMonthlyController.java +++ b/src/main/java/com/zhgd/xmgl/modules/baotou/controller/ContractorMonthlyController.java @@ -1,15 +1,9 @@ package com.zhgd.xmgl.modules.baotou.controller; -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.metadata.IPage; import com.zhgd.annotation.OperLog; import com.zhgd.jeecg.common.api.vo.Result; -import com.zhgd.xmgl.modules.baotou.entity.ContractorMonthlyDetail; -import com.zhgd.xmgl.modules.baotou.entity.ContractorMonthlyTemplate; import com.zhgd.xmgl.modules.baotou.entity.DeviceUnit; -import com.zhgd.xmgl.modules.baotou.entity.ProjectGroup; import com.zhgd.xmgl.modules.baotou.service.*; import com.zhgd.xmgl.modules.project.service.IProjectEnterpriseService; import com.zhgd.xmgl.modules.worker.entity.EnterpriseInfo; @@ -19,16 +13,13 @@ import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections.MapUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.web.bind.annotation.*; import springfox.documentation.annotations.ApiIgnore; -import java.util.Date; import java.util.HashMap; import java.util.Map; -import java.util.Objects; @RestController @RequestMapping("/xmgl/contractorMonthly") @@ -76,7 +67,7 @@ public class ContractorMonthlyController { }) @PostMapping(value = "/queryEnterpriseInfoPageList") public Result> queryPageList(@RequestBody Map map) { - IPage pageList = projectEnterpriseService.selectProjectEnterprisePage(map); + IPage pageList = projectEnterpriseService.queryPageList(map); return Result.success(pageList); } diff --git a/src/main/java/com/zhgd/xmgl/modules/baotou/plan/entity/PlanChooseCategory.java b/src/main/java/com/zhgd/xmgl/modules/baotou/plan/entity/PlanChooseCategory.java index 69b7d71fb..9acce3e94 100644 --- a/src/main/java/com/zhgd/xmgl/modules/baotou/plan/entity/PlanChooseCategory.java +++ b/src/main/java/com/zhgd/xmgl/modules/baotou/plan/entity/PlanChooseCategory.java @@ -47,15 +47,18 @@ public class PlanChooseCategory implements Serializable { @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") @ApiModelProperty(value="更新时间 yyyy-MM-dd HH:mm:ss") private java.util.Date updateTime ; - @TableField(exist = false) - private String categoryName ; - @TableField(exist = false) - private String recordName ; - @TableField(exist = false) - @ApiModelProperty(value = "层级名称") - private String fullName ; - @TableField(exist = false) - @ApiModelProperty(value = "祖级列表") - private java.lang.String ancestors; + @TableField(exist = false) + private String categoryName; + @TableField(exist = false) + private String recordName; + @TableField(exist = false) + @ApiModelProperty(value = "层级名称") + private String fullName; + @TableField(exist = false) + @ApiModelProperty(value = "祖级列表") + private java.lang.String ancestors; + @TableField(exist = false) + @ApiModelProperty(value = "1项目里程碑2装置里程碑") + private java.lang.Integer projectType; } diff --git a/src/main/java/com/zhgd/xmgl/modules/baotou/plan/mapper/xml/PlanChooseCategoryMapper.xml b/src/main/java/com/zhgd/xmgl/modules/baotou/plan/mapper/xml/PlanChooseCategoryMapper.xml index 8e1bca31d..6458035c2 100644 --- a/src/main/java/com/zhgd/xmgl/modules/baotou/plan/mapper/xml/PlanChooseCategoryMapper.xml +++ b/src/main/java/com/zhgd/xmgl/modules/baotou/plan/mapper/xml/PlanChooseCategoryMapper.xml @@ -7,6 +7,7 @@ ,pwc.category_name as category_name ,pr.job_name as record_name ,pwc.ancestors + ,pwc.project_type from plan_choose_category t left join plan_work_category pwc on t.category_id = pwc.id left join plan_record pr on pr.id=t.record_id @@ -18,6 +19,8 @@ select t.* ,pwc.category_name as category_name ,pr.job_name as record_name + ,pwc.ancestors + ,pwc.project_type from plan_choose_category t left join plan_work_category pwc on t.category_id = pwc.id left join plan_record pr on pr.id=t.record_id diff --git a/src/main/java/com/zhgd/xmgl/modules/car/controller/CarInfoController.java b/src/main/java/com/zhgd/xmgl/modules/car/controller/CarInfoController.java index 19f1f8fa7..7387400d7 100644 --- a/src/main/java/com/zhgd/xmgl/modules/car/controller/CarInfoController.java +++ b/src/main/java/com/zhgd/xmgl/modules/car/controller/CarInfoController.java @@ -32,8 +32,10 @@ import org.apache.commons.collections.MapUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import springfox.documentation.annotations.ApiIgnore; +import javax.servlet.http.HttpServletResponse; import java.util.*; import java.util.stream.Collectors; @@ -369,5 +371,24 @@ public class CarInfoController { return Result.success(carInfoService.validEnterpriseStatus(param)); } + @OperLog(operModul = "车辆黑白名单管理", operType = "", operDesc = "车辆导入模板下载") + @ApiOperation(value = "车辆导入模板下载", notes = "车辆导入模板下载", httpMethod = "GET") + @ApiImplicitParams({ + @ApiImplicitParam(name = "projectSn", value = "项目SN", paramType = "query", required = true, dataType = "String"), + }) + @GetMapping(value = "/exportExcelCarTemplate") + public void exportExcelCarTemplate(HttpServletResponse response, String projectSn) { + carInfoService.exportExcelCarTemplate(response, projectSn); + } + @OperLog(operModul = "车辆黑白名单管理", operType = "", operDesc = "车辆模板批量导入") + @ApiOperation(value = "车辆模板批量导入", notes = "车辆模板批量导入") + @ApiImplicitParams({ + @ApiImplicitParam(name = "projectSn", value = "项目SN", paramType = "query", required = true, dataType = "String"), + @ApiImplicitParam(name = "excelFile", value = "导入文件", paramType = "query", required = true, dataType = "String"), + }) + @PostMapping(value = "/uploadExcelCar") + public Result uploadExcelCar(MultipartFile excelFile, String projectSn) { + return carInfoService.uploadExcelCar(excelFile, projectSn); + } } diff --git a/src/main/java/com/zhgd/xmgl/modules/car/entity/CarInfo.java b/src/main/java/com/zhgd/xmgl/modules/car/entity/CarInfo.java index 84441fcb6..ccdebc964 100644 --- a/src/main/java/com/zhgd/xmgl/modules/car/entity/CarInfo.java +++ b/src/main/java/com/zhgd/xmgl/modules/car/entity/CarInfo.java @@ -63,10 +63,10 @@ public class CarInfo implements Serializable { @ApiModelProperty(value = "项目SN") private java.lang.String projectSn; /** - * 车辆类型 1渣土车辆,2外来车辆,3 工作车辆 + * 车辆类型 */ - @Excel(name = "车辆类型 1渣土车辆,2外来车辆,3 工作车辆", width = 15) - @ApiModelProperty(value = "车辆类型 1渣土车辆,2外来车辆,3 工作车辆") + @Excel(name = "车辆类型", width = 15) + @ApiModelProperty(value = "车辆类型") private java.lang.Long carType; @Excel(name = "驾驶劳务人员ID", width = 15) @@ -157,4 +157,23 @@ public class CarInfo implements Serializable { @TableField(exist = false) @ApiModelProperty(value = "从审批流过来") private Boolean fromFlow; + + public String toExistString() { + return "CarInfo{" + + "id=" + id + + ", carNumber='" + carNumber + '\'' + + ", carColor='" + carColor + '\'' + + ", projectSn='" + projectSn + '\'' + + ", carType=" + carType + + ", driverWorkerId='" + driverWorkerId + '\'' + + ", driverWorkerName='" + driverWorkerName + '\'' + + ", driverTelephone='" + driverTelephone + '\'' + + ", isBlack=" + isBlack + + ", carModuleType=" + carModuleType + + ", reserveStartTime=" + reserveStartTime + + ", reserveEndTime=" + reserveEndTime + + ", entryAndExitPermit=" + entryAndExitPermit + + ", enterpriseId=" + enterpriseId + + '}'; + } } diff --git a/src/main/java/com/zhgd/xmgl/modules/car/service/ICarInfoService.java b/src/main/java/com/zhgd/xmgl/modules/car/service/ICarInfoService.java index 1add1cd33..6eb78478e 100644 --- a/src/main/java/com/zhgd/xmgl/modules/car/service/ICarInfoService.java +++ b/src/main/java/com/zhgd/xmgl/modules/car/service/ICarInfoService.java @@ -2,11 +2,14 @@ package com.zhgd.xmgl.modules.car.service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; +import com.zhgd.jeecg.common.api.vo.Result; import com.zhgd.xmgl.async.AsyncHikvision; import com.zhgd.xmgl.modules.car.entity.CarInfo; import com.zhgd.xmgl.modules.car.entity.vo.CountCarModuleTypeVo; import com.zhgd.xmgl.modules.project.entity.Project; +import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletResponse; import java.util.List; import java.util.Map; @@ -153,4 +156,8 @@ public interface ICarInfoService extends IService { * @param carInfo */ void validEnterpriseTime(CarInfo carInfo); + + void exportExcelCarTemplate(HttpServletResponse response, String projectSn); + + Result uploadExcelCar(MultipartFile excelFile, String projectSn); } diff --git a/src/main/java/com/zhgd/xmgl/modules/car/service/impl/CarInfoServiceImpl.java b/src/main/java/com/zhgd/xmgl/modules/car/service/impl/CarInfoServiceImpl.java index f2e4d60ef..da8dbfa70 100644 --- a/src/main/java/com/zhgd/xmgl/modules/car/service/impl/CarInfoServiceImpl.java +++ b/src/main/java/com/zhgd/xmgl/modules/car/service/impl/CarInfoServiceImpl.java @@ -1,6 +1,7 @@ package com.zhgd.xmgl.modules.car.service.impl; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.StrUtil; @@ -13,6 +14,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.gexin.fastjson.JSON; import com.gexin.fastjson.JSONObject; +import com.zhgd.jeecg.common.api.vo.Result; import com.zhgd.jeecg.common.execption.OpenAlertException; import com.zhgd.redis.lock.redisson.DistributedLock; import com.zhgd.xmgl.async.AsyncHikvision; @@ -25,27 +27,38 @@ import com.zhgd.xmgl.modules.car.entity.vo.CountCarModuleTypeVo; import com.zhgd.xmgl.modules.car.enums.CarInfoCarModuleTypeEnum; import com.zhgd.xmgl.modules.car.mapper.*; import com.zhgd.xmgl.modules.car.service.ICarInfoService; +import com.zhgd.xmgl.modules.car.service.ICarTypeService; import com.zhgd.xmgl.modules.project.entity.Project; import com.zhgd.xmgl.modules.project.entity.vo.ProjectInfoExtVo; import com.zhgd.xmgl.modules.project.mapper.ProjectMapper; +import com.zhgd.xmgl.modules.project.service.IProjectEnterpriseService; import com.zhgd.xmgl.modules.project.service.impl.ProjectServiceImpl; +import com.zhgd.xmgl.modules.worker.entity.EnterpriseInfo; import com.zhgd.xmgl.modules.worker.entity.WorkerInfo; import com.zhgd.xmgl.modules.worker.mapper.WorkerInfoMapper; import com.zhgd.xmgl.modules.worker.service.impl.EnterpriseInfoServiceImpl; +import com.zhgd.xmgl.modules.worker.service.impl.WorkerInfoServiceImpl; import com.zhgd.xmgl.modules.xz.entity.XzHikvisionSync; import com.zhgd.xmgl.modules.xz.mapper.XzHikvisionSyncMapper; import com.zhgd.xmgl.modules.xz.service.impl.XzHikvisionCompareDataServiceImpl; +import com.zhgd.xmgl.security.entity.UserInfo; +import com.zhgd.xmgl.security.util.SecurityUtils; import com.zhgd.xmgl.util.*; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import java.io.InputStream; import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; import static com.zhgd.xmgl.async.AsyncHikvision.getSyncTimeWithInitAndDeleteSyncIfAbsent; @@ -82,6 +95,9 @@ public class CarInfoServiceImpl extends ServiceImpl impl MinioUtils minioUtils; @Lazy @Autowired + WorkerInfoServiceImpl workerInfoService; + @Lazy + @Autowired private XzHikvisionSyncMapper xzHikvisionSyncMapper; @Autowired private EnterpriseInfoServiceImpl enterpriseInfoService; @@ -107,6 +123,12 @@ public class CarInfoServiceImpl extends ServiceImpl impl private AsyncWorker asyncWorker; @Autowired private AsyncHikvision asyncHikvision; + @Lazy + @Autowired + private IProjectEnterpriseService projectEnterpriseService; + @Lazy + @Autowired + private ICarTypeService carTypeService; @Override public IPage selectCarListPage(Map map) { @@ -127,8 +149,7 @@ public class CarInfoServiceImpl extends ServiceImpl impl QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(CarInfo::getProjectSn, c.getProjectSn()) .eq(CarInfo::getCarNumber, c.getCarNumber()) - .last(Cts.IGNORE_DATA_SCOPE_CONDITION) - ; + .last(Cts.IGNORE_DATA_SCOPE_CONDITION); CarInfo old = carInfoMapper.selectOne(queryWrapper); c.setSendSuccessStatus(4); if (old != null) { @@ -198,6 +219,137 @@ public class CarInfoServiceImpl extends ServiceImpl impl } } + @Override + public void exportExcelCarTemplate(HttpServletResponse response, String projectSn) { + List enterpriseInfos = projectEnterpriseService.queryPageList(new MapBuilder() + .put("projectSn", projectSn) + .build()).getRecords(); + List carTypes = carTypeService.list(new LambdaQueryWrapper() + .eq(CarType::getProjectSn, projectSn)); + ExcelUtils.exportExcelCarTemplate(response, enterpriseInfos, carTypes); + } + + @Override + public Result uploadExcelCar(MultipartFile excelFile, String projectSn) { + Result result = new Result(); + StringBuilder existName = new StringBuilder(""); + ArrayList errIdCards = new ArrayList<>(); + String rtMsg = ""; + String existMsg = ""; + try { + InputStream is = excelFile.getInputStream(); + List> list = ExcelUtils.jxlExlToList(is, 0); + if (list == null || list.size() == 0) { + throw new OpenAlertException(MessageUtil.get("excelNotDataErr")); + } + this.checkParams(list, projectSn); + Map enterpriseInfoMap = projectEnterpriseService.queryPageList(new MapBuilder() + .put("projectSn", projectSn) + .build()).getRecords().stream().collect(Collectors.toMap(EnterpriseInfo::getEnterpriseName, Function.identity(), (enterpriseInfo, enterpriseInfo2) -> enterpriseInfo)); + Map numMap = carInfoMapper.selectList(new LambdaQueryWrapper() + .in(CarInfo::getCarNumber, list.stream().map(o -> o.get("车牌号")).collect(Collectors.toList())) + .last(Cts.IGNORE_DATA_SCOPE_CONDITION)).stream().collect(Collectors.toMap(CarInfo::getCarNumber, Function.identity())); + Map workerMap = workerInfoService.list(new LambdaQueryWrapper() + .eq(WorkerInfo::getProjectSn, projectSn) + .last(Cts.IGNORE_DATA_SCOPE_CONDITION)).stream().collect(Collectors.toMap(WorkerInfo::getWorkerName, Function.identity(), (workerInfo, workerInfo2) -> workerInfo)); + Map carTypeMap = carTypeService.list(new LambdaQueryWrapper() + .eq(CarType::getProjectSn, projectSn) + .last(Cts.IGNORE_DATA_SCOPE_CONDITION) + ).stream().collect(Collectors.toMap(CarType::getCarTypeName, Function.identity(), (o1, o2) -> o1)); + for (Map importInfo : list) { + String carModuleType = importInfo.get("车辆类型"); + CarInfo dataCar = numMap.get(importInfo.get("车牌号")); + CarInfo excelCar = new CarInfo(); + excelCar.setCarNumber(importInfo.get("车牌号")); + excelCar.setCarColor(importInfo.get("车辆颜色")); + excelCar.setAddTime(new Date()); + excelCar.setProjectSn(projectSn); + if (!"临时车辆".equals(carModuleType)) { + excelCar.setDriverWorkerId(Optional.ofNullable(workerMap.get(importInfo.get("司机姓名"))).map(o -> String.valueOf(o.getId())).orElse(null)); + } + excelCar.setDriverWorkerName(importInfo.get("司机姓名")); + excelCar.setDriverTelephone(importInfo.get("司机电话")); + excelCar.setIsBlack(Objects.equals(importInfo.get("是否黑名单"), "是") ? 1 : 0); + excelCar.setCarType(Optional.ofNullable(carTypeMap.get(importInfo.get("车种类型"))).map(CarType::getId).orElse(null)); + excelCar.setCarModuleType("固定车辆".equals(carModuleType) ? 1 : ("长期车辆".equals(carModuleType) ? 2 : 3)); + excelCar.setReserveStartTime(DateUtil.parse(importInfo.get("预约开始时间"))); + excelCar.setReserveEndTime(DateUtil.parse(importInfo.get("预约结束时间"))); + excelCar.setEntryAndExitPermit("单次".equals(importInfo.get("允许进出次数")) ? 0 : 1); + excelCar.setEnterpriseId(Optional.ofNullable(enterpriseInfoMap.get(importInfo.get("单位"))).map(EnterpriseInfo::getId).orElse(null)); + if (dataCar == null) { + this.addCarInfo(excelCar); + } else { + //存在车辆 + if (dataCar.toExistString().equals(excelCar.toExistString())) { + existName.append(excelCar.getCarNumber()); + existName.append("、"); + log.info("忽略批量导入已存在完全一样车辆:{}", excelCar.getCarNumber()); + continue; + } + excelCar.setId(dataCar.getId()); + this.editCarInfo(excelCar); + } + } + if (!"".equals(existName.toString())) { + existName.deleteCharAt(existName.lastIndexOf("、")); + existMsg = "车牌号为:" + existName + "的车辆已存在对应信息(车牌号等信息一致)"; + } + String errIdCardMsg = ""; + if (CollUtil.isNotEmpty(errIdCards)) { + if (StrUtil.isNotBlank(existMsg)) { + errIdCardMsg += ","; + } + } + rtMsg = StrUtil.format("导入成功。{}{}", existMsg, errIdCardMsg); + result.successMsg(rtMsg); + } catch (OpenAlertException e) { + log.error("error:", e); + rtMsg = e.getMessage(); + result.error500(rtMsg); + } catch (Exception e) { + log.error("error:", e); + rtMsg = MessageUtil.get("failErr"); + result.error500(rtMsg); + } + UserInfo user = SecurityUtils.getUser(); + if (user != null) { + noticeService.addUserNotice(user.getUserId(), "批量导入提醒", rtMsg, "10"); + } + return result; + } + + private void checkParams(List> list, String projectSn) { + for (Map importInfo : list) { + if (StringUtils.isBlank(importInfo.get("单位"))) { + throw new OpenAlertException("有单位未填写"); + } + if (StringUtils.isBlank(importInfo.get("车辆类型"))) { + throw new OpenAlertException("有车辆类型未填写"); + } + if (StringUtils.isBlank(importInfo.get("车牌号"))) { + throw new OpenAlertException("有车牌号未填写"); + } + if (StringUtils.isBlank(importInfo.get("车辆颜色"))) { + throw new OpenAlertException("有车辆颜色未填写"); + } + if (StringUtils.isBlank(importInfo.get("车种类型"))) { + throw new OpenAlertException("有车种类型未填写"); + } + if (StringUtils.isBlank(importInfo.get("司机姓名"))) { + throw new OpenAlertException("有司机姓名未填写"); + } + if (StringUtils.isBlank(importInfo.get("司机电话"))) { + throw new OpenAlertException("有司机电话未填写"); + } + if (StringUtils.isBlank(importInfo.get("司机电话"))) { + throw new OpenAlertException("有司机电话未填写"); + } + if (!"固定车辆".equals(importInfo.get("车辆类型")) && DateUtil.compare(DateUtil.parse(importInfo.get("预约结束时间")), new Date()) < 0) { + throw new OpenAlertException("预约时间已失效,车辆" + importInfo.get("车牌号") + "无法下发,请重新提交"); + } + } + } + private void validTime(CarInfo c) { if (isReservationType(c) && DateUtil.compare(c.getReserveEndTime(), new Date()) < 0) { throw new OpenAlertException("预约时间已失效,车辆无法下发,请重新提交"); diff --git a/src/main/java/com/zhgd/xmgl/modules/project/controller/ProjectEnterpriseController.java b/src/main/java/com/zhgd/xmgl/modules/project/controller/ProjectEnterpriseController.java index e014f66ad..90645f401 100644 --- a/src/main/java/com/zhgd/xmgl/modules/project/controller/ProjectEnterpriseController.java +++ b/src/main/java/com/zhgd/xmgl/modules/project/controller/ProjectEnterpriseController.java @@ -92,7 +92,7 @@ public class ProjectEnterpriseController { }) @PostMapping(value = "/list") public Result> queryPageList(@RequestBody Map map) { - IPage pageList = projectEnterpriseService.selectProjectEnterprisePage(map); + IPage pageList = projectEnterpriseService.queryPageList(map); return Result.success(pageList); } @@ -116,7 +116,7 @@ public class ProjectEnterpriseController { public Result>> selectDetailList(@RequestBody Map map) { map.put("pageNo", -1); map.put("pageSize", 10); - IPage pageList = projectEnterpriseService.selectProjectEnterprisePage(map); + IPage pageList = projectEnterpriseService.queryPageList(map); List enterpriseIds = pageList.getRecords().stream().map(e -> e.getId()).collect(Collectors.toList()); Map userMap = new HashMap<>(16); userMap.put("projectSn", map.get("projectSn").toString()); diff --git a/src/main/java/com/zhgd/xmgl/modules/project/service/IProjectEnterpriseService.java b/src/main/java/com/zhgd/xmgl/modules/project/service/IProjectEnterpriseService.java index a53759d9b..3f289091e 100644 --- a/src/main/java/com/zhgd/xmgl/modules/project/service/IProjectEnterpriseService.java +++ b/src/main/java/com/zhgd/xmgl/modules/project/service/IProjectEnterpriseService.java @@ -24,7 +24,7 @@ public interface IProjectEnterpriseService extends IService { * @param map * @return */ - IPage selectProjectEnterprisePage(Map map); + IPage queryPageList(Map map); /** * 添加项目劳务公司关联信息 diff --git a/src/main/java/com/zhgd/xmgl/modules/project/service/impl/ProjectEnterpriseServiceImpl.java b/src/main/java/com/zhgd/xmgl/modules/project/service/impl/ProjectEnterpriseServiceImpl.java index 1c6469610..bfe59a0be 100644 --- a/src/main/java/com/zhgd/xmgl/modules/project/service/impl/ProjectEnterpriseServiceImpl.java +++ b/src/main/java/com/zhgd/xmgl/modules/project/service/impl/ProjectEnterpriseServiceImpl.java @@ -52,7 +52,7 @@ public class ProjectEnterpriseServiceImpl extends ServiceImpl selectProjectEnterprisePage(Map map) { + public IPage queryPageList(Map map) { int pageNo = Integer.parseInt(map.getOrDefault("pageNo", 1).toString()); int pageSize = Integer.parseInt(map.getOrDefault("pageSize", 10).toString()); Page page = new Page<>(pageNo, pageSize); diff --git a/src/main/java/com/zhgd/xmgl/modules/worker/service/IWorkerTypeService.java b/src/main/java/com/zhgd/xmgl/modules/worker/service/IWorkerTypeService.java index 940fb5167..507ae26cb 100644 --- a/src/main/java/com/zhgd/xmgl/modules/worker/service/IWorkerTypeService.java +++ b/src/main/java/com/zhgd/xmgl/modules/worker/service/IWorkerTypeService.java @@ -1,8 +1,10 @@ package com.zhgd.xmgl.modules.worker.service; +import com.zhgd.jeecg.common.mybatis.EntityMap; import com.zhgd.xmgl.modules.worker.entity.WorkerType; import com.baomidou.mybatisplus.extension.service.IService; +import java.util.List; import java.util.Map; /** diff --git a/src/main/java/com/zhgd/xmgl/modules/worker/service/impl/WorkerInfoServiceImpl.java b/src/main/java/com/zhgd/xmgl/modules/worker/service/impl/WorkerInfoServiceImpl.java index ca19ae076..cc3525399 100644 --- a/src/main/java/com/zhgd/xmgl/modules/worker/service/impl/WorkerInfoServiceImpl.java +++ b/src/main/java/com/zhgd/xmgl/modules/worker/service/impl/WorkerInfoServiceImpl.java @@ -36,7 +36,6 @@ import com.zhgd.xmgl.modules.baotou.entity.WorkerAdmissionDetail; import com.zhgd.xmgl.modules.baotou.service.IDeviceUnitService; import com.zhgd.xmgl.modules.baotou.service.IWorkerAdmissionDetailService; import com.zhgd.xmgl.modules.basicdata.entity.Company; -import com.zhgd.xmgl.modules.basicdata.entity.DictionaryItem; import com.zhgd.xmgl.modules.basicdata.entity.SystemUser; import com.zhgd.xmgl.modules.basicdata.enums.CompanyTypeEnum; import com.zhgd.xmgl.modules.basicdata.enums.SystemUserAccountTypeEnum; @@ -133,6 +132,8 @@ public class WorkerInfoServiceImpl extends ServiceImpl teamList = teamInfoMapper.selectTeamInfoBySnList(projectSn); -// List departmentList = departmentInfoMapper.selectDepartmentInfoBySnList(projectSn); - List workerTypeList = dictionaryItemService.getDictList("bt_worker_type", projectSn); + List departmentList = departmentInfoMapper.selectDepartmentInfoBySnList(projectSn); + //List workerTypeList = dictionaryItemService.getDictList("bt_worker_type", projectSn); List deviceUnitList = deviceUnitService.list(new LambdaQueryWrapper() .eq(DeviceUnit::getProjectSn, projectSn)); + List workerTypeList = workerTypeService.list(new LambdaQueryWrapper() + .eq(WorkerType::getProjectSn, projectSn)); List enterpriseInfoList = projectEnterpriseService.selectProjectEnterpriseList(new MapBuilder().put("sn", projectSn).build()); - ExcelUtils.exporExcelWorkerTemplate(response, workerTypeList, deviceUnitList, enterpriseInfoList); + ExcelUtils.exporExcelWorkerTemplate(response, deviceUnitList, enterpriseInfoList, departmentList, workerTypeList); } @Override @@ -1951,7 +1954,6 @@ public class WorkerInfoServiceImpl extends ServiceImpl unitMap = deviceUnitService.list(new LambdaQueryWrapper() .eq(DeviceUnit::getProjectSn, projectSn)).stream().collect(Collectors.toMap(DeviceUnit::getDeviceUnitName, Function.identity(), (deviceUnit, deviceUnit2) -> deviceUnit)); - Map enterpriseNameMap = projectEnterpriseService.selectProjectEnterpriseList(new MapBuilder().put("sn", projectSn).build()).stream().collect(Collectors.toMap(o -> MapUtils.getString(o, "enterpriseName"), o -> MapUtils.getLong(o, "id"), (aLong, aLong2) -> aLong)); for (Map importInfo : list) { WorkerInfo workerInfo = new WorkerInfo(); workerInfo.setProjectSn(projectSn); @@ -1983,7 +1985,7 @@ public class WorkerInfoServiceImpl extends ServiceImpl> list, String projectSn) { - List workerTypeList = dictionaryItemService.getDictList("bt_worker_type", projectSn); - Map typeMap = workerTypeList.stream().collect(Collectors.toMap(DictionaryItem::getName, Function.identity(), (dictionaryItem, dictionaryItem2) -> dictionaryItem)); + //List workerTypeList = dictionaryItemService.getDictList("bt_worker_type", projectSn); + List workerTypeList = workerTypeService.list(new LambdaQueryWrapper() + .eq(WorkerType::getProjectSn, projectSn)); + //Map typeMap = workerTypeList.stream().collect(Collectors.toMap(DictionaryItem::getName, Function.identity(), (dictionaryItem, dictionaryItem2) -> dictionaryItem)); + Map typeMap = workerTypeList.stream().collect(Collectors.toMap(WorkerType::getTypeName, Function.identity(), (dictionaryItem, dictionaryItem2) -> dictionaryItem)); Map teamMap = teamInfoMapper.getTeamInfoMapBySn(projectSn); Map departmentMap = departmentInfoMapper.getDepartmentInfoMapBySn(projectSn); List typeList = workerTypeService.list(new LambdaQueryWrapper() .eq(WorkerType::getProjectSn, projectSn)); List enterpriseList = projectEnterpriseService.selectProjectEnterpriseList(new MapBuilder().put("sn", projectSn).build()); - List addTypeList = new ArrayList<>(); - for (DictionaryItem item : workerTypeList) { - Optional op = typeList.stream().filter(o -> Objects.equals(o.getTypeName(), item.getName())).findAny(); - if (!op.isPresent()) { - WorkerType type = new WorkerType(); - type.setTypeName(item.getName()); - type.setProjectSn(projectSn); - addTypeList.add(type); - } - } - if (CollUtil.isNotEmpty(addTypeList)) { - workerTypeService.saveBatch(addTypeList); - typeList = workerTypeService.list(new LambdaQueryWrapper() - .eq(WorkerType::getProjectSn, projectSn)); - } + //List addTypeList = new ArrayList<>(); + //for (DictionaryItem item : workerTypeList) { + // Optional op = typeList.stream().filter(o -> Objects.equals(o.getTypeName(), item.getName())).findAny(); + // if (!op.isPresent()) { + // WorkerType type = new WorkerType(); + // type.setTypeName(item.getName()); + // type.setProjectSn(projectSn); + // addTypeList.add(type); + // } + //} + //if (CollUtil.isNotEmpty(addTypeList)) { + // workerTypeService.saveBatch(addTypeList); + // typeList = workerTypeService.list(new LambdaQueryWrapper() + // .eq(WorkerType::getProjectSn, projectSn)); + //} for (Map map : list) { String name = MapUtils.getString(map, "*单位名称"); String typeName = MapUtils.getString(map, "*岗位(工种)"); - Integer personType = getPersonType(typeMap, typeName); + Integer personType = typeMap.get(typeName) != null ? 1 : 2; Long dtId = null; Optional enterpriseNameOp = enterpriseList.stream().filter(o -> Objects.equals(MapUtils.getString(((Map) o), "enterpriseName"), name)).findFirst(); Long enterpriseId = null; @@ -2163,29 +2173,12 @@ public class WorkerInfoServiceImpl extends ServiceImpl typeMap, String typeName) { - Integer personType = 1; - DictionaryItem di = typeMap.get(typeName); - if (di != null) { - Integer i = Convert.toInt(di.getData()); - if (i != null) { - if (i >= 200) { - personType = 1; - } else { - personType = 2; - } - } - } - return personType; - } - @Transactional(rollbackFor = Exception.class) public void editWorkerForUploadExcel(WorkerInfo workerInfo) { xzHikvisionSyncMapper.delete(new LambdaQueryWrapper() @@ -2230,21 +2223,23 @@ public class WorkerInfoServiceImpl extends ServiceImpl numList = list.stream().collect(Collectors.groupingBy(m -> m.get("编号"), Collectors.counting())).entrySet().stream().filter(key -> key.getValue() > 1).map(o -> o.getKey()).collect(Collectors.toList()); + List numList = list.stream().filter(m -> StrUtil.isNotBlank(m.get("编号"))).collect(Collectors.groupingBy(m -> m.get("编号"), Collectors.counting())).entrySet().stream().filter(key -> key.getValue() > 1).map(o -> o.getKey()).collect(Collectors.toList()); if (CollUtil.isNotEmpty(numList)) { throw new OpenAlertException("编号有重复,重复的号码为:" + StringUtils.join(numList)); } - List numList1 = list.stream().map(o -> o.get("编号")).collect(Collectors.toList()); + List numList1 = list.stream().filter(m -> StrUtil.isNotBlank(m.get("编号"))).map(o -> o.get("编号")).collect(Collectors.toList()); List cardList1 = list.stream().map(o -> o.get("*身份证号码")).collect(Collectors.toList()); - List infos = workerInfoMapper.selectList(new LambdaQueryWrapper() - .eq(WorkerInfo::getProjectSn, projectSn) - .in(WorkerInfo::getNum, numList1) - .notIn(WorkerInfo::getIdCard, cardList1) - .last(Cts.IGNORE_DATA_SCOPE_CONDITION) - ); - if (CollUtil.isNotEmpty(infos)) { - throw new OpenAlertException("人员编号已存在,重复的人员和编号为:" + StringUtils.join(infos.stream().map(o -> o.getWorkerName() + "(" + o.getNum() + ")").collect(Collectors.toList()))); + if (CollUtil.isNotEmpty(numList1)) { + List infos = workerInfoMapper.selectList(new LambdaQueryWrapper() + .eq(WorkerInfo::getProjectSn, projectSn) + .in(WorkerInfo::getNum, numList1) + .notIn(WorkerInfo::getIdCard, cardList1) + .last(Cts.IGNORE_DATA_SCOPE_CONDITION) + ); + if (CollUtil.isNotEmpty(infos)) { + throw new OpenAlertException("人员编号已存在,重复的人员和编号为:" + StringUtils.join(infos.stream().map(o -> o.getWorkerName() + "(" + o.getNum() + ")").collect(Collectors.toList()))); + } } } diff --git a/src/main/java/com/zhgd/xmgl/security/WebSecurityConfig.java b/src/main/java/com/zhgd/xmgl/security/WebSecurityConfig.java index 38ea221ad..9777e1853 100644 --- a/src/main/java/com/zhgd/xmgl/security/WebSecurityConfig.java +++ b/src/main/java/com/zhgd/xmgl/security/WebSecurityConfig.java @@ -80,6 +80,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { http.authorizeRequests() //请求路径允许访问 + .antMatchers("/xmgl/carInfo/exportExcelCarTemplate").permitAll() .antMatchers("/xmgl/weeklyMonthlyRiskIdentification/flow/add").permitAll() .antMatchers("/xmgl/projectHomeNotice/flow/add").permitAll() .antMatchers("/xmgl/promotionalVideo/flow/add").permitAll() diff --git a/src/main/java/com/zhgd/xmgl/task/JzgTask.java b/src/main/java/com/zhgd/xmgl/task/JzgTask.java index eb3debf53..923d2b717 100644 --- a/src/main/java/com/zhgd/xmgl/task/JzgTask.java +++ b/src/main/java/com/zhgd/xmgl/task/JzgTask.java @@ -33,7 +33,6 @@ import net.javacrumbs.shedlock.core.SchedulerLock; import org.apache.commons.codec.binary.Hex; import org.apache.commons.collections.MapUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -837,7 +836,7 @@ public class JzgTask { eMap.put("projectSn", projectSn); eMap.put("pageNo", "1"); eMap.put("pageSize", "9999999"); - List records = projectEnterpriseService.selectProjectEnterprisePage(eMap).getRecords(); + List records = projectEnterpriseService.queryPageList(eMap).getRecords(); Map jzgEnterpriseInfoMap = new HashMap<>(16); if (jzgRt != null) { String data = jzgRt.getData(); diff --git a/src/main/java/com/zhgd/xmgl/util/ExcelUtils.java b/src/main/java/com/zhgd/xmgl/util/ExcelUtils.java index 68d6ead7b..082abf062 100644 --- a/src/main/java/com/zhgd/xmgl/util/ExcelUtils.java +++ b/src/main/java/com/zhgd/xmgl/util/ExcelUtils.java @@ -2,7 +2,7 @@ package com.zhgd.xmgl.util; import com.zhgd.jeecg.common.mybatis.EntityMap; import com.zhgd.xmgl.modules.baotou.entity.DeviceUnit; -import com.zhgd.xmgl.modules.basicdata.entity.DictionaryItem; +import com.zhgd.xmgl.modules.car.entity.CarType; import com.zhgd.xmgl.modules.exam.entity.ExamSubject; import com.zhgd.xmgl.modules.worker.entity.EnterpriseInfo; import com.zhgd.xmgl.modules.worker.entity.WorkerSafeEducationWorker; @@ -229,22 +229,32 @@ public class ExcelUtils { } } - public static void exporExcelWorkerTemplate(HttpServletResponse response, List workerTypeList, List deviceUnitList, List enterpriseInfoList) { + public static void exporExcelWorkerTemplate(HttpServletResponse response, List deviceUnitList, List enterpriseInfoList, List departmentList, List typeList) { try { ClassPathResource classPathResource = new ClassPathResource("excel/人员导入模板.xlsx"); InputStream inputStream = classPathResource.getInputStream(); XSSFWorkbook workbook = new XSSFWorkbook(inputStream); //*岗位(工种)下拉列 - XSSFSheet sheet1 = workbook.getSheet("岗位(班组)"); - if (workerTypeList.size() > 0) { - for (int i = 0; i < workerTypeList.size(); i++) { + XSSFSheet sheet1 = workbook.getSheet("岗位(工种)"); + if (departmentList.size() > 0) { + for (int i = 0; i < departmentList.size(); i++) { XSSFRow row1 = sheet1.createRow(i); XSSFCell cell1 = row1.createCell(0); - DictionaryItem obj = workerTypeList.get(i); + EntityMap obj = departmentList.get(i); cell1.setCellType(CellType.STRING); - cell1.setCellValue(obj.getName()); + cell1.setCellValue(MapUtils.getString(obj, "enterpriseDepartmentName")); } } + if (typeList.size() > 0) { + for (int i = departmentList.size(); i < typeList.size() + departmentList.size(); i++) { + XSSFRow row1 = sheet1.createRow(i); + XSSFCell cell1 = row1.createCell(0); + WorkerType obj = typeList.get(i - departmentList.size()); + cell1.setCellType(CellType.STRING); + cell1.setCellValue(obj.getTypeName()); + } + } + //工作区域下拉 XSSFSheet sheet2 = workbook.getSheet("工作区域"); if (deviceUnitList.size() > 0) { @@ -264,7 +274,8 @@ public class ExcelUtils { XSSFCell cell1 = row1.createCell(0); EntityMap obj = enterpriseInfoList.get(i); cell1.setCellType(CellType.STRING); - cell1.setCellValue(MapUtils.getString(obj, "enterpriseName")); } + cell1.setCellValue(MapUtils.getString(obj, "enterpriseName")); + } } downLoadExcel("人员导入模板.xlsx", response, workbook); } catch (IOException e) { @@ -418,4 +429,38 @@ public class ExcelUtils { return cell.getStringCellValue(); } + public static void exportExcelCarTemplate(HttpServletResponse response, List enterpriseInfos, List carTypes) { + try { + ClassPathResource classPathResource = new ClassPathResource("excel/车辆导入模板.xlsx"); + InputStream inputStream = classPathResource.getInputStream(); + XSSFWorkbook workbook = new XSSFWorkbook(inputStream); + //单位 + XSSFSheet sheet1 = workbook.getSheet("单位"); + if (enterpriseInfos.size() > 0) { + for (int i = 0; i < enterpriseInfos.size(); i++) { + XSSFRow row1 = sheet1.createRow(i); + XSSFCell cell1 = row1.createCell(0); + EnterpriseInfo obj = enterpriseInfos.get(i); + cell1.setCellType(CellType.STRING); + cell1.setCellValue(obj.getEnterpriseName()); + } + } + + //车种类型 + XSSFSheet sheet2 = workbook.getSheet("车种类型"); + if (carTypes.size() > 0) { + for (int i = 0; i < carTypes.size(); i++) { + XSSFRow row1 = sheet2.createRow(i); + XSSFCell cell1 = row1.createCell(0); + CarType obj = carTypes.get(i); + cell1.setCellType(CellType.STRING); + cell1.setCellValue(obj.getCarTypeName()); + } + } + + downLoadExcel("车辆导入模板.xlsx", response, workbook); + } catch (IOException e) { + log.error("error:", e); + } + } } diff --git a/src/main/resources/excel/人员导入模板.xlsx b/src/main/resources/excel/人员导入模板.xlsx index cb535cf26d785c0e5adcb1f4c86c55cb9d543845..6ff048281822c86b1c3ce6d53fc3b64946858a84 100644 GIT binary patch delta 5527 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 Z3&mY{{Y~g4G{nU diff --git a/src/main/resources/excel/车辆导入模板.xlsx b/src/main/resources/excel/车辆导入模板.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..e7d7be658d05b8d1481ca5d7a2896d3fce609ff8 GIT binary patch literal 14361 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