设备日历和运算

parent fee62722
......@@ -8,7 +8,7 @@
<version>2.7.18</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<groupId>com.aps</groupId>
<artifactId>java-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo2</name>
......@@ -73,16 +73,11 @@
<version>10.2.1.jre8</version>
</dependency>
<!-- Swagger -->
<!-- SpringDoc OpenAPI -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.7.0</version>
</dependency>
<dependency>
......@@ -120,8 +115,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>9</source>
<target>9</target>
<source>8</source>
<target>8</target>
<encoding>${project.build.sourceEncoding}</encoding>
<annotationProcessorPaths>
<path>
......
This diff is collapsed.
package com.example;
package com.aps;
import org.mybatis.spring.annotation.MapperScan;
......@@ -7,11 +7,11 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.example.mapper") // 扫描Mapper接口
public class Demo1Application {
@MapperScan("com.aps.mapper") // 扫描Mapper接口
public class ApsApplication {
public static void main(String[] args) {
SpringApplication.run(Demo1Application.class, args);
SpringApplication.run(ApsApplication.class, args);
}
}
}
\ No newline at end of file
package com.example;
package com.aps;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
......
package com.aps.common.util;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class FileHelper {
private static final String LOG_FILE_PATH = "schedule_log.txt";
public static void writeLogFile(String message) {
try (PrintWriter writer = new PrintWriter(new FileWriter(LOG_FILE_PATH, true))) {
String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
writer.println("[" + timestamp + "] " + message);
} catch (IOException e) {
System.err.println("Failed to write log: " + e.getMessage());
}
}
}
\ No newline at end of file
package com.aps.common.util;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Scanner;
public class JsonFileReader {
public static <T> List<T> readListFromResources(String fileName, Class<T> clazz) throws IOException {
// 1. 从classpath读取文件
try (InputStream inputStream = JsonFileReader.class.getClassLoader().getResourceAsStream(fileName)) {
if (inputStream == null) {
throw new IOException("File not found in resources: " + fileName);
}
// 使用Scanner替代readAllBytes以兼容Java 8
Scanner scanner = new Scanner(inputStream, StandardCharsets.UTF_8.name()).useDelimiter("\\A");
String jsonContent = scanner.hasNext() ? scanner.next() : "";
// 2. 配置ObjectMapper支持Java 8时间API
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// 3. 反序列化JSON到对象列表
return objectMapper.readValue(jsonContent,
objectMapper.getTypeFactory().constructCollectionType(List.class, clazz));
}
}
}
\ No newline at end of file
package com.aps.common.util;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
@Builder
@ToString
@Accessors(chain = true)
@AllArgsConstructor
public class R<T> implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "code码,通常为0为正常,500为异常,其它code码见异常对照表,为规范code码报错异常操作。所有异常报错码以数据表映射相关")
@Getter
@Setter
private int code = 0;
@Getter
@Setter
@Schema(description = "返回code码为0 时, 默认为success,其它的情况为具体的消息")
private String msg = "success";
@Getter
@Setter
@Schema(description = "业务返回具体的数据", example = "示例值有很多,不一一列举")
private T data;
@Getter
@Setter
@Schema(description = "接口返回时间,默认带有毫秒数值,用于数据排查问题")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss SSS")
private LocalDateTime timestamp = LocalDateTime.now();
public static <T> R<T> ok() {
return restResult(null, 0, "success");
}
public static <T> R<T> ok(T data) {
return restResult(data, 0, "success");
}
public static <T> R<T> ok(T data, String msg) {
return restResult(data, 0, msg);
}
public static <T> R<T> failed() {
return restResult(null, 1, "error");
}
public static <T> R<T> failed(String msg) {
return restResult(null, 1, msg);
}
public static <T> R<T> failed(T data) {
return restResult(data, 1, "error");
}
public static <T> R<T> failed(T data, String msg) {
return restResult(data, 1, msg);
}
public static <T> R<T> failed(int code, String msg) {
return restResult(null, code, msg);
}
public static <T> R<T> failed(T data, int code) {
return restResult(data, code, null);
}
public static <T> R<T> failed(T data, int code, String msg) {
return restResult(data, code, msg);
}
public R() {
super();
}
public R(T data) {
super();
this.data = data;
}
public R(T data, String msg) {
super();
this.data = data;
this.msg = msg;
}
public R(Throwable e) {
super();
this.msg = e.getMessage();
this.code = 1;
}
private static <T> R<T> restResult(T data, int code, String msg) {
R<T> apiResult = new R<>();
apiResult.setCode(code);
apiResult.setData(data);
apiResult.setMsg(msg);
return apiResult;
}
/**
* 判断是否成功
*
* @return
*/
public boolean is() {
return this.code == 0;
}
}
\ No newline at end of file
package com.aps.config;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.License;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("Demo2 API 文档")
.version("1.0.0")
.description("多数据库项目接口文档")
.contact(new Contact()
.name("APS Team")
.email("contact@example.com"))
.license(new License()
.name("Apache 2.0")
.url("http://www.apache.org/licenses/LICENSE-2.0.html")));
}
}
\ No newline at end of file
package com.example.controller;
package com.aps.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
......@@ -15,4 +15,4 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/department")
public class DepartmentController {
}
}
\ No newline at end of file
package com.example.controller;
package com.aps.controller;
import com.example.entity.MaterialInfo;
import com.example.service.MaterialInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import com.aps.entity.MaterialInfo;
import com.aps.service.MaterialInfoService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.List;
......@@ -20,19 +19,25 @@ import java.util.List;
*/
@RestController
@RequestMapping("/materialInfo")
@Api(tags = "测试接口")
@Tag(name = "test", description = "物料信息相关接口")
public class MaterialInfoController {
@Autowired
MaterialInfoService materialInfoService;
@ApiOperation(value = "获取物料列表", notes = "返回所有用物料据", httpMethod = "GET")
@RequestMapping("/test")
@Operation(summary = "获取单个物料信息", description = "返回第一个物料数据")
@GetMapping("/test")
public MaterialInfo test(){
List<MaterialInfo> list = materialInfoService.list();
// 检查列表是否为空,避免IndexOutOfBoundsException
if (list == null || list.isEmpty()) {
return null; // 自定义异常
}
return list.get(0);
}
}
}
\ No newline at end of file
package com.aps.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 班次表 前端控制器
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-10
*/
@RestController
@RequestMapping("/mesShiftWorkSched")
public class MesShiftWorkSchedController {
}
\ No newline at end of file
package com.aps.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 前端控制器
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-10
*/
@RestController
@RequestMapping("/planResource")
public class PlanResourceController {
}
\ No newline at end of file
package com.aps.controller;
import com.aps.entity.MaterialInfo;
import com.aps.entity.RoutingHeader;
import com.aps.service.MaterialInfoService;
import com.aps.service.RoutingHeaderService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* <p>
* 前端控制器
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-09
*/
@RestController
@RequestMapping("/routingHeader")
@Tag(name = "测试接口", description = "工艺相关接口")
public class RoutingHeaderController {
@Autowired
RoutingHeaderService routingHeaderService;
@Operation(summary = "获取工艺列表", description = "返回所有工艺数据")
@GetMapping("/test")
public RoutingHeader test(){
return routingHeaderService.list().get(0);
}
}
\ No newline at end of file
package com.aps.controller;
import com.aps.entity.*;
import com.aps.mapper.EquipinfoMapper;
import com.aps.mapper.MpsplannedorderMapper;
import com.aps.mapper.RoutingDetailMapper;
import com.aps.mapper.RoutingHeaderMapper;
import com.aps.service.*;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/schedule")
@Tag(name = "调度任务", description = "调度任务相关接口")
public class ScheduleController {
@Autowired
private ScheduleService schedulerService;
@Autowired
private MpsplannedorderService orderService;
@Autowired
private RoutingHeaderService processService;
@Autowired
private RoutingDetailService operationService;
@Autowired
private RoutingDetailEquipService operationEquipService;
@Autowired
private EquipinfoService equipmentService;
@GetMapping("/run")
public List<ScheduledTask> runScheduling() {
try {
// 获取routingid为'SY1102507-0056202车间-21号线'和'SY1102507-0060202车间-21号线'的待调度工单
List<Mpsplannedorder> orders = orderService.lambdaQuery()
.in(Mpsplannedorder::getRoutingid, "SY1102507-0056202车间-21号线", "SY1102507-0060202车间-21号线")
.list();
if (orders.isEmpty()) {
return new ArrayList<>();
}
// 提取所需的工艺ID列表
Set<String> routingIds = orders.stream()
.map(Mpsplannedorder::getRoutingid)
.collect(Collectors.toSet());
// 根据工单获取相关工艺
List<RoutingHeader> processes = processService.lambdaQuery()
.in(RoutingHeader::getCode, routingIds)
.list();
if (processes.isEmpty()) {
throw new RuntimeException("未找到相关工艺信息");
}
// 提取工艺ID用于后续查询
Set<Integer> processIds = processes.stream()
.map(RoutingHeader::getId)
.collect(Collectors.toSet());
// 根据工艺获取相关工序
List<RoutingDetail> operations = operationService.lambdaQuery()
.in(RoutingDetail::getRoutingHeaderId, processIds)
.orderByAsc(RoutingDetail::getTaskSeq)
.list();
if (operations.isEmpty()) {
throw new RuntimeException("未找到相关工序信息");
}
// 提取工序ID用于后续查询
Set<Integer> operationIds = operations.stream()
.map(RoutingDetail::getId)
.collect(Collectors.toSet());
// 获取相关工序设备关系
List<RoutingDetailEquip> operationEquipments = operationEquipService.lambdaQuery()
.in(RoutingDetailEquip::getRoutingDetailId, operationIds)
.list();
if (operationEquipments.isEmpty()) {
throw new RuntimeException("未找到工序设备关系信息");
}
// 提取设备ID用于后续查询
Set<Integer> equipmentIds = operationEquipments.stream()
.map(RoutingDetailEquip::getEquipId)
.collect(Collectors.toSet());
// 获取相关设备
List<Equipinfo> equipments = equipmentService.lambdaQuery()
.in(Equipinfo::getId, equipmentIds)
.list();
// 添加空值检查
if (orders == null || processes == null || operations == null || operationEquipments == null || equipments == null) {
throw new RuntimeException("获取调度数据失败,存在空数据");
}
List<ScheduledTask> result = schedulerService.scheduleOrders(
orders, processes, operations, operationEquipments, equipments);
return result;
} catch (Exception e) {
throw new RuntimeException("调度执行失败: " + e.getMessage(), e);
}
}
}
\ No newline at end of file
package com.aps.controller;
import com.aps.common.util.R;
import com.aps.entity.*;
import com.aps.entity.Gantt.PlanResourceTaskGanttVO;
import com.aps.entity.Gantt.SimpleEquipinfo;
import com.aps.service.*;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.beans.factory.annotation.Autowired;
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.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/ganttest")
@Tag(name = "甘特图", description = "甘特图相关接口")
public class ScheduleResultController {
@Autowired
private ScheduleService schedulerService;
@Autowired
private MpsplannedorderService orderService;
@Autowired
private RoutingHeaderService processService;
@Autowired
private RoutingDetailService operationService;
@Autowired
private RoutingDetailEquipService operationEquipService;
@Autowired
private EquipinfoService equipmentService;
@Operation(summary = "资源甘特图", description = "资源甘特图")
@GetMapping("/resource")
public R<PlanResourceTaskGanttVO> runScheduling() {
try {
// 获取routingid为'SY1102507-0056202车间-21号线'和'SY1102507-0060202车间-21号线'的待调度工单
List<Mpsplannedorder> orders = orderService.lambdaQuery()
.in(Mpsplannedorder::getRoutingid, "SY1102507-0056202车间-21号线", "SY1102507-0060202车间-21号线")
.list();
if (orders.isEmpty()) {
// 当没有订单时,返回空的甘特图VO
PlanResourceTaskGanttVO ganttVO = new PlanResourceTaskGanttVO()
.setTasks(new ArrayList<>())
.setResources(new ArrayList<>())
.setEarliestTaskStartTime(LocalDateTime.of(2025, 6, 1, 0, 0, 0))
.setLastTaskAssignmentTime(LocalDateTime.of(2025, 12, 1, 0, 0, 0));
return R.ok(ganttVO);
}
// 提取所需的工艺ID列表
Set<String> routingIds = orders.stream()
.map(Mpsplannedorder::getRoutingid)
.collect(Collectors.toSet());
// 根据工单获取相关工艺
List<RoutingHeader> processes = processService.lambdaQuery()
.in(RoutingHeader::getCode, routingIds)
.list();
if (processes.isEmpty()) {
return R.failed("未找到相关工艺信息");
}
// 提取工艺ID用于后续查询
Set<Integer> processIds = processes.stream()
.map(RoutingHeader::getId)
.collect(Collectors.toSet());
// 根据工艺获取相关工序
List<RoutingDetail> operations = operationService.lambdaQuery()
.in(RoutingDetail::getRoutingHeaderId, processIds)
.orderByAsc(RoutingDetail::getTaskSeq)
.list();
if (operations.isEmpty()) {
return R.failed("未找到相关工序信息");
}
// 提取工序ID用于后续查询
Set<Integer> operationIds = operations.stream()
.map(RoutingDetail::getId)
.collect(Collectors.toSet());
// 获取相关工序设备关系
List<RoutingDetailEquip> operationEquipments = operationEquipService.lambdaQuery()
.in(RoutingDetailEquip::getRoutingDetailId, operationIds)
.list();
if (operationEquipments.isEmpty()) {
return R.failed("未找到工序设备关系信息");
}
// 提取设备ID用于后续查询
Set<Integer> equipmentIds = operationEquipments.stream()
.map(RoutingDetailEquip::getEquipId)
.collect(Collectors.toSet());
// 获取相关设备
List<Equipinfo> equipments = equipmentService.lambdaQuery()
.in(Equipinfo::getId, equipmentIds)
.list();
// 添加空值检查
if (orders == null || processes == null || operations == null || operationEquipments == null || equipments == null) {
return R.failed("获取调度数据失败,存在空数据");
}
List<ScheduledTask> result = schedulerService.scheduleOrders(
orders, processes, operations, operationEquipments, equipments);
// 转换设备信息为简要信息,并关联相关任务
List<SimpleEquipinfo> simpleEquipinfos = equipments.stream()
.map(equip -> {
// 查找与该设备关联的任务
List<ScheduledTask> equipTasks = result.stream()
.filter(task -> task.getEquipId() != null && task.getEquipId().equals(equip.getId()))
.collect(Collectors.toList());
return new SimpleEquipinfo()
.setId(equip.getId())
.setEquipId(equip.getEquipId())
.setEquipName(equip.getEquipName())
.setTasks(equipTasks);
})
.collect(Collectors.toList());
// 设置甘特图VO的最早时间为2025年6月1日,最晚时间为2025年12月1日
PlanResourceTaskGanttVO ganttVO = new PlanResourceTaskGanttVO()
.setTasks(result)
.setResources(simpleEquipinfos)
.setEarliestTaskStartTime(LocalDateTime.of(2025, 6, 1, 0, 0, 0))
.setLastTaskAssignmentTime(LocalDateTime.of(2025, 12, 1, 0, 0, 0));
return R.ok(ganttVO);
} catch (Exception e) {
return R.failed("调度执行失败: " + e.getMessage());
}
}
}
\ No newline at end of file
package com.aps.controller;
import com.aps.common.util.R;
import com.aps.entity.Gantt.PlanResourceTaskGanttVO1;
import com.aps.entity.Gantt.SimpleEquipinfo1;
import com.aps.entity.Mpsplannedorder;
import com.aps.entity.RoutingDetail;
import com.aps.entity.RoutingDetailEquip;
import com.aps.entity.RoutingHeader;
import com.aps.entity.ScheduledTask;
import com.aps.entity.Equipinfo;
import com.aps.service.ScheduleService;
import com.aps.service.MpsplannedorderService;
import com.aps.service.RoutingHeaderService;
import com.aps.service.RoutingDetailService;
import com.aps.service.RoutingDetailEquipService;
import com.aps.service.EquipinfoService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import org.springframework.beans.factory.annotation.Autowired;
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.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/ganttest")
@Tag(name = "甘特图", description = "甘特图相关API")
public class ScheduleResultController1 {
@Autowired
private ScheduleService schedulerService;
@Autowired
private MpsplannedorderService orderService;
@Autowired
private RoutingHeaderService processService;
@Autowired
private RoutingDetailService operationService;
@Autowired
private RoutingDetailEquipService operationEquipService;
@Autowired
private EquipinfoService equipmentService;
@GetMapping("/resourcetest")
@Operation(summary = "资源甘特图", description = "获取资源甘特图数据")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "成功返回甘特图数据"),
@ApiResponse(responseCode = "500", description = "内部服务器错误")
})
public R<PlanResourceTaskGanttVO1> runScheduling() {
try {
// 获取routingid为'SY1102507-0056202车间-21号线'和'SY1102507-0060202车间-21号线'的待调度工单
List<Mpsplannedorder> orders = orderService.lambdaQuery()
.in(Mpsplannedorder::getRoutingid, "SY1102507-0056202车间-21号线", "SY1102507-0060202车间-21号线")
.list();
if (orders.isEmpty()) {
// 当没有订单时,返回空的甘特图VO
PlanResourceTaskGanttVO1 ganttVO = new PlanResourceTaskGanttVO1()
.setResources(new ArrayList<>())
.setEarliestTaskStartTime(LocalDateTime.of(2025, 6, 1, 0, 0, 0))
.setLastTaskAssignmentTime(LocalDateTime.of(2025, 12, 1, 0, 0, 0));
return R.ok(ganttVO);
}
// 提取所需的工艺ID列表
Set<String> routingIds = orders.stream()
.map(Mpsplannedorder::getRoutingid)
.collect(Collectors.toSet());
// 根据工单获取相关工艺
List<RoutingHeader> processes = processService.lambdaQuery()
.in(RoutingHeader::getCode, routingIds)
.list();
if (processes.isEmpty()) {
return R.failed("未找到相关工艺信息");
}
// 提取工艺ID用于后续查询
Set<Integer> processIds = processes.stream()
.map(RoutingHeader::getId)
.collect(Collectors.toSet());
// 根据工艺获取相关工序
List<RoutingDetail> operations = operationService.lambdaQuery()
.in(RoutingDetail::getRoutingHeaderId, processIds)
.orderByAsc(RoutingDetail::getTaskSeq)
.list();
if (operations.isEmpty()) {
return R.failed("未找到相关工序信息");
}
// 提取工序ID用于后续查询
Set<Integer> operationIds = operations.stream()
.map(RoutingDetail::getId)
.collect(Collectors.toSet());
// 获取相关工序设备关系
List<RoutingDetailEquip> operationEquipments = operationEquipService.lambdaQuery()
.in(RoutingDetailEquip::getRoutingDetailId, operationIds)
.list();
if (operationEquipments.isEmpty()) {
return R.failed("未找到工序设备关系信息");
}
// 提取设备ID用于后续查询
Set<Integer> equipmentIds = operationEquipments.stream()
.map(RoutingDetailEquip::getEquipId)
.collect(Collectors.toSet());
// 获取相关设备
List<Equipinfo> equipments = equipmentService.lambdaQuery()
.in(Equipinfo::getId, equipmentIds)
.list();
// 添加空值检查
if (orders == null || processes == null || operations == null || operationEquipments == null || equipments == null) {
return R.failed("获取调度数据失败,存在空数据");
}
List<ScheduledTask> result = schedulerService.scheduleOrders(
orders, processes, operations, operationEquipments, equipments);
// 转换设备信息为简要信息,并关联相关任务
List<SimpleEquipinfo1> simpleEquipinfos = equipments.stream()
.map(equip -> {
// 查找与该设备关联的任务
List<ScheduledTask> equipTasks = result.stream()
.filter(task -> task.getEquipId() != null && task.getEquipId().equals(equip.getId()))
.collect(Collectors.toList());
return new SimpleEquipinfo1()
.setId(equip.getId())
.setEquipId(equip.getEquipId())
.setEquipName(equip.getEquipName())
.setTasks(equipTasks);
})
.collect(Collectors.toList());
// 设置甘特图VO的最早时间为2025年6月1日,最晚时间为2025年12月1日
PlanResourceTaskGanttVO1 ganttVO = new PlanResourceTaskGanttVO1()
.setResources(simpleEquipinfos)
.setEarliestTaskStartTime(LocalDateTime.of(2025, 6, 1, 0, 0, 0))
.setLastTaskAssignmentTime(LocalDateTime.of(2025, 12, 1, 0, 0, 0));
return R.ok(ganttVO);
} catch (Exception e) {
return R.failed("调度执行失败: " + e.getMessage());
}
}
}
\ No newline at end of file
package com.example.controller.codeGeneratorController;
package com.aps.controller.codeGeneratorController;
import com.example.entity.codeGeneratorEntity.DatabaseConfig;
import com.example.entity.codeGeneratorEntity.GenerateRequest;
import com.example.service.codeGeneratorService.CodeGeneratorService;
import com.example.service.codeGeneratorService.DatabaseConfigService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import com.aps.entity.codeGeneratorEntity.DatabaseConfig;
import com.aps.entity.codeGeneratorEntity.GenerateRequest;
import com.aps.service.codeGeneratorService.CodeGeneratorService;
import com.aps.service.codeGeneratorService.DatabaseConfigService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
......@@ -15,7 +15,7 @@ import java.util.Map;
@RestController
@RequestMapping("/api/code-generator")
@Api(tags = "代码生成器")
@Tag(name = "代码生成器", description = "代码生成相关接口")
public class CodeGeneratorController {
@Autowired
......@@ -25,7 +25,7 @@ public class CodeGeneratorController {
private DatabaseConfigService databaseConfigService;
@GetMapping("/config")
@ApiOperation("获取当前主数据源配置")
@Operation(summary = "获取当前主数据源配置", description = "获取当前主数据源配置")
public DatabaseConfig getDatabaseConfig() {
DatabaseConfig config = databaseConfigService.getPrimaryDatabaseConfig();
if (config == null) {
......@@ -35,7 +35,7 @@ public class CodeGeneratorController {
}
@GetMapping("/config/{dataSourceName}")
@ApiOperation("获取指定数据源配置")
@Operation(summary = "获取指定数据源配置", description = "获取指定数据源配置")
public DatabaseConfig getDatabaseConfig(@PathVariable String dataSourceName) {
DatabaseConfig config = databaseConfigService.getDatabaseConfig(dataSourceName);
if (config == null) {
......@@ -45,7 +45,7 @@ public class CodeGeneratorController {
}
@GetMapping("/tables/{dataSourceName}")
@ApiOperation("获取指定数据源的表列表")
@Operation(summary = "获取指定数据源的表列表", description = "获取指定数据源的表列表")
public List<String> getTables(@PathVariable String dataSourceName) {
DatabaseConfig config = databaseConfigService.getDatabaseConfig(dataSourceName);
if (config == null || config.getUrl() == null) {
......@@ -55,7 +55,7 @@ public class CodeGeneratorController {
}
@GetMapping("/test-connection/{dataSourceName}")
@ApiOperation("测试指定数据源连接")
@Operation(summary = "测试指定数据源连接", description = "测试指定数据源连接")
public String testConnection(@PathVariable String dataSourceName) {
DatabaseConfig config = databaseConfigService.getDatabaseConfig(dataSourceName);
if (config == null) {
......@@ -67,7 +67,7 @@ public class CodeGeneratorController {
}
@PostMapping("/generate/{dataSourceName}")
@ApiOperation("使用指定数据源生成代码")
@Operation(summary = "使用指定数据源生成代码", description = "使用指定数据源生成代码")
public String generateCode(@PathVariable String dataSourceName,
@RequestBody GenerateRequest request) {
try {
......
// MachineSchedulerController.java
package com.aps.controller.plan;
import com.aps.common.util.R;
import com.aps.entity.Schedule.PlanResourceTaskGanttVO;
import com.aps.service.plan.PlanSchedulerService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("/gantt")
@Tag(name = "机器调度管理", description = "机器调度相关API")
public class PlanSchedulerController {
@Autowired
private PlanSchedulerService schedulingService;
@GetMapping("/scheduleresource")
@Operation(summary = "执行机器调度", description = "执行机器调度并返回甘特图数据")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "成功返回调度结果")
})
public R<List<PlanResourceTaskGanttVO>> runScheduling() {
List<PlanResourceTaskGanttVO> execute = schedulingService.execute();
return R.ok(execute);
}
@GetMapping("/health")
@Operation(summary = "健康检查", description = "检查服务是否正常运行")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "服务正常运行")
})
public String healthCheck() {
return "Machine Scheduler Service is running!";
}
}
\ No newline at end of file
package com.example.entity;
package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
......
package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
*
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-09
*/
@Getter
@Setter
public class Equipinfo implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private Integer shopId;
private String equipId;
private Integer equipType;
private String equipName;
private String equipStatus;
private String location;
private Integer shaftQty;
private BigDecimal capabilityValue;
private Integer securityclassid;
private String equipIp;
private String equipmentSc;
private Integer operatorId;
private String equipVersion;
private String equipSystem;
private String equipPic;
private Integer locationx;
private Integer isimportant;
private String filepath;
private LocalDate equipStatusUpdatetime;
private Integer hot;
private BigDecimal capacity;
private BigDecimal standard;
private String usedepartment;
private String installplace;
private String mainnumber;
private String manufacturer;
private String enabledate;
private String equipWinpwd;
private String equipWinname;
private String equipPort;
private Integer status;
private String property;
private LocalDate creationtime;
private Long creatoruserid;
private LocalDate lastmodificationtime;
private Long lastmodifieruserid;
private Boolean isdeleted;
private Long deleteruserid;
private LocalDate deletiontime;
private Integer head;
private Integer runningstatus;
private String systemInfo;
private Integer ismdc;
private Integer workPattern;
private String workPatternName;
private String measureUnitName;
private String currencyTypeName;
private String capacityTypeName;
private Integer measureUnit;
private Integer currencyType;
private Integer capacityType;
private String fequipid;
private BigDecimal minTime;
private BigDecimal minDurationTime;
private BigDecimal maxDurationTime;
private BigDecimal jpExpecationTime;
}
package com.aps.entity;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.LinkedList;
import java.util.Queue;
@Data
public class EquipmentScheduleState {
private Integer equipId; // 设备ID
private String equipName; // 设备名称
private Queue<ScheduledTask> taskQueue = new LinkedList<>(); // 任务队列
private LocalDateTime nextAvailableTime; // 下次可用时间
// 从Equipinfo初始化
public EquipmentScheduleState(Equipinfo equipinfo, LocalDateTime now) {
this.equipId = equipinfo.getId();
this.equipName = equipinfo.getEquipName(); // 添加设备名称
// 确保设备创建时间不为空
if (equipinfo.getCreationtime() != null) {
this.nextAvailableTime = equipinfo.getCreationtime().atStartOfDay();
} else {
this.nextAvailableTime = now != null ? now : LocalDateTime.now();
}
}
}
\ No newline at end of file
package com.aps.entity.Gantt;
import com.aps.entity.Equipinfo;
import com.aps.entity.ScheduledTask;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.apache.ibatis.type.Alias;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author jvs
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@Schema(name = "排产结果可视化——资源任务甘特图", description = "排产结果可视化——资源任务甘特图")
@Alias("PlanResourceTaskGanttVO")
public class PlanResourceTaskGanttVO {
@Schema(description = "任务计划最早开始时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime earliestTaskStartTime;
@Schema(description = "最近任务派工截止时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime lastTaskAssignmentTime;
@Schema(description = "资源集合")
private List<SimpleEquipinfo> resources;
@Schema(description = "任务集合")
private List<ScheduledTask> tasks;
}
\ No newline at end of file
package com.aps.entity.Gantt;
import com.aps.entity.ScheduledTask;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.apache.ibatis.type.Alias;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author jvs
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@Schema(name = "排产结果可视化——资源任务甘特图1", description = "排产结果可视化——资源任务甘特图1")
@Alias("PlanResourceTaskGanttVO1")
public class PlanResourceTaskGanttVO1 {
@Schema(description = "任务计划最早开始时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime earliestTaskStartTime;
@Schema(description = "最近任务派工截止时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime lastTaskAssignmentTime;
@Schema(description = "资源任务集合")
private List<SimpleEquipinfo1> resources;
}
\ No newline at end of file
package com.aps.entity.Gantt;
import com.aps.entity.ScheduledTask;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Data
@Accessors(chain = true)
@Schema(name = "设备简要信息", description = "设备简要信息")
public class SimpleEquipinfo {
@Schema(description = "设备内部ID")
private Integer id;
@Schema(description = "设备编码")
private String equipId;
@Schema(description = "设备名称")
private String equipName;
@Schema(description = "关联的任务列表")
private List<ScheduledTask> tasks;
}
\ No newline at end of file
package com.aps.entity.Gantt;
import com.aps.entity.ScheduledTask;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Data
@Accessors(chain = true)
@Schema(name = "设备简要信息", description = "设备简要信息")
public class SimpleEquipinfo1 {
@Schema(description = "设备内部ID")
private Integer id;
@Schema(description = "设备编码")
private String equipId;
@Schema(description = "设备名称")
private String equipName;
@Schema(description = "任务集合")
private List<ScheduledTask> tasks;
}
\ No newline at end of file
package com.example.entity;
package com.aps.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
......@@ -175,13 +175,13 @@ public class MaterialInfo implements Serializable {
private Long latest;
/**
* 是否创建原材料供应供应
* 是否创建原材料供应供应?
*/
@TableField("iscreatesupplyrouting")
private Long iscreatesupplyrouting;
/**
* 是否创建原材料检验供应
* 是否创建原材料检验供应?
*/
@TableField("iscreatecheckrouting")
private Long iscreatecheckrouting;
......@@ -250,13 +250,13 @@ public class MaterialInfo implements Serializable {
private String ser;
/**
* 是否共用
* 是否共用?
*/
@TableField("iscommon")
private Long iscommon;
/**
* 是否创建汇总供应
* 是否创建汇总供应?
*/
@TableField("iscreatepoolrouting")
private Long iscreatepoolrouting;
......@@ -358,7 +358,7 @@ public class MaterialInfo implements Serializable {
private Long smallpro;
/**
* 周三后排
* 周三后排?
*/
@TableField("isthree")
private Long isthree;
......@@ -403,13 +403,13 @@ public class MaterialInfo implements Serializable {
private String fullName;
/**
* 是否包含库存,默认1,1是,0否
* 是否包含库存,默认是,0否
*/
@TableField("is_include_store")
private Long isIncludeStore;
/**
* 是否平分到未来四周,默认0,0否,1是
* 是否平分到未来四周,默认0否,1是
*/
@TableField("is_average_four_week")
private Long isAverageFourWeek;
......@@ -482,4 +482,4 @@ public class MaterialInfo implements Serializable {
*/
@TableField("invisable")
private Long invisable;
}
}
\ No newline at end of file
package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 班次表
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-10
*/
@Getter
@Setter
@TableName("mes_shift_work_sched")
public class MesShiftWorkSched implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 编号
*/
private String shiftWorkSchedCode;
/**
* 班次名称
*/
private String shiftName;
/**
* 班次开始时间
*/
private LocalDateTime shiftStart;
/**
* 班次结束时间
*/
private LocalDateTime shiftEnd;
/**
* 状态
*/
private Integer status;
/**
* 工作时长
*/
private Integer workingLong;
/**
* 班次id
*/
private Integer shiftWorkSchedPk1;
private LocalDateTime creationtime;
private Integer creatoruserid;
private LocalDateTime lastmodificationtime;
private Integer lastmodifieruserid;
private Integer isdeleted;
private LocalDateTime deletiontime;
private Integer deleteruserid;
/**
* 开始周几值
*/
private Integer startWeekDay;
/**
* 开始周几名称
*/
private String startWeekDayName;
/**
* 班次模板id
*/
private Integer weekWorkSchedId;
/**
* 结束周几值
*/
private Integer endWeekDay;
/**
* 结束周几名称
*/
private String endWeekDayName;
/**
* (字符duration)working_long
*/
private String strWorkingLong;
}
\ No newline at end of file
package com.aps.entity;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
public class Mpsplannedorder {
private String routingid;
private Integer quantity;
private LocalDateTime startdate;
private LocalDateTime end;
private LocalDateTime duadate;
private Integer orderid;
private String mpplanid;
private String id;
private Integer priority;
private LocalDateTime addtime;
private String serie;
private String bigorder;
private String unitid;
private String productid;
}
package com.aps.entity;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
@Data
public class PlanResource {
private Integer id;
private String title;
private String code;
private String type1;
private Integer referenceId;
private Integer departId;
private String departTitle;
private Integer isimportant;
private BigDecimal capabilityValue;
private LocalDate creationtime;
private Long creatoruserid;
private LocalDate lastmodificationtime;
private Long lastmodifieruserid;
private Boolean isdeleted;
private LocalDate deletiontime;
private Long deleteruserid;
private String calId;
private String calName;
private String holidayCalId;
private String holidayCalName;
private String referenceCode;
private Integer equipTypeId;
private String equipType;
private Integer workSchedId;
private Long nrofunitsopen;
private Integer isstop;
private LocalDate stoptime;
private LocalDate stopendtime;
}
package com.aps.entity;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
@Data
public class RoutingDetail {
private Integer id;
private LocalDate creationTime;
private Long creatorUserId;
private LocalDate lastModificationTime;
private Long lastModifierUserId;
private Boolean isDeleted;
private Long deleterUserId;
private LocalDate deletionTime;
private Integer classId;
private Integer routingHeaderId;
private String name;
private BigDecimal taskSeq;
private String description;
private String taskContent;
private Integer resourceId;
private Short resourceType;
private BigDecimal runtime;
private BigDecimal setupTime;
private BigDecimal transportTime;
private BigDecimal checkTime;
private Short checkFlag;
private BigDecimal efficiencyValue;
private BigDecimal singleOut;
private Short isOutside;
private Integer departmentId;
private Short isImportant;
private Integer milestoneId;
private Integer phaseId;
private Short status;
private String remark;
private String extend;
private BigDecimal outsideTime;
private BigDecimal performanceHours;
private String resourceCode;
private Integer isImportantResources;
private BigDecimal schedulingWorkingHours;
private BigDecimal realWorkingHours;
private BigDecimal realRuntime;
private BigDecimal performanceWorkingHours;
private Integer isParticipateIntime;
private String equipType;
private Integer equipTypeId;
private String note;
private String fileId;
private Integer measureUnit;
private String measureUnitName;
private BigDecimal afterProcessTime;
private Integer isGeneral;
private Integer canInterrupt;
private Integer canStartEarly;
private BigDecimal previousStartTimeBegin;
private String code;
private String tool;
private BigDecimal changeLineTime;
private Integer preDetailId;
private Integer connectType;
private Integer connectProperty;
private String connectTypeName;
private String connectPropertyName;
private String strSetupTime;
private Long isync;
private BigDecimal constTime;
private String usable;
private BigDecimal leadTime;
}
package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 工序可用设备
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-10
*/
@Getter
@Setter
@TableName("routing_detail_equip")
public class RoutingDetailEquip implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 创建时间
*/
private LocalDateTime creationtime;
/**
* 创建人
*/
private Integer creatoruserid;
/**
* 更新时间
*/
private LocalDateTime lastmodificationtime;
/**
* 更新人
*/
private Integer lastmodifieruserid;
/**
* 删除人
*/
private Integer isdeleted;
/**
* 删除时间
*/
private LocalDateTime deletiontime;
/**
* 删除人
*/
private Integer deleteruserid;
/**
* 设备类型
*/
private Integer type1;
/**
* 设备类型名
*/
private String typeName;
/**
* 设备名称
*/
private String name;
/**
* 产出数量
*/
private BigDecimal outputQuantity;
/**
* 计量单位
*/
private Integer measureUnit;
/**
* 计量单位名称
*/
private String measureUnitName;
/**
* 持续时间
*/
private BigDecimal duration;
private String exp1;
private String exp2;
/**
* 设备的类型:1--设备 2--班组
*/
private Integer exp3;
private Integer exp4;
/**
* 工序id
*/
private Integer routingDetailId;
/**
* 设备id
*/
private Integer equipId;
/**
* 工艺id
*/
private Integer routingHeaderId;
/**
* 单次批量产出
*/
private BigDecimal oneBatchQuantity;
private String strId;
}
\ No newline at end of file
package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
*
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-09
*/
@Getter
@Setter
@TableName("routing_header")
public class RoutingHeader implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private LocalDate creationTime;
private Long creatorUserId;
private LocalDate lastModificationTime;
private Long lastModifierUserId;
private Integer deleterUserId;
private LocalDate deletionTime;
private Integer classId;
private String unicode;
private String name;
private String code;
private Integer productId;
private String version;
private Integer author;
private Integer departmentId;
private Integer isMain;
private Integer upId;
private Integer upDetailId;
private Integer routingType;
private Short status;
private Short approvalStatus;
private String remark;
private String approvalStatusRemark;
private String auditUserId1;
private String auditUserId2;
private Boolean isDeleted;
private Double platesnum;
private String isEffect;
private String versionnotes;
private Integer phase;
private Integer versionid;
private Integer isSendPpm;
private String fileId;
private String productName;
private String departmentName;
private String drawingNo;
private Integer productBomId;
private String routingChangeorderCode;
private Integer routingChangeheaderId;
private String auditUserId3;
private String materialId;
private Double outputQuantity;
private String routingTypeName;
private Double leadTime;
private Integer quintiqOrtems;
private Integer iscreatecheckrouting;
private Integer iscreateoutbom;
private Integer issupportingstore;
private Long isync;
private Integer routingUsetype;
private Integer linkroutingid;
private LocalDate effectEnd;
private Integer year;
private LocalDate effectBegin;
private Integer cost;
private Integer erptag;
private LocalDate createoutbomtime;
private Integer materialPlanType;
private BigDecimal pcost;
private Integer invisable;
}
package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDate;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
*
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-10
*/
@Getter
@Setter
@TableName("routing_step")
public class RoutingStep implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private LocalDate creationTime;
private Long creatorUserId;
private LocalDate lastModificationTime;
private Long lastModifierUserId;
private Long isDeleted;
private Long deleterUserId;
private LocalDate deletionTime;
private Integer routingHeaderId;
private Integer routingDetailId;
private Integer classId;
private Integer stepSeq;
private String name;
private String description;
private Short status;
private String remark;
private String stepContent;
private String extend;
}
package com.aps.entity.Schedule;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
public class GenVO {
private String orderId; // 工单ID
private Integer operationId; // 工序ID
private Integer equipId; // 设备ID
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime startTime; // 实际开始时间
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime endTime; // 实际结束时间
private BigDecimal quantity; // 加工数量
private String operationName; // 工序名称
private String equipName; // 设备名称
}
\ No newline at end of file
package com.aps.entity.Schedule;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@Schema(name = "节假日信息", description = "节假日信息")
public class HolidayDTO {
@Schema(description = "开始时间")
private LocalDateTime start;
@Schema(description = "结束时间")
private LocalDateTime end;
}
\ No newline at end of file
package com.aps.entity.Schedule;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
public class MachineVO {
@Schema(description = "设备内部ID")
private Integer id;
@Schema(description = "设备编码")
private String equipId;
@Schema(description = "设备名称")
private String equipName;
@Schema(description = "任务集合")
private List<GenVO> tasks;
}
\ No newline at end of file
package com.aps.entity.Schedule;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.apache.ibatis.type.Alias;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author jvs
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@Schema(name = "排产结果可视化——资源任务甘特图", description = "排产结果可视化——资源任务甘特图")
@Alias("SchedulePlanResourceTaskGanttVO")
public class PlanResourceTaskGanttVO {
@Schema(description = "任务计划最早开始时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime earliestTaskStartTime;
@Schema(description = "最近任务派工截止时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime lastTaskAssignmentTime;
@Schema(description = "资源任务集合")
private List<MachineVO> resources;
@Schema(description = "场景id")
private Long sceneId;
}
\ No newline at end of file
// ScheduleRequest.java
package com.aps.entity.Schedule;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Data
@Schema(name = "调度请求参数", description = "调度请求参数")
public class ScheduleRequest {
@Schema(description = "开始时间", example = "2025-10-01T00:00:00")
private LocalDateTime startTime;
@Schema(description = "节假日列表")
private List<HolidayDTO> holidays;
@Schema(description = "是否运行所有算法", example = "true")
private boolean runAll = false;
}
package com.aps.entity.Schedule;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
@Schema(name = "调度响应结果", description = "调度响应结果")
public class ScheduleResponse {
@Schema(description = "成功标志")
private boolean success;
@Schema(description = "返回消息")
private String message;
@Schema(description = "单个调度结果")
private ScheduleResult singleResult;
@Schema(description = "所有调度结果")
private List<ScheduleResultList> allResults;
@Schema(description = "缓存大小")
private Integer cacheSize;
}
\ No newline at end of file
package com.aps.entity.Schedule;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(name = "调度结果详情", description = "调度结果详情")
public class ScheduleResult {
@Schema(description = "适应度分数")
private Double fitness;
@Schema(description = "调度摘要")
private String summary;
@Schema(description = "算法运行ID")
private String runId;
}
\ No newline at end of file
package com.aps.entity.Schedule;
import com.aps.entity.basic.ScheduleChromosome;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(name = "调度结果", description = "调度结果")
public class ScheduleResultList {
@Schema(description = "计划详情")
private ScheduleChromosome chromosomeList;
@Schema(description = "运算ID")
private String runId;
}
\ No newline at end of file
package com.aps.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
public class ScheduledTask {
private String orderId; // 工单ID
private Integer operationId; // 工序ID
private Integer equipId; // 设备ID
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime startTime; // 实际开始时间
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime endTime; // 实际结束时间
private BigDecimal quantity; // 加工数量
private BigDecimal utilization; // 加工效率
private String routeId; // 工艺路线ID
private String operationName; // 工序名称
private String equipName; // 设备名称
}
\ No newline at end of file
package com.aps.entity.basic;
import lombok.Data;
import java.util.List;
/**
* 基因表示
*/
@Data
public class Gene {
private int orderId;
private int productId;
private int operationId;
private int machineId;
private int startTime; // 相对开始时间(分钟)
private int endTime; // 相对结束时间(分钟)
private int batchSize; // 批次大小(订单可拆分)
private List<GeneDetail> geneDetails; // 时间详情
private int processingTime; // 绝对处理时间(分钟)
}
\ No newline at end of file
package com.aps.entity.basic;
import lombok.Data;
@Data
public class GeneDetail {
private String key;
private int startTime; // 相对开始时间(分钟)
private int endTime; // 相对结束时间(分钟)
}
\ No newline at end of file
package com.aps.entity.basic;
import java.time.LocalDateTime;
public class Holiday {
private LocalDateTime start;
private LocalDateTime end;
public Holiday() {}
public Holiday(LocalDateTime start, LocalDateTime end) {
this.start = start;
this.end = end;
}
public LocalDateTime getStart() {
return start;
}
public void setStart(LocalDateTime start) {
this.start = start;
}
public LocalDateTime getEnd() {
return end;
}
public void setEnd(LocalDateTime end) {
this.end = end;
}
}
\ No newline at end of file
package com.aps.entity.basic;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
@Data
public class Machine {
private int id;
private String name;
private int earliestTime=0;
private int totalTaskTime=0;
private List<Shift> shifts;
private List<MaintenanceWindow> maintenanceWindows;
private List<TimeSegment> availability;
// 事件回调
private Consumer<Void> shiftsChanged;
private Consumer<Void> maintenanceWindowsChanged;
public Machine() {
this.shifts = new ArrayList<>();
this.maintenanceWindows = new ArrayList<>();
this.availability = new ArrayList<>();
}
public Machine(int id, String name) {
this();
this.id = id;
this.name = name;
}
// 添加维护窗口的方法
public void addMaintenanceWindow(MaintenanceWindow window) {
maintenanceWindows.add(window);
if (maintenanceWindowsChanged != null) {
maintenanceWindowsChanged.accept(null);
}
}
public void addShift(Shift shift) {
shifts.add(shift);
if (shiftsChanged != null) {
shiftsChanged.accept(null);
}
}
// 重写equals和hashCode方法,只基于id进行比较
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Machine machine = (Machine) o;
return id == machine.id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
\ No newline at end of file
package com.aps.entity.basic;
import lombok.Data;
/**
* 设备选项
*/
@Data
public class MachineOption {
private int machineId;
private int processingTime; // 加工时间
private int setupTime; // 换型时间(如果与前一个产品不同)
}
\ No newline at end of file
package com.aps.entity.basic;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class MachineTimeline {
private int machineId;
private List<TimeSegment> segments;
private LocalDateTime validFrom;
private LocalDateTime validTo;
private LocalDateTime lastUpdated;
private int version = 1;
public MachineTimeline() {
this.segments = new ArrayList<>();
}
// Getters and Setters
public int getMachineId() {
return machineId;
}
public void setMachineId(int machineId) {
this.machineId = machineId;
}
public List<TimeSegment> getSegments() {
return segments;
}
public void setSegments(List<TimeSegment> segments) {
this.segments = segments;
}
public LocalDateTime getValidFrom() {
return validFrom;
}
public void setValidFrom(LocalDateTime validFrom) {
this.validFrom = validFrom;
}
public LocalDateTime getValidTo() {
return validTo;
}
public void setValidTo(LocalDateTime validTo) {
this.validTo = validTo;
}
public LocalDateTime getLastUpdated() {
return lastUpdated;
}
public void setLastUpdated(LocalDateTime lastUpdated) {
this.lastUpdated = lastUpdated;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MachineTimeline that = (MachineTimeline) o;
return machineId == that.machineId;
}
@Override
public int hashCode() {
return Objects.hash(machineId);
}
}
\ No newline at end of file
package com.aps.entity.basic;
import java.time.LocalDateTime;
import java.util.Objects;
public class MaintenanceWindow {
private LocalDateTime startTime;
private LocalDateTime endTime;
private String reason;
public MaintenanceWindow() {}
public MaintenanceWindow(LocalDateTime startTime, LocalDateTime endTime, String reason) {
this.startTime = startTime;
this.endTime = endTime;
this.reason = reason;
}
// Getters and Setters
public LocalDateTime getStartTime() {
return startTime;
}
public void setStartTime(LocalDateTime startTime) {
this.startTime = startTime;
}
public LocalDateTime getEndTime() {
return endTime;
}
public void setEndTime(LocalDateTime endTime) {
this.endTime = endTime;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MaintenanceWindow that = (MaintenanceWindow) o;
return Objects.equals(startTime, that.startTime) &&
Objects.equals(endTime, that.endTime);
}
@Override
public int hashCode() {
return Objects.hash(startTime, endTime);
}
}
\ No newline at end of file
package com.aps.entity.basic;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
* 工序定义
*/
@Data
public class Operation {
@JsonProperty("id")
private int id;
@JsonProperty("productId")
private int productId;
@JsonProperty("sequence")
private int sequence; // 工序顺序
@JsonProperty("machineOptions")
private List<MachineOption> machineOptions; // 可选设备列表
@JsonProperty("isInterrupt")
private boolean isInterrupt = false; // 是否可中断,间缝插针
}
\ No newline at end of file
package com.aps.entity.basic;
import lombok.Data;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
/**
* 订单定义
*/
@Data
public class Order {
private int id;
private int productId;
private int quantity = 100; // 100个
private OffsetDateTime dueDate;
private LocalDateTime orderCompletion;
private double tardiness;
private int priority;
private boolean canSplit = false;
private boolean canInterrupt = false;
}
\ No newline at end of file
package com.aps.entity.basic;
import lombok.Data;
import java.util.List;
/**
* 产品定义
*/
@Data
public class Product {
private int id;
private String name;
private List<Operation> operations; // 工序列表,顺序代表工序顺序约束
}
\ No newline at end of file
package com.aps.entity.basic;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@Data
public class ScheduleChromosome {
private List<Gene> genes;
private List<Order> orders;
private List<Machine> machines;
private double fitness;
private double tardiness;
private Map<Integer, Double> objectiveValues;
private LocalDateTime baseTime;
public ScheduleChromosome() {
this.genes = new ArrayList<>();
this.objectiveValues = new HashMap<>();
}
public ScheduleChromosome(LocalDateTime baseTime) {
this();
this.baseTime = baseTime;
}
// 修改:放宽去重条件,包含更多关键信息
// public String getGenesStr() {
// return genes.stream()
// .sorted(Comparator.comparing(Gene::getOrderId)
// .thenComparing(Gene::getOperationId)
// .thenComparing(Gene::getStartTime))
// .map(p -> String.format("%d:%d:%d:%d:%d:%d",
// p.getOrderId(), p.getOperationId(), p.getMachineId(),
// p.getBatchSize(), p.getStartTime(), p.getEndTime()))
// .collect(Collectors.joining(";"));
// }
public String getGenesStr() {
return getGenes().stream()
.sorted(Comparator.comparing(Gene::getOrderId)
.thenComparing(Gene::getOperationId)
.thenComparing(Gene::getMachineId))
.map(g -> String.format("%d:%d:%d",
g.getOrderId(), g.getOperationId(), g.getMachineId()))
.collect(Collectors.joining("; "));
}
// 新增:生成更详细的键用于调试
public String getDetailedKey() {
return genes.stream()
.sorted(Comparator.comparing(Gene::getOrderId)
.thenComparing(Gene::getOperationId)
.thenComparing(Gene::getStartTime))
.map(g -> String.format("O%d-P%d-M%d-B%d-S%d-E%d",
g.getOrderId(), g.getOperationId(), g.getMachineId(),
g.getBatchSize(), g.getStartTime(), g.getEndTime()))
.collect(Collectors.joining("_"));
}
public List<Order> getOrders() {
return calTardiness();
}
// private List<Order> calTardiness() {
// tardiness = 0;
//
// for (Order order : orders) {
// final int orderId = order.getId();
// List<Gene> orderGroups = genes.stream()
// .filter(g -> g.getOrderId() == orderId)
// .collect(Collectors.toList());
//
// int orderCompletion = orderGroups.stream()
// .mapToInt(Gene::getEndTime)
// .max()
// .orElse(0);
//
// LocalDateTime orderCompletionTime = baseTime.plusMinutes(orderCompletion);
// order.setOrderCompletion(orderCompletionTime);
// order.setTardiness(0);
//
// if (orderCompletionTime.isAfter(order.getDueDate().toLocalDateTime())) {
// long diffHours = java.time.temporal.ChronoUnit.HOURS.between(order.getDueDate(), orderCompletionTime);
// double tardinessHours = diffHours + (double) java.time.temporal.ChronoUnit.MINUTES.between(order.getDueDate(), orderCompletionTime) % 60 / 60;
// order.setTardiness(tardinessHours);
// tardiness += tardinessHours;
// }
// }
// return orders;
// }
private List<Order> calTardiness() {
tardiness = 0;
for (Order order : orders) {
final int orderId = order.getId();
List<Gene> orderGroups = genes.stream()
.filter(g -> g.getOrderId() == orderId)
.collect(Collectors.toList());
int orderCompletion = orderGroups.stream()
.mapToInt(Gene::getEndTime)
.max()
.orElse(0);
LocalDateTime orderCompletionTime = baseTime.plusMinutes(orderCompletion);
order.setOrderCompletion(orderCompletionTime);
order.setTardiness(0);
// 修复:统一时间类型
LocalDateTime dueDateTime = order.getDueDate().toLocalDateTime();
if (orderCompletionTime.isAfter(dueDateTime)) {
// 方法1:使用分钟计算再转换为小时(推荐)
long totalMinutes = java.time.temporal.ChronoUnit.MINUTES.between(dueDateTime, orderCompletionTime);
double tardinessHours = totalMinutes / 60.0;
// 方法2:或者保持原有逻辑但使用统一的时间类型
// long diffHours = java.time.temporal.ChronoUnit.HOURS.between(dueDateTime, orderCompletionTime);
// long remainingMinutes = java.time.temporal.ChronoUnit.MINUTES.between(dueDateTime, orderCompletionTime) % 60;
// double tardinessHours = diffHours + (double) remainingMinutes / 60;
order.setTardiness(tardinessHours);
tardiness += tardinessHours;
}
}
return orders;
}
}
\ No newline at end of file
package com.aps.entity.basic;
public enum SegmentType {
REGULAR, // 常规班次
TEMP, // 临时班次(优先级高)
MAINTENANCE // 维护窗口(不可用)
}
\ No newline at end of file
package com.aps.entity.basic;
import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Set;
public class Shift {
private LocalTime startTime;
private LocalTime endTime;
private Set<Integer> days; // 改为Integer类型,便于JSON反序列化
private LocalDateTime shiftDate;
private boolean isTemporaryShift;
private int priority;
public Shift() {}
public LocalTime getStartTime() {
return startTime;
}
public void setStartTime(LocalTime startTime) {
this.startTime = startTime;
}
public LocalTime getEndTime() {
return endTime;
}
public void setEndTime(LocalTime endTime) {
this.endTime = endTime;
}
public Set<Integer> getDays() {
return days;
}
public void setDays(Set<Integer> days) {
this.days = days;
}
// 辅助方法:将数字转换为DayOfWeek
public Set<DayOfWeek> getDaysAsEnum() {
if (days == null) return null;
return days.stream()
.map(day -> DayOfWeek.of(day == 0 ? 7 : day)) // 处理周日(0)转换为7
.collect(java.util.stream.Collectors.toSet());
}
public LocalDateTime getShiftDate() {
return shiftDate;
}
public void setShiftDate(LocalDateTime shiftDate) {
this.shiftDate = shiftDate;
}
public boolean isTemporaryShift() {
return isTemporaryShift;
}
public void setTemporaryShift(boolean temporaryShift) {
isTemporaryShift = temporaryShift;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
}
\ No newline at end of file
package com.aps.entity.basic;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.UUID;
/**
* 时间段(设备的时间片段,标记可用/不可用状态)
*/
@Data
public class TimeSegment {
private String key = UUID.randomUUID().toString(); // 时间段唯一标识(如"Machine-1_20251008_1000")
private LocalDateTime start; // 时间段开始时间
private LocalDateTime end; // 时间段结束时间
private int earliestTime; // 该时段内最早可用时间(分钟)
private int totalTaskTime; // 该时段内已分配任务时间(分钟)
private SegmentType type; // 时间段类型(关联SegmentType枚举)
private boolean isHoliday; // 是否节假日(true=节假日)
private boolean isUsed; // 是否已被占用(true=已分配任务)
// 无参构造(Lombok默认生成)
public TimeSegment() {}
// 全参构造(按需添加)
public TimeSegment(LocalDateTime start, LocalDateTime end, SegmentType type, boolean isHoliday) {
this.start = start;
this.end = end;
this.type = type;
this.isHoliday = isHoliday;
}
public TimeSegment(String key, LocalDateTime start, LocalDateTime end, int earliestTime,
int totalTaskTime, SegmentType type, boolean isHoliday, boolean isUsed) {
this.key = key;
this.start = start;
this.end = end;
this.earliestTime = earliestTime;
this.totalTaskTime = totalTaskTime;
this.type = type;
this.isHoliday = isHoliday;
this.isUsed = isUsed;
}
}
\ No newline at end of file
package com.example.entity.codeGeneratorEntity;
package com.aps.entity.codeGeneratorEntity;
public class DatabaseConfig {
private String url;
......
package com.example.entity.codeGeneratorEntity;
package com.aps.entity.codeGeneratorEntity;
import java.util.List;
......@@ -22,4 +22,4 @@ public class GenerateRequest {
public void setAuthor(String author) { this.author = author; }
public boolean isOverwrite() { return overwrite; }
public void setOverwrite(boolean overwrite) { this.overwrite = overwrite; }
}
\ No newline at end of file
}
package com.example.generator;
package com.aps.generator;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
......@@ -21,7 +21,7 @@ public class CodeGenerator {
})
// 3. 包配置(指定代码存放的包路径)
.packageConfig(builder -> {
builder.parent("com.example") // 父包名
builder.parent("com.aps") // 父包名
.entity("entity") // 实体类包
.mapper("mapper") // Mapper接口包
.service("service") // Service接口包
......@@ -56,4 +56,4 @@ public class CodeGenerator {
// 执行生成
.execute();
}
}
}
\ No newline at end of file
package com.example.generator;
package com.aps.generator;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
......@@ -21,7 +21,7 @@ public class CodeGenerator1 {
})
// 3. 包配置
.packageConfig(builder -> {
builder.parent("com.example") // 父包名
builder.parent("com.aps") // 父包名
.entity("entity") // 实体类包
.mapper("mapper") // Mapper接口包
.service("service") // Service接口包
......@@ -29,7 +29,7 @@ public class CodeGenerator1 {
.controller("controller") // Controller包
// Mapper XML文件输出路径
.pathInfo(Collections.singletonMap(
OutputFile.xml,
OutputFile.xml,
System.getProperty("user.dir") + "/src/main/resources/mapper"
));
})
......@@ -55,7 +55,7 @@ public class CodeGenerator1 {
.templateEngine(new VelocityTemplateEngine())
// 执行生成
.execute();
System.out.println("代码生成完成");
System.out.println("代码生成完成!");
}
}
\ No newline at end of file
package com.example.mapper;
package com.aps.mapper;
import com.example.entity.Department;
import com.aps.entity.Department;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
......
package com.aps.mapper;
import com.aps.entity.Equipinfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-09
*/
public interface EquipinfoMapper extends BaseMapper<Equipinfo> {
}
package com.example.mapper;
package com.aps.mapper;
import com.example.entity.MaterialInfo;
import com.aps.entity.MaterialInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
......
package com.aps.mapper;
import com.aps.entity.MesShiftWorkSched;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 班次表 Mapper 接口
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-10
*/
public interface MesShiftWorkSchedMapper extends BaseMapper<MesShiftWorkSched> {
}
\ No newline at end of file
package com.aps.mapper;
import com.aps.entity.Mpsplannedorder;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-14
*/
public interface MpsplannedorderMapper extends BaseMapper<Mpsplannedorder> {
}
package com.aps.mapper;
import com.aps.entity.PlanResource;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-10
*/
public interface PlanResourceMapper extends BaseMapper<PlanResource> {
}
package com.aps.mapper;
import com.aps.entity.RoutingDetailEquip;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 工序可用设备 Mapper 接口
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-10
*/
public interface RoutingDetailEquipMapper extends BaseMapper<RoutingDetailEquip> {
}
package com.aps.mapper;
import com.aps.entity.RoutingDetail;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-14
*/
public interface RoutingDetailMapper extends BaseMapper<RoutingDetail> {
}
package com.aps.mapper;
import com.aps.entity.RoutingHeader;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-09
*/
public interface RoutingHeaderMapper extends BaseMapper<RoutingHeader> {
}
package com.aps.mapper;
import com.aps.entity.RoutingStep;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-10
*/
public interface RoutingStepMapper extends BaseMapper<RoutingStep> {
}
package com.example.service;
package com.aps.service;
import com.example.entity.Department;
import com.aps.entity.Department;
import com.baomidou.mybatisplus.extension.service.IService;
/**
......@@ -13,4 +13,4 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/
public interface DepartmentService extends IService<Department> {
}
}
\ No newline at end of file
package com.aps.service;
import com.aps.entity.Equipinfo;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-09
*/
public interface EquipinfoService extends IService<Equipinfo> {
}
\ No newline at end of file
package com.example.service;
package com.aps.service;
import com.example.entity.MaterialInfo;
import com.aps.entity.MaterialInfo;
import com.baomidou.mybatisplus.extension.service.IService;
/**
......@@ -13,4 +13,4 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/
public interface MaterialInfoService extends IService<MaterialInfo> {
}
}
\ No newline at end of file
package com.aps.service;
import com.aps.entity.MesShiftWorkSched;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 班次表 服务类
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-10
*/
public interface MesShiftWorkSchedService extends IService<MesShiftWorkSched> {
}
\ No newline at end of file
package com.aps.service;
import com.aps.entity.Mpsplannedorder;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-14
*/
public interface MpsplannedorderService extends IService<Mpsplannedorder> {
}
\ No newline at end of file
package com.aps.service;
import com.aps.entity.PlanResource;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-10
*/
public interface PlanResourceService extends IService<PlanResource> {
}
\ No newline at end of file
package com.aps.service;
import com.aps.entity.RoutingDetailEquip;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 工序可用设备 服务类
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-10
*/
public interface RoutingDetailEquipService extends IService<RoutingDetailEquip> {
}
\ No newline at end of file
package com.aps.service;
import com.aps.entity.RoutingDetail;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-14
*/
public interface RoutingDetailService extends IService<RoutingDetail> {
}
\ No newline at end of file
package com.aps.service;
import com.aps.entity.RoutingHeader;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-09
*/
public interface RoutingHeaderService extends IService<RoutingHeader> {
}
\ No newline at end of file
package com.aps.service;
import com.aps.entity.RoutingStep;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-10
*/
public interface RoutingStepService extends IService<RoutingStep> {
}
\ No newline at end of file
package com.aps.service;
import com.aps.entity.*;
import java.util.List;
public interface ScheduleService {
public List<ScheduledTask> scheduleOrders( List<Mpsplannedorder> orders,
List<RoutingHeader> processHeaders,
List<RoutingDetail> operations,
List<RoutingDetailEquip> operationEquipments,
List<Equipinfo> equipments);
}
package com.example.service.codeGeneratorService;
package com.aps.service.codeGeneratorService;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import com.example.entity.codeGeneratorEntity.DatabaseConfig;
import com.aps.entity.codeGeneratorEntity.DatabaseConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
@Service
public class CodeGeneratorService {
......@@ -65,6 +67,9 @@ public class CodeGeneratorService {
.enableBaseColumnList();
})
.templateEngine(new VelocityTemplateEngine())
// .templateConfig(builder -> {
// builder.entity("/templates/entity.java.vm"); // 指向自定义模板
// })
.execute();
}
......
package com.example.service.codeGeneratorService;
package com.aps.service.codeGeneratorService;
import com.example.entity.codeGeneratorEntity.DatabaseConfig;
import com.aps.entity.codeGeneratorEntity.DatabaseConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.core.env.Environment;
......
package com.example.service.codeGeneratorService;
package com.aps.service.codeGeneratorService;
import com.example.entity.codeGeneratorEntity.DatabaseConfig;
import com.aps.entity.codeGeneratorEntity.DatabaseConfig;
import org.springframework.stereotype.Service;
import java.sql.Connection;
......@@ -25,7 +25,41 @@ public class DatabaseService {
DatabaseMetaData metaData = connection.getMetaData();
String[] types = {"TABLE"};
ResultSet resultSet = metaData.getTables(null, null, "%", types);
// 根据不同数据库类型设置不同的schemaPattern参数
String schemaPattern = null;
String catalog = null;
if ("oracle".equals(dbConfig.getDbType())) {
// Oracle数据库使用用户名作为schema
schemaPattern = dbConfig.getUsername().toUpperCase();
} else if ("mysql".equals(dbConfig.getDbType())) {
// MySQL从URL中提取数据库名作为catalog
String url = dbConfig.getUrl();
if (url.contains("?")) {
url = url.substring(0, url.indexOf("?"));
}
if (url.contains("/")) {
catalog = url.substring(url.lastIndexOf("/") + 1);
}
} else if ("sqlserver".equals(dbConfig.getDbType())) {
// SQL Server使用用户名作为schema,同时catalog设置为数据库名
schemaPattern = "dbo"; // SQL Server默认schema通常是dbo
// 从URL中提取数据库名作为catalog
String url = dbConfig.getUrl();
if (url.contains(";")) {
String[] parts = url.split(";");
for (String part : parts) {
if (part.toLowerCase().startsWith("databasename=")) {
catalog = part.substring(part.indexOf("=") + 1);
break;
}
}
}
}
ResultSet resultSet = metaData.getTables(catalog, schemaPattern, "%", types);
while (resultSet.next()) {
String tableName = resultSet.getString("TABLE_NAME");
......
package com.example.service.impl;
package com.aps.service.impl;
import com.example.entity.Department;
import com.example.mapper.DepartmentMapper;
import com.example.service.DepartmentService;
import com.aps.entity.Department;
import com.aps.mapper.DepartmentMapper;
import com.aps.service.DepartmentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
......@@ -17,4 +17,4 @@ import org.springframework.stereotype.Service;
@Service
public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Department> implements DepartmentService {
}
}
\ No newline at end of file
package com.aps.service.impl;
import com.aps.entity.Equipinfo;
import com.aps.mapper.EquipinfoMapper;
import com.aps.service.EquipinfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-09
*/
@Service
public class EquipinfoServiceImpl extends ServiceImpl<EquipinfoMapper, Equipinfo> implements EquipinfoService {
}
\ No newline at end of file
package com.example.service.impl;
package com.aps.service.impl;
import com.example.entity.MaterialInfo;
import com.example.mapper.MaterialInfoMapper;
import com.example.service.MaterialInfoService;
import com.aps.entity.MaterialInfo;
import com.aps.mapper.MaterialInfoMapper;
import com.aps.service.MaterialInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
......@@ -17,4 +17,4 @@ import org.springframework.stereotype.Service;
@Service
public class MaterialInfoServiceImpl extends ServiceImpl<MaterialInfoMapper, MaterialInfo> implements MaterialInfoService {
}
}
\ No newline at end of file
package com.aps.service.impl;
import com.aps.entity.MesShiftWorkSched;
import com.aps.mapper.MesShiftWorkSchedMapper;
import com.aps.service.MesShiftWorkSchedService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 班次表 服务实现类
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-10
*/
@Service
public class MesShiftWorkSchedServiceImpl extends ServiceImpl<MesShiftWorkSchedMapper, MesShiftWorkSched> implements MesShiftWorkSchedService {
}
\ No newline at end of file
package com.aps.service.impl;
import com.aps.entity.Mpsplannedorder;
import com.aps.mapper.MpsplannedorderMapper;
import com.aps.service.MpsplannedorderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-14
*/
@Service
public class MpsplannedorderServiceImpl extends ServiceImpl<MpsplannedorderMapper, Mpsplannedorder> implements MpsplannedorderService {
}
\ No newline at end of file
package com.aps.service.impl;
import com.aps.entity.PlanResource;
import com.aps.mapper.PlanResourceMapper;
import com.aps.service.PlanResourceService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-10
*/
@Service
public class PlanResourceServiceImpl extends ServiceImpl<PlanResourceMapper, PlanResource> implements PlanResourceService {
}
\ No newline at end of file
package com.aps.service.impl;
import com.aps.entity.RoutingDetailEquip;
import com.aps.mapper.RoutingDetailEquipMapper;
import com.aps.service.RoutingDetailEquipService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 工序可用设备 服务实现类
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-10
*/
@Service
public class RoutingDetailEquipServiceImpl extends ServiceImpl<RoutingDetailEquipMapper, RoutingDetailEquip> implements RoutingDetailEquipService {
}
\ No newline at end of file
package com.aps.service.impl;
import com.aps.entity.RoutingDetail;
import com.aps.mapper.RoutingDetailMapper;
import com.aps.service.RoutingDetailService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-14
*/
@Service
public class RoutingDetailServiceImpl extends ServiceImpl<RoutingDetailMapper, RoutingDetail> implements RoutingDetailService {
}
\ No newline at end of file
package com.aps.service.impl;
import com.aps.entity.RoutingHeader;
import com.aps.mapper.RoutingHeaderMapper;
import com.aps.service.RoutingHeaderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-09
*/
@Service
public class RoutingHeaderServiceImpl extends ServiceImpl<RoutingHeaderMapper, RoutingHeader> implements RoutingHeaderService {
}
\ No newline at end of file
package com.aps.service.impl;
import com.aps.entity.RoutingStep;
import com.aps.mapper.RoutingStepMapper;
import com.aps.service.RoutingStepService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author MyBatis-Plus
* @since 2025-10-10
*/
@Service
public class RoutingStepServiceImpl extends ServiceImpl<RoutingStepMapper, RoutingStep> implements RoutingStepService {
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
package com.aps.service.plan;
import com.aps.common.util.JsonFileReader;
import com.aps.entity.Schedule.GenVO;
import com.aps.entity.Schedule.MachineVO;
import com.aps.entity.Schedule.PlanResourceTaskGanttVO;
import com.aps.entity.basic.*;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class PlanSchedulerService {
private final LocalDateTime baseTime = LocalDateTime.of(2025, 10, 1, 0, 0, 0);
public List<PlanResourceTaskGanttVO> execute() {
try {
// 1. 读取数据
List<Machine> machines = JsonFileReader.readListFromResources("machines.json", Machine.class);
List<Product> products = JsonFileReader.readListFromResources("products.json", Product.class);
List<Order> orders = JsonFileReader.readListFromResources("orders.json", Order.class);
// 2. 创建节假日
List<Holiday> holidays = Arrays.asList(
new Holiday(LocalDateTime.of(2025, 10, 1, 0, 0),
LocalDateTime.of(2025, 10, 7, 23, 59))
);
// 3. 创建调度服务
MachineSchedulerService machineScheduler = new MachineSchedulerService(
holidays, LocalDateTime.of(2025, 10, 1, 0, 0, 0));
// 4. 初始化机器时间线
for (Machine machine : machines) {
MachineTimeline timeline = machineScheduler.getOrCreateTimeline(machine);
machine.setAvailability(timeline.getSegments());
}
// 5. 执行调度算法
AlgorithmScheduler6 scheduler = new AlgorithmScheduler6(products, machines, orders, machineScheduler);
List<ScheduleChromosome> scheduleChromosomes = scheduler.RunAll();
List<PlanResourceTaskGanttVO> ganttlist = new ArrayList<>();
long sceneId = 1L;
for (ScheduleChromosome chromosome : scheduleChromosomes
) {
// 转换基因列表和设备列表
List<GenVO> genVOS = convertGeneListToGenVO(chromosome.getGenes(), baseTime);
List<MachineVO> machineVOS = machines.stream()
.map(this::convertToVO)
.collect(Collectors.toList());
// 按设备ID分组任务
Map<Integer, List<GenVO>> taskMap = genVOS.stream()
.collect(Collectors.groupingBy(GenVO::getEquipId));
// 为每个设备设置任务
for (MachineVO machine : machineVOS) {
Integer equipId = Integer.valueOf(machine.getEquipId());
List<GenVO> tasks = taskMap.get(equipId);
if (tasks != null) {
// 按开始时间排序
tasks.sort(Comparator.comparing(GenVO::getStartTime));
machine.setTasks(tasks);
} else {
machine.setTasks(new ArrayList<>()); // 如果没有任务,设置为空列表
}
}
// 现在machineVOS中的每个MachineVO都包含了对应的任务列表
PlanResourceTaskGanttVO ganttVO = new PlanResourceTaskGanttVO()
.setResources(machineVOS)
.setEarliestTaskStartTime(LocalDateTime.of(2025, 9, 1, 0, 0, 0))
.setLastTaskAssignmentTime(LocalDateTime.of(2025, 12, 1, 0, 0, 0))
.setSceneId(sceneId);
sceneId++;
ganttlist.add(ganttVO);
}
return ganttlist;
} catch (Exception e) {
throw new RuntimeException("调度执行失败", e);
}
}
public GenVO convertGeneToGenVO(Gene gene, LocalDateTime baseTime) {
GenVO genVO = new GenVO();
genVO.setOrderId(String.valueOf(gene.getOrderId()));
genVO.setOperationId(gene.getOperationId());
genVO.setEquipId(gene.getMachineId());
genVO.setQuantity(BigDecimal.valueOf(gene.getBatchSize()));
genVO.setStartTime(baseTime.plusMinutes(gene.getStartTime()));
genVO.setEndTime(baseTime.plusMinutes(gene.getEndTime()));
genVO.setOperationName(""); // 从其他数据源获取
genVO.setEquipName(""); // 从其他数据源获取
return genVO;
}
// 批量转换
public List<GenVO> convertGeneListToGenVO(List<Gene> geneList, LocalDateTime baseTime) {
return geneList.stream()
.map(gene -> convertGeneToGenVO(gene, baseTime))
.collect(Collectors.toList());
}
private MachineVO convertToVO(Machine machine) {
MachineVO machineVO = new MachineVO();
machineVO.setId(machine.getId());
machineVO.setEquipId(String.valueOf(machine.getId()));
machineVO.setEquipName(machine.getName());
return machineVO;
}
}
\ No newline at end of file
package com.example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.controller")) // 修改为您的包名
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Demo2 API 文档")
.description("多数据库项目接口文档")
.version("1.0.0")
.build();
}
}
\ No newline at end of file
package com.example.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/test")
@Api(tags = "测试接口")
public class TestController {
@GetMapping("/hello")
@ApiOperation("Hello World 测试接口")
public String hello() {
return "Hello, Swagger!";
}
@GetMapping("/info")
@ApiOperation("获取应用信息")
public String info() {
return "Demo2 Application - Multi Database Project";
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment