Переглянути джерело

Merge remote-tracking branch 'origin/dev_20260131_youshen430' into dev_20260131_youshen430

donglang 1 місяць тому
батько
коміт
660ffd2e1c
17 змінених файлів з 181 додано та 104 видалено
  1. 1 1
      pom.xml
  2. 10 3
      sckw-auth/src/main/java/com/sckw/auth/service/impl/AuthServiceImpl.java
  3. 1 1
      sckw-auth/src/main/resources/bootstrap-prod.yml
  4. 7 8
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/FileUploadUtils.java
  5. 24 8
      sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/FileUtils.java
  6. 45 17
      sckw-common/sckw-common-log/src/main/java/com/sckw/log/aspect/LogInfoAspect.java
  7. 1 1
      sckw-modules/sckw-file/src/main/resources/bootstrap.yml
  8. 1 1
      sckw-modules/sckw-message/src/main/java/com/sckw/message/controller/SmsController.java
  9. 2 2
      sckw-modules/sckw-message/src/main/java/com/sckw/message/feign/SmsApiServiceImpl.java
  10. 2 2
      sckw-modules/sckw-message/src/main/java/com/sckw/message/model/bo/SmsBo.java
  11. 8 9
      sckw-modules/sckw-message/src/main/java/com/sckw/message/service/SmsService.java
  12. 2 2
      sckw-modules/sckw-message/src/main/java/com/sckw/message/utils/SmsUtil.java
  13. 2 0
      sckw-modules/sckw-product/src/main/java/com/sckw/product/model/vo/req/AddGoodsParam.java
  14. 47 39
      sckw-modules/sckw-system/src/main/java/com/sckw/system/service/KwsUserService.java
  15. 2 2
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/repository/KwtWaybillOrderRepository.java
  16. 4 4
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/KwtWaybillOrderV1Service.java
  17. 22 4
      sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/TransportStatisticsService.java

+ 1 - 1
pom.xml

@@ -405,7 +405,7 @@
             <id>prod</id>
             <properties>
                 <profiles.active>prod</profiles.active>
-                <nacos.server>172.17.0.4:8848</nacos.server>
+                <nacos.server>nacos-server:8848</nacos.server>
                 <nacos.namespace>sckw-ng-service-platform</nacos.namespace>
             </properties>
         </profile>

+ 10 - 3
sckw-auth/src/main/java/com/sckw/auth/service/impl/AuthServiceImpl.java

@@ -355,6 +355,13 @@ public class AuthServiceImpl implements IAuthService {
         List<LoginResVo1.TabBarItem> tabBar = buildAppTabBar(loginBase, user.getRoleName(),0,loginRes.getEntTypes());
         if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(tabBar)) {
             loginRes.setTabBar(tabBar);
+            if (org.apache.commons.lang3.StringUtils.equals(loginRes.getEntTypes(), "1")  ) {
+                loginRes.setRoleName("供应商管理员");
+            } else if (org.apache.commons.lang3.StringUtils.equals(loginRes.getEntTypes(), "2")) {
+                loginRes.setRoleName("采购商管理员");
+            }else if (org.apache.commons.lang3.StringUtils.equals(loginRes.getEntTypes(), "3")) {
+                loginRes.setRoleName("物流商管理员");
+            }
         }
         applyAppModulePermissions(loginRes, loginBase, user.getRoleName());
         if (user.getSystemType().equals(SystemTypeEnum.MANAGE.getCode())) {
@@ -975,9 +982,9 @@ public class AuthServiceImpl implements IAuthService {
         boolean isLogistics = StringUtils.isNotBlank(roleName) && roleName.contains("物流");
         boolean isFinance = StringUtils.isNotBlank(roleName) && roleName.contains("财务");
         //企业属性 (1供应商,2采购商,34PL物流,43PL物流)
-        boolean isSupplierAdmin = StringUtils.isNotBlank(roleName) && roleName.contains("供应商管理员") && org.apache.commons.lang3.StringUtils.equals(entTypeNames, "1")  ;
-        boolean isLogisticsAdmin = StringUtils.isNotBlank(roleName) && roleName.contains("物流商管理员") && org.apache.commons.lang3.StringUtils.equals(entTypeNames, "3");
-        boolean isPurchaseAdmin = StringUtils.isNotBlank(roleName) && roleName.contains("采购商管理员") && org.apache.commons.lang3.StringUtils.equals(entTypeNames, "2");
+        boolean isSupplierAdmin = StringUtils.isNotBlank(roleName) && roleName.contains("系统管理员") && org.apache.commons.lang3.StringUtils.equals(entTypeNames, "1")  ;
+        boolean isLogisticsAdmin = StringUtils.isNotBlank(roleName) && roleName.contains("系统管理员") && org.apache.commons.lang3.StringUtils.equals(entTypeNames, "3");
+        boolean isPurchaseAdmin = StringUtils.isNotBlank(roleName) && roleName.contains("系统管理员") && org.apache.commons.lang3.StringUtils.equals(entTypeNames, "2");
 
         if (isDoorKeeper) {
             return buildDoorKeeperTabBar();

+ 1 - 1
sckw-auth/src/main/resources/bootstrap-prod.yml

@@ -19,7 +19,7 @@ spring:
         file-extension: yaml
         shared-configs:
           - data-id: sckw-common.yml
-            group: sckw-common
+            group: sckw-ng-common
             refresh: true
         #可以读多个配置文件 需要在同一个命名空间下面可以是不同的组
         extension-configs:

+ 7 - 8
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/FileUploadUtils.java

@@ -5,7 +5,6 @@ import cn.hutool.core.io.file.FileNameUtil;
 import cn.hutool.core.util.StrUtil;
 import com.sckw.core.exception.BusinessException;
 import com.sckw.core.exception.InvalidExtensionException;
-import com.sckw.core.web.constant.CommonConstants;
 import org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException;
 import org.springframework.web.multipart.MultipartFile;
 
@@ -16,7 +15,6 @@ import java.util.Objects;
 
 /**
  * 文件上传工具类
- *
  */
 public class FileUploadUtils {
     /**
@@ -98,13 +96,13 @@ public class FileUploadUtils {
      * @param file             上传的文件
      * @param allowedExtension 上传文件类型
      * @return 返回上传成功的文件名
-     * @throws FileSizeLimitExceededException       如果超出最大大小
-     * @throws IOException                          比如读写文件出错时
+     * @throws FileSizeLimitExceededException 如果超出最大大小
+     * @throws IOException                    比如读写文件出错时
      */
     public static String upload(String baseDir, MultipartFile file, String[] allowedExtension) throws FileSizeLimitExceededException, IOException, InvalidExtensionException {
         int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
         if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
-            throw new BusinessException("文件名超长"+FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
+            throw new BusinessException("文件名超长" + FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
         }
         assertAllowed(file, allowedExtension);
 
@@ -134,8 +132,9 @@ public class FileUploadUtils {
         return desc;
     }
 
-    public static String getPathFileName( String fileName) throws IOException {
-        return CommonConstants.RESOURCE_PREFIX + "/" +  fileName;
+    public static String getPathFileName(String fileName) throws IOException {
+//        return CommonConstants.RESOURCE_PREFIX + "/" +  fileName;
+        return fileName;
     }
 
 
@@ -146,7 +145,7 @@ public class FileUploadUtils {
      * @return 后缀名
      */
     public static String getExtension(MultipartFile file) {
-        String extension =  FileUtil.getSuffix(file.getOriginalFilename());
+        String extension = FileUtil.getSuffix(file.getOriginalFilename());
         if (StringUtils.isEmpty(extension)) {
             extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
         }

+ 24 - 8
sckw-common/sckw-common-core/src/main/java/com/sckw/core/utils/FileUtils.java

@@ -59,6 +59,7 @@ public class FileUtils {
     private static String accessKeyId;
     private static String accessKeySecret;
     private static String bucketName;
+    private static String domain;
     private static FileUtils fileUtils;
 
     @Value("${aliyun.oss.endpoint}")
@@ -73,6 +74,8 @@ public class FileUtils {
     @Value("${aliyun.oss.bucket}")
     public String oss_bucketName;
 
+    @Value("${common.domain}")
+    private String domainUrl;
     private static void defaultOss() {
         if (StringUtils.isBlank(endpoint)) {
             endpoint = DEFAULT_ENDPOINT;
@@ -94,6 +97,7 @@ public class FileUtils {
         accessKeyId = this.oss_accessKeyId;
         accessKeySecret = this.oss_accessKeySecret;
         bucketName = this.oss_bucketName;
+        domain = this.domainUrl;
     }
 
 //    @PostConstruct
@@ -134,13 +138,14 @@ public class FileUtils {
      */
     public static String getOSSAddressPrefix() {
         defaultOss();
-        return StringConstant.HTTPS_STRING
-                + StringConstant.COLON
-                + StringConstant.LEFT_SEPARATORS
-                + bucketName
-                + StringConstant.POINT
-                + endpoint
-                + StringConstant.LEFT_SEPARATOR;
+//        return StringConstant.HTTPS_STRING
+//                + StringConstant.COLON
+//                + StringConstant.LEFT_SEPARATORS
+//                + bucketName
+//                + StringConstant.POINT
+//                + endpoint
+//                + StringConstant.LEFT_SEPARATOR;
+        return domain;
     }
 
     /**
@@ -170,7 +175,18 @@ public class FileUtils {
         if (StrUtil.startWith(replace, "http")) {
             return replace;
         }
-        return stringBuilder.append(getOSSAddressPrefix()).append(replace).toString();
+        String prefix = getOSSAddressPrefix();
+        String path = replace;
+
+        if (prefix.endsWith("/")) {
+            prefix = prefix.substring(0, prefix.length() - 1);
+        }
+        if (path.startsWith("/")) {
+            path = path.substring(1);
+        }
+
+        stringBuilder.append(prefix).append("/").append(path);
+        return stringBuilder.toString();
     }
 
 

+ 45 - 17
sckw-common/sckw-common-log/src/main/java/com/sckw/log/aspect/LogInfoAspect.java

@@ -1,7 +1,8 @@
 package com.sckw.log.aspect;
 
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.alibaba.fastjson2.filter.ValueFilter;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 import lombok.extern.slf4j.Slf4j;
@@ -56,9 +57,37 @@ public class LogInfoAspect {
         return getResult(p);
     }
 
+    // 定义最大字符串长度(例如 10000 字符)
+    private static final int MAX_STR_LEN = 10000;
+
+    // 复用 ValueFilter 实例,避免重复创建
+    private static final ValueFilter TRUNCATE_FILTER = (object, name, value) -> {
+        if (value instanceof String) {
+            String str = (String) value;
+            if (str.length() > MAX_STR_LEN) {
+                return str.substring(0, MAX_STR_LEN) + "...(truncated)";
+            }
+        }
+        return value;
+    };
+
+    /**
+     * 安全序列化对象,截断超大字符串
+     */
+    private String safeToJSONString(Object obj) {
+        if (obj == null) {
+            return null;
+        }
+        try {
+            return JSON.toJSONString(obj, TRUNCATE_FILTER);
+        } catch (Exception e) {
+            // 如果序列化依然失败,返回简单类型信息
+            return "Serialization failed: " + e.getMessage() + " - object type: " + obj.getClass().getSimpleName();
+        }
+    }
+
     private Object getResult(ProceedingJoinPoint p) throws Throwable {
         Object result = null;
-        //开始时间
         Date startTime = new Date();
         String targetName = p.getTarget().getClass().getName();
         String methodName = p.getSignature().getName();
@@ -68,39 +97,39 @@ public class LogInfoAspect {
         List<Object> logArgs = stream
                 .filter(arg -> (!(arg instanceof HttpServletRequest) && !(arg instanceof HttpServletResponse)) && !(arg instanceof MultipartFile))
                 .collect(Collectors.toList());
-        //过滤后序列化无异常
-        String param = JSON.toJSONString(logArgs);
+        // 参数序列化(也可使用安全版本,但通常参数较小)
+        String param = safeToJSONString(logArgs);  // 替换为安全方法
         String exception = "";
         try {
-            //执行结果,返回参数
             result = p.proceed();
         } catch (Throwable e) {
             exception = e.getMessage();
-            //异常抛出
             throw e;
         } finally {
             Date endTime = new Date();
             long time = endTime.getTime() - startTime.getTime();
             Boolean slowRequest = (time > 1500L);
 
+            // 使用 safeToJSONString 替代直接序列化
+            String resultJson = safeToJSONString(result);
             if (exception != null && !exception.isEmpty()) {
                 log.error("\nAPI调用异常 - {}.{} \n调用方 - {} \n参数:{} \n结果:{} \n异常:{} \n耗时:{}ms \n慢请求:{}",
-                        targetName, methodName, callerMethodName, param, JSON.toJSONString(result), exception, time, slowRequest);
+                        targetName, methodName, callerMethodName, param, resultJson, exception, time, slowRequest);
             } else if (slowRequest) {
                 log.warn("\nAPI慢请求 - {}.{} \n调用方 - {} \n参数:{} \n结果:{} \n耗时:{}ms \n慢请求:{}",
-                        targetName, methodName, callerMethodName, param, JSON.toJSONString(result), time, slowRequest);
+                        targetName, methodName, callerMethodName, param, resultJson, time, slowRequest);
             } else {
                 log.info("\nAPI调用成功 - {}.{} \n调用方 - {} \n参数:{} \n结果:{} \n耗时:{}ms",
-                        targetName, methodName, callerMethodName, param, JSON.toJSONString(result), time);
+                        targetName, methodName, callerMethodName, param, resultJson, time);
             }
 
-            // 原始详细日志保留为debug级别
+            // debug 日志同样使用安全序列化
             log.debug("\n接口调用 - {}.{} \n调用方 - {}\nparam={}\nresult={}\nexception={}\n[{}->{}],slowRequest{}=[{}]",
                     targetName,
                     methodName,
                     callerMethodName,
                     param,
-                    JSON.toJSONString(result),
+                    resultJson,
                     exception,
                     DateFormatUtils.format(startTime, TIME_PATTERN),
                     DateFormatUtils.format(endTime, TIME_PATTERN),
@@ -148,17 +177,16 @@ public void doAfterThrowing(JoinPoint point, Throwable e) throws Throwable {
         String targetName = point.getTarget().getClass().getName();
         String methodName = point.getSignature().getName();
         String callerMethodName = getCallerMethodName();
-        //获取用户请求方法的参数并序列化为JSON格式字符串
         StringBuilder params = new StringBuilder();
         if (point.getArgs() != null && point.getArgs().length > 0) {
             for (int i = 0; i < point.getArgs().length; i++) {
-                Object object = point.getArgs()[i];
-                if (!(object instanceof MultipartFile) && !(object instanceof HttpServletResponse) && !(object instanceof HttpServletRequest)) {
-                    params.append(JSONObject.toJSONString(point.getArgs()[i])).append(";");
+                Object arg = point.getArgs()[i];
+                if (!(arg instanceof MultipartFile) && !(arg instanceof HttpServletResponse) && !(arg instanceof HttpServletRequest)) {
+                    // 使用安全序列化
+                    params.append(safeToJSONString(arg)).append(";");
                 }
             }
         }
-
         Date endTime = new Date();
         long time = endTime.getTime() - startTime.getTime();
         log.error("\nSERVICE异常 - {}.{} \n调用方 - {} \n参数:{} \n异常:{} \n耗时:{}ms \n时间:[{}->{}]",

+ 1 - 1
sckw-modules/sckw-file/src/main/resources/bootstrap.yml

@@ -13,5 +13,5 @@ spring:
 
 common:
   profile: /www/wwwroot/resources
-  domain: http://8.156.88.8:9600
+  domain: http://8.156.88.8:9600/
 

+ 1 - 1
sckw-modules/sckw-message/src/main/java/com/sckw/message/controller/SmsController.java

@@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.*;
 
 
 @RestController
-@RequestMapping(value = "/sms")
+@RequestMapping(value = "/kwmSms")
 @RequiredArgsConstructor
 public class SmsController {
 

+ 2 - 2
sckw-modules/sckw-message/src/main/java/com/sckw/message/feign/SmsApiServiceImpl.java

@@ -35,8 +35,8 @@ public class SmsApiServiceImpl implements SmsApiService {
     public BaseResult<Object> sendVerifyCode(SendSmsDto sendSmsDto) {
         try {
             SmsBo smsBo = new SmsBo();
-            smsBo.setMobile(sendSmsDto.getMobile());
-            smsBo.setBizType(sendSmsDto.getBizType());
+            smsBo.setPhone(sendSmsDto.getMobile());
+            smsBo.setType(sendSmsDto.getBizType());
             smsService.sendVerifyCode(smsBo);
         } catch (Exception exception) {
             return BaseResult.failed(HttpStatus.GLOBAL_EXCEPTION_CODE, exception.getMessage());

+ 2 - 2
sckw-modules/sckw-message/src/main/java/com/sckw/message/model/bo/SmsBo.java

@@ -11,10 +11,10 @@ public class SmsBo {
 
     @NotBlank(message = "手机号不能为空")
     @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
-    private String mobile;
+    private String phone;
 
     @NotBlank(message = "模板编码不能为空")
-    private String bizType;
+    private String type;
 
     private String templateCode;
 

+ 8 - 9
sckw-modules/sckw-message/src/main/java/com/sckw/message/service/SmsService.java

@@ -25,7 +25,6 @@ import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Random;
 import java.util.UUID;
 
 @Service
@@ -43,8 +42,8 @@ public class SmsService {
     private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
 
     public void sendVerifyCode(SmsBo param) {
-        String mobile = param.getMobile();
-        String bizType = param.getBizType();
+        String mobile = param.getPhone();
+        String bizType = param.getType();
         String lockKey = String.format(RedisConstant.MESSAGE_SMS_VERIFY_CODE_LOCK_KEY, bizType, mobile);
         if (!RedissonUtils.tryLock(lockKey, 5L, 10L)) {
             throw new BusinessException("操作太频繁,请稍后再试");
@@ -164,7 +163,7 @@ public class SmsService {
     }
 
     public void sendSms(SmsBo param) {
-        String mobile = param.getMobile();
+        String mobile = param.getPhone();
         String templateCode = param.getTemplateCode();
         Map<String, Object> templateParam = param.getTemplateParam();
 
@@ -190,7 +189,7 @@ public class SmsService {
             throw new BusinessException("请勿频繁获取验证码,请60秒后再试");
         }
 
-        KwmSmsRecord record = buildSmsRecord(mobile, templateCode, param.getBizType(), template.getSmsType(), templateParam);
+        KwmSmsRecord record = buildSmsRecord(mobile, templateCode, param.getType(), template.getSmsType(), templateParam);
         record.setTemplateContent(template.getContent());
         record.setSendStatus(3);
 
@@ -312,10 +311,10 @@ public class SmsService {
     }
 
     private String generateVerifyCode() {
-        if (EnvConstant.PROD.equals(env)) {
-            Random random = new Random();
-            return String.format("%06d", random.nextInt(1000000));
-        }
+//        if (EnvConstant.PROD.equals(env)) {
+//            Random random = new Random();
+//            return String.format("%06d", random.nextInt(1000000));
+//        }
         return "123456";
 
     }

+ 2 - 2
sckw-modules/sckw-message/src/main/java/com/sckw/message/utils/SmsUtil.java

@@ -96,11 +96,11 @@ public class SmsUtil {
 
     public static void main(String[] args) throws Exception {
         boolean result = SmsUtil.sendSms(
-                "15884485773",
+                "17076615563",
                 "乐山沙湾盛昶矿石加工",
                 "SMS_506110118",
                 Map.of(
-                        "code", "123456"
+                        "code", "1234"
                 )
         );
 

+ 2 - 0
sckw-modules/sckw-product/src/main/java/com/sckw/product/model/vo/req/AddGoodsParam.java

@@ -1,5 +1,6 @@
 package com.sckw.product.model.vo.req;
 
+import com.alibaba.fastjson2.annotation.JSONField;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.*;
@@ -83,6 +84,7 @@ public class AddGoodsParam {
      * 富文本内容
      */
     @Schema(description = "富文本内容")
+    @JSONField(serialize = false)
     private String content;
 
     /**

+ 47 - 39
sckw-modules/sckw-system/src/main/java/com/sckw/system/service/KwsUserService.java

@@ -245,14 +245,16 @@ public class KwsUserService {
             kwsMenus = kwsMenus.stream().filter(item -> item.getClientType().equals(Global.NUMERICAL_TWO)).collect(Collectors.toList());
 
             //企业属性 (1供应商,2采购商,34PL物流,43PL物流)
-            if (org.apache.commons.lang3.StringUtils.equals("1",reqDto.getEntTypes())){
-                editRoleReqVo.setName("供应商管理员");
-            }else if (org.apache.commons.lang3.StringUtils.equals("2",reqDto.getEntTypes())){
-                editRoleReqVo.setName("采购商管理员");
-            }else if (org.apache.commons.lang3.StringUtils.equals("3",reqDto.getEntTypes())){
-                editRoleReqVo.setName("物流商管理员");
-            }
-           // editRoleReqVo.setName(Global.MANAGE_NAME);
+//            if (org.apache.commons.lang3.StringUtils.equals("1", reqDto.getEntTypes())) {
+//                editRoleReqVo.setName("供应商管理员");
+//            } else if (org.apache.commons.lang3.StringUtils.equals("2", reqDto.getEntTypes())) {
+//                editRoleReqVo.setName("采购商管理员");
+//            } else if (org.apache.commons.lang3.StringUtils.equals("3", reqDto.getEntTypes())) {
+//                editRoleReqVo.setName("物流商管理员");
+//            } else {
+//                editRoleReqVo.setName(Global.MANAGE_NAME);
+//            }
+            editRoleReqVo.setName(Global.MANAGE_NAME);
             editRoleReqVo.setCurrentUnitId(null);
             editRoleReqVo.setMenuIds(String.join(Global.COMMA, kwsMenus.stream().map(KwsMenu::getId).map(String::valueOf).toList()));
             editRoleReqVo.setVisiblePersonal(false);
@@ -870,7 +872,7 @@ public class KwsUserService {
      */
     public UserInfoResVo getUserInfoById(Long userId) {
         log.info("查询用户信息,用户ID: {}", userId);
-        
+
         // 1. 查询用户基本信息
         KwsUser kwsUser = kwsUserRepository.getById(userId);
         if (Objects.isNull(kwsUser) || kwsUser.getDelFlag() != Global.NO) {
@@ -889,7 +891,7 @@ public class KwsUserService {
 
         // 3. 组装返回结果
         String statusDesc = kwsUser.getStatus() != null && kwsUser.getStatus() == Global.YES ? "锁定" : "正常";
-        
+
         return UserInfoResVo.builder()
                 .userId(kwsUser.getId())
                 .photo(kwsUser.getPhoto())
@@ -904,14 +906,14 @@ public class KwsUserService {
     /**
      * 修改密码(叉车APP)
      *
-     * @param userId 用户ID
+     * @param userId      用户ID
      * @param oldPassword 旧密码
      * @param newPassword 新密码
      */
     public void updatePasswordForApp(Long userId, String oldPassword, String newPassword,
                                      String clientType, Integer systemType, String deviceId) {
         log.info("修改密码,用户ID: {}", userId);
-        
+
         // 1. 查询用户信息
         KwsUser kwsUser = checkUserBase(userId);
 
@@ -919,7 +921,7 @@ public class KwsUserService {
         String account = kwsUser.getAccount();
         String currentPwd = kwsUser.getPassword();
         String salt = kwsUser.getSalt();
-        oldPassword =  PasswordUtils.md5(oldPassword);
+        oldPassword = PasswordUtils.md5(oldPassword);
         checkPassword(account, oldPassword, currentPwd, salt);
 
         // 3. 校验新密码是否与旧密码相同
@@ -930,12 +932,13 @@ public class KwsUserService {
         // 4. 修改密码
         updatePwd(newPassword, kwsUser);
         // 5. 清除当前登录用户的token缓存
-        clearCurrentUserToken(deviceId,kwsUser);
+        clearCurrentUserToken(deviceId, kwsUser);
         log.info("密码修改成功,用户ID: {}", userId);
     }
+
     private void clearCurrentUserToken(String deviceId, KwsUser kwsUser) {
         try {
-            if (kwsUser.getId()!= null) {
+            if (kwsUser.getId() != null) {
                 for (ClientTypeEnum clientTypeEnum : ClientTypeEnum.values()) {
                     // 清除当前用户的refreshToken
                     String refreshTokenKey = Global.getFullRefreshTokenKey(clientTypeEnum.getValue(), kwsUser.getId(), deviceId);
@@ -953,13 +956,14 @@ public class KwsUserService {
             log.warn("清除当前用户token缓存失败", e);
         }
     }
+
     /**
      * 用户登录(叉车APP)
      *
-     * @param account 账号
-     * @param password 密码
+     * @param account    账号
+     * @param password   密码
      * @param systemType 系统类型
-     * @param request HTTP请求(用于记录登录日志)
+     * @param request    HTTP请求(用于记录登录日志)
      * @return LoginResVo
      */
     public LoginResVo login(String account, String password, Integer systemType, HttpServletRequest request) {
@@ -967,13 +971,13 @@ public class KwsUserService {
 
         // 1. 查询用户信息
         KwsUser kwsUser = getKwsUser(account, systemType);
-        password= PasswordUtils.md5(password);
+        password = PasswordUtils.md5(password);
         // 3. 校验密码
         checkPassword(account, password, kwsUser.getPassword(), kwsUser.getSalt());
 
         // 4. 查询用户角色
         List<RoleInfoDto> roleInfoList = kwsUserRoleDao.queryRoleList(kwsUser.getId());
-        if (CollUtil.isEmpty(roleInfoList)){
+        if (CollUtil.isEmpty(roleInfoList)) {
             throw new SystemException(HttpStatus.CODE_60603, "该用户没有分配角色");
         }
         List<String> roleNames = Arrays.asList("铲车司机", "门卫");
@@ -1003,12 +1007,12 @@ public class KwsUserService {
 
         // 8. 缓存企业信息
         KwsEnterprise kwsEnterprise = null;
-        if ( kwsUser.getEntId() != null) {
+        if (kwsUser.getEntId() != null) {
             kwsEnterprise = saveEntToCache(kwsUser.getEntId());
         }
 
         // 9. 缓存菜单权限
-        List<KwsMenuResVo> kwsMenuResVos  = saveMenusToCache(kwsUser.getId(), systemType, roleId);
+        List<KwsMenuResVo> kwsMenuResVos = saveMenusToCache(kwsUser.getId(), systemType, roleId);
 
         // 10. 组装返回结果
         LoginResVo result = LoginResVo.builder()
@@ -1038,15 +1042,15 @@ public class KwsUserService {
     /**
      * 切换账号(叉车APP)
      *
-     * @param account 账号
-     * @param password 密码
+     * @param account    账号
+     * @param password   密码
      * @param systemType 系统类型
-     * @param request HTTP请求(可选,用于记录登录日志)
+     * @param request    HTTP请求(可选,用于记录登录日志)
      * @return SwitchAccountResVo
      */
     public SwitchAccountResVo switchAccount(String account, String password, Integer systemType, HttpServletRequest request) {
         log.info("切换账号,账号: {}, 系统类型: {}", account, systemType);
-        
+
         // 1. 查询用户信息
         KwsUser kwsUser = getKwsUser(account, systemType);
 
@@ -1056,7 +1060,7 @@ public class KwsUserService {
 
         // 4. 查询用户角色
         List<RoleInfoDto> roleInfoList = kwsUserRoleDao.queryRoleList(kwsUser.getId());
-        if (CollUtil.isEmpty(roleInfoList)){
+        if (CollUtil.isEmpty(roleInfoList)) {
             throw new SystemException(HttpStatus.CODE_60603, "该用户没有分配角色");
         }
         List<String> roleNames = Arrays.asList("铲车司机", "门卫");
@@ -1088,7 +1092,7 @@ public class KwsUserService {
 
         // 8. 缓存企业信息
         KwsEnterprise kwsEnterprise = null;
-        if ( kwsUser.getEntId() != null) {
+        if (kwsUser.getEntId() != null) {
             kwsEnterprise = saveEntToCache(kwsUser.getEntId());
         }
 
@@ -1141,7 +1145,7 @@ public class KwsUserService {
      */
     public void logout(Long userId) {
         log.info("退出登录,用户ID: {}", userId);
-        
+
         // 1. 校验用户是否存在
         KwsUser kwsUser = kwsUserRepository.getById(userId);
         if (Objects.isNull(kwsUser)) {
@@ -1193,10 +1197,11 @@ public class KwsUserService {
 
     /**
      * 缓存用户登录信息
-     * @param kwsUser 用户信息
+     *
+     * @param kwsUser    用户信息
      * @param systemType 系统类型
      * @param clientType 客户端类型
-     * @param roleId 角色ID
+     * @param roleId     角色ID
      */
     private void saveUserToCache(KwsUser kwsUser, Integer systemType, String clientType, Long roleId) {
         try {
@@ -1233,6 +1238,7 @@ public class KwsUserService {
 
     /**
      * 缓存企业信息
+     *
      * @param entId 企业ID
      */
     private KwsEnterprise saveEntToCache(Long entId) {
@@ -1247,24 +1253,25 @@ public class KwsUserService {
         } catch (Exception e) {
             log.error("缓存企业信息失败,企业ID: {}", entId, e);
         }
-      return null;
+        return null;
     }
 
     /**
      * 缓存菜单权限
-     * @param userId 用户ID
+     *
+     * @param userId     用户ID
      * @param systemType 系统类型
-     * @param roleId 角色ID
+     * @param roleId     角色ID
      */
     private List<KwsMenuResVo> saveMenusToCache(Long userId, Integer systemType, Long roleId) {
-        if (Objects.isNull(roleId)){
+        if (Objects.isNull(roleId)) {
             return List.of();
         }
         try {
             // 使用本地服务查询菜单
             com.sckw.system.model.pojo.FindMenuTreePojo findMenuTreePojo = new com.sckw.system.model.pojo.FindMenuTreePojo();
             findMenuTreePojo.setRoleIds(Collections.singletonList(roleId));
-            
+
             List<KwsMenuResVo> kwsMenuResVos = kwsMenuService.findList(findMenuTreePojo);
             if (CollectionUtils.isEmpty(kwsMenuResVos)) {
                 RedissonUtils.delete(Global.REDIS_SYS_MENU_PREFIX + systemType + Global.COLON + userId);
@@ -1289,15 +1296,16 @@ public class KwsUserService {
 
     /**
      * 保存登录日志
-     * @param userId 用户ID
-     * @param request HTTP请求
+     *
+     * @param userId    用户ID
+     * @param request   HTTP请求
      * @param loginType 登录类型: 1-首次登录, 2-切换账号登录
      */
     public void saveLoginLogs(Long userId, HttpServletRequest request, Integer loginType) {
         try {
             // 获取登录IP
             String loginIp = RequestUtil.getClientIp(request);
-            
+
             // 获取设备信息
             String userAgentStr = request.getHeader("User-Agent");
             String deviceInfo = "";

+ 2 - 2
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/repository/KwtWaybillOrderRepository.java

@@ -250,7 +250,7 @@ public class KwtWaybillOrderRepository extends ServiceImpl<KwtWaybillOrderMapper
      */
     public List<KwtWaybillOrder> queryCompletedWaybillOrders(Integer status) {
         return list(Wrappers.<KwtWaybillOrder>lambdaQuery()
-                .select(KwtWaybillOrder::getId, KwtWaybillOrder::getUpdateTime)
+                .select(KwtWaybillOrder::getId, KwtWaybillOrder::getLOrderId, KwtWaybillOrder::getUpdateTime)
                 .eq(KwtWaybillOrder::getDelFlag, 0)
                 .eq(KwtWaybillOrder::getStatus, status)
                 .orderByDesc(KwtWaybillOrder::getUpdateTime));
@@ -358,4 +358,4 @@ public class KwtWaybillOrderRepository extends ServiceImpl<KwtWaybillOrderMapper
         return page(page,wrapper);
     }
 
-}
+}

+ 4 - 4
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/KwtWaybillOrderV1Service.java

@@ -3472,10 +3472,10 @@ public class KwtWaybillOrderV1Service {
         //氧化钙
         WaybillOrderSaleDto waybillOrderSaleDto2 = waybillOrderV1Dao.saleSum(List.of("003", "0007", "0008", "0009"));
         WaybillOrderSaleVo waybillOrderSaleVo = new WaybillOrderSaleVo();
-        waybillOrderSaleVo.setShsChl(waybillOrderSaleDto.getChl());
-        waybillOrderSaleVo.setShsXsl(waybillOrderSaleDto.getXsl());
-        waybillOrderSaleVo.setYhgChl(waybillOrderSaleDto2.getChl());
-        waybillOrderSaleVo.setYhgXsl(waybillOrderSaleDto2.getXsl());
+        waybillOrderSaleVo.setShsChl(Objects.nonNull(waybillOrderSaleDto) ? waybillOrderSaleDto.getChl() : BigDecimal.ZERO);
+        waybillOrderSaleVo.setShsXsl(Objects.nonNull(waybillOrderSaleDto) ? waybillOrderSaleDto.getXsl() : BigDecimal.ZERO);
+        waybillOrderSaleVo.setYhgChl(Objects.nonNull(waybillOrderSaleDto2) ? waybillOrderSaleDto2.getChl() : BigDecimal.ZERO);
+        waybillOrderSaleVo.setYhgXsl(Objects.nonNull(waybillOrderSaleDto2) ? waybillOrderSaleDto2.getXsl() : BigDecimal.ZERO);
 
         return waybillOrderSaleVo;
     }

+ 22 - 4
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/TransportStatisticsService.java

@@ -15,6 +15,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
+import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
@@ -59,8 +60,8 @@ public class TransportStatisticsService {
 
         log.info("查询顶部运输统计数据,todayStart={}, tomorrowStart={}", todayStart, tomorrowStart);
 
-        List<KwtWaybillOrder> completedWaybillOrders =
-                waybillOrderRepository.queryCompletedWaybillOrders(CarWaybillV1Enum.COMPLETED.getCode());
+        List<KwtWaybillOrder> completedWaybillOrders = defaultList(
+                waybillOrderRepository.queryCompletedWaybillOrders(CarWaybillV1Enum.COMPLETED.getCode()));
         if (completedWaybillOrders.isEmpty()) {
             log.info("未查询到已完成运单,返回默认零值");
             return buildEmptyStatistics();
@@ -68,11 +69,13 @@ public class TransportStatisticsService {
 
         // 提取已完成运单的ID列表,用于查询关联的子任务数据
         List<Long> waybillOrderIds = completedWaybillOrders.stream()
+                .filter(Objects::nonNull)
                 .map(KwtWaybillOrder::getId)
                 .filter(Objects::nonNull)
                 .toList();
         // 提取已完成运单关联的物流订单ID,用于查询计费方式
         List<Long> logisticsOrderIds = completedWaybillOrders.stream()
+                .filter(Objects::nonNull)
                 .map(KwtWaybillOrder::getLOrderId)
                 .filter(Objects::nonNull)
                 .distinct()
@@ -80,22 +83,28 @@ public class TransportStatisticsService {
         log.debug("提取到 {} 个唯一的物流订单ID", logisticsOrderIds.size());
 
         // 批量查询物流订单信息
-        List<KwtLogisticsOrder> logisticsOrders = logisticsOrderRepository.queryByLogisticsOrderIds(logisticsOrderIds);
+        List<KwtLogisticsOrder> logisticsOrders = logisticsOrderIds.isEmpty()
+                ? Collections.emptyList()
+                : defaultList(logisticsOrderRepository.queryByLogisticsOrderIds(logisticsOrderIds));
         log.debug("查询到 {} 条物流订单记录", logisticsOrders.size());
 
         // 构建物流订单ID到计费方式的映射关系
         Map<Long, String> billingModeMap = logisticsOrders.stream()
+                .filter(Objects::nonNull)
                 .filter(logisticsOrder -> Objects.nonNull(logisticsOrder.getId()))
                 .collect(Collectors.toMap(KwtLogisticsOrder::getId, KwtLogisticsOrder::getBillingMode, (left, right) -> left));
         log.debug("构建计费方式映射完成,共 {} 条记录", billingModeMap.size());
 
         // 根据运单ID列表批量查询子任务信息,用于后续统计净重
-        List<KwtWaybillOrderSubtask> subtasks = waybillOrderSubtaskRepository.queryByWOrderIds(waybillOrderIds);
+        List<KwtWaybillOrderSubtask> subtasks = waybillOrderIds.isEmpty()
+                ? Collections.emptyList()
+                : defaultList(waybillOrderSubtaskRepository.queryByWOrderIds(waybillOrderIds));
 
         // 先按运单维度汇总净重,后续累计和今日统计都直接复用,避免重复遍历明细数据。
         // 其中净重按物流订单计费方式动态取值:
         // billingMode=1 取装货量,billingMode=2 取卸货量,其它情况默认按卸货量处理。
         Map<Long, BigDecimal> transportAmountMap = subtasks.stream()
+                .filter(Objects::nonNull)
                 .filter(subtask -> Objects.nonNull(subtask.getWOrderId()))
                 .collect(Collectors.groupingBy(
                         KwtWaybillOrderSubtask::getWOrderId,
@@ -107,12 +116,14 @@ public class TransportStatisticsService {
 
         // 计算累计运量:遍历所有已完成运单,从预计算的运量映射中获取各运单净重并累加
         BigDecimal totalTransportAmount = completedWaybillOrders.stream()
+                .filter(Objects::nonNull)
                 .map(KwtWaybillOrder::getId)
                 .map(id -> transportAmountMap.getOrDefault(id, BigDecimal.ZERO))
                 .reduce(BigDecimal.ZERO, BigDecimal::add);
 
         // 筛选今日完成的运单:根据运单更新时间判断是否落在当天时间范围内
         List<KwtWaybillOrder> todayCompletedWaybillOrders = completedWaybillOrders.stream()
+                .filter(Objects::nonNull)
                 .filter(waybillOrder -> isBetween(waybillOrder.getUpdateTime(), todayStart, tomorrowStart))
                 .toList();
 
@@ -143,6 +154,10 @@ public class TransportStatisticsService {
                 .build();
     }
 
+    private <T> List<T> defaultList(List<T> list) {
+        return list == null ? Collections.emptyList() : list;
+    }
+
     private BigDecimal defaultAmount(BigDecimal amount) {
         return amount == null ? BigDecimal.ZERO : amount;
     }
@@ -155,6 +170,9 @@ public class TransportStatisticsService {
      * @return 当前子单应参与统计的净重
      */
     private BigDecimal resolveTransportAmount(KwtWaybillOrderSubtask subtask, String billingMode) {
+        if (billingMode == null) {
+            return BigDecimal.ZERO;
+        }
         if (DictEnum.CHARGING_TYPE_1.getValue().equals(billingMode)) {
             return defaultAmount(subtask.getLoadAmount());
         }