智慧实物管理系统相关功能优化

This commit is contained in:
2025-12-05 16:04:35 +08:00
parent f338e53883
commit 2c21c1560e
25 changed files with 2708 additions and 46 deletions

View File

@@ -0,0 +1,17 @@
package com.zg.project.wisdom.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "qwen-ocr")
@Data
public class QwenOcrRemoteProperties {
/**
* 远程 OCR 服务的完整地址
* 例如http://192.168.1.5:8087/ocr/extractErpByBase64
*/
private String baseUrl;
}

View File

@@ -43,6 +43,7 @@ public class AuditSignatureController extends BaseController
* 上传签字图片到 MinIO
*/
@PostMapping("/upload")
@Log(title = "签字图片上传", businessType = BusinessType.INSERT)
public AjaxResult uploadSignature(@RequestParam("file") MultipartFile file) {
if (file == null || file.isEmpty()) {
return AjaxResult.error("上传文件不能为空");
@@ -56,6 +57,7 @@ public class AuditSignatureController extends BaseController
}
// 上传图片接收base64格式 zhangjinbo
@PostMapping("/uploadBase64")
@Log(title = "签字图片上传", businessType = BusinessType.INSERT)
public AjaxResult uploadSignatureBase64(@RequestBody Map<String, String> param) {
String imgStr = param.get("imgStr");
// return AjaxResult.success("上传成功").put("url", imgStr);
@@ -150,6 +152,7 @@ public class AuditSignatureController extends BaseController
* 审核操作(通过 / 驳回)
*/
@PostMapping("/audit")
@Log(title = "审批记录", businessType = BusinessType.UPDATE)
public AjaxResult audit(@RequestBody AuditSignature audit) {
try {
auditSignatureService.audit(audit);

View File

@@ -2,6 +2,11 @@ package com.zg.project.wisdom.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson2.JSON;
import com.zg.common.utils.StringUtils;
import com.zg.project.wisdom.domain.dto.ExcelFieldMapping;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -123,4 +128,39 @@ public class GysJhController extends BaseController
{
return toAjax(gysJhService.deleteGysJhByIds(ids));
}
/**
* 供应计划导入(带字段映射)
*
* 前端 form-data 结构示例:
* - file: 选中的 excel 文件
* - mapping[0].label = wlNo
* - mapping[0].prop = E
* - mapping[1].label = wlMs
* - mapping[1].prop = F
* ...
*/
@PreAuthorize("@ss.hasPermi('wisdom:gysJh:import')")
@Log(title = "供应计划导入", businessType = BusinessType.IMPORT)
@PostMapping(
value = "/importByMapping",
consumes = MediaType.MULTIPART_FORM_DATA_VALUE
)
public AjaxResult importByMapping(@RequestPart("file") MultipartFile file,
@RequestParam("mapping") String mappingJson) throws Exception {
if (file == null || file.isEmpty()) {
return AjaxResult.error("导入文件不能为空");
}
if (StringUtils.isBlank(mappingJson)) {
return AjaxResult.error("字段映射不能为空");
}
// 把 JSON 字符串转成 List<ExcelFieldMapping>
List<ExcelFieldMapping> mapping =
JSON.parseArray(mappingJson, ExcelFieldMapping.class);
int rows = gysJhService.importByMapping(file, mapping);
return AjaxResult.success("成功导入 " + rows + " 条记录");
}
}

View File

@@ -1,5 +1,7 @@
package com.zg.project.wisdom.controller;
import com.zg.framework.aspectj.lang.annotation.Log;
import com.zg.framework.aspectj.lang.enums.BusinessType;
import com.zg.framework.web.domain.AjaxResult;
import com.zg.project.wisdom.domain.dto.PhotoDeleteDTO;
import com.zg.project.wisdom.service.PhotoService;
@@ -38,6 +40,7 @@ public class PhotoController {
* 返回:每张图片的可访问 URL 列表
*/
@PostMapping(value = "/upload/batch", consumes = "multipart/form-data")
@Log(title = "照片上传", businessType = BusinessType.INSERT)
public AjaxResult uploadBatch(@RequestPart("files") List<MultipartFile> files,
@RequestParam("photoType") String photoType,
@RequestParam("billNo") String billNo,
@@ -88,12 +91,13 @@ public class PhotoController {
* @return
*/
@PostMapping(value = "/delete", consumes = "application/json")
// @PreAuthorize("@ss.hasPermi('wisdom:photo:remove')")
@Log(title = "照片删除", businessType = BusinessType.DELETE)
public AjaxResult delete(@Validated @RequestBody PhotoDeleteDTO dto) {
Map<String, Object> result = photoService.deleteByUrls(dto.getUrls());
return AjaxResult.success("删除完成", result);
}
@GetMapping("/deleteById")
@Log(title = "照片删除", businessType = BusinessType.DELETE)
public AjaxResult deleteById(@RequestParam("id") Integer id){
return AjaxResult.success(photoService.deleteById(id));
}

View File

@@ -9,6 +9,7 @@ import com.github.pagehelper.PageHelper;
import com.zg.project.wisdom.domain.dto.*;
import com.zg.project.wisdom.domain.vo.DeliveryBillVO;
import com.zg.project.wisdom.domain.vo.PcodeQtyVO;
import com.zg.project.wisdom.service.QwenOcrRemoteService;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
@@ -21,6 +22,7 @@ import com.zg.framework.web.controller.BaseController;
import com.zg.framework.web.domain.AjaxResult;
import com.zg.common.utils.poi.ExcelUtil;
import com.zg.framework.web.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;
/**
* 库存单据主Controller
@@ -35,6 +37,9 @@ public class RkInfoController extends BaseController
@Autowired
private IRkInfoService rkInfoService;
@Autowired
private QwenOcrRemoteService qwenOcrRemoteService;
/**
* 查询出库,借料,待审批,撤销出入库单据主列表
@@ -47,7 +52,6 @@ public class RkInfoController extends BaseController
return getDataTable(list);
}
// @PreAuthorize("@ss.hasPermi('wisdom:stock:stat')")
@GetMapping("/pcode/{pcode}")
public AjaxResult listRkInfoByPcode(@PathVariable String pcode) {
List<RkInfo> rows = rkInfoService.listRkInfoByPcode(pcode);
@@ -128,7 +132,6 @@ public class RkInfoController extends BaseController
* @return
*/
@GetMapping("/warning/stock/over20")
@PreAuthorize("@ss.hasPermi('wisdom:stock:warning')")
public AjaxResult getOverdueStockTopList() {
int total = rkInfoService.countOverdueStock();
List<RkInfo> list = rkInfoService.selectTopOverdueStock(20);
@@ -144,7 +147,7 @@ public class RkInfoController extends BaseController
* @return
*/
@PutMapping("/deleteByCkBillNo")
@PreAuthorize("@ss.hasPermi('wisdom:stock:deleteByBillNo')")
@Log(title = "库存单据主", businessType = BusinessType.UPDATE)
public AjaxResult deleteByCkBillNo(@RequestBody Map<String, String> body) {
String billNoCk = body.get("billNoCk");
if (billNoCk == null || billNoCk.trim().isEmpty()) {
@@ -161,7 +164,7 @@ public class RkInfoController extends BaseController
* 根据主键ID撤销入库
*/
@PostMapping("/cancel")
@PreAuthorize("@ss.hasPermi('wisdom:stock:deleteByBillNo')")
@Log(title = "库存单据主", businessType = BusinessType.UPDATE)
public AjaxResult deleteById(@RequestBody RkCancelDTO dto) {
rkInfoService.deleteRkInfoById(dto);
return AjaxResult.success("撤销成功");
@@ -171,7 +174,7 @@ public class RkInfoController extends BaseController
* 根据主键ID撤销出库
*/
@PostMapping("/cancelById/{id}")
@PreAuthorize("@ss.hasPermi('wisdom:stock:deleteByBillNo')")
@Log(title = "库存单据主", businessType = BusinessType.UPDATE)
public AjaxResult cancelOutStockById(@PathVariable Long id) {
rkInfoService.cancelOutStockById(id);
return AjaxResult.success("撤销出库成功");
@@ -183,7 +186,7 @@ public class RkInfoController extends BaseController
* 出入库撤销记录删除
*/
@PostMapping("/deleteByIds")
@PreAuthorize("@ss.hasPermi('wisdom:stock:deleteById')")
@Log(title = "库存单据主", businessType = BusinessType.UPDATE)
public AjaxResult deleteByIds(@RequestBody Long[] ids) {
return AjaxResult.success(rkInfoService.deleteRkInfoByIds(ids));
}
@@ -192,7 +195,7 @@ public class RkInfoController extends BaseController
* 根据ids恢复出库或入库
*/
@PostMapping("/revertByIds")
@PreAuthorize("@ss.hasPermi('wisdom:stock:deleteById')")
@Log(title = "库存单据主", businessType = BusinessType.UPDATE)
public AjaxResult revertByIds(@RequestBody Long[] ids) {
rkInfoService.revertByIds(ids);
return AjaxResult.success();
@@ -302,14 +305,39 @@ public class RkInfoController extends BaseController
@PostMapping("/updateDeliveryStatus")
@Log(title = "更新配送状态", businessType = BusinessType.UPDATE)
public AjaxResult updateDeliveryStatus(@RequestBody RkDeliveryUpdateDTO dto) {
if (dto.getBillNoCk() == null) {
return AjaxResult.error("出库单据号不能为空");
if (dto.getIds() == null || dto.getIds().isEmpty()) {
return AjaxResult.error("rk_info 主键ID集合不能为空");
}
if (dto.getIsDelivery() == null) {
return AjaxResult.error("配送状态不能为空");
}
int rows = rkInfoService.updateDeliveryStatus(dto.getBillNoCk(), dto.getIsDelivery());
int rows = rkInfoService.updateDeliveryStatus(dto.getIds(), dto.getIsDelivery());
return AjaxResult.success(rows);
}
/**
* 上传图片,识别采购订单号(ERP)
*
* 前端调用示例multipart/form-data
* POST /wisdom/ocr/extractErp
* file: <图片文件>
*/
@PostMapping("/extractErp")
public AjaxResult extractErp(@RequestParam("file") MultipartFile file) {
if (file == null || file.isEmpty()) {
return AjaxResult.error("上传文件不能为空");
}
String erpOrderNo = qwenOcrRemoteService.extractErpOrderNo(file);
return AjaxResult.success(erpOrderNo);
}
}

View File

@@ -0,0 +1,14 @@
package com.zg.project.wisdom.domain.dto;
import lombok.Data;
@Data
public class ExcelFieldMapping {
/** 后端字段名,如 wlNo、sapNo */
private String label;
/** Excel 列,如 A、B、C、AA */
private String prop;
}

View File

@@ -0,0 +1,62 @@
package com.zg.project.wisdom.domain.dto;
import java.util.List;
/**
* 供应计划导入DTO - 支持自定义映射关系
*
* @author zg
* @date 2025-12-01
*/
public class GysJhImportDTO {
/**
* 映射关系对象
*/
public static class MappingItem {
private String label; // 字段标识名
private String prop; // Excel列标识如A、B、C等
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getProp() {
return prop;
}
public void setProp(String prop) {
this.prop = prop;
}
}
/**
* 映射关系数组
*/
private List<MappingItem> mapping;
/**
* 操作人
*/
private String operName;
public List<MappingItem> getMapping() {
return mapping;
}
public void setMapping(List<MappingItem> mapping) {
this.mapping = mapping;
}
public String getOperName() {
return operName;
}
public void setOperName(String operName) {
this.operName = operName;
}
}

View File

@@ -2,8 +2,14 @@ package com.zg.project.wisdom.domain.dto;
import lombok.Data;
import java.util.List;
@Data
public class RkDeliveryUpdateDTO {
private String billNoCk;
private Integer isDelivery; // 0否 1是 2配送中 3已完成
/** rk_info 主键ID集合 */
private List<Long> ids;
/** 配送状态0否 1是 2配送中 3已完成 */
private Integer isDelivery;
}

View File

@@ -86,15 +86,13 @@ public interface GysJhMapper
void resetGysJhStatusBySapNos(List<String> sapNos);
/**
* 根据sapNo和xmNo和wlNo查询
* @param sapNo
* @param xmNo
* @param wlNo
* @return
* 【已注释】根据SAP订单号、项目号和物料号检查是否已存在唯一性校验
* @param sapNo SAP订单号
* @param xmNo 项目号
* @param wlNo 物料号
* @return 是否存在
*/
boolean existsByUniqueKeys(@Param("sapNo") String sapNo,
@Param("xmNo") String xmNo,
@Param("wlNo") String wlNo);
// boolean existsByUniqueKeys(@Param("sapNo") String sapNo, @Param("xmNo") String xmNo, @Param("wlNo") String wlNo);
/**
* 批量修改状态

View File

@@ -236,7 +236,8 @@ public interface RkInfoMapper
* 修改出库单据状态
*/
int updateDeliveryStatus(@Param("billNoCk") String billNoCk,
int updateDeliveryStatus(@Param("ids") List<Long> ids,
@Param("isDelivery") Integer isDelivery);
/**

View File

@@ -2,6 +2,8 @@ package com.zg.project.wisdom.service;
import java.util.List;
import com.zg.project.wisdom.domain.GysJh;
import com.zg.project.wisdom.domain.dto.ExcelFieldMapping;
import org.springframework.web.multipart.MultipartFile;
/**
* 供应计划Service接口
@@ -73,4 +75,10 @@ public interface IGysJhService
* @return
*/
List<GysJh> getBySapNo(String sapNo);
/**
* 按字段映射导入供应计划
*/
int importByMapping(MultipartFile file, List<ExcelFieldMapping> mapping) throws Exception;
}

View File

@@ -175,12 +175,11 @@ public interface IRkInfoService
void appendToExistingBill(PcRkInfoBatchDTO dto);
/**
* 修改出库单的配送状态
* @param billNoCk
* @param isDelivery
* @return
* 按 rk_info 主键ID集合修改配送状态
* @param ids rk_info.id 集合
* @param isDelivery 配送状态
*/
int updateDeliveryStatus(String billNoCk, Integer isDelivery);
int updateDeliveryStatus(List<Long> ids, Integer isDelivery);
/**
* 获取指定出库单的配送信息

View File

@@ -0,0 +1,98 @@
package com.zg.project.wisdom.service;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zg.project.wisdom.config.QwenOcrRemoteProperties;
import okhttp3.*;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.Base64;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@Service
public class QwenOcrRemoteService {
private final QwenOcrRemoteProperties properties;
private final ObjectMapper objectMapper = new ObjectMapper();
private final OkHttpClient httpClient = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(25, TimeUnit.SECONDS)
.writeTimeout(25, TimeUnit.SECONDS)
.build();
public QwenOcrRemoteService(QwenOcrRemoteProperties properties) {
this.properties = properties;
}
/**
* 接收上传的图片文件,转成 Base64 后,
* 调用 250 上的 /ocr/extractErpByBase64 接口,返回采购订单号(ERP)
*/
public String extractErpOrderNo(MultipartFile file) {
try {
// 1. 读取文件字节
byte[] bytes = file.getBytes();
// 2. 推断 contentType
String contentType = file.getContentType();
if (contentType == null || contentType.isEmpty()) {
String name = file.getOriginalFilename();
if (name != null && name.toLowerCase().endsWith(".png")) {
contentType = "image/png";
} else {
contentType = "image/jpeg";
}
}
// 3. 转成 Base64并加上 data: 前缀
String base64 = Base64.getEncoder().encodeToString(bytes);
String imageBase64 = "data:" + contentType + ";base64," + base64;
// 4. 组装 JSON 请求体:{ "imageBase64": "data:image/jpeg;base64,xxxx" }
String json = objectMapper.createObjectNode()
.put("imageBase64", imageBase64)
.toString();
RequestBody body = RequestBody.create(
MediaType.parse("application/json"),
json
);
String url = properties.getBaseUrl(); // yml 里配置的 /ocr/extractErpByBase64
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
// 5. 发送 HTTP 请求
Response response = httpClient.newCall(request).execute();
try {
if (!response.isSuccessful()) {
String errorBody = response.body() != null ? response.body().string() : "no error body";
throw new RuntimeException("调用远程 OCR 服务失败HTTP 状态码:" +
response.code() + ",错误信息:" + errorBody);
}
String resp = Objects.requireNonNull(response.body()).string();
JsonNode rootNode = objectMapper.readTree(resp);
// 远程服务返回:{ success: true, found: true/false, erpOrderNo: "0101398982" }
JsonNode erpNode = rootNode.get("erpOrderNo");
if (erpNode == null || erpNode.isNull()) {
return "";
}
return erpNode.asText("");
} finally {
response.close();
}
} catch (IOException e) {
throw new RuntimeException("调用远程 OCR 服务异常:" + e.getMessage(), e);
}
}
}

View File

@@ -1,14 +1,22 @@
package com.zg.project.wisdom.service.impl;
import java.util.List;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;
import com.zg.common.exception.ServiceException;
import com.zg.common.utils.DateUtils;
import com.zg.common.utils.SecurityUtils;
import com.zg.common.utils.StringUtils;
import com.zg.project.wisdom.domain.dto.ExcelFieldMapping;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zg.project.wisdom.mapper.GysJhMapper;
import com.zg.project.wisdom.domain.GysJh;
import com.zg.project.wisdom.service.IGysJhService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
/**
* 供应计划Service业务层处理
@@ -115,15 +123,15 @@ public class GysJhServiceImpl implements IGysJhService
for (GysJh jh : jhList) {
try {
// 唯一性校验:订单号 + 项目号 + 物料号
boolean exists = gysJhMapper.existsByUniqueKeys(jh.getSapNo(), jh.getXmNo(), jh.getWlNo());
if (exists) {
failureNum++;
failureMsg.append("<br/>订单号:").append(jh.getSapNo())
.append(",项目号:").append(jh.getXmNo())
.append(",物料号:").append(jh.getWlNo())
.append(" 已存在,跳过导入。");
continue;
}
// boolean exists = gysJhMapper.existsByUniqueKeys(jh.getSapNo(), jh.getXmNo(), jh.getWlNo());
// if (exists) {
// failureNum++;
// failureMsg.append("<br/>订单号:").append(jh.getSapNo())
// .append(",项目号:").append(jh.getXmNo())
// .append(",物料号:").append(jh.getWlNo())
// .append(" 已存在,跳过导入。");
// continue;
// }
jh.setCreateBy(operName);
jh.setStatus("0");
@@ -157,4 +165,225 @@ public class GysJhServiceImpl implements IGysJhService
public List<GysJh> getBySapNo(String sapNo) {
return gysJhMapper.getBySapNo(sapNo);
}
@Override
@Transactional(rollbackFor = Exception.class)
public int importByMapping(MultipartFile file, List<ExcelFieldMapping> mapping) throws Exception {
List<GysJh> list = parseExcel(file, mapping);
if (list == null || list.isEmpty()) {
return 0;
}
for (GysJh item : list) {
gysJhMapper.insertGysJh(item);
}
return list.size();
}
/**
* 解析 Excel -> GysJh 列表
*/
private List<GysJh> parseExcel(MultipartFile file, List<ExcelFieldMapping> mappingList) throws Exception {
List<GysJh> result = new ArrayList<>();
try (InputStream is = file.getInputStream();
Workbook workbook = WorkbookFactory.create(is)) {
Sheet sheet = workbook.getSheetAt(0);
if (sheet == null) {
return result;
}
// 1. 把映射转换成:字段名 -> 列索引
Map<String, Integer> fieldColumnIndex = new HashMap<>();
for (ExcelFieldMapping m : mappingList) {
if (m == null) {
continue;
}
String label = m.getLabel(); // wlNo / jhAmt ...
String prop = m.getProp(); // A / B / C ...
if (StringUtils.isEmpty(label) || StringUtils.isEmpty(prop)) {
continue;
}
fieldColumnIndex.put(label, excelColToIndex(prop));
}
DataFormatter formatter = new DataFormatter();
int firstRowNum = sheet.getFirstRowNum();
int lastRowNum = sheet.getLastRowNum();
// 默认第一行是表头,从第二行开始读
for (int rowNum = firstRowNum + 1; rowNum <= lastRowNum; rowNum++) {
Row row = sheet.getRow(rowNum);
if (row == null) {
continue;
}
// 关键字段都为空则认为是空行,跳过
String wlNoVal = getCellString(row, fieldColumnIndex.get("wlNo"), formatter);
String sapNoVal = getCellString(row, fieldColumnIndex.get("sapNo"), formatter);
if (StringUtils.isEmpty(wlNoVal) && StringUtils.isEmpty(sapNoVal)) {
continue;
}
GysJh item = new GysJh();
// 序号可以用行号,也可以单独映射,看你需求
item.setIndexNo((long) (rowNum));
// 按字段名逐个赋值
for (Map.Entry<String, Integer> entry : fieldColumnIndex.entrySet()) {
String field = entry.getKey();
Integer colIndex = entry.getValue();
String cellValue = getCellString(row, colIndex, formatter);
if (StringUtils.isEmpty(cellValue)) {
continue;
}
switch (field) {
case "wlNo":
item.setWlNo(cellValue.trim());
break;
case "wlMs":
item.setWlMs(cellValue.trim());
break;
case "xmNo":
item.setXmNo(cellValue.trim());
break;
case "xmMs":
item.setXmMs(cellValue.trim());
break;
case "dw":
item.setDw(cellValue.trim());
break;
case "gysNo":
item.setGysNo(cellValue.trim());
break;
case "gysMc":
item.setGysMc(cellValue.trim());
break;
case "jhAmt":
// BigDecimal
item.setJhAmt(parseBigDecimal(cellValue));
break;
case "htDj":
// BigDecimal
item.setHtDj(parseBigDecimal(cellValue));
break;
case "jhQty":
// Long这里用 Long避免 BigDecimal 转 Long 的报错
item.setJhQty(parseLong(cellValue));
break;
case "htQty":
item.setHtQty(parseLong(cellValue));
break;
case "sapNo":
item.setSapNo(cellValue.trim());
break;
default:
// 以后扩展字段,就在上面加 case
break;
}
}
// 默认字段
item.setStatus("0");
item.setIsDelete("0");
// String username = SecurityUtils.getUsername();
item.setCreateBy("大爷的!!!");
item.setCreateTime(DateUtils.getNowDate());
result.add(item);
}
}
return result;
}
/**
* Excel 列字母转索引A -> 0, B -> 1, ..., AA -> 26
*/
private int excelColToIndex(String col) {
col = col.trim().toUpperCase();
int index = 0;
for (int i = 0; i < col.length(); i++) {
char c = col.charAt(i);
index = index * 26 + (c - 'A' + 1);
}
return index - 1;
}
/**
* 统一获取单元格字符串
*/
private String getCellString(Row row, Integer colIndex, DataFormatter formatter) {
if (row == null || colIndex == null || colIndex < 0) {
return null;
}
Cell cell = row.getCell(colIndex);
if (cell == null) {
return null;
}
String val = formatter.formatCellValue(cell);
return StringUtils.isEmpty(val) ? null : val.trim();
}
/**
* 字符串转 BigDecimal空串返回 null
*/
/**
* 字符串转 BigDecimal空串或"null"返回 null
*/
private BigDecimal parseBigDecimal(String value) {
if (StringUtils.isEmpty(value)) {
return null;
}
try {
String trimmedValue = value.trim();
if ("null".equalsIgnoreCase(trimmedValue)) {
return null;
}
// 去掉千分位逗号
String v = trimmedValue.replace(",", "").trim();
// 再次检查处理后的值
if (StringUtils.isEmpty(v) || "null".equalsIgnoreCase(v)) {
return null;
}
return new BigDecimal(v);
} catch (NumberFormatException e) {
// 记录详细错误信息以便调试
// log.warn("解析BigDecimal失败输入值: '{}'", value, e);
return null;
}
}
/**
* 字符串转 Long空串返回 null
*/
private Long parseLong(String value) {
if (StringUtils.isEmpty(value)) {
return null;
}
String trimmedValue = value.trim();
if ("null".equalsIgnoreCase(trimmedValue)) {
return null;
}
try {
String v = trimmedValue.replace(",", "").trim();
if (StringUtils.isEmpty(v) || "null".equalsIgnoreCase(v)) {
return null;
}
return Long.valueOf(v);
} catch (NumberFormatException e) {
// log.warn("无法解析为Long的值: '{}'", value);
return null;
}
}
}

View File

@@ -1128,8 +1128,11 @@ public class RkInfoServiceImpl implements IRkInfoService
}
@Override
public int updateDeliveryStatus(String billNoCk, Integer isDelivery) {
return rkInfoMapper.updateDeliveryStatus(billNoCk, isDelivery);
public int updateDeliveryStatus(List<Long> ids, Integer isDelivery) {
if (ids == null || ids.isEmpty()) {
return 0;
}
return rkInfoMapper.updateDeliveryStatus(ids, isDelivery);
}
@Override

View File

@@ -165,4 +165,8 @@ minio:
mock:
agv-job-create-url: http://localhost:8086/mock/agv/task/create
wcs-job-create-url: http://localhost:8086/mock/wcs/task/create
wcs-job-create-url: http://localhost:8086/mock/wcs/task/create
#配送系统中调用大模型进行图片识别
qwen-ocr:
base-url: http://192.168.1.253:8087/ocr/extractErpByBase64

View File

@@ -76,14 +76,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND status != '1'
</select>
<select id="existsByUniqueKeys" resultType="boolean">
<!-- 【已注释】唯一性校验查询基于SAP订单号、项目号、物料号判断是否已存在 -->
<!-- <select id="existsByUniqueKeys" resultType="boolean">
SELECT COUNT(1)
FROM gys_jh
WHERE sap_no = #{sapNo}
AND xm_no = #{xmNo}
AND wl_no = #{wlNo}
AND is_delete != '1'
</select>
</select> -->
<select id="selectByIds" resultMap="GysJhResult">
SELECT * FROM gys_jh
@@ -230,4 +231,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{id}
</foreach>
</delete>
</mapper>
</mapper>

View File

@@ -1223,8 +1223,10 @@
<update id="updateDeliveryStatus">
UPDATE rk_info
SET is_delivery = #{isDelivery}
WHERE bill_no_ck = #{billNoCk}
AND is_delete = '0'
WHERE is_delete = '0'
AND id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</update>
</mapper>