diff --git a/aucma-base/src/main/java/com/aucma/base/domain/BaseOrderInfo.java b/aucma-base/src/main/java/com/aucma/base/domain/BaseOrderInfo.java
index e8d46a3..b57942b 100644
--- a/aucma-base/src/main/java/com/aucma/base/domain/BaseOrderInfo.java
+++ b/aucma-base/src/main/java/com/aucma/base/domain/BaseOrderInfo.java
@@ -272,6 +272,8 @@ public class BaseOrderInfo extends BaseEntity {
public void setActualCompleteQty(Long actualCompleteQty) {
this.actualCompleteQty = actualCompleteQty;
+ // 同步列表展示字段
+ this.completeAmount = actualCompleteQty;
}
public Long getActualDefectQty() {
@@ -380,6 +382,8 @@ public class BaseOrderInfo extends BaseEntity {
public void setCompleteAmount(Long completeAmount) {
this.completeAmount = completeAmount;
+ // 保持展示字段与实际完工数量一致
+ this.actualCompleteQty = completeAmount;
}
public Long getCompleteAmount() {
diff --git a/aucma-base/src/main/resources/mapper/base/BaseMaterialinfoMapper.xml b/aucma-base/src/main/resources/mapper/base/BaseMaterialinfoMapper.xml
index 7fa29df..eab61db 100644
--- a/aucma-base/src/main/resources/mapper/base/BaseMaterialinfoMapper.xml
+++ b/aucma-base/src/main/resources/mapper/base/BaseMaterialinfoMapper.xml
@@ -89,7 +89,7 @@
FROM (
- WHERE ml.is_flag = 1
+ WHERE ml.is_flag = 0
AND (
UPPER(ml.material_code) LIKE '%' || UPPER(#{keyword}) || '%'
diff --git a/aucma-base/src/main/resources/mapper/base/BaseOrderInfoMapper.xml b/aucma-base/src/main/resources/mapper/base/BaseOrderInfoMapper.xml
index fc6aac5..e883565 100644
--- a/aucma-base/src/main/resources/mapper/base/BaseOrderInfoMapper.xml
+++ b/aucma-base/src/main/resources/mapper/base/BaseOrderInfoMapper.xml
@@ -141,7 +141,7 @@
- AND NVL(oi.is_flag, 1) = 1
+ AND NVL(oi.is_flag, 0) = 0
AND oi.material_code IN
diff --git a/aucma-dms/src/main/java/com/aucma/dms/controller/DmsMobileController.java b/aucma-dms/src/main/java/com/aucma/dms/controller/DmsMobileController.java
index 8f21f75..f7fa2e8 100644
--- a/aucma-dms/src/main/java/com/aucma/dms/controller/DmsMobileController.java
+++ b/aucma-dms/src/main/java/com/aucma/dms/controller/DmsMobileController.java
@@ -9,6 +9,7 @@ import com.aucma.dms.domain.*;
import com.aucma.dms.domain.dto.DmsBaseDeviceLedgerDTO;
import com.aucma.dms.domain.vo.DmsBillsFaultInstanceScanVo;
import com.aucma.dms.domain.vo.DmsBillsInspectInstanceScanVo;
+import com.aucma.dms.domain.vo.DmsPdaDeviceParamUpdateVo;
import com.aucma.base.domain.BaseDeviceLedger;
import com.aucma.base.domain.BaseOrderInfo;
import com.aucma.base.service.IBaseDeviceLedgerService;
@@ -252,410 +253,7 @@ public class DmsMobileController extends BaseController {
return dms;
}
- /**
- * PDA-按物料关键字查询关联工单
- */
- @GetMapping("/order/listByMaterial")
- public AjaxResult listOrdersByMaterial(String keyword) {
- // 物料关键字是PDA唯一输入入口,空值时直接拒绝,避免放大后端模糊查询范围
- if (keyword == null || keyword.trim().isEmpty()) {
- throw new ServiceException("物料关键字不能为空");
- }
- try {
- // Why:先按物料主数据检索,再按物料编码反查订单,能保证PDA搜索口径与主数据一致
- List orders = baseOrderInfoService.selectPdaOrderListByMaterialKeyword(keyword.trim());
- return success(orders);
- } catch (Exception e) {
- log.error("PDA按物料查询工单失败 | keyword={}, 异常信息: {}", keyword, e.getMessage(), e);
- throw new ServiceException("查询工单失败: " + e.getMessage());
- }
- }
- /**
- * PDA-维护订单状态与数量
- */
- @PostMapping("/order/updateStatusAndQty")
- @Transactional(rollbackFor = Exception.class)
- public AjaxResult updateOrderStatusAndQty(@RequestBody BaseOrderInfo baseOrderInfo) {
- // 请求体为空时没有任何维护目标,直接拦截比进入service后再判空更清晰
- if (baseOrderInfo == null) {
- throw new ServiceException("请求体不能为空");
- }
- // PDA下拉选中订单后至少应能定位到一条工单,兼容前端传objId或orderCode两种方式
- if (baseOrderInfo.getObjId() == null
- && (baseOrderInfo.getOrderCode() == null || baseOrderInfo.getOrderCode().trim().isEmpty())) {
- throw new ServiceException("objId和orderCode不能同时为空");
- }
- // 状态和数量都在控制器前置校验,避免脏数据落到service或数据库层
- validateOrderExecutionStatus(baseOrderInfo.getExecutionStatus());
- validateOrderQty(baseOrderInfo.getActualCompleteQty(), "完工数量");
- validateOrderQty(baseOrderInfo.getActualDefectQty(), "不良数量");
-
- try {
- // Why:PDA订单维护属于人工修正场景,统一走service封装,避免控制器直接拼装状态流转细节
- int rows = baseOrderInfoService.updatePdaOrderExecution(baseOrderInfo);
- return rows > 0 ? success(rows) : error("工单不存在或更新失败");
- } catch (ServiceException e) {
- throw e;
- } catch (Exception e) {
- log.error("PDA维护订单失败 | objId={}, orderCode={}, executionStatus={}, actualCompleteQty={}, 异常信息: {}",
- baseOrderInfo.getObjId(), baseOrderInfo.getOrderCode(), baseOrderInfo.getExecutionStatus(),
- baseOrderInfo.getActualCompleteQty(), e.getMessage(), e);
- throw new ServiceException("维护订单失败: " + e.getMessage());
- }
- }
-
- private void validateOrderExecutionStatus(String executionStatus) {
- // PDA当前仅允许维护执行态,保持与execution.vue和现有执行页状态枚举一致
- if (executionStatus == null || executionStatus.trim().isEmpty()) {
- throw new ServiceException("执行状态不能为空");
- }
- String normalized = executionStatus.trim();
- if (!ORDER_EXECUTION_PENDING.equals(normalized)
- && !ORDER_EXECUTION_RUNNING.equals(normalized)
- && !ORDER_EXECUTION_PAUSED.equals(normalized)
- && !ORDER_EXECUTION_COMPLETED.equals(normalized)) {
- throw new ServiceException("执行状态不合法");
- }
- }
-
- private void validateOrderQty(Long qty, String fieldName) {
- // 数量允许为空,表示本次只改状态;但一旦传值就必须满足非负约束
- if (qty != null && qty < 0) {
- throw new ServiceException(fieldName + "不能小于0");
- }
- }
-
- // ========== PDA 停机相关 ==========
-
-
- /**
- * 获取OLD开头的设备列表(仅启用)
- */
- @GetMapping("/device/listOld")
- public AjaxResult listOldDevices() {
- BaseDeviceLedger query = new BaseDeviceLedger();
- query.setIsFlag(1L);
- List list = baseDeviceLedgerService.selectBaseDeviceLedgerList(query);
- List resultList = new ArrayList<>();
- if (!CollectionUtils.isEmpty(list)) {
- for (BaseDeviceLedger base : list) {
- if (base.getDeviceCode() != null && base.getDeviceCode().startsWith("OLD")) {
- resultList.add(convertDeviceLedgerToDto(convertToDeviceLedger(base)));
- }
- }
- }
- return success(resultList);
- }
-
-
- /**
- * PDA-获取停机原因列表(仅启用 isFlag=1)
- */
- @GetMapping("/shutReason/list")
- public AjaxResult listShutReasonsForPda(DmsBaseShutReason reason) {
- reason.setIsFlag("1");
- List list = dmsBaseShutReasonService.selectDmsBaseShutReasonList(reason);
- return success(list);
- }
-
- /**
- * PDA-新增停机记录:根据停机原因自动匹配停机类型
- */
- @PostMapping("/shutDown/add")
- @Transactional(rollbackFor = Exception.class)
- public AjaxResult addShutDownForPda(@RequestBody DmsRecordShutDown shutDown) {
- try {
- // 若传入了停机原因ID,则查询原因并回填类型
- if (shutDown.getShutReason() != null) {
- DmsBaseShutReason query = new DmsBaseShutReason();
- query.setShutReason(shutDown.getShutReason());
- query.setIsFlag("1");
- List reasons = dmsBaseShutReasonService.selectDmsBaseShutReasonList(query);
- if (!reasons.isEmpty()) {
- shutDown.setShutType(reasons.get(0).getShutTypeId());
- shutDown.setShutReasonId(reasons.get(0).getShutReasonId());
- // 若前端未传 deviceId,尝试从原因带出
- if (shutDown.getDeviceId() == null) {
- shutDown.setDeviceId(reasons.get(0).getDeviceId());
- }
- }
- }
- // 默认启用标识
- if (shutDown.getIsFlag() == null) {
- shutDown.setIsFlag(1L);
- }
- // 新增停机记录默认未结束
- if (shutDown.getDowntimeFlag() == null) {
- shutDown.setDowntimeFlag("0");
- }
- // 若未传入开始时间,则使用当前时间
- if (shutDown.getShutBeginTime() == null) {
- shutDown.setShutBeginTime(new Date());
- }
- int rows = dmsRecordShutDownService.insertDmsRecordShutDown(shutDown);
-
- // 对指定设备(OLD-01~OLD-05)同步写入三色灯状态参数,供设备状态统计使用
- String deviceCode = shutDown.getDeviceCode();
- if (deviceCode != null && deviceCode.startsWith("OLD-")) {
- // 新增停机记录代表进入停机,三色灯置为“暂停”
- insertTriColorStatusParams(deviceCode, shutDown.getDeviceId(), false);
- }
-
- return success(rows);
- } catch (Exception e) {
- // 系统异常统一落日志并转业务异常,避免将内部堆栈直接暴露给调用方
- log.error("PDA新增停机记录失败 | deviceCode={}, shutReason={}, deviceId={}, 异常信息: {}",
- shutDown.getDeviceCode(), shutDown.getShutReason(), shutDown.getDeviceId(), e.getMessage(), e);
- throw new ServiceException("新增停机记录失败: " + e.getMessage());
- }
- }
-
- /**
- * PDA-获取待处理停机记录列表
- * 返回条件:停机结束时间为空(老设备未完成)或 停机原因ID=1(新设备默认原因待修改)
- */
- @GetMapping("/shutDown/get")
- public AjaxResult getShutDownForPda() {
- try {
- List list = dmsRecordShutDownService.selectPdaShutDownList();
- return success(list);
- } catch (Exception e) {
- // 系统异常统一落日志并转业务异常,避免将内部堆栈直接暴露给调用方
- log.error("PDA获取待处理停机记录失败 | 异常信息: {}", e.getMessage(), e);
- throw new ServiceException("获取停机记录失败: " + e.getMessage());
- }
- }
-
- /**
- * PDA-更新停机记录
- * 老设备(shutEndTime为空):更新停机结束时间、计算停机时长、更新停机原因ID
- * 新设备(shutEndTime不为空):仅更新停机原因ID
- */
- @PostMapping("/shutDown/complete")
- @Transactional(rollbackFor = Exception.class)
- public AjaxResult completeShutDownForPda(@RequestBody DmsRecordShutDown shutDown) {
- if (shutDown.getRecordShutDownId() == null) {
- throw new ServiceException("recordShutDownId不能为空");
- }
- if (shutDown.getShutReasonId() == null) {
- throw new ServiceException("shutReasonId不能为空");
- }
- try {
- // 查询原记录
- DmsRecordShutDown origin = dmsRecordShutDownService.selectDmsRecordShutDownByRecordShutDownId(shutDown.getRecordShutDownId());
- if (origin == null) {
- throw new ServiceException("停机记录不存在");
- }
-
- // 构建更新对象,仅设置需要更新的字段
- DmsRecordShutDown updateRecord = new DmsRecordShutDown();
- updateRecord.setRecordShutDownId(shutDown.getRecordShutDownId());
- updateRecord.setShutReasonId(shutDown.getShutReasonId());
-
- if (origin.getShutEndTime() == null) {
- // 老设备:标记停机已结束
- updateRecord.setDowntimeFlag("1");
- // 老设备:补充结束时间和停机时长
- Date end = new Date();
- Date begin = origin.getShutBeginTime();
- updateRecord.setShutEndTime(end);
- if (begin != null) {
- long minutes = Math.max(0, (end.getTime() - begin.getTime()) / 60000);
- updateRecord.setShutTime(BigDecimal.valueOf(minutes));
- }
- }
- // 新设备(shutEndTime已有值):仅更新shutReasonId,无需额外处理
-
- int rows = dmsRecordShutDownService.updateDmsRecordShutDown(updateRecord);
-
- // 对老设备(OLD-01~OLD-05)同步写入三色灯状态参数
- if (origin.getShutEndTime() == null && origin.getDeviceId() != null) {
- // 原记录不含deviceCode,需通过deviceId反查设备编号
- BaseDeviceLedger deviceQuery = new BaseDeviceLedger();
- deviceQuery.setObjId(origin.getDeviceId());
- List devices = baseDeviceLedgerService.selectBaseDeviceLedgerList(deviceQuery);
- if (!devices.isEmpty()) {
- String deviceCode = devices.get(0).getDeviceCode();
- if (deviceCode != null && deviceCode.startsWith("OLD-")) {
- // 完成停机代表重新运行,三色灯置为"运行"
- insertTriColorStatusParams(deviceCode, origin.getDeviceId(), true);
- }
- }
- }
-
- return rows > 0 ? success(origin.getRecordShutDownId()) : error("更新停机记录失败");
- } catch (Exception e) {
- // 系统异常统一落日志并转业务异常,避免将内部堆栈直接暴露给调用方
- log.error("PDA完成停机记录失败 | recordShutDownId={}, shutReasonId={}, 异常信息: {}",
- shutDown.getRecordShutDownId(), shutDown.getShutReasonId(), e.getMessage(), e);
- throw new ServiceException("完成停机失败: " + e.getMessage());
- }
- }
-
- /**
- * 插入三色灯状态参数(运行/暂停/报警),以“暂停”为当前状态
- */
- private void insertTriColorStatusParams(String deviceCode, Long deviceId, boolean running) {
- // 仅处理 OLD-01~OLD-05
- if (!"OLD-01".equals(deviceCode) && !"OLD-02".equals(deviceCode)
- && !"OLD-03".equals(deviceCode) && !"OLD-04".equals(deviceCode)
- && !"OLD-05".equals(deviceCode)) {
- return;
- }
-
- // 补齐 deviceId(如果未传)
- Long resolvedDeviceId = deviceId;
- if (resolvedDeviceId == null) {
- BaseDeviceLedger query = new BaseDeviceLedger();
- query.setDeviceCode(deviceCode);
- query.setIsFlag(1L);
- List list = baseDeviceLedgerService.selectBaseDeviceLedgerList(query);
- if (!list.isEmpty()) {
- resolvedDeviceId = list.get(0).getObjId();
- }
- }
-
- Date now = new Date();
- // 运行、暂停、报警 三个参数,运行/暂停取决于状态
- List records = new ArrayList<>();
- String runVal = running ? "True" : "False";
- String pauseVal = running ? "False" : "True";
- records.add(buildParamVal(PARAM_CODE_PDA_CUSTOM, deviceCode, resolvedDeviceId, "机台状态-三色灯机器运行", runVal, now));
- records.add(buildParamVal(PARAM_CODE_PDA_CUSTOM, deviceCode, resolvedDeviceId, "机台状态-三色灯机器暂停", pauseVal, now));
- records.add(buildParamVal(PARAM_CODE_PDA_CUSTOM, deviceCode, resolvedDeviceId, "机台状态-三色灯机器报警", "False", now));
-
- for (BaseDeviceParamVal rec : records) {
- baseDeviceParamValService.insertBaseDeviceParamVal(rec);
- }
- }
-
- private BaseDeviceParamVal buildParamVal(String paramCode, String deviceCode, Long deviceId,
- String paramName, String paramValue, Date time) {
- BaseDeviceParamVal v = new BaseDeviceParamVal();
- v.setParamCode(paramCode);
- v.setDeviceCode(deviceCode);
- v.setDeviceId(deviceId);
- v.setParamName(paramName);
- v.setParamValue(paramValue);
- v.setCollectTime(time);
- v.setRecordTime(time);
- return v;
- }
-
- /**
- * PDA-选择设备后更新运行时间(写入参数:机台状态-实际生产时间)
- */
- @PostMapping("/device/updateRunTime")
- @Transactional(rollbackFor = Exception.class)
- public AjaxResult updateDeviceRunTime(@RequestBody BaseDeviceParamVal baseDeviceParamVal) {
- return updatePdaDeviceParamValue(baseDeviceParamVal, PARAM_NAME_ACTUAL_RUNTIME, false, "运行时间");
- }
-
- /**
- * PDA-选择设备后更新当日产量(写入参数:机台状态-实际产出数量)
- */
- @PostMapping("/device/updateDailyOutput")
- @Transactional(rollbackFor = Exception.class)
- public AjaxResult updateDeviceDailyOutput(@RequestBody BaseDeviceParamVal baseDeviceParamVal) {
- return updatePdaDeviceParamValue(baseDeviceParamVal, PARAM_NAME_DAILY_OUTPUT, true, "当日产量");
- }
-
- private AjaxResult updatePdaDeviceParamValue(BaseDeviceParamVal baseDeviceParamVal, String paramName,
- boolean integerRequired, String bizName) {
- // 请求体为空时直接拒绝,避免后续空指针并明确返回可读错误
- if (baseDeviceParamVal == null) {
- throw new ServiceException("请求体不能为空");
- }
- // PDA上报的业务值统一从paramValue读取,后续会按业务类型做数值校验
- String rawValue = baseDeviceParamVal.getParamValue();
- if (rawValue == null || rawValue.trim().isEmpty()) {
- throw new ServiceException(bizName + "不能为空");
- }
- // 运行时间允许小数;当日产量要求整数,规则由integerRequired控制
- validateNumericParamValue(rawValue.trim(), integerRequired, bizName);
-
- try {
- // 兼容PDA只传deviceId或只传deviceCode的场景,统一补齐设备主数据标识
- fillDeviceIdentity(baseDeviceParamVal);
- Date now = new Date();
- // 参数名由后端强制指定,避免前端透传导致写错业务口径
- baseDeviceParamVal.setParamName(paramName);
- baseDeviceParamVal.setParamValue(rawValue.trim());
- if (baseDeviceParamVal.getParamCode() == null || baseDeviceParamVal.getParamCode().trim().isEmpty()) {
- // Why:该参数值用于PDA手工更新场景,统一标识便于后续数据追溯与运维排查
- baseDeviceParamVal.setParamCode(PARAM_CODE_PDA_CUSTOM);
- }
- // 采集时间/记录时间均取服务端当前时间,确保同一时区口径一致
- baseDeviceParamVal.setCollectTime(now);
- baseDeviceParamVal.setRecordTime(now);
-
- // 直接插入一条新参数记录,保留完整时间序列,避免覆盖历史值
- int rows = baseDeviceParamValService.upsertTodayParamValue(baseDeviceParamVal);
- return rows > 0 ? success(rows) : error("更新" + bizName + "失败");
- } catch (ServiceException e) {
- // 业务异常原样抛出,保留明确可读的提示信息
- throw e;
- } catch (Exception e) {
- // 系统异常统一落日志并转业务异常,避免将内部堆栈直接暴露给调用方
- log.error("PDA更新设备{}失败 | deviceCode={}, deviceId={}, paramName={}, paramValue={}, 异常信息: {}",
- bizName, baseDeviceParamVal.getDeviceCode(), baseDeviceParamVal.getDeviceId(),
- paramName, baseDeviceParamVal.getParamValue(), e.getMessage(), e);
- throw new ServiceException("更新" + bizName + "失败: " + e.getMessage());
- }
- }
-
- private void fillDeviceIdentity(BaseDeviceParamVal baseDeviceParamVal) {
- String deviceCode = baseDeviceParamVal.getDeviceCode();
- Long deviceId = baseDeviceParamVal.getDeviceId();
- boolean hasCode = deviceCode != null && !deviceCode.trim().isEmpty();
-
- // 未传deviceCode时,必须依赖deviceId反查设备编码;否则无法确定落库维度
- if (!hasCode) {
- // 两个标识都没有时无法定位设备,直接拒绝请求
- if (deviceId == null) {
- throw new ServiceException("deviceCode和deviceId不能同时为空");
- }
- BaseDeviceLedger query = new BaseDeviceLedger();
- query.setObjId(deviceId);
- query.setIsFlag(1L);
- List list = baseDeviceLedgerService.selectBaseDeviceLedgerList(query);
- if (CollectionUtils.isEmpty(list)) {
- throw new ServiceException("设备不存在或已停用");
- }
- baseDeviceParamVal.setDeviceCode(list.get(0).getDeviceCode());
- return;
- }
-
- // 已传deviceCode时统一去空白,并在缺少deviceId时补齐主键
- baseDeviceParamVal.setDeviceCode(deviceCode.trim());
- if (deviceId == null) {
- BaseDeviceLedger query = new BaseDeviceLedger();
- query.setDeviceCode(baseDeviceParamVal.getDeviceCode());
- query.setIsFlag(1L);
- List list = baseDeviceLedgerService.selectBaseDeviceLedgerList(query);
- if (CollectionUtils.isEmpty(list)) {
- throw new ServiceException("设备不存在或已停用");
- }
- baseDeviceParamVal.setDeviceId(list.get(0).getObjId());
- }
- }
-
- private void validateNumericParamValue(String value, boolean integerRequired, String bizName) {
- try {
- BigDecimal decimal = new BigDecimal(value);
- // 业务口径下运行时间/产量都不允许负值
- if (decimal.compareTo(BigDecimal.ZERO) < 0) {
- throw new ServiceException(bizName + "不能小于0");
- }
- // 当日产量必须是整数,避免出现1.2这类无意义产量值
- if (integerRequired && decimal.stripTrailingZeros().scale() > 0) {
- throw new ServiceException(bizName + "必须为整数");
- }
- } catch (NumberFormatException ex) {
- throw new ServiceException(bizName + "必须为数字");
- }
- }
/**
* PDA-报修
@@ -988,71 +586,513 @@ public class DmsMobileController extends BaseController {
+// /**
+// * 获取最新一条待保养或保养中的保养工单
+// *
+// * @return
+// */
+// // //@PreAuthorize("@ss.hasPermi('qms:checkrule:list')" )
+// @GetMapping("/getNewestMaintInstance")
+// public AjaxResult getNewestMaintInstance(DmsBillsMaintInstance dmsBillsMaintInstance) {
+// DmsBillsMaintInstance newestMaintInstance = dmsBillsMaintInstanceService.getNewestBillsMaintInstance(dmsBillsMaintInstance);
+// return success(newestMaintInstance);
+// }
+//
+//
+// /**
+// * 开始保养
+// */
+//// //@PreAuthorize("@ss.hasPermi('qms:checkresultdetail:add')" )
+// ////@Log(title = "保养工单", businessType = BusinessType.START)
+// @PostMapping("/startMaint")
+// public AjaxResult startMaint(@RequestBody DmsBillsMaintDetail dmsBillsMaintDetail) {
+// return success(dmsBillsMaintInstanceService.startMaint(dmsBillsMaintDetail));
+// }
+//
+// /**
+// * 完成保养
+// */
+//// //@PreAuthorize("@ss.hasPermi('qms:checkresultdetail:add')" )
+// ////@Log(title = "保养工单", businessType = BusinessType.COMPLETE)
+// @PostMapping("/completeMaint")
+// public AjaxResult completeMaint(@RequestBody DmsBillsMaintDetail dmsBillsMaintDetail) {
+// return success(dmsBillsMaintInstanceService.completeMaint(dmsBillsMaintDetail));
+// }
+//
+//
+// /**
+// * 获取最新一条待润滑或润滑中的润滑工单
+// *
+// * @return
+// */
+// // //@PreAuthorize("@ss.hasPermi('qms:checkrule:list')" )
+// @GetMapping("/getNewestLubeInstance")
+// public AjaxResult getNewestLubeInstance(DmsBillsLubeInstance dmsBillsLubeInstance) {
+// DmsBillsLubeInstance newestLubeInstance = dmsBillsLubeInstanceService.getNewestBillsLubeInstance(dmsBillsLubeInstance);
+// return success(newestLubeInstance);
+// }
+//
+// /**
+// * 开始润滑
+// */
+//// //@PreAuthorize("@ss.hasPermi('qms:checkresultdetail:add')" )
+// ////@Log(title = "润滑工单", businessType = BusinessType.START)
+// @PostMapping("/startLube")
+// public AjaxResult startLube(@RequestBody DmsBillsLubeDetail dmsBillsLubeDetail) {
+//
+// return success(dmsBillsLubeInstanceService.startLube(dmsBillsLubeDetail));
+// }
+//
+// /**
+// * 完成润滑
+// */
+//// //@PreAuthorize("@ss.hasPermi('qms:checkresultdetail:add')" )
+// ////@Log(title = "润滑工单", businessType = BusinessType.COMPLETE)
+// @PostMapping("/completeLube")
+// public AjaxResult completeLube(@RequestBody DmsBillsLubeDetail dmsBillsLubeDetail) {
+// return success(dmsBillsLubeInstanceService.completeLube(dmsBillsLubeDetail));
+// }
+//
+
+
+
+
+
+
+
/**
- * 获取最新一条待保养或保养中的保养工单
- *
- * @return
+ * 获取OLD开头的设备列表(仅启用)
*/
- // //@PreAuthorize("@ss.hasPermi('qms:checkrule:list')" )
- @GetMapping("/getNewestMaintInstance")
- public AjaxResult getNewestMaintInstance(DmsBillsMaintInstance dmsBillsMaintInstance) {
- DmsBillsMaintInstance newestMaintInstance = dmsBillsMaintInstanceService.getNewestBillsMaintInstance(dmsBillsMaintInstance);
- return success(newestMaintInstance);
+ @GetMapping("/device/listOld")
+ public AjaxResult listOldDevices() {
+ BaseDeviceLedger query = new BaseDeviceLedger();
+ query.setIsFlag(1L);
+ List list = baseDeviceLedgerService.selectBaseDeviceLedgerList(query);
+ List resultList = new ArrayList<>();
+ if (!CollectionUtils.isEmpty(list)) {
+ for (BaseDeviceLedger base : list) {
+ if (base.getDeviceCode() != null && base.getDeviceCode().startsWith("OLD")) {
+ resultList.add(convertDeviceLedgerToDto(convertToDeviceLedger(base)));
+ }
+ }
+ }
+ return success(resultList);
}
/**
- * 开始保养
+ * PDA-获取停机原因列表(仅启用 isFlag=1)
*/
-// //@PreAuthorize("@ss.hasPermi('qms:checkresultdetail:add')" )
- ////@Log(title = "保养工单", businessType = BusinessType.START)
- @PostMapping("/startMaint")
- public AjaxResult startMaint(@RequestBody DmsBillsMaintDetail dmsBillsMaintDetail) {
- return success(dmsBillsMaintInstanceService.startMaint(dmsBillsMaintDetail));
+ @GetMapping("/shutReason/list")
+ public AjaxResult listShutReasonsForPda(DmsBaseShutReason reason) {
+ reason.setIsFlag("1");
+ List list = dmsBaseShutReasonService.selectDmsBaseShutReasonList(reason);
+ return success(list);
}
/**
- * 完成保养
+ * PDA-新增停机记录:根据停机原因自动匹配停机类型
*/
-// //@PreAuthorize("@ss.hasPermi('qms:checkresultdetail:add')" )
- ////@Log(title = "保养工单", businessType = BusinessType.COMPLETE)
- @PostMapping("/completeMaint")
- public AjaxResult completeMaint(@RequestBody DmsBillsMaintDetail dmsBillsMaintDetail) {
- return success(dmsBillsMaintInstanceService.completeMaint(dmsBillsMaintDetail));
+ @PostMapping("/shutDown/add")
+ @Transactional(rollbackFor = Exception.class)
+ public AjaxResult addShutDownForPda(@RequestBody DmsRecordShutDown shutDown) {
+ try {
+ // 若传入了停机原因ID,则查询原因并回填类型
+ if (shutDown.getShutReason() != null) {
+ DmsBaseShutReason query = new DmsBaseShutReason();
+ query.setShutReason(shutDown.getShutReason());
+ query.setIsFlag("1");
+ List reasons = dmsBaseShutReasonService.selectDmsBaseShutReasonList(query);
+ if (!reasons.isEmpty()) {
+ shutDown.setShutType(reasons.get(0).getShutTypeId());
+ shutDown.setShutReasonId(reasons.get(0).getShutReasonId());
+ // 若前端未传 deviceId,尝试从原因带出
+ if (shutDown.getDeviceId() == null) {
+ shutDown.setDeviceId(reasons.get(0).getDeviceId());
+ }
+ }
+ }
+ // 默认启用标识
+ if (shutDown.getIsFlag() == null) {
+ shutDown.setIsFlag(1L);
+ }
+ // 新增停机记录默认未结束
+ if (shutDown.getDowntimeFlag() == null) {
+ shutDown.setDowntimeFlag("0");
+ }
+ // 若未传入开始时间,则使用当前时间
+ if (shutDown.getShutBeginTime() == null) {
+ shutDown.setShutBeginTime(new Date());
+ }
+ int rows = dmsRecordShutDownService.insertDmsRecordShutDown(shutDown);
+
+ // 对指定设备(OLD-01~OLD-05)同步写入三色灯状态参数,供设备状态统计使用
+ String deviceCode = shutDown.getDeviceCode();
+ if (deviceCode != null && deviceCode.startsWith("OLD-")) {
+ // 新增停机记录代表进入停机,三色灯置为“暂停”
+ insertTriColorStatusParams(deviceCode, shutDown.getDeviceId(), false);
+ }
+
+ return success(rows);
+ } catch (Exception e) {
+ // 系统异常统一落日志并转业务异常,避免将内部堆栈直接暴露给调用方
+ log.error("PDA新增停机记录失败 | deviceCode={}, shutReason={}, deviceId={}, 异常信息: {}",
+ shutDown.getDeviceCode(), shutDown.getShutReason(), shutDown.getDeviceId(), e.getMessage(), e);
+ throw new ServiceException("新增停机记录失败: " + e.getMessage());
+ }
+ }
+
+ /**
+ * PDA-获取待处理停机记录列表
+ * 返回条件:停机结束时间为空(老设备未完成)或 停机原因ID=1(新设备默认原因待修改)
+ */
+ @GetMapping("/shutDown/get")
+ public AjaxResult getShutDownForPda() {
+ try {
+ List list = dmsRecordShutDownService.selectPdaShutDownList();
+ return success(list);
+ } catch (Exception e) {
+ // 系统异常统一落日志并转业务异常,避免将内部堆栈直接暴露给调用方
+ log.error("PDA获取待处理停机记录失败 | 异常信息: {}", e.getMessage(), e);
+ throw new ServiceException("获取停机记录失败: " + e.getMessage());
+ }
+ }
+
+ /**
+ * PDA-更新停机记录
+ * 老设备(shutEndTime为空):更新停机结束时间、计算停机时长、更新停机原因ID
+ * 新设备(shutEndTime不为空):仅更新停机原因ID
+ */
+ @PostMapping("/shutDown/complete")
+ @Transactional(rollbackFor = Exception.class)
+ public AjaxResult completeShutDownForPda(@RequestBody DmsRecordShutDown shutDown) {
+ if (shutDown.getRecordShutDownId() == null) {
+ throw new ServiceException("recordShutDownId不能为空");
+ }
+ if (shutDown.getShutReasonId() == null) {
+ throw new ServiceException("shutReasonId不能为空");
+ }
+ try {
+ // 查询原记录
+ DmsRecordShutDown origin = dmsRecordShutDownService.selectDmsRecordShutDownByRecordShutDownId(shutDown.getRecordShutDownId());
+ if (origin == null) {
+ throw new ServiceException("停机记录不存在");
+ }
+
+ // 构建更新对象,仅设置需要更新的字段
+ DmsRecordShutDown updateRecord = new DmsRecordShutDown();
+ updateRecord.setRecordShutDownId(shutDown.getRecordShutDownId());
+ updateRecord.setShutReasonId(shutDown.getShutReasonId());
+
+ if (origin.getShutEndTime() == null) {
+ // 老设备:标记停机已结束
+ updateRecord.setDowntimeFlag("1");
+ // 老设备:补充结束时间和停机时长
+ Date end = new Date();
+ Date begin = origin.getShutBeginTime();
+ updateRecord.setShutEndTime(end);
+ if (begin != null) {
+ long minutes = Math.max(0, (end.getTime() - begin.getTime()) / 60000);
+ updateRecord.setShutTime(BigDecimal.valueOf(minutes));
+ }
+ }
+ // 新设备(shutEndTime已有值):仅更新shutReasonId,无需额外处理
+
+ int rows = dmsRecordShutDownService.updateDmsRecordShutDown(updateRecord);
+
+ // 对老设备(OLD-01~OLD-05)同步写入三色灯状态参数
+ if (origin.getShutEndTime() == null && origin.getDeviceId() != null) {
+ // 原记录不含deviceCode,需通过deviceId反查设备编号
+ BaseDeviceLedger deviceQuery = new BaseDeviceLedger();
+ deviceQuery.setObjId(origin.getDeviceId());
+ List devices = baseDeviceLedgerService.selectBaseDeviceLedgerList(deviceQuery);
+ if (!devices.isEmpty()) {
+ String deviceCode = devices.get(0).getDeviceCode();
+ if (deviceCode != null && deviceCode.startsWith("OLD-")) {
+ // 完成停机代表重新运行,三色灯置为"运行"
+ insertTriColorStatusParams(deviceCode, origin.getDeviceId(), true);
+ }
+ }
+ }
+
+ return rows > 0 ? success(origin.getRecordShutDownId()) : error("更新停机记录失败");
+ } catch (Exception e) {
+ // 系统异常统一落日志并转业务异常,避免将内部堆栈直接暴露给调用方
+ log.error("PDA完成停机记录失败 | recordShutDownId={}, shutReasonId={}, 异常信息: {}",
+ shutDown.getRecordShutDownId(), shutDown.getShutReasonId(), e.getMessage(), e);
+ throw new ServiceException("完成停机失败: " + e.getMessage());
+ }
+ }
+
+ /**
+ * 插入三色灯状态参数(运行/暂停/报警),以“暂停”为当前状态
+ */
+ private void insertTriColorStatusParams(String deviceCode, Long deviceId, boolean running) {
+ // 仅处理 OLD-01~OLD-05
+ if (!"OLD-01".equals(deviceCode) && !"OLD-02".equals(deviceCode)
+ && !"OLD-03".equals(deviceCode) && !"OLD-04".equals(deviceCode)
+ && !"OLD-05".equals(deviceCode)) {
+ return;
+ }
+
+ // 补齐 deviceId(如果未传)
+ Long resolvedDeviceId = deviceId;
+ if (resolvedDeviceId == null) {
+ BaseDeviceLedger query = new BaseDeviceLedger();
+ query.setDeviceCode(deviceCode);
+ query.setIsFlag(1L);
+ List list = baseDeviceLedgerService.selectBaseDeviceLedgerList(query);
+ if (!list.isEmpty()) {
+ resolvedDeviceId = list.get(0).getObjId();
+ }
+ }
+
+ Date now = new Date();
+ // 运行、暂停、报警 三个参数,运行/暂停取决于状态
+ List records = new ArrayList<>();
+ String runVal = running ? "True" : "False";
+ String pauseVal = running ? "False" : "True";
+ records.add(buildParamVal(PARAM_CODE_PDA_CUSTOM, deviceCode, resolvedDeviceId, "机台状态-三色灯机器运行", runVal, now));
+ records.add(buildParamVal(PARAM_CODE_PDA_CUSTOM, deviceCode, resolvedDeviceId, "机台状态-三色灯机器暂停", pauseVal, now));
+ records.add(buildParamVal(PARAM_CODE_PDA_CUSTOM, deviceCode, resolvedDeviceId, "机台状态-三色灯机器报警", "False", now));
+
+ for (BaseDeviceParamVal rec : records) {
+ baseDeviceParamValService.insertBaseDeviceParamVal(rec);
+ }
+ }
+
+ private BaseDeviceParamVal buildParamVal(String paramCode, String deviceCode, Long deviceId,
+ String paramName, String paramValue, Date time) {
+ BaseDeviceParamVal v = new BaseDeviceParamVal();
+ v.setParamCode(paramCode);
+ v.setDeviceCode(deviceCode);
+ v.setDeviceId(deviceId);
+ v.setParamName(paramName);
+ v.setParamValue(paramValue);
+ v.setCollectTime(time);
+ v.setRecordTime(time);
+ return v;
+ }
+
+
+
+
+ // ========== PDA 参数相关 ==========
+
+ /**
+ * 获取所有的设备列表(仅启用)
+ */
+ @GetMapping("/device/getDevices")
+ public AjaxResult getDevices() {
+ BaseDeviceLedger query = new BaseDeviceLedger();
+ query.setIsFlag(1L);
+ List list = baseDeviceLedgerService.selectBaseDeviceLedgerList(query);
+ List resultList = new ArrayList<>();
+ if (!CollectionUtils.isEmpty(list)) {
+ for (BaseDeviceLedger base : list) {
+ resultList.add(convertDeviceLedgerToDto(convertToDeviceLedger(base)));
+ }
+ }
+ return success(resultList);
+ }
+
+ /**
+ * PDA-选择设备后更新运行时间(写入参数:机台状态-实际生产时间)
+ */
+ @PostMapping("/device/updateRunTime")
+ @Transactional(rollbackFor = Exception.class)
+ public AjaxResult updateDeviceRunTime(@RequestBody DmsPdaDeviceParamUpdateVo request) {
+ if (request == null) {
+ throw new ServiceException("请求体不能为空");
+ }
+ return updatePdaDeviceParamValue(request.getDeviceCode(), request.getDeviceId(), request.getParamValue(),
+ PARAM_NAME_ACTUAL_RUNTIME, false, "运行时间");
+ }
+
+ /**
+ * PDA-选择设备后更新当日产量(写入参数:机台状态-实际产出数量)
+ */
+ @PostMapping("/device/updateDailyOutput")
+ @Transactional(rollbackFor = Exception.class)
+ public AjaxResult updateDeviceDailyOutput(@RequestBody DmsPdaDeviceParamUpdateVo request) {
+ if (request == null) {
+ throw new ServiceException("请求体不能为空");
+ }
+ return updatePdaDeviceParamValue(request.getDeviceCode(), request.getDeviceId(), request.getParamValue(),
+ PARAM_NAME_DAILY_OUTPUT, true, "当日产量");
+ }
+
+ private AjaxResult updatePdaDeviceParamValue(String deviceCode, Long deviceId, BigDecimal paramValue, String paramName,
+ boolean integerRequired, String bizName) {
+ // 业务参数值为空时直接拒绝,避免后续数值转换出现非预期错误
+ if (paramValue == null) {
+ throw new ServiceException(bizName + "不能为空");
+ }
+ // PDA上报的业务值统一从paramValue读取,后续会按业务类型做数值校验
+ BigDecimal rawValue = paramValue;
+ if (rawValue == null || rawValue.compareTo(BigDecimal.ZERO) < 0) {
+ throw new ServiceException(bizName + "不能为空");
+ }
+ // 运行时间允许小数;当日产量要求整数,规则由integerRequired控制
+ validateNumericParamValue(rawValue, integerRequired, bizName);
+
+ try {
+ // 兼容PDA只传deviceId或只传deviceCode的场景,统一补齐设备主数据标识
+ BaseDeviceParamVal baseDeviceParamVal = fillDeviceIdentity(deviceCode, deviceId);
+ Date now = new Date();
+ // 参数名由后端强制指定,避免前端透传导致写错业务口径
+ baseDeviceParamVal.setParamName(paramName);
+ baseDeviceParamVal.setParamValue(rawValue.toString());
+ if (baseDeviceParamVal.getParamCode() == null || baseDeviceParamVal.getParamCode().trim().isEmpty()) {
+ // Why:该参数值用于PDA手工更新场景,统一标识便于后续数据追溯与运维排查
+ baseDeviceParamVal.setParamCode(PARAM_CODE_PDA_CUSTOM);
+ }
+ // 采集时间/记录时间均取服务端当前时间,确保同一时区口径一致
+ baseDeviceParamVal.setCollectTime(now);
+ baseDeviceParamVal.setRecordTime(now);
+
+ // 直接插入一条新参数记录,保留完整时间序列,避免覆盖历史值
+ int rows = baseDeviceParamValService.upsertTodayParamValue(baseDeviceParamVal);
+ return rows > 0 ? success(rows) : error("更新" + bizName + "失败");
+ } catch (ServiceException e) {
+ // 业务异常原样抛出,保留明确可读的提示信息
+ throw e;
+ } catch (Exception e) {
+ // 系统异常统一落日志并转业务异常,避免将内部堆栈直接暴露给调用方
+ log.error("PDA更新设备{}失败 | deviceCode={}, deviceId={}, paramName={}, paramValue={}, 异常信息: {}",
+ bizName, deviceCode, deviceId, paramName, rawValue, e.getMessage(), e);
+ throw new ServiceException("更新" + bizName + "失败: " + e.getMessage());
+ }
+ }
+
+ private BaseDeviceParamVal fillDeviceIdentity(String deviceCode, Long deviceId) {
+ BaseDeviceParamVal baseDeviceParamVal = new BaseDeviceParamVal();
+ boolean hasCode = deviceCode != null && !deviceCode.trim().isEmpty();
+
+ // 未传deviceCode时,必须依赖deviceId反查设备编码;否则无法确定落库维度
+ if (!hasCode) {
+ // 两个标识都没有时无法定位设备,直接拒绝请求
+ if (deviceId == null) {
+ throw new ServiceException("deviceCode和deviceId不能同时为空");
+ }
+ BaseDeviceLedger query = new BaseDeviceLedger();
+ query.setObjId(deviceId);
+ query.setIsFlag(1L);
+ List list = baseDeviceLedgerService.selectBaseDeviceLedgerList(query);
+ if (CollectionUtils.isEmpty(list)) {
+ throw new ServiceException("设备不存在或已停用");
+ }
+ baseDeviceParamVal.setDeviceId(deviceId);
+ baseDeviceParamVal.setDeviceCode(list.get(0).getDeviceCode());
+ return baseDeviceParamVal;
+ }
+
+ // 已传deviceCode时统一去空白,并在缺少deviceId时补齐主键
+ baseDeviceParamVal.setDeviceCode(deviceCode.trim());
+ if (deviceId == null) {
+ BaseDeviceLedger query = new BaseDeviceLedger();
+ query.setDeviceCode(baseDeviceParamVal.getDeviceCode());
+ query.setIsFlag(1L);
+ List list = baseDeviceLedgerService.selectBaseDeviceLedgerList(query);
+ if (CollectionUtils.isEmpty(list)) {
+ throw new ServiceException("设备不存在或已停用");
+ }
+ baseDeviceParamVal.setDeviceId(list.get(0).getObjId());
+ return baseDeviceParamVal;
+ }
+ baseDeviceParamVal.setDeviceId(deviceId);
+ return baseDeviceParamVal;
+ }
+
+ private void validateNumericParamValue(BigDecimal value, boolean integerRequired, String bizName) {
+ try {
+ BigDecimal decimal = value;
+ // 业务口径下运行时间/产量都不允许负值
+ if (decimal.compareTo(BigDecimal.ZERO) < 0) {
+ throw new ServiceException(bizName + "不能小于0");
+ }
+ // 当日产量必须是整数,避免出现1.2这类无意义产量值
+ if (integerRequired && decimal.stripTrailingZeros().scale() > 0) {
+ throw new ServiceException(bizName + "必须为整数");
+ }
+ } catch (NumberFormatException ex) {
+ throw new ServiceException(bizName + "必须为数字");
+ }
}
/**
- * 获取最新一条待润滑或润滑中的润滑工单
- *
- * @return
+ * PDA-按物料关键字查询关联工单
*/
- // //@PreAuthorize("@ss.hasPermi('qms:checkrule:list')" )
- @GetMapping("/getNewestLubeInstance")
- public AjaxResult getNewestLubeInstance(DmsBillsLubeInstance dmsBillsLubeInstance) {
- DmsBillsLubeInstance newestLubeInstance = dmsBillsLubeInstanceService.getNewestBillsLubeInstance(dmsBillsLubeInstance);
- return success(newestLubeInstance);
+ @GetMapping("/order/listByMaterial")
+ public AjaxResult listOrdersByMaterial(String keyword) {
+ // 物料关键字是PDA唯一输入入口,空值时直接拒绝,避免放大后端模糊查询范围
+ if (keyword == null || keyword.trim().isEmpty()) {
+ throw new ServiceException("物料关键字不能为空");
+ }
+ try {
+ // Why:先按物料主数据检索,再按物料编码反查订单,能保证PDA搜索口径与主数据一致
+ List orders = baseOrderInfoService.selectPdaOrderListByMaterialKeyword(keyword.trim());
+ return success(orders);
+ } catch (Exception e) {
+ log.error("PDA按物料查询工单失败 | keyword={}, 异常信息: {}", keyword, e.getMessage(), e);
+ throw new ServiceException("查询工单失败: " + e.getMessage());
+ }
}
/**
- * 开始润滑
+ * PDA-维护订单状态与数量
*/
-// //@PreAuthorize("@ss.hasPermi('qms:checkresultdetail:add')" )
- ////@Log(title = "润滑工单", businessType = BusinessType.START)
- @PostMapping("/startLube")
- public AjaxResult startLube(@RequestBody DmsBillsLubeDetail dmsBillsLubeDetail) {
+ @PostMapping("/order/updateStatusAndQty")
+ @Transactional(rollbackFor = Exception.class)
+ public AjaxResult updateOrderStatusAndQty(@RequestBody BaseOrderInfo baseOrderInfo) {
+ // 请求体为空时没有任何维护目标,直接拦截比进入service后再判空更清晰
+ if (baseOrderInfo == null) {
+ throw new ServiceException("请求体不能为空");
+ }
+ // PDA下拉选中订单后至少应能定位到一条工单,兼容前端传objId或orderCode两种方式
+ if (baseOrderInfo.getObjId() == null
+ && (baseOrderInfo.getOrderCode() == null || baseOrderInfo.getOrderCode().trim().isEmpty())) {
+ throw new ServiceException("objId和orderCode不能同时为空");
+ }
+ // 状态和数量都在控制器前置校验,避免脏数据落到service或数据库层
+ validateOrderExecutionStatus(baseOrderInfo.getExecutionStatus());
+ validateOrderQty(baseOrderInfo.getActualCompleteQty(), "完工数量");
+ validateOrderQty(baseOrderInfo.getActualDefectQty(), "不良数量");
- return success(dmsBillsLubeInstanceService.startLube(dmsBillsLubeDetail));
+ try {
+ // Why:PDA订单维护属于人工修正场景,统一走service封装,避免控制器直接拼装状态流转细节
+ int rows = baseOrderInfoService.updatePdaOrderExecution(baseOrderInfo);
+ return rows > 0 ? success(rows) : error("工单不存在或更新失败");
+ } catch (ServiceException e) {
+ throw e;
+ } catch (Exception e) {
+ log.error("PDA维护订单失败 | objId={}, orderCode={}, executionStatus={}, actualCompleteQty={}, 异常信息: {}",
+ baseOrderInfo.getObjId(), baseOrderInfo.getOrderCode(), baseOrderInfo.getExecutionStatus(),
+ baseOrderInfo.getActualCompleteQty(), e.getMessage(), e);
+ throw new ServiceException("维护订单失败: " + e.getMessage());
+ }
}
- /**
- * 完成润滑
- */
-// //@PreAuthorize("@ss.hasPermi('qms:checkresultdetail:add')" )
- ////@Log(title = "润滑工单", businessType = BusinessType.COMPLETE)
- @PostMapping("/completeLube")
- public AjaxResult completeLube(@RequestBody DmsBillsLubeDetail dmsBillsLubeDetail) {
- return success(dmsBillsLubeInstanceService.completeLube(dmsBillsLubeDetail));
+ private void validateOrderExecutionStatus(String executionStatus) {
+ // PDA当前仅允许维护执行态,保持与execution.vue和现有执行页状态枚举一致
+ if (executionStatus == null || executionStatus.trim().isEmpty()) {
+ throw new ServiceException("执行状态不能为空");
+ }
+ String normalized = executionStatus.trim();
+ if (!ORDER_EXECUTION_PENDING.equals(normalized)
+ && !ORDER_EXECUTION_RUNNING.equals(normalized)
+ && !ORDER_EXECUTION_PAUSED.equals(normalized)
+ && !ORDER_EXECUTION_COMPLETED.equals(normalized)) {
+ throw new ServiceException("执行状态不合法");
+ }
+ }
+
+ private void validateOrderQty(Long qty, String fieldName) {
+ // 数量允许为空,表示本次只改状态;但一旦传值就必须满足非负约束
+ if (qty != null && qty < 0) {
+ throw new ServiceException(fieldName + "不能小于0");
+ }
}
}