去除mqtt功能
修改查询接口
This commit is contained in:
@@ -1,182 +0,0 @@
|
||||
package com.zg.project.wisdom.config;
|
||||
|
||||
import com.zg.project.wisdom.mqtt.dispatcher.MqttMessageDispatcher;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.paho.client.mqttv3.*;
|
||||
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.annotation.Resource;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* MQTT 客户端初始化配置类
|
||||
*
|
||||
* 作用说明:
|
||||
* 1. Spring Boot 启动时自动创建 MQTT 客户端
|
||||
* 2. 连接 EMQX Broker
|
||||
* 3. 订阅 application.yml 中配置的 Topic(支持通配符)
|
||||
* 4. 接收传感器上报的数据
|
||||
*
|
||||
* 说明:
|
||||
* - 同一个 MQTT Client 同时支持「订阅(接收)」和「发布(下发指令)」
|
||||
* - 后端一般只需要一个 Client
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class MqttClientConfig {
|
||||
|
||||
/**
|
||||
* MQTT 客户端实例
|
||||
* 由本配置类统一维护
|
||||
*/
|
||||
private MqttClient mqttClient;
|
||||
|
||||
@Resource
|
||||
private MqttMessageDispatcher mqttMessageDispatcher;
|
||||
|
||||
/**
|
||||
* 创建 MQTT Client Bean
|
||||
*
|
||||
* @param props MQTT 配置(来自 application.yml)
|
||||
*/
|
||||
@Bean
|
||||
public MqttClient mqttClient(MqttProperties props) throws MqttException {
|
||||
|
||||
// 如果未开启 MQTT 功能,直接不初始化
|
||||
// 注意:此时 mqttClient Bean 为 null
|
||||
if (!props.isEnabled()) {
|
||||
log.warn("[MQTT] mqtt.enabled=false,MQTT 功能未启用");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 1. 创建 MQTT 客户端
|
||||
mqttClient = new MqttClient(
|
||||
props.getBroker(),
|
||||
props.getClientId(),
|
||||
new MemoryPersistence()
|
||||
);
|
||||
|
||||
// 2. MQTT 连接参数
|
||||
MqttConnectOptions options = new MqttConnectOptions();
|
||||
|
||||
// 是否清除会话:
|
||||
// true - 断开后清除订阅(推荐后端使用)
|
||||
// false - 保留会话(多用于设备端)
|
||||
options.setCleanSession(props.isCleanSession());
|
||||
|
||||
// 心跳时间(秒)
|
||||
options.setKeepAliveInterval(props.getKeepAlive());
|
||||
|
||||
// 连接超时时间(秒)
|
||||
options.setConnectionTimeout(props.getTimeout());
|
||||
|
||||
// 自动重连(非常重要,防止网络抖动)
|
||||
options.setAutomaticReconnect(true);
|
||||
|
||||
// 设置用户名密码(如果配置了)
|
||||
if (props.getUsername() != null && !props.getUsername().trim().isEmpty()) {
|
||||
options.setUserName(props.getUsername().trim());
|
||||
}
|
||||
if (props.getPassword() != null && !props.getPassword().trim().isEmpty()) {
|
||||
options.setPassword(props.getPassword().toCharArray());
|
||||
}
|
||||
|
||||
// 3. 设置 MQTT 回调
|
||||
mqttClient.setCallback(new MqttCallbackExtended() {
|
||||
|
||||
/**
|
||||
* 连接成功(或重连成功)回调
|
||||
*/
|
||||
@Override
|
||||
public void connectComplete(boolean reconnect, String serverURI) {
|
||||
log.info("[MQTT] 连接成功 reconnect={}, serverURI={}", reconnect, serverURI);
|
||||
// 连接成功后订阅 Topic
|
||||
subscribe(props);
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接丢失回调
|
||||
*/
|
||||
@Override
|
||||
public void connectionLost(Throwable cause) {
|
||||
log.warn("[MQTT] 连接断开", cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收到消息回调
|
||||
*
|
||||
* @param topic 消息主题(用于区分设备、类型)
|
||||
* @param message 消息内容
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void messageArrived(String topic, MqttMessage message) {
|
||||
String payload = new String(message.getPayload(), StandardCharsets.UTF_8);
|
||||
mqttMessageDispatcher.dispatch(topic, payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息发送完成回调(发布消息后触发)
|
||||
*/
|
||||
@Override
|
||||
public void deliveryComplete(IMqttDeliveryToken token) {
|
||||
// 后端下发指令时可用于确认发送完成
|
||||
}
|
||||
});
|
||||
|
||||
// 4. 连接 Broker
|
||||
log.info("[MQTT] 正在连接 Broker:{}", props.getBroker());
|
||||
mqttClient.connect(options);
|
||||
log.info("[MQTT] MQTT 已连接");
|
||||
|
||||
// 5. 启动时先订阅一次(防止 connectComplete 未触发)
|
||||
subscribe(props);
|
||||
|
||||
return mqttClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* 订阅 Topic(支持通配符)
|
||||
*/
|
||||
private void subscribe(MqttProperties props) {
|
||||
if (mqttClient == null || !mqttClient.isConnected()) {
|
||||
log.warn("[MQTT] 订阅失败:客户端未连接");
|
||||
return;
|
||||
}
|
||||
if (props.getTopics() == null || props.getTopics().isEmpty()) {
|
||||
log.warn("[MQTT] 未配置订阅 Topic");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
for (String topic : props.getTopics()) {
|
||||
if (topic == null || topic.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
mqttClient.subscribe(topic.trim(), props.getQos());
|
||||
log.info("[MQTT] 已订阅 Topic:{},QoS={}", topic.trim(), props.getQos());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[MQTT] 订阅 Topic 失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Spring 容器关闭时,优雅断开 MQTT 连接
|
||||
*/
|
||||
@PreDestroy
|
||||
public void destroy() {
|
||||
try {
|
||||
if (mqttClient != null) {
|
||||
if (mqttClient.isConnected()) {
|
||||
mqttClient.disconnect();
|
||||
}
|
||||
mqttClient.close();
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package com.zg.project.wisdom.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* MQTT 配置属性(对应 application.yml 中 mqtt.*)
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "mqtt")
|
||||
public class MqttProperties {
|
||||
|
||||
/** 是否启用 MQTT */
|
||||
private boolean enabled;
|
||||
|
||||
/** Broker 地址:tcp://192.168.1.29:1883 */
|
||||
private String broker;
|
||||
|
||||
/** 客户端ID(在 EMQX 中唯一) */
|
||||
private String clientId;
|
||||
|
||||
/** 账号 */
|
||||
private String username;
|
||||
|
||||
/** 密码 */
|
||||
private String password;
|
||||
|
||||
/** 是否清除会话 */
|
||||
private boolean cleanSession = true;
|
||||
|
||||
/** 心跳时间(秒) */
|
||||
private int keepAlive = 30;
|
||||
|
||||
/** 连接超时时间(秒) */
|
||||
private int timeout = 10;
|
||||
|
||||
/** 默认 QoS */
|
||||
private int qos = 1;
|
||||
|
||||
/** 订阅 Topic 列表(支持通配符) */
|
||||
private List<String> topics;
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package com.zg.project.wisdom.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* MQTT 消息发布客户端
|
||||
*
|
||||
* 作用说明:
|
||||
* - 专门用于向指定设备下发控制指令
|
||||
* - 例如:开启 / 关闭 / 重启 传感器
|
||||
*
|
||||
* 说明:
|
||||
* - 依赖同一个 MqttClient
|
||||
* - 发布消息时使用“精确 Topic”(不能使用通配符)
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class MqttPublishClient {
|
||||
|
||||
/**
|
||||
* MQTT 客户端(由 Spring 注入)
|
||||
*/
|
||||
private final MqttClient mqttClient;
|
||||
|
||||
public MqttPublishClient(MqttClient mqttClient) {
|
||||
this.mqttClient = mqttClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布 MQTT 消息(默认 QoS=1,不保留消息)
|
||||
*
|
||||
* @param topic 目标 Topic(必须是具体设备的 Topic)
|
||||
* @param payload 消息内容(JSON 字符串)
|
||||
*/
|
||||
public void publish(String topic, String payload) {
|
||||
publish(topic, payload, 1, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布 MQTT 消息(自定义参数)
|
||||
*/
|
||||
public void publish(String topic, String payload, int qos, boolean retained) {
|
||||
|
||||
// 如果 MQTT 未启用或未初始化
|
||||
if (mqttClient == null) {
|
||||
throw new IllegalStateException("MQTT 客户端未初始化(mqtt.enabled=false)");
|
||||
}
|
||||
|
||||
// 如果 MQTT 尚未连接
|
||||
if (!mqttClient.isConnected()) {
|
||||
throw new IllegalStateException("MQTT 客户端未连接到 Broker");
|
||||
}
|
||||
|
||||
try {
|
||||
MqttMessage msg = new MqttMessage(payload.getBytes(StandardCharsets.UTF_8));
|
||||
msg.setQos(qos);
|
||||
msg.setRetained(retained);
|
||||
|
||||
mqttClient.publish(topic, msg);
|
||||
|
||||
log.info("[MQTT] 指令已发送 topic={}, qos={}, retained={}, payload={}",
|
||||
topic, qos, retained, payload);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[MQTT] 指令发送失败 topic=" + topic, e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import com.zg.common.utils.StringUtils;
|
||||
import com.zg.project.wisdom.domain.dto.*;
|
||||
import com.zg.project.wisdom.domain.vo.DeliveryBillVO;
|
||||
import com.zg.project.wisdom.service.QwenOcrRemoteService;
|
||||
import com.zg.project.wisdom.service.RkStatisticsService;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -96,14 +97,28 @@ public class RkInfoController extends BaseController
|
||||
}
|
||||
|
||||
// @PreAuthorize("@ss.hasPermi('wisdom:stock:list')")
|
||||
@PostMapping("/bill/groups")
|
||||
public TableDataInfo billGroups(@RequestBody RkInfoQueryDTO query) {
|
||||
// 分页
|
||||
PageHelper.startPage(query.getPageNum(), query.getPageSize());
|
||||
// 查询
|
||||
List<RkInfo> rows = rkInfoService.selectGroupedByBill(query);
|
||||
// @PostMapping("/bill/groups")
|
||||
// public TableDataInfo billGroups(@RequestBody RkInfoQueryDTO query) {
|
||||
// // 分页
|
||||
// PageHelper.startPage(query.getPageNum(), query.getPageSize());
|
||||
// // 查询
|
||||
// List<RkInfo> rows = rkInfoService.selectGroupedByBill(query);
|
||||
//
|
||||
// return getDataTable(rows);
|
||||
// }
|
||||
|
||||
return getDataTable(rows);
|
||||
/**
|
||||
* 获取单据列表(轻量级:仅返回单据头公共信息,不聚合明细字段)
|
||||
*/
|
||||
@PostMapping("/bill/groups")
|
||||
public TableDataInfo billHeaderList(@RequestBody RkInfoQueryDTO query) {
|
||||
// 1. 分页
|
||||
PageHelper.startPage(query.getPageNum(), query.getPageSize());
|
||||
|
||||
// 2. 查询
|
||||
List<RkInfo> list = rkInfoService.selectBillHeaderList(query);
|
||||
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -365,16 +380,5 @@ public class RkInfoController extends BaseController
|
||||
|
||||
}
|
||||
|
||||
@PostMapping("/statistics")
|
||||
public Map<String, Object> statistics(@RequestBody RkInfoQueryDTO dto) {
|
||||
|
||||
Long sumMoney = rkInfoService.selectStatistics(dto);
|
||||
Long pcdeCount = rkInfoService.selectPcde(dto);
|
||||
|
||||
Map<String, Object> dataInfo = new HashMap<>();
|
||||
dataInfo.put("sumMoney", sumMoney);
|
||||
dataInfo.put("pcdeCount", pcdeCount);
|
||||
return dataInfo;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.zg.project.wisdom.controller;
|
||||
|
||||
import com.zg.framework.web.domain.AjaxResult;
|
||||
import com.zg.project.wisdom.domain.dto.RkInfoQueryDTO;
|
||||
import com.zg.project.wisdom.domain.vo.*;
|
||||
import com.zg.project.wisdom.service.RkStatisticsService;
|
||||
import com.zg.project.wisdom.service.WarehouseStatService;
|
||||
@@ -178,4 +179,10 @@ public class RkStatisticsController {
|
||||
List<IOBucketVO> rows = rkStatisticsService.getIOBuckets(range);
|
||||
return AjaxResult.success(rows);
|
||||
}
|
||||
|
||||
@PostMapping("/statistics")
|
||||
public Map<String, Object> statistics(@RequestBody RkInfoQueryDTO dto) {
|
||||
// 调用新的合并查询方法
|
||||
return rkStatisticsService.selectStockStatistics(dto);
|
||||
}
|
||||
}
|
||||
@@ -20,10 +20,10 @@ public class RkInfoQueryDTO extends RkInfo {
|
||||
private Integer pageSize;
|
||||
|
||||
/** 开始时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date statDate;
|
||||
|
||||
/** 结束时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date endDate;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.zg.project.wisdom.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.zg.project.inventory.domain.vo.PcdeCntVO;
|
||||
import com.zg.project.inventory.domain.vo.RkInfoMatchVO;
|
||||
@@ -39,6 +40,8 @@ public interface RkInfoMapper
|
||||
@Param("needAudit") Integer needAudit);
|
||||
|
||||
|
||||
List<RkInfo> selectBillHeaderList(@Param("q") RkInfoQueryDTO query,
|
||||
@Param("needAudit") Integer needAudit);
|
||||
|
||||
/**
|
||||
* 修改库存单据主
|
||||
@@ -234,10 +237,6 @@ public interface RkInfoMapper
|
||||
*/
|
||||
List<RkInfo> selectAllRkInfo(RkInfo query);
|
||||
|
||||
Long selectStatistics(RkInfo query);
|
||||
|
||||
Long selectPcde(RkInfo query);
|
||||
|
||||
|
||||
int updateBillInfo(RkInfo query);
|
||||
|
||||
@@ -263,4 +262,7 @@ public interface RkInfoMapper
|
||||
RkInfo selectHeaderByBillNo(String billNo);
|
||||
|
||||
String selectMaxBillNo(@Param("prefix") String prefix);
|
||||
|
||||
|
||||
Map<String, Object> selectStockStatistics(RkInfoQueryDTO query);
|
||||
}
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
package com.zg.project.wisdom.mqtt.dispatcher;
|
||||
|
||||
import com.zg.project.wisdom.mqtt.handler.HumiSensorHandler;
|
||||
import com.zg.project.wisdom.mqtt.handler.SmokeSensorHandler;
|
||||
import com.zg.project.wisdom.mqtt.handler.TempSensorHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* MQTT消息分发器
|
||||
* 负责根据MQTT主题(topic)将消息分发给相应的传感器处理器
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class MqttMessageDispatcher {
|
||||
|
||||
@Autowired
|
||||
private TempSensorHandler tempSensorHandler;
|
||||
@Autowired
|
||||
private HumiSensorHandler humiSensorHandler;
|
||||
@Autowired
|
||||
private SmokeSensorHandler smokeSensorHandler;
|
||||
|
||||
/**
|
||||
* 分发MQTT消息到对应的处理器
|
||||
* 根据topic的前缀判断消息类型,并调用相应的处理器进行处理
|
||||
*
|
||||
* @param topic MQTT主题,用于判断消息类型
|
||||
* @param payload 消息负载,包含具体的传感器数据
|
||||
*/
|
||||
public void dispatch(String topic, String payload) {
|
||||
|
||||
// 处理温度传感器消息
|
||||
if (topic.startsWith("zg/wms/test/temp/")) {
|
||||
tempSensorHandler.handle(topic, payload);
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理湿度传感器消息
|
||||
if (topic.startsWith("zg/wms/test/humi/")) {
|
||||
humiSensorHandler.handle(topic, payload);
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理烟雾传感器消息
|
||||
if (topic.startsWith("zg/wms/test/smoke/")) {
|
||||
smokeSensorHandler.handle(topic, payload);
|
||||
return;
|
||||
}
|
||||
|
||||
log.warn("未知 MQTT Topic: {}", topic);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
package com.zg.project.wisdom.mqtt.handler;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 湿度传感器 Handler
|
||||
* Topic 示例:zg/wms/test/humi/{deviceId}
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class HumiSensorHandler {
|
||||
|
||||
public static final String TOPIC_PREFIX = "zg/wms/test/humi/";
|
||||
|
||||
/**
|
||||
* 处理湿度传感器消息
|
||||
* @param topic MQTT主题
|
||||
* @param payload 消息负载
|
||||
*/
|
||||
public void handle(String topic, String payload) {
|
||||
String deviceId = resolveDeviceId(topic, TOPIC_PREFIX);
|
||||
|
||||
log.info("[HUMI] deviceId={}, topic={}, payload={}", deviceId, topic, payload);
|
||||
|
||||
// TODO: 这里后续写湿度业务逻辑
|
||||
}
|
||||
|
||||
/**
|
||||
* 从MQTT主题中解析设备ID
|
||||
* @param topic MQTT主题
|
||||
* @param prefix 主题前缀
|
||||
* @return 设备ID
|
||||
*/
|
||||
private String resolveDeviceId(String topic, String prefix) {
|
||||
if (topic == null || !topic.startsWith(prefix)) {
|
||||
return "";
|
||||
}
|
||||
// 提取设备ID部分
|
||||
return topic.substring(prefix.length());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
package com.zg.project.wisdom.mqtt.handler;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 烟雾传感器 Handler
|
||||
* Topic 示例:zg/wms/test/smoke/{deviceId}
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class SmokeSensorHandler {
|
||||
|
||||
/**
|
||||
* MQTT主题前缀,用于烟雾传感器消息
|
||||
*/
|
||||
public static final String TOPIC_PREFIX = "zg/wms/test/smoke/";
|
||||
|
||||
/**
|
||||
* 处理烟雾传感器消息
|
||||
*
|
||||
* @param topic MQTT主题
|
||||
* @param payload 消息负载内容
|
||||
*/
|
||||
public void handle(String topic, String payload) {
|
||||
String deviceId = resolveDeviceId(topic, TOPIC_PREFIX);
|
||||
|
||||
log.info("[SMOKE] deviceId={}, topic={}, payload={}", deviceId, topic, payload);
|
||||
|
||||
// TODO: 这里后续写烟雾业务逻辑
|
||||
}
|
||||
|
||||
/**
|
||||
* 从MQTT主题中解析设备ID
|
||||
*
|
||||
* @param topic 完整的MQTT主题
|
||||
* @param prefix 主题前缀
|
||||
* @return 设备ID,如果主题格式不正确则返回空字符串
|
||||
*/
|
||||
private String resolveDeviceId(String topic, String prefix) {
|
||||
if (topic == null || !topic.startsWith(prefix)) {
|
||||
return "";
|
||||
}
|
||||
// 提取前缀后的设备ID部分
|
||||
return topic.substring(prefix.length());
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package com.zg.project.wisdom.mqtt.handler;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 温度传感器 Handler
|
||||
* Topic 示例:zg/wms/test/temp/{deviceId}
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class TempSensorHandler {
|
||||
|
||||
/**
|
||||
* MQTT主题前缀,用于温度传感器数据
|
||||
*/
|
||||
public static final String TOPIC_PREFIX = "zg/wms/test/temp/";
|
||||
|
||||
/**
|
||||
* 处理温度传感器数据
|
||||
*
|
||||
* @param topic MQTT主题,格式为 zg/wms/test/temp/{deviceId}
|
||||
* @param payload 传感器数据载荷
|
||||
*/
|
||||
public void handle(String topic, String payload) {
|
||||
String deviceId = resolveDeviceId(topic, TOPIC_PREFIX);
|
||||
|
||||
log.info("[TEMP] deviceId={}, topic={}, payload={}", deviceId, topic, payload);
|
||||
|
||||
// TODO: 这里后续写温度业务逻辑(解析JSON、落库、告警等)
|
||||
}
|
||||
|
||||
/**
|
||||
* 从MQTT主题中解析设备ID
|
||||
*
|
||||
* @param topic MQTT主题
|
||||
* @param prefix 主题前缀
|
||||
* @return 设备ID,如果主题格式不正确则返回空字符串
|
||||
*/
|
||||
private String resolveDeviceId(String topic, String prefix) {
|
||||
if (topic == null || !topic.startsWith(prefix)) {
|
||||
return "";
|
||||
}
|
||||
return topic.substring(prefix.length());
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.zg.project.wisdom.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.zg.project.inventory.domain.dto.QueryDTO;
|
||||
import com.zg.project.inventory.domain.vo.ChartDataVO;
|
||||
@@ -38,6 +39,10 @@ public interface IRkInfoService
|
||||
*/
|
||||
List<RkInfo> selectGroupedByBill(RkInfoQueryDTO query);
|
||||
|
||||
// 接口
|
||||
List<RkInfo> selectBillHeaderList(RkInfoQueryDTO query);
|
||||
|
||||
|
||||
/**
|
||||
* 修改库存单据主
|
||||
*
|
||||
@@ -168,11 +173,6 @@ public interface IRkInfoService
|
||||
*/
|
||||
List<RkInfo> selectAllRkInfo(RkInfo query);
|
||||
|
||||
Long selectStatistics(RkInfo query);
|
||||
|
||||
Long selectPcde(RkInfo query);
|
||||
|
||||
|
||||
public int updateBillInfo(RkInfo rkInfo);
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.zg.project.wisdom.service;
|
||||
|
||||
import com.zg.project.wisdom.domain.dto.RkInfoQueryDTO;
|
||||
import com.zg.project.wisdom.domain.vo.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -87,4 +88,11 @@ public interface RkStatisticsService {
|
||||
* 规则:排除 rk_info 中未出库(is_chuku=0 或 NULL)的占用库位
|
||||
*/
|
||||
List<SceneAvailableVO> listAvailableByWarehouse(String warehouseCode);
|
||||
|
||||
/**
|
||||
* 库存统计
|
||||
* @param dto 查询参数
|
||||
* @return { "total": 0, "rows": List<StockStatVO> }
|
||||
*/
|
||||
Map<String, Object> selectStockStatistics(RkInfoQueryDTO dto);
|
||||
}
|
||||
|
||||
@@ -183,7 +183,13 @@ public class RkInfoServiceImpl implements IRkInfoService
|
||||
boolean needAudit = "1".equals(configService.selectConfigByKey("rk.audit.enabled"));
|
||||
// 直接传给 Mapper;不改 DTO 结构,走多参数方式
|
||||
return rkInfoMapper.selectGroupedByBill(query, needAudit ? 1 : 0);
|
||||
// return rkInfoMapper.selectGroupedByBillSimple(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RkInfo> selectBillHeaderList(RkInfoQueryDTO query) {
|
||||
// 同样传入审核开关逻辑(保留原逻辑一致性)
|
||||
boolean needAudit = "1".equals(configService.selectConfigByKey("rk.audit.enabled"));
|
||||
return rkInfoMapper.selectBillHeaderList(query, needAudit ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1388,16 +1394,6 @@ public class RkInfoServiceImpl implements IRkInfoService
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long selectStatistics(RkInfo query) {
|
||||
return rkInfoMapper.selectStatistics(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long selectPcde(RkInfo query) {
|
||||
return rkInfoMapper.selectPcde(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateBillInfo(RkInfo query) {
|
||||
return rkInfoMapper.updateBillInfo(query);
|
||||
|
||||
@@ -5,10 +5,13 @@ import com.zg.common.exception.ServiceException;
|
||||
import com.zg.common.utils.DateUtils;
|
||||
import com.zg.common.utils.StringUtils;
|
||||
import com.zg.common.utils.poi.ExcelUtil;
|
||||
import com.zg.project.wisdom.domain.dto.RkInfoQueryDTO;
|
||||
import com.zg.project.wisdom.domain.vo.*;
|
||||
import com.zg.project.wisdom.mapper.GysJhMapper;
|
||||
import com.zg.project.wisdom.mapper.RkInfoMapper;
|
||||
import com.zg.project.wisdom.mapper.RkStatisticsMapper;
|
||||
import com.zg.project.wisdom.service.RkStatisticsService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@@ -23,9 +26,12 @@ import java.util.*;
|
||||
@Service
|
||||
public class RkStatisticsServiceImpl implements RkStatisticsService {
|
||||
|
||||
@Resource
|
||||
@Autowired
|
||||
private RkStatisticsMapper rkStatisticsMapper;
|
||||
|
||||
@Autowired
|
||||
private RkInfoMapper rkInfoMapper;
|
||||
|
||||
|
||||
@Override
|
||||
public List<Map<String, Object>> getAgeStatsAsList() {
|
||||
@@ -426,4 +432,24 @@ public class RkStatisticsServiceImpl implements RkStatisticsService {
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> selectStockStatistics(RkInfoQueryDTO query) {
|
||||
|
||||
if (query.getIsChuku() == null) {
|
||||
query.setIsChuku("0"); // 默认只查在库
|
||||
}
|
||||
|
||||
Map<String, Object> result = rkInfoMapper.selectStockStatistics(query);
|
||||
|
||||
// 处理空值情况,防止前端拿到 null 报错
|
||||
if (result == null) {
|
||||
result = new HashMap<>();
|
||||
}
|
||||
result.putIfAbsent("sumMoney", 0);
|
||||
result.putIfAbsent("sumQty", 0);
|
||||
result.putIfAbsent("pcdeCount", 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@ spring:
|
||||
# 主库数据源
|
||||
master:
|
||||
# url: jdbc:mysql://101.132.133.142:3306/wisdom?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
url: jdbc:mysql://192.168.1.28:3306/wisdom?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
# url: jdbc:mysql://192.168.1.28:3306/wisdom?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
# url: jdbc:mysql://192.168.1.192:3306/wisdom?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
# url: jdbc:mysql://192.168.1.251:3306/wisdom?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
url: jdbc:mysql://192.168.1.251:3306/wisdom?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
# url: jdbc:mysql://localhost:3306/wisdom?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: root
|
||||
password: shzg
|
||||
|
||||
@@ -170,51 +170,3 @@ mock:
|
||||
#配送系统中调用大模型进行图片识别
|
||||
qwen-ocr:
|
||||
base-url: http://192.168.1.253:8087/ocr/extractErpByBase64
|
||||
|
||||
# =========================
|
||||
# MQTT 配置(EMQX 接入)
|
||||
# =========================
|
||||
mqtt:
|
||||
# 是否启用 MQTT 功能
|
||||
# true:系统启动时自动连接 EMQX 并订阅 Topic
|
||||
# false:不初始化 MQTT 客户端
|
||||
enabled: true
|
||||
|
||||
# MQTT Broker 地址
|
||||
# tcp://IP:1883 —— MQTT TCP
|
||||
# ws://IP:8083 —— MQTT WebSocket
|
||||
# ssl://IP:8883 —— MQTT SSL
|
||||
broker: tcp://192.168.1.29:1883
|
||||
|
||||
# MQTT 客户端 ID(在 EMQX 中唯一)
|
||||
# 建议:系统名 + 模块名,避免重复
|
||||
clientId: zg-wms-backend-test
|
||||
|
||||
# MQTT 账号(EMQX Dashboard 中配置)
|
||||
username: demo02
|
||||
|
||||
# MQTT 密码
|
||||
password: admin123
|
||||
|
||||
# 是否清除会话
|
||||
# true :断开后清除订阅和未接收消息(推荐后端使用)
|
||||
# false :保留会话(适合设备端)
|
||||
cleanSession: true
|
||||
|
||||
# 心跳时间(秒)
|
||||
# 客户端与 Broker 保持连接的心跳间隔
|
||||
keepAlive: 30
|
||||
|
||||
# 连接超时时间(秒)
|
||||
timeout: 10
|
||||
|
||||
# 默认消息 QoS
|
||||
# 0:最多一次(不保证到达,性能最好)
|
||||
# 1:至少一次(推荐,业务数据常用)
|
||||
# 2:仅一次(最严格,性能最差)
|
||||
qos: 1
|
||||
|
||||
# 订阅的 Topic 列表(支持通配符)
|
||||
# 建议先使用测试 Topic,确认链路正常后再接入真实业务 Topic
|
||||
topics:
|
||||
- zg/wms/test/#
|
||||
@@ -587,6 +587,160 @@
|
||||
|
||||
</select>
|
||||
|
||||
<select id="selectBillHeaderList" resultMap="RkInfoResult">
|
||||
SELECT
|
||||
-- 3. 外层:关联字典表获取名称
|
||||
a.show_bill_no AS bill_no, -- 最终展示的单据号
|
||||
a.bill_no AS bill_no, -- 原始入库单号(兼容实体)
|
||||
a.bill_no_ck AS bill_no_ck, -- 原始出库单号
|
||||
|
||||
-- 状态与标识
|
||||
a.is_chuku,
|
||||
a.is_delivery,
|
||||
a.id, -- 取聚合后的最小ID作为主键标识
|
||||
|
||||
-- 入库维度的公共字段
|
||||
a.rk_type,
|
||||
si.type_name AS rk_type_name,
|
||||
a.wl_type,
|
||||
mt.type_name AS wl_type_name,
|
||||
a.rk_time,
|
||||
a.lihuo_y,
|
||||
ru.user_name AS lihuo_y_name,
|
||||
|
||||
-- 仓库信息
|
||||
a.cangku,
|
||||
wh.warehouse_name AS cangku_name,
|
||||
wh.parent_warehouse_code AS parent_warehouse_code,
|
||||
wh.parent_warehouse_name AS parent_warehouse_name,
|
||||
wh.warehouse_code AS warehouse_code,
|
||||
wh.warehouse_name AS warehouse_name,
|
||||
|
||||
-- 出库维度的公共字段
|
||||
a.ck_type,
|
||||
so.type_name AS ck_type_name,
|
||||
a.ly_time,
|
||||
a.ck_lihuo_y,
|
||||
u.user_name AS ck_lihuo_y_name, -- 注意:这里对应 XML 里的 u 表别名
|
||||
a.team_code,
|
||||
ct.team_name AS team_name,
|
||||
|
||||
-- 创建时间
|
||||
a.create_time
|
||||
|
||||
FROM (
|
||||
SELECT
|
||||
-- 2. 中间层:按单据号聚合
|
||||
t.show_bill_no,
|
||||
MIN(t.id) AS id,
|
||||
-- 单据头信息聚合(取最大值或最小值均可,因为同一单据号下这些字段是一致的)
|
||||
MAX(t.bill_no) AS bill_no,
|
||||
MAX(t.bill_no_ck) AS bill_no_ck,
|
||||
|
||||
MAX(t.is_chuku) AS is_chuku,
|
||||
MAX(t.is_delivery) AS is_delivery,
|
||||
|
||||
MIN(t.rk_type) AS rk_type,
|
||||
MIN(t.wl_type) AS wl_type,
|
||||
MIN(t.rk_time) AS rk_time,
|
||||
MIN(t.lihuo_y) AS lihuo_y,
|
||||
MIN(t.cangku) AS cangku,
|
||||
|
||||
MIN(t.ck_type) AS ck_type,
|
||||
MIN(t.ly_time) AS ly_time,
|
||||
MIN(t.ck_lihuo_y) AS ck_lihuo_y,
|
||||
MIN(t.team_code) AS team_code,
|
||||
|
||||
MAX(t.create_time) AS create_time
|
||||
FROM (
|
||||
-- 1. 内层:过滤并计算 show_bill_no
|
||||
SELECT
|
||||
ri.id,
|
||||
ri.bill_no,
|
||||
ri.bill_no_ck,
|
||||
ri.rk_type,
|
||||
ri.wl_type,
|
||||
ri.cangku,
|
||||
ri.rk_time,
|
||||
ri.lihuo_y,
|
||||
ri.is_chuku,
|
||||
ri.is_delivery,
|
||||
ri.ck_type,
|
||||
ri.ly_time,
|
||||
ri.ck_lihuo_y,
|
||||
ri.team_code,
|
||||
ri.create_time,
|
||||
-- 计算逻辑:如果是出库状态且有出库单号,则以出库单号为主
|
||||
CASE
|
||||
WHEN ri.is_chuku IN ('1','3') AND ri.bill_no_ck IS NOT NULL AND ri.bill_no_ck != ''
|
||||
THEN ri.bill_no_ck
|
||||
ELSE ri.bill_no
|
||||
END AS show_bill_no
|
||||
FROM rk_info ri
|
||||
<where>
|
||||
AND ri.is_delete = 0
|
||||
|
||||
<!-- 关键字搜索:依然保留对项目号、物料号等的支持,方便用户查找 -->
|
||||
<if test="q.keyword != null and q.keyword != ''">
|
||||
AND (
|
||||
ri.xm_no LIKE concat('%', #{q.keyword}, '%')
|
||||
OR ri.wl_no LIKE concat('%', #{q.keyword}, '%')
|
||||
OR ri.gys_mc LIKE concat('%', #{q.keyword}, '%')
|
||||
)
|
||||
</if>
|
||||
|
||||
<if test="q.isChukuList != null and q.isChukuList.size() > 0">
|
||||
AND ri.is_chuku IN
|
||||
<foreach collection="q.isChukuList" item="s" open="(" separator="," close=")">
|
||||
#{s}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="(q.isChukuList == null or q.isChukuList.size() == 0) and q.isChuku != null and q.isChuku != ''">
|
||||
AND ri.is_chuku = #{q.isChuku}
|
||||
</if>
|
||||
|
||||
<if test="q.ckType != null and q.ckType != ''">
|
||||
AND ri.ck_type = #{q.ckType}
|
||||
</if>
|
||||
<if test="q.cangku != null and q.cangku != ''">
|
||||
AND ri.cangku = #{q.cangku}
|
||||
</if>
|
||||
<if test="q.billNoCk != null and q.billNoCk != ''">
|
||||
AND ri.bill_no_ck = #{q.billNoCk}
|
||||
</if>
|
||||
<if test="q.billNo != null and q.billNo != ''">
|
||||
AND ri.bill_no = #{q.billNo}
|
||||
</if>
|
||||
<if test="q.startTime != null">
|
||||
AND ri.rk_time >= #{q.startTime}
|
||||
</if>
|
||||
<if test="q.endTime != null">
|
||||
AND ri.rk_time <= #{q.endTime}
|
||||
</if>
|
||||
<if test="q.statDate != null">
|
||||
AND ri.ly_time >= #{q.statDate}
|
||||
</if>
|
||||
<if test="q.endDate != null">
|
||||
AND ri.ly_time <= #{q.endDate}
|
||||
</if>
|
||||
</where>
|
||||
) t
|
||||
GROUP BY t.show_bill_no
|
||||
) a
|
||||
|
||||
-- 字典关联
|
||||
LEFT JOIN stock_in_type si ON a.rk_type = si.type_code
|
||||
LEFT JOIN stock_out_type so ON a.ck_type = so.type_code
|
||||
LEFT JOIN warehouse_info wh ON a.cangku = wh.warehouse_code
|
||||
LEFT JOIN sys_user u ON a.ck_lihuo_y = u.user_id -- 出库理货员
|
||||
LEFT JOIN sys_user ru ON a.lihuo_y = ru.user_id -- 入库理货员
|
||||
LEFT JOIN construction_team ct ON a.team_code = ct.team_code
|
||||
LEFT JOIN material_type mt ON a.wl_type = mt.type_code
|
||||
|
||||
-- 排序优化:优先按出库时间排序;若无出库时间(入库单),则按入库时间排序
|
||||
ORDER BY COALESCE(a.ly_time, a.rk_time) DESC, a.id DESC
|
||||
</select>
|
||||
|
||||
<!-- ================== /按单据分组查询 ================== -->
|
||||
|
||||
<select id="selectRkInfoById" parameterType="Long" resultMap="RkInfoResult">
|
||||
@@ -1120,148 +1274,6 @@
|
||||
ORDER BY ri.create_time DESC, ri.id DESC
|
||||
</select>
|
||||
|
||||
|
||||
<select id="selectStatistics" resultType="java.lang.Long" parameterType="java.lang.Object" >
|
||||
SELECT sum(ri.ht_dj * ri.real_qty)
|
||||
FROM rk_info ri
|
||||
<where>
|
||||
(ri.is_delete = '0' OR ri.is_delete = 0 OR ri.is_delete IS NULL)
|
||||
|
||||
<if test="isChuku != null and isChuku != ''">
|
||||
AND ri.is_chuku = #{isChuku}
|
||||
</if>
|
||||
|
||||
<if test="cangku != null and cangku != ''">
|
||||
AND ri.cangku = #{cangku}
|
||||
</if>
|
||||
<if test="rkType != null and rkType != ''">
|
||||
AND ri.rk_type = #{rkType}
|
||||
</if>
|
||||
<if test="startTime != null">
|
||||
AND ri.rk_time <![CDATA[ >= ]]> #{startTime}
|
||||
</if>
|
||||
<if test="endTime != null">
|
||||
AND ri.rk_time <![CDATA[ <= ]]> #{endTime}
|
||||
</if>
|
||||
|
||||
<if test="lyStartTime != null and lyStartTime != ''">
|
||||
AND ri.ly_time <![CDATA[ >= ]]> #{lyStartTime}
|
||||
</if>
|
||||
<if test="lyEndTime != null and lyEndTime != ''">
|
||||
AND ri.ly_time <![CDATA[ <= ]]> #{lyEndTime}
|
||||
</if>
|
||||
|
||||
<if test="xmNo != null and xmNo != ''">
|
||||
AND ri.xm_no LIKE CONCAT('%', #{xmNo}, '%')
|
||||
</if>
|
||||
<if test="xmMs != null and xmMs != ''">
|
||||
AND ri.xm_ms LIKE CONCAT('%', #{xmMs}, '%')
|
||||
</if>
|
||||
<if test="wlNo != null and wlNo != ''">
|
||||
AND ri.wl_no LIKE CONCAT('%', #{wlNo}, '%')
|
||||
</if>
|
||||
<if test="wlMs != null and wlMs != ''">
|
||||
AND ri.wl_ms LIKE CONCAT('%', #{wlMs}, '%')
|
||||
</if>
|
||||
<if test="gysNo != null and gysNo != ''">
|
||||
AND ri.gys_no LIKE CONCAT('%', #{gysNo}, '%')
|
||||
</if>
|
||||
<if test="gysMc != null and gysMc != ''">
|
||||
AND ri.gys_mc LIKE CONCAT('%', #{gysMc}, '%')
|
||||
</if>
|
||||
<if test="sapNo != null and sapNo != ''">
|
||||
AND ri.sap_no LIKE CONCAT('%', #{sapNo}, '%')
|
||||
</if>
|
||||
<if test="billNo != null and billNo != ''">
|
||||
AND ri.bill_no LIKE CONCAT('%', #{billNo}, '%')
|
||||
</if>
|
||||
<if test="billNoCk != null and billNoCk != ''">
|
||||
AND ri.bill_no_ck LIKE CONCAT('%', #{billNoCk}, '%')
|
||||
</if>
|
||||
<if test="ckType != null and ckType != ''">
|
||||
AND ri.ck_type LIKE CONCAT('%', #{ckType}, '%')
|
||||
</if>
|
||||
<if test="pcode != null and pcode != ''">
|
||||
AND ri.pcode LIKE CONCAT('%', #{pcode}, '%')
|
||||
</if>
|
||||
<if test="fycde1 != null and fycde1 != ''">
|
||||
AND ri.fycde_1 LIKE CONCAT('%', #{fycde1}, '%')
|
||||
</if>
|
||||
<if test="fycde2 != null and fycde2 != ''">
|
||||
AND ri.fycde_2 LIKE CONCAT('%', #{fycde2}, '%')
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectPcde" resultType="java.lang.Long" parameterType="java.lang.Object" >
|
||||
SELECT count(distinct pcode)
|
||||
FROM rk_info ri
|
||||
<where>
|
||||
(ri.is_delete = '0' OR ri.is_delete = 0 OR ri.is_delete IS NULL)
|
||||
|
||||
<if test="isChuku != null and isChuku != ''">
|
||||
AND ri.is_chuku = #{isChuku}
|
||||
</if>
|
||||
|
||||
<if test="cangku != null and cangku != ''">
|
||||
AND ri.cangku = #{cangku}
|
||||
</if>
|
||||
|
||||
<if test="startTime != null">
|
||||
AND ri.rk_time <![CDATA[ >= ]]> #{startTime}
|
||||
</if>
|
||||
<if test="endTime != null">
|
||||
AND ri.rk_time <![CDATA[ <= ]]> #{endTime}
|
||||
</if>
|
||||
|
||||
<if test="lyStartTime != null and lyStartTime != ''">
|
||||
AND ri.ly_time <![CDATA[ >= ]]> #{lyStartTime}
|
||||
</if>
|
||||
<if test="lyEndTime != null and lyEndTime != ''">
|
||||
AND ri.ly_time <![CDATA[ <= ]]> #{lyEndTime}
|
||||
</if>
|
||||
|
||||
<if test="xmNo != null and xmNo != ''">
|
||||
AND ri.xm_no LIKE CONCAT('%', #{xmNo}, '%')
|
||||
</if>
|
||||
<if test="xmMs != null and xmMs != ''">
|
||||
AND ri.xm_ms LIKE CONCAT('%', #{xmMs}, '%')
|
||||
</if>
|
||||
<if test="wlNo != null and wlNo != ''">
|
||||
AND ri.wl_no LIKE CONCAT('%', #{wlNo}, '%')
|
||||
</if>
|
||||
<if test="wlMs != null and wlMs != ''">
|
||||
AND ri.wl_ms LIKE CONCAT('%', #{wlMs}, '%')
|
||||
</if>
|
||||
<if test="gysNo != null and gysNo != ''">
|
||||
AND ri.gys_no LIKE CONCAT('%', #{gysNo}, '%')
|
||||
</if>
|
||||
<if test="gysMc != null and gysMc != ''">
|
||||
AND ri.gys_mc LIKE CONCAT('%', #{gysMc}, '%')
|
||||
</if>
|
||||
<if test="sapNo != null and sapNo != ''">
|
||||
AND ri.sap_no LIKE CONCAT('%', #{sapNo}, '%')
|
||||
</if>
|
||||
<if test="billNo != null and billNo != ''">
|
||||
AND ri.bill_no LIKE CONCAT('%', #{billNo}, '%')
|
||||
</if>
|
||||
<if test="billNoCk != null and billNoCk != ''">
|
||||
AND ri.bill_no_ck LIKE CONCAT('%', #{billNoCk}, '%')
|
||||
</if>
|
||||
<if test="ckType != null and ckType != ''">
|
||||
AND ri.ck_type LIKE CONCAT('%', #{ckType}, '%')
|
||||
</if>
|
||||
<if test="pcode != null and pcode != ''">
|
||||
AND ri.pcode LIKE CONCAT('%', #{pcode}, '%')
|
||||
</if>
|
||||
<if test="fycde1 != null and fycde1 != ''">
|
||||
AND ri.fycde_1 LIKE CONCAT('%', #{fycde1}, '%')
|
||||
</if>
|
||||
<if test="fycde2 != null and fycde2 != ''">
|
||||
AND ri.fycde_2 LIKE CONCAT('%', #{fycde2}, '%')
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
<select id="selectDeliveryCkList"
|
||||
parameterType="com.zg.project.wisdom.domain.RkInfo"
|
||||
resultMap="RkInfoResult">
|
||||
@@ -1326,6 +1338,95 @@
|
||||
AND bill_no LIKE CONCAT(#{prefix}, '%')
|
||||
</select>
|
||||
|
||||
<!-- 聚合统计:总金额、总数量、库位数 -->
|
||||
<select id="selectStockStatistics" resultType="java.util.Map">
|
||||
SELECT
|
||||
-- 1. 总金额:合同单价 * 实际入库数量 (处理 null 为 0)
|
||||
COALESCE(SUM(ri.ht_dj * ri.real_qty), 0) AS sumMoney,
|
||||
|
||||
-- 2. 总数量:实际入库数量求和
|
||||
COALESCE(SUM(ri.real_qty), 0) AS sumQty,
|
||||
|
||||
-- 3. 库位数:去重统计 pcode
|
||||
COUNT(DISTINCT ri.pcode) AS pcdeCount
|
||||
|
||||
FROM rk_info ri
|
||||
<where>
|
||||
-- 基础过滤:未删除
|
||||
(ri.is_delete = '0' OR ri.is_delete = 0 OR ri.is_delete IS NULL)
|
||||
|
||||
-- 核心过滤:在库状态 (由Service传参或此处硬编码 '0')
|
||||
<if test="isChuku != null and isChuku != ''">
|
||||
AND ri.is_chuku = #{isChuku}
|
||||
</if>
|
||||
|
||||
<!-- 以下为动态查询条件,直接复用你 selectRkInfoList 的逻辑 -->
|
||||
<if test="cangku != null and cangku != ''">
|
||||
AND ri.cangku = #{cangku}
|
||||
</if>
|
||||
<if test="rkType != null and rkType != ''">
|
||||
AND ri.rk_type = #{rkType}
|
||||
</if>
|
||||
<if test="wlType != null and wlType != ''">
|
||||
AND ri.wl_type = #{wlType}
|
||||
</if>
|
||||
|
||||
<!-- 时间范围 -->
|
||||
<if test="startTime != null">
|
||||
AND ri.rk_time >= #{startTime}
|
||||
</if>
|
||||
<if test="endTime != null">
|
||||
AND ri.rk_time <= #{endTime}
|
||||
</if>
|
||||
|
||||
<!-- 模糊搜索 (复用原来的逻辑,确保结果与列表一致) -->
|
||||
<if test="keyword != null and keyword != ''">
|
||||
AND (
|
||||
ri.xm_no LIKE concat('%', #{keyword}, '%')
|
||||
OR ri.xm_ms LIKE concat('%', #{keyword}, '%')
|
||||
OR ri.wl_no LIKE concat('%', #{keyword}, '%')
|
||||
OR ri.wl_ms LIKE concat('%', #{keyword}, '%')
|
||||
OR ri.gys_no LIKE concat('%', #{keyword}, '%')
|
||||
OR ri.gys_mc LIKE concat('%', #{keyword}, '%')
|
||||
OR ri.sap_no LIKE concat('%', #{keyword}, '%')
|
||||
OR ri.bill_no LIKE concat('%', #{keyword}, '%')
|
||||
OR ri.bill_no_ck LIKE concat('%', #{keyword}, '%')
|
||||
OR ri.ck_type LIKE concat('%', #{keyword}, '%')
|
||||
OR ri.pcode LIKE concat('%', #{keyword}, '%')
|
||||
)
|
||||
</if>
|
||||
|
||||
<!-- 单字段精确/模糊匹配 -->
|
||||
<if test="xmNo != null and xmNo != ''">
|
||||
AND ri.xm_no LIKE CONCAT('%', #{xmNo}, '%')
|
||||
</if>
|
||||
<if test="xmMs != null and xmMs != ''">
|
||||
AND ri.xm_ms LIKE CONCAT('%', #{xmMs}, '%')
|
||||
</if>
|
||||
<if test="wlNo != null and wlNo != ''">
|
||||
AND ri.wl_no LIKE CONCAT('%', #{wlNo}, '%')
|
||||
</if>
|
||||
<if test="wlMs != null and wlMs != ''">
|
||||
AND ri.wl_ms LIKE CONCAT('%', #{wlMs}, '%')
|
||||
</if>
|
||||
<if test="gysNo != null and gysNo != ''">
|
||||
AND ri.gys_no LIKE CONCAT('%', #{gysNo}, '%')
|
||||
</if>
|
||||
<if test="gysMc != null and gysMc != ''">
|
||||
AND ri.gys_mc LIKE CONCAT('%', #{gysMc}, '%')
|
||||
</if>
|
||||
<if test="sapNo != null and sapNo != ''">
|
||||
AND ri.sap_no LIKE CONCAT('%', #{sapNo}, '%')
|
||||
</if>
|
||||
<if test="billNo != null and billNo != ''">
|
||||
AND ri.bill_no LIKE CONCAT('%', #{billNo}, '%')
|
||||
</if>
|
||||
<if test="pcode != null and pcode != ''">
|
||||
AND ri.pcode LIKE CONCAT('%', #{pcode}, '%')
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<update id="updateBillInfo" parameterType="com.zg.project.wisdom.domain.RkInfo">
|
||||
UPDATE rk_info
|
||||
<set>
|
||||
|
||||
Reference in New Issue
Block a user