Commit 6a6f391d6f70d99354a374d2a42ee3711e451ad0

Authored by 王富生
2 parents a6132677 f2fb187d

Merge remote-tracking branch 'origin/dev' into dev

# Conflicts:
#	urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/road/RoadStreetController.java
Showing 50 changed files with 1292 additions and 179 deletions
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/api/material/MaterialApi.java 0 → 100644
  1 +package com.zteits.urbanops.module.garden.api.material;
  2 +
  3 +import com.zteits.urbanops.module.garden.api.material.dto.MaterialInventoryOutDto;
  4 +
  5 +/**
  6 + * @Classname MaterialApi
  7 + * @Description 物料出库
  8 + * @Date 2025/12/16 16:19
  9 + * @Created by wangqian
  10 + */
  11 +public interface MaterialApi {
  12 +
  13 + /**
  14 + * 创建物料出库
  15 + *
  16 + * @param outDto 创建信息
  17 + * @return 编号
  18 + */
  19 + Long createMaterialInventoryOut(MaterialInventoryOutDto outDto);
  20 +}
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/api/material/MaterialApiImpl.java 0 → 100644
  1 +package com.zteits.urbanops.module.garden.api.material;
  2 +
  3 +import cn.hutool.core.bean.BeanUtil;
  4 +import com.zteits.urbanops.module.garden.api.material.dto.MaterialInventoryOutDto;
  5 +import com.zteits.urbanops.module.garden.controller.admin.materialinventoryout.vo.MaterialInventoryOutSaveReqVO;
  6 +import com.zteits.urbanops.module.garden.service.materialinventoryout.MaterialInventoryOutService;
  7 +import jakarta.annotation.Resource;
  8 +import org.springframework.stereotype.Service;
  9 +import org.springframework.validation.annotation.Validated;
  10 +
  11 +/**
  12 + * @Classname MaterialApiImpl
  13 + * @Description 物料接口
  14 + * @Date 2025/12/16 16:21
  15 + * @Created by wangqian
  16 + */
  17 +@Service
  18 +@Validated
  19 +public class MaterialApiImpl implements MaterialApi{
  20 +
  21 + @Resource
  22 + private MaterialInventoryOutService materialInventoryOutService;
  23 + @Override
  24 + public Long createMaterialInventoryOut(MaterialInventoryOutDto outDto) {
  25 + MaterialInventoryOutSaveReqVO createReqVO = BeanUtil.toBean(outDto, MaterialInventoryOutSaveReqVO.class);
  26 + return materialInventoryOutService.createMaterialInventoryOut(createReqVO);
  27 + }
  28 +}
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/api/material/dto/MaterialInventoryOutDto.java 0 → 100644
  1 +package com.zteits.urbanops.module.garden.api.material.dto;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import jakarta.validation.constraints.NotNull;
  5 +import lombok.Data;
  6 +
  7 +import java.time.LocalDateTime;
  8 +
  9 +/**
  10 + * @Classname MaterialInventoryOutDto
  11 + * @Description 物料出库
  12 + * @Date 2025/12/16 16:22
  13 + * @Created by wangqian
  14 + */
  15 +@Data
  16 +public class MaterialInventoryOutDto {
  17 + @Schema(description = "入库ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "18713")
  18 + private Long id;
  19 +
  20 + @Schema(description = "物料ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "14541")
  21 + @NotNull(message = "物料ID不能为空")
  22 + private Long materialId;
  23 +
  24 + @Schema(description = "物料名称", example = "芋艿")
  25 + private String materialName;
  26 +
  27 + @Schema(description = "出库数量", requiredMode = Schema.RequiredMode.REQUIRED)
  28 + @NotNull(message = "出库数量不能为空")
  29 + private Long outInventoryNum;
  30 +
  31 + @Schema(description = "出库日期", requiredMode = Schema.RequiredMode.REQUIRED)
  32 + @NotNull(message = "出库日期不能为空")
  33 + private LocalDateTime outDate;
  34 +
  35 +}
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/assigntasks/AssignTasksController.java
... ... @@ -92,12 +92,10 @@ public class AssignTasksController {
92 92 List<AssignTasksInfoDO> assignTaskInfoList = asignTasksInfoService.getAssignTasksInfos(assignTasks.getId());
93 93 assignTasksRespVO.setAssignTaskInfoList(assignTaskInfoList);
94 94 //获取单位集合
95   - List<String> companyIds = CollectionUtil.isEmpty(assignTaskInfoList)
  95 + List<Long> companyIds = CollectionUtil.isEmpty(assignTaskInfoList)
96 96 ? Collections.emptyList()
97 97 : assignTaskInfoList.stream()
98 98 .map(AssignTasksInfoDO::getCompanyId)
99   - .map(StrUtil::toString) // Hutool 工具类:自动处理 null(转为 null 字符串,需配合过滤)
100   - .filter(StrUtil::isNotEmpty) // 过滤 null/空字符串
101 99 .distinct()
102 100 .collect(Collectors.toList());
103 101 assignTasksRespVO.setCompanyIds(companyIds);
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/assigntasks/vo/AssignTasksRespVO.java
... ... @@ -63,7 +63,7 @@ public class AssignTasksRespVO {
63 63 @Schema(description = "修改人(关联用户ID,最后修改人)")
64 64 private String updater;
65 65  
66   - private List<String> companyIds;
  66 + private List<Long> companyIds;
67 67 private List<AssignTasksInfoDO> assignTaskInfoList;
68 68  
69 69 public void setParentFinish(Integer parentFinish) {
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/assigntasks/vo/AssignTasksSaveReqVO.java
... ... @@ -58,6 +58,6 @@ public class AssignTasksSaveReqVO {
58 58  
59 59 /*单位集合*/
60 60 @NotEmpty(message = "派发单位不能为空")
61   - private List<String> companyIds;
  61 + private List<Long> companyIds;
62 62  
63 63 }
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/inspectionplan/InspectionPlanController.java
... ... @@ -47,7 +47,7 @@ public class InspectionPlanController {
47 47 @PreAuthorize("@ss.hasPermission('garden:inspection-plan:create')")
48 48 public CommonResult<Integer> createInspectionPlan(@Valid @RequestBody InspectionPlanSaveReqVO createReqVO) {
49 49 if(!createReqVO.verify()){
50   - log.warn("次数值范围:1-10或者分数格式:1/3, rateValue={}", createReqVO.getRateValue());
  50 + log.warn("次数值范围:1-1000或者分数格式:1/3, rateValue={}", createReqVO.getRateValue());
51 51 return error(PLAN_RATE_VALUE_ERROR);
52 52 }
53 53 // //临时计划
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/inspectionplan/vo/InspectionPlanCommitPageReqVO.java
... ... @@ -63,4 +63,12 @@ public class InspectionPlanCommitPageReqVO extends PageParam {
63 63 private String remark;
64 64  
65 65 private List<String> busiLineList;
  66 +
  67 + @Schema(description = "创建开始时间")
  68 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
  69 + private LocalDate createTimeStart;
  70 +
  71 + @Schema(description = "创建结束时间")
  72 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
  73 + private LocalDate createTimeEnd;
66 74 }
67 75 \ No newline at end of file
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/inspectionplan/vo/InspectionPlanSaveReqVO.java
... ... @@ -46,6 +46,7 @@ public class InspectionPlanSaveReqVO {
46 46  
47 47 @Schema(description = "频次值", requiredMode = Schema.RequiredMode.REQUIRED)
48 48 @NotEmpty(message = "频次值不能为空")
  49 + @Size(max = 6 , message = "频次值长度不能大于6")
49 50 private String rateValue;
50 51  
51 52 @Schema(description = "周期ID: 0:次;1:日/次;2:周/次;3:月/次;4:季/次;5:半年/次;6:年/次", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/maintainplan/vo/MaintainPlanCommitPageReqVO.java
... ... @@ -60,4 +60,12 @@ public class MaintainPlanCommitPageReqVO extends PageParam {
60 60 @Schema(description = "提交人用户ID", example = "王五")
61 61 private String userName;
62 62  
63   -}
64 63 \ No newline at end of file
  64 + @Schema(description = "创建开始时间")
  65 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
  66 + private LocalDate createTimeStart;
  67 +
  68 + @Schema(description = "创建结束时间")
  69 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
  70 + private LocalDate createTimeEnd;
  71 +
  72 +}
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/maintainplan/vo/MaintainPlanDetailRespVO.java
... ... @@ -74,4 +74,4 @@ public class MaintainPlanDetailRespVO {
74 74 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
75 75 @ExcelProperty("创建时间")
76 76 private LocalDateTime createTime;
77   -}
78 77 \ No newline at end of file
  78 +}
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/maintainplan/vo/MaintainPlanSaveReqVO.java
... ... @@ -46,6 +46,7 @@ public class MaintainPlanSaveReqVO {
46 46  
47 47 @Schema(description = "频次值", requiredMode = Schema.RequiredMode.REQUIRED)
48 48 @NotEmpty(message = "频次值不能为空")
  49 + @Size(max = 6 , message = "频次值长度不能大于6")
49 50 private String rateValue;
50 51  
51 52 @Schema(description = "周期ID: 1:日/次;2:周/次;3:月/次;4:年/次;5:按次;6:季度;7:半年", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/road/RoadStreetController.java
... ... @@ -40,14 +40,14 @@ public class RoadStreetController {
40 40  
41 41 @PostMapping("/create")
42 42 @Operation(summary = "创建街道")
43   - @PreAuthorize("@ss.hasPermission('garden:road-street:create')")
  43 +// @PreAuthorize("@ss.hasPermission('garden:road-street:create')")
44 44 public CommonResult<Long> createRoadStreet(@Valid @RequestBody RoadStreetSaveReqVO createReqVO) {
45 45 return success(roadStreetService.createRoadStreet(createReqVO));
46 46 }
47 47  
48 48 @PutMapping("/update")
49 49 @Operation(summary = "更新街道")
50   - @PreAuthorize("@ss.hasPermission('garden:road-street:update')")
  50 +// @PreAuthorize("@ss.hasPermission('garden:road-street:update')")
51 51 public CommonResult<Boolean> updateRoadStreet(@Valid @RequestBody RoadStreetSaveReqVO updateReqVO) {
52 52 roadStreetService.updateRoadStreet(updateReqVO);
53 53 return success(true);
... ... @@ -56,7 +56,7 @@ public class RoadStreetController {
56 56 @DeleteMapping("/delete")
57 57 @Operation(summary = "删除街道")
58 58 @Parameter(name = "id", description = "编号", required = true)
59   - @PreAuthorize("@ss.hasPermission('garden:road-street:delete')")
  59 +// @PreAuthorize("@ss.hasPermission('garden:road-street:delete')")
60 60 public CommonResult<Boolean> deleteRoadStreet(@RequestParam("id") Long id) {
61 61 roadStreetService.deleteRoadStreet(id);
62 62 return success(true);
... ... @@ -65,7 +65,7 @@ public class RoadStreetController {
65 65 @DeleteMapping("/delete-list")
66 66 @Parameter(name = "ids", description = "编号", required = true)
67 67 @Operation(summary = "批量删除街道")
68   - @PreAuthorize("@ss.hasPermission('garden:road-street:delete')")
  68 +// @PreAuthorize("@ss.hasPermission('garden:road-street:delete')")
69 69 public CommonResult<Boolean> deleteRoadStreetList(@RequestParam("ids") List<Long> ids) {
70 70 roadStreetService.deleteRoadStreetListByIds(ids);
71 71 return success(true);
... ... @@ -74,7 +74,7 @@ public class RoadStreetController {
74 74 @GetMapping("/get")
75 75 @Operation(summary = "获得街道")
76 76 @Parameter(name = "id", description = "编号", required = true, example = "1024")
77   - @PreAuthorize("@ss.hasPermission('garden:road-street:query')")
  77 +// @PreAuthorize("@ss.hasPermission('garden:road-street:query')")
78 78 public CommonResult<RoadStreetRespVO> getRoadStreet(@RequestParam("id") Long id) {
79 79 RoadStreetDO roadStreet = roadStreetService.getRoadStreet(id);
80 80 return success(BeanUtils.toBean(roadStreet, RoadStreetRespVO.class));
... ... @@ -90,7 +90,7 @@ public class RoadStreetController {
90 90  
91 91 @GetMapping("/page")
92 92 @Operation(summary = "获得街道分页")
93   - @PreAuthorize("@ss.hasPermission('garden:road-street:query')")
  93 +// @PreAuthorize("@ss.hasPermission('garden:road-street:query')")
94 94 public CommonResult<PageResult<RoadStreetRespVO>> getRoadStreetPage(@Valid RoadStreetPageReqVO pageReqVO) {
95 95 PageResult<RoadStreetDO> pageResult = roadStreetService.getRoadStreetPage(pageReqVO);
96 96 return success(BeanUtils.toBean(pageResult, RoadStreetRespVO.class));
... ... @@ -98,7 +98,7 @@ public class RoadStreetController {
98 98  
99 99 @GetMapping("/export-excel")
100 100 @Operation(summary = "导出街道 Excel")
101   - @PreAuthorize("@ss.hasPermission('garden:road-street:export')")
  101 +// @PreAuthorize("@ss.hasPermission('garden:road-street:export')")
102 102 @ApiAccessLog(operateType = EXPORT)
103 103 public void exportRoadStreetExcel(@Valid RoadStreetPageReqVO pageReqVO,
104 104 HttpServletResponse response) throws IOException {
... ... @@ -109,4 +109,4 @@ public class RoadStreetController {
109 109 BeanUtils.toBean(list, RoadStreetRespVO.class));
110 110 }
111 111  
112   -}
113 112 \ No newline at end of file
  113 +}
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/dataobject/assigntasksinfo/AssignTasksInfoDO.java
... ... @@ -38,7 +38,7 @@ public class AssignTasksInfoDO extends BaseDO {
38 38 /**
39 39 * 单位ID(关联单位表主键)
40 40 */
41   - private String companyId;
  41 + private Long companyId;
42 42 /**
43 43 * 单位ID(关联单位表主键)
44 44 */
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/enums/ErrorCodeConstants.java
... ... @@ -98,7 +98,7 @@ public interface ErrorCodeConstants {
98 98 ErrorCode PLAN_RATE_DETAIL_EXISTS = new ErrorCode(1-100-007-003, "计划频次已存在");
99 99 ErrorCode PLAN_RATE_VALUE_ERROR = new ErrorCode(1-100-007-004, "次数值范围:1-10或者分数格式:1/3");
100 100 ErrorCode PLAN_RATE_VALUE_INTEGER_ERROR = new ErrorCode(1-100-007-005, "临时计划-次数值范围:1-10的整数");
101   -
  101 + ErrorCode PLAN_NAME_EXISTED = new ErrorCode(1-100-007-006, "计划名称已存在");
102 102 ErrorCode MATERIAL_TYPE_NOT_EXISTS = new ErrorCode(1-100-004-001, "物料类型不存在");
103 103 ErrorCode MATERIAL_TYPE_MANAGER_NOT_EXISTS = new ErrorCode(1-100-004-002, "耗材类别管理不存在");
104 104  
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/assigntasks/AssignTasksServiceImpl.java
... ... @@ -92,7 +92,7 @@ public class AssignTasksServiceImpl implements AssignTasksService {
92 92 assignTasksMapper.updateById(updateObj);
93 93  
94 94 // 1. 处理关联的单位任务信息(仅当存在单位ID列表时)
95   - List<String> companyIds = updateReqVO.getCompanyIds();
  95 + List<Long> companyIds = updateReqVO.getCompanyIds();
96 96 // add by wq 20251116
97 97 List<AssignTasksInfoDO> assignTaskInfoList = assignTasksInfoMapper.selectList(AssignTasksInfoDO::getTaskId, updateObj.getId());
98 98 if (CollectionUtils.isEmpty(assignTaskInfoList)) {
... ... @@ -113,11 +113,11 @@ public class AssignTasksServiceImpl implements AssignTasksService {
113 113  
114 114  
115 115 //获取已添加单位集合
116   - List<String> existingCompanyIds = assignTaskInfoList.stream()
117   - .map(info -> String.valueOf(info.getCompanyId()))
  116 + List<Long> existingCompanyIds = assignTaskInfoList.stream()
  117 + .map(info -> info.getCompanyId())
118 118 .collect(Collectors.toList());
119 119 //排除 existingCompanyIds 中的元素 作为新增的单位
120   - List<String> filteredCompanyIds = companyIds.stream()
  120 + List<Long> filteredCompanyIds = companyIds.stream()
121 121 .filter(Objects::nonNull)
122 122 .filter(id -> !existingCompanyIds.contains(id)) // 直接用列表 contains()
123 123 .collect(Collectors.toList());
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/assigntasksinfo/AssignTasksInfoService.java
... ... @@ -70,7 +70,7 @@ public interface AssignTasksInfoService {
70 70 * @param assignTasks
71 71 * @Return java.lang.Long
72 72 */
73   - public void saveAssignTasksInfos(List<String> companyIds, AssignTasksDO assignTasks);
  73 + public void saveAssignTasksInfos(List<Long> companyIds, AssignTasksDO assignTasks);
74 74  
75 75 /**
76 76 * @Author wangqian
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/assigntasksinfo/AssignTasksInfoServiceImpl.java
... ... @@ -126,7 +126,7 @@ public class AssignTasksInfoServiceImpl implements AssignTasksInfoService {
126 126 }
127 127  
128 128 @Override
129   - public void saveAssignTasksInfos(List<String> companyIds, AssignTasksDO assignTasks) {
  129 + public void saveAssignTasksInfos(List<Long> companyIds, AssignTasksDO assignTasks) {
130 130 // 获得用户基本信息
131 131 if (companyIds != null && companyIds.size() > 0) {
132 132 //1、获取单位集合
... ... @@ -140,7 +140,7 @@ public class AssignTasksInfoServiceImpl implements AssignTasksInfoService {
140 140 dept -> dept.getName().trim(), // value 映射:取 companyName(去空格)
141 141 (oldValue, newValue) -> newValue
142 142 ));
143   - for (String companyId : companyIds) {
  143 + for (Long companyId : companyIds) {
144 144 AssignTasksInfoDO assignTaskInfo = new AssignTasksInfoDO();
145 145 assignTaskInfo.setCompanyId(companyId);
146 146 assignTaskInfo.setCompanyName(companyIdToNameMap.get(Long.valueOf(companyId)));
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/inspectionplan/InspectionPlanServiceImpl.java
... ... @@ -148,7 +148,12 @@ public class InspectionPlanServiceImpl implements InspectionPlanService {
148 148 String planAttrLabel = DictFrameworkUtils.parseDictDataLabel(PlanConstants.GARDEN_PLAN_ATTR_REDIS_KEY, createReqVO.getPlanAttr());
149 149 String planTypeIdLabel = DictFrameworkUtils.parseDictDataLabel(PlanConstants.INSPECTION_MAINTAIN_TYPE, createReqVO.getPlanTypeId());
150 150 String planNameSuffix = StringUtil.isNotEmpty(createReqVO.getPlanNameSuffix()) ? createReqVO.getPlanNameSuffix() : "";
151   - inspectionPlan.setPlanName(roadReqVO.getRoadName() + planAttrLabel + planTypeIdLabel + planNameSuffix);
  151 + String planName = roadReqVO.getRoadName() + planAttrLabel + planTypeIdLabel + planNameSuffix;
  152 + InspectionPlanDO existInspectionPlan = inspectionPlanMapper.selectOne(new QueryWrapper<InspectionPlanDO>().lambda().eq(InspectionPlanDO::getPlanName, planName));
  153 + if (existInspectionPlan != null) {
  154 + throw exception(PLAN_NAME_EXISTED, planName);
  155 + }
  156 + inspectionPlan.setPlanName(planName);
152 157 inspectionPlanList.add(inspectionPlan);
153 158 /*2.插入角色*/
154 159 createReqVO.getRoleIds().forEach(roleId -> {
... ... @@ -244,17 +249,18 @@ public class InspectionPlanServiceImpl implements InspectionPlanService {
244 249 .ge(InspectionPlanDO::getEndTime, req.getBeginTime()); // end_time >= startTime
245 250  
246 251 count = inspectionPlanMapper.selectCount(sql);
247   - } else {
248   - QueryWrapper<InspectionPlanDO> sql = new QueryWrapper<>();
249   - sql.lambda().eq(InspectionPlanDO::getPlanTypeId, req.getPlanTypeId())
250   - .in(InspectionPlanDO::getRoadId, roadIds)
251   - .eq(InspectionPlanDO::getDeleted, 0)
252   - .eq(InspectionPlanDO::getPlanAttr, 2) //临时计划
253   - .le(InspectionPlanDO::getBeginTime, req.getEndTime()) // start_time <= endTime
254   - .ge(InspectionPlanDO::getEndTime, req.getBeginTime()); // end_time >= startTime
255   -
256   - count = inspectionPlanMapper.selectCount(sql);
257 252 }
  253 +// else {
  254 +// QueryWrapper<InspectionPlanDO> sql = new QueryWrapper<>();
  255 +// sql.lambda().eq(InspectionPlanDO::getPlanTypeId, req.getPlanTypeId())
  256 +// .in(InspectionPlanDO::getRoadId, roadIds)
  257 +// .eq(InspectionPlanDO::getDeleted, 0)
  258 +// .eq(InspectionPlanDO::getPlanAttr, 2) //临时计划
  259 +// .le(InspectionPlanDO::getBeginTime, req.getEndTime()) // start_time <= endTime
  260 +// .ge(InspectionPlanDO::getEndTime, req.getBeginTime()); // end_time >= startTime
  261 +//
  262 +// count = inspectionPlanMapper.selectCount(sql);
  263 +// }
258 264  
259 265 if (count > 0) {
260 266 throw exception(INSPECTION_PLAN_EXISTS);
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/maintainplan/MaintainPlanServiceImpl.java
... ... @@ -124,7 +124,7 @@ public class MaintainPlanServiceImpl implements MaintainPlanService {
124 124 calculate.add(periodResult);
125 125 planNum = Integer.parseInt(createReqVO.getRateValue());
126 126 }else{
127   - calculate= TimeIntervalFrequencyUtil.calculate(createReqVO.getBeginTime().toString(), createReqVO.getEndTime().toString(), rateValue, createReqVO.getCycleId());
  127 + calculate= TimeIntervalFrequencyUtil.calculateNew(createReqVO.getBeginTime().toString(), createReqVO.getEndTime().toString(), rateValue, createReqVO.getCycleId());
128 128 if (CollectionUtils.isEmpty(calculate)) {
129 129 log.warn("获取两个时间之间间隔天数错误");
130 130 return CommonResult.error(INSPECTION_CYCLE_ERROR);
... ... @@ -158,9 +158,15 @@ public class MaintainPlanServiceImpl implements MaintainPlanService {
158 158 maintainPlan.setRoadName(roadReqVO.getRoadName());
159 159 //计划属性label
160 160 String planAttrLabel = DictFrameworkUtils.parseDictDataLabel(PlanConstants.GARDEN_PLAN_ATTR_REDIS_KEY, createReqVO.getPlanAttr());
161   - String planTypeIdLabel = DictFrameworkUtils.parseDictDataLabel(PlanConstants.INSPECTION_MAINTAIN_TYPE, createReqVO.getPlanTypeId());
  161 + String planTypeIdLabel = DictFrameworkUtils.parseDictDataLabel(PlanConstants.MAINTAIN_TYPE, createReqVO.getPlanTypeId());
162 162 String planNameSuffix = StringUtil.isNotEmpty(createReqVO.getPlanNameSuffix()) ? createReqVO.getPlanNameSuffix() : "";
163   - maintainPlan.setPlanName(roadReqVO.getRoadName() + planAttrLabel + planTypeIdLabel + planNameSuffix);
  163 + String planName = roadReqVO.getRoadName() + planAttrLabel + planTypeIdLabel + planNameSuffix;
  164 + MaintainPlanDO existMaintainPlan = maintainPlanMapper.selectOne(new QueryWrapper<MaintainPlanDO>().lambda().eq(MaintainPlanDO::getPlanName, planName));
  165 + if (existMaintainPlan != null) {
  166 + throw exception(PLAN_NAME_EXISTED, planName);
  167 + }
  168 +
  169 + maintainPlan.setPlanName(planName);
164 170 maintainPlanList.add(maintainPlan);
165 171 /*2.插入角色*/
166 172 createReqVO.getRoleIds().forEach(roleId -> {
... ... @@ -262,17 +268,18 @@ public class MaintainPlanServiceImpl implements MaintainPlanService {
262 268 .ge(MaintainPlanDO::getEndTime, req.getBeginTime()); // end_time >= startTime
263 269  
264 270 count = maintainPlanMapper.selectCount(sql);
265   - } else {
266   - QueryWrapper<MaintainPlanDO> sql = new QueryWrapper<>();
267   - sql.lambda().eq(MaintainPlanDO::getPlanTypeId, req.getPlanTypeId())
268   - .in(MaintainPlanDO::getRoadId, roadIds)
269   - .eq(MaintainPlanDO::getDeleted, 0)
270   - .eq(MaintainPlanDO::getPlanAttr, 2) //临时计划
271   - .le(MaintainPlanDO::getBeginTime, req.getEndTime()) // start_time <= endTime
272   - .ge(MaintainPlanDO::getEndTime, req.getBeginTime()); // end_time >= startTime
273   -
274   - count = maintainPlanMapper.selectCount(sql);
275 271 }
  272 +// else {
  273 +// QueryWrapper<MaintainPlanDO> sql = new QueryWrapper<>();
  274 +// sql.lambda().eq(MaintainPlanDO::getPlanTypeId, req.getPlanTypeId())
  275 +// .in(MaintainPlanDO::getRoadId, roadIds)
  276 +// .eq(MaintainPlanDO::getDeleted, 0)
  277 +// .eq(MaintainPlanDO::getPlanAttr, 2) //临时计划
  278 +// .le(MaintainPlanDO::getBeginTime, req.getEndTime()) // start_time <= endTime
  279 +// .ge(MaintainPlanDO::getEndTime, req.getBeginTime()); // end_time >= startTime
  280 +//
  281 +// count = maintainPlanMapper.selectCount(sql);
  282 +// }
276 283  
277 284 if (count > 0) {
278 285 throw exception(INSPECTION_PLAN_EXISTS);
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/util/StringValidateUtil.java
... ... @@ -3,13 +3,13 @@ package com.zteits.urbanops.module.garden.util;
3 3 import java.util.regex.Pattern;
4 4  
5 5 /**
6   - * 字符串校验工具:校验是否为1-20的整数或合法分数(如1/3)
  6 + * 字符串校验工具:校验是否为1-1000的整数或合法分数(如1/3)
7 7 */
8 8 public class StringValidateUtil {
9 9  
10   - // 正则表达式:匹配1-10的数字 或 分子/分母(分子、分母均为1-10的数字)
  10 + // 正则表达式:匹配1-1000的数字 或 分子/分母(分子、分母均为1-100的数字)
11 11 private static final Pattern PATTERN = Pattern.compile(
12   - "^(?:[1-9]|10)$|^(?:[1-9]|10)/(?:[1-9]|10)$"
  12 + "^(?:[1-9]|[1-9]\\d|1\\d{2}|1000)$|^(?:[1-9]|[1-9]\\d|100)/(?:[1-9]|[1-9]\\d|100)$"
13 13 );
14 14  
15 15 /**
... ... @@ -38,7 +38,7 @@ public class StringValidateUtil {
38 38 // 检查是否为纯数字
39 39 if (isNumber(input)) {
40 40 int num = Integer.parseInt(input);
41   - return num >= 1 && num <= 10;
  41 + return num >= 1 && num <= 1000;
42 42 }
43 43  
44 44 // 检查是否为分数格式
... ... @@ -52,7 +52,7 @@ public class StringValidateUtil {
52 52 return false;
53 53 }
54 54 int numerator = Integer.parseInt(parts[0]);
55   - if (numerator < 1 || numerator > 10) {
  55 + if (numerator < 1 || numerator > 100) {
56 56 return false;
57 57 }
58 58 // 校验分母
... ... @@ -60,7 +60,7 @@ public class StringValidateUtil {
60 60 return false;
61 61 }
62 62 int denominator = Integer.parseInt(parts[1]);
63   - return denominator >= 1 && denominator <= 10;
  63 + return denominator >= 1 && denominator <= 100;
64 64 }
65 65  
66 66 // 既不是数字也不是分数
... ... @@ -107,7 +107,7 @@ public class StringValidateUtil {
107 107 // 3. 转换为数字并校验范围
108 108 try {
109 109 int number = Integer.parseInt(str);
110   - return number >= 1 && number <= 10;
  110 + return number >= 1 && number <= 100;
111 111 } catch (NumberFormatException e) {
112 112 // 理论上不会走到这里(已通过正则校验),兜底处理
113 113 return false;
... ...
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/util/timeinterval/TimeIntervalFrequencyUtil.java
... ... @@ -2,6 +2,7 @@ package com.zteits.urbanops.module.garden.util.timeinterval;
2 2  
3 3 import java.time.LocalDate;
4 4 import java.time.format.DateTimeFormatter;
  5 +import java.time.temporal.ChronoUnit;
5 6 import java.util.ArrayList;
6 7 import java.util.Collections;
7 8 import java.util.List;
... ... @@ -38,6 +39,82 @@ public class TimeIntervalFrequencyUtil {
38 39 * @param cycleId 1:日/次;2:周/次;3:月/次;4:年/次;5:按次;6:季度;7:半年
39 40 * @return 划分结果列表
40 41 */
  42 + /**
  43 + * 计算时间段划分结果(基于固定天数换算)
  44 + *
  45 + * @param startStr 开始日期 (yyyy-MM-dd)
  46 + * @param endStr 结束日期 (yyyy-MM-dd)
  47 + * @param freq 频次值,格式 "x/y",其中 x 为每周期次数,y 为周期数量
  48 + * @param cycleId 周期类型:1:日/次;2:周/次;3:月/次;4:年/次;5:按次;6:季度;7:半年
  49 + * @return 时间段划分结果列表,包含每个时间段的开始日期、结束日期和执行次数
  50 + */
  51 + public static List<PeriodResult> calculateNew(String startStr, String endStr, String freq, Integer cycleId) {
  52 + // 解析日期参数
  53 + LocalDate startDate = LocalDate.parse(startStr, FORMATTER);
  54 + LocalDate endDate = LocalDate.parse(endStr, FORMATTER);
  55 +
  56 + // 边界条件:开始日期晚于结束日期时返回空列表
  57 + if (startDate.isAfter(endDate)) {
  58 + return Collections.emptyList();
  59 + }
  60 +
  61 + // 解析频次参数 (格式: "x/y")
  62 + String[] freqParts = freq.split("/", 2);
  63 + if (freqParts.length != 2) {
  64 + throw new IllegalArgumentException(String.format("频次值格式错误,应为 'x/y': %s", freq));
  65 + }
  66 + int timesPerPeriod = Integer.parseInt(freqParts[0]); // 每周期执行次数
  67 + int periodCount = Integer.parseInt(freqParts[1]); // 周期数量
  68 +
  69 + // 计算周期相关天数
  70 + long daysPerPeriod = convertToDaysNew(periodCount, cycleId); // 单个周期的天数
  71 + long totalPeriodDays = daysPerPeriod * periodCount; // 总周期天数
  72 +
  73 + List<PeriodResult> resultList = new ArrayList<>();
  74 + LocalDate segmentStart = startDate;
  75 +
  76 + // 循环划分时间段
  77 + while (!segmentStart.isAfter(endDate)) {
  78 + // 计算当前时间段的理论结束日期(segmentStart + totalPeriodDays - 1)
  79 + LocalDate segmentEnd = safePlusDays(segmentStart, totalPeriodDays - 1);
  80 +
  81 + // 如果理论结束日期超过总结束日期,则截断
  82 + if (segmentEnd.isAfter(endDate)) {
  83 + segmentEnd = endDate;
  84 + }
  85 +
  86 + // 计算当前时间段的实际天数(包含开始和结束日期)
  87 + long daysInSegment = ChronoUnit.DAYS.between(segmentStart, segmentEnd) + 1;
  88 +
  89 + // 计算当前时间段的执行次数:(实际天数/周期天数) * 每周期次数,向上取整
  90 + double proportion = (double) daysInSegment / daysPerPeriod;
  91 + int executionCount = (int) Math.ceil(proportion * timesPerPeriod);
  92 +
  93 + // 添加当前时间段结果
  94 + resultList.add(new PeriodResult(segmentStart, segmentEnd, executionCount));
  95 +
  96 + // 计算下一个时间段的开始日期(当前结束日期的次日)
  97 + LocalDate nextSegmentStart = segmentEnd.plusDays(1);
  98 +
  99 + // 如果下一个开始日期超过总结束日期,则退出循环
  100 + if (nextSegmentStart.isAfter(endDate)) {
  101 + break;
  102 + }
  103 +
  104 + segmentStart = nextSegmentStart;
  105 + }
  106 +
  107 + return resultList;
  108 + }
  109 + /**
  110 + * 计算时间段划分结果(基于固定天数换算)
  111 + *
  112 + * @param startStr 开始日期 (yyyy-MM-dd)
  113 + * @param endStr 结束日期 (yyyy-MM-dd)
  114 + * @param freq 频次值,格式 "x/y"
  115 + * @param cycleId 1:日/次;2:周/次;3:月/次;4:年/次;5:按次;6:季度;7:半年
  116 + * @return 划分结果列表
  117 + */
41 118 public static List<PeriodResult> calculate(String startStr, String endStr, String freq, Integer cycleId) {
42 119 LocalDate start = LocalDate.parse(startStr, FORMATTER);
43 120 LocalDate end = LocalDate.parse(endStr, FORMATTER);
... ... @@ -77,10 +154,45 @@ public class TimeIntervalFrequencyUtil {
77 154  
78 155 return results;
79 156 }
80   -
81 157 /**
82 158 * 将 y 个单位转换为固定天数
83   - * 1:日/次;2:周/次;3:月/次;4:年/次;5:按次;6:季度;7:半年
  159 + * TIME(0, "次"),
  160 + * DAY(1, "次/日"),
  161 + * WEEK(2, "次/周"),
  162 + * MONTH(3, "次/月"),
  163 + * QUARTER(4, "次/季"),
  164 + * SEMIANNUAL(5, "次/半年"),
  165 + * YEAR(6, "次/年");
  166 + */
  167 + private static long convertToDaysNew(int y, Integer cycleId) {
  168 + switch (cycleId) {
  169 + case 1: // DAY
  170 + return 1;
  171 + case 2: // WEEK
  172 + return (long) 7;
  173 + case 3: // MONTH
  174 + return (long) 30;
  175 + case 6: // YEAR
  176 + return (long) 365;
  177 + case 0: // TIME
  178 + return 9999; // 按次:将整个时间段视为1个周期
  179 + case 4: // QUARTER
  180 + return (long) 90; // 1季度=3个月=90天
  181 + case 5: // SEMIANNUAL
  182 + return (long) 180; // 半年=6个月=180天
  183 + default:
  184 + throw new IllegalArgumentException("无效的周期ID: " + cycleId);
  185 + }
  186 + }
  187 + /**
  188 + * 将 y 个单位转换为固定天数
  189 + * TIME(0, "次"),
  190 + * DAY(1, "次/日"),
  191 + * WEEK(2, "次/周"),
  192 + * MONTH(3, "次/月"),
  193 + * QUARTER(4, "次/季"),
  194 + * SEMIANNUAL(5, "次/半年"),
  195 + * YEAR(6, "次/年");
84 196 */
85 197 private static long convertToDays(int y, Integer cycleId) {
86 198 switch (cycleId) {
... ... @@ -90,13 +202,13 @@ public class TimeIntervalFrequencyUtil {
90 202 return (long) y * 7;
91 203 case 3: // MONTH
92 204 return (long) y * 30;
93   - case 4: // YEAR
  205 + case 6: // YEAR
94 206 return (long) y * 365;
95   - case 5: // TIME
  207 + case 0: // TIME
96 208 return 1; // 按次:将整个时间段视为1个周期
97   - case 6: // QUARTER
  209 + case 4: // QUARTER
98 210 return (long) y * 90; // 1季度=3个月=90天
99   - case 7: // SEMIANNUAL
  211 + case 5: // SEMIANNUAL
100 212 return (long) y * 180; // 半年=6个月=180天
101 213 default:
102 214 throw new IllegalArgumentException("无效的周期ID: " + cycleId);
... ... @@ -117,52 +229,56 @@ public class TimeIntervalFrequencyUtil {
117 229  
118 230 // ====================== 测试用例 ======================
119 231 public static void main(String[] args) {
120   - //1:日/次;2:周/次;3:月/次;4:年/次
121   - System.out.println("=== 示例1:每2天3次(即:3/2),按日 ===2025-12-01 2025-12-31");
122   - List<PeriodResult> r1 = calculate("2025-12-01", "2025-12-31", "3/2", 1);
123   - r1.forEach(System.out::println);
124   - // 输出:
125   - // 2025-01-01 2025-01-03 1次
126   - // 2025-01-04 2025-01-06 1次
127   - // 2025-01-07 2025-01-07 1次
128   - System.out.println("\n=== 示例2:每2周3次(即:3/2)(14天),按周 ===2025-12-01 2025-12-10");
129   - List<PeriodResult> r2 = calculate("2025-12-01", "2025-12-10", "3/2", 2);
  232 +
  233 + List<PeriodResult> r2 = calculateNew("2026-01-01", "2026-02-15", "7/1", 2);
130 234 r2.forEach(System.out::println);
131   - // 每2周 = 14天
132   - // 2025-01-01 ~ 2025-01-14
133   - // 2025-01-15 ~ 2025-01-28
134   - // 2025-01-29 ~ 2025-02-08(剩余11天)
135   - System.out.println("\n=== 示例3:每2个月4次(即:4/2)(30天),按月 === 2025-09-15 2025-12-31");
136   - List<PeriodResult> r3 = calculate("2025-09-15", "2025-12-31", "4/2", 3);
137   - r3.forEach(System.out::println);
138   - // 每1月 = 30天
139   - // 2025-01-01 ~ 2025-01-30
140   - // 2025-01-31 ~ 2025-02-28(30天?→ 实际是29天,但按30天算)
141   - // 2025-03-01 ~ 2025-03-15(不足)
142   -
143   - System.out.println("\n=== 示例4:每2年1次(即:1/2)(730天),按年 ===2025-01-01 2030-01-01");
144   - List<PeriodResult> r4 = calculate("2025-01-01", "2030-01-01", "1/2", 4);
145   - r4.forEach(System.out::println);
146   - // 每2年 = 730天
147   - // 2025-01-01 ~ 2025-12-26(+729d)
148   - // 2025-12-27 ~ 2027-12-21
149   - // 2027-12-22 ~ 2029-12-16
150   - // 2029-12-17 ~ 2030-01-01(最后一段)
151   - System.out.println("\n=== 示例5:每1年4次(即:4/1),按年(测试)=== 2023-09-15 2025-01-31");
152   - List<PeriodResult> r5 = calculate("2023-09-15", "2025-01-31", "4/1", 4);
153   - r5.forEach(System.out::println);
154   -
155   - // 新增示例:按次、季度、半年
156   - System.out.println("\n=== 示例6:按次单位,整个时间段算1个周期 === 2025-01-01 2025-12-31");
157   - List<PeriodResult> r6 = calculate("2025-01-01", "2025-12-31", "2/1", 5);
158   - r6.forEach(System.out::println);
159   -
160   - System.out.println("\n=== 示例7:每1季度2次(即:2/1),按季度(90天)=== 2025-01-01 2025-12-31");
161   - List<PeriodResult> r7 = calculate("2025-01-01", "2025-12-31", "2/1", 6);
162   - r7.forEach(System.out::println);
163   -
164   - System.out.println("\n=== 示例8:每1半年3次(即:3/1),按半年(180天)=== 2025-01-01 2025-12-31");
165   - List<PeriodResult> r8 = calculate("2025-01-01", "2025-12-31", "3/1", 7);
166   - r8.forEach(System.out::println);
  235 +
  236 +// //1:日/次;2:周/次;3:月/次;4:年/次
  237 +// System.out.println("=== 示例1:每2天3次(即:3/2),按日 ===2025-12-01 2025-12-31");
  238 +// List<PeriodResult> r1 = calculate("2025-12-01", "2025-12-31", "3/2", 1);
  239 +// r1.forEach(System.out::println);
  240 +// // 输出:
  241 +// // 2025-01-01 2025-01-03 1次
  242 +// // 2025-01-04 2025-01-06 1次
  243 +// // 2025-01-07 2025-01-07 1次
  244 +// System.out.println("\n=== 示例2:每2周3次(即:3/2)(14天),按周 ===2025-12-01 2025-12-10");
  245 +// List<PeriodResult> r2 = calculate("2025-12-01", "2025-12-10", "3/2", 2);
  246 +// r2.forEach(System.out::println);
  247 +// // 每2周 = 14天
  248 +// // 2025-01-01 ~ 2025-01-14
  249 +// // 2025-01-15 ~ 2025-01-28
  250 +// // 2025-01-29 ~ 2025-02-08(剩余11天)
  251 +// System.out.println("\n=== 示例3:每2个月4次(即:4/2)(30天),按月 === 2025-09-15 2025-12-31");
  252 +// List<PeriodResult> r3 = calculate("2025-09-15", "2025-12-31", "4/2", 3);
  253 +// r3.forEach(System.out::println);
  254 +// // 每1月 = 30天
  255 +// // 2025-01-01 ~ 2025-01-30
  256 +// // 2025-01-31 ~ 2025-02-28(30天?→ 实际是29天,但按30天算)
  257 +// // 2025-03-01 ~ 2025-03-15(不足)
  258 +//
  259 +// System.out.println("\n=== 示例4:每2年1次(即:1/2)(730天),按年 ===2025-01-01 2030-01-01");
  260 +// List<PeriodResult> r4 = calculate("2025-01-01", "2030-01-01", "1/2", 4);
  261 +// r4.forEach(System.out::println);
  262 +// // 每2年 = 730天
  263 +// // 2025-01-01 ~ 2025-12-26(+729d)
  264 +// // 2025-12-27 ~ 2027-12-21
  265 +// // 2027-12-22 ~ 2029-12-16
  266 +// // 2029-12-17 ~ 2030-01-01(最后一段)
  267 +// System.out.println("\n=== 示例5:每1年4次(即:4/1),按年(测试)=== 2023-09-15 2025-01-31");
  268 +// List<PeriodResult> r5 = calculate("2023-09-15", "2025-01-31", "4/1", 4);
  269 +// r5.forEach(System.out::println);
  270 +//
  271 +// // 新增示例:按次、季度、半年
  272 +// System.out.println("\n=== 示例6:按次单位,整个时间段算1个周期 === 2025-01-01 2025-12-31");
  273 +// List<PeriodResult> r6 = calculate("2025-01-01", "2025-12-31", "2/1", 5);
  274 +// r6.forEach(System.out::println);
  275 +//
  276 +// System.out.println("\n=== 示例7:每1季度2次(即:2/1),按季度(90天)=== 2025-01-01 2025-12-31");
  277 +// List<PeriodResult> r7 = calculate("2025-01-01", "2025-12-31", "2/1", 6);
  278 +// r7.forEach(System.out::println);
  279 +//
  280 +// System.out.println("\n=== 示例8:每1半年3次(即:3/1),按半年(180天)=== 2025-01-01 2025-12-31");
  281 +// List<PeriodResult> r8 = calculate("2025-01-01", "2025-12-31", "3/1", 7);
  282 +// r8.forEach(System.out::println);
167 283 }
168 284 }
... ...
urbanops-module-garden/src/main/resources/mapper/inspectionplan/InspectionPlanCommitMapper.xml
... ... @@ -85,7 +85,12 @@
85 85 <if test="req.remark != null and req.remark !=''">
86 86 AND a.remark LIKE CONCAT('%', #{req.remark} ,'%')
87 87 </if>
88   -
  88 + <if test="req.createTimeStart != null">
  89 + <![CDATA[AND DATE_FORMAT(a.create_time, '%Y-%m-%d') >= #{req.createTimeStart}]]>
  90 + </if>
  91 + <if test="req.createTimeEnd != null">
  92 + <![CDATA[AND DATE_FORMAT(a.create_time, '%Y-%m-%d') <= #{req.createTimeEnd}]]>
  93 + </if>
89 94 order by a.id desc
90 95 </select>
91 96  
... ... @@ -133,4 +138,4 @@
133 138 </foreach>
134 139 </if>
135 140 </select>
136   -</mapper>
137 141 \ No newline at end of file
  142 +</mapper>
... ...
urbanops-module-garden/src/main/resources/mapper/inspectionplan/InspectionPlanMapper.xml
... ... @@ -24,8 +24,10 @@
24 24 a.finish_state,
25 25 a.begin_time,
26 26 a.end_time
27   - FROM
28   - garden_inspection_plan a
  27 + FROM garden_inspection_plan a JOIN -- 建议用显式JOIN代替隐式连接,可读性更高
  28 + garden_inspection_plan_detail b ON
  29 + a.batch_no = b.batch_no
  30 + AND a.deleted = b.deleted
29 31 WHERE a.deleted = 0
30 32 <if test="req.roadName != null and req.roadName !=''">
31 33 AND a.road_name LIKE CONCAT('%',#{req.roadName},'%')
... ... @@ -44,14 +46,17 @@
44 46 </if>
45 47 <!--状态 1:未完成;2:已完成;3:已失效-->
46 48 <if test="req.finishState == 3">
  49 + and b.finish_state = #{req.finishState}
47 50 <![CDATA[and a.end_time < #{req.localDate}]]>
48 51 </if>
49 52 <if test="req.finishState == 2">
50   - and a.finish_state = #{req.finishState}
  53 + and b.finish_state = #{req.finishState}
51 54 </if>
52 55 <if test="req.finishState == 1">
53   - and a.finish_state = #{req.finishState}
  56 + and b.finish_state = #{req.finishState}
54 57 <![CDATA[and a.end_time >= #{req.localDate}]]>
  58 + <![CDATA[and b.end_time >= #{req.localDate}]]>
  59 + <![CDATA[and b.begin_time <= #{req.localDate}]]>
55 60 </if>
56 61 </select>
57   -</mapper>
58 62 \ No newline at end of file
  63 +</mapper>
... ...
urbanops-module-garden/src/main/resources/mapper/maintainplan/MaintainPlanCommitMapper.xml
... ... @@ -76,6 +76,12 @@
76 76 <if test="req.finishTime != null">
77 77 AND DATE_FORMAT(c.finish_time, '%Y-%m-%d') = #{req.finishTime}
78 78 </if>
  79 + <if test="req.createTimeStart != null">
  80 + <![CDATA[AND DATE_FORMAT(a.create_time, '%Y-%m-%d') >= #{req.createTimeStart}]]>
  81 + </if>
  82 + <if test="req.createTimeEnd != null">
  83 + <![CDATA[AND DATE_FORMAT(a.create_time, '%Y-%m-%d') <= #{req.createTimeEnd}]]>
  84 + </if>
79 85 </select>
80 86  
81 87 <select id="appMaintainPlanCommitDetailPage" resultType="com.zteits.urbanops.module.garden.controller.app.maintainplan.vo.AppMaintainPlanCommitDetailPageRespVO">
... ...
urbanops-module-garden/src/main/resources/mapper/maintainplan/MaintainPlanDetailMapper.xml
... ... @@ -59,6 +59,8 @@
59 59 <if test="req.finishState == 1">
60 60 and c.finish_state = #{req.finishState}
61 61 <![CDATA[and c.end_time >= #{req.localDateTime}]]>
  62 + <![CDATA[and c.begin_time <= #{req.localDateTime}]]>
  63 +
62 64 </if>
63 65 </select>
64 66  
... ...
urbanops-module-garden/src/main/resources/mapper/maintainplan/MaintainPlanMapper.xml
... ... @@ -26,8 +26,12 @@
26 26 a.end_time
27 27 FROM
28 28 garden_maintain_plan a
29   - WHERE a.deleted=0
30   - <if test="req.roadName != null and req.roadName !=''">
  29 + JOIN -- 建议用显式JOIN代替隐式连接,可读性更高
  30 + garden_maintain_plan_detail b ON
  31 + a.batch_no = b.batch_no
  32 + AND a.deleted = b.deleted
  33 + WHERE a.deleted = 0
  34 + <if test="req.roadName != null and req.roadName !=''">
31 35 AND a.road_name LIKE CONCAT('%',#{req.roadName},'%')
32 36 </if>
33 37 <if test="req.batchNos != null and req.batchNos.size() > 0">
... ... @@ -44,15 +48,17 @@
44 48 </if>
45 49 <!--状态 1:未完成;2:已完成;3:已失效-->
46 50 <if test="req.finishState == 3">
47   - and a.finish_state = #{req.finishState}
  51 + and b.finish_state = #{req.finishState}
48 52 <![CDATA[and a.end_time < #{req.localDate}]]>
49 53 </if>
50 54 <if test="req.finishState == 2">
51   - and a.finish_state = #{req.finishState}
  55 + and b.finish_state = #{req.finishState}
52 56 </if>
53 57 <if test="req.finishState == 1">
54   - and a.finish_state = #{req.finishState}
  58 + and b.finish_state = #{req.finishState}
55 59 <![CDATA[and a.end_time >= #{req.localDate}]]>
  60 + <![CDATA[and b.end_time >= #{req.localDate}]]>
  61 + <![CDATA[and b.begin_time <= #{req.localDate}]]>
56 62 </if>
57 63 </select>
58 64  
... ... @@ -103,6 +109,8 @@
103 109 <if test="req.finishState == 1">
104 110 and c.finish_state = #{req.finishState}
105 111 <![CDATA[and c.end_time >= #{req.localDateTime}]]>
  112 + <![CDATA[and c.begin_time <= #{req.localDateTime}]]>
  113 +
106 114 </if>
107 115 </select>
108 116  
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/controller/admin/attachment/AttachmentController.java
... ... @@ -101,4 +101,11 @@ public class AttachmentController {
101 101 BeanUtils.toBean(list, AttachmentRespVO.class));
102 102 }
103 103  
104   -}
105 104 \ No newline at end of file
  105 + @PostMapping("/getByCondition")
  106 + @Operation(summary = "获得工单附件信息")
  107 + @PreAuthorize("@ss.hasPermission('workorder:attachment:query')")
  108 + public CommonResult<List<AttachmentRespVO>> getAttachmentByCondition(@Valid @RequestBody AttachmentReqVO reqVO) {
  109 + List<AttachmentDO> attachment = attachmentService.getAttachmentByCondition(reqVO);
  110 + return success(BeanUtils.toBean(attachment, AttachmentRespVO.class));
  111 + }
  112 +}
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/controller/admin/attachment/vo/AttachmentPageReqVO.java
... ... @@ -19,7 +19,7 @@ public class AttachmentPageReqVO extends PageParam {
19 19 @Schema(description = "业务线:yl 园林,wy 物业,sz 市政 ")
20 20 private String busiLine;
21 21  
22   - @Schema(description = "业务类型:01 问题图片,02 街道图片,03 选景图片", example = "1")
  22 + @Schema(description = "业务类型:01 问题图片,02 进行中图片,03 已完成图片", example = "01")
23 23 private String busiType;
24 24  
25 25 @Schema(description = "文件名称")
... ... @@ -41,4 +41,4 @@ public class AttachmentPageReqVO extends PageParam {
41 41 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
42 42 private LocalDateTime[] createTime;
43 43  
44   -}
45 44 \ No newline at end of file
  45 +}
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/controller/admin/attachment/vo/AttachmentReqVO.java 0 → 100644
  1 +package com.zteits.urbanops.module.workorder.controller.admin.attachment.vo;
  2 +
  3 +import com.zteits.urbanops.framework.common.pojo.PageParam;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import lombok.Data;
  6 +import org.springframework.format.annotation.DateTimeFormat;
  7 +
  8 +import java.time.LocalDateTime;
  9 +
  10 +import static com.zteits.urbanops.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  11 +
  12 +@Schema(description = "管理后台 - 工单附件信息分页 Request VO")
  13 +@Data
  14 +public class AttachmentReqVO extends PageParam {
  15 +
  16 + @Schema(description = "工单号")
  17 + private String orderNo;
  18 +
  19 + @Schema(description = "业务线:yl 园林,wy 物业,sz 市政 ")
  20 + private String busiLine;
  21 +
  22 + @Schema(description = "业务类型:01 问题图片,02 进行中图片,03 已完成图片", example = "01")
  23 + private String busiType;
  24 +
  25 +}
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/controller/admin/maininfo/vo/MainInfoHasTaskPageReqVO.java 0 → 100644
  1 +package com.zteits.urbanops.module.workorder.controller.admin.maininfo.vo;
  2 +
  3 +import com.zteits.urbanops.framework.common.pojo.PageParam;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import jakarta.validation.constraints.NotNull;
  6 +import lombok.Data;
  7 +import org.springframework.format.annotation.DateTimeFormat;
  8 +
  9 +import java.time.LocalDateTime;
  10 +
  11 +import static com.zteits.urbanops.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  12 +
  13 +/**
  14 + * 类描述:工单工作流分页请求 reqVO
  15 + * 创建人:yanhuiqing
  16 + * 创建时间:2025/12/15 21:41
  17 + * 修改人:yanhuiqing
  18 + * 修改时间:2025/12/15 21:41
  19 + * 修改备注:
  20 + *
  21 + * @author yanhuiqing
  22 + * @version 1.0
  23 + */
  24 +@Schema(description = "管理后台 - 工单工作流信息分页 Request VO")
  25 +@Data
  26 +public class MainInfoHasTaskPageReqVO extends PageParam {
  27 + @NotNull
  28 + @Schema(description = "任务指派人", example = "admin")
  29 + private Long userId;
  30 + @Schema(description = "流程定义key", example = "quik_local_test")
  31 + private String key;
  32 + @Schema(description = "开始时间")
  33 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  34 + private LocalDateTime[] startTime;
  35 + @Schema(description = "结束时间")
  36 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  37 + private LocalDateTime[] endTime;
  38 + @Schema(description = "业务线:yl 园林,wy 物业,sz 市政 ")
  39 + private String busiLine;
  40 + @Schema(description = "工单号")
  41 + private String orderNo;
  42 + @Schema(description = "工单名称", example = "张三")
  43 + private String orderName;
  44 + @Schema(description = "工单描述", example = "你说的对")
  45 + private String remark;
  46 + @Schema(description = "道路名称", example = "王五")
  47 + private String roadName;
  48 + @Schema(description = "街道名称", example = "芋艿")
  49 + private String streetName;
  50 + @Schema(description = "养护级别ID", example = "1")
  51 + private Integer curingLevelId;
  52 +}
0 53 \ No newline at end of file
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/controller/admin/materialdetail/MaterialDetailController.java
... ... @@ -101,4 +101,17 @@ public class MaterialDetailController {
101 101 BeanUtils.toBean(list, MaterialDetailRespVO.class));
102 102 }
103 103  
104   -}
105 104 \ No newline at end of file
  105 + /**
  106 + * 批量创建物料明细
  107 + * @param materialDetailSaveReqVOs 物料明细保存请求列表
  108 + * @return 统一响应结果
  109 + */
  110 + @PostMapping("/batch-create")
  111 + @Operation(summary = "批量创建工单耗材明细")
  112 + @PreAuthorize("@ss.hasPermission('workorder:material-detail:create')")
  113 + public CommonResult<Boolean> batchCreateMaterialDetail(
  114 + @RequestBody @Valid List<MaterialDetailSaveReqVO> materialDetailSaveReqVOs) {
  115 + return success(materialDetailService.batchCreateMaterialDetail(materialDetailSaveReqVOs));
  116 + }
  117 +
  118 +}
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/controller/admin/materialdetail/vo/MaterialDetailSaveReqVO.java
... ... @@ -16,14 +16,6 @@ public class MaterialDetailSaveReqVO {
16 16 @NotEmpty(message = "工单号不能为空")
17 17 private String orderNo;
18 18  
19   - @Schema(description = "提交用户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10300")
20   - @NotNull(message = "提交用户ID不能为空")
21   - private Long userId;
22   -
23   - @Schema(description = "提交用户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
24   - @NotEmpty(message = "提交用户名称不能为空")
25   - private String userName;
26   -
27 19 @Schema(description = "种类ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "27821")
28 20 @NotNull(message = "种类ID不能为空")
29 21 private Long classifyId;
... ... @@ -60,7 +52,17 @@ public class MaterialDetailSaveReqVO {
60 52 private String status;
61 53  
62 54 @Schema(description = "描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对")
63   - @NotEmpty(message = "描述不能为空")
64 55 private String remark;
65 56  
66   -}
67 57 \ No newline at end of file
  58 + /*耗材ID*/
  59 + @Schema(description = "耗材ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "111")
  60 + @NotNull(message = "物料ID不能为空")
  61 + private Long materialId;
  62 +
  63 + /**
  64 + * 耗材名称
  65 + */
  66 + @Schema(description = "耗材名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "耗材名称")
  67 + @NotEmpty(message = "耗材名称不能为空")
  68 + private String materialName;
  69 +}
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/controller/app/garden/AppGardenWorkOrderController.java
... ... @@ -104,7 +104,7 @@ public class AppGardenWorkOrderController {
104 104 }
105 105  
106 106 @PutMapping("/return")
107   - @Operation(summary = "退回任务", description = "用于【流程详情】的【退回】按钮")
  107 + @Operation(summary = " app - 退回任务", description = "用于【流程详情】的【退回】按钮")
108 108 //@PreAuthorize("@ss.hasPermission('bpm:garden-workorder:update')")
109 109 public CommonResult<Boolean> returnTask(@Valid @RequestBody AppGardenTaskReturnReqVO reqVO) {
110 110 gardenService.returnTask(reqVO);
... ... @@ -112,7 +112,7 @@ public class AppGardenWorkOrderController {
112 112 }
113 113  
114 114 @PutMapping("/withdraw")
115   - @Operation(summary = "撤回任务")
  115 + @Operation(summary = "app - 撤回任务")
116 116 //@PreAuthorize("@ss.hasPermission('bpm:garden-workorder:update')")
117 117 public CommonResult<Boolean> withdrawTask(@RequestParam("taskId") String taskId) {
118 118 gardenService.withdrawTask(taskId);
... ... @@ -120,7 +120,7 @@ public class AppGardenWorkOrderController {
120 120 }
121 121  
122 122 @PutMapping("/delegate")
123   - @Operation(summary = "委派任务", description = "用于【流程详情】的【委派】按钮")
  123 + @Operation(summary = "app - 委派任务", description = "用于【流程详情】的【委派】按钮")
124 124 //@PreAuthorize("@ss.hasPermission('bpm:garden-workorder:update')")
125 125 public CommonResult<Boolean> delegateTask(@Valid @RequestBody AppGardenTaskDelegateReqVO reqVO) {
126 126 gardenService.delegateTask(reqVO);
... ... @@ -128,7 +128,7 @@ public class AppGardenWorkOrderController {
128 128 }
129 129  
130 130 @PutMapping("/transfer")
131   - @Operation(summary = "转派任务", description = "用于【流程详情】的【转派】按钮")
  131 + @Operation(summary = "app - 转派任务", description = "用于【流程详情】的【转派】按钮")
132 132 //@PreAuthorize("@ss.hasPermission('bpm:garden-workorder:update')")
133 133 public CommonResult<Boolean> transferTask(@Valid @RequestBody AppGardenTaskTransferReqVO reqVO) {
134 134 gardenService.transferTask(reqVO);
... ... @@ -149,4 +149,19 @@ public class AppGardenWorkOrderController {
149 149 PageResult<AppGardenTaskRespVO> pageResult = gardenService.getTaskTodoPage(pageVO);
150 150 return success(pageResult);
151 151 }
  152 +
  153 + @GetMapping("doneBuzSimplePage")
  154 + @Operation(summary = "app - 获取工单业务已办任务分页")
  155 + //@PreAuthorize("@ss.hasPermission('bpm:garden-workorder:query')")
  156 + public CommonResult<PageResult<AppGardenWorkOrderRespVO>> getTaskDoneBuzSimplePage(@Valid AppGardenWorkOrderPageReqVO pageVO) {
  157 + PageResult<AppGardenWorkOrderRespVO> pageResult = gardenService.getTaskDoneBuzSimplePage(pageVO);
  158 + return success(pageResult);
  159 + }
  160 + @GetMapping("todoBuzSimplePage")
  161 + @Operation(summary = "app - 获取工单业务待办任务分页")
  162 + //@PreAuthorize("@ss.hasPermission('bpm:garden-workorder:query')")
  163 + public CommonResult<PageResult<AppGardenWorkOrderRespVO>> getTaskTodoBuzSimplePage(@Valid AppGardenWorkOrderPageReqVO pageVO) {
  164 + PageResult<AppGardenWorkOrderRespVO> pageResult = gardenService.getTaskTodoBuzSimplePage(pageVO);
  165 + return success(pageResult);
  166 + }
152 167 }
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/controller/app/garden/vo/AppGardenWorkOrderRespVO.java
... ... @@ -4,6 +4,7 @@ import com.zteits.urbanops.module.workorder.controller.admin.maininfo.vo.MainInf
4 4 import io.swagger.v3.oas.annotations.media.Schema;
5 5 import lombok.Data;
6 6  
  7 +import java.time.LocalDateTime;
7 8 import java.util.List;
8 9  
9 10 /**
... ... @@ -21,4 +22,22 @@ public class AppGardenWorkOrderRespVO extends MainInfoRespVO {
21 22  
22 23 @Schema(description = "处理完成照片", example = "9184")
23 24 private List<String> completeImgsList;
  25 +
  26 + @Schema(description = "任务id")
  27 + private String taskId;
  28 +
  29 + @Schema(description = "任务名称")
  30 + private String taskName;
  31 +
  32 + @Schema(description = "流程定义名称")
  33 + private String processDefinitionName;
  34 +
  35 + @Schema(description = "任务开始时间")
  36 + private LocalDateTime startTime;
  37 +
  38 + @Schema(description = "任务结束时间")
  39 + private LocalDateTime endTime;
  40 +
  41 + @Schema(description = "流程定义key")
  42 + private String key_;
24 43 }
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/convert/garden/AppGardenTaskConvert.java
1 1 package com.zteits.urbanops.module.workorder.convert.garden;
2 2  
  3 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
3 4 import com.zteits.urbanops.framework.common.pojo.PageResult;
4 5 import com.zteits.urbanops.framework.common.util.collection.CollectionUtils;
5 6 import com.zteits.urbanops.framework.common.util.date.DateUtils;
... ... @@ -11,7 +12,12 @@ import com.zteits.urbanops.module.bpm.dal.dataobject.definition.BpmProcessDefini
11 12 import com.zteits.urbanops.module.bpm.framework.flowable.core.util.FlowableUtils;
12 13 import com.zteits.urbanops.module.system.api.dept.dto.DeptRespDTO;
13 14 import com.zteits.urbanops.module.system.api.user.dto.AdminUserRespDTO;
  15 +import com.zteits.urbanops.module.workorder.api.constant.BpmCommonConstant;
  16 +import com.zteits.urbanops.module.workorder.controller.app.garden.vo.AppGardenWorkOrderRespVO;
14 17 import com.zteits.urbanops.module.workorder.controller.app.garden.vo.task.AppGardenTaskRespVO;
  18 +import com.zteits.urbanops.module.workorder.dal.dataobject.attachment.AttachmentDO;
  19 +import com.zteits.urbanops.module.workorder.dal.dataobject.maininfo.MainInfoExtDO;
  20 +import com.zteits.urbanops.module.workorder.dal.mysql.attachment.AttachmentMapper;
15 21 import org.flowable.engine.history.HistoricProcessInstance;
16 22 import org.flowable.engine.runtime.ProcessInstance;
17 23 import org.flowable.task.api.Task;
... ... @@ -19,8 +25,11 @@ import org.flowable.task.api.history.HistoricTaskInstance;
19 25 import org.mapstruct.Mapper;
20 26 import org.mapstruct.factory.Mappers;
21 27  
  28 +import java.util.Arrays;
  29 +import java.util.Collections;
22 30 import java.util.List;
23 31 import java.util.Map;
  32 +import java.util.stream.Collectors;
24 33  
25 34 import static com.zteits.urbanops.framework.common.util.collection.MapUtils.findAndThen;
26 35  
... ... @@ -88,4 +97,80 @@ public interface AppGardenTaskConvert {
88 97 return new PageResult<>(taskVOList, pageResult.getTotal());
89 98 }
90 99  
  100 + default PageResult<AppGardenWorkOrderRespVO> buildBuziTaskPage(PageResult<MainInfoExtDO> pageResult, AttachmentMapper attachmentMapper){
  101 + // 1. 源分页对象为空,返回空分页
  102 + if (pageResult == null) {
  103 + return PageResult.empty();
  104 + }
  105 +
  106 + // 2. 转换列表数据,保留分页参数(总数、页码、页大小等)
  107 + List<AppGardenWorkOrderRespVO> targetList = convertList(pageResult.getList(), attachmentMapper);
  108 + return new PageResult<>(targetList, pageResult.getTotal());
  109 + }
  110 +
  111 + default List<AppGardenWorkOrderRespVO> convertList(List<MainInfoExtDO> sourceList, AttachmentMapper attachmentMapper) {
  112 + // 1. 源列表为空,返回空列表(避免NPE)
  113 + if (sourceList == null || sourceList.isEmpty()) {
  114 + return Collections.emptyList();
  115 + }
  116 +
  117 + // 2. 遍历源列表,调用单对象转换方法
  118 + return sourceList.stream()
  119 + .map(source -> convert(source, attachmentMapper))
  120 + .collect(Collectors.toList());
  121 + }
  122 +
  123 + /**
  124 + * MainInfoExtDO → AppGardenWorkOrderRespVO
  125 + * @param source 源对象
  126 + * @param attachmentMapper 附件Mapper,用于查询图片列表
  127 + * @return 目标对象
  128 + */
  129 + default AppGardenWorkOrderRespVO convert(MainInfoExtDO source, AttachmentMapper attachmentMapper) {
  130 + // 1. 源对象为空,直接返回null
  131 + if (source == null) {
  132 + return null;
  133 + }
  134 +
  135 + AppGardenWorkOrderRespVO target = new AppGardenWorkOrderRespVO();
  136 + org.springframework.beans.BeanUtils.copyProperties(source, target);
  137 +
  138 + // 3. 手动赋值扩展字段:查询问题图片列表和完成图片列表
  139 + List<String> problemImgsList = queryAttachment(
  140 + source.getBusiLine(),
  141 + BpmCommonConstant.PROBLEM_IMG_GROUP,
  142 + source.getOrderNo(),
  143 + attachmentMapper
  144 + );
  145 + List<String> completeImgsList = queryAttachment(
  146 + source.getBusiLine(),
  147 + BpmCommonConstant.RESULT_IMG_GROUP,
  148 + source.getOrderNo(),
  149 + attachmentMapper
  150 + );
  151 + target.setProblemImgsList(problemImgsList);
  152 + target.setCompleteImgsList(completeImgsList);
  153 +
  154 + return target;
  155 + }
  156 +
  157 + default List<String> queryAttachment(String busiLine, String busiType, String orderNo, AttachmentMapper attachmentMapper) {
  158 +
  159 + LambdaQueryWrapper<AttachmentDO> queryWrapper = new LambdaQueryWrapper<AttachmentDO>()
  160 + .eq(AttachmentDO::getBusiLine, busiLine)
  161 + .eq(AttachmentDO::getBusiType, busiType)
  162 + .eq(AttachmentDO::getOrderNo, orderNo);
  163 + List<AttachmentDO> attachments = attachmentMapper.selectList(queryWrapper);
  164 + if (attachments == null || attachments.isEmpty()) {
  165 + return List.of();
  166 + }
  167 + return attachments.stream()
  168 + .map(AttachmentDO::getFileNames)
  169 + .filter(s -> s != null && !s.isEmpty())
  170 + .flatMap(s -> Arrays.stream(s.split(",")).map(String::trim))
  171 + .filter(s -> !s.isEmpty())
  172 + .distinct()
  173 + .collect(Collectors.toList());
  174 + }
  175 +
91 176 }
92 177 \ No newline at end of file
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/dal/dataobject/attachment/AttachmentDO.java
... ... @@ -32,11 +32,11 @@ public class AttachmentDO extends BaseDO {
32 32 */
33 33 private String orderNo;
34 34 /**
35   - * 业务线:yl 园林,wy 物业,sz 市政
  35 + * 业务线:yl 园林,wy 物业,sz 市政
36 36 */
37 37 private String busiLine;
38 38 /**
39   - * 业务类型:01 问题图片,02 街道图片,03 选景图片
  39 + * 业务类型:01 问题图片,02 进行中图片,03 已完成图片
40 40 */
41 41 private String busiType;
42 42 /**
... ... @@ -61,4 +61,4 @@ public class AttachmentDO extends BaseDO {
61 61 private String remark;
62 62  
63 63  
64   -}
65 64 \ No newline at end of file
  65 +}
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/dal/dataobject/maininfo/MainInfoExtDO.java 0 → 100644
  1 +package com.zteits.urbanops.module.workorder.dal.dataobject.maininfo;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.KeySequence;
  4 +import com.baomidou.mybatisplus.annotation.TableName;
  5 +import com.zteits.urbanops.framework.mybatis.core.dataobject.BaseDO;
  6 +import lombok.*;
  7 +
  8 +import java.math.BigDecimal;
  9 +import java.time.LocalDateTime;
  10 +
  11 +/**
  12 + * 类描述:工单扩展信息,支持工作流任务信息 DO
  13 + * 创建人:yanhuiqing
  14 + * 创建时间:2025/12/15 17:37
  15 + * 修改人:yanhuiqing
  16 + * 修改时间:2025/12/15 17:37
  17 + * 修改备注:
  18 + *
  19 + * @author yanhuiqing
  20 + * @version 1.0
  21 + */
  22 +
  23 +@Data
  24 +@EqualsAndHashCode(callSuper = true)
  25 +@ToString(callSuper = true)
  26 +@Builder
  27 +@NoArgsConstructor
  28 +@AllArgsConstructor
  29 +public class MainInfoExtDO extends BaseDO {
  30 +
  31 + /**
  32 + * ID
  33 + */
  34 + private Long id;
  35 + /**
  36 + * 业务线:yl 园林,wy 物业,sz 市政
  37 + */
  38 + private String busiLine;
  39 + /**
  40 + * 工单号
  41 + */
  42 + private String orderNo;
  43 + /**
  44 + * 工单名称
  45 + */
  46 + private String orderName;
  47 + /**
  48 + * 来源ID
  49 + */
  50 + private Integer sourceId;
  51 + /**
  52 + * 来源名称
  53 + */
  54 + private String sourceName;
  55 + /**
  56 + * 道路ID
  57 + */
  58 + private Long roadId;
  59 + /**
  60 + * 道路名称
  61 + */
  62 + private String roadName;
  63 + /**
  64 + * 街道ID
  65 + */
  66 + private String streetId;
  67 + /**
  68 + * 街道名称
  69 + */
  70 + private String streetName;
  71 + /**
  72 + * 养护级别ID
  73 + */
  74 + private Integer curingLevelId;
  75 + /**
  76 + * 养护级别
  77 + */
  78 + private String curingLevelName;
  79 + /**
  80 + * 提交日期
  81 + */
  82 + private LocalDateTime commitDate;
  83 +
  84 + /**
  85 + * 完成时间
  86 + */
  87 + private LocalDateTime finishDate;
  88 + /**
  89 + * 紧急程度:1:特急;2:紧急;3:一般
  90 + */
  91 + private Integer pressingType;
  92 + /**
  93 + * 提交用户ID
  94 + */
  95 + private Long userId;
  96 + /**
  97 + * 提交用户名称
  98 + */
  99 + private String userName;
  100 + /**
  101 + * 部门id
  102 + */
  103 + private Long companyId;
  104 + /**
  105 + * 经纬度类型: 1:国标; 2:百度;3:高德;4:腾讯
  106 + */
  107 + private Integer latLonType;
  108 + /**
  109 + * 经度
  110 + */
  111 + private BigDecimal lat;
  112 + /**
  113 + * 维度
  114 + */
  115 + private BigDecimal lon;
  116 + /**
  117 + * 经纬度地址
  118 + */
  119 + private String lonLatAddress;
  120 + /**
  121 + * 三方工单ID
  122 + */
  123 + private String thirdWorkNo;
  124 + /**
  125 + * 三方工单结果上报状态:1:待推送;2:推送成功;3:推送失败
  126 + */
  127 + private Integer thirdPushState;
  128 + /**
  129 + * 业务状态
  130 + */
  131 + private String buzStatus;
  132 + /**
  133 + * 审批状态
  134 + */
  135 + private Integer status;
  136 + /**
  137 + * 流程实例的编号
  138 + */
  139 + private String processInstanceId;
  140 + /**
  141 + * 工单描述
  142 + */
  143 + private String remark;
  144 + /**
  145 + * 工单完成结果描述
  146 + */
  147 + private String handleResult;
  148 + /**
  149 + * 任务id
  150 + */
  151 + private String taskId;
  152 + /**
  153 + * 任务名称
  154 + */
  155 + private String taskName;
  156 + /**
  157 + * 流程定义名称
  158 + */
  159 + private String processDefinitionName;
  160 + /**
  161 + * 任务开始时间
  162 + */
  163 + private LocalDateTime startTime;
  164 + /**
  165 + * 任务结束时间
  166 + */
  167 + private LocalDateTime endTime;
  168 + /**
  169 + * 流程定义key
  170 + */
  171 + private String key_;
  172 +
  173 +
  174 +}
0 175 \ No newline at end of file
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/dal/dataobject/materialdetail/MaterialDetailDO.java
... ... @@ -66,7 +66,7 @@ public class MaterialDetailDO extends BaseDO {
66 66 /**
67 67 * 使用数量
68 68 */
69   - private Double userCount;
  69 + private Long userCount;
70 70 /**
71 71 * 单位
72 72 */
... ... @@ -80,5 +80,11 @@ public class MaterialDetailDO extends BaseDO {
80 80 */
81 81 private String remark;
82 82  
  83 + /*耗材ID*/
  84 + private Long materialId;
83 85  
84   -}
85 86 \ No newline at end of file
  87 + /**
  88 + * 耗材名称
  89 + */
  90 + private String materialName;
  91 +}
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/dal/mysql/maininfo/MainInfoExtMapper.java 0 → 100644
  1 +package com.zteits.urbanops.module.workorder.dal.mysql.maininfo;
  2 +
  3 +import com.baomidou.mybatisplus.core.conditions.Wrapper;
  4 +import com.baomidou.mybatisplus.core.metadata.IPage;
  5 +import com.zteits.urbanops.framework.common.pojo.PageParam;
  6 +import com.zteits.urbanops.framework.common.pojo.PageResult;
  7 +import com.zteits.urbanops.framework.mybatis.core.mapper.BaseMapperX;
  8 +import com.zteits.urbanops.framework.mybatis.core.util.MyBatisUtils;
  9 +import com.zteits.urbanops.module.workorder.controller.admin.maininfo.vo.MainInfoHasTaskPageReqVO;
  10 +import com.zteits.urbanops.module.workorder.controller.admin.maininfo.vo.MainInfoPageReqVO;
  11 +import com.zteits.urbanops.module.workorder.dal.dataobject.maininfo.MainInfoDO;
  12 +import com.zteits.urbanops.module.workorder.dal.dataobject.maininfo.MainInfoExtDO;
  13 +import org.apache.ibatis.annotations.*;
  14 +
  15 +/**
  16 + * 类描述:工单工作流扩展Mapper
  17 + * 创建人:yanhuiqing
  18 + * 创建时间:2025/12/15 17:27
  19 + * 修改人:yanhuiqing
  20 + * 修改时间:2025/12/15 17:27
  21 + * 修改备注:
  22 + *
  23 + * @author yanhuiqing
  24 + * @version 1.0
  25 + */
  26 +@Mapper
  27 +public interface MainInfoExtMapper extends BaseMapperX<MainInfoDO> {
  28 + @Select({
  29 + "<script>",
  30 + "SELECT",
  31 + " m.*,",
  32 + " t.ID_ AS task_id,",
  33 + " t.NAME_ AS task_name,",
  34 + " pd.NAME_ AS process_definition_name,",
  35 + " t.START_TIME_,",
  36 + " t.END_TIME_,",
  37 + " pd.KEY_",
  38 + "FROM act_hi_taskinst t",
  39 + "LEFT JOIN act_re_procdef pd ON t.PROC_DEF_ID_ = pd.ID_",
  40 + "LEFT JOIN workorder_main_info m ON t.PROC_INST_ID_ = m.process_instance_id AND m.deleted = 0",
  41 + "WHERE 1=1",
  42 + " AND t.END_TIME_ IS NOT NULL",
  43 + " <if test='query.userId != null'>",
  44 + " AND t.ASSIGNEE_ = #{query.userId}",
  45 + " </if>",
  46 + " <if test='query.key != null'>",
  47 + " AND pd.KEY_ = #{query.key}",
  48 + " </if>",
  49 + " <if test='query.startTime != null'>",
  50 + " <![CDATA[ AND t.START_TIME_ >= #{query.startTime} ]]>",
  51 + " </if>",
  52 + " <if test='query.endTime != null'>",
  53 + " <![CDATA[ AND t.END_TIME_ <= #{query.endTime} ]]>",
  54 + " </if>",
  55 + " <if test='query.busiLine != null'>",
  56 + " AND m.busi_line = #{query.busiLine}",
  57 + " </if>",
  58 + " <if test=\"query.orderNo != null and query.orderNo != ''\">",
  59 + " AND m.order_no LIKE CONCAT('%', #{query.orderNo}, '%')",
  60 + " </if>",
  61 + " <if test=\"query.orderName != null and query.orderName != ''\">",
  62 + " AND m.order_name LIKE CONCAT('%', #{query.orderName}, '%')",
  63 + " </if>",
  64 + " <if test=\"query.remark != null and query.remark != ''\">",
  65 + " AND m.remark LIKE CONCAT('%', #{query.remark}, '%')",
  66 + " </if>",
  67 + " <if test=\"query.roadName != null and query.roadName != ''\">",
  68 + " AND m.road_name LIKE CONCAT('%', #{query.roadName}, '%')",
  69 + " </if>",
  70 + " <if test=\"query.streetName != null and query.streetName != ''\">",
  71 + " AND m.street_name = #{query.streetName}",
  72 + " <!-- 若需模糊匹配,改为:AND m.street_name LIKE CONCAT('%', #{query.streetName}, '%') -->",
  73 + " </if>",
  74 + " <if test='query.curingLevelId != null'>",
  75 + " AND m.curing_level_id = #{query.curingLevelId}",
  76 + " </if>",
  77 + "ORDER BY t.END_TIME_ DESC",
  78 + "</script>"
  79 + })
  80 + @Results({
  81 + @Result(column = "id", property = "id"),
  82 + @Result(column = "busi_line", property = "busiLine"),
  83 + @Result(column = "order_no", property = "orderNo"),
  84 + @Result(column = "order_name", property = "orderName"),
  85 + @Result(column = "source_id", property = "sourceId"),
  86 + @Result(column = "source_name", property = "sourceName"),
  87 + @Result(column = "road_id", property = "roadId"),
  88 + @Result(column = "road_name", property = "roadName"),
  89 + @Result(column = "street_id", property = "streetId"),
  90 + @Result(column = "street_name", property = "streetName"),
  91 + @Result(column = "curing_level_id", property = "curingLevelId"),
  92 + @Result(column = "curing_level_name", property = "curingLevelName"),
  93 + @Result(column = "commit_date", property = "commitDate"),
  94 + @Result(column = "finish_date", property = "finishDate"),
  95 + @Result(column = "pressing_type", property = "pressingType"),
  96 + @Result(column = "user_id", property = "userId"),
  97 + @Result(column = "user_name", property = "userName"),
  98 + @Result(column = "company_id", property = "companyId"),
  99 + @Result(column = "lat_lon_type", property = "latLonType"),
  100 + @Result(column = "lat", property = "lat"),
  101 + @Result(column = "lon", property = "lon"),
  102 + @Result(column = "lon_lat_address", property = "lonLatAddress"),
  103 + @Result(column = "third_work_no", property = "thirdWorkNo"),
  104 + @Result(column = "third_push_state", property = "thirdPushState"),
  105 + @Result(column = "buz_status", property = "buzStatus"),
  106 + @Result(column = "status", property = "status"),
  107 + @Result(column = "process_instance_id", property = "processInstanceId"),
  108 + @Result(column = "remark", property = "remark"),
  109 + @Result(column = "handle_result", property = "handleResult"),
  110 + @Result(column = "creator", property = "creator"),
  111 + @Result(column = "create_time", property = "createTime"),
  112 + @Result(column = "updater", property = "updater"),
  113 + @Result(column = "update_time", property = "updateTime"),
  114 + @Result(column = "deleted", property = "deleted"),
  115 +
  116 + @Result(column = "task_id", property = "taskId"),
  117 + @Result(column = "task_name", property = "taskName"),
  118 + @Result(column = "process_definition_name", property = "processDefinitionName"),
  119 + @Result(column = "START_TIME_", property = "startTime"),
  120 + @Result(column = "END_TIME_", property = "endTime"),
  121 + @Result(column = "KEY_", property = "key_")
  122 + })
  123 + IPage<MainInfoExtDO> selectDoneExtPage(IPage<MainInfoExtDO> page, @Param("query") MainInfoHasTaskPageReqVO reqVO);
  124 +
  125 + default PageResult<MainInfoExtDO> selectWorkOrderDonePage(PageParam pageParam, @Param("query") MainInfoHasTaskPageReqVO reqVO) {
  126 + IPage<MainInfoExtDO> mpPage = MyBatisUtils.buildPage(pageParam);
  127 + mpPage = selectDoneExtPage(mpPage, reqVO);
  128 + return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
  129 + }
  130 +
  131 + @Select({
  132 + "<script>",
  133 + "SELECT",
  134 + " m.*,",
  135 + " t.ID_ AS task_id,",
  136 + " t.NAME_ AS task_name,",
  137 + " pd.NAME_ AS process_definition_name,",
  138 + " t.CREATE_TIME_ AS START_TIME_,",
  139 + " t.DUE_DATE_ AS END_TIME_,",
  140 + " pd.KEY_",
  141 + "FROM act_ru_task t",
  142 + "LEFT JOIN act_re_procdef pd ON t.PROC_DEF_ID_ = pd.ID_",
  143 + "LEFT JOIN workorder_main_info m ON t.PROC_INST_ID_ = m.process_instance_id AND m.deleted = 0",
  144 + "WHERE 1=1",
  145 + " AND t.SUSPENSION_STATE_ = 1",
  146 + " <if test='query.userId != null'>",
  147 + " AND t.ASSIGNEE_ = #{query.userId}",
  148 + " </if>",
  149 + " <if test='query.key != null'>",
  150 + " AND pd.KEY_ = #{query.key}",
  151 + " </if>",
  152 + " <if test='query.startTime != null'>",
  153 + " <![CDATA[ AND t.CREATE_TIME_ >= #{query.startTime} ]]>",
  154 + " </if>",
  155 + " <if test='query.busiLine != null'>",
  156 + " AND m.busi_line = #{query.busiLine}",
  157 + " </if>",
  158 + " <if test=\"query.orderNo != null and query.orderNo != ''\">",
  159 + " AND m.order_no LIKE CONCAT('%', #{query.orderNo}, '%')",
  160 + " </if>",
  161 + " <if test=\"query.orderName != null and query.orderName != ''\">",
  162 + " AND m.order_name LIKE CONCAT('%', #{query.orderName}, '%')",
  163 + " </if>",
  164 + " <if test=\"query.remark != null and query.remark != ''\">",
  165 + " AND m.remark LIKE CONCAT('%', #{query.remark}, '%')",
  166 + " </if>",
  167 + " <if test=\"query.roadName != null and query.roadName != ''\">",
  168 + " AND m.road_name LIKE CONCAT('%', #{query.roadName}, '%')",
  169 + " </if>",
  170 + " <if test=\"query.streetName != null and query.streetName != ''\">",
  171 + " AND m.street_name = #{query.streetName}",
  172 + " <!-- 若需模糊匹配,改为:AND m.street_name LIKE CONCAT('%', #{query.streetName}, '%') -->",
  173 + " </if>",
  174 + " <if test='query.curingLevelId != null'>",
  175 + " AND m.curing_level_id = #{query.curingLevelId}",
  176 + " </if>",
  177 + "ORDER BY t.CREATE_TIME_ DESC",
  178 + "</script>"
  179 + })
  180 + @Results({
  181 + @Result(column = "id", property = "id"),
  182 + @Result(column = "busi_line", property = "busiLine"),
  183 + @Result(column = "order_no", property = "orderNo"),
  184 + @Result(column = "order_name", property = "orderName"),
  185 + @Result(column = "source_id", property = "sourceId"),
  186 + @Result(column = "source_name", property = "sourceName"),
  187 + @Result(column = "road_id", property = "roadId"),
  188 + @Result(column = "road_name", property = "roadName"),
  189 + @Result(column = "street_id", property = "streetId"),
  190 + @Result(column = "street_name", property = "streetName"),
  191 + @Result(column = "curing_level_id", property = "curingLevelId"),
  192 + @Result(column = "curing_level_name", property = "curingLevelName"),
  193 + @Result(column = "commit_date", property = "commitDate"),
  194 + @Result(column = "finish_date", property = "finishDate"),
  195 + @Result(column = "pressing_type", property = "pressingType"),
  196 + @Result(column = "user_id", property = "userId"),
  197 + @Result(column = "user_name", property = "userName"),
  198 + @Result(column = "company_id", property = "companyId"),
  199 + @Result(column = "lat_lon_type", property = "latLonType"),
  200 + @Result(column = "lat", property = "lat"),
  201 + @Result(column = "lon", property = "lon"),
  202 + @Result(column = "lon_lat_address", property = "lonLatAddress"),
  203 + @Result(column = "third_work_no", property = "thirdWorkNo"),
  204 + @Result(column = "third_push_state", property = "thirdPushState"),
  205 + @Result(column = "buz_status", property = "buzStatus"),
  206 + @Result(column = "status", property = "status"),
  207 + @Result(column = "process_instance_id", property = "processInstanceId"),
  208 + @Result(column = "remark", property = "remark"),
  209 + @Result(column = "handle_result", property = "handleResult"),
  210 + @Result(column = "creator", property = "creator"),
  211 + @Result(column = "create_time", property = "createTime"),
  212 + @Result(column = "updater", property = "updater"),
  213 + @Result(column = "update_time", property = "updateTime"),
  214 + @Result(column = "deleted", property = "deleted"),
  215 +
  216 + @Result(column = "task_id", property = "taskId"),
  217 + @Result(column = "task_name", property = "taskName"),
  218 + @Result(column = "process_definition_name", property = "processDefinitionName"),
  219 + @Result(column = "START_TIME_", property = "startTime"),
  220 + @Result(column = "END_TIME_", property = "endTime"),
  221 + @Result(column = "KEY_", property = "key_")
  222 + })
  223 + IPage<MainInfoExtDO> selectTodoExtPage(IPage<MainInfoExtDO> page, @Param("query") MainInfoHasTaskPageReqVO reqVO);
  224 +
  225 + default PageResult<MainInfoExtDO> selectWorkOrderTodoPage(PageParam pageParam, @Param("query") MainInfoHasTaskPageReqVO reqVO) {
  226 + IPage<MainInfoExtDO> mpPage = MyBatisUtils.buildPage(pageParam);
  227 + mpPage = selectTodoExtPage(mpPage, reqVO);
  228 + return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
  229 + }
  230 +}
0 231 \ No newline at end of file
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/dal/mysql/maininfo/MainInfoMapper.java
... ... @@ -2,12 +2,14 @@ package com.zteits.urbanops.module.workorder.dal.mysql.maininfo;
2 2  
3 3 import java.util.*;
4 4  
  5 +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
5 6 import com.zteits.urbanops.framework.common.pojo.PageResult;
6 7 import com.zteits.urbanops.framework.mybatis.core.query.LambdaQueryWrapperX;
7 8 import com.zteits.urbanops.framework.mybatis.core.mapper.BaseMapperX;
8 9 import com.zteits.urbanops.module.workorder.dal.dataobject.maininfo.MainInfoDO;
9 10 import org.apache.ibatis.annotations.Mapper;
10 11 import com.zteits.urbanops.module.workorder.controller.admin.maininfo.vo.*;
  12 +import org.apache.poi.ss.formula.functions.T;
11 13  
12 14 /**
13 15 * 工单信息 Mapper
... ... @@ -85,4 +87,12 @@ public interface MainInfoMapper extends BaseMapperX&lt;MainInfoDO&gt; {
85 87 .orderByDesc(MainInfoDO::getId));
86 88 }
87 89  
  90 + default List<MainInfoDO> selectListIn(String field, Collection<?> values) {
  91 + // 空集合判断:避免 SQL 中出现 IN () 语法错误
  92 + if (values == null || values.isEmpty()) {
  93 + return List.of(); // 返回空列表(JDK9+),也可以用 new ArrayList<>()
  94 + }
  95 + return selectList(new QueryWrapper<MainInfoDO>().in(field, values));
  96 + }
  97 +
88 98 }
89 99 \ No newline at end of file
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/service/attachment/AttachmentService.java
... ... @@ -59,4 +59,12 @@ public interface AttachmentService {
59 59 */
60 60 PageResult<AttachmentDO> getAttachmentPage(AttachmentPageReqVO pageReqVO);
61 61  
62   -}
63 62 \ No newline at end of file
  63 + /**
  64 + * 获得工单附件信息
  65 + *
  66 + * @param reqVO 编号
  67 + * @return 工单附件信息
  68 + */
  69 + List<AttachmentDO> getAttachmentByCondition(AttachmentReqVO reqVO);
  70 +
  71 +}
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/service/attachment/AttachmentServiceImpl.java
1 1 package com.zteits.urbanops.module.workorder.service.attachment;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
  4 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  5 +import com.baomidou.mybatisplus.core.toolkit.StringUtils;
4 6 import org.springframework.stereotype.Service;
5 7 import jakarta.annotation.Resource;
6 8 import org.springframework.validation.annotation.Validated;
... ... @@ -15,7 +17,9 @@ import com.zteits.urbanops.framework.common.util.object.BeanUtils;
15 17  
16 18 import com.zteits.urbanops.module.workorder.dal.mysql.attachment.AttachmentMapper;
17 19  
  20 +import static com.zteits.urbanops.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
18 21 import static com.zteits.urbanops.framework.common.exception.util.ServiceExceptionUtil.exception;
  22 +import static com.zteits.urbanops.framework.common.exception.util.ServiceExceptionUtil.exception0;
19 23 import static com.zteits.urbanops.framework.common.util.collection.CollectionUtils.convertList;
20 24 import static com.zteits.urbanops.framework.common.util.collection.CollectionUtils.diffList;
21 25 import static com.zteits.urbanops.module.workorder.enums.ErrorCodeConstants.*;
... ... @@ -60,10 +64,10 @@ public class AttachmentServiceImpl implements AttachmentService {
60 64 }
61 65  
62 66 @Override
63   - public void deleteAttachmentListByIds(List<Long> ids) {
  67 + public void deleteAttachmentListByIds(List<Long> ids) {
64 68 // 删除
65 69 attachmentMapper.deleteByIds(ids);
66   - }
  70 + }
67 71  
68 72  
69 73 private void validateAttachmentExists(Long id) {
... ... @@ -82,4 +86,16 @@ public class AttachmentServiceImpl implements AttachmentService {
82 86 return attachmentMapper.selectPage(pageReqVO);
83 87 }
84 88  
85   -}
86 89 \ No newline at end of file
  90 + @Override
  91 + public List<AttachmentDO> getAttachmentByCondition(AttachmentReqVO reqVO) {
  92 + if (StringUtils.isEmpty(reqVO.getOrderNo())) {
  93 + throw exception0(BAD_REQUEST.getCode(),"工单号不能为空");
  94 + }
  95 + LambdaQueryWrapper<AttachmentDO> queryWrapper = new LambdaQueryWrapper<>();
  96 + queryWrapper.eq(AttachmentDO::getOrderNo, reqVO.getOrderNo());
  97 + if (StringUtils.isNotEmpty(reqVO.getBusiType())) {
  98 + queryWrapper.eq(AttachmentDO::getBusiType, reqVO.getBusiType());
  99 + }
  100 + return attachmentMapper.selectList(queryWrapper);
  101 + }
  102 +}
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/service/garden/BpmGardenService.java
... ... @@ -119,4 +119,18 @@ public interface BpmGardenService {
119 119 * @return
120 120 */
121 121 AppGardenApprovalDetailRespVO getApprovalDetail(AppGardenApprovalDetailReqVO reqVO);
  122 +
  123 + /**
  124 + * 工单业务已完结 列表 -app 端
  125 + * @param pageVO
  126 + * @return
  127 + */
  128 + PageResult<AppGardenWorkOrderRespVO> getTaskDoneBuzSimplePage(AppGardenWorkOrderPageReqVO pageVO);
  129 +
  130 + /**
  131 + * 工单业务待办 列表 -app端
  132 + * @param pageVO
  133 + * @return
  134 + */
  135 + PageResult<AppGardenWorkOrderRespVO> getTaskTodoBuzSimplePage(AppGardenWorkOrderPageReqVO pageVO);
122 136 }
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/service/garden/BpmGardenServiceImpl.java
... ... @@ -25,6 +25,7 @@ import com.zteits.urbanops.module.workorder.api.constant.BpmCommonConstant;
25 25 import com.zteits.urbanops.module.workorder.api.workorder.WorkOrderApi;
26 26 import com.zteits.urbanops.module.workorder.controller.admin.garden.vo.BpmGardenWorkOrderCreateReqVO;
27 27 import com.zteits.urbanops.module.workorder.controller.admin.garden.vo.BpmGardenWorkOrderPageReqVO;
  28 +import com.zteits.urbanops.module.workorder.controller.admin.maininfo.vo.MainInfoHasTaskPageReqVO;
28 29 import com.zteits.urbanops.module.workorder.controller.admin.maininfo.vo.MainInfoPageReqVO;
29 30 import com.zteits.urbanops.module.workorder.controller.app.garden.vo.*;
30 31 import com.zteits.urbanops.module.workorder.controller.app.garden.vo.process.AppGardenApprovalDetailReqVO;
... ... @@ -35,7 +36,9 @@ import com.zteits.urbanops.module.workorder.convert.garden.BpmGardenWorkOrderCon
35 36 import com.zteits.urbanops.module.workorder.dal.dataobject.attachment.AttachmentDO;
36 37 import com.zteits.urbanops.module.workorder.dal.dataobject.garden.BpmGardenWorkOrderDO;
37 38 import com.zteits.urbanops.module.workorder.dal.dataobject.maininfo.MainInfoDO;
  39 +import com.zteits.urbanops.module.workorder.dal.dataobject.maininfo.MainInfoExtDO;
38 40 import com.zteits.urbanops.module.workorder.dal.mysql.attachment.AttachmentMapper;
  41 +import com.zteits.urbanops.module.workorder.dal.mysql.maininfo.MainInfoExtMapper;
39 42 import com.zteits.urbanops.module.workorder.dal.mysql.maininfo.MainInfoMapper;
40 43 import jakarta.annotation.Resource;
41 44 import org.flowable.engine.RuntimeService;
... ... @@ -51,6 +54,8 @@ import java.time.LocalDateTime;
51 54 import java.util.HashMap;
52 55 import java.util.List;
53 56 import java.util.Map;
  57 +import java.util.Set;
  58 +import java.util.stream.Collectors;
54 59  
55 60 import static com.zteits.urbanops.framework.common.exception.util.ServiceExceptionUtil.exception;
56 61 import static com.zteits.urbanops.framework.common.util.collection.CollectionUtils.convertSet;
... ... @@ -70,6 +75,9 @@ public class BpmGardenServiceImpl implements BpmGardenService{
70 75 private AttachmentMapper attachmentMapper;
71 76 @Resource
72 77 private MainInfoMapper workOrderMapper;
  78 +
  79 + @Resource
  80 + private MainInfoExtMapper workOrderExtMapper;
73 81 @Resource
74 82 private BpmProcessInstanceApi processInstanceApi;
75 83 @Resource
... ... @@ -201,6 +209,71 @@ public class BpmGardenServiceImpl implements BpmGardenService{
201 209 }
202 210  
203 211 @Override
  212 + public PageResult<AppGardenWorkOrderRespVO> getTaskDoneBuzSimplePage(AppGardenWorkOrderPageReqVO pageVO) {
  213 + MainInfoHasTaskPageReqVO taskBuzReqVO = new MainInfoHasTaskPageReqVO();
  214 + String type = pageVO.getType();
  215 + String content = pageVO.getSearchContent();
  216 + if(ObjectUtils.isNotAllEmpty(type)){
  217 + if("1".equals(type)){
  218 + if(ObjectUtils.isNotAllEmpty(content)){taskBuzReqVO.setRoadName(content);}
  219 + } else
  220 + if("2".equals(type)){
  221 + if(ObjectUtils.isNotAllEmpty(content)){taskBuzReqVO.setOrderName(content);}
  222 + }else
  223 + if("3".equals(type)){
  224 + if(ObjectUtils.isNotAllEmpty(content)){taskBuzReqVO.setRemark(content);}
  225 + } else
  226 + if("4".equals(type)){
  227 + if(ObjectUtils.isNotAllEmpty(content)){taskBuzReqVO.setOrderNo(content);}
  228 + }else {
  229 + if (ObjectUtils.isNotAllEmpty(content)) {
  230 + taskBuzReqVO.setOrderName(content);
  231 + }
  232 + }
  233 + }else {//默认是工单名称
  234 + if (ObjectUtils.isNotAllEmpty(content)) {
  235 + taskBuzReqVO.setOrderName(content);
  236 + }
  237 + }
  238 + taskBuzReqVO.setUserId(SecurityFrameworkUtils.getLoginUserId());
  239 + PageResult<MainInfoExtDO> pageResult = workOrderExtMapper.selectWorkOrderDonePage(pageVO,taskBuzReqVO);
  240 + return AppGardenTaskConvert.INSTANCE.buildBuziTaskPage(pageResult,attachmentMapper);
  241 + }
  242 +
  243 + @Override
  244 + public PageResult<AppGardenWorkOrderRespVO> getTaskTodoBuzSimplePage(AppGardenWorkOrderPageReqVO pageVO) {
  245 + MainInfoHasTaskPageReqVO taskBuzReqVO = new MainInfoHasTaskPageReqVO();
  246 + String type = pageVO.getType();
  247 + String content = pageVO.getSearchContent();
  248 + if(ObjectUtils.isNotAllEmpty(type)){
  249 + if("1".equals(type)){
  250 + if(ObjectUtils.isNotAllEmpty(content)){taskBuzReqVO.setRoadName(content);}
  251 + } else
  252 + if("2".equals(type)){
  253 + if(ObjectUtils.isNotAllEmpty(content)){taskBuzReqVO.setOrderName(content);}
  254 + }else
  255 + if("3".equals(type)){
  256 + if(ObjectUtils.isNotAllEmpty(content)){taskBuzReqVO.setRemark(content);}
  257 + } else
  258 + if("4".equals(type)){
  259 + if(ObjectUtils.isNotAllEmpty(content)){taskBuzReqVO.setOrderNo(content);}
  260 + }else {
  261 + if (ObjectUtils.isNotAllEmpty(content)) {
  262 + taskBuzReqVO.setOrderName(content);
  263 + }
  264 + }
  265 + }else {//默认是工单名称
  266 + if (ObjectUtils.isNotAllEmpty(content)) {
  267 + taskBuzReqVO.setOrderName(content);
  268 + }
  269 + }
  270 + taskBuzReqVO.setUserId(SecurityFrameworkUtils.getLoginUserId());
  271 + PageResult<MainInfoExtDO> pageResult = workOrderExtMapper.selectWorkOrderTodoPage(pageVO,taskBuzReqVO);
  272 +
  273 + return AppGardenTaskConvert.INSTANCE.buildBuziTaskPage(pageResult,attachmentMapper);
  274 + }
  275 +
  276 + @Override
204 277 public PageResult<AppGardenTaskRespVO> getTaskDonePage(AppGardenTaskPageReqVO pageVO) {
205 278 BpmTaskPageReqVO targetVO = BeanUtils.toBean(pageVO,BpmTaskPageReqVO.class);
206 279 PageResult<HistoricTaskInstance> pageResult = taskService.getTaskDonePage(SecurityFrameworkUtils.getLoginUserId(), targetVO);
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/service/garden/listener/AutoCompleteExecutionListener.java 0 → 100644
  1 +package com.zteits.urbanops.module.workorder.service.garden.listener;
  2 +
  3 +import org.flowable.common.engine.api.FlowableException;
  4 +import org.flowable.engine.delegate.DelegateExecution;
  5 +import org.flowable.engine.delegate.ExecutionListener;
  6 +import org.flowable.common.engine.impl.identity.Authentication; // 关键导入
  7 +import org.springframework.stereotype.Component;
  8 +
  9 +/**
  10 + * 流程启动时的执行监听器:设置自动完成变量
  11 + */
  12 +@Component("autoCompleteExecutionListener")
  13 +public class AutoCompleteExecutionListener implements ExecutionListener {
  14 +
  15 + @Override
  16 + public void notify(DelegateExecution execution) {
  17 + try {
  18 + // 1. 获取发起人ID:使用Authentication工具类(适配新版本)
  19 + String initiator = null;
  20 + // 获取当前认证的用户ID(静态方法)
  21 + if (Authentication.getAuthenticatedUserId() != null) {
  22 + initiator = Authentication.getAuthenticatedUserId();
  23 + } else {
  24 + // 备选:从流程变量中获取
  25 + initiator = (String) execution.getVariable("initiator");
  26 + }
  27 +
  28 + // 容错:默认用户
  29 + if (initiator == null || initiator.isEmpty()) {
  30 + initiator = "system_admin";
  31 + }
  32 +
  33 + // 2. 设置skipExpression需要的变量:autoComplete=true(表示跳过用户任务)
  34 + execution.setVariable("autoComplete", true);
  35 + // 3. 存储发起人ID和备注变量(用于追溯)
  36 + execution.setVariable("initiator", initiator);
  37 + execution.setVariable("completeRemark", "系统自动完成,办理人:" + initiator);
  38 +
  39 + } catch (Exception e) {
  40 + throw new FlowableException("设置自动完成变量失败:" + e.getMessage(), e);
  41 + }
  42 + }
  43 +}
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/service/maininfo/MainInfoService.java
... ... @@ -59,4 +59,12 @@ public interface MainInfoService {
59 59 */
60 60 PageResult<MainInfoDO> getMainInfoPage(MainInfoPageReqVO pageReqVO);
61 61  
62   -}
63 62 \ No newline at end of file
  63 + /**
  64 + * 获得工单信息
  65 + *
  66 + * @param orderNo 编号
  67 + * @return 工单信息
  68 + */
  69 + MainInfoDO getMainInfoByOrderNo(String orderNo);
  70 +
  71 +}
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/service/maininfo/MainInfoServiceImpl.java
1 1 package com.zteits.urbanops.module.workorder.service.maininfo;
2 2  
3   -import cn.hutool.core.collection.CollUtil;
4   -import org.springframework.stereotype.Service;
5   -import jakarta.annotation.Resource;
6   -import org.springframework.validation.annotation.Validated;
7   -import org.springframework.transaction.annotation.Transactional;
8   -
9   -import java.util.*;
10   -import com.zteits.urbanops.module.workorder.controller.admin.maininfo.vo.*;
11   -import com.zteits.urbanops.module.workorder.dal.dataobject.maininfo.MainInfoDO;
12 3 import com.zteits.urbanops.framework.common.pojo.PageResult;
13   -import com.zteits.urbanops.framework.common.pojo.PageParam;
14 4 import com.zteits.urbanops.framework.common.util.object.BeanUtils;
15   -
  5 +import com.zteits.urbanops.module.workorder.controller.admin.maininfo.vo.MainInfoPageReqVO;
  6 +import com.zteits.urbanops.module.workorder.controller.admin.maininfo.vo.MainInfoSaveReqVO;
  7 +import com.zteits.urbanops.module.workorder.dal.dataobject.maininfo.MainInfoDO;
16 8 import com.zteits.urbanops.module.workorder.dal.mysql.maininfo.MainInfoMapper;
  9 +import jakarta.annotation.Resource;
  10 +import org.springframework.stereotype.Service;
  11 +import org.springframework.validation.annotation.Validated;
  12 +
  13 +import java.util.List;
17 14  
18 15 import static com.zteits.urbanops.framework.common.exception.util.ServiceExceptionUtil.exception;
19   -import static com.zteits.urbanops.framework.common.util.collection.CollectionUtils.convertList;
20   -import static com.zteits.urbanops.framework.common.util.collection.CollectionUtils.diffList;
21   -import static com.zteits.urbanops.module.workorder.enums.ErrorCodeConstants.*;
  16 +import static com.zteits.urbanops.module.workorder.enums.ErrorCodeConstants.MAIN_INFO_NOT_EXISTS;
22 17  
23 18 /**
24 19 * 工单信息 Service 实现类
... ... @@ -82,4 +77,9 @@ public class MainInfoServiceImpl implements MainInfoService {
82 77 return mainInfoMapper.selectPage(pageReqVO);
83 78 }
84 79  
85   -}
86 80 \ No newline at end of file
  81 + @Override
  82 + public MainInfoDO getMainInfoByOrderNo(String orderNo) {
  83 + return mainInfoMapper.selectOne(MainInfoDO::getOrderNo, orderNo);
  84 + }
  85 +
  86 +}
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/service/materialdetail/MaterialDetailService.java
... ... @@ -59,4 +59,12 @@ public interface MaterialDetailService {
59 59 */
60 60 PageResult<MaterialDetailDO> getMaterialDetailPage(MaterialDetailPageReqVO pageReqVO);
61 61  
62   -}
63 62 \ No newline at end of file
  63 + /**
  64 + * 创建工单耗材明细
  65 + *
  66 + * @param createReqVO 创建信息
  67 + * @return 编号
  68 + */
  69 + Boolean batchCreateMaterialDetail(@Valid List<MaterialDetailSaveReqVO> createReqVO);
  70 +
  71 +}
... ...
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/service/materialdetail/MaterialDetailServiceImpl.java
1 1 package com.zteits.urbanops.module.workorder.service.materialdetail;
2 2  
3   -import cn.hutool.core.collection.CollUtil;
4   -import org.springframework.stereotype.Service;
5   -import jakarta.annotation.Resource;
6   -import org.springframework.validation.annotation.Validated;
7   -import org.springframework.transaction.annotation.Transactional;
8   -
9   -import java.util.*;
10   -import com.zteits.urbanops.module.workorder.controller.admin.materialdetail.vo.*;
11   -import com.zteits.urbanops.module.workorder.dal.dataobject.materialdetail.MaterialDetailDO;
12 3 import com.zteits.urbanops.framework.common.pojo.PageResult;
13   -import com.zteits.urbanops.framework.common.pojo.PageParam;
14 4 import com.zteits.urbanops.framework.common.util.object.BeanUtils;
15   -
  5 +import com.zteits.urbanops.module.garden.api.material.MaterialApi;
  6 +import com.zteits.urbanops.module.garden.api.material.dto.MaterialInventoryOutDto;
  7 +import com.zteits.urbanops.module.garden.controller.admin.materialinventoryout.vo.MaterialInventoryOutSaveReqVO;
  8 +import com.zteits.urbanops.module.garden.service.materialinventoryout.MaterialInventoryOutService;
  9 +import com.zteits.urbanops.module.workorder.controller.admin.materialdetail.vo.MaterialDetailPageReqVO;
  10 +import com.zteits.urbanops.module.workorder.controller.admin.materialdetail.vo.MaterialDetailSaveReqVO;
  11 +import com.zteits.urbanops.module.workorder.dal.dataobject.maininfo.MainInfoDO;
  12 +import com.zteits.urbanops.module.workorder.dal.dataobject.materialdetail.MaterialDetailDO;
16 13 import com.zteits.urbanops.module.workorder.dal.mysql.materialdetail.MaterialDetailMapper;
  14 +import com.zteits.urbanops.module.workorder.service.maininfo.MainInfoService;
  15 +import jakarta.annotation.Resource;
  16 +import org.springframework.stereotype.Service;
  17 +import org.springframework.transaction.annotation.Transactional;
  18 +import org.springframework.validation.annotation.Validated;
  19 +
  20 +import java.time.LocalDateTime;
  21 +import java.util.List;
  22 +import java.util.stream.Collectors;
17 23  
  24 +import static com.zteits.urbanops.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
18 25 import static com.zteits.urbanops.framework.common.exception.util.ServiceExceptionUtil.exception;
19   -import static com.zteits.urbanops.framework.common.util.collection.CollectionUtils.convertList;
20   -import static com.zteits.urbanops.framework.common.util.collection.CollectionUtils.diffList;
21   -import static com.zteits.urbanops.module.workorder.enums.ErrorCodeConstants.*;
  26 +import static com.zteits.urbanops.framework.common.exception.util.ServiceExceptionUtil.exception0;
  27 +import static com.zteits.urbanops.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
  28 +import static com.zteits.urbanops.framework.security.core.util.SecurityFrameworkUtils.getLoginUserNickname;
  29 +import static com.zteits.urbanops.module.workorder.enums.ErrorCodeConstants.MATERIAL_DETAIL_NOT_EXISTS;
22 30  
23 31 /**
24 32 * 工单耗材明细 Service 实现类
... ... @@ -32,10 +40,18 @@ public class MaterialDetailServiceImpl implements MaterialDetailService {
32 40 @Resource
33 41 private MaterialDetailMapper materialDetailMapper;
34 42  
  43 + @Resource
  44 + private MaterialApi materialApi;
  45 +
  46 + @Resource
  47 + private MainInfoService mainInfoService;
  48 +
35 49 @Override
36 50 public Long createMaterialDetail(MaterialDetailSaveReqVO createReqVO) {
37 51 // 插入
38 52 MaterialDetailDO materialDetail = BeanUtils.toBean(createReqVO, MaterialDetailDO.class);
  53 + materialDetail.setUserId(getLoginUserId());
  54 + materialDetail.setUserName(getLoginUserNickname());
39 55 materialDetailMapper.insert(materialDetail);
40 56  
41 57 // 返回
... ... @@ -82,4 +98,39 @@ public class MaterialDetailServiceImpl implements MaterialDetailService {
82 98 return materialDetailMapper.selectPage(pageReqVO);
83 99 }
84 100  
85   -}
86 101 \ No newline at end of file
  102 + @Override
  103 + @Transactional
  104 + public Boolean batchCreateMaterialDetail(List<MaterialDetailSaveReqVO> createReqVO) {
  105 +
  106 + List<MaterialDetailDO> materialDetailList = createReqVO.stream()
  107 + .map(vo -> {
  108 + MaterialDetailDO detailDO = new MaterialDetailDO();
  109 + BeanUtils.copyProperties(vo, detailDO); // 单个对象属性拷贝
  110 + detailDO.setUserId(getLoginUserId());
  111 + detailDO.setUserName(getLoginUserNickname());
  112 + return detailDO;
  113 + })
  114 + .collect(Collectors.toList());
  115 +
  116 + //订单号校验
  117 + for (MaterialDetailDO materialDetailDO : materialDetailList) {
  118 + MainInfoDO mainInfoDO = mainInfoService.getMainInfoByOrderNo(materialDetailDO.getOrderNo());
  119 + if (mainInfoDO == null) {
  120 + throw exception0(BAD_REQUEST.getCode(),"订单号"+materialDetailDO.getOrderNo()+"不存在");
  121 + }
  122 + }
  123 + //耗材出库
  124 + for (MaterialDetailDO materialDetailDO : materialDetailList) {
  125 + MaterialInventoryOutDto outDto = new MaterialInventoryOutDto();
  126 + outDto.setMaterialId(materialDetailDO.getMaterialId());
  127 + outDto.setMaterialName(materialDetailDO.getMaterialName());
  128 + outDto.setOutInventoryNum(materialDetailDO.getUserCount());
  129 + outDto.setOutDate(LocalDateTime.now());
  130 + materialApi.createMaterialInventoryOut(outDto);
  131 + }
  132 + //保存耗材
  133 + materialDetailMapper.insertBatch(materialDetailList);
  134 + return Boolean.TRUE;
  135 + }
  136 +
  137 +}
... ...