feat(business): 同步G30添加发送任务模板功能并扩展计划实体
- 新增 BizSendJob、BizSendJobGroup、BizSendJobItem 实体类用于发送任务管理 - 新增 BizSendTemplate、BizSendTemplateItem 实体类用于发送模板配置 - 实现发送模板的增删改查和批量保存功能 - 添加 DashboardController 提供首页仪表板统计接口 - 实现发送任务查询和执行服务 - 扩展 PdiPlan 相关实体类增加锌层厚度字段 - 优化 OPC 消息发送功能,支持多种数据类型转换 - 更新日志配置,调整错误日志处理策略
This commit is contained in:
12
.idea/dbnavigator.xml
generated
12
.idea/dbnavigator.xml
generated
@@ -7,9 +7,21 @@
|
||||
<component name="DBNavigator.Project.DatabaseAssistantManager">
|
||||
<assistants />
|
||||
</component>
|
||||
<component name="DBNavigator.Project.DatabaseBrowserManager">
|
||||
<autoscroll-to-editor value="false" />
|
||||
<autoscroll-from-editor value="true" />
|
||||
<show-object-properties value="true" />
|
||||
<loaded-nodes />
|
||||
</component>
|
||||
<component name="DBNavigator.Project.DatabaseFileManager">
|
||||
<open-files />
|
||||
</component>
|
||||
<component name="DBNavigator.Project.ExecutionManager">
|
||||
<retain-sticky-names value="false" />
|
||||
</component>
|
||||
<component name="DBNavigator.Project.ParserDiagnosticsManager">
|
||||
<diagnostics-history />
|
||||
</component>
|
||||
<component name="DBNavigator.Project.Settings">
|
||||
<connections />
|
||||
<browser-settings>
|
||||
|
||||
@@ -61,6 +61,59 @@ public class OpcMessageSend {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用写入方法,用于向指定 OPC 节点写入一个值
|
||||
* @param address OPC 节点地址 (e.g., "ns=2;s=ProcessCGL.PLCLine.ExitCut.cutLength")
|
||||
* @param value 要写入的值
|
||||
*/
|
||||
public void writeNode(String address, Object value) {
|
||||
try {
|
||||
List<ReadWriteEntity> entities = new ArrayList<>();
|
||||
entities.add(ReadWriteEntity.builder()
|
||||
.identifier(address)
|
||||
.value(value)
|
||||
.build());
|
||||
miloService.writeToOpcUa(entities);
|
||||
log.info("写入 OPC 成功, node={}, value={}", address, value);
|
||||
} catch (Exception e) {
|
||||
log.error("写入 OPC 失败, node={}, value={}, 原因: {}", address, value, e.getMessage(), e);
|
||||
// 抛出运行时异常,以便上层调用者(如 SendJobServiceImpl)可以捕获并处理失败状态
|
||||
throw new RuntimeException("写入 OPC 失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入 OPC 节点(增强版):根据字符串值尝试转换为数值/布尔,再写入
|
||||
* 规则:
|
||||
* 1) 先尝试转 Integer
|
||||
* 2) 再尝试转 Double
|
||||
* 3) 再尝试转 Boolean(true/false/1/0)
|
||||
* 4) 都不行则按原字符串写入
|
||||
*/
|
||||
public void writeNode(String address, String valueRaw) {
|
||||
Object v = valueRaw;
|
||||
if (valueRaw != null) {
|
||||
String s = valueRaw.trim();
|
||||
// boolean
|
||||
if ("1".equals(s) || "0".equals(s) || "true".equalsIgnoreCase(s) || "false".equalsIgnoreCase(s)) {
|
||||
v = ("1".equals(s) || "true".equalsIgnoreCase(s));
|
||||
} else {
|
||||
// int
|
||||
try {
|
||||
v = Integer.parseInt(s);
|
||||
} catch (Exception ignore) {
|
||||
// double
|
||||
try {
|
||||
v = Double.parseDouble(s);
|
||||
} catch (Exception ignore2) {
|
||||
v = valueRaw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
writeNode(address, v);
|
||||
}
|
||||
|
||||
private List<ReadWriteEntity> getWriteEntities(OpcMessage msg, Map<String,String> msgIds) {
|
||||
List<ReadWriteEntity> entities = new ArrayList<>();
|
||||
for (String key : msgIds.keySet()) {
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.fizz.business.controller;
|
||||
|
||||
import com.fizz.business.domain.BizSendTemplate;
|
||||
import com.fizz.business.domain.BizSendTemplateItem;
|
||||
import com.fizz.business.domain.dto.SendTemplateItemsBatchSaveDTO;
|
||||
import com.fizz.business.domain.vo.BizSendTemplateVO;
|
||||
import com.fizz.business.service.IBizSendTemplateItemService;
|
||||
import com.fizz.business.service.IBizSendTemplateService;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 发送模板配置 Controller
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/business/sendTemplate")
|
||||
public class BizSendTemplateController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IBizSendTemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private IBizSendTemplateItemService templateItemService;
|
||||
|
||||
/**
|
||||
* 按模板编码获取模板(含明细)
|
||||
*/
|
||||
@GetMapping("/{templateCode}")
|
||||
public AjaxResult getByCode(@PathVariable String templateCode) {
|
||||
BizSendTemplateVO vo = templateService.getTemplateWithItems(templateCode);
|
||||
if (vo == null) {
|
||||
return AjaxResult.error("Template not found");
|
||||
}
|
||||
return AjaxResult.success(vo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新模板主表(如 deviceName)
|
||||
*/
|
||||
@PutMapping
|
||||
public AjaxResult updateTemplate(@RequestBody BizSendTemplate template) {
|
||||
if (template == null || template.getTemplateId() == null) {
|
||||
return AjaxResult.error("templateId is required");
|
||||
}
|
||||
template.setUpdateBy(SecurityUtils.getUsername());
|
||||
template.setUpdateTime(new Date());
|
||||
return toAjax(templateService.updateById(template));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量更新模板明细(address/defaultValueRaw/enabled等)
|
||||
*/
|
||||
@PutMapping("/items")
|
||||
public AjaxResult updateTemplateItems(@RequestBody List<BizSendTemplateItem> items) {
|
||||
if (items == null || items.isEmpty()) {
|
||||
return AjaxResult.success();
|
||||
}
|
||||
Date now = new Date();
|
||||
String username = SecurityUtils.getUsername();
|
||||
for (BizSendTemplateItem it : items) {
|
||||
it.setUpdateBy(username);
|
||||
it.setUpdateTime(now);
|
||||
}
|
||||
return toAjax(templateItemService.updateItemsBatch(items));
|
||||
}
|
||||
|
||||
/**
|
||||
* 模板明细批量保存(新增/更新/删除)
|
||||
*/
|
||||
@PutMapping("/items/batchSave")
|
||||
public AjaxResult batchSaveItems(@RequestBody SendTemplateItemsBatchSaveDTO dto) {
|
||||
if (dto == null || dto.getTemplateId() == null) {
|
||||
return AjaxResult.error("templateId is required");
|
||||
}
|
||||
try {
|
||||
Boolean ok = templateItemService.batchSave(
|
||||
dto.getTemplateId(),
|
||||
dto.getItems(),
|
||||
dto.getDeleteIds(),
|
||||
SecurityUtils.getUsername()
|
||||
);
|
||||
return toAjax(ok);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.fizz.business.controller;
|
||||
|
||||
|
||||
import com.fizz.business.service.DashboardService;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 首页仪表板相关接口
|
||||
*/
|
||||
@RestController
|
||||
public class DashboardController extends BaseController {
|
||||
|
||||
@Resource
|
||||
private DashboardService dashboardService;
|
||||
|
||||
/**
|
||||
* 当前生产中的计划信息(crm_pdi_plan.status = 'PRODUCING')
|
||||
*/
|
||||
@GetMapping("/api/business/dashboard/currentPlan")
|
||||
public AjaxResult getCurrentProducingPlan() {
|
||||
return AjaxResult.success(dashboardService.getCurrentProducingPlan());
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前生产卷的关键工艺参数
|
||||
* - 从 cpl_segment_total.total_values_json 解析
|
||||
* - 键名来自 DeviceEnum.paramFields
|
||||
*/
|
||||
@GetMapping("/api/business/dashboard/currentProcess")
|
||||
public AjaxResult getCurrentProcessParams() {
|
||||
return AjaxResult.success(dashboardService.getCurrentProcessParams());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.fizz.business.controller;
|
||||
|
||||
import com.fizz.business.domain.BizSendJob;
|
||||
import com.fizz.business.domain.dto.SendJobCreateDTO;
|
||||
import com.fizz.business.domain.dto.SendJobQueryDTO;
|
||||
import com.fizz.business.domain.vo.SendJobDetailVO;
|
||||
import com.fizz.business.service.ISendJobService;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.fizz.business.domain.vo.SendJobLastSuccessVO;
|
||||
import com.fizz.business.service.ISendJobQueryService;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 发送任务 Controller
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/business/sendJob")
|
||||
public class SendJobController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private ISendJobService sendJobService;
|
||||
|
||||
@Autowired
|
||||
private ISendJobQueryService sendJobQueryService;
|
||||
|
||||
/**
|
||||
* 创建发送任务
|
||||
*/
|
||||
@Log(title = "发送任务", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult create(@Validated @RequestBody SendJobCreateDTO dto) {
|
||||
Integer jobId = sendJobService.createSendJob(dto);
|
||||
return success(jobId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询发送任务列表
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(SendJobQueryDTO query) {
|
||||
startPage(); // 使用BaseController的分页方法
|
||||
List<BizSendJob> list = sendJobService.selectSendJobList(query);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取发送任务详情
|
||||
*/
|
||||
@GetMapping("/{jobId}")
|
||||
public AjaxResult getDetail(@PathVariable Integer jobId) {
|
||||
SendJobDetailVO detail = sendJobService.selectSendJobDetail(jobId);
|
||||
return success(detail);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除发送任务(逻辑删除)
|
||||
*/
|
||||
@Log(title = "发送任务", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{jobIds}")
|
||||
public AjaxResult remove(@PathVariable Integer[] jobIds) {
|
||||
return toAjax(sendJobService.deleteSendJobByJobIds(jobIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行发送任务
|
||||
*/
|
||||
@Log(title = "发送任务", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/{jobId}/execute")
|
||||
public AjaxResult execute(@PathVariable Integer jobId) {
|
||||
return toAjax(sendJobService.executeSendJob(jobId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询最近一次成功发送(用于界面显示上次发送时间 + 推荐上次值)
|
||||
* @param groupType DRIVE / FURNACE
|
||||
*/
|
||||
@GetMapping("/lastSuccess")
|
||||
public AjaxResult lastSuccess(@RequestParam String groupType) {
|
||||
SendJobLastSuccessVO vo = sendJobQueryService.getLastSuccess(groupType);
|
||||
return AjaxResult.success(vo);
|
||||
}
|
||||
}
|
||||
@@ -30,57 +30,45 @@ public class SteelGradeInfoController {
|
||||
@Operation(summary = "查询钢种列表")
|
||||
public R<List<StdAlloyVO>> list(@RequestParam(value = "keyword", required = false) String keyword) {
|
||||
|
||||
// 使用 LambdaQueryWrapper 查询 StdAlloy 表中的数据,支持按名称/编号模糊查询
|
||||
// 严格按 cgldb.sql:查询 std_alloy(GRADEID, NAME)
|
||||
LambdaQueryWrapper<StdAlloy> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.select(StdAlloy::getGradeid, StdAlloy::getName); // 只查询 gradeId 和 name 字段
|
||||
queryWrapper.select(StdAlloy::getGradeid, StdAlloy::getName);
|
||||
if (StringUtils.isNotBlank(keyword)) {
|
||||
queryWrapper.like(StdAlloy::getName, keyword)
|
||||
.or()
|
||||
.like(StdAlloy::getGradeid, keyword);
|
||||
}
|
||||
queryWrapper.orderByAsc(StdAlloy::getName); // 按 name 排序
|
||||
queryWrapper.orderByAsc(StdAlloy::getName);
|
||||
|
||||
// 查询 StdAlloy 数据
|
||||
List<StdAlloy> stdAlloyList = steelGradeInfoService.list(queryWrapper);
|
||||
|
||||
// 使用 BeanUtils 将 StdAlloy 对象的字段映射到 StdAlloyVO
|
||||
List<StdAlloyVO> stdAlloyVOList = new ArrayList<>();
|
||||
for (StdAlloy stdAlloy : stdAlloyList) {
|
||||
StdAlloyVO stdAlloyVO = new StdAlloyVO();
|
||||
BeanUtils.copyProperties(stdAlloy, stdAlloyVO); // 将 StdAlloy 属性复制到 StdAlloyVO
|
||||
BeanUtils.copyProperties(stdAlloy, stdAlloyVO);
|
||||
stdAlloyVOList.add(stdAlloyVO);
|
||||
}
|
||||
|
||||
// 返回结果
|
||||
return R.ok(stdAlloyVOList);
|
||||
}
|
||||
|
||||
@GetMapping("/info")
|
||||
@Operation(summary ="询单个钢种详情")
|
||||
public R<StdAlloy> getSteelGradeInfo(@RequestParam Integer gradeid) {
|
||||
|
||||
// 使用 LambdaQueryWrapper 查询 StdAlloy 表中的数据
|
||||
LambdaQueryWrapper<StdAlloy> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(StdAlloy::getGradeid, gradeid); // 只查询 gradeId 和 name 字段
|
||||
|
||||
// 查询 StdAlloy 数据
|
||||
StdAlloy stdAlloyList = steelGradeInfoService.getById(gradeid);
|
||||
|
||||
// 返回结果
|
||||
return R.ok(stdAlloyList);
|
||||
return R.ok(steelGradeInfoService.getById(gradeid));
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/add")
|
||||
@Operation(summary ="新增")
|
||||
public R<Boolean> add(@RequestBody StdAlloy steelGradeInfo) {
|
||||
return R.ok(steelGradeInfoService.save(steelGradeInfo));
|
||||
public R<Boolean> add(@RequestBody StdAlloy stdAlloy) {
|
||||
return R.ok(steelGradeInfoService.save(stdAlloy));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary ="更新")
|
||||
public R<Boolean> update(@RequestBody StdAlloy steelGradeInfo) {
|
||||
return R.ok(steelGradeInfoService.updateById(steelGradeInfo));
|
||||
public R<Boolean> update(@RequestBody StdAlloy stdAlloy) {
|
||||
return R.ok(steelGradeInfoService.updateById(stdAlloy));
|
||||
}
|
||||
|
||||
@Operation(summary ="删除")
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.fizz.business.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 业务发送批次表 biz_send_job
|
||||
*
|
||||
* @author Cascade
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("biz_send_job")
|
||||
public class BizSendJob extends BaseEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 批次ID */
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer jobId;
|
||||
|
||||
/** 业务唯一键, 用于幂等控制 */
|
||||
private String bizKey;
|
||||
|
||||
/** 目标设备/产线名称 (如 CGL_LINE_1, FURNACE_A) */
|
||||
private String deviceName;
|
||||
|
||||
/** 计划发送时间 */
|
||||
private Date planSendTime;
|
||||
|
||||
/** 实际开始发送时间 */
|
||||
private Date actualSendTime;
|
||||
|
||||
/** 发送完成时间 */
|
||||
private Date finishTime;
|
||||
|
||||
/** 批次状态: PENDING, IN_PROGRESS, COMPLETED, PARTIAL_SUCCESS, FAILED */
|
||||
private String status;
|
||||
|
||||
/** 操作员ID */
|
||||
private Long operatorId;
|
||||
|
||||
/** 操作员姓名 */
|
||||
private String operatorName;
|
||||
|
||||
// 解决 BaseEntity 字段导致的未知列问题
|
||||
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
|
||||
private String searchValue;
|
||||
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
|
||||
private java.util.Map<String,Object> params;
|
||||
|
||||
// GroupType
|
||||
private String groupType;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.fizz.business.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 业务发送分组表 biz_send_job_group
|
||||
*
|
||||
* @author Cascade
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("biz_send_job_group")
|
||||
public class BizSendJobGroup extends BaseEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 分组ID */
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer groupId;
|
||||
|
||||
/** 所属批次ID */
|
||||
private Integer jobId;
|
||||
|
||||
/** 在本批次内的组序号 */
|
||||
private Integer groupNo;
|
||||
|
||||
/** 组类型: DRIVE(传动), FURNACE(炉火) */
|
||||
private String groupType;
|
||||
|
||||
/** 组名称 (可选) */
|
||||
private String groupName;
|
||||
|
||||
/** 分组状态: PENDING, IN_PROGRESS, COMPLETED, FAILED */
|
||||
private String status;
|
||||
|
||||
// 解决 BaseEntity 字段导致的未知列问题
|
||||
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
|
||||
private String searchValue;
|
||||
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
|
||||
private java.util.Map<String,Object> params;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.fizz.business.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 业务发送项历史表 biz_send_job_item
|
||||
*
|
||||
* @author Cascade
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("biz_send_job_item")
|
||||
public class BizSendJobItem extends BaseEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 发送项ID */
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer itemId;
|
||||
|
||||
/** 所属批次ID (冗余) */
|
||||
private Integer jobId;
|
||||
|
||||
/** 所属分组ID */
|
||||
private Integer groupId;
|
||||
|
||||
/** 参数业务编码 */
|
||||
private String paramCode;
|
||||
|
||||
/** 设定地址 (OPC地址) */
|
||||
private String address;
|
||||
|
||||
/** 设定的原始值 */
|
||||
private String valueRaw;
|
||||
|
||||
/** 设定值的数值形式 */
|
||||
private BigDecimal valueNum;
|
||||
|
||||
/** 参数的设定时间 */
|
||||
private Date setTime;
|
||||
|
||||
/** 发送结果: PENDING, SUCCESS, FAILED */
|
||||
private String resultStatus;
|
||||
|
||||
/** 结果消息 */
|
||||
private String resultMsg;
|
||||
|
||||
/** 重试次数 */
|
||||
private Integer retryCount;
|
||||
|
||||
// 解决 BaseEntity 字段导致的未知列问题
|
||||
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
|
||||
private String searchValue;
|
||||
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
|
||||
private java.util.Map<String,Object> params;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.fizz.business.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 发送默认模板主表
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("biz_send_template")
|
||||
public class BizSendTemplate extends BaseEntity {
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer templateId;
|
||||
|
||||
// 解决 MyBatis-Plus 父类字段映射导致的 search_value 报错
|
||||
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
|
||||
private String searchValue;
|
||||
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
|
||||
private java.util.Map<String,Object> params;
|
||||
|
||||
/** 模板编码 */
|
||||
private String templateCode;
|
||||
|
||||
/** 模板名称 */
|
||||
private String templateName;
|
||||
|
||||
/** 默认设备名称 */
|
||||
private String deviceName;
|
||||
|
||||
/** 组类型 DRIVE / FURNACE */
|
||||
private String groupType;
|
||||
|
||||
/** 是否启用 */
|
||||
private Integer enabled;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.fizz.business.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 发送默认模板明细表
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("biz_send_template_item")
|
||||
public class BizSendTemplateItem extends BaseEntity {
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer templateItemId;
|
||||
|
||||
private Integer templateId;
|
||||
|
||||
/** 明细序号 */
|
||||
private Integer itemNo;
|
||||
|
||||
/** 参数编码 */
|
||||
private String paramCode;
|
||||
|
||||
/** 英文显示名 */
|
||||
private String labelEn;
|
||||
|
||||
/** 英文分组名 */
|
||||
private String groupNameEn;
|
||||
|
||||
/** OPC地址 */
|
||||
private String address;
|
||||
|
||||
/** 默认值(字符串) */
|
||||
private String defaultValueRaw;
|
||||
|
||||
/** 是否启用 */
|
||||
private Integer enabled;
|
||||
|
||||
// 解决 BaseEntity 字段导致的未知列问题
|
||||
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
|
||||
private String searchValue;
|
||||
@com.baomidou.mybatisplus.annotation.TableField(exist = false)
|
||||
private java.util.Map<String,Object> params;
|
||||
}
|
||||
|
||||
@@ -313,4 +313,8 @@ public class CrmPdiPlan implements Serializable {
|
||||
|
||||
@Schema(description = "原卷号")
|
||||
private String originCoilid;
|
||||
|
||||
//锌层厚度 zinc_coating_thickness
|
||||
@Schema(description = "锌层厚度")
|
||||
private BigDecimal zincCoatingThickness;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@@ -130,4 +131,7 @@ public class CrmPdoExcoil implements Serializable {
|
||||
|
||||
@Schema(description = "计划来源:L3-L3计划,MANUAL-人工")
|
||||
private String planOrigin;
|
||||
|
||||
@Schema(description = "锌层厚度")
|
||||
private BigDecimal zincCoatingThickness;
|
||||
}
|
||||
@@ -2,10 +2,12 @@ package com.fizz.business.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@TableName("std_alloy")
|
||||
public class StdAlloy {
|
||||
|
||||
@TableId("GRADEID")
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.fizz.business.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 创建发送任务 DTO
|
||||
*/
|
||||
@Data
|
||||
public class SendJobCreateDTO {
|
||||
|
||||
/** 目标设备/产线名称 (如 CGL_LINE_1, FURNACE_A) */
|
||||
@NotBlank(message = "deviceName不能为空")
|
||||
private String deviceName;
|
||||
|
||||
/** 计划发送时间 */
|
||||
private Date planSendTime;
|
||||
|
||||
/** 操作员ID */
|
||||
private Long operatorId;
|
||||
|
||||
/** 操作员姓名 */
|
||||
private String operatorName;
|
||||
|
||||
/** 分组列表 */
|
||||
@Valid
|
||||
@NotNull(message = "groups不能为空")
|
||||
@Size(min = 1, message = "至少需要一个分组")
|
||||
private List<GroupDTO> groups;
|
||||
|
||||
@Data
|
||||
public static class GroupDTO {
|
||||
|
||||
/** 在本批次内的组序号 */
|
||||
@NotNull(message = "groupNo不能为空")
|
||||
private Integer groupNo;
|
||||
|
||||
/** 组类型: DRIVE(传动), FURNACE(炉火) */
|
||||
@NotBlank(message = "groupType不能为空")
|
||||
private String groupType;
|
||||
|
||||
/** 组名称 (可选) */
|
||||
private String groupName;
|
||||
|
||||
/** 参数项列表 */
|
||||
@Valid
|
||||
@NotNull(message = "items不能为空")
|
||||
@Size(min = 1, message = "至少需要一个参数项")
|
||||
private List<ItemDTO> items;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class ItemDTO {
|
||||
|
||||
/** 参数业务编码 */
|
||||
private String paramCode;
|
||||
|
||||
/** 设定地址 (OPC地址) */
|
||||
@NotBlank(message = "address不能为空")
|
||||
private String address;
|
||||
|
||||
/** 设定的原始值 */
|
||||
private String valueRaw;
|
||||
|
||||
/** 参数的设定时间 */
|
||||
private Date setTime;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.fizz.business.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 发送任务查询 DTO
|
||||
* 说明:分页参数沿用 RuoYi BaseController 的 startPage() 机制,从 request 里取 pageNum/pageSize。
|
||||
*/
|
||||
@Data
|
||||
public class SendJobQueryDTO {
|
||||
|
||||
/** 设备/产线名称 */
|
||||
private String deviceName;
|
||||
|
||||
/** 状态: PENDING, IN_PROGRESS, COMPLETED, PARTIAL_SUCCESS, FAILED, DELETED */
|
||||
private String status;
|
||||
|
||||
/** 分组类型: DRIVE / FURNACE */
|
||||
private String groupType;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.fizz.business.domain.dto;
|
||||
|
||||
import com.fizz.business.domain.BizSendTemplateItem;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 模板明细批量保存(新增/更新/删除)
|
||||
*/
|
||||
@Data
|
||||
public class SendTemplateItemsBatchSaveDTO {
|
||||
|
||||
/** 模板ID */
|
||||
private Integer templateId;
|
||||
|
||||
/** 需要新增/更新的明细 */
|
||||
private List<BizSendTemplateItem> items;
|
||||
|
||||
/** 需要删除的明细ID */
|
||||
private List<Integer> deleteIds;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.fizz.business.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 模板明细 VO
|
||||
*/
|
||||
@Data
|
||||
public class BizSendTemplateItemVO {
|
||||
private Integer templateItemId;
|
||||
private Integer templateId;
|
||||
private Integer itemNo;
|
||||
private String paramCode;
|
||||
private String labelEn;
|
||||
private String groupNameEn;
|
||||
private String address;
|
||||
private String defaultValueRaw;
|
||||
|
||||
private Boolean enabled;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.fizz.business.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 模板主VO(含明细)
|
||||
*/
|
||||
@Data
|
||||
public class BizSendTemplateVO {
|
||||
private Integer templateId;
|
||||
private String templateCode;
|
||||
private String templateName;
|
||||
private String deviceName;
|
||||
private String groupType;
|
||||
private Integer enabled;
|
||||
|
||||
private List<BizSendTemplateItemVO> items;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.fizz.business.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 发送任务详情 VO
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class SendJobDetailVO extends SendJobVO {
|
||||
|
||||
private Date planSendTime;
|
||||
|
||||
private Date actualSendTime;
|
||||
|
||||
private Date finishTime;
|
||||
|
||||
private String remark;
|
||||
|
||||
private List<SendJobGroupVO> groups;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.fizz.business.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 发送任务分组 VO
|
||||
*/
|
||||
@Data
|
||||
public class SendJobGroupVO {
|
||||
|
||||
private Integer groupId;
|
||||
|
||||
private Integer jobId;
|
||||
|
||||
private Integer groupNo;
|
||||
|
||||
private String groupType;
|
||||
|
||||
private String groupName;
|
||||
|
||||
private String status;
|
||||
|
||||
private List<SendJobItemVO> items;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.fizz.business.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 发送任务明细项 VO
|
||||
*/
|
||||
@Data
|
||||
public class SendJobItemVO {
|
||||
|
||||
private Integer itemId;
|
||||
|
||||
private Integer jobId;
|
||||
|
||||
private Integer groupId;
|
||||
|
||||
private String paramCode;
|
||||
|
||||
private String address;
|
||||
|
||||
private String valueRaw;
|
||||
|
||||
private BigDecimal valueNum;
|
||||
|
||||
private Date setTime;
|
||||
|
||||
private String resultStatus;
|
||||
|
||||
private String resultMsg;
|
||||
|
||||
private Integer retryCount;
|
||||
|
||||
private LocalDateTime createTime;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.fizz.business.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 最近一次成功发送结果(用于前端推荐默认值 + 显示上次发送时间)
|
||||
*/
|
||||
@Data
|
||||
public class SendJobLastSuccessVO {
|
||||
|
||||
/** 最近一次成功发送时间(job.finish_time) */
|
||||
private Date lastSendTime;
|
||||
|
||||
/** paramCode -> valueRaw */
|
||||
private Map<String, String> values;
|
||||
|
||||
/** 最近一次成功的jobId(可选) */
|
||||
private Integer jobId;
|
||||
|
||||
//IsFromHistory
|
||||
private Boolean isFromHistory;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.fizz.business.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 发送任务列表 VO
|
||||
*/
|
||||
@Data
|
||||
public class SendJobVO {
|
||||
|
||||
private Integer jobId;
|
||||
|
||||
private String bizKey;
|
||||
|
||||
private String deviceName;
|
||||
|
||||
private String status;
|
||||
|
||||
private Long operatorId;
|
||||
|
||||
private String operatorName;
|
||||
|
||||
private Date createTime;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 子计划数据
|
||||
@@ -57,4 +58,7 @@ public class PdiPlanSubDTO implements Serializable {
|
||||
|
||||
@Schema(description = "实际重量")
|
||||
private Double actualWeight;
|
||||
|
||||
@Schema(description = "锌层厚度")
|
||||
private BigDecimal zincCoatingThickness;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
@@ -71,4 +72,7 @@ public class PdoExCoilSubDTO implements Serializable {
|
||||
|
||||
@Schema(description = "结束时间")
|
||||
private LocalDateTime endTime;
|
||||
|
||||
@Schema(description = "锌层厚度")
|
||||
private BigDecimal zincCoatingThickness;
|
||||
}
|
||||
|
||||
@@ -115,5 +115,5 @@ public class CrmPdiPlanForm {
|
||||
private BigDecimal tailendGaugeLength; // 尾端测厚长度(mm)
|
||||
private String origin; // 产地
|
||||
private String originCoilid; // 原卷号
|
||||
|
||||
private BigDecimal zincCoatingThickness;//锌层厚度
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.fizz.business.form;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@@ -18,4 +19,7 @@ public class CrmPdoExcoilForm {
|
||||
@Schema(description = "结束日期")
|
||||
private String endDate;
|
||||
|
||||
@Schema(description = "锌层厚度")
|
||||
private BigDecimal zincCoatingThickness;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.fizz.business.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.fizz.business.domain.BizSendJobGroup;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface BizSendJobGroupMapper extends BaseMapper<BizSendJobGroup> {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.fizz.business.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.fizz.business.domain.BizSendJobItem;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface BizSendJobItemMapper extends BaseMapper<BizSendJobItem> {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.fizz.business.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.fizz.business.domain.BizSendJob;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface BizSendJobMapper extends BaseMapper<BizSendJob> {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.fizz.business.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.fizz.business.domain.BizSendTemplateItem;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface BizSendTemplateItemMapper extends BaseMapper<BizSendTemplateItem> {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.fizz.business.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.fizz.business.domain.BizSendTemplate;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface BizSendTemplateMapper extends BaseMapper<BizSendTemplate> {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.fizz.business.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 计划相关仪表板 Mapper(crm_pdi_plan)
|
||||
*/
|
||||
@Mapper
|
||||
public interface PlanDashboardMapper {
|
||||
|
||||
/**
|
||||
* 查询当前生产中的计划(status = 'PRODUCING')
|
||||
* 返回字段至少包括:
|
||||
* - coilid, planid, steel_grade, entry_weight, entry_thick, entry_width, start_date 等
|
||||
*/
|
||||
Map<String, Object> selectCurrentProducingPlan();
|
||||
}
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
package com.fizz.business.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.fizz.business.domain.SegmentTotal;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 各机张力,电流等架跟踪表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author baomidou
|
||||
* @since 2023-10-26
|
||||
* 带钢段工艺参数 Mapper(cpl_segment_total)
|
||||
*/
|
||||
@Mapper
|
||||
public interface SegmentTotalMapper extends BaseMapper<SegmentTotal> {
|
||||
SegmentTotal getLatestRecord();
|
||||
public interface SegmentTotalMapper {
|
||||
|
||||
/**
|
||||
* 根据入库钢卷号查询最新一段的 total_values_json
|
||||
*/
|
||||
String selectLatestTotalValuesJsonByCoilId(@Param("coilId") String coilId);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.fizz.business.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.fizz.business.domain.StdAlloy;
|
||||
import com.fizz.business.domain.SteelGradeInfo;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.fizz.business.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 首页仪表板统计服务
|
||||
*/
|
||||
public interface DashboardService {
|
||||
|
||||
/**
|
||||
* 当前生产中的计划信息(包含卷号、规格、时间等)
|
||||
*/
|
||||
Map<String, Object> getCurrentProducingPlan();
|
||||
|
||||
/**
|
||||
* 当前生产卷的关键工艺参数
|
||||
* 结构说明(示例):
|
||||
* {
|
||||
* "coilId": "...",
|
||||
* "entrySection": { "POR1": { ... }, "POR2": { ... }, ... },
|
||||
* "processSection":{ "CLEAN": { ... }, "FUR1": { ... }, ... },
|
||||
* "exitSection": { "TR": { ... }, "CXL1": { ... }, ... }
|
||||
* }
|
||||
*/
|
||||
Map<String, Object> getCurrentProcessParams();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.fizz.business.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.fizz.business.domain.BizSendTemplateItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 发送模板明细 Service
|
||||
*/
|
||||
public interface IBizSendTemplateItemService extends IService<BizSendTemplateItem> {
|
||||
|
||||
/**
|
||||
* 批量更新模板明细(仅更新已有ID)
|
||||
*/
|
||||
Boolean updateItemsBatch(List<BizSendTemplateItem> items);
|
||||
|
||||
/**
|
||||
* 批量保存模板明细(新增/更新/删除)
|
||||
*/
|
||||
Boolean batchSave(Integer templateId, List<BizSendTemplateItem> items, List<Integer> deleteIds, String username);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.fizz.business.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.fizz.business.domain.BizSendTemplate;
|
||||
import com.fizz.business.domain.vo.BizSendTemplateVO;
|
||||
|
||||
/**
|
||||
* 发送默认模板 Service
|
||||
*/
|
||||
public interface IBizSendTemplateService extends IService<BizSendTemplate> {
|
||||
|
||||
/**
|
||||
* 按模板编码获取模板(含明细)
|
||||
*/
|
||||
BizSendTemplateVO getTemplateWithItems(String templateCode);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.fizz.business.service;
|
||||
|
||||
import com.fizz.business.domain.vo.SendJobLastSuccessVO;
|
||||
|
||||
/**
|
||||
* 发送任务查询扩展(用于推荐值、上次发送时间)
|
||||
*/
|
||||
public interface ISendJobQueryService {
|
||||
|
||||
/**
|
||||
* 查询最近一次成功发送(按 groupType 过滤:DRIVE / FURNACE)
|
||||
*/
|
||||
SendJobLastSuccessVO getLastSuccess(String groupType);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.fizz.business.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.fizz.business.domain.BizSendJob;
|
||||
import com.fizz.business.domain.dto.SendJobCreateDTO;
|
||||
import com.fizz.business.domain.dto.SendJobQueryDTO;
|
||||
import com.fizz.business.domain.vo.SendJobDetailVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 发送任务 Service
|
||||
*/
|
||||
public interface ISendJobService extends IService<BizSendJob> {
|
||||
|
||||
/**
|
||||
* 创建发送任务(包含分组与明细)
|
||||
*/
|
||||
Integer createSendJob(SendJobCreateDTO dto);
|
||||
|
||||
/**
|
||||
* 查询发送任务列表(分页由 Controller 的 startPage() 控制)
|
||||
*/
|
||||
List<BizSendJob> selectSendJobList(SendJobQueryDTO query);
|
||||
|
||||
/**
|
||||
* 查询发送任务详情(包含分组与明细)
|
||||
*/
|
||||
SendJobDetailVO selectSendJobDetail(Integer jobId);
|
||||
|
||||
/**
|
||||
* 删除任务(逻辑删除:status=DELETED)
|
||||
*/
|
||||
Boolean deleteSendJobByJobIds(Integer[] jobIds);
|
||||
|
||||
/**
|
||||
* 执行发送:写入 OPC,并将发送结果保存为历史(更新 job/group/item 状态)
|
||||
*/
|
||||
Boolean executeSendJob(Integer jobId);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.fizz.business.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.fizz.business.domain.StdAlloy;
|
||||
import com.fizz.business.domain.SteelGradeInfo;
|
||||
|
||||
public interface SteelGradeInfoService extends IService<StdAlloy> {
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.fizz.business.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.fizz.business.domain.BizSendTemplateItem;
|
||||
import com.fizz.business.mapper.BizSendTemplateItemMapper;
|
||||
import com.fizz.business.service.IBizSendTemplateItemService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
public class BizSendTemplateItemServiceImpl extends ServiceImpl<BizSendTemplateItemMapper, BizSendTemplateItem> implements IBizSendTemplateItemService {
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean updateItemsBatch(List<BizSendTemplateItem> items) {
|
||||
if (items == null || items.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
// MyBatis-Plus 批量更新:这里简单循环 updateById(数量约40~100可接受)
|
||||
for (BizSendTemplateItem it : items) {
|
||||
this.updateById(it);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean batchSave(Integer templateId, List<BizSendTemplateItem> items, List<Integer> deleteIds, String username) {
|
||||
Date now = new Date();
|
||||
|
||||
// 1) 删除(物理删除)。如果你们希望逻辑删除,可在此改为 enabled=0 / deleted 标记。
|
||||
if (deleteIds != null && !deleteIds.isEmpty()) {
|
||||
this.removeByIds(deleteIds);
|
||||
}
|
||||
|
||||
// 2) 新增/更新
|
||||
if (items == null) {
|
||||
items = Collections.emptyList();
|
||||
}
|
||||
|
||||
// 基础校验:templateId 必须一致
|
||||
for (BizSendTemplateItem it : items) {
|
||||
if (it.getTemplateId() == null) {
|
||||
it.setTemplateId(templateId);
|
||||
}
|
||||
}
|
||||
|
||||
// 校验:同一 templateId 下 paramCode 唯一
|
||||
// - 先校验本次提交内是否重复
|
||||
Set<String> seen = new HashSet<>();
|
||||
for (BizSendTemplateItem it : items) {
|
||||
if (it.getParamCode() == null || it.getParamCode().trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("paramCode is required");
|
||||
}
|
||||
String code = it.getParamCode().trim();
|
||||
if (!seen.add(code)) {
|
||||
throw new IllegalArgumentException("Duplicate paramCode in request: " + code);
|
||||
}
|
||||
it.setParamCode(code);
|
||||
}
|
||||
|
||||
// - 再校验数据库里是否已存在同 paramCode(排除自身ID)
|
||||
for (BizSendTemplateItem it : items) {
|
||||
LambdaQueryWrapper<BizSendTemplateItem> qw = new LambdaQueryWrapper<>();
|
||||
qw.eq(BizSendTemplateItem::getTemplateId, templateId)
|
||||
.eq(BizSendTemplateItem::getParamCode, it.getParamCode());
|
||||
if (it.getTemplateItemId() != null) {
|
||||
qw.ne(BizSendTemplateItem::getTemplateItemId, it.getTemplateItemId());
|
||||
}
|
||||
long cnt = this.count(qw);
|
||||
if (cnt > 0) {
|
||||
throw new IllegalArgumentException("paramCode already exists: " + it.getParamCode());
|
||||
}
|
||||
}
|
||||
|
||||
for (BizSendTemplateItem it : items) {
|
||||
it.setTemplateId(templateId);
|
||||
if (it.getTemplateItemId() == null) {
|
||||
it.setCreateBy(username);
|
||||
it.setCreateTime(now);
|
||||
it.setUpdateBy(username);
|
||||
it.setUpdateTime(now);
|
||||
this.save(it);
|
||||
} else {
|
||||
it.setUpdateBy(username);
|
||||
it.setUpdateTime(now);
|
||||
this.updateById(it);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.fizz.business.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.fizz.business.domain.BizSendTemplate;
|
||||
import com.fizz.business.domain.BizSendTemplateItem;
|
||||
import com.fizz.business.domain.vo.BizSendTemplateItemVO;
|
||||
import com.fizz.business.domain.vo.BizSendTemplateVO;
|
||||
import com.fizz.business.mapper.BizSendTemplateItemMapper;
|
||||
import com.fizz.business.mapper.BizSendTemplateMapper;
|
||||
import com.fizz.business.service.IBizSendTemplateService;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class BizSendTemplateServiceImpl extends ServiceImpl<BizSendTemplateMapper, BizSendTemplate> implements IBizSendTemplateService {
|
||||
|
||||
@Autowired
|
||||
private BizSendTemplateItemMapper templateItemMapper;
|
||||
|
||||
@Override
|
||||
public BizSendTemplateVO getTemplateWithItems(String templateCode) {
|
||||
BizSendTemplate template = this.lambdaQuery()
|
||||
.eq(BizSendTemplate::getTemplateCode, templateCode)
|
||||
.eq(BizSendTemplate::getEnabled, 1)
|
||||
.one();
|
||||
|
||||
if (template == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<BizSendTemplateItem> items = templateItemMapper.selectList(
|
||||
new LambdaQueryWrapper<BizSendTemplateItem>()
|
||||
.eq(BizSendTemplateItem::getTemplateId, template.getTemplateId())
|
||||
.eq(BizSendTemplateItem::getEnabled, 1)
|
||||
.orderByAsc(BizSendTemplateItem::getItemNo)
|
||||
);
|
||||
|
||||
BizSendTemplateVO vo = new BizSendTemplateVO();
|
||||
BeanUtils.copyProperties(template, vo);
|
||||
|
||||
List<BizSendTemplateItemVO> itemVOs = items.stream().map(item -> {
|
||||
BizSendTemplateItemVO it = new BizSendTemplateItemVO();
|
||||
BeanUtils.copyProperties(item, it);
|
||||
return it;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
vo.setItems(itemVOs);
|
||||
return vo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package com.fizz.business.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fizz.business.constants.enums.DeviceEnum;
|
||||
import com.fizz.business.mapper.PlanDashboardMapper;
|
||||
import com.fizz.business.mapper.SegmentTotalMapper;
|
||||
import com.fizz.business.service.DashboardService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 首页仪表板统计服务实现
|
||||
*/
|
||||
@Service
|
||||
public class DashboardServiceImpl implements DashboardService {
|
||||
|
||||
@Resource
|
||||
private PlanDashboardMapper planDashboardMapper;
|
||||
|
||||
@Resource
|
||||
private SegmentTotalMapper segmentTotalMapper;
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getCurrentProducingPlan() {
|
||||
// 查询当前 PRODUCING 的计划
|
||||
Map<String, Object> plan = planDashboardMapper.selectCurrentProducingPlan();
|
||||
if (plan == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return plan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getCurrentProcessParams() {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
|
||||
// 1. 当前生产计划
|
||||
Map<String, Object> plan = planDashboardMapper.selectCurrentProducingPlan();
|
||||
if (plan == null || plan.get("coilid") == null) {
|
||||
return result;
|
||||
}
|
||||
String coilId = String.valueOf(plan.get("coilid"));
|
||||
result.put("coilId", coilId);
|
||||
|
||||
// 2. 查询该卷最新一段的 total_values_json
|
||||
String totalValuesJson = segmentTotalMapper.selectLatestTotalValuesJsonByCoilId(coilId);
|
||||
if (totalValuesJson == null || totalValuesJson.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
try {
|
||||
// 3. 解析 JSON -> Map<String, Object>
|
||||
Map<String, Object> valuesMap = objectMapper.readValue(
|
||||
totalValuesJson,
|
||||
new TypeReference<Map<String, Object>>() {}
|
||||
);
|
||||
|
||||
// 4. 按设备 + 段类型整理数据
|
||||
Map<String, Object> entrySection = new LinkedHashMap<>();
|
||||
Map<String, Object> processSection = new LinkedHashMap<>();
|
||||
Map<String, Object> exitSection = new LinkedHashMap<>();
|
||||
|
||||
for (DeviceEnum device : DeviceEnum.values()) {
|
||||
List<String> fields = device.getParamFields();
|
||||
if (fields == null || fields.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<String, Object> devData = new LinkedHashMap<>();
|
||||
for (String field : fields) {
|
||||
if (valuesMap.containsKey(field)) {
|
||||
devData.put(field, valuesMap.get(field));
|
||||
}
|
||||
}
|
||||
|
||||
if (devData.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// key 用设备英文枚举名,如 POR1/FUR1/TM/TL/COAT 等
|
||||
String key = device.name();
|
||||
switch (device.getSectionType()) {
|
||||
case ENTRY:
|
||||
entrySection.put(key, devData);
|
||||
break;
|
||||
case PROCESS:
|
||||
processSection.put(key, devData);
|
||||
break;
|
||||
case EXIT:
|
||||
exitSection.put(key, devData);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result.put("entrySection", entrySection);
|
||||
result.put("processSection", processSection);
|
||||
result.put("exitSection", exitSection);
|
||||
} catch (Exception e) {
|
||||
// 解析异常时,可按你项目的日志方案记录
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class PdoExCoilServiceImpl implements PdoExCoilService {
|
||||
|
||||
double aimWeightTop = 1;
|
||||
double aimWeightBottom = 1;
|
||||
|
||||
pdoExCoilDTO.setZincCoatingThickness(plan.getZincCoatingThickness());
|
||||
pdoExCoilDTO.setPlanOrigin(plan.getUnitCode());
|
||||
pdoExCoilDTO.setUnitCode(plan.getUnitCode());
|
||||
pdoExCoilDTO.setProcessCode(SYSTEM_MODULE);
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
package com.fizz.business.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.fizz.business.domain.BizSendJob;
|
||||
import com.fizz.business.domain.BizSendJobGroup;
|
||||
import com.fizz.business.domain.BizSendJobItem;
|
||||
import com.fizz.business.domain.CrmPdiPlan;
|
||||
import com.fizz.business.domain.vo.BizSendTemplateItemVO;
|
||||
import com.fizz.business.domain.vo.BizSendTemplateVO;
|
||||
import com.fizz.business.domain.vo.SendJobLastSuccessVO;
|
||||
import com.fizz.business.mapper.BizSendJobGroupMapper;
|
||||
import com.fizz.business.mapper.BizSendJobItemMapper;
|
||||
import com.fizz.business.mapper.BizSendJobMapper;
|
||||
import com.fizz.business.mapper.CrmPdiPlanMapper;
|
||||
import com.fizz.business.service.IBizSendTemplateService;
|
||||
import com.fizz.business.service.ISendJobQueryService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class SendJobQueryServiceImpl implements ISendJobQueryService {
|
||||
|
||||
@Autowired
|
||||
private BizSendJobMapper jobMapper;
|
||||
|
||||
@Autowired
|
||||
private BizSendJobGroupMapper groupMapper;
|
||||
|
||||
@Autowired
|
||||
private BizSendJobItemMapper itemMapper;
|
||||
|
||||
@Autowired
|
||||
private IBizSendTemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private CrmPdiPlanMapper planMapper;
|
||||
|
||||
@Override
|
||||
public SendJobLastSuccessVO getLastSuccess(String groupType) {
|
||||
// 1. 根据 groupType 从 group 表中找到所有相关的 job_id
|
||||
List<BizSendJobGroup> groupsWithType = groupMapper.selectList(
|
||||
new LambdaQueryWrapper<BizSendJobGroup>().eq(BizSendJobGroup::getGroupType, groupType)
|
||||
);
|
||||
|
||||
if (CollectionUtils.isEmpty(groupsWithType)) {
|
||||
// 如果一个相关的 group 都没有,直接走 fallback 逻辑
|
||||
return getFallbackValues(groupType);
|
||||
}
|
||||
|
||||
List<Integer> jobIds = groupsWithType.stream()
|
||||
.map(BizSendJobGroup::getJobId)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 2. 在这些 job_id 中,找到状态为 COMPLETED 且时间最新的一个 job
|
||||
BizSendJob lastJob = jobMapper.selectOne(
|
||||
new LambdaQueryWrapper<BizSendJob>()
|
||||
.in(BizSendJob::getJobId, jobIds)
|
||||
.eq(BizSendJob::getStatus, "COMPLETED")
|
||||
.orderByDesc(BizSendJob::getFinishTime)
|
||||
.last("LIMIT 1")
|
||||
);
|
||||
|
||||
// 如果找到了,直接返回上次成功的值
|
||||
if (lastJob != null) {
|
||||
List<BizSendJobGroup> groups = groupMapper.selectList(
|
||||
new LambdaQueryWrapper<BizSendJobGroup>()
|
||||
.eq(BizSendJobGroup::getJobId, lastJob.getJobId())
|
||||
);
|
||||
if (groups != null && !groups.isEmpty()) {
|
||||
List<Integer> groupIdsForJob = groups.stream().map(BizSendJobGroup::getGroupId).collect(Collectors.toList());
|
||||
List<BizSendJobItem> items = itemMapper.selectList(
|
||||
new LambdaQueryWrapper<BizSendJobItem>()
|
||||
.in(BizSendJobItem::getGroupId, groupIdsForJob)
|
||||
.eq(BizSendJobItem::getResultStatus, "SUCCESS")
|
||||
.orderByAsc(BizSendJobItem::getItemId)
|
||||
);
|
||||
|
||||
Map<String, String> values = new HashMap<>();
|
||||
for (BizSendJobItem it : items) {
|
||||
if (it.getParamCode() == null) continue;
|
||||
values.put(it.getParamCode(), it.getValueRaw());
|
||||
}
|
||||
|
||||
SendJobLastSuccessVO vo = new SendJobLastSuccessVO();
|
||||
vo.setJobId(lastJob.getJobId());
|
||||
vo.setLastSendTime(lastJob.getFinishTime());
|
||||
vo.setValues(values);
|
||||
// 添加一个标志,告诉前端这是真实发送过的值
|
||||
vo.setIsFromHistory(true);
|
||||
return vo;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没找到符合条件的 job,走 fallback 逻辑
|
||||
return getFallbackValues(groupType);
|
||||
}
|
||||
|
||||
private SendJobLastSuccessVO getFallbackValues(String groupType) {
|
||||
if ("FURNACE".equalsIgnoreCase(groupType)) {
|
||||
return getFurnaceTemplateValues();
|
||||
} else if ("DRIVE".equalsIgnoreCase(groupType)) {
|
||||
return getDrivePlanValues();
|
||||
}
|
||||
return null; // 其他情况返回 null
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取炉火工艺模板的默认值
|
||||
*/
|
||||
private SendJobLastSuccessVO getFurnaceTemplateValues() {
|
||||
// "FURNACE_DEFAULT" 是前端写死的模板编码
|
||||
BizSendTemplateVO template = templateService.getTemplateWithItems("FURNACE_DEFAULT");
|
||||
if (template == null || template.getItems() == null || template.getItems().isEmpty()) {
|
||||
return createEmptyResponse("Furnace template 'FURNACE_DEFAULT' not found or is empty.");
|
||||
}
|
||||
|
||||
Map<String, String> values = new HashMap<>();
|
||||
for (BizSendTemplateItemVO item : template.getItems()) {
|
||||
if (item.getEnabled() && item.getParamCode() != null) {
|
||||
values.put(item.getParamCode(), item.getDefaultValueRaw());
|
||||
}
|
||||
}
|
||||
|
||||
SendJobLastSuccessVO vo = new SendJobLastSuccessVO();
|
||||
vo.setValues(values);
|
||||
// 标志为非历史值
|
||||
vo.setIsFromHistory(false);
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前计划的传动参数
|
||||
*/
|
||||
private SendJobLastSuccessVO getDrivePlanValues() {
|
||||
// 优先找 PRODUCING 或 ONLINE 状态的计划,按更新时间倒序取最新的一个
|
||||
CrmPdiPlan currentPlan = planMapper.selectOne(
|
||||
new LambdaQueryWrapper<CrmPdiPlan>()
|
||||
.in(CrmPdiPlan::getStatus, "PRODUCING", "ONLINE")
|
||||
.orderByDesc(CrmPdiPlan::getUpdateTime)
|
||||
.last("LIMIT 1")
|
||||
);
|
||||
|
||||
// 如果没有正在生产的,就找第一个 READY 的计划
|
||||
if (currentPlan == null) {
|
||||
currentPlan = planMapper.selectOne(
|
||||
new LambdaQueryWrapper<CrmPdiPlan>()
|
||||
.eq(CrmPdiPlan::getStatus, "READY")
|
||||
.orderByAsc(CrmPdiPlan::getSeqid)
|
||||
.last("LIMIT 1")
|
||||
);
|
||||
}
|
||||
|
||||
if (currentPlan == null) {
|
||||
return createEmptyResponse("No active or ready plan found.");
|
||||
}
|
||||
|
||||
// 将 CrmPdiPlan 对象的字段反射为 Map
|
||||
Map<String, String> values = new HashMap<>();
|
||||
Field[] fields = CrmPdiPlan.class.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
Object value = field.get(currentPlan);
|
||||
if (value != null) {
|
||||
values.put(field.getName(), String.valueOf(value));
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
// 忽略无法访问的字段
|
||||
}
|
||||
}
|
||||
|
||||
SendJobLastSuccessVO vo = new SendJobLastSuccessVO();
|
||||
vo.setValues(values);
|
||||
vo.setIsFromHistory(false); // 标志为非历史值
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个空的带消息的返回对象
|
||||
*/
|
||||
private SendJobLastSuccessVO createEmptyResponse(String message) {
|
||||
SendJobLastSuccessVO vo = new SendJobLastSuccessVO();
|
||||
vo.setValues(Collections.singletonMap("_message", message));
|
||||
vo.setIsFromHistory(false);
|
||||
return vo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,344 @@
|
||||
package com.fizz.business.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.fizz.business.domain.BizSendJob;
|
||||
import com.fizz.business.domain.BizSendJobGroup;
|
||||
import com.fizz.business.domain.BizSendJobItem;
|
||||
import com.fizz.business.domain.dto.SendJobCreateDTO;
|
||||
import com.fizz.business.domain.dto.SendJobQueryDTO;
|
||||
import com.fizz.business.domain.vo.SendJobDetailVO;
|
||||
import com.fizz.business.domain.vo.SendJobGroupVO;
|
||||
import com.fizz.business.domain.vo.SendJobItemVO;
|
||||
import com.fizz.business.mapper.BizSendJobGroupMapper;
|
||||
import com.fizz.business.mapper.BizSendJobItemMapper;
|
||||
import com.fizz.business.mapper.BizSendJobMapper;
|
||||
import com.fizz.business.service.ISendJobService;
|
||||
import com.fizz.business.service.manager.OpcMessageIdsManager;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class SendJobServiceImpl extends ServiceImpl<BizSendJobMapper, BizSendJob> implements ISendJobService {
|
||||
|
||||
@Autowired
|
||||
private com.fizz.business.comm.OPC.OpcMessageSend opcMessageSend;
|
||||
|
||||
|
||||
@Autowired
|
||||
private BizSendJobGroupMapper jobGroupMapper;
|
||||
|
||||
@Autowired
|
||||
private BizSendJobItemMapper jobItemMapper;
|
||||
|
||||
@Autowired
|
||||
private OpcMessageIdsManager opcMessageIdsManager;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Integer createSendJob(SendJobCreateDTO dto) {
|
||||
// 1. 创建批次
|
||||
BizSendJob job = new BizSendJob();
|
||||
BeanUtils.copyProperties(dto, job);
|
||||
|
||||
// 生成业务唯一键
|
||||
String bizKey = opcMessageIdsManager.generateMessageId("SEND_JOB");
|
||||
job.setBizKey(bizKey);
|
||||
job.setStatus("PENDING");
|
||||
|
||||
// 设置操作人
|
||||
String username = SecurityUtils.getUsername();
|
||||
job.setCreateBy(username);
|
||||
job.setCreateTime(new Date());
|
||||
|
||||
// 保存批次
|
||||
baseMapper.insert(job);
|
||||
|
||||
// 2. 保存分组与明细
|
||||
if (dto.getGroups() != null) {
|
||||
for (SendJobCreateDTO.GroupDTO groupDTO : dto.getGroups()) {
|
||||
// 2.1 保存分组
|
||||
BizSendJobGroup group = new BizSendJobGroup();
|
||||
BeanUtils.copyProperties(groupDTO, group);
|
||||
group.setJobId(job.getJobId());
|
||||
group.setStatus("PENDING");
|
||||
group.setCreateBy(username);
|
||||
group.setCreateTime(new Date());
|
||||
jobGroupMapper.insert(group);
|
||||
|
||||
// 2.2 保存明细项
|
||||
if (groupDTO.getItems() != null) {
|
||||
for (SendJobCreateDTO.ItemDTO itemDTO : groupDTO.getItems()) {
|
||||
BizSendJobItem item = new BizSendJobItem();
|
||||
BeanUtils.copyProperties(itemDTO, item);
|
||||
item.setJobId(job.getJobId());
|
||||
item.setGroupId(group.getGroupId());
|
||||
item.setResultStatus("PENDING");
|
||||
item.setCreateBy(username);
|
||||
item.setCreateTime(new Date());
|
||||
|
||||
// 尝试将valueRaw转为数值
|
||||
try {
|
||||
item.setValueNum(new BigDecimal(itemDTO.getValueRaw()));
|
||||
} catch (Exception e) {
|
||||
log.warn("转换数值失败: {}", itemDTO.getValueRaw(), e);
|
||||
}
|
||||
|
||||
jobItemMapper.insert(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return job.getJobId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BizSendJob> selectSendJobList(SendJobQueryDTO query) {
|
||||
LambdaQueryWrapper<BizSendJob> qw = new LambdaQueryWrapper<>();
|
||||
qw.eq(StringUtils.isNotBlank(query.getDeviceName()),
|
||||
BizSendJob::getDeviceName, query.getDeviceName())
|
||||
.eq(StringUtils.isNotBlank(query.getStatus()),
|
||||
BizSendJob::getStatus, query.getStatus())
|
||||
.orderByDesc(BizSendJob::getCreateTime);
|
||||
|
||||
List<BizSendJob> jobs = baseMapper.selectList(qw);
|
||||
if (jobs == null || jobs.isEmpty()) {
|
||||
return jobs;
|
||||
}
|
||||
|
||||
// 如果传了 groupType(如 FURNACE),则仅保留包含该 groupType 的 job
|
||||
if (StringUtils.isNotBlank(query.getGroupType())) {
|
||||
String gt = query.getGroupType().trim();
|
||||
|
||||
List<Integer> jobIds = jobs.stream().map(BizSendJob::getJobId).collect(Collectors.toList());
|
||||
List<BizSendJobGroup> groups = jobGroupMapper.selectList(
|
||||
new LambdaQueryWrapper<BizSendJobGroup>()
|
||||
.in(BizSendJobGroup::getJobId, jobIds)
|
||||
.eq(BizSendJobGroup::getGroupType, gt)
|
||||
);
|
||||
if (groups == null || groups.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Set<Integer> allowedJobIds = groups.stream().map(BizSendJobGroup::getJobId).collect(Collectors.toSet());
|
||||
return jobs.stream().filter(j -> allowedJobIds.contains(j.getJobId())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
return jobs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SendJobDetailVO selectSendJobDetail(Integer jobId) {
|
||||
// 1. 查询任务
|
||||
BizSendJob job = baseMapper.selectById(jobId);
|
||||
if (job == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 2. 转换为VO
|
||||
SendJobDetailVO detailVO = new SendJobDetailVO();
|
||||
BeanUtils.copyProperties(job, detailVO);
|
||||
|
||||
// 3. 查询分组
|
||||
List<BizSendJobGroup> groups = jobGroupMapper.selectList(
|
||||
new LambdaQueryWrapper<BizSendJobGroup>()
|
||||
.eq(BizSendJobGroup::getJobId, jobId)
|
||||
.orderByAsc(BizSendJobGroup::getGroupNo)
|
||||
);
|
||||
|
||||
if (groups.isEmpty()) {
|
||||
return detailVO;
|
||||
}
|
||||
|
||||
// 4. 查询所有明细项
|
||||
List<Integer> groupIds = groups.stream()
|
||||
.map(BizSendJobGroup::getGroupId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<BizSendJobItem> items = jobItemMapper.selectList(
|
||||
new LambdaQueryWrapper<BizSendJobItem>()
|
||||
.in(BizSendJobItem::getGroupId, groupIds)
|
||||
);
|
||||
|
||||
// 5. 按groupId分组
|
||||
Map<Integer, List<BizSendJobItem>> groupItemsMap = items.stream()
|
||||
.collect(Collectors.groupingBy(BizSendJobItem::getGroupId));
|
||||
|
||||
// 6. 构建分组VO
|
||||
List<SendJobGroupVO> groupVOs = groups.stream().map(group -> {
|
||||
SendJobGroupVO groupVO = new SendJobGroupVO();
|
||||
BeanUtils.copyProperties(group, groupVO);
|
||||
|
||||
// 设置分组下的明细项
|
||||
List<BizSendJobItem> groupItems = groupItemsMap
|
||||
.getOrDefault(group.getGroupId(), Collections.emptyList());
|
||||
|
||||
List<SendJobItemVO> itemVOs = groupItems.stream().map(item -> {
|
||||
SendJobItemVO itemVO = new SendJobItemVO();
|
||||
BeanUtils.copyProperties(item, itemVO);
|
||||
return itemVO;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
groupVO.setItems(itemVOs);
|
||||
return groupVO;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
detailVO.setGroups(groupVOs);
|
||||
return detailVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean deleteSendJobByJobIds(Integer[] jobIds) {
|
||||
if (jobIds == null || jobIds.length == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 1. 更新任务状态为已删除
|
||||
BizSendJob updateJob = new BizSendJob();
|
||||
updateJob.setStatus("DELETED");
|
||||
updateJob.setUpdateBy(SecurityUtils.getUsername());
|
||||
updateJob.setUpdateTime(new Date());
|
||||
|
||||
LambdaQueryWrapper<BizSendJob> qw = new LambdaQueryWrapper<>();
|
||||
qw.in(BizSendJob::getJobId, Arrays.asList(jobIds));
|
||||
|
||||
return update(updateJob, qw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行发送:写入 OPC,并将发送结果保存为历史(更新 job/group/item 状态)
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean executeSendJob(Integer jobId) {
|
||||
BizSendJob job = baseMapper.selectById(jobId);
|
||||
if (job == null) {
|
||||
return false;
|
||||
}
|
||||
if ("DELETED".equalsIgnoreCase(job.getStatus())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 更新 job 状态为发送中
|
||||
BizSendJob jobUpd = new BizSendJob();
|
||||
jobUpd.setJobId(jobId);
|
||||
jobUpd.setStatus("IN_PROGRESS");
|
||||
jobUpd.setActualSendTime(new Date());
|
||||
jobUpd.setUpdateBy(SecurityUtils.getUsername());
|
||||
jobUpd.setUpdateTime(new Date());
|
||||
baseMapper.updateById(jobUpd);
|
||||
|
||||
// 查询该job下所有 PENDING 的 item
|
||||
List<BizSendJobItem> items = jobItemMapper.selectList(
|
||||
new LambdaQueryWrapper<BizSendJobItem>()
|
||||
.eq(BizSendJobItem::getJobId, jobId)
|
||||
.eq(BizSendJobItem::getResultStatus, "PENDING")
|
||||
);
|
||||
|
||||
// 如果没有 PENDING 的项,检查是否有其他状态的项
|
||||
if (items == null || items.isEmpty()) {
|
||||
boolean hasItems = jobItemMapper.selectCount(
|
||||
new LambdaQueryWrapper<BizSendJobItem>().eq(BizSendJobItem::getJobId, jobId)
|
||||
) > 0;
|
||||
|
||||
BizSendJob finish = new BizSendJob();
|
||||
finish.setJobId(jobId);
|
||||
finish.setStatus(hasItems ? "COMPLETED" : "FAILED");
|
||||
finish.setFinishTime(new Date());
|
||||
finish.setUpdateBy(SecurityUtils.getUsername());
|
||||
finish.setUpdateTime(new Date());
|
||||
finish.setRemark(hasItems ? "没有待发送的项" : "没有找到任何发送项");
|
||||
baseMapper.updateById(finish);
|
||||
return hasItems;
|
||||
}
|
||||
|
||||
// 查询该job下group
|
||||
List<BizSendJobGroup> groups = jobGroupMapper.selectList(
|
||||
new LambdaQueryWrapper<BizSendJobGroup>().eq(BizSendJobGroup::getJobId, jobId)
|
||||
);
|
||||
for (BizSendJobGroup g : groups) {
|
||||
BizSendJobGroup gu = new BizSendJobGroup();
|
||||
gu.setGroupId(g.getGroupId());
|
||||
gu.setStatus("IN_PROGRESS");
|
||||
gu.setUpdateBy(SecurityUtils.getUsername());
|
||||
gu.setUpdateTime(new Date());
|
||||
jobGroupMapper.updateById(gu);
|
||||
}
|
||||
|
||||
boolean allSuccess = true;
|
||||
|
||||
// 按 address 分组,只发送最后一条记录
|
||||
Map<String, List<BizSendJobItem>> itemsByAddr = items.stream()
|
||||
.collect(Collectors.groupingBy(BizSendJobItem::getAddress));
|
||||
|
||||
for (Map.Entry<String, List<BizSendJobItem>> entry : itemsByAddr.entrySet()) {
|
||||
List<BizSendJobItem> addrItems = entry.getValue();
|
||||
// 取最后一条(按 itemId 最大 || createTime 最新)
|
||||
addrItems.sort(Comparator.comparing(BizSendJobItem::getItemId));
|
||||
BizSendJobItem last = addrItems.get(addrItems.size() - 1);
|
||||
boolean success = true;
|
||||
String failMsg = null;
|
||||
try {
|
||||
opcMessageSend.writeNode(last.getAddress(), last.getValueRaw());
|
||||
} catch (Exception ex) {
|
||||
success = false;
|
||||
allSuccess = false;
|
||||
failMsg = ex.getMessage();
|
||||
}
|
||||
|
||||
// 更新该 address 下所有项的状态(统一)
|
||||
for (BizSendJobItem it : addrItems) {
|
||||
BizSendJobItem upd = new BizSendJobItem();
|
||||
upd.setItemId(it.getItemId());
|
||||
upd.setResultStatus(success ? "SUCCESS" : "FAILED");
|
||||
upd.setResultMsg(success ? "OK" : failMsg);
|
||||
upd.setUpdateBy(SecurityUtils.getUsername());
|
||||
upd.setUpdateTime(new Date());
|
||||
jobItemMapper.updateById(upd);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新 group 状态(按 group 下 item 是否全部成功)
|
||||
Map<Integer, List<BizSendJobItem>> itemByGroup = jobItemMapper.selectList(
|
||||
new LambdaQueryWrapper<BizSendJobItem>().eq(BizSendJobItem::getJobId, jobId)
|
||||
).stream().collect(Collectors.groupingBy(BizSendJobItem::getGroupId));
|
||||
|
||||
for (BizSendJobGroup g : groups) {
|
||||
List<BizSendJobItem> gi = itemByGroup.getOrDefault(g.getGroupId(), Collections.emptyList());
|
||||
boolean groupOk = gi.stream().allMatch(x -> "SUCCESS".equalsIgnoreCase(x.getResultStatus()));
|
||||
|
||||
BizSendJobGroup gu = new BizSendJobGroup();
|
||||
gu.setGroupId(g.getGroupId());
|
||||
gu.setStatus(groupOk ? "COMPLETED" : "FAILED");
|
||||
gu.setUpdateBy(SecurityUtils.getUsername());
|
||||
gu.setUpdateTime(new Date());
|
||||
jobGroupMapper.updateById(gu);
|
||||
}
|
||||
|
||||
// 更新 job 最终状态
|
||||
BizSendJob finish = new BizSendJob();
|
||||
finish.setJobId(jobId);
|
||||
finish.setFinishTime(new Date());
|
||||
finish.setUpdateBy(SecurityUtils.getUsername());
|
||||
finish.setUpdateTime(new Date());
|
||||
finish.setStatus(allSuccess ? "COMPLETED" : "PARTIAL_SUCCESS");
|
||||
finish.setRemark(allSuccess ? "全部发送成功" : "部分发送失败");
|
||||
baseMapper.updateById(finish);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,16 @@ import java.util.Map;
|
||||
@Component
|
||||
public class OpcMessageIdsManager {
|
||||
|
||||
/**
|
||||
* 生成业务/消息唯一ID(用于发送批次 bizKey 等)
|
||||
* 规则:PREFIX_时间戳_8位随机
|
||||
*/
|
||||
public String generateMessageId(String prefix) {
|
||||
String p = (prefix == null || prefix.trim().isEmpty()) ? "MSG" : prefix.trim();
|
||||
String random = java.util.UUID.randomUUID().toString().replace("-", "").substring(0, 8);
|
||||
return (p + "_" + System.currentTimeMillis() + "_" + random).toUpperCase();
|
||||
}
|
||||
|
||||
public static List<String> msgTriggers = Lists.newArrayList();
|
||||
|
||||
public static Map<String,String> lineMeasureIds = Maps.newHashMap();
|
||||
|
||||
@@ -311,4 +311,7 @@ public class CrmPdiPlanVO {
|
||||
|
||||
@Schema(description = "原卷号")
|
||||
private String originCoilid;
|
||||
|
||||
@Schema(description = "锌层厚度")
|
||||
private BigDecimal zincCoatingThickness;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@@ -145,4 +146,7 @@ public class PdiPlanSetupInfoVO {
|
||||
@Schema(description = "设定值列表")
|
||||
List<ModSetupResultVO> lists;
|
||||
|
||||
@Schema(description = "锌层厚度")
|
||||
private BigDecimal zincCoatingThickness;
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@@ -157,4 +158,7 @@ public class PdiPlanVO implements Serializable {
|
||||
|
||||
@Schema(description = "实验类别")
|
||||
private String experimentType;
|
||||
|
||||
@Schema(description = "锌层厚度")
|
||||
private BigDecimal zincCoatingThickness;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.fizz.business.vo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
|
||||
@@ -80,5 +81,8 @@ public class Plan2PdoVO {
|
||||
@Schema(description = "热卷温度")
|
||||
private Double hotCoilTemp;
|
||||
|
||||
@Schema(description = "锌层厚度")
|
||||
private BigDecimal zincCoatingThickness;
|
||||
|
||||
|
||||
}
|
||||
|
||||
34
business/src/main/resources/mapper/PlanDashboardMapper.xml
Normal file
34
business/src/main/resources/mapper/PlanDashboardMapper.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
|
||||
<mapper namespace="com.fizz.business.mapper.PlanDashboardMapper">
|
||||
|
||||
<!-- 当前生产中的计划(status = 'PRODUCING',按 producing_time / start_date 倒序取最新一条) -->
|
||||
<select id="selectCurrentProducingPlan" resultType="java.util.Map">
|
||||
SELECT
|
||||
id,
|
||||
coilid,
|
||||
planid,
|
||||
steel_grade AS steelGrade,
|
||||
entry_weight AS entryWeight,
|
||||
entry_thick AS entryThick,
|
||||
entry_width AS entryWidth,
|
||||
entry_length AS entryLength,
|
||||
status,
|
||||
start_date AS startDate,
|
||||
end_date AS endDate,
|
||||
producing_time AS producingTime,
|
||||
unit_code AS unitCode
|
||||
FROM crm_pdi_plan
|
||||
WHERE status = 'PRODUCING'
|
||||
ORDER BY
|
||||
producing_time DESC,
|
||||
start_date DESC,
|
||||
id DESC
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -1,7 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
|
||||
<mapper namespace="com.fizz.business.mapper.SegmentTotalMapper">
|
||||
<select id="getLatestRecord" resultType="com.fizz.business.domain.SegmentTotal">
|
||||
SELECT * FROM cpg_segment_total where id=(SELECT max(id) FROM cpg_segment_total)
|
||||
|
||||
<!-- 根据入库钢卷号查询最新一段的 total_values_json -->
|
||||
<select id="selectLatestTotalValuesJsonByCoilId"
|
||||
parameterType="java.lang.String"
|
||||
resultType="java.lang.String">
|
||||
SELECT
|
||||
total_values_json
|
||||
FROM cpl_segment_total
|
||||
WHERE en_coil_id = #{coilId}
|
||||
ORDER BY seg_no DESC
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>0</maxHistory> <!-- 保留0天,生成后立即清理 -->
|
||||
<totalSizeCap>0MB</totalSizeCap> <!-- 总大小限制为0,禁止存储 -->
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>7</maxHistory>
|
||||
<maxHistory>0</maxHistory> <!-- 保留0天,生成后立即清理 -->
|
||||
<totalSizeCap>0MB</totalSizeCap> <!-- 总大小限制为0,禁止存储 -->
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
@@ -51,7 +52,8 @@
|
||||
<!-- 过滤的级别 -->
|
||||
<level>ERROR</level>
|
||||
<!-- 匹配时的操作:接收(记录) -->
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<!-- <onMatch>ACCEPT</onMatch>-->
|
||||
<onMatch>DENY</onMatch> <!-- 拒绝所有ERROR日志 -->
|
||||
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
@@ -83,7 +85,7 @@
|
||||
<!--系统操作日志-->
|
||||
<root level="info">
|
||||
<appender-ref ref="file_info" />
|
||||
<appender-ref ref="file_error" />
|
||||
<!-- <appender-ref ref="file_error" />-->
|
||||
</root>
|
||||
|
||||
<!--系统用户操作日志-->
|
||||
|
||||
@@ -7,7 +7,7 @@ import java.util.Map;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
/**
|
||||
* Entity基类
|
||||
*
|
||||
@@ -19,6 +19,7 @@ public class BaseEntity implements Serializable
|
||||
|
||||
/** 搜索值 */
|
||||
@JsonIgnore
|
||||
@TableField(exist = false)
|
||||
private String searchValue;
|
||||
|
||||
/** 创建者 */
|
||||
|
||||
Reference in New Issue
Block a user