diff --git a/pom.xml b/pom.xml
index b4016c7..a9c15ea 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,6 +25,7 @@
+ yudao-module-mes
${project.artifactId}
diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
index aa523b9..28265a5 100644
--- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
+++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
@@ -349,4 +349,27 @@ public class CollectionUtils {
return (LinkedHashSet) toCollection(LinkedHashSet.class, elementType, value);
}
+ public static boolean dfs(Long node, Map> graph) {
+ return dfs(node, graph, new HashSet<>(), new HashSet<>());
+ }
+
+ private static boolean dfs(Long node, Map> graph, Set visited, Set inStack) {
+ if (inStack.contains(node)) {
+ return true;
+ }
+ if (visited.contains(node)) {
+ return false;
+ }
+ visited.add(node);
+ inStack.add(node);
+ Set neighbors = graph.getOrDefault(node, Collections.emptySet());
+ for (Long neighbor : neighbors) {
+ if (dfs(neighbor, graph, visited, inStack)) {
+ return true;
+ }
+ }
+ inStack.remove(node);
+ return false;
+ }
+
}
\ No newline at end of file
diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
index 4cbd4b6..287cda2 100644
--- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
+++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
@@ -336,6 +336,27 @@ public class LocalDateTimeUtils {
}
/**
+ * 获取指定日期所在季度的第一天
+ *
+ * @param date 日期
+ * @return 所在季度的第一天
+ */
+ public static LocalDate getQuarterStart(LocalDate date) {
+ Month firstMonthOfQuarter = date.getMonth().firstMonthOfQuarter();
+ return LocalDate.of(date.getYear(), firstMonthOfQuarter, 1);
+ }
+
+ /**
+ * 获取指定日期所在周的第一天(周一)
+ *
+ * @param date 日期
+ * @return 所在周的周一
+ */
+ public static LocalDate getWeekStart(LocalDate date) {
+ return date.with(DayOfWeek.MONDAY);
+ }
+
+ /**
* 将给定的 {@link LocalDateTime} 转换为自 Unix 纪元时间(1970-01-01T00:00:00Z)以来的秒数。
*
* @param sourceDateTime 需要转换的本地日期时间,不能为空
diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/ObjectUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/ObjectUtils.java
index a26c7c1..5858585 100644
--- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/ObjectUtils.java
+++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/ObjectUtils.java
@@ -60,6 +60,11 @@ public class ObjectUtils {
return Arrays.asList(array).contains(obj);
}
+ @SafeVarargs
+ public static boolean notEqualsAny(T obj, T... array) {
+ return !Arrays.asList(array).contains(obj);
+ }
+
public static boolean isNotAllEmpty(Object... objs) {
return !ObjectUtil.isAllEmpty(objs);
}
diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/api/config/ConfigApi.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/api/config/ConfigApi.java
index 85de49e..677dbf3 100644
--- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/api/config/ConfigApi.java
+++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/api/config/ConfigApi.java
@@ -7,6 +7,7 @@ package cn.iocoder.yudao.module.infra.api.config;
*/
public interface ConfigApi {
+
/**
* 根据参数键查询参数值
*
diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApi.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApi.java
index 38582c2..c608ba0 100644
--- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApi.java
+++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApi.java
@@ -11,6 +11,7 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
*/
public interface WebSocketSenderApi {
+
/**
* 发送消息给指定用户
*
diff --git a/yudao-module-mes/pom.xml b/yudao-module-mes/pom.xml
new file mode 100644
index 0000000..a20eadb
--- /dev/null
+++ b/yudao-module-mes/pom.xml
@@ -0,0 +1,65 @@
+
+
+
+ cn.iocoder.boot
+ yudao
+ ${revision}
+
+ 4.0.0
+ yudao-module-mes
+ jar
+
+ ${project.artifactId}
+
+ mes 模块下,制造执行系统(Manufacturing Execution System)。
+ 例如说:基础数据、排班日历、设备管理、工具管理、生产管理、质量管理、仓库管理等等
+
+
+
+
+ cn.iocoder.boot
+ yudao-module-system
+ ${revision}
+
+
+
+
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-web
+
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-security
+
+
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-mybatis
+
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-redis
+
+
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-excel
+
+
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-test
+
+
+
+
+
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/MesCalCalendarController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/MesCalCalendarController.java
new file mode 100644
index 0000000..a734553
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/MesCalCalendarController.java
@@ -0,0 +1,212 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.calendar;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.calendar.vo.MesCalCalendarListReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.calendar.vo.MesCalCalendarRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.shift.MesCalTeamShiftListReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.cal.holiday.MesCalHolidayDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanShiftDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamMemberDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamShiftDO;
+import cn.iocoder.yudao.module.mes.enums.cal.MesCalHolidayTypeEnum;
+import cn.iocoder.yudao.module.mes.service.cal.holiday.MesCalHolidayService;
+import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanService;
+import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanShiftService;
+import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamMemberService;
+import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamService;
+import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamShiftService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
+
+@Tag(name = "管理后台 - MES 排班日历")
+@RestController
+@RequestMapping("/mes/cal/calendar")
+@Validated
+public class MesCalCalendarController {
+
+ @Resource
+ private MesCalTeamShiftService teamShiftService;
+ @Resource
+ private MesCalTeamService teamService;
+ @Resource
+ private MesCalPlanShiftService planShiftService;
+ @Resource
+ private MesCalPlanService planService;
+ @Resource
+ private MesCalTeamMemberService teamMemberService;
+ @Resource
+ private MesCalHolidayService holidayService;
+
+ @GetMapping("/list")
+ @Operation(summary = "查询排班日历")
+ @PreAuthorize("@ss.hasPermission('mes:cal-team-shift:query')")
+ public CommonResult> getCalendarList(@Valid MesCalCalendarListReqVO reqVO) {
+ // 1.1 根据查询类型获取班组排班记录
+ List teamShifts = getTeamShifts(reqVO);
+ if (CollUtil.isEmpty(teamShifts)) {
+ return success(Collections.emptyList());
+ }
+ // 1.2 按日期范围查询假期,构建节假日日期集合
+ Set holidaySet = buildHolidaySet(reqVO.getStartDay(), reqVO.getEndDay());
+ // 1.3 批量查询关联数据:班组、班次、排班计划
+ Map teamMap = teamService.getTeamMap(
+ convertSet(teamShifts, MesCalTeamShiftDO::getTeamId));
+ Map shiftMap = planShiftService.getPlanShiftMap(
+ convertSet(teamShifts, MesCalTeamShiftDO::getShiftId));
+ Map planMap = planService.getPlanMap(
+ convertSet(teamShifts, MesCalTeamShiftDO::getPlanId));
+
+ // 2. 按 day 分组聚合
+ Map> dayGroupMap = convertMultiMap(teamShifts,
+ teamShift -> LocalDateTimeUtil.format(teamShift.getDay(), DatePattern.NORM_DATE_PATTERN));
+
+ // 3. 遍历分组,过滤假期,构建日历响应
+ List result = new ArrayList<>();
+ for (Map.Entry> entry : dayGroupMap.entrySet()) {
+ String dayStr = entry.getKey();
+ // 3.1 过滤节假日
+ if (holidaySet.contains(dayStr)) {
+ continue;
+ }
+ List dayShifts = entry.getValue();
+ dayShifts.sort(Comparator.comparing(ts -> ts.getSort() != null ? ts.getSort() : 0));
+ // 3.2 获取轮班方式(取第一条记录关联的排班计划)
+ Integer shiftType = null;
+ MesCalTeamShiftDO first = dayShifts.get(0);
+ if (first.getPlanId() != null) {
+ MesCalPlanDO plan = planMap.get(first.getPlanId());
+ if (plan != null) {
+ shiftType = plan.getShiftType();
+ }
+ }
+ // 3.3 构建班组排班项列表
+ List items = convertList(dayShifts,
+ teamShift -> buildTeamShiftItem(teamShift, teamMap, shiftMap));
+
+ // 3.4 构建日历项,添加到结果列表
+ MesCalCalendarRespVO calendarVO = MesCalCalendarRespVO.builder()
+ .day(LocalDateTimeUtil.parseDate(dayStr, DatePattern.NORM_DATE_FORMATTER).atStartOfDay())
+ .shiftType(shiftType)
+ .teamShifts(items)
+ .build();
+ result.add(calendarVO);
+ }
+ return success(result);
+ }
+
+ /**
+ * 根据查询类型获取班组排班记录
+ */
+ @SuppressWarnings("EnhancedSwitchMigration")
+ private List getTeamShifts(MesCalCalendarListReqVO reqVO) {
+ LocalDateTime startDay = reqVO.getStartDay();
+ LocalDateTime endDay = reqVO.getEndDay();
+ switch (reqVO.getQueryType()) {
+ case MesCalCalendarListReqVO.QUERY_TYPE_TYPE:
+ return getTeamShiftsByCalendarType(reqVO.getCalendarType(), startDay, endDay);
+ case MesCalCalendarListReqVO.QUERY_TYPE_TEAM:
+ return getTeamShiftsByTeamId(reqVO.getTeamId(), startDay, endDay);
+ case MesCalCalendarListReqVO.QUERY_TYPE_USER:
+ return getTeamShiftsByUserId(reqVO.getUserId(), startDay, endDay);
+ default:
+ return Collections.emptyList();
+ }
+ }
+
+ /**
+ * 构建单条 TeamShiftItem
+ */
+ private MesCalCalendarRespVO.TeamShiftItem buildTeamShiftItem(MesCalTeamShiftDO ts,
+ Map teamMap,
+ Map shiftMap) {
+ MesCalTeamDO team = teamMap.get(ts.getTeamId());
+ MesCalPlanShiftDO shift = shiftMap.get(ts.getShiftId());
+ return MesCalCalendarRespVO.TeamShiftItem.builder()
+ .teamId(ts.getTeamId()).teamName(team != null ? team.getName() : null)
+ .shiftId(ts.getShiftId()).shiftName(shift != null ? shift.getName() : null)
+ .sort(ts.getSort()).build();
+ }
+
+ /**
+ * 按班组类型查询排班记录
+ */
+ private List getTeamShiftsByCalendarType(Integer calendarType,
+ LocalDateTime startDay, LocalDateTime endDay) {
+ if (calendarType == null) {
+ return Collections.emptyList();
+ }
+ // 1. 查询指定类型的所有班组
+ List teams = teamService.getTeamList().stream()
+ .filter(t -> calendarType.equals(t.getCalendarType()))
+ .collect(Collectors.toList());
+ if (CollUtil.isEmpty(teams)) {
+ return Collections.emptyList();
+ }
+ // 2. 一次 IN 查询这些班组在日期范围内的排班记录
+ MesCalTeamShiftListReqVO reqVO = new MesCalTeamShiftListReqVO()
+ .setTeamIds(convertSet(teams, MesCalTeamDO::getId))
+ .setStartDay(startDay).setEndDay(endDay);
+ return teamShiftService.getTeamShiftList(reqVO);
+ }
+
+ /**
+ * 按班组编号查询排班记录
+ */
+ private List getTeamShiftsByTeamId(Long teamId, LocalDateTime startDay, LocalDateTime endDay) {
+ if (teamId == null) {
+ return Collections.emptyList();
+ }
+ MesCalTeamShiftListReqVO reqVO = new MesCalTeamShiftListReqVO()
+ .setTeamId(teamId).setStartDay(startDay).setEndDay(endDay);
+ return teamShiftService.getTeamShiftList(reqVO);
+ }
+
+ /**
+ * 按用户编号查询排班记录(先查用户所属班组,再查班组排班)
+ */
+ private List getTeamShiftsByUserId(Long userId,
+ LocalDateTime startDay, LocalDateTime endDay) {
+ if (userId == null) {
+ return Collections.emptyList();
+ }
+ // 1. 查询用户所属的班组(一个用户只属于一个班组)
+ MesCalTeamMemberDO member = teamMemberService.getTeamMemberByUserId(userId);
+ if (member == null) {
+ return Collections.emptyList();
+ }
+ // 2. 查询该班组在日期范围内的排班记录
+ MesCalTeamShiftListReqVO reqVO = new MesCalTeamShiftListReqVO()
+ .setTeamId(member.getTeamId()).setStartDay(startDay).setEndDay(endDay);
+ return teamShiftService.getTeamShiftList(reqVO);
+ }
+
+ /**
+ * 按日期范围查询假期,构建节假日日期集合(yyyy-MM-dd 格式)
+ */
+ private Set buildHolidaySet(LocalDateTime startDay, LocalDateTime endDay) {
+ List holidays = holidayService.getHolidayList(startDay, endDay);
+ return convertSet(holidays,
+ holiday -> LocalDateTimeUtil.format(holiday.getDay(), DatePattern.NORM_DATE_PATTERN),
+ holiday -> MesCalHolidayTypeEnum.HOLIDAY.getType().equals(holiday.getType()));
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/vo/MesCalCalendarListReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/vo/MesCalCalendarListReqVO.java
new file mode 100644
index 0000000..ac4774d
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/vo/MesCalCalendarListReqVO.java
@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.calendar.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - MES 排班日历查询 Request VO")
+@Data
+public class MesCalCalendarListReqVO {
+
+ public static final String QUERY_TYPE_TYPE = "TYPE";
+ public static final String QUERY_TYPE_TEAM = "TEAM";
+ public static final String QUERY_TYPE_USER = "USER";
+
+ @Schema(description = "开始日期", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "开始日期不能为空")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime startDay;
+
+ @Schema(description = "结束日期", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "结束日期不能为空")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime endDay;
+
+ @Schema(description = "查询类型:TYPE-按分类,TEAM-按班组,USER-按个人", requiredMode = Schema.RequiredMode.REQUIRED, example = "TYPE")
+ @NotEmpty(message = "查询类型不能为空")
+ private String queryType;
+
+ @Schema(description = "班组类型(queryType=TYPE 时使用)", example = "1")
+ private Integer calendarType;
+
+ @Schema(description = "班组编号(queryType=TEAM 时使用)", example = "201")
+ private Long teamId;
+
+ @Schema(description = "用户编号(queryType=USER 时使用)", example = "1")
+ private Long userId;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/vo/MesCalCalendarRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/vo/MesCalCalendarRespVO.java
new file mode 100644
index 0000000..254857e
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/vo/MesCalCalendarRespVO.java
@@ -0,0 +1,52 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.calendar.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Schema(description = "管理后台 - MES 排班日历 Response VO")
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class MesCalCalendarRespVO {
+
+ @Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2025-01-15 00:00:00")
+ private LocalDateTime day;
+
+ @Schema(description = "轮班方式", example = "2")
+ private Integer shiftType; // 对应 MesCalShiftTypeEnum 枚举值
+
+ @Schema(description = "班组排班列表")
+ private List teamShifts;
+
+ @Schema(description = "班组排班项")
+ @Data
+ @Builder
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class TeamShiftItem {
+
+ @Schema(description = "班组编号", example = "201")
+ private Long teamId;
+
+ @Schema(description = "班组名称", example = "注塑A组")
+ private String teamName;
+
+ @Schema(description = "班次编号", example = "1")
+ private Long shiftId;
+
+ @Schema(description = "班次名称", example = "白班")
+ private String shiftName;
+
+ @Schema(description = "排序", example = "1")
+ private Integer sort;
+
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/holiday/MesCalHolidayController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/holiday/MesCalHolidayController.java
new file mode 100644
index 0000000..a8cfd09
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/holiday/MesCalHolidayController.java
@@ -0,0 +1,64 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.holiday;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.holiday.vo.MesCalHolidayRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.holiday.vo.MesCalHolidaySaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.cal.holiday.MesCalHolidayDO;
+import cn.iocoder.yudao.module.mes.service.cal.holiday.MesCalHolidayService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - MES 假期设置")
+@RestController
+@RequestMapping("/mes/cal/holiday")
+@Validated
+public class MesCalHolidayController {
+
+ @Resource
+ private MesCalHolidayService holidayService;
+
+ @PostMapping("/save")
+ @Operation(summary = "保存假期设置", description = "如果该日期已存在记录,则更新")
+ @PreAuthorize("@ss.hasPermission('mes:cal-holiday:create')")
+ public CommonResult saveHoliday(@Valid @RequestBody MesCalHolidaySaveReqVO saveReqVO) {
+ return success(holidayService.saveHoliday(saveReqVO));
+ }
+
+ @GetMapping("/get-by-day")
+ @Operation(summary = "根据日期获得假期设置")
+ @Parameter(name = "day", description = "日期", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:cal-holiday:query')")
+ public CommonResult getHolidayByDay(
+ @RequestParam("day") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) LocalDateTime day) {
+ MesCalHolidayDO holiday = holidayService.getHolidayByDay(day);
+ return success(BeanUtils.toBean(holiday, MesCalHolidayRespVO.class));
+ }
+
+ @GetMapping("/list")
+ @Operation(summary = "获得假期设置列表", description = "支持可选日期范围过滤,不传则返回全量数据")
+ @PreAuthorize("@ss.hasPermission('mes:cal-holiday:query')")
+ public CommonResult> getHolidayList(
+ @RequestParam(value = "startDay", required = false)
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) LocalDateTime startDay,
+ @RequestParam(value = "endDay", required = false)
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) LocalDateTime endDay) {
+ List list = holidayService.getHolidayList(startDay, endDay);
+ return success(BeanUtils.toBean(list, MesCalHolidayRespVO.class));
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/holiday/vo/MesCalHolidayRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/holiday/vo/MesCalHolidayRespVO.java
new file mode 100644
index 0000000..cfde7a0
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/holiday/vo/MesCalHolidayRespVO.java
@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.holiday.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 假期设置 Response VO")
+@Data
+public class MesCalHolidayRespVO {
+
+ @Schema(description = "编号", example = "1024")
+ private Long id;
+
+ @Schema(description = "日期")
+ private LocalDateTime day;
+
+ @Schema(description = "日期类型")
+ private Integer type;
+
+ @Schema(description = "备注")
+ private String remark;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/holiday/vo/MesCalHolidaySaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/holiday/vo/MesCalHolidaySaveReqVO.java
new file mode 100644
index 0000000..0a85172
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/holiday/vo/MesCalHolidaySaveReqVO.java
@@ -0,0 +1,27 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.holiday.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 假期设置新增/修改 Request VO")
+@Data
+public class MesCalHolidaySaveReqVO {
+
+ @Schema(description = "编号", example = "1024")
+ private Long id;
+
+ @Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "日期不能为空")
+ private LocalDateTime day;
+
+ @Schema(description = "日期类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+ @NotNull(message = "日期类型不能为空")
+ private Integer type;
+
+ @Schema(description = "备注")
+ private String remark;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/package-info.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/package-info.java
new file mode 100644
index 0000000..4b2f9f3
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * MES 日历排班(Calendar / Shift Planning):班次、班组、班组成员、排班计划、假期设置等生产人员轮班与工作日历
+ */
+package cn.iocoder.yudao.module.mes.controller.admin.cal;
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanController.java
new file mode 100644
index 0000000..5a1a782
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanController.java
@@ -0,0 +1,102 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.plan;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanPageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO;
+import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - MES 排班计划")
+@RestController
+@RequestMapping("/mes/cal/plan")
+@Validated
+public class MesCalPlanController {
+
+ @Resource
+ private MesCalPlanService planService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建排班计划")
+ @PreAuthorize("@ss.hasPermission('mes:cal-plan:create')")
+ public CommonResult createPlan(@Valid @RequestBody MesCalPlanSaveReqVO createReqVO) {
+ return success(planService.createPlan(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新排班计划")
+ @PreAuthorize("@ss.hasPermission('mes:cal-plan:update')")
+ public CommonResult updatePlan(@Valid @RequestBody MesCalPlanSaveReqVO updateReqVO) {
+ planService.updatePlan(updateReqVO);
+ return success(true);
+ }
+
+ @PutMapping("/confirm")
+ @Operation(summary = "确认排班计划")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:cal-plan:update')")
+ public CommonResult confirmPlan(@RequestParam("id") Long id) {
+ planService.confirmPlan(id);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除排班计划")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:cal-plan:delete')")
+ public CommonResult deletePlan(@RequestParam("id") Long id) {
+ planService.deletePlan(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得排班计划")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:cal-plan:query')")
+ public CommonResult getPlan(@RequestParam("id") Long id) {
+ MesCalPlanDO plan = planService.getPlan(id);
+ return success(BeanUtils.toBean(plan, MesCalPlanRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得排班计划分页")
+ @PreAuthorize("@ss.hasPermission('mes:cal-plan:query')")
+ public CommonResult> getPlanPage(@Valid MesCalPlanPageReqVO pageReqVO) {
+ PageResult pageResult = planService.getPlanPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, MesCalPlanRespVO.class));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出排班计划 Excel")
+ @PreAuthorize("@ss.hasPermission('mes:cal-plan:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportPlanExcel(@Valid MesCalPlanPageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = planService.getPlanPage(pageReqVO).getList();
+ // 导出 Excel
+ ExcelUtils.write(response, "排班计划.xls", "数据", MesCalPlanRespVO.class,
+ BeanUtils.toBean(list, MesCalPlanRespVO.class));
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanShiftController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanShiftController.java
new file mode 100644
index 0000000..1f6013e
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanShiftController.java
@@ -0,0 +1,83 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.plan;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift.MesCalPlanShiftPageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift.MesCalPlanShiftRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift.MesCalPlanShiftSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanShiftDO;
+import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanShiftService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - MES 计划班次")
+@RestController
+@RequestMapping("/mes/cal/plan-shift")
+@Validated
+public class MesCalPlanShiftController {
+
+ @Resource
+ private MesCalPlanShiftService planShiftService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建计划班次")
+ @PreAuthorize("@ss.hasPermission('mes:cal-plan:update')")
+ public CommonResult createPlanShift(@Valid @RequestBody MesCalPlanShiftSaveReqVO createReqVO) {
+ return success(planShiftService.createPlanShift(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新计划班次")
+ @PreAuthorize("@ss.hasPermission('mes:cal-plan:update')")
+ public CommonResult updatePlanShift(@Valid @RequestBody MesCalPlanShiftSaveReqVO updateReqVO) {
+ planShiftService.updatePlanShift(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除计划班次")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:cal-plan:update')")
+ public CommonResult deletePlanShift(@RequestParam("id") Long id) {
+ planShiftService.deletePlanShift(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得计划班次")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:cal-plan:query')")
+ public CommonResult getPlanShift(@RequestParam("id") Long id) {
+ MesCalPlanShiftDO planShift = planShiftService.getPlanShift(id);
+ return success(BeanUtils.toBean(planShift, MesCalPlanShiftRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得计划班次分页")
+ @PreAuthorize("@ss.hasPermission('mes:cal-plan:query')")
+ public CommonResult> getPlanShiftPage(@Valid MesCalPlanShiftPageReqVO pageReqVO) {
+ PageResult pageResult = planShiftService.getPlanShiftPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, MesCalPlanShiftRespVO.class));
+ }
+
+ @GetMapping("/list-by-plan")
+ @Operation(summary = "获得指定排班计划的班次列表")
+ @Parameter(name = "planId", description = "排班计划编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:cal-plan:query')")
+ public CommonResult> getPlanShiftListByPlan(@RequestParam("planId") Long planId) {
+ List list = planShiftService.getPlanShiftListByPlanId(planId);
+ return success(BeanUtils.toBean(list, MesCalPlanShiftRespVO.class));
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanTeamController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanTeamController.java
new file mode 100644
index 0000000..7170ac5
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanTeamController.java
@@ -0,0 +1,77 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.plan;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.team.MesCalPlanTeamRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.team.MesCalPlanTeamSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanTeamDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamDO;
+import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanTeamService;
+import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
+
+@Tag(name = "管理后台 - MES 计划班组关联")
+@RestController
+@RequestMapping("/mes/cal/plan-team")
+@Validated
+public class MesCalPlanTeamController {
+
+ @Resource
+ private MesCalPlanTeamService planTeamService;
+ @Resource
+ private MesCalTeamService teamService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建计划班组关联")
+ @PreAuthorize("@ss.hasPermission('mes:cal-plan:update')")
+ public CommonResult createPlanTeam(@Valid @RequestBody MesCalPlanTeamSaveReqVO createReqVO) {
+ return success(planTeamService.createPlanTeam(createReqVO));
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除计划班组关联")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:cal-plan:update')")
+ public CommonResult deletePlanTeam(@RequestParam("id") Long id) {
+ planTeamService.deletePlanTeam(id);
+ return success(true);
+ }
+
+ @GetMapping("/list-by-plan")
+ @Operation(summary = "获得指定排班计划的班组列表")
+ @Parameter(name = "planId", description = "排班计划编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:cal-plan:query')")
+ public CommonResult> getPlanTeamListByPlan(@RequestParam("planId") Long planId) {
+ List list = planTeamService.getPlanTeamListByPlanId(planId);
+ List respList = BeanUtils.toBean(list, MesCalPlanTeamRespVO.class);
+ // 拼装班组编码/名称
+ // TODO @AI:if return
+ if (CollUtil.isNotEmpty(respList)) {
+ Map teamMap = teamService.getTeamMap(
+ convertList(respList, MesCalPlanTeamRespVO::getTeamId));
+ respList.forEach(resp -> {
+ // TODO @AI:findand then
+ MesCalTeamDO team = teamMap.get(resp.getTeamId());
+ if (team != null) {
+ resp.setTeamCode(team.getCode()).setTeamName(team.getName());
+ }
+ });
+ }
+ return success(respList);
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanPageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanPageReqVO.java
new file mode 100644
index 0000000..b88ef25
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanPageReqVO.java
@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - MES 排班计划分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MesCalPlanPageReqVO extends PageParam {
+
+ @Schema(description = "计划编码", example = "PLAN001")
+ private String code;
+
+ @Schema(description = "计划名称", example = "2024年排班")
+ private String name;
+
+ @Schema(description = "轮班方式", example = "1")
+ private Integer shiftType;
+
+ @Schema(description = "状态", example = "0")
+ private Integer status;
+
+ @Schema(description = "班组类型", example = "1")
+ private Integer calendarType;
+
+ @Schema(description = "开始日期")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] startDate;
+
+ @Schema(description = "结束日期")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] endDate;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanRespVO.java
new file mode 100644
index 0000000..d680868
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanRespVO.java
@@ -0,0 +1,63 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo;
+
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 排班计划 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class MesCalPlanRespVO {
+
+ @Schema(description = "计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @ExcelProperty("计划编号")
+ private Long id;
+
+ @Schema(description = "计划编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "PLAN001")
+ @ExcelProperty("计划编码")
+ private String code;
+
+ @Schema(description = "计划名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024年排班计划")
+ @ExcelProperty("计划名称")
+ private String name;
+
+ @Schema(description = "班组类型", example = "1")
+ @ExcelProperty("班组类型")
+ private Integer calendarType;
+
+ @Schema(description = "开始日期", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("开始日期")
+ private LocalDateTime startDate;
+
+ @Schema(description = "结束日期", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("结束日期")
+ private LocalDateTime endDate;
+
+ @Schema(description = "轮班方式", example = "1")
+ @ExcelProperty("轮班方式")
+ private Integer shiftType;
+
+ @Schema(description = "倒班方式", example = "1")
+ @ExcelProperty("倒班方式")
+ private Integer shiftMethod;
+
+ @Schema(description = "倒班天数", example = "7")
+ @ExcelProperty("倒班天数")
+ private Integer shiftCount;
+
+ @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+ @ExcelProperty("状态")
+ private Integer status;
+
+ @Schema(description = "备注")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanSaveReqVO.java
new file mode 100644
index 0000000..4de1501
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanSaveReqVO.java
@@ -0,0 +1,53 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 排班计划新增/修改 Request VO")
+@Data
+public class MesCalPlanSaveReqVO {
+
+ @Schema(description = "计划编号", example = "1024")
+ private Long id;
+
+ @Schema(description = "计划编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "PLAN001")
+ @NotEmpty(message = "计划编码不能为空")
+ private String code;
+
+ @Schema(description = "计划名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024年排班计划")
+ @NotEmpty(message = "计划名称不能为空")
+ private String name;
+
+ @Schema(description = "班组类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "班组类型不能为空")
+ private Integer calendarType;
+
+ @Schema(description = "开始日期", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "开始日期不能为空")
+ private LocalDateTime startDate;
+
+ @Schema(description = "结束日期", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "结束日期不能为空")
+ private LocalDateTime endDate;
+
+ @Schema(description = "轮班方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "轮班方式不能为空")
+ private Integer shiftType;
+
+ @Schema(description = "倒班方式", example = "1")
+ private Integer shiftMethod;
+
+ @Schema(description = "倒班天数", example = "7")
+ private Integer shiftCount;
+
+ @Schema(description = "状态", example = "0")
+ private Integer status;
+
+ @Schema(description = "备注")
+ private String remark;
+
+ }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalPlanShiftPageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalPlanShiftPageReqVO.java
new file mode 100644
index 0000000..525e168
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalPlanShiftPageReqVO.java
@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@Schema(description = "管理后台 - MES 计划班次分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MesCalPlanShiftPageReqVO extends PageParam {
+
+ @Schema(description = "排班计划编号", example = "1")
+ private Long planId;
+
+ @Schema(description = "班次名称", example = "白班")
+ private String name;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalPlanShiftRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalPlanShiftRespVO.java
new file mode 100644
index 0000000..c0613a9
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalPlanShiftRespVO.java
@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 计划班次 Response VO")
+@Data
+public class MesCalPlanShiftRespVO {
+
+ @Schema(description = "班次编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ private Long id;
+
+ @Schema(description = "排班计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long planId;
+
+ @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Integer sort;
+
+ @Schema(description = "班次名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "白班")
+ private String name;
+
+ @Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "08:00")
+ private String startTime;
+
+ @Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "17:00")
+ private String endTime;
+
+ @Schema(description = "备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalPlanShiftSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalPlanShiftSaveReqVO.java
new file mode 100644
index 0000000..cf2cefb
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalPlanShiftSaveReqVO.java
@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - MES 计划班次新增/修改 Request VO")
+@Data
+public class MesCalPlanShiftSaveReqVO {
+
+ @Schema(description = "班次编号", example = "1024")
+ private Long id;
+
+ @Schema(description = "排班计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "排班计划不能为空")
+ private Long planId;
+
+ @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "显示顺序不能为空")
+ private Integer sort;
+
+ @Schema(description = "班次名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "白班")
+ @NotEmpty(message = "班次名称不能为空")
+ private String name;
+
+ @Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "08:00")
+ @NotEmpty(message = "开始时间不能为空")
+ private String startTime;
+
+ @Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "17:00")
+ @NotEmpty(message = "结束时间不能为空")
+ private String endTime;
+
+ @Schema(description = "备注")
+ private String remark;
+
+ }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/team/MesCalPlanTeamRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/team/MesCalPlanTeamRespVO.java
new file mode 100644
index 0000000..d2a0a0d
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/team/MesCalPlanTeamRespVO.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.team;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 计划班组关联 Response VO")
+@Data
+public class MesCalPlanTeamRespVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ private Long id;
+
+ @Schema(description = "排班计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long planId;
+
+ @Schema(description = "班组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long teamId;
+
+ @Schema(description = "班组编码", example = "T001")
+ private String teamCode;
+
+ @Schema(description = "班组名称", example = "A组")
+ private String teamName;
+
+ @Schema(description = "备注")
+ private String remark;
+
+ @Schema(description = "创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/team/MesCalPlanTeamSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/team/MesCalPlanTeamSaveReqVO.java
new file mode 100644
index 0000000..1ea1165
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/team/MesCalPlanTeamSaveReqVO.java
@@ -0,0 +1,25 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.team;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - MES 计划班组关联新增 Request VO")
+@Data
+public class MesCalPlanTeamSaveReqVO {
+
+ @Schema(description = "编号", example = "1024")
+ private Long id;
+
+ @Schema(description = "排班计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "排班计划不能为空")
+ private Long planId;
+
+ @Schema(description = "班组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "班组不能为空")
+ private Long teamId;
+
+ @Schema(description = "备注")
+ private String remark;
+
+ }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/MesCalTeamController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/MesCalTeamController.java
new file mode 100644
index 0000000..5ba5108
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/MesCalTeamController.java
@@ -0,0 +1,101 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.team;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.MesCalTeamPageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.MesCalTeamRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.MesCalTeamSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamDO;
+import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - MES 班组")
+@RestController
+@RequestMapping("/mes/cal/team")
+@Validated
+public class MesCalTeamController {
+
+ @Resource
+ private MesCalTeamService teamService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建班组")
+ @PreAuthorize("@ss.hasPermission('mes:cal-team:create')")
+ public CommonResult createTeam(@Valid @RequestBody MesCalTeamSaveReqVO createReqVO) {
+ return success(teamService.createTeam(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新班组")
+ @PreAuthorize("@ss.hasPermission('mes:cal-team:update')")
+ public CommonResult updateTeam(@Valid @RequestBody MesCalTeamSaveReqVO updateReqVO) {
+ teamService.updateTeam(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除班组")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:cal-team:delete')")
+ public CommonResult deleteTeam(@RequestParam("id") Long id) {
+ teamService.deleteTeam(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得班组")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:cal-team:query')")
+ public CommonResult getTeam(@RequestParam("id") Long id) {
+ MesCalTeamDO team = teamService.getTeam(id);
+ return success(BeanUtils.toBean(team, MesCalTeamRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得班组分页")
+ @PreAuthorize("@ss.hasPermission('mes:cal-team:query')")
+ public CommonResult> getTeamPage(@Valid MesCalTeamPageReqVO pageReqVO) {
+ PageResult pageResult = teamService.getTeamPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, MesCalTeamRespVO.class));
+ }
+
+ @GetMapping("/list")
+ @Operation(summary = "获得班组列表")
+ @PreAuthorize("@ss.hasPermission('mes:cal-team:query')")
+ public CommonResult> getTeamList() {
+ List list = teamService.getTeamList();
+ return success(BeanUtils.toBean(list, MesCalTeamRespVO.class));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出班组 Excel")
+ @PreAuthorize("@ss.hasPermission('mes:cal-team:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportTeamExcel(@Valid MesCalTeamPageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = teamService.getTeamPage(pageReqVO).getList();
+ // 导出 Excel
+ ExcelUtils.write(response, "班组.xls", "数据", MesCalTeamRespVO.class,
+ BeanUtils.toBean(list, MesCalTeamRespVO.class));
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/MesCalTeamMemberController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/MesCalTeamMemberController.java
new file mode 100644
index 0000000..78bc15d
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/MesCalTeamMemberController.java
@@ -0,0 +1,108 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.team;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.member.MesCalTeamMemberPageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.member.MesCalTeamMemberRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.member.MesCalTeamMemberSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamMemberDO;
+import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamMemberService;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+
+@Tag(name = "管理后台 - MES 班组成员")
+@RestController
+@RequestMapping("/mes/cal/team-member")
+@Validated
+public class MesCalTeamMemberController {
+
+ @Resource
+ private MesCalTeamMemberService teamMemberService;
+ @Resource
+ private AdminUserApi adminUserApi;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建班组成员")
+ @PreAuthorize("@ss.hasPermission('mes:cal-team:create')")
+ public CommonResult createTeamMember(@Valid @RequestBody MesCalTeamMemberSaveReqVO createReqVO) {
+ return success(teamMemberService.createTeamMember(createReqVO));
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除班组成员")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:cal-team:delete')")
+ public CommonResult deleteTeamMember(@RequestParam("id") Long id) {
+ teamMemberService.deleteTeamMember(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得班组成员")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:cal-team:query')")
+ public CommonResult getTeamMember(@RequestParam("id") Long id) {
+ MesCalTeamMemberDO member = teamMemberService.getTeamMember(id);
+ return success(BeanUtils.toBean(member, MesCalTeamMemberRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得班组成员分页")
+ @PreAuthorize("@ss.hasPermission('mes:cal-team:query')")
+ public CommonResult> getTeamMemberPage(@Valid MesCalTeamMemberPageReqVO pageReqVO) {
+ PageResult pageResult = teamMemberService.getTeamMemberPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, MesCalTeamMemberRespVO.class));
+ }
+
+ @GetMapping("/list-by-team")
+ @Operation(summary = "获得班组成员列表", description = "支持单个 teamId 或多个 teamIds")
+ @PreAuthorize("@ss.hasPermission('mes:cal-team:query')")
+ public CommonResult> getTeamMemberListByTeam(
+ @RequestParam(value = "teamId", required = false) Long teamId,
+ @RequestParam(value = "teamIds", required = false) Collection teamIds) {
+ List list;
+ if (CollUtil.isNotEmpty(teamIds)) {
+ list = teamMemberService.getTeamMemberListByTeamIds(teamIds);
+ } else if (teamId != null) {
+ list = teamMemberService.getTeamMemberListByTeamId(teamId);
+ } else {
+ list = Collections.emptyList();
+ }
+ return success(buildMemberRespVOList(list));
+ }
+
+ // ==================== 拼接 VO ====================
+
+ private List buildMemberRespVOList(List list) {
+ if (CollUtil.isEmpty(list)) {
+ return Collections.emptyList();
+ }
+ Map userMap = adminUserApi.getUserMap(
+ convertSet(list, MesCalTeamMemberDO::getUserId));
+ return BeanUtils.toBean(list, MesCalTeamMemberRespVO.class, vo ->
+ MapUtils.findAndThen(userMap, vo.getUserId(), user -> {
+ vo.setNickname(user.getNickname());
+ vo.setTelephone(user.getMobile());
+ }));
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/MesCalTeamShiftController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/MesCalTeamShiftController.java
new file mode 100644
index 0000000..165aa76
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/MesCalTeamShiftController.java
@@ -0,0 +1,64 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.team;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.shift.MesCalTeamShiftListReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.shift.MesCalTeamShiftRespVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanShiftDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamShiftDO;
+import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanShiftService;
+import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamService;
+import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamShiftService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+
+@Tag(name = "管理后台 - MES 班组排班")
+@RestController
+@RequestMapping("/mes/cal/team-shift")
+@Validated
+public class MesCalTeamShiftController {
+
+ @Resource
+ private MesCalTeamShiftService teamShiftService;
+ @Resource
+ private MesCalTeamService teamService;
+ @Resource
+ private MesCalPlanShiftService planShiftService;
+
+ @GetMapping("/list")
+ @Operation(summary = "获得班组排班列表")
+ @PreAuthorize("@ss.hasPermission('mes:cal-team-shift:query')")
+ public CommonResult> getTeamShiftList(@Valid MesCalTeamShiftListReqVO reqVO) {
+ List list = teamShiftService.getTeamShiftList(reqVO);
+ if (CollUtil.isEmpty(list)) {
+ return success(Collections.emptyList());
+ }
+ // 关联查询班组名称和班次名称
+ Map teamMap = teamService.getTeamMap(
+ convertSet(list, MesCalTeamShiftDO::getTeamId));
+ Map shiftMap = planShiftService.getPlanShiftMap(
+ convertSet(list, MesCalTeamShiftDO::getShiftId));
+ return success(BeanUtils.toBean(list, MesCalTeamShiftRespVO.class, vo -> {
+ MapUtils.findAndThen(teamMap, vo.getTeamId(), team -> vo.setTeamName(team.getName()));
+ MapUtils.findAndThen(shiftMap, vo.getShiftId(), shift -> vo.setShiftName(shift.getName()));
+ }));
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamPageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamPageReqVO.java
new file mode 100644
index 0000000..ddc3681
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamPageReqVO.java
@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@Schema(description = "管理后台 - MES 班组分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MesCalTeamPageReqVO extends PageParam {
+
+ @Schema(description = "班组编码", example = "TEAM-A")
+ private String code;
+
+ @Schema(description = "班组名称", example = "注塑")
+ private String name;
+
+ @Schema(description = "班组类型", example = "1")
+ private Integer calendarType;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamRespVO.java
new file mode 100644
index 0000000..27d4117
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamRespVO.java
@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo;
+
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 班组 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class MesCalTeamRespVO {
+
+ @Schema(description = "班组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @ExcelProperty("班组编号")
+ private Long id;
+
+ @Schema(description = "班组编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "TEAM-A")
+ @ExcelProperty("班组编码")
+ private String code;
+
+ @Schema(description = "班组名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "注塑A组")
+ @ExcelProperty("班组名称")
+ private String name;
+
+ @Schema(description = "班组类型", example = "1")
+ @ExcelProperty("班组类型")
+ private Integer calendarType;
+
+ @Schema(description = "备注")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamSaveReqVO.java
new file mode 100644
index 0000000..e2f10f9
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamSaveReqVO.java
@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - MES 班组新增/修改 Request VO")
+@Data
+public class MesCalTeamSaveReqVO {
+
+ @Schema(description = "班组编号", example = "1024")
+ private Long id;
+
+ @Schema(description = "班组编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "TEAM-A")
+ @NotEmpty(message = "班组编码不能为空")
+ private String code;
+
+ @Schema(description = "班组名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "注塑A组")
+ @NotEmpty(message = "班组名称不能为空")
+ private String name;
+
+ @Schema(description = "班组类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "班组类型不能为空")
+ private Integer calendarType;
+
+ @Schema(description = "备注")
+ private String remark;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/member/MesCalTeamMemberPageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/member/MesCalTeamMemberPageReqVO.java
new file mode 100644
index 0000000..c225375
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/member/MesCalTeamMemberPageReqVO.java
@@ -0,0 +1,20 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.member;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@Schema(description = "管理后台 - MES 班组成员分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MesCalTeamMemberPageReqVO extends PageParam {
+
+ @Schema(description = "班组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "201")
+ @NotNull(message = "班组编号不能为空")
+ private Long teamId;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/member/MesCalTeamMemberRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/member/MesCalTeamMemberRespVO.java
new file mode 100644
index 0000000..023538b
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/member/MesCalTeamMemberRespVO.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.member;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 班组成员 Response VO")
+@Data
+public class MesCalTeamMemberRespVO {
+
+ @Schema(description = "班组成员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ private Long id;
+
+ @Schema(description = "班组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "201")
+ private Long teamId;
+
+ @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long userId;
+
+ @Schema(description = "用户昵称", example = "管理员")
+ private String nickname;
+
+ @Schema(description = "电话", example = "13800138000")
+ private String telephone;
+
+ @Schema(description = "备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/member/MesCalTeamMemberSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/member/MesCalTeamMemberSaveReqVO.java
new file mode 100644
index 0000000..71a2658
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/member/MesCalTeamMemberSaveReqVO.java
@@ -0,0 +1,25 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.member;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - MES 班组成员新增 Request VO")
+@Data
+public class MesCalTeamMemberSaveReqVO {
+
+ @Schema(description = "班组成员编号", example = "1024")
+ private Long id;
+
+ @Schema(description = "班组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "201")
+ @NotNull(message = "班组编号不能为空")
+ private Long teamId;
+
+ @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "用户编号不能为空")
+ private Long userId;
+
+ @Schema(description = "备注")
+ private String remark;
+
+ }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/shift/MesCalTeamShiftListReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/shift/MesCalTeamShiftListReqVO.java
new file mode 100644
index 0000000..459be38
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/shift/MesCalTeamShiftListReqVO.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.shift;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+import java.util.Collection;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - MES 班组排班列表 Request VO")
+@Data
+public class MesCalTeamShiftListReqVO {
+
+ @Schema(description = "班组编号", example = "201")
+ private Long teamId;
+
+ @Schema(description = "班组编号集合")
+ private Collection teamIds;
+
+ @Schema(description = "排班计划编号", example = "1")
+ private Long planId;
+
+ @Schema(description = "开始日期")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime startDay;
+
+ @Schema(description = "结束日期")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime endDay;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/shift/MesCalTeamShiftRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/shift/MesCalTeamShiftRespVO.java
new file mode 100644
index 0000000..a1af1bb
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/shift/MesCalTeamShiftRespVO.java
@@ -0,0 +1,42 @@
+package cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.shift;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 班组排班 Response VO")
+@Data
+public class MesCalTeamShiftRespVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ private Long id;
+
+ @Schema(description = "排班计划编号", example = "1")
+ private Long planId;
+
+ @Schema(description = "班组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "201")
+ private Long teamId;
+
+ @Schema(description = "班组名称", example = "注塑A组")
+ private String teamName;
+
+ @Schema(description = "班次编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long shiftId;
+
+ @Schema(description = "班次名称", example = "白班")
+ private String shiftName;
+
+ @Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED)
+ private LocalDateTime day;
+
+ @Schema(description = "排序", example = "1")
+ private Integer sort;
+
+ @Schema(description = "备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanController.java
new file mode 100644
index 0000000..55872f1
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanController.java
@@ -0,0 +1,111 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.MesDvCheckPlanPageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.MesDvCheckPlanRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.MesDvCheckPlanSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanDO;
+import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - MES 点检保养方案")
+@RestController
+@RequestMapping("/mes/dv/check-plan")
+@Validated
+public class MesDvCheckPlanController {
+
+ @Resource
+ private MesDvCheckPlanService checkPlanService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建点检保养方案")
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:create')")
+ public CommonResult createCheckPlan(@Valid @RequestBody MesDvCheckPlanSaveReqVO createReqVO) {
+ return success(checkPlanService.createCheckPlan(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新点检保养方案")
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:update')")
+ public CommonResult updateCheckPlan(@Valid @RequestBody MesDvCheckPlanSaveReqVO updateReqVO) {
+ checkPlanService.updateCheckPlan(updateReqVO);
+ return success(true);
+ }
+
+ @PutMapping("/enable")
+ @Operation(summary = "启用点检保养方案")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:update')")
+ public CommonResult enableCheckPlan(@RequestParam("id") Long id) {
+ checkPlanService.enableCheckPlan(id);
+ return success(true);
+ }
+
+ @PutMapping("/disable")
+ @Operation(summary = "停用点检保养方案")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:update')")
+ public CommonResult disableCheckPlan(@RequestParam("id") Long id) {
+ checkPlanService.disableCheckPlan(id);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除点检保养方案")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:delete')")
+ public CommonResult deleteCheckPlan(@RequestParam("id") Long id) {
+ checkPlanService.deleteCheckPlan(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得点检保养方案")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:query')")
+ public CommonResult getCheckPlan(@RequestParam("id") Long id) {
+ MesDvCheckPlanDO checkPlan = checkPlanService.getCheckPlan(id);
+ return success(BeanUtils.toBean(checkPlan, MesDvCheckPlanRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得点检保养方案分页")
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:query')")
+ public CommonResult> getCheckPlanPage(@Valid MesDvCheckPlanPageReqVO pageReqVO) {
+ PageResult pageResult = checkPlanService.getCheckPlanPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, MesDvCheckPlanRespVO.class));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出点检保养方案 Excel")
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportCheckPlanExcel(@Valid MesDvCheckPlanPageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = checkPlanService.getCheckPlanPage(pageReqVO).getList();
+ // 导出 Excel
+ ExcelUtils.write(response, "点检保养方案.xls", "数据", MesDvCheckPlanRespVO.class,
+ BeanUtils.toBean(list, MesDvCheckPlanRespVO.class));
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanMachineryController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanMachineryController.java
new file mode 100644
index 0000000..ef7a3d0
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanMachineryController.java
@@ -0,0 +1,83 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.machinery.MesDvCheckPlanMachineryRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.machinery.MesDvCheckPlanMachinerySaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanMachineryDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO;
+import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanMachineryService;
+import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+
+@Tag(name = "管理后台 - MES 点检保养方案设备")
+@RestController
+@RequestMapping("/mes/dv/check-plan-machinery")
+@Validated
+public class MesDvCheckPlanMachineryController {
+
+ @Resource
+ private MesDvCheckPlanMachineryService checkPlanMachineryService;
+ @Resource
+ private MesDvMachineryService machineryService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建方案设备关联")
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:update')")
+ public CommonResult createCheckPlanMachinery(@Valid @RequestBody MesDvCheckPlanMachinerySaveReqVO createReqVO) {
+ return success(checkPlanMachineryService.createCheckPlanMachinery(createReqVO));
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除方案设备关联")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:update')")
+ public CommonResult deleteCheckPlanMachinery(@RequestParam("id") Long id) {
+ checkPlanMachineryService.deleteCheckPlanMachinery(id);
+ return success(true);
+ }
+
+ @GetMapping("/list-by-plan")
+ @Operation(summary = "获得指定方案的设备列表")
+ @Parameter(name = "planId", description = "方案编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:query')")
+ public CommonResult> getCheckPlanMachineryListByPlan(
+ @RequestParam("planId") Long planId) {
+ List list = checkPlanMachineryService.getCheckPlanMachineryListByPlanId(planId);
+ return success(buildCheckPlanMachineryRespVOList(list));
+ }
+
+ // ==================== 拼接 VO ====================
+
+ private List buildCheckPlanMachineryRespVOList(
+ List list) {
+ if (CollUtil.isEmpty(list)) {
+ return Collections.emptyList();
+ }
+ Map machineryMap = machineryService.getMachineryMap(
+ convertSet(list, MesDvCheckPlanMachineryDO::getMachineryId));
+ return BeanUtils.toBean(list, MesDvCheckPlanMachineryRespVO.class, vo ->
+ MapUtils.findAndThen(machineryMap, vo.getMachineryId(), machinery ->
+ vo.setMachineryCode(machinery.getCode()).setMachineryName(machinery.getName())
+ .setMachineryBrand(machinery.getBrand()).setMachinerySpec(machinery.getSpec())
+ )
+ );
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanSubjectController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanSubjectController.java
new file mode 100644
index 0000000..ce0d56f
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanSubjectController.java
@@ -0,0 +1,81 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.subject.MesDvCheckPlanSubjectRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.subject.MesDvCheckPlanSubjectSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanSubjectDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.subject.MesDvSubjectDO;
+import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanSubjectService;
+import cn.iocoder.yudao.module.mes.service.dv.subject.MesDvSubjectService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - MES 点检保养方案项目")
+@RestController
+@RequestMapping("/mes/dv/check-plan-subject")
+@Validated
+public class MesDvCheckPlanSubjectController {
+
+ @Resource
+ private MesDvCheckPlanSubjectService checkPlanSubjectService;
+ @Resource
+ private MesDvSubjectService subjectService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建方案项目关联")
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:update')")
+ public CommonResult createCheckPlanSubject(@Valid @RequestBody MesDvCheckPlanSubjectSaveReqVO createReqVO) {
+ return success(checkPlanSubjectService.createCheckPlanSubject(createReqVO));
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除方案项目关联")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:update')")
+ public CommonResult deleteCheckPlanSubject(@RequestParam("id") Long id) {
+ checkPlanSubjectService.deleteCheckPlanSubject(id);
+ return success(true);
+ }
+
+ @GetMapping("/list-by-plan")
+ @Operation(summary = "获得指定方案的项目列表")
+ @Parameter(name = "planId", description = "方案编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:query')")
+ public CommonResult> getCheckPlanSubjectListByPlan(
+ @RequestParam("planId") Long planId) {
+ List list = checkPlanSubjectService.getCheckPlanSubjectListByPlanId(planId);
+ List respList = BeanUtils.toBean(list, MesDvCheckPlanSubjectRespVO.class);
+ // 拼装项目编码/名称/类型/内容/标准
+ // MesDvCheckPlanMachineryController.java 参考下里面的 todo;
+ if (CollUtil.isNotEmpty(respList)) {
+ List subjectIds = CollectionUtils.convertList(respList, MesDvCheckPlanSubjectRespVO::getSubjectId);
+ Map subjectMap = subjectService.getSubjectMap(subjectIds);
+ respList.forEach(resp -> {
+ MesDvSubjectDO subject = subjectMap.get(resp.getSubjectId());
+ if (subject != null) {
+ resp.setSubjectCode(subject.getCode());
+ resp.setSubjectName(subject.getName());
+ resp.setSubjectType(subject.getType());
+ resp.setSubjectContent(subject.getContent());
+ resp.setSubjectStandard(subject.getStandard());
+ }
+ });
+ }
+ return success(respList);
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanPageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanPageReqVO.java
new file mode 100644
index 0000000..c7c1319
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanPageReqVO.java
@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - MES 点检保养方案分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MesDvCheckPlanPageReqVO extends PageParam {
+
+ @Schema(description = "方案编码", example = "CHP001")
+ private String code;
+
+ @Schema(description = "方案名称", example = "注塑机")
+ private String name;
+
+ @Schema(description = "方案类型", example = "1")
+ private Integer type;
+
+ @Schema(description = "状态", example = "0")
+ private Integer status;
+
+ @Schema(description = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanRespVO.java
new file mode 100644
index 0000000..ff9c79d
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanRespVO.java
@@ -0,0 +1,59 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo;
+
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 点检保养方案 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class MesDvCheckPlanRespVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @ExcelProperty("编号")
+ private Long id;
+
+ @Schema(description = "方案编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "CHP001")
+ @ExcelProperty("方案编码")
+ private String code;
+
+ @Schema(description = "方案名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "注塑机日检方案")
+ @ExcelProperty("方案名称")
+ private String name;
+
+ @Schema(description = "方案类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @ExcelProperty("方案类型")
+ private Integer type;
+
+ @Schema(description = "开始日期")
+ @ExcelProperty("开始日期")
+ private LocalDateTime startDate;
+
+ @Schema(description = "结束日期")
+ @ExcelProperty("结束日期")
+ private LocalDateTime endDate;
+
+ @Schema(description = "周期类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @ExcelProperty("周期类型")
+ private Integer cycleType;
+
+ @Schema(description = "周期数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @ExcelProperty("周期数量")
+ private Integer cycleCount;
+
+ @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+ @ExcelProperty("状态")
+ private Integer status;
+
+ @Schema(description = "备注")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanSaveReqVO.java
new file mode 100644
index 0000000..fe4832e
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanSaveReqVO.java
@@ -0,0 +1,49 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 点检保养方案新增/修改 Request VO")
+@Data
+public class MesDvCheckPlanSaveReqVO {
+
+ @Schema(description = "编号", example = "1024")
+ private Long id;
+
+ @Schema(description = "方案编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "CHP001")
+ @NotEmpty(message = "方案编码不能为空")
+ private String code;
+
+ @Schema(description = "方案名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "注塑机日检方案")
+ @NotEmpty(message = "方案名称不能为空")
+ private String name;
+
+ @Schema(description = "方案类型(1=设备点检,2=设备保养)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "方案类型不能为空")
+ private Integer type;
+
+ @Schema(description = "开始日期")
+ private LocalDateTime startDate;
+
+ @Schema(description = "结束日期")
+ private LocalDateTime endDate;
+
+ @Schema(description = "周期类型(1=天,2=周,3=月,4=年)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "周期类型不能为空")
+ private Integer cycleType;
+
+ @Schema(description = "周期数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "周期数量不能为空")
+ private Integer cycleCount;
+
+ @Schema(description = "状态", example = "0")
+ private Integer status;
+
+ @Schema(description = "备注")
+ private String remark;
+
+ }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/machinery/MesDvCheckPlanMachineryRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/machinery/MesDvCheckPlanMachineryRespVO.java
new file mode 100644
index 0000000..0d2b742
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/machinery/MesDvCheckPlanMachineryRespVO.java
@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.machinery;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 点检保养方案设备 Response VO")
+@Data
+public class MesDvCheckPlanMachineryRespVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ private Long id;
+
+ @Schema(description = "方案编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long planId;
+
+ @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long machineryId;
+
+ @Schema(description = "设备编码", example = "EQ001")
+ private String machineryCode;
+
+ @Schema(description = "设备名称", example = "注塑机A")
+ private String machineryName;
+
+ @Schema(description = "品牌", example = "海天")
+ private String machineryBrand;
+
+ @Schema(description = "规格型号", example = "HTF120")
+ private String machinerySpec;
+
+ @Schema(description = "备注")
+ private String remark;
+
+ @Schema(description = "创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/machinery/MesDvCheckPlanMachinerySaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/machinery/MesDvCheckPlanMachinerySaveReqVO.java
new file mode 100644
index 0000000..8a0bc03
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/machinery/MesDvCheckPlanMachinerySaveReqVO.java
@@ -0,0 +1,25 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.machinery;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - MES 点检保养方案设备新增 Request VO")
+@Data
+public class MesDvCheckPlanMachinerySaveReqVO {
+
+ @Schema(description = "编号", example = "1024")
+ private Long id;
+
+ @Schema(description = "方案编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "方案编号不能为空")
+ private Long planId;
+
+ @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "设备不能为空")
+ private Long machineryId;
+
+ @Schema(description = "备注")
+ private String remark;
+
+ }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/subject/MesDvCheckPlanSubjectRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/subject/MesDvCheckPlanSubjectRespVO.java
new file mode 100644
index 0000000..5457006
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/subject/MesDvCheckPlanSubjectRespVO.java
@@ -0,0 +1,42 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.subject;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 点检保养方案项目 Response VO")
+@Data
+public class MesDvCheckPlanSubjectRespVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ private Long id;
+
+ @Schema(description = "方案编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long planId;
+
+ @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long subjectId;
+
+ @Schema(description = "项目编码", example = "CHK001")
+ private String subjectCode;
+
+ @Schema(description = "项目名称", example = "油温检查")
+ private String subjectName;
+
+ @Schema(description = "项目类型", example = "1")
+ private Integer subjectType;
+
+ @Schema(description = "项目内容", example = "检查油温是否正常")
+ private String subjectContent;
+
+ @Schema(description = "标准", example = "40-60°C")
+ private String subjectStandard;
+
+ @Schema(description = "备注")
+ private String remark;
+
+ @Schema(description = "创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/subject/MesDvCheckPlanSubjectSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/subject/MesDvCheckPlanSubjectSaveReqVO.java
new file mode 100644
index 0000000..ad633a3
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/subject/MesDvCheckPlanSubjectSaveReqVO.java
@@ -0,0 +1,25 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.subject;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - MES 点检保养方案项目新增 Request VO")
+@Data
+public class MesDvCheckPlanSubjectSaveReqVO {
+
+ @Schema(description = "编号", example = "1024")
+ private Long id;
+
+ @Schema(description = "方案编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "方案编号不能为空")
+ private Long planId;
+
+ @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "点检保养项目不能为空")
+ private Long subjectId;
+
+ @Schema(description = "备注")
+ private String remark;
+
+ }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/MesDvCheckRecordController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/MesDvCheckRecordController.java
new file mode 100644
index 0000000..d6b5529
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/MesDvCheckRecordController.java
@@ -0,0 +1,152 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.MesDvCheckRecordPageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.MesDvCheckRecordRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.MesDvCheckRecordSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkrecord.MesDvCheckRecordDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO;
+import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanService;
+import cn.iocoder.yudao.module.mes.service.dv.checkrecord.MesDvCheckRecordService;
+import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+
+@Tag(name = "管理后台 - MES 设备点检记录")
+@RestController
+@RequestMapping("/mes/dv/check-record")
+@Validated
+public class MesDvCheckRecordController {
+
+ @Resource
+ private MesDvCheckRecordService checkRecordService;
+
+ @Resource
+ private MesDvCheckPlanService checkPlanService;
+
+ @Resource
+ private MesDvMachineryService machineryService;
+
+ @Resource
+ private AdminUserApi adminUserApi;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建设备点检记录")
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-record:create')")
+ public CommonResult createCheckRecord(@Valid @RequestBody MesDvCheckRecordSaveReqVO createReqVO) {
+ return success(checkRecordService.createCheckRecord(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新设备点检记录")
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-record:update')")
+ public CommonResult updateCheckRecord(@Valid @RequestBody MesDvCheckRecordSaveReqVO updateReqVO) {
+ checkRecordService.updateCheckRecord(updateReqVO);
+ return success(true);
+ }
+
+ @PutMapping("/submit")
+ @Operation(summary = "提交设备点检记录(草稿→已完成)")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-record:update')")
+ public CommonResult submitCheckRecord(@RequestParam("id") Long id) {
+ checkRecordService.submitCheckRecord(id);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除设备点检记录")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-record:delete')")
+ public CommonResult deleteCheckRecord(@RequestParam("id") Long id) {
+ checkRecordService.deleteCheckRecord(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得设备点检记录")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-record:query')")
+ public CommonResult getCheckRecord(@RequestParam("id") Long id) {
+ MesDvCheckRecordDO checkRecord = checkRecordService.getCheckRecord(id);
+ if (checkRecord == null) {
+ return success(null);
+ }
+ return success(buildCheckRecordRespVOList(Collections.singletonList(checkRecord)).get(0));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得设备点检记录分页")
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-record:query')")
+ public CommonResult> getCheckRecordPage(@Valid MesDvCheckRecordPageReqVO pageReqVO) {
+ PageResult pageResult = checkRecordService.getCheckRecordPage(pageReqVO);
+ return success(new PageResult<>(buildCheckRecordRespVOList(pageResult.getList()), pageResult.getTotal()));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出设备点检记录 Excel")
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-record:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportCheckRecordExcel(@Valid MesDvCheckRecordPageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = checkRecordService.getCheckRecordPage(pageReqVO).getList();
+ ExcelUtils.write(response, "设备点检记录.xls", "数据", MesDvCheckRecordRespVO.class,
+ buildCheckRecordRespVOList(list));
+ }
+
+ // ==================== 拼接 VO ====================
+
+ @SuppressWarnings("DuplicatedCode")
+ private List buildCheckRecordRespVOList(List list) {
+ if (CollUtil.isEmpty(list)) {
+ return Collections.emptyList();
+ }
+ // 1. 批量获取关联数据
+ Map planMap = checkPlanService.getCheckPlanMap(
+ convertSet(list, MesDvCheckRecordDO::getPlanId));
+ Map machineryMap = machineryService.getMachineryMap(
+ convertSet(list, MesDvCheckRecordDO::getMachineryId));
+ Map userMap = adminUserApi.getUserMap(
+ convertSet(list, MesDvCheckRecordDO::getUserId));
+ // 2. 拼接 VO
+ return BeanUtils.toBean(list, MesDvCheckRecordRespVO.class, vo -> {
+ MapUtils.findAndThen(planMap, vo.getPlanId(),
+ plan -> vo.setPlanName(plan.getName()).setPlanCode(plan.getCode())
+ .setPlanStartDate(plan.getStartDate()).setPlanEndDate(plan.getEndDate())
+ .setPlanCycleType(plan.getCycleType()).setPlanCycleCount(plan.getCycleCount()));
+ MapUtils.findAndThen(machineryMap, vo.getMachineryId(), machinery -> vo
+ .setMachineryCode(machinery.getCode()).setMachineryName(machinery.getName())
+ .setMachineryBrand(machinery.getBrand()).setMachinerySpec(machinery.getSpec()));
+ MapUtils.findAndThen(userMap, vo.getUserId(),
+ user -> vo.setNickname(user.getNickname()));
+ });
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/MesDvCheckRecordLineController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/MesDvCheckRecordLineController.java
new file mode 100644
index 0000000..95e61d2
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/MesDvCheckRecordLineController.java
@@ -0,0 +1,103 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.line.MesDvCheckRecordLinePageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.line.MesDvCheckRecordLineRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.line.MesDvCheckRecordLineSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkrecord.MesDvCheckRecordLineDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.subject.MesDvSubjectDO;
+import cn.iocoder.yudao.module.mes.service.dv.checkrecord.MesDvCheckRecordLineService;
+import cn.iocoder.yudao.module.mes.service.dv.subject.MesDvSubjectService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+
+@Tag(name = "管理后台 - MES 设备点检记录明细")
+@RestController
+@RequestMapping("/mes/dv/check-record-line")
+@Validated
+public class MesDvCheckRecordLineController {
+
+ @Resource
+ private MesDvCheckRecordLineService checkRecordLineService;
+
+ @Resource
+ private MesDvSubjectService subjectService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建设备点检记录明细")
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-record:create')")
+ public CommonResult createCheckRecordLine(@Valid @RequestBody MesDvCheckRecordLineSaveReqVO createReqVO) {
+ return success(checkRecordLineService.createCheckRecordLine(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新设备点检记录明细")
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-record:update')")
+ public CommonResult updateCheckRecordLine(@Valid @RequestBody MesDvCheckRecordLineSaveReqVO updateReqVO) {
+ checkRecordLineService.updateCheckRecordLine(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除设备点检记录明细")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-record:delete')")
+ public CommonResult deleteCheckRecordLine(@RequestParam("id") Long id) {
+ checkRecordLineService.deleteCheckRecordLine(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得设备点检记录明细")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-record:query')")
+ public CommonResult getCheckRecordLine(@RequestParam("id") Long id) {
+ MesDvCheckRecordLineDO line = checkRecordLineService.getCheckRecordLine(id);
+ if (line == null) {
+ return success(null);
+ }
+ return success(buildCheckRecordLineRespVOList(Collections.singletonList(line)).get(0));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得设备点检记录明细分页")
+ @PreAuthorize("@ss.hasPermission('mes:dv-check-record:query')")
+ public CommonResult> getCheckRecordLinePage(@Valid MesDvCheckRecordLinePageReqVO pageReqVO) {
+ PageResult pageResult = checkRecordLineService.getCheckRecordLinePage(pageReqVO);
+ return success(new PageResult<>(buildCheckRecordLineRespVOList(pageResult.getList()), pageResult.getTotal()));
+ }
+
+ // ==================== 拼接 VO ====================
+
+ private List buildCheckRecordLineRespVOList(List list) {
+ if (CollUtil.isEmpty(list)) {
+ return Collections.emptyList();
+ }
+ // 1. 批量获取关联数据
+ Map subjectMap = subjectService.getSubjectMap(
+ convertSet(list, MesDvCheckRecordLineDO::getSubjectId));
+ // 2. 拼接 VO
+ return BeanUtils.toBean(list, MesDvCheckRecordLineRespVO.class, vo ->
+ MapUtils.findAndThen(subjectMap, vo.getSubjectId(), subject -> vo
+ .setSubjectCode(subject.getCode()).setSubjectName(subject.getName())
+ .setSubjectType(subject.getType()).setSubjectContent(subject.getContent()).setSubjectStandard(subject.getStandard())));
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordPageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordPageReqVO.java
new file mode 100644
index 0000000..340a2a2
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordPageReqVO.java
@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - MES 设备点检记录分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MesDvCheckRecordPageReqVO extends PageParam {
+
+ @Schema(description = "点检计划编号", example = "1")
+ private Long planId;
+
+ @Schema(description = "设备编号", example = "1")
+ private Long machineryId;
+
+ @Schema(description = "点检人编号", example = "1")
+ private Long userId;
+
+ @Schema(description = "状态", example = "10")
+ private Integer status;
+
+ @Schema(description = "点检时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] checkTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordRespVO.java
new file mode 100644
index 0000000..857d9dc
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordRespVO.java
@@ -0,0 +1,93 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo;
+
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+import cn.iocoder.yudao.module.mes.enums.DictTypeConstants;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 设备点检记录 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class MesDvCheckRecordRespVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @ExcelProperty("编号")
+ private Long id;
+
+ @Schema(description = "点检计划编号", example = "1")
+ private Long planId;
+
+ @Schema(description = "计划名称", example = "日常点检计划")
+ @ExcelProperty("计划名称")
+ private String planName;
+
+ @Schema(description = "计划编码", example = "P001")
+ @ExcelProperty("计划编码")
+ private String planCode;
+
+ @Schema(description = "开始时间")
+ @ExcelProperty("开始时间")
+ private LocalDateTime planStartDate;
+
+ @Schema(description = "结束日期")
+ @ExcelProperty("结束日期")
+ private LocalDateTime planEndDate;
+
+ @Schema(description = "频率类型", example = "1")
+ @ExcelProperty(value = "频率类型", converter = DictConvert.class)
+ @DictFormat(DictTypeConstants.MES_DV_CYCLE_TYPE)
+ private Integer planCycleType;
+
+ @Schema(description = "频率数量", example = "5")
+ @ExcelProperty(value = "频率数量")
+ private Integer planCycleCount;
+
+ @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long machineryId;
+
+ @Schema(description = "设备编码", example = "M001")
+ @ExcelProperty("设备编码")
+ private String machineryCode;
+
+ @Schema(description = "设备名称", example = "机床A")
+ @ExcelProperty("设备名称")
+ private String machineryName;
+
+ @Schema(description = "品牌", example = "西门子")
+ @ExcelProperty("品牌")
+ private String machineryBrand;
+
+ @Schema(description = "规格型号", example = "X-100")
+ @ExcelProperty("规格型号")
+ private String machinerySpec;
+
+ @Schema(description = "点检时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("点检时间")
+ private LocalDateTime checkTime;
+
+ @Schema(description = "点检人编号", example = "1")
+ private Long userId;
+
+ @Schema(description = "点检人名称", example = "张三")
+ @ExcelProperty("点检人")
+ private String nickname;
+
+ @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
+ @ExcelProperty(value = "状态", converter = DictConvert.class)
+ @DictFormat(DictTypeConstants.MES_DV_CHECK_RECORD_STATUS)
+ private Integer status;
+
+ @Schema(description = "备注", example = "测试备注")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordSaveReqVO.java
new file mode 100644
index 0000000..3abbc1b
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordSaveReqVO.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import jakarta.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 设备点检记录新增/修改 Request VO")
+@Data
+public class MesDvCheckRecordSaveReqVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1024")
+ private Long id;
+
+ @Schema(description = "点检计划编号", example = "1")
+ private Long planId;
+
+ @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "设备不能为空")
+ private Long machineryId;
+
+ @Schema(description = "点检时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "点检时间不能为空")
+ private LocalDateTime checkTime;
+
+ @Schema(description = "点检人编号", example = "1")
+ private Long userId;
+
+ @Schema(description = "备注", example = "测试备注")
+ private String remark;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLinePageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLinePageReqVO.java
new file mode 100644
index 0000000..166fc55
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLinePageReqVO.java
@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.line;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@Schema(description = "管理后台 - MES 设备点检记录明细分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MesDvCheckRecordLinePageReqVO extends PageParam {
+
+ @Schema(description = "点检记录编号", example = "1")
+ private Long recordId;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLineRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLineRespVO.java
new file mode 100644
index 0000000..27a90ab
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLineRespVO.java
@@ -0,0 +1,65 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.line;
+
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+import cn.iocoder.yudao.module.mes.enums.DictTypeConstants;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 设备点检记录明细 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class MesDvCheckRecordLineRespVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @ExcelProperty("编号")
+ private Long id;
+
+ @Schema(description = "点检记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long recordId;
+
+ @Schema(description = "点检项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long subjectId;
+
+ @Schema(description = "项目编码", example = "S001")
+ @ExcelProperty("项目编码")
+ private String subjectCode;
+
+ @Schema(description = "项目名称", example = "润滑油检查")
+ @ExcelProperty("项目名称")
+ private String subjectName;
+
+ @Schema(description = "项目类型", example = "1")
+ @ExcelProperty("项目类型")
+ private Integer subjectType;
+
+ @Schema(description = "检查内容", example = "检查润滑油是否充足")
+ @ExcelProperty("检查内容")
+ private String subjectContent;
+
+ @Schema(description = "检查标准", example = "油位不低于最低刻度")
+ @ExcelProperty("检查标准")
+ private String subjectStandard;
+
+ @Schema(description = "点检结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @ExcelProperty(value = "点检结果", converter = DictConvert.class)
+ @DictFormat(DictTypeConstants.MES_DV_CHECK_RESULT)
+ private Integer checkStatus;
+
+ @Schema(description = "异常描述", example = "设备异响")
+ @ExcelProperty("异常描述")
+ private String checkResult;
+
+ @Schema(description = "备注", example = "测试备注")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLineSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLineSaveReqVO.java
new file mode 100644
index 0000000..9ece085
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLineSaveReqVO.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.line;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import jakarta.validation.constraints.NotNull;
+
+@Schema(description = "管理后台 - MES 设备点检记录明细新增/修改 Request VO")
+@Data
+public class MesDvCheckRecordLineSaveReqVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1024")
+ private Long id;
+
+ @Schema(description = "点检记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "点检记录不能为空")
+ private Long recordId;
+
+ @Schema(description = "点检项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "点检项目不能为空")
+ private Long subjectId;
+
+ @Schema(description = "点检结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "点检结果不能为空")
+ private Integer checkStatus;
+
+ @Schema(description = "异常描述", example = "设备异响")
+ private String checkResult;
+
+ @Schema(description = "备注", example = "测试备注")
+ private String remark;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryController.java
new file mode 100644
index 0000000..e6d89e5
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryController.java
@@ -0,0 +1,170 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachineryImportExcelVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachineryImportRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachineryPageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachineryRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachinerySaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryTypeDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkshopDO;
+import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService;
+import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryTypeService;
+import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkshopService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+
+@Tag(name = "管理后台 - MES 设备台账")
+@RestController
+@RequestMapping("/mes/dv/machinery")
+@Validated
+public class MesDvMachineryController {
+
+ @Resource
+ private MesDvMachineryService machineryService;
+
+ @Resource
+ private MesDvMachineryTypeService machineryTypeService;
+
+ @Resource
+ private MesMdWorkshopService workshopService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建设备")
+ @PreAuthorize("@ss.hasPermission('mes:dv-machinery:create')")
+ public CommonResult createMachinery(@Valid @RequestBody MesDvMachinerySaveReqVO createReqVO) {
+ return success(machineryService.createMachinery(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新设备")
+ @PreAuthorize("@ss.hasPermission('mes:dv-machinery:update')")
+ public CommonResult updateMachinery(@Valid @RequestBody MesDvMachinerySaveReqVO updateReqVO) {
+ machineryService.updateMachinery(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除设备")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:dv-machinery:delete')")
+ public CommonResult deleteMachinery(@RequestParam("id") Long id) {
+ machineryService.deleteMachinery(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得设备")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:dv-machinery:query')")
+ public CommonResult getMachinery(@RequestParam("id") Long id) {
+ MesDvMachineryDO machinery = machineryService.getMachinery(id);
+ if (machinery == null) {
+ return success(null);
+ }
+ return success(buildMachineryRespVOList(Collections.singletonList(machinery)).get(0));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得设备分页")
+ @PreAuthorize("@ss.hasPermission('mes:dv-machinery:query')")
+ public CommonResult> getMachineryPage(@Valid MesDvMachineryPageReqVO pageReqVO) {
+ PageResult pageResult = machineryService.getMachineryPage(pageReqVO);
+ return success(new PageResult<>(buildMachineryRespVOList(pageResult.getList()), pageResult.getTotal()));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出设备 Excel")
+ @PreAuthorize("@ss.hasPermission('mes:dv-machinery:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportMachineryExcel(@Valid MesDvMachineryPageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = machineryService.getMachineryPage(pageReqVO).getList();
+ // 导出 Excel
+ ExcelUtils.write(response, "设备台账.xls", "数据", MesDvMachineryRespVO.class,
+ buildMachineryRespVOList(list));
+ }
+
+ @GetMapping("/simple-list")
+ @Operation(summary = "获得设备精简列表", description = "主要用于前端的下拉选项")
+ @PreAuthorize("@ss.hasPermission('mes:dv-machinery:query')")
+ public CommonResult> getMachinerySimpleList() {
+ List list = machineryService.getMachineryList();
+ return success(BeanUtils.toBean(list, MesDvMachineryRespVO.class));
+ }
+
+ @GetMapping("/get-import-template")
+ @Operation(summary = "获得设备导入模板")
+ public void importTemplate(HttpServletResponse response) throws IOException {
+ // 手动创建导出 demo
+ List list = Collections.singletonList(
+ MesDvMachineryImportExcelVO.builder().code("EQ-001").name("示例设备")
+ .brand("示例品牌").spec("型号A").machineryTypeCode("MT-001")
+ .workshopCode("WS-001").status(0).build()
+ );
+ // 输出
+ ExcelUtils.write(response, "设备导入模板.xls", "设备列表", MesDvMachineryImportExcelVO.class, list);
+ }
+
+ @PostMapping("/import")
+ @Operation(summary = "导入设备")
+ @Parameters({
+ @Parameter(name = "file", description = "Excel 文件", required = true),
+ @Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true")
+ })
+ @PreAuthorize("@ss.hasPermission('mes:dv-machinery:import')")
+ public CommonResult importExcel(@RequestParam("file") MultipartFile file,
+ @RequestParam(value = "updateSupport", required = false,
+ defaultValue = "false") Boolean updateSupport) throws Exception {
+ List list = ExcelUtils.read(file, MesDvMachineryImportExcelVO.class);
+ return success(machineryService.importMachineryList(list, updateSupport));
+ }
+
+ // ==================== 拼接 VO ====================
+
+ private List buildMachineryRespVOList(List list) {
+ if (CollUtil.isEmpty(list)) {
+ return Collections.emptyList();
+ }
+ // 1. 批量获取设备类型和车间信息
+ Map machineryTypeMap = machineryTypeService.getMachineryTypeMap(
+ convertSet(list, MesDvMachineryDO::getMachineryTypeId));
+ Map workshopMap = workshopService.getWorkshopMap(
+ convertSet(list, MesDvMachineryDO::getWorkshopId));
+ // 2. 拼接 VO
+ return BeanUtils.toBean(list, MesDvMachineryRespVO.class, vo -> {
+ MapUtils.findAndThen(machineryTypeMap, vo.getMachineryTypeId(),
+ machineryType -> vo.setMachineryTypeName(machineryType.getName()));
+ MapUtils.findAndThen(workshopMap, vo.getWorkshopId(),
+ workshop -> vo.setWorkshopName(workshop.getName()));
+ });
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryTypeController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryTypeController.java
new file mode 100644
index 0000000..ed3c8c7
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryTypeController.java
@@ -0,0 +1,85 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery;
+
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type.MesDvMachineryTypeListReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type.MesDvMachineryTypeRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type.MesDvMachineryTypeSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryTypeDO;
+import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryTypeService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
+
+@Tag(name = "管理后台 - MES 设备类型")
+@RestController
+@RequestMapping("/mes/dv/machinery-type")
+@Validated
+public class MesDvMachineryTypeController {
+
+ @Resource
+ private MesDvMachineryTypeService machineryTypeService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建设备类型")
+ @PreAuthorize("@ss.hasPermission('mes:dv-machinery-type:create')")
+ public CommonResult createMachineryType(@Valid @RequestBody MesDvMachineryTypeSaveReqVO createReqVO) {
+ return success(machineryTypeService.createMachineryType(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新设备类型")
+ @PreAuthorize("@ss.hasPermission('mes:dv-machinery-type:update')")
+ public CommonResult updateMachineryType(@Valid @RequestBody MesDvMachineryTypeSaveReqVO updateReqVO) {
+ machineryTypeService.updateMachineryType(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除设备类型")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:dv-machinery-type:delete')")
+ public CommonResult deleteMachineryType(@RequestParam("id") Long id) {
+ machineryTypeService.deleteMachineryType(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得设备类型")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:dv-machinery-type:query')")
+ public CommonResult getMachineryType(@RequestParam("id") Long id) {
+ MesDvMachineryTypeDO machineryType = machineryTypeService.getMachineryType(id);
+ return success(BeanUtils.toBean(machineryType, MesDvMachineryTypeRespVO.class));
+ }
+
+ @GetMapping("/list")
+ @Operation(summary = "获得设备类型列表")
+ @PreAuthorize("@ss.hasPermission('mes:dv-machinery-type:query')")
+ public CommonResult> getMachineryTypeList(@Valid MesDvMachineryTypeListReqVO listReqVO) {
+ List list = machineryTypeService.getMachineryTypeList(listReqVO);
+ return success(BeanUtils.toBean(list, MesDvMachineryTypeRespVO.class));
+ }
+
+ @GetMapping("/simple-list")
+ @Operation(summary = "获得设备类型精简列表", description = "只包含被开启的类型,主要用于前端的下拉选项")
+ public CommonResult> getMachineryTypeSimpleList() {
+ List list = machineryTypeService.getMachineryTypeList(
+ new MesDvMachineryTypeListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus()));
+ return success(convertList(list, machineryType -> new MesDvMachineryTypeRespVO()
+ .setId(machineryType.getId()).setName(machineryType.getName())
+ .setParentId(machineryType.getParentId())));
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportExcelVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportExcelVO.java
new file mode 100644
index 0000000..64f8d82
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportExcelVO.java
@@ -0,0 +1,46 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo;
+
+import cn.idev.excel.annotation.ExcelProperty;
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+import cn.iocoder.yudao.module.mes.enums.DictTypeConstants;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 设备台账 Excel 导入 VO
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class MesDvMachineryImportExcelVO {
+
+ @ExcelProperty("设备编码")
+ private String code;
+
+ @ExcelProperty("设备名称")
+ private String name;
+
+ @ExcelProperty("品牌")
+ private String brand;
+
+ @ExcelProperty("规格型号")
+ private String spec;
+
+ @ExcelProperty("设备类型编码")
+ private String machineryTypeCode;
+
+ @ExcelProperty("所属车间编码")
+ private String workshopCode;
+
+ @ExcelProperty(value = "设备状态", converter = DictConvert.class)
+ @DictFormat(DictTypeConstants.MES_DV_MACHINERY_STATUS)
+ private Integer status;
+
+ @ExcelProperty("备注")
+ private String remark;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportRespVO.java
new file mode 100644
index 0000000..aef4a69
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportRespVO.java
@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+@Schema(description = "管理后台 - MES 设备台账导入 Response VO")
+@Data
+@Builder
+public class MesDvMachineryImportRespVO {
+
+ @Schema(description = "创建成功的设备编码数组", requiredMode = Schema.RequiredMode.REQUIRED)
+ private List createCodes;
+
+ @Schema(description = "更新成功的设备编码数组", requiredMode = Schema.RequiredMode.REQUIRED)
+ private List updateCodes;
+
+ @Schema(description = "导入失败的设备集合,key 为设备编码,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED)
+ private Map failureCodes;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryPageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryPageReqVO.java
new file mode 100644
index 0000000..aefad44
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryPageReqVO.java
@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import java.util.Set;
+
+@Schema(description = "管理后台 - MES 设备台账分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MesDvMachineryPageReqVO extends PageParam {
+
+ @Schema(description = "设备编码", example = "EQ-001")
+ private String code;
+
+ @Schema(description = "设备名称", example = "CNC 加工中心")
+ private String name;
+
+ @Schema(description = "品牌", example = "西门子")
+ private String brand;
+
+ @Schema(description = "设备类型编号", example = "100")
+ private Long machineryTypeId;
+
+ @Schema(description = "设备类型编号列表(含子类型,由后端自动填充)", hidden = true)
+ private Set machineryTypeIds;
+
+ @Schema(description = "所属车间编号", example = "200")
+ private Long workshopId;
+
+ @Schema(description = "设备状态", example = "1")
+ private Integer status;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryRespVO.java
new file mode 100644
index 0000000..5e29fa8
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryRespVO.java
@@ -0,0 +1,73 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo;
+
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+import cn.iocoder.yudao.module.mes.enums.DictTypeConstants;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 设备台账 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class MesDvMachineryRespVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @ExcelProperty("编号")
+ private Long id;
+
+ @Schema(description = "设备编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "EQ-001")
+ @ExcelProperty("设备编码")
+ private String code;
+
+ @Schema(description = "设备名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "CNC 加工中心")
+ @ExcelProperty("设备名称")
+ private String name;
+
+ @Schema(description = "品牌", example = "西门子")
+ @ExcelProperty("品牌")
+ private String brand;
+
+ @Schema(description = "规格型号", example = "S7-300")
+ @ExcelProperty("规格型号")
+ private String spec;
+
+ @Schema(description = "设备类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
+ private Long machineryTypeId;
+
+ @Schema(description = "设备类型名称", example = "数控机床")
+ @ExcelProperty("设备类型")
+ private String machineryTypeName;
+
+ @Schema(description = "所属车间编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "200")
+ private Long workshopId;
+
+ @Schema(description = "所属车间名称", example = "一号车间")
+ @ExcelProperty("所属车间")
+ private String workshopName;
+
+ @Schema(description = "设备状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @ExcelProperty(value = "设备状态", converter = DictConvert.class)
+ @DictFormat(DictTypeConstants.MES_DV_MACHINERY_STATUS)
+ private Integer status;
+
+ @Schema(description = "最近保养时间")
+ @ExcelProperty("最近保养时间")
+ private LocalDateTime lastMaintenTime;
+
+ @Schema(description = "最近点检时间")
+ @ExcelProperty("最近点检时间")
+ private LocalDateTime lastCheckTime;
+
+ @Schema(description = "备注", example = "备注")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachinerySaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachinerySaveReqVO.java
new file mode 100644
index 0000000..9ff0c5d
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachinerySaveReqVO.java
@@ -0,0 +1,52 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 设备台账新增/修改 Request VO")
+@Data
+public class MesDvMachinerySaveReqVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ private Long id;
+
+ @Schema(description = "设备编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "EQ-001")
+ @NotEmpty(message = "设备编码不能为空")
+ private String code;
+
+ @Schema(description = "设备名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "CNC 加工中心")
+ @NotEmpty(message = "设备名称不能为空")
+ private String name;
+
+ @Schema(description = "品牌", example = "西门子")
+ private String brand;
+
+ @Schema(description = "规格型号", example = "S7-300")
+ private String spec;
+
+ @Schema(description = "设备类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
+ @NotNull(message = "设备类型不能为空")
+ private Long machineryTypeId;
+
+ @Schema(description = "所属车间编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "200")
+ @NotNull(message = "所属车间不能为空")
+ private Long workshopId;
+
+ @Schema(description = "设备状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "设备状态不能为空")
+ private Integer status;
+
+ @Schema(description = "最近保养时间")
+ private LocalDateTime lastMaintenTime;
+
+ @Schema(description = "最近点检时间")
+ private LocalDateTime lastCheckTime;
+
+ @Schema(description = "备注", example = "备注")
+ private String remark;
+
+ }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeListReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeListReqVO.java
new file mode 100644
index 0000000..47c530d
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeListReqVO.java
@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+@Schema(description = "管理后台 - MES 设备类型列表 Request VO")
+@Data
+@Accessors(chain = true)
+public class MesDvMachineryTypeListReqVO {
+
+ @Schema(description = "类型名称", example = "数控机床")
+ private String name;
+
+ @Schema(description = "状态", example = "0")
+ private Integer status;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeRespVO.java
new file mode 100644
index 0000000..80859d8
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeRespVO.java
@@ -0,0 +1,46 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type;
+
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 设备类型 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class MesDvMachineryTypeRespVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @ExcelProperty("编号")
+ private Long id;
+
+ @Schema(description = "类型编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "MT-001")
+ @ExcelProperty("类型编码")
+ private String code;
+
+ @Schema(description = "类型名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "数控机床")
+ @ExcelProperty("类型名称")
+ private String name;
+
+ @Schema(description = "父类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+ private Long parentId;
+
+ @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+ @ExcelProperty("状态")
+ private Integer status;
+
+ @Schema(description = "显示排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+ @ExcelProperty("显示排序")
+ private Integer sort;
+
+ @Schema(description = "备注", example = "备注")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeSaveReqVO.java
new file mode 100644
index 0000000..1a0f1ed
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeSaveReqVO.java
@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - MES 设备类型新增/修改 Request VO")
+@Data
+public class MesDvMachineryTypeSaveReqVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ private Long id;
+
+ @Schema(description = "类型编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "MT-001")
+ @NotEmpty(message = "类型编码不能为空")
+ private String code;
+
+ @Schema(description = "类型名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "数控机床")
+ @NotEmpty(message = "类型名称不能为空")
+ private String name;
+
+ @Schema(description = "父类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+ @NotNull(message = "父类型编号不能为空")
+ private Long parentId;
+
+ @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+ @NotNull(message = "状态不能为空")
+ private Integer status;
+
+ @Schema(description = "显示排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+ @NotNull(message = "显示排序不能为空")
+ private Integer sort;
+
+ @Schema(description = "备注", example = "备注")
+ private String remark;
+
+ }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/MesDvMaintenRecordController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/MesDvMaintenRecordController.java
new file mode 100644
index 0000000..5a9400c
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/MesDvMaintenRecordController.java
@@ -0,0 +1,155 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.MesDvMaintenRecordPageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.MesDvMaintenRecordRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.MesDvMaintenRecordSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.maintenrecord.MesDvMaintenRecordDO;
+import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanService;
+import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService;
+import cn.iocoder.yudao.module.mes.service.dv.maintenrecord.MesDvMaintenRecordService;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+
+@Tag(name = "管理后台 - MES 设备保养记录")
+@RestController
+@RequestMapping("/mes/dv/mainten-record")
+@Validated
+public class MesDvMaintenRecordController {
+
+ @Resource
+ private MesDvMaintenRecordService maintenRecordService;
+
+ @Resource
+ private MesDvCheckPlanService checkPlanService;
+
+ @Resource
+ private MesDvMachineryService machineryService;
+
+ @Resource
+ private AdminUserApi adminUserApi;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建设备保养记录")
+ @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:create')")
+ public CommonResult createMaintenRecord(@Valid @RequestBody MesDvMaintenRecordSaveReqVO createReqVO) {
+ return success(maintenRecordService.createMaintenRecord(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新设备保养记录")
+ @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:update')")
+ public CommonResult updateMaintenRecord(@Valid @RequestBody MesDvMaintenRecordSaveReqVO updateReqVO) {
+ maintenRecordService.updateMaintenRecord(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除设备保养记录")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:delete')")
+ public CommonResult deleteMaintenRecord(@RequestParam("id") Long id) {
+ maintenRecordService.deleteMaintenRecord(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得设备保养记录")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:query')")
+ public CommonResult getMaintenRecord(@RequestParam("id") Long id) {
+ MesDvMaintenRecordDO maintenRecord = maintenRecordService.getMaintenRecord(id);
+ if (maintenRecord == null) {
+ return success(null);
+ }
+ return success(buildMaintenRecordRespVOList(Collections.singletonList(maintenRecord)).get(0));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得设备保养记录分页")
+ @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:query')")
+ public CommonResult> getMaintenRecordPage(@Valid MesDvMaintenRecordPageReqVO pageReqVO) {
+ PageResult pageResult = maintenRecordService.getMaintenRecordPage(pageReqVO);
+ return success(new PageResult<>(buildMaintenRecordRespVOList(pageResult.getList()), pageResult.getTotal()));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出设备保养记录 Excel")
+ @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportMaintenRecordExcel(@Valid MesDvMaintenRecordPageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = maintenRecordService.getMaintenRecordPage(pageReqVO).getList();
+ // 导出 Excel
+ ExcelUtils.write(response, "设备保养记录.xls", "数据", MesDvMaintenRecordRespVO.class,
+ buildMaintenRecordRespVOList(list));
+ }
+
+ @PutMapping("/submit")
+ @Operation(summary = "提交设备保养记录(草稿→已提交)")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:update')")
+ public CommonResult submitMaintenRecord(@RequestParam("id") Long id) {
+ maintenRecordService.submitMaintenRecord(id);
+ return success(true);
+ }
+
+ // ==================== 拼接 VO ====================
+
+ private List buildMaintenRecordRespVOList(List list) {
+ if (CollUtil.isEmpty(list)) {
+ return Collections.emptyList();
+ }
+ // 1. 批量获取关联数据
+ Map planMap = checkPlanService.getCheckPlanMap(
+ convertSet(list, MesDvMaintenRecordDO::getPlanId));
+ Map machineryMap = machineryService.getMachineryMap(
+ convertSet(list, MesDvMaintenRecordDO::getMachineryId));
+ Map userMap = adminUserApi.getUserMap(
+ convertSet(list, MesDvMaintenRecordDO::getUserId));
+ // 2. 拼接 VO
+ return BeanUtils.toBean(list, MesDvMaintenRecordRespVO.class, vo -> {
+ MapUtils.findAndThen(planMap, vo.getPlanId(),
+ plan -> vo.setPlanName(plan.getName())
+ .setPlanCode(plan.getCode())
+ .setPlanStartDate(plan.getStartDate())
+ .setPlanEndDate(plan.getEndDate())
+ .setPlanCycleType(plan.getCycleType())
+ .setPlanCycleCount(plan.getCycleCount()));
+ MapUtils.findAndThen(machineryMap, vo.getMachineryId(), machinery -> vo
+ .setMachineryCode(machinery.getCode()).setMachineryName(machinery.getName())
+ .setMachineryBrand(machinery.getBrand()).setMachinerySpec(machinery.getSpec()));
+ MapUtils.findAndThen(userMap, vo.getUserId(),
+ user -> vo.setNickname(user.getNickname()));
+ });
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/MesDvMaintenRecordLineController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/MesDvMaintenRecordLineController.java
new file mode 100644
index 0000000..e3616cb
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/MesDvMaintenRecordLineController.java
@@ -0,0 +1,122 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.line.MesDvMaintenRecordLinePageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.line.MesDvMaintenRecordLineRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.line.MesDvMaintenRecordLineSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.maintenrecord.MesDvMaintenRecordLineDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.subject.MesDvSubjectDO;
+import cn.iocoder.yudao.module.mes.service.dv.maintenrecord.MesDvMaintenRecordLineService;
+import cn.iocoder.yudao.module.mes.service.dv.subject.MesDvSubjectService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+
+@Tag(name = "管理后台 - MES 设备保养记录明细")
+@RestController
+@RequestMapping("/mes/dv/mainten-record-line")
+@Validated
+public class MesDvMaintenRecordLineController {
+
+ @Resource
+ private MesDvMaintenRecordLineService maintenRecordLineService;
+
+ @Resource
+ private MesDvSubjectService subjectService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建设备保养记录明细")
+ @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:create')")
+ public CommonResult createMaintenRecordLine(@Valid @RequestBody MesDvMaintenRecordLineSaveReqVO createReqVO) {
+ return success(maintenRecordLineService.createMaintenRecordLine(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新设备保养记录明细")
+ @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:update')")
+ public CommonResult updateMaintenRecordLine(@Valid @RequestBody MesDvMaintenRecordLineSaveReqVO updateReqVO) {
+ maintenRecordLineService.updateMaintenRecordLine(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除设备保养记录明细")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:delete')")
+ public CommonResult deleteMaintenRecordLine(@RequestParam("id") Long id) {
+ maintenRecordLineService.deleteMaintenRecordLine(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得设备保养记录明细")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:query')")
+ public CommonResult getMaintenRecordLine(@RequestParam("id") Long id) {
+ MesDvMaintenRecordLineDO maintenRecordLine = maintenRecordLineService.getMaintenRecordLine(id);
+ if (maintenRecordLine == null) {
+ return success(null);
+ }
+ return success(buildMaintenRecordLineRespVOList(Collections.singletonList(maintenRecordLine)).get(0));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得设备保养记录明细分页")
+ @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:query')")
+ public CommonResult> getMaintenRecordLinePage(@Valid MesDvMaintenRecordLinePageReqVO pageReqVO) {
+ PageResult pageResult = maintenRecordLineService.getMaintenRecordLinePage(pageReqVO);
+ return success(new PageResult<>(buildMaintenRecordLineRespVOList(pageResult.getList()), pageResult.getTotal()));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出设备保养记录明细 Excel")
+ @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportMaintenRecordLineExcel(@Valid MesDvMaintenRecordLinePageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = maintenRecordLineService.getMaintenRecordLinePage(pageReqVO).getList();
+ // 导出 Excel
+ ExcelUtils.write(response, "设备保养记录明细.xls", "数据", MesDvMaintenRecordLineRespVO.class,
+ buildMaintenRecordLineRespVOList(list));
+ }
+
+ // ==================== 拼接 VO ====================
+
+ private List buildMaintenRecordLineRespVOList(List list) {
+ if (CollUtil.isEmpty(list)) {
+ return Collections.emptyList();
+ }
+ // 1. 批量获取关联数据
+ Map subjectMap = subjectService.getSubjectMap(
+ convertSet(list, MesDvMaintenRecordLineDO::getSubjectId));
+ // 2. 拼接 VO
+ return BeanUtils.toBean(list, MesDvMaintenRecordLineRespVO.class, vo ->
+ MapUtils.findAndThen(subjectMap, vo.getSubjectId(), subject -> vo
+ .setSubjectName(subject.getName()).setSubjectContent(subject.getContent())
+ .setSubjectStandard(subject.getStandard())));
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordPageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordPageReqVO.java
new file mode 100644
index 0000000..1e75613
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordPageReqVO.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - MES 设备保养记录分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MesDvMaintenRecordPageReqVO extends PageParam {
+
+ @Schema(description = "保养计划编号", example = "1")
+ private Long planId;
+
+ @Schema(description = "设备编号", example = "1")
+ private Long machineryId;
+
+ @Schema(description = "保养人编号", example = "1")
+ private Long userId;
+
+ @Schema(description = "保养时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] maintenTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordRespVO.java
new file mode 100644
index 0000000..7b8d962
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordRespVO.java
@@ -0,0 +1,93 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo;
+
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+import cn.iocoder.yudao.module.mes.enums.DictTypeConstants;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 设备保养记录 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class MesDvMaintenRecordRespVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @ExcelProperty("编号")
+ private Long id;
+
+ @Schema(description = "计划编号", example = "1")
+ private Long planId;
+
+ @Schema(description = "计划名称", example = "保养计划1")
+ @ExcelProperty("计划名称")
+ private String planName;
+
+ @Schema(description = "计划编码", example = "P001")
+ @ExcelProperty("计划编码")
+ private String planCode;
+
+ @Schema(description = "开始时间")
+ @ExcelProperty("开始时间")
+ private LocalDateTime planStartDate;
+
+ @Schema(description = "结束日期")
+ @ExcelProperty("结束日期")
+ private LocalDateTime planEndDate;
+
+ @Schema(description = "频率类型", example = "1")
+ @ExcelProperty(value = "频率类型", converter = DictConvert.class)
+ @DictFormat(DictTypeConstants.MES_DV_CYCLE_TYPE)
+ private Integer planCycleType;
+
+ @Schema(description = "频率数量", example = "5")
+ @ExcelProperty(value = "频率数量")
+ private Integer planCycleCount;
+
+ @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long machineryId;
+
+ @Schema(description = "设备编码", example = "M001")
+ @ExcelProperty("设备编码")
+ private String machineryCode;
+
+ @Schema(description = "设备名称", example = "机床A")
+ @ExcelProperty("设备名称")
+ private String machineryName;
+
+ @Schema(description = "品牌", example = "西门子")
+ @ExcelProperty("品牌")
+ private String machineryBrand;
+
+ @Schema(description = "规格型号", example = "X-100")
+ @ExcelProperty("规格型号")
+ private String machinerySpec;
+
+ @Schema(description = "保养时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("保养时间")
+ private LocalDateTime maintenTime;
+
+ @Schema(description = "用户编号", example = "1")
+ private Long userId;
+
+ @Schema(description = "保养人名称", example = "张三")
+ @ExcelProperty("保养人")
+ private String nickname;
+
+ @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
+ @ExcelProperty(value = "状态", converter = DictConvert.class)
+ @DictFormat(DictTypeConstants.MES_MAINTEN_RECORD_STATUS)
+ private Integer status;
+
+ @Schema(description = "备注", example = "测试备注")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordSaveReqVO.java
new file mode 100644
index 0000000..2e44d41
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordSaveReqVO.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import jakarta.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 设备保养记录新增/修改 Request VO")
+@Data
+public class MesDvMaintenRecordSaveReqVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1024")
+ private Long id;
+
+ @Schema(description = "计划编号", example = "1")
+ private Long planId;
+
+ @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "设备不能为空")
+ private Long machineryId;
+
+ @Schema(description = "保养时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "保养时间不能为空")
+ private LocalDateTime maintenTime;
+
+ @Schema(description = "用户编号", example = "1")
+ private Long userId;
+
+ @Schema(description = "备注", example = "测试备注")
+ private String remark;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLinePageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLinePageReqVO.java
new file mode 100644
index 0000000..047fb32
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLinePageReqVO.java
@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.line;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@Schema(description = "管理后台 - MES 设备保养记录明细分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MesDvMaintenRecordLinePageReqVO extends PageParam {
+
+ @Schema(description = "保养记录ID", example = "1")
+ private Long recordId;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLineRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLineRespVO.java
new file mode 100644
index 0000000..adea3c9
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLineRespVO.java
@@ -0,0 +1,57 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.line;
+
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+import cn.iocoder.yudao.module.mes.enums.DictTypeConstants;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 设备保养记录明细 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class MesDvMaintenRecordLineRespVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @ExcelProperty("编号")
+ private Long id;
+
+ @Schema(description = "保养记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long recordId;
+
+ @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long subjectId;
+
+ @Schema(description = "项目名称", example = "检查机油")
+ @ExcelProperty("项目名称")
+ private String subjectName;
+
+ @Schema(description = "项目内容", example = "检查机油是否充足")
+ @ExcelProperty("项目内容")
+ private String subjectContent;
+
+ @Schema(description = "项目标准", example = "无漏油")
+ @ExcelProperty("标准")
+ private String subjectStandard;
+
+ @Schema(description = "保养结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @ExcelProperty(value = "保养结果", converter = DictConvert.class)
+ @DictFormat(DictTypeConstants.MES_MAINTEN_STATUS)
+ private Integer status;
+
+ @Schema(description = "异常描述", example = "发现损坏")
+ @ExcelProperty("异常描述")
+ private String result;
+
+ @Schema(description = "备注", example = "测试备注")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLineSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLineSaveReqVO.java
new file mode 100644
index 0000000..b691306
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLineSaveReqVO.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.line;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import jakarta.validation.constraints.NotNull;
+
+@Schema(description = "管理后台 - MES 设备保养记录明细新增/修改 Request VO")
+@Data
+public class MesDvMaintenRecordLineSaveReqVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1024")
+ private Long id;
+
+ @Schema(description = "保养记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "保养记录不能为空")
+ private Long recordId;
+
+ @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "项目不能为空")
+ private Long subjectId;
+
+ @Schema(description = "保养结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "保养结果不能为空")
+ private Integer status;
+
+ @Schema(description = "异常描述", example = "发现损坏")
+ private String result;
+
+ @Schema(description = "备注", example = "测试备注")
+ private String remark;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/package-info.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/package-info.java
new file mode 100644
index 0000000..8cdd365
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * MES 设备管理(Device / Equipment Management):设备类型、设备台账、点检计划与记录、保养记录、维修工单等设备全生命周期管理
+ */
+package cn.iocoder.yudao.module.mes.controller.admin.dv;
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/MesDvRepairController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/MesDvRepairController.java
new file mode 100644
index 0000000..7b958ce
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/MesDvRepairController.java
@@ -0,0 +1,171 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.repair;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.MesDvRepairPageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.MesDvRepairRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.MesDvRepairSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.repair.MesDvRepairDO;
+import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService;
+import cn.iocoder.yudao.module.mes.service.dv.repair.MesDvRepairService;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
+import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
+
+@Tag(name = "管理后台 - MES 维修工单")
+@RestController
+@RequestMapping("/mes/dv/repair")
+@Validated
+public class MesDvRepairController {
+
+ @Resource
+ private MesDvRepairService repairService;
+
+ @Resource
+ private MesDvMachineryService machineryService;
+
+ @Resource
+ private AdminUserApi adminUserApi;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建维修工单")
+ @PreAuthorize("@ss.hasPermission('mes:dv-repair:create')")
+ public CommonResult createRepair(@Valid @RequestBody MesDvRepairSaveReqVO createReqVO) {
+ return success(repairService.createRepair(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新维修工单")
+ @PreAuthorize("@ss.hasPermission('mes:dv-repair:update')")
+ public CommonResult updateRepair(@Valid @RequestBody MesDvRepairSaveReqVO updateReqVO) {
+ repairService.updateRepair(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除维修工单")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:dv-repair:delete')")
+ public CommonResult deleteRepair(@RequestParam("id") Long id) {
+ repairService.deleteRepair(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得维修工单")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:dv-repair:query')")
+ public CommonResult getRepair(@RequestParam("id") Long id) {
+ MesDvRepairDO repair = repairService.getRepair(id);
+ if (repair == null) {
+ return success(null);
+ }
+ return success(buildRepairRespVOList(Collections.singletonList(repair)).get(0));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得维修工单分页")
+ @PreAuthorize("@ss.hasPermission('mes:dv-repair:query')")
+ public CommonResult> getRepairPage(@Valid MesDvRepairPageReqVO pageReqVO) {
+ PageResult pageResult = repairService.getRepairPage(pageReqVO);
+ return success(new PageResult<>(buildRepairRespVOList(pageResult.getList()), pageResult.getTotal()));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出维修工单 Excel")
+ @PreAuthorize("@ss.hasPermission('mes:dv-repair:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportRepairExcel(@Valid MesDvRepairPageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = repairService.getRepairPage(pageReqVO).getList();
+ // 导出 Excel
+ ExcelUtils.write(response, "维修工单.xls", "数据", MesDvRepairRespVO.class,
+ buildRepairRespVOList(list));
+ }
+
+ // DONE @AI:submit=>confirm=>finish(然后里面有是 resultstatus 这样的字段【对齐实体?】)
+
+ @PutMapping("/submit")
+ @Operation(summary = "提交维修工单(草稿→维修中)")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:dv-repair:update')")
+ public CommonResult submitRepair(@RequestParam("id") Long id) {
+ repairService.submitRepair(id, getLoginUserId());
+ return success(true);
+ }
+
+ @PutMapping("/confirm")
+ @Operation(summary = "确认维修完成(维修中→待验收)")
+ @PreAuthorize("@ss.hasPermission('mes:dv-repair:update')")
+ public CommonResult confirmRepair(@Valid @RequestBody cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.MesDvRepairConfirmReqVO confirmReqVO) {
+ repairService.confirmRepair(confirmReqVO);
+ return success(true);
+ }
+
+ @PutMapping("/finish")
+ @Operation(summary = "完成验收(待验收→已确认)")
+ @Parameters({
+ @Parameter(name = "id", description = "编号", required = true),
+ @Parameter(name = "result", description = "验收结果", required = true)
+ })
+ @PreAuthorize("@ss.hasPermission('mes:dv-repair:update')")
+ public CommonResult finishRepair(@RequestParam("id") Long id,
+ @RequestParam("result") Integer result) {
+ repairService.finishRepair(id, result, getLoginUserId());
+ return success(true);
+ }
+
+ // ==================== 拼接 VO ====================
+
+ private List buildRepairRespVOList(List list) {
+ if (CollUtil.isEmpty(list)) {
+ return Collections.emptyList();
+ }
+ // 1.1 批量获取关联数据
+ Map machineryMap = machineryService.getMachineryMap(
+ convertSet(list, MesDvRepairDO::getMachineryId));
+ // 1.2 收集所有用户 ID(维修人 + 验收人)
+ Map userMap = adminUserApi.getUserMap(convertSetByFlatMap(list,
+ repair -> Stream.of(repair.getAcceptedUserId(), repair.getConfirmUserId())));
+ // 2. 拼接 VO
+ return BeanUtils.toBean(list, MesDvRepairRespVO.class, vo -> {
+ MapUtils.findAndThen(machineryMap, vo.getMachineryId(), machinery -> vo
+ .setMachineryCode(machinery.getCode()).setMachineryName(machinery.getName())
+ .setMachineryBrand(machinery.getBrand()).setMachinerySpec(machinery.getSpec()));
+ MapUtils.findAndThen(userMap, vo.getAcceptedUserId(),
+ user -> vo.setAcceptedUserNickname(user.getNickname()));
+ MapUtils.findAndThen(userMap, vo.getConfirmUserId(),
+ user -> vo.setConfirmUserNickname(user.getNickname()));
+ });
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/MesDvRepairLineController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/MesDvRepairLineController.java
new file mode 100644
index 0000000..b0e6ccf
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/MesDvRepairLineController.java
@@ -0,0 +1,122 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.repair;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.line.MesDvRepairLinePageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.line.MesDvRepairLineRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.line.MesDvRepairLineSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.repair.MesDvRepairLineDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.subject.MesDvSubjectDO;
+import cn.iocoder.yudao.module.mes.service.dv.repair.MesDvRepairLineService;
+import cn.iocoder.yudao.module.mes.service.dv.subject.MesDvSubjectService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+
+@Tag(name = "管理后台 - MES 维修工单行")
+@RestController
+@RequestMapping("/mes/dv/repair-line")
+@Validated
+public class MesDvRepairLineController {
+
+ @Resource
+ private MesDvRepairLineService repairLineService;
+
+ @Resource
+ private MesDvSubjectService subjectService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建维修工单行")
+ @PreAuthorize("@ss.hasPermission('mes:dv-repair:create')")
+ public CommonResult createRepairLine(@Valid @RequestBody MesDvRepairLineSaveReqVO createReqVO) {
+ return success(repairLineService.createRepairLine(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新维修工单行")
+ @PreAuthorize("@ss.hasPermission('mes:dv-repair:update')")
+ public CommonResult updateRepairLine(@Valid @RequestBody MesDvRepairLineSaveReqVO updateReqVO) {
+ repairLineService.updateRepairLine(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除维修工单行")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:dv-repair:delete')")
+ public CommonResult deleteRepairLine(@RequestParam("id") Long id) {
+ repairLineService.deleteRepairLine(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得维修工单行")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:dv-repair:query')")
+ public CommonResult getRepairLine(@RequestParam("id") Long id) {
+ MesDvRepairLineDO repairLine = repairLineService.getRepairLine(id);
+ if (repairLine == null) {
+ return success(null);
+ }
+ return success(buildRepairLineRespVOList(Collections.singletonList(repairLine)).get(0));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得维修工单行分页")
+ @PreAuthorize("@ss.hasPermission('mes:dv-repair:query')")
+ public CommonResult> getRepairLinePage(@Valid MesDvRepairLinePageReqVO pageReqVO) {
+ PageResult pageResult = repairLineService.getRepairLinePage(pageReqVO);
+ return success(new PageResult<>(buildRepairLineRespVOList(pageResult.getList()), pageResult.getTotal()));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出维修工单行 Excel")
+ @PreAuthorize("@ss.hasPermission('mes:dv-repair:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportRepairLineExcel(@Valid MesDvRepairLinePageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = repairLineService.getRepairLinePage(pageReqVO).getList();
+ // 导出 Excel
+ ExcelUtils.write(response, "维修工单行.xls", "数据", MesDvRepairLineRespVO.class,
+ buildRepairLineRespVOList(list));
+ }
+
+ // ==================== 拼接 VO ====================
+
+ private List buildRepairLineRespVOList(List list) {
+ if (CollUtil.isEmpty(list)) {
+ return Collections.emptyList();
+ }
+ // 1. 批量获取关联数据
+ Map subjectMap = subjectService.getSubjectMap(
+ convertSet(list, MesDvRepairLineDO::getSubjectId));
+ // 2. 拼接 VO
+ return BeanUtils.toBean(list, MesDvRepairLineRespVO.class, vo ->
+ MapUtils.findAndThen(subjectMap, vo.getSubjectId(), subject -> vo
+ .setSubjectName(subject.getName()).setSubjectContent(subject.getContent())
+ .setSubjectStandard(subject.getStandard())));
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairConfirmReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairConfirmReqVO.java
new file mode 100644
index 0000000..c707ef4
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairConfirmReqVO.java
@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import jakarta.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 维修工单确认完成 Request VO")
+@Data
+public class MesDvRepairConfirmReqVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @NotNull(message = "维修工单编号不能为空")
+ private Long id;
+
+ @Schema(description = "维修完成日期", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "维修完成日期不能为空")
+ private LocalDateTime finishDate;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairPageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairPageReqVO.java
new file mode 100644
index 0000000..9c1dc53
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairPageReqVO.java
@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - MES 维修工单分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MesDvRepairPageReqVO extends PageParam {
+
+ @Schema(description = "维修工单编码", example = "REP2024001")
+ private String code;
+
+ @Schema(description = "维修工单名称", example = "注塑机维修")
+ private String name;
+
+ @Schema(description = "设备编号", example = "1")
+ private Long machineryId;
+
+ @Schema(description = "维修结果", example = "1")
+ private Integer result;
+
+ @Schema(description = "状态", example = "10")
+ private Integer status;
+
+ @Schema(description = "报修日期")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] requireDate;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairRespVO.java
new file mode 100644
index 0000000..4833808
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairRespVO.java
@@ -0,0 +1,102 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo;
+
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+import cn.iocoder.yudao.module.mes.enums.DictTypeConstants;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 维修工单 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class MesDvRepairRespVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @ExcelProperty("编号")
+ private Long id;
+
+ @Schema(description = "维修工单编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "REP2024001")
+ @ExcelProperty("维修工单编码")
+ private String code;
+
+ @Schema(description = "维修工单名称", example = "注塑机液压系统维修")
+ @ExcelProperty("维修工单名称")
+ private String name;
+
+ @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long machineryId;
+
+ @Schema(description = "设备编码", example = "M001")
+ @ExcelProperty("设备编码")
+ private String machineryCode;
+
+ @Schema(description = "设备名称", example = "注塑机")
+ @ExcelProperty("设备名称")
+ private String machineryName;
+
+ @Schema(description = "品牌", example = "西门子")
+ @ExcelProperty("品牌")
+ private String machineryBrand;
+
+ @Schema(description = "规格型号", example = "X-100")
+ @ExcelProperty("规格型号")
+ private String machinerySpec;
+
+ @Schema(description = "报修日期")
+ @ExcelProperty("报修日期")
+ private LocalDateTime requireDate;
+
+ @Schema(description = "维修完成日期")
+ @ExcelProperty("维修完成日期")
+ private LocalDateTime finishDate;
+
+ @Schema(description = "验收日期")
+ @ExcelProperty("验收日期")
+ private LocalDateTime confirmDate;
+
+ @Schema(description = "维修结果", example = "1")
+ @ExcelProperty(value = "维修结果", converter = DictConvert.class)
+ @DictFormat(DictTypeConstants.MES_DV_REPAIR_RESULT)
+ private Integer result;
+
+ @Schema(description = "维修人用户编号", example = "1")
+ private Long acceptedUserId;
+
+ @Schema(description = "维修人名称", example = "张三")
+ @ExcelProperty("维修人")
+ private String acceptedUserNickname;
+
+ @Schema(description = "验收人用户编号", example = "1")
+ private Long confirmUserId;
+
+ @Schema(description = "验收人名称", example = "李四")
+ @ExcelProperty("验收人")
+ private String confirmUserNickname;
+
+ @Schema(description = "来源单据类型", example = "1")
+ private Integer sourceDocType;
+
+ @Schema(description = "来源单据编号", example = "1")
+ private Long sourceDocId;
+
+ @Schema(description = "来源单据编码", example = "DOC001")
+ private String sourceDocCode;
+
+ @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
+ @ExcelProperty(value = "状态", converter = DictConvert.class)
+ @DictFormat(DictTypeConstants.MES_DV_REPAIR_STATUS)
+ private Integer status;
+
+ @Schema(description = "备注", example = "测试备注")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairSaveReqVO.java
new file mode 100644
index 0000000..d841153
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairSaveReqVO.java
@@ -0,0 +1,60 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 维修工单新增/修改 Request VO")
+@Data
+public class MesDvRepairSaveReqVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1024")
+ private Long id;
+
+ @Schema(description = "维修工单编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "REP2024001")
+ @NotBlank(message = "维修工单编码不能为空")
+ private String code;
+
+ @Schema(description = "维修工单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "注塑机液压系统维修")
+ @NotBlank(message = "维修工单名称不能为空")
+ private String name;
+
+ @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "设备不能为空")
+ private Long machineryId;
+
+ @Schema(description = "报修日期", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "报修日期不能为空")
+ private LocalDateTime requireDate;
+
+ @Schema(description = "维修完成日期")
+ private LocalDateTime finishDate;
+
+ @Schema(description = "验收日期")
+ private LocalDateTime confirmDate;
+
+ @Schema(description = "维修结果", example = "1")
+ private Integer result;
+
+ @Schema(description = "维修人用户编号", example = "1")
+ private Long acceptedUserId;
+
+ @Schema(description = "验收人用户编号", example = "1")
+ private Long confirmUserId;
+
+ @Schema(description = "来源单据类型", example = "1")
+ private Integer sourceDocType;
+
+ @Schema(description = "来源单据编号", example = "1")
+ private Long sourceDocId;
+
+ @Schema(description = "来源单据编码", example = "DOC001")
+ private String sourceDocCode;
+
+ @Schema(description = "备注", example = "测试备注")
+ private String remark;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLinePageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLinePageReqVO.java
new file mode 100644
index 0000000..759fece
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLinePageReqVO.java
@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.line;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@Schema(description = "管理后台 - MES 维修工单行分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MesDvRepairLinePageReqVO extends PageParam {
+
+ @Schema(description = "维修工单编号", example = "1")
+ private Long repairId;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLineRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLineRespVO.java
new file mode 100644
index 0000000..3adcda5
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLineRespVO.java
@@ -0,0 +1,56 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.line;
+
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 维修工单行 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class MesDvRepairLineRespVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @ExcelProperty("编号")
+ private Long id;
+
+ @Schema(description = "维修工单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long repairId;
+
+ @Schema(description = "点检保养项目编号", example = "1")
+ private Long subjectId;
+
+ @Schema(description = "项目名称", example = "检查机油")
+ @ExcelProperty("项目名称")
+ private String subjectName;
+
+ @Schema(description = "项目内容", example = "检查机油是否充足")
+ @ExcelProperty("项目内容")
+ private String subjectContent;
+
+ @Schema(description = "项目标准", example = "无漏油")
+ @ExcelProperty("标准")
+ private String subjectStandard;
+
+ @Schema(description = "故障描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "液压系统漏油")
+ @ExcelProperty("故障描述")
+ private String malfunction;
+
+ @Schema(description = "故障图片 URL", example = "https://example.com/image.png")
+ private String malfunctionUrl;
+
+ @Schema(description = "维修描述", example = "更换密封圈")
+ @ExcelProperty("维修描述")
+ private String description;
+
+ @Schema(description = "备注", example = "测试备注")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLineSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLineSaveReqVO.java
new file mode 100644
index 0000000..75c73c8
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLineSaveReqVO.java
@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.line;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+
+@Schema(description = "管理后台 - MES 维修工单行新增/修改 Request VO")
+@Data
+public class MesDvRepairLineSaveReqVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1024")
+ private Long id;
+
+ @Schema(description = "维修工单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "维修工单不能为空")
+ private Long repairId;
+
+ @Schema(description = "点检保养项目编号", example = "1")
+ private Long subjectId;
+
+ @Schema(description = "故障描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "液压系统漏油")
+ @NotBlank(message = "故障描述不能为空")
+ private String malfunction;
+
+ @Schema(description = "故障图片 URL", example = "https://example.com/image.png")
+ private String malfunctionUrl;
+
+ @Schema(description = "维修描述", example = "更换密封圈")
+ private String description;
+
+ @Schema(description = "备注", example = "测试备注")
+ private String remark;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/MesDvSubjectController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/MesDvSubjectController.java
new file mode 100644
index 0000000..c18d7f9
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/MesDvSubjectController.java
@@ -0,0 +1,101 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.subject;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.subject.vo.MesDvSubjectPageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.subject.vo.MesDvSubjectRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.dv.subject.vo.MesDvSubjectSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dv.subject.MesDvSubjectDO;
+import cn.iocoder.yudao.module.mes.service.dv.subject.MesDvSubjectService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - MES 点检保养项目")
+@RestController
+@RequestMapping("/mes/dv/subject")
+@Validated
+public class MesDvSubjectController {
+
+ @Resource
+ private MesDvSubjectService subjectService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建点检保养项目")
+ @PreAuthorize("@ss.hasPermission('mes:dv-subject:create')")
+ public CommonResult createSubject(@Valid @RequestBody MesDvSubjectSaveReqVO createReqVO) {
+ return success(subjectService.createSubject(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新点检保养项目")
+ @PreAuthorize("@ss.hasPermission('mes:dv-subject:update')")
+ public CommonResult updateSubject(@Valid @RequestBody MesDvSubjectSaveReqVO updateReqVO) {
+ subjectService.updateSubject(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除点检保养项目")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:dv-subject:delete')")
+ public CommonResult deleteSubject(@RequestParam("id") Long id) {
+ subjectService.deleteSubject(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得点检保养项目")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:dv-subject:query')")
+ public CommonResult getSubject(@RequestParam("id") Long id) {
+ MesDvSubjectDO subject = subjectService.getSubject(id);
+ return success(BeanUtils.toBean(subject, MesDvSubjectRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得点检保养项目分页")
+ @PreAuthorize("@ss.hasPermission('mes:dv-subject:query')")
+ public CommonResult> getSubjectPage(@Valid MesDvSubjectPageReqVO pageReqVO) {
+ PageResult pageResult = subjectService.getSubjectPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, MesDvSubjectRespVO.class));
+ }
+
+ @GetMapping("/simple-list")
+ @Operation(summary = "获得点检保养项目精简列表", description = "主要用于前端的下拉选项")
+ @PreAuthorize("@ss.hasPermission('mes:dv-subject:query')")
+ public CommonResult> getSubjectSimpleList() {
+ List list = subjectService.getSubjectList();
+ return success(BeanUtils.toBean(list, MesDvSubjectRespVO.class));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出点检保养项目 Excel")
+ @PreAuthorize("@ss.hasPermission('mes:dv-subject:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportSubjectExcel(@Valid MesDvSubjectPageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = subjectService.getSubjectPage(pageReqVO).getList();
+ // 导出 Excel
+ ExcelUtils.write(response, "点检保养项目.xls", "数据", MesDvSubjectRespVO.class,
+ BeanUtils.toBean(list, MesDvSubjectRespVO.class));
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectPageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectPageReqVO.java
new file mode 100644
index 0000000..73495d9
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectPageReqVO.java
@@ -0,0 +1,27 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.subject.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@Schema(description = "管理后台 - MES 点检保养项目分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MesDvSubjectPageReqVO extends PageParam {
+
+ @Schema(description = "项目编码", example = "CHK001")
+ private String code;
+
+ @Schema(description = "项目名称", example = "注塑机外观检查")
+ private String name;
+
+ @Schema(description = "项目类型", example = "1")
+ private Integer type;
+
+ @Schema(description = "状态", example = "0")
+ private Integer status;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectRespVO.java
new file mode 100644
index 0000000..03b04ed
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectRespVO.java
@@ -0,0 +1,56 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.subject.vo;
+
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+import cn.iocoder.yudao.module.mes.enums.DictTypeConstants;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 点检保养项目 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class MesDvSubjectRespVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @ExcelProperty("编号")
+ private Long id;
+
+ @Schema(description = "项目编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "CHK001")
+ @ExcelProperty("项目编码")
+ private String code;
+
+ @Schema(description = "项目名称", example = "注塑机外观检查")
+ @ExcelProperty("项目名称")
+ private String name;
+
+ @Schema(description = "项目类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @ExcelProperty(value = "项目类型", converter = DictConvert.class)
+ @DictFormat(DictTypeConstants.MES_DV_SUBJECT_TYPE)
+ private Integer type;
+
+ @Schema(description = "项目内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "检查注塑机外壳是否有裂纹")
+ @ExcelProperty("项目内容")
+ private String content;
+
+ @Schema(description = "标准", example = "外观完好,无明显损伤")
+ @ExcelProperty("标准")
+ private String standard;
+
+ @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+ @ExcelProperty(value = "状态", converter = DictConvert.class)
+ @DictFormat("common_status")
+ private Integer status;
+
+ @Schema(description = "备注", example = "备注")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectSaveReqVO.java
new file mode 100644
index 0000000..93644f5
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectSaveReqVO.java
@@ -0,0 +1,40 @@
+package cn.iocoder.yudao.module.mes.controller.admin.dv.subject.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - MES 点检保养项目新增/修改 Request VO")
+@Data
+public class MesDvSubjectSaveReqVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ private Long id;
+
+ @Schema(description = "项目编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "CHK001")
+ @NotEmpty(message = "项目编码不能为空")
+ private String code;
+
+ @Schema(description = "项目名称", example = "注塑机外观检查")
+ private String name;
+
+ @Schema(description = "项目类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "项目类型不能为空")
+ private Integer type;
+
+ @Schema(description = "项目内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "检查注塑机外壳是否有裂纹")
+ @NotEmpty(message = "项目内容不能为空")
+ private String content;
+
+ @Schema(description = "标准", example = "外观完好,无明显损伤")
+ private String standard;
+
+ @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+ @NotNull(message = "状态不能为空")
+ private Integer status;
+
+ @Schema(description = "备注", example = "备注")
+ private String remark;
+
+ }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/MesHomeStatisticsController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/MesHomeStatisticsController.java
new file mode 100644
index 0000000..37bbdeb
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/MesHomeStatisticsController.java
@@ -0,0 +1,57 @@
+package cn.iocoder.yudao.module.mes.controller.admin.home;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.module.mes.controller.admin.home.vo.MesHomeProductionTrendRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.home.vo.MesHomeSummaryRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.home.vo.MesHomeWorkOrderStatusRespVO;
+import cn.iocoder.yudao.module.mes.service.home.MesHomeStatisticsService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.constraints.Max;
+import jakarta.validation.constraints.Min;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - MES 首页统计")
+@RestController
+@RequestMapping("/mes/home-statistics")
+@Validated
+public class MesHomeStatisticsController {
+
+ @Resource
+ private MesHomeStatisticsService homeStatisticsService;
+
+ @GetMapping("/summary")
+ @Operation(summary = "获得首页汇总统计")
+ @PreAuthorize("@ss.hasPermission('mes:home:query')")
+ public CommonResult getHomeSummary() {
+ return success(homeStatisticsService.getHomeSummary());
+ }
+
+ @GetMapping("/work-order-status")
+ @Operation(summary = "获得工单状态分布")
+ @PreAuthorize("@ss.hasPermission('mes:home:query')")
+ public CommonResult> getWorkOrderStatusDistribution() {
+ return success(homeStatisticsService.getWorkOrderStatusDistribution());
+ }
+
+ @GetMapping("/production-trend")
+ @Operation(summary = "获得生产趋势")
+ @Parameter(name = "days", description = "天数", example = "7")
+ @PreAuthorize("@ss.hasPermission('mes:home:query')")
+ public CommonResult> getProductionTrend(
+ @RequestParam(value = "days", defaultValue = "7") @Min(1) @Max(90) Integer days) {
+ return success(homeStatisticsService.getProductionTrend(days));
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/vo/MesHomeProductionTrendRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/vo/MesHomeProductionTrendRespVO.java
new file mode 100644
index 0000000..dec50f5
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/vo/MesHomeProductionTrendRespVO.java
@@ -0,0 +1,28 @@
+package cn.iocoder.yudao.module.mes.controller.admin.home.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+@Schema(description = "管理后台 - MES 首页生产趋势 Response VO")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class MesHomeProductionTrendRespVO {
+
+ @Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-04-05")
+ private String date;
+
+ @Schema(description = "产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1234")
+ private BigDecimal quantity;
+
+ @Schema(description = "合格品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1200")
+ private BigDecimal qualifiedQuantity;
+
+ @Schema(description = "不良品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "34")
+ private BigDecimal unqualifiedQuantity;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/vo/MesHomeSummaryRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/vo/MesHomeSummaryRespVO.java
new file mode 100644
index 0000000..4a36bb1
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/vo/MesHomeSummaryRespVO.java
@@ -0,0 +1,61 @@
+package cn.iocoder.yudao.module.mes.controller.admin.home.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Schema(description = "管理后台 - MES 首页汇总统计 Response VO")
+@Data
+public class MesHomeSummaryRespVO {
+
+ // ========== 工单统计 ==========
+
+ @Schema(description = "进行中工单数", requiredMode = Schema.RequiredMode.REQUIRED, example = "12")
+ private Long workOrderActiveCount;
+
+ @Schema(description = "待排产工单数(草稿)", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
+ private Long workOrderPrepareCount;
+
+ @Schema(description = "已完成工单数", requiredMode = Schema.RequiredMode.REQUIRED, example = "30")
+ private Long workOrderFinishedCount;
+
+ // ========== 产量统计 ==========
+
+ @Schema(description = "今日报工总产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1234")
+ private BigDecimal todayOutput;
+
+ @Schema(description = "昨日报工总产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1100")
+ private BigDecimal yesterdayOutput;
+
+ // ========== 质量统计 ==========
+
+ @Schema(description = "今日合格品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1200")
+ private BigDecimal todayQualifiedQuantity;
+
+ @Schema(description = "今日不良品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "34")
+ private BigDecimal todayUnqualifiedQuantity;
+
+ // ========== 设备统计 ==========
+
+ @Schema(description = "设备总数", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
+ private Long machineryTotal;
+
+ @Schema(description = "运行中设备数", requiredMode = Schema.RequiredMode.REQUIRED, example = "15")
+ private Long machineryProducing;
+
+ @Schema(description = "停机设备数", requiredMode = Schema.RequiredMode.REQUIRED, example = "3")
+ private Long machineryStop;
+
+ @Schema(description = "维护中设备数", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+ private Long machineryMaintenance;
+
+ // ========== 异常/待办统计 ==========
+
+ @Schema(description = "未处置安灯报警数", requiredMode = Schema.RequiredMode.REQUIRED, example = "3")
+ private Long andonActiveCount;
+
+ @Schema(description = "未完成维修工单数", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+ private Long repairActiveCount;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/vo/MesHomeWorkOrderStatusRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/vo/MesHomeWorkOrderStatusRespVO.java
new file mode 100644
index 0000000..e2b7307
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/vo/MesHomeWorkOrderStatusRespVO.java
@@ -0,0 +1,23 @@
+package cn.iocoder.yudao.module.mes.controller.admin.home.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Schema(description = "管理后台 - MES 首页工单状态分布 Response VO")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class MesHomeWorkOrderStatusRespVO {
+
+ @Schema(description = "状态值", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+ private Integer status;
+
+ @Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "草稿")
+ private String statusName;
+
+ @Schema(description = "工单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "12")
+ private Long count;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodePartController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodePartController.java
new file mode 100644
index 0000000..a38e5e2
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodePartController.java
@@ -0,0 +1,73 @@
+package cn.iocoder.yudao.module.mes.controller.admin.md.autocode;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.part.MesMdAutoCodePartRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.part.MesMdAutoCodePartSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO;
+import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodePartService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - MES 编码规则组成")
+@RestController
+@RequestMapping("/mes/md/auto-code-part")
+@Validated
+public class MesMdAutoCodePartController {
+
+ @Resource
+ private MesMdAutoCodePartService partService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建规则组成")
+ @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:update')")
+ public CommonResult createAutoCodePart(@Valid @RequestBody MesMdAutoCodePartSaveReqVO createReqVO) {
+ return success(partService.createAutoCodePart(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新规则组成")
+ @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:update')")
+ public CommonResult updateAutoCodePart(@Valid @RequestBody MesMdAutoCodePartSaveReqVO updateReqVO) {
+ partService.updateAutoCodePart(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除规则组成")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:update')")
+ public CommonResult deleteAutoCodePart(@RequestParam("id") Long id) {
+ partService.deleteAutoCodePart(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得规则组成")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:query')")
+ public CommonResult getAutoCodePart(@RequestParam("id") Long id) {
+ MesMdAutoCodePartDO part = partService.getAutoCodePart(id);
+ return success(BeanUtils.toBean(part, MesMdAutoCodePartRespVO.class));
+ }
+
+ @GetMapping("/list-by-rule-id")
+ @Operation(summary = "根据规则 ID 获得规则组成列表")
+ @Parameter(name = "ruleId", description = "规则 ID", required = true, example = "1")
+ @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:query')")
+ public CommonResult> getAutoCodePartListByRuleId(@RequestParam("ruleId") Long ruleId) {
+ List list = partService.getAutoCodePartListByRuleId(ruleId);
+ return success(BeanUtils.toBean(list, MesMdAutoCodePartRespVO.class));
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodeRecordController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodeRecordController.java
new file mode 100644
index 0000000..aef637c
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodeRecordController.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.mes.controller.admin.md.autocode;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.record.MesMdAutoCodeGenerateReqVO;
+import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - MES 编码生成记录")
+@RestController
+@RequestMapping("/mes/md/auto-code-record")
+@Validated
+public class MesMdAutoCodeRecordController {
+
+ @Resource
+ private MesMdAutoCodeRecordService autoCodeRecordService;
+
+ @PostMapping("/generate")
+ @Operation(summary = "生成编码")
+ @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:query')")
+ public CommonResult generateAutoCode(@Valid @RequestBody MesMdAutoCodeGenerateReqVO generateReqVO) {
+ String code = autoCodeRecordService.generateAutoCode(generateReqVO.getRuleCode(), generateReqVO.getInputChar());
+ return success(code);
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodeRuleController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodeRuleController.java
new file mode 100644
index 0000000..2194104
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodeRuleController.java
@@ -0,0 +1,102 @@
+package cn.iocoder.yudao.module.mes.controller.admin.md.autocode;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule.MesMdAutoCodeRulePageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule.MesMdAutoCodeRuleRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule.MesMdAutoCodeRuleSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRuleDO;
+import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRuleService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
+
+@Tag(name = "管理后台 - MES 编码规则")
+@RestController
+@RequestMapping("/mes/md/auto-code-rule")
+@Validated
+public class MesMdAutoCodeRuleController {
+
+ @Resource
+ private MesMdAutoCodeRuleService ruleService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建编码规则")
+ @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:create')")
+ public CommonResult createAutoCodeRule(@Valid @RequestBody MesMdAutoCodeRuleSaveReqVO createReqVO) {
+ return success(ruleService.createAutoCodeRule(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新编码规则")
+ @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:update')")
+ public CommonResult updateAutoCodeRule(@Valid @RequestBody MesMdAutoCodeRuleSaveReqVO updateReqVO) {
+ ruleService.updateAutoCodeRule(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除编码规则")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:delete')")
+ public CommonResult deleteAutoCodeRule(@RequestParam("id") Long id) {
+ ruleService.deleteAutoCodeRule(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得编码规则")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:query')")
+ public CommonResult getAutoCodeRule(@RequestParam("id") Long id) {
+ MesMdAutoCodeRuleDO rule = ruleService.getAutoCodeRule(id);
+ return success(BeanUtils.toBean(rule, MesMdAutoCodeRuleRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得编码规则分页")
+ @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:query')")
+ public CommonResult> getAutoCodeRulePage(@Valid MesMdAutoCodeRulePageReqVO pageReqVO) {
+ PageResult pageResult = ruleService.getAutoCodeRulePage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, MesMdAutoCodeRuleRespVO.class));
+ }
+
+ @GetMapping("/simple-list")
+ @Operation(summary = "获得编码规则精简列表", description = "只包含被开启的编码规则,主要用于前端的下拉选项")
+ public CommonResult> getAutoCodeRuleSimpleList() {
+ List list = ruleService.getAutoCodeRuleListByStatus(CommonStatusEnum.ENABLE.getStatus());
+ return success(convertList(list, rule -> new MesMdAutoCodeRuleRespVO()
+ .setId(rule.getId()).setName(rule.getName()).setCode(rule.getCode())));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出编码规则 Excel")
+ @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportAutoCodeRuleExcel(@Valid MesMdAutoCodeRulePageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = ruleService.getAutoCodeRulePage(pageReqVO).getList();
+ List data = BeanUtils.toBean(list, MesMdAutoCodeRuleRespVO.class);
+ ExcelUtils.write(response, "编码规则.xls", "数据", MesMdAutoCodeRuleRespVO.class, data);
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartRespVO.java
new file mode 100644
index 0000000..a184bc2
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartRespVO.java
@@ -0,0 +1,71 @@
+package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.part;
+
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 编码规则组成 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class MesMdAutoCodePartRespVO {
+
+ @Schema(description = "分段 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @ExcelProperty("分段 ID")
+ private Long id;
+
+ @Schema(description = "规则 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @ExcelProperty("规则 ID")
+ private Long ruleId;
+
+ @Schema(description = "分段序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @ExcelProperty("分段序号")
+ private Integer sort;
+
+ @Schema(description = "分段类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @ExcelProperty(value = "分段类型", converter = DictConvert.class)
+ @DictFormat("mes_auto_code_part_type")
+ private Integer type;
+
+ @Schema(description = "分段长度", requiredMode = Schema.RequiredMode.REQUIRED, example = "4")
+ @ExcelProperty("分段长度")
+ private Integer length;
+
+ @Schema(description = "日期格式", example = "yyyyMMdd")
+ @ExcelProperty("日期格式")
+ private String dateFormat;
+
+ @Schema(description = "固定字符", example = "ITEM_")
+ @ExcelProperty("固定字符")
+ private String fixCharacter;
+
+ @Schema(description = "流水号起始值", example = "1")
+ @ExcelProperty("流水号起始值")
+ private Integer serialStartNo;
+
+ @Schema(description = "流水号步长", example = "1")
+ @ExcelProperty("流水号步长")
+ private Integer serialStep;
+
+ @Schema(description = "流水号是否循环", example = "true")
+ @ExcelProperty("流水号是否循环")
+ private Boolean cycleFlag;
+
+ @Schema(description = "循环方式", example = "3")
+ @ExcelProperty(value = "循环方式", converter = DictConvert.class)
+ @DictFormat("mes_auto_code_cycle_method")
+ private Integer cycleMethod;
+
+ @Schema(description = "备注", example = "备注")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartSaveReqVO.java
new file mode 100644
index 0000000..d1c6502
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartSaveReqVO.java
@@ -0,0 +1,51 @@
+package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.part;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - MES 编码规则组成新增/修改 Request VO")
+@Data
+public class MesMdAutoCodePartSaveReqVO {
+
+ @Schema(description = "分段 ID", example = "1024")
+ private Long id;
+
+ @Schema(description = "规则 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "规则 ID 不能为空")
+ private Long ruleId;
+
+ @Schema(description = "分段序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "分段序号不能为空")
+ private Integer sort;
+
+ @Schema(description = "分段类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "分段类型不能为空")
+ private Integer type;
+
+ @Schema(description = "分段长度", requiredMode = Schema.RequiredMode.REQUIRED, example = "4")
+ @NotNull(message = "分段长度不能为空")
+ private Integer length;
+
+ @Schema(description = "日期格式", example = "yyyyMMdd")
+ private String dateFormat;
+
+ @Schema(description = "固定字符", example = "ITEM_")
+ private String fixCharacter;
+
+ @Schema(description = "流水号起始值", example = "1")
+ private Integer serialStartNo;
+
+ @Schema(description = "流水号步长", example = "1")
+ private Integer serialStep;
+
+ @Schema(description = "流水号是否循环", example = "true")
+ private Boolean cycleFlag;
+
+ @Schema(description = "循环方式", example = "3")
+ private Integer cycleMethod;
+
+ @Schema(description = "备注", example = "备注")
+ private String remark;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/record/MesMdAutoCodeGenerateReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/record/MesMdAutoCodeGenerateReqVO.java
new file mode 100644
index 0000000..4c808d4
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/record/MesMdAutoCodeGenerateReqVO.java
@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.record;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import lombok.Data;
+
+@Schema(description = "管理后台 - MES 编码生成 Request VO")
+@Data
+public class MesMdAutoCodeGenerateReqVO {
+
+ @Schema(description = "规则编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM_CODE")
+ @NotEmpty(message = "规则编码不能为空")
+ private String ruleCode;
+
+ @Schema(description = "输入字符", example = "A")
+ private String inputChar;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRulePageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRulePageReqVO.java
new file mode 100644
index 0000000..6c5a0a4
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRulePageReqVO.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - MES 编码规则分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MesMdAutoCodeRulePageReqVO extends PageParam {
+
+ @Schema(description = "规则编码", example = "ITEM_CODE")
+ private String code;
+
+ @Schema(description = "规则名称", example = "物料编码规则")
+ private String name;
+
+ @Schema(description = "状态", example = "0")
+ private Integer status;
+
+ @Schema(description = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleRespVO.java
new file mode 100644
index 0000000..5c69f74
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleRespVO.java
@@ -0,0 +1,64 @@
+package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule;
+
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 编码规则 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class MesMdAutoCodeRuleRespVO {
+
+ @Schema(description = "规则 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @ExcelProperty("规则 ID")
+ private Long id;
+
+ @Schema(description = "规则编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM_CODE")
+ @ExcelProperty("规则编码")
+ private String code;
+
+ @Schema(description = "规则名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "物料编码规则")
+ @ExcelProperty("规则名称")
+ private String name;
+
+ @Schema(description = "描述", example = "用于生成物料编码")
+ @ExcelProperty("描述")
+ private String description;
+
+ @Schema(description = "最大长度", example = "20")
+ @ExcelProperty("最大长度")
+ private Integer maxLength;
+
+ @Schema(description = "是否补齐", example = "true")
+ @ExcelProperty("是否补齐")
+ private Boolean padded;
+
+ @Schema(description = "补齐字符", example = "0")
+ @ExcelProperty("补齐字符")
+ private String paddedChar;
+
+ @Schema(description = "补齐方式", example = "1")
+ @ExcelProperty(value = "补齐方式", converter = DictConvert.class)
+ @DictFormat("mes_auto_code_padded_method")
+ private Integer paddedMethod;
+
+ @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+ @ExcelProperty(value = "状态", converter = DictConvert.class)
+ @DictFormat(DictTypeConstants.COMMON_STATUS)
+ private Integer status;
+
+ @Schema(description = "备注", example = "备注")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleSaveReqVO.java
new file mode 100644
index 0000000..fd9b769
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleSaveReqVO.java
@@ -0,0 +1,45 @@
+package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - MES 编码规则新增/修改 Request VO")
+@Data
+public class MesMdAutoCodeRuleSaveReqVO {
+
+ @Schema(description = "规则 ID", example = "1024")
+ private Long id;
+
+ @Schema(description = "规则编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM_CODE")
+ @NotEmpty(message = "规则编码不能为空")
+ private String code;
+
+ @Schema(description = "规则名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "物料编码规则")
+ @NotEmpty(message = "规则名称不能为空")
+ private String name;
+
+ @Schema(description = "描述", example = "用于生成物料编码")
+ private String description;
+
+ @Schema(description = "最大长度", example = "20")
+ private Integer maxLength;
+
+ @Schema(description = "是否补齐", example = "true")
+ private Boolean padded;
+
+ @Schema(description = "补齐字符", example = "0")
+ private String paddedChar;
+
+ @Schema(description = "补齐方式", example = "1")
+ private Integer paddedMethod;
+
+ @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+ @NotNull(message = "状态不能为空")
+ private Integer status;
+
+ @Schema(description = "备注", example = "备注")
+ private String remark;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/MesMdClientController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/MesMdClientController.java
new file mode 100644
index 0000000..95fd5c5
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/MesMdClientController.java
@@ -0,0 +1,126 @@
+package cn.iocoder.yudao.module.mes.controller.admin.md.client;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientImportExcelVO;
+import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientImportRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientPageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
+import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+
+@Tag(name = "管理后台 - MES 客户")
+@RestController
+@RequestMapping("/mes/md-client")
+@Validated
+public class MesMdClientController {
+
+ @Resource
+ private MesMdClientService clientService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建客户")
+ @PreAuthorize("@ss.hasPermission('mes:md-client:create')")
+ public CommonResult createClient(@Valid @RequestBody MesMdClientSaveReqVO createReqVO) {
+ return success(clientService.createClient(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新客户")
+ @PreAuthorize("@ss.hasPermission('mes:md-client:update')")
+ public CommonResult updateClient(@Valid @RequestBody MesMdClientSaveReqVO updateReqVO) {
+ clientService.updateClient(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除客户")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:md-client:delete')")
+ public CommonResult deleteClient(@RequestParam("id") Long id) {
+ clientService.deleteClient(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得客户")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:md-client:query')")
+ public CommonResult getClient(@RequestParam("id") Long id) {
+ MesMdClientDO client = clientService.getClient(id);
+ return success(BeanUtils.toBean(client, MesMdClientRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得客户分页")
+ @PreAuthorize("@ss.hasPermission('mes:md-client:query')")
+ public CommonResult> getClientPage(@Valid MesMdClientPageReqVO pageReqVO) {
+ PageResult pageResult = clientService.getClientPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, MesMdClientRespVO.class));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出客户 Excel")
+ @PreAuthorize("@ss.hasPermission('mes:md-client:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportClientExcel(@Valid MesMdClientPageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = clientService.getClientPage(pageReqVO).getList();
+ // 导出 Excel
+ ExcelUtils.write(response, "客户.xls", "数据", MesMdClientRespVO.class,
+ BeanUtils.toBean(list, MesMdClientRespVO.class));
+ }
+
+ @GetMapping("/get-import-template")
+ @Operation(summary = "获得客户导入模板")
+ public void importTemplate(HttpServletResponse response) throws IOException {
+ // 手动创建导出 demo
+ List list = Collections.singletonList(
+ MesMdClientImportExcelVO.builder().code("C001").name("示例客户").nickname("示例")
+ .type(1).telephone("13800138000").status(0).build()
+ );
+ // 输出
+ ExcelUtils.write(response, "客户导入模板.xls", "客户列表", MesMdClientImportExcelVO.class, list);
+ }
+
+ @PostMapping("/import")
+ @Operation(summary = "导入客户")
+ @Parameters({
+ @Parameter(name = "file", description = "Excel 文件", required = true),
+ @Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true")
+ })
+ @PreAuthorize("@ss.hasPermission('mes:md-client:import')")
+ public CommonResult importExcel(@RequestParam("file") MultipartFile file,
+ @RequestParam(value = "updateSupport", required = false,
+ defaultValue = "false") Boolean updateSupport) throws Exception {
+ List list = ExcelUtils.read(file, MesMdClientImportExcelVO.class);
+ return success(clientService.importClientList(list, updateSupport));
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportExcelVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportExcelVO.java
new file mode 100644
index 0000000..64f5c12
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportExcelVO.java
@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.module.mes.controller.admin.md.client.vo;
+
+import cn.idev.excel.annotation.ExcelProperty;
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+import cn.iocoder.yudao.module.mes.enums.DictTypeConstants;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 客户 Excel 导入 VO
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class MesMdClientImportExcelVO {
+
+ @ExcelProperty("客户编码")
+ private String code;
+
+ @ExcelProperty("客户名称")
+ private String name;
+
+ @ExcelProperty("客户简称")
+ private String nickname;
+
+ @ExcelProperty(value = "客户类型", converter = DictConvert.class)
+ @DictFormat(DictTypeConstants.MES_CLIENT_TYPE)
+ private Integer type;
+
+ @ExcelProperty("客户电话")
+ private String telephone;
+
+ @ExcelProperty("客户邮箱地址")
+ private String email;
+
+ @ExcelProperty(value = "状态", converter = DictConvert.class)
+ @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.COMMON_STATUS)
+ private Integer status;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportRespVO.java
new file mode 100644
index 0000000..7554dd0
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportRespVO.java
@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.mes.controller.admin.md.client.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+@Schema(description = "管理后台 - MES 客户导入 Response VO")
+@Data
+@Builder
+public class MesMdClientImportRespVO {
+
+ @Schema(description = "创建成功的客户编码数组", requiredMode = Schema.RequiredMode.REQUIRED)
+ private List createCodes;
+
+ @Schema(description = "更新成功的客户编码数组", requiredMode = Schema.RequiredMode.REQUIRED)
+ private List updateCodes;
+
+ @Schema(description = "导入失败的客户集合,key 为客户编码,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED)
+ private Map failureCodes;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientPageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientPageReqVO.java
new file mode 100644
index 0000000..a9c0e52
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientPageReqVO.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.mes.controller.admin.md.client.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@Schema(description = "管理后台 - MES 客户分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MesMdClientPageReqVO extends PageParam {
+
+ @Schema(description = "客户编码", example = "C00184")
+ private String code;
+
+ @Schema(description = "客户名称", example = "比亚迪")
+ private String name;
+
+ @Schema(description = "客户简称", example = "比亚迪")
+ private String nickname;
+
+ @Schema(description = "客户英文名称", example = "BYD")
+ private String englishName;
+
+ @Schema(description = "客户类型", example = "1")
+ private Integer type;
+
+ @Schema(description = "状态", example = "0")
+ private Integer status;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientRespVO.java
new file mode 100644
index 0000000..9ed58bb
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientRespVO.java
@@ -0,0 +1,107 @@
+package cn.iocoder.yudao.module.mes.controller.admin.md.client.vo;
+
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+import cn.iocoder.yudao.module.mes.enums.DictTypeConstants;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - MES 客户 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class MesMdClientRespVO {
+
+ @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @ExcelProperty("客户编号")
+ private Long id;
+
+ @Schema(description = "客户编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "C00184")
+ @ExcelProperty("客户编码")
+ private String code;
+
+ @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "比亚迪")
+ @ExcelProperty("客户名称")
+ private String name;
+
+ @Schema(description = "客户简称", example = "比亚迪")
+ @ExcelProperty("客户简称")
+ private String nickname;
+
+ @Schema(description = "客户英文名称", example = "BYD")
+ @ExcelProperty("客户英文名称")
+ private String englishName;
+
+ @Schema(description = "客户简介", example = "比亚迪品牌诞生于深圳")
+ @ExcelProperty("客户简介")
+ private String description;
+
+ @Schema(description = "客户LOGO地址", example = "https://xxx.com/logo.png")
+ private String logo;
+
+ @Schema(description = "客户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @ExcelProperty(value = "客户类型", converter = DictConvert.class)
+ @DictFormat(DictTypeConstants.MES_CLIENT_TYPE)
+ private Integer type;
+
+ @Schema(description = "客户地址", example = "深圳南山区")
+ @ExcelProperty("客户地址")
+ private String address;
+
+ @Schema(description = "客户官网地址", example = "https://www.bydglobal.com")
+ @ExcelProperty("客户官网地址")
+ private String website;
+
+ @Schema(description = "客户邮箱地址", example = "salse@bydglobal.com")
+ @ExcelProperty("客户邮箱地址")
+ private String email;
+
+ @Schema(description = "客户电话", example = "123432222")
+ @ExcelProperty("客户电话")
+ private String telephone;
+
+ @Schema(description = "联系人1", example = "张三")
+ @ExcelProperty("联系人1")
+ private String contact1Name;
+
+ @Schema(description = "联系人1-电话", example = "122212312")
+ @ExcelProperty("联系人1-电话")
+ private String contact1Telephone;
+
+ @Schema(description = "联系人1-邮箱", example = "s1@bydglobal.com")
+ @ExcelProperty("联系人1-邮箱")
+ private String contact1Email;
+
+ @Schema(description = "联系人2", example = "李四")
+ @ExcelProperty("联系人2")
+ private String contact2Name;
+
+ @Schema(description = "联系人2-电话", example = "1132323232")
+ @ExcelProperty("联系人2-电话")
+ private String contact2Telephone;
+
+ @Schema(description = "联系人2-邮箱", example = "s2@bydglobal.com")
+ @ExcelProperty("联系人2-邮箱")
+ private String contact2Email;
+
+ @Schema(description = "统一社会信用代码", example = "11212121")
+ @ExcelProperty("统一社会信用代码")
+ private String creditCode;
+
+ @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+ @ExcelProperty(value = "状态", converter = DictConvert.class)
+ @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.COMMON_STATUS)
+ private Integer status;
+
+ @Schema(description = "备注", example = "备注")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientSaveReqVO.java
new file mode 100644
index 0000000..1e75183
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientSaveReqVO.java
@@ -0,0 +1,79 @@
+package cn.iocoder.yudao.module.mes.controller.admin.md.client.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - MES 客户新增/修改 Request VO")
+@Data
+public class MesMdClientSaveReqVO {
+
+ @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ private Long id;
+
+ @Schema(description = "客户编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "C00184")
+ @NotEmpty(message = "客户编码不能为空")
+ private String code;
+
+ @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "比亚迪")
+ @NotEmpty(message = "客户名称不能为空")
+ private String name;
+
+ @Schema(description = "客户简称", example = "比亚迪")
+ private String nickname;
+
+ @Schema(description = "客户英文名称", example = "BYD")
+ private String englishName;
+
+ @Schema(description = "客户简介", example = "比亚迪品牌诞生于深圳")
+ private String description;
+
+ @Schema(description = "客户LOGO地址", example = "https://xxx.com/logo.png")
+ private String logo;
+
+ @Schema(description = "客户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "客户类型不能为空")
+ private Integer type;
+
+ @Schema(description = "客户地址", example = "深圳南山区")
+ private String address;
+
+ @Schema(description = "客户官网地址", example = "https://www.bydglobal.com")
+ private String website;
+
+ @Schema(description = "客户邮箱地址", example = "salse@bydglobal.com")
+ private String email;
+
+ @Schema(description = "客户电话", example = "123432222")
+ private String telephone;
+
+ @Schema(description = "联系人1", example = "张三")
+ private String contact1Name;
+
+ @Schema(description = "联系人1-电话", example = "122212312")
+ private String contact1Telephone;
+
+ @Schema(description = "联系人1-邮箱", example = "s1@bydglobal.com")
+ private String contact1Email;
+
+ @Schema(description = "联系人2", example = "李四")
+ private String contact2Name;
+
+ @Schema(description = "联系人2-电话", example = "1132323232")
+ private String contact2Telephone;
+
+ @Schema(description = "联系人2-邮箱", example = "s2@bydglobal.com")
+ private String contact2Email;
+
+ @Schema(description = "统一社会信用代码", example = "11212121")
+ private String creditCode;
+
+ @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+ @NotNull(message = "状态不能为空")
+ private Integer status;
+
+ @Schema(description = "备注", example = "备注")
+ private String remark;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemBatchConfigController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemBatchConfigController.java
new file mode 100644
index 0000000..2e8586b
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemBatchConfigController.java
@@ -0,0 +1,46 @@
+package cn.iocoder.yudao.module.mes.controller.admin.md.item;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.batchconfig.MesMdItemBatchConfigRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.batchconfig.MesMdItemBatchConfigSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemBatchConfigDO;
+import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemBatchConfigService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - MES 物料批次属性配置")
+@RestController
+@RequestMapping("/mes/md/item-batch-config")
+@Validated
+public class MesMdItemBatchConfigController {
+
+ @Resource
+ private MesMdItemBatchConfigService itemBatchConfigService;
+
+ @GetMapping("/get-by-item-id")
+ @Operation(summary = "根据物料编号获取批次属性配置")
+ @Parameter(name = "itemId", description = "物料编号", required = true, example = "69")
+ @PreAuthorize("@ss.hasPermission('mes:md-item:query')")
+ public CommonResult getItemBatchConfigByItemId(
+ @RequestParam("itemId") Long itemId) {
+ MesMdItemBatchConfigDO config = itemBatchConfigService.getItemBatchConfigByItemId(itemId);
+ return success(BeanUtils.toBean(config, MesMdItemBatchConfigRespVO.class));
+ }
+
+ @PostMapping("/save")
+ @Operation(summary = "保存批次属性配置(新增或更新)")
+ @PreAuthorize("@ss.hasPermission('mes:md-item:update')")
+ public CommonResult saveItemBatchConfig(@Valid @RequestBody MesMdItemBatchConfigSaveReqVO saveReqVO) {
+ return success(itemBatchConfigService.saveItemBatchConfig(saveReqVO));
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemController.java
new file mode 100644
index 0000000..3a6b378
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemController.java
@@ -0,0 +1,179 @@
+package cn.iocoder.yudao.module.mes.controller.admin.md.item;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemImportExcelVO;
+import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemImportRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemPageReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemRespVO;
+import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemSaveReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
+import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
+import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemTypeService;
+import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+
+@Tag(name = "管理后台 - MES 物料产品")
+@RestController
+@RequestMapping("/mes/md/item")
+@Validated
+public class MesMdItemController {
+
+ @Resource
+ private MesMdItemService itemService;
+
+ @Resource
+ private MesMdItemTypeService itemTypeService;
+
+ @Resource
+ private MesMdUnitMeasureService unitMeasureService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建物料产品")
+ @PreAuthorize("@ss.hasPermission('mes:md-item:create')")
+ public CommonResult createItem(@Valid @RequestBody MesMdItemSaveReqVO createReqVO) {
+ return success(itemService.createItem(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新物料产品")
+ @PreAuthorize("@ss.hasPermission('mes:md-item:update')")
+ public CommonResult updateItem(@Valid @RequestBody MesMdItemSaveReqVO updateReqVO) {
+ itemService.updateItem(updateReqVO);
+ return success(true);
+ }
+
+ @PutMapping("/update-status")
+ @Operation(summary = "更新物料产品状态")
+ @Parameters({
+ @Parameter(name = "id", description = "编号", required = true),
+ @Parameter(name = "status", description = "状态", required = true)
+ })
+ @PreAuthorize("@ss.hasPermission('mes:md-item:update')")
+ public CommonResult updateItemStatus(@RequestParam("id") Long id,
+ @RequestParam("status") Integer status) {
+ itemService.updateItemStatus(id, status);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除物料产品")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:md-item:delete')")
+ public CommonResult deleteItem(@RequestParam("id") Long id) {
+ itemService.deleteItem(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得物料产品")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:md-item:query')")
+ public CommonResult getItem(@RequestParam("id") Long id) {
+ MesMdItemDO item = itemService.getItem(id);
+ return success(buildItemVO(item));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得物料产品分页")
+ @PreAuthorize("@ss.hasPermission('mes:md-item:query')")
+ public CommonResult> getItemPage(@Valid MesMdItemPageReqVO pageReqVO) {
+ PageResult pageResult = itemService.getItemPage(pageReqVO);
+ return success(new PageResult<>(buildItemVOList(pageResult.getList()), pageResult.getTotal()));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出物料产品 Excel")
+ @PreAuthorize("@ss.hasPermission('mes:md-item:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportItemExcel(@Valid MesMdItemPageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ PageResult pageResult = itemService.getItemPage(pageReqVO);
+ // 导出 Excel
+ ExcelUtils.write(response, "物料产品.xls", "数据", MesMdItemRespVO.class,
+ buildItemVOList(pageResult.getList()));
+ }
+
+ @GetMapping("/get-import-template")
+ @Operation(summary = "获得物料导入模板")
+ public void importTemplate(HttpServletResponse response) throws IOException {
+ // 手动创建导出 demo
+ List list = Collections.singletonList(
+ MesMdItemImportExcelVO.builder().code("ITEM001").name("螺丝").specification("M6*20")
+ .unitMeasureCode("PCS").itemTypeId(1L).status(0).build()
+ );
+ // 输出
+ ExcelUtils.write(response, "物料导入模板.xls", "物料列表", MesMdItemImportExcelVO.class, list);
+ }
+
+ @PostMapping("/import")
+ @Operation(summary = "导入物料")
+ @Parameters({
+ @Parameter(name = "file", description = "Excel 文件", required = true),
+ @Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true")
+ })
+ @PreAuthorize("@ss.hasPermission('mes:md-item:import')")
+ public CommonResult importExcel(@RequestParam("file") MultipartFile file,
+ @RequestParam(value = "updateSupport", required = false,
+ defaultValue = "false") Boolean updateSupport) throws Exception {
+ List list = ExcelUtils.read(file, MesMdItemImportExcelVO.class);
+ return success(itemService.importItemList(list, updateSupport));
+ }
+
+ // ==================== 拼接 VO ====================
+
+ private List