no message

main
HUOJIN\92525 2025-11-23 19:17:05 +08:00
parent 6d64ca5662
commit 50a9c19e15
17 changed files with 207 additions and 61 deletions

View File

@ -5,16 +5,18 @@ import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.*;
import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.log.Log;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.jeecg.common.config.TenantContext;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.TenantConstant;
@ -27,14 +29,17 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* jeecg.datasource.open = false
* @Author zhoujf
*
* @Author zhoujf
*/
@Slf4j
@Configuration
@ -46,7 +51,7 @@ public class MybatisPlusSaasConfig {
/**
*
*
*
* <p>
*
* 1.ID
* 2. TENANT_TABLE
@ -82,6 +87,22 @@ public class MybatisPlusSaasConfig {
TENANT_TABLE.add("airag_knowledge");
TENANT_TABLE.add("airag_knowledge_doc");
TENANT_TABLE.add("airag_model");
TENANT_TABLE.add("base_area");
TENANT_TABLE.add("base_item");
TENANT_TABLE.add("base_point");
TENANT_TABLE.add("base_stock");
TENANT_TABLE.add("data_asn");
TENANT_TABLE.add("data_asn_detail");
TENANT_TABLE.add("data_receive_record");
TENANT_TABLE.add("data_pick");
TENANT_TABLE.add("data_pick_detail");
TENANT_TABLE.add("data_task");
TENANT_TABLE.add("data_agv_task");
TENANT_TABLE.add("data_inventory");
TENANT_TABLE.add("data_inventory_log");
}
//2.示例测试
@ -94,6 +115,7 @@ public class MybatisPlusSaasConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 先 add TenantLineInnerInterceptor 再 add PaginationInnerInterceptor
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
@Override
@ -151,19 +173,19 @@ public class MybatisPlusSaasConfig {
//【jeecg-boot/issues/3847】增加@Version乐观锁支持
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
interceptor.addInnerInterceptor(fixForUpdateOrderInterceptor());
return interceptor;
}
/**
* ,vue2vue3,sys_role_indexvue3sys_role_index_v3
*
* @return
*/
private DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor() {
DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> {
/* if (sql.contains("FOR UPDATE")) {
return tableName;
}*/
//获取需要动态解析的表名
String dynamicTableName = ThreadLocalDataHelper.get(CommonConstant.DYNAMIC_TABLE_NAME);
//当dynamicTableName不为空时才走动态表名处理逻辑,否则返回原始表名
@ -180,6 +202,66 @@ public class MybatisPlusSaasConfig {
return dynamicTableNameInnerInterceptor;
}
private InnerInterceptor fixForUpdateOrderInterceptor() {
return new InnerInterceptor() {
@Override
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds,
ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
String originalSql = boundSql.getSql();
String upperSql = originalSql.toUpperCase();
if (upperSql.contains("FOR UPDATE") && upperSql.contains("ORDER BY")) {
// 检查FOR UPDATE是否在ORDER BY之后
String fixedSql = moveForUpdateToEnd(upperSql);
try {
Field sqlField = BoundSql.class.getDeclaredField("sql");
sqlField.setAccessible(true);
sqlField.set(boundSql, fixedSql);
} catch (Exception e) {
log.warn("Failed to fix FOR UPDATE order in SQL: {}", e.getMessage());
}
}
}
public static String moveForUpdateToEnd(String originalSql) {
if (originalSql == null || originalSql.trim().isEmpty()) {
return originalSql;
}
// 1. 将 SQL 转换为大写,以简化匹配过程,但保留原始大小写用于最终输出(通过捕获组实现)。
// 同时在处理前和处理后去除多余的首尾空格。
String sql = originalSql.trim();
// 2. 正则表达式模式解释:
// - (.*?):捕获语句开头到 FOR UPDATE 之前的任何内容 (第1组SELECT/FROM/WHERE 部分)。
// - (\sFOR\sUPDATE\s*):捕获 'FOR UPDATE' (第2组FOR UPDATE)。
// - (\sORDER\sBY\s.*):捕获 'ORDER BY' 及其之后的所有内容 (第3组ORDER BY 部分)。
// - $:确保匹配到字符串末尾。
// - 关键字之间使用 \s 匹配空白字符,防止误匹配。
// - 使用 (?i) 开启不区分大小写匹配。
//
// 完整的原始结构: (SELECT/FROM/WHERE...) (FOR UPDATE) (ORDER BY...)
// 期望的替换结构: (SELECT/FROM/WHERE...) (ORDER BY...) (FOR UPDATE)
// 模式: 捕获 (SELECT/FROM/WHERE) + (FOR UPDATE) + (ORDER BY ...)
String regex = "(?is)(.*?)(\\sFOR\\sUPDATE\\s*)(\\sORDER\\sBY.*)";
// 替换表达式: $1 是 SELECT/FROM/WHERE 部分, $3 是 ORDER BY 部分, $2 是 FOR UPDATE 部分
String replacement = "$1$3$2";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(sql);
if (matcher.find()) {
// 如果找到匹配,则进行替换
return matcher.replaceAll(replacement);
} else {
// 如果没有匹配到包含 FOR UPDATE 和 ORDER BY 的特定顺序,则返回原始语句
return originalSql;
}
}
};
}
// /**
// * 下个版本会删除,现在为了避免缓存出现问题不得不配置
// * @return

View File

@ -16,7 +16,9 @@ public enum AsnStatusEnum {
RECEIVED(3, "收货完成"),
CANCELED(4, "已取消"),
CLOSED(4, "已关闭"),
CANCELED(5, "已取消"),
;

View File

@ -32,10 +32,18 @@ public class ConveyorLineController {
@AutoLog(value = "输送线扫描")
@Operation(summary = "输送线-扫描托盘")
@PostMapping(value = "/scanTray")
@IgnoreAuth
public Result<String> scanTray(@RequestBody @Valid ScanTrayRequest scanTrayRequest) {
iConveyorLineService.scanTray(scanTrayRequest);
return Result.OK("扫描成功");
}
@AutoLog(value = "输送线大屏")
@Operation(summary = "输送线-大屏显示")
@PostMapping(value = "/")
public Result<String> showConveyorLineBigScreen() {
iConveyorLineService.showConveyorLineBigScreen();
return Result.OK();
}
}

View File

@ -10,4 +10,6 @@ public interface IConveyorLineService {
* @param scanTrayRequest
*/
void scanTray(ScanTrayRequest scanTrayRequest);
void showConveyorLineBigScreen();
}

View File

@ -0,0 +1,5 @@
package org.cpte.modules.conveyorLine.vo;
public class ConveyorLineBigScreenVo {
private String stockCode;
}

View File

@ -27,6 +27,7 @@
#{whCode}
</foreach>
</if>
ORDER BY create_time
FOR UPDATE
</select>
</mapper>

View File

@ -85,7 +85,7 @@ public class Asn implements Serializable {
private java.lang.Integer orderType;
/**
*
* 1.;2.;3.;4.
* 1.;2.;3.;4.5.
*/
@Excel(name = "订单状态", width = 15)
@Schema(description = "订单状态")

View File

@ -279,16 +279,18 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
@Override
public void receiveCallback(Asn asn, AsnDetail asnDetail, Stock stock) {
String url = openApiMapper.getRequestUrl(GeneralConstant.INBOUND_CALLBACK);
String json = receiveCallbackJson(asn, asnDetail, stock);
log.info("入库回传请求报文:{}", json);
// 检查接口开关, 未开启则返回
if (sysDictMapper.queryByDictCode(GeneralConstant.OPEN_FLAG) == null) {
updateAsnDetailResponse(asn, "接口未开启");
return;
}
if(AsnStatusEnum.){
}
String json = receiveCallbackJson(asn, asnDetail, stock);
String url = openApiMapper.getRequestUrl(GeneralConstant.INBOUND_CALLBACK);
log.info("入库回传请求报文:{}", json);
Boolean Success = null;
String Message = null;
try {

View File

@ -1,8 +1,5 @@
package org.cpte.modules.saiWms.service;
import org.cpte.modules.base.entity.Stock;
import org.cpte.modules.receive.entity.Asn;
import org.cpte.modules.receive.entity.AsnDetail;
import org.cpte.modules.saiWms.request.InboundRequest;
import org.cpte.modules.saiWms.request.OutboundRequest;

View File

@ -58,17 +58,11 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
@RequestMapping("/shipping/pick")
@Slf4j
public class PickController {
@Autowired
private PickMapper pickMapper;
@Autowired
private TaskMapper taskMapper;
@Autowired
private IPickService pickService;
@Autowired
private IPickDetailService pickDetailService;
@Autowired
private ITaskService taskService;
@Autowired
private PickSerialNumberRule pickSerialNumberRule;
/**
@ -277,19 +271,4 @@ public class PickController {
}
return Result.OK("文件导入失败!");
}
/**
*
*/
@AutoLog(value = "出库分配")
@Operation(summary = "出库分配")
@PostMapping(value = "/allocatedPick")
@IgnoreAuth
public Result<String> allocatedPick() {
List<Long> pickList = pickMapper.queryUnallocatedPick();
pickService.allocatePick2(pickList);
taskService.generateAgvTask();
return Result.OK("操作成功!");
}
}

View File

@ -21,6 +21,6 @@ public interface TaskMapper extends BaseMapper<Task> {
*
* @return List<Pick>
*/
@Select("SELECT t.* FROM data_task t WHERE t.agv_task_id IS NULL ORDER BY t.create_time ASC FOR UPDATE ")
@Select("SELECT * FROM data_task WHERE agv_task_id is null order by create_time for update ")
List<Task> queryUnallocatedTask();
}

View File

@ -1,4 +1,5 @@
<?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="org.cpte.modules.shipping.mapper.TaskMapper">
</mapper>

View File

@ -3,6 +3,7 @@ package org.cpte.modules.shipping.service;
import org.cpte.modules.shipping.entity.PickDetail;
import org.cpte.modules.shipping.entity.Pick;
import com.baomidou.mybatisplus.extension.service.IService;
import org.cpte.modules.shipping.entity.Task;
import java.io.Serializable;
import java.util.Collection;
@ -60,4 +61,12 @@ public interface IPickService extends IService<Pick> {
*/
List<String> allocatePick2(List<Long> pickIds);
/**
*
*
* @param task
*/
void pickTaskCallback(Task task);
}

View File

@ -542,4 +542,9 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
return new ArrayList<>(errorMsgSet);
}
@Override
public void pickTaskCallback(Task task) {
Pick pick = pickMapper.selectById(task.getPickId());
}
}

View File

@ -117,6 +117,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
@Override
@Transactional(rollbackFor = Exception.class)
public void generateAgvTask() {
List<Task> taskList = taskMapper.queryUnallocatedTask();
if (CollectionUtils.isEmpty(taskList)) {
return;

View File

@ -32,9 +32,9 @@ public class CodeGeneratorUtil {
try {
String dateStr = LocalDate.now().format(DATE_FORMATTER);
// 使用 SELECT FOR UPDATE 加锁查询并更新
// 使用 SELECT for update 加锁查询并更新
String lockAndUpdateSql =
"SELECT current_seq FROM generator_sequence WHERE type = ? AND date_str = ? FOR UPDATE";
"SELECT current_seq FROM generator_sequence WHERE type = ? AND date_str = ? for update";
List<Integer> result = jdbcTemplate.queryForList(lockAndUpdateSql, Integer.class, type, dateStr);

View File

@ -0,0 +1,52 @@
package org.cpte.modules.utils;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;
public class test {
public static void main(String[] args) {
Map<String, String> saiMap = new HashMap<>();
saiMap.put("ak", "ak-h98TNj1bO5258uuS");
saiMap.put("sk", "E20j9w4vkTkLkv6tjALrzYqcybrvDaCx");
Map<String, String> tesMap = new HashMap<>();
tesMap.put("ak", "ak-EMCNIpxwfMXzJ8rj");
tesMap.put("sk", "HtT14KlSwCfLfLyGe3FeJVPc3zmjZwXR");
long timestamp = System.currentTimeMillis();
System.out.println("sai-timestamp:" + timestamp);
System.out.println("sai-signature:" + md5(saiMap.get("ak")+ saiMap.get("sk") + timestamp));
System.out.println("=======================================================================================");
System.out.println("tes-timestamp:" + timestamp);
System.out.println("tes-signature:" + md5(tesMap.get("ak")+ tesMap.get("sk") + timestamp));
}
public static String md5(String sourceStr) {
String result = "";
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(sourceStr.getBytes(StandardCharsets.UTF_8));
byte[] hash = md.digest();
int i;
StringBuffer buf = new StringBuffer(32);
for (int offset = 0; offset < hash.length; offset++) {
i = hash[offset];
if (i < 0) {
i += 256;
}
if (i < 16) {
buf.append("0");
}
buf.append(Integer.toHexString(i));
}
result = buf.toString();
} catch (Exception e) {
System.out.println("sign签名错误" + e);
}
return result;
}
}