Compare commits

...

3 Commits

Author SHA1 Message Date
曹鹏飞 9788e08fcf feat(warehouse): 添加大箱二维码一键收货功能字段
- 在WarehouseAddQO中新增bigBoxFastReceipt字段用于控制大箱二维码一键收货功能
- 在WarehouseVO中新增bigBoxFastReceipt字段用于返回大箱二维码一键收货状态
- 在WmsWarehouse实体中新增bigBoxFastReceipt字段用于数据库存储该功能配置
- 为新增字段添加NotNull验证注解确保数据完整性
- 为新增字段添加中文文档注释说明功能用途
2026-03-05 15:47:46 +08:00
曹鹏飞 7ff1ab70b7 fix(h5): 解决物料二维码查询和包装码关联查询问题
- 在H5Controller中添加物料不存在的业务异常检查
- 修复WmsShipmentPackagingCodeMapper.xml中的表别名冲突问题
- 将delivery_item表别名从di改为sdi以避免与dictionary_item表别名冲突
- 确保包装码与配送单关联查询的正确性
2026-03-05 15:44:51 +08:00
曹鹏飞 f13b529f72 拆分出测试环境和开发环境 2026-03-05 15:44:37 +08:00
16 changed files with 1105 additions and 14 deletions

View File

@ -0,0 +1,30 @@
logging:
loki:
url: http://192.168.163.83:3100/loki/api/v1/push
level:
root: info
com:
nflg: trace
alibaba:
cloud:
nacos: debug
org:
springframework: debug
# sa-token配置
sa-token:
# SSO-相关配置
sso-client:
# SSO-Server 用户中心地址
server-url: http://sa-sso-server.com:9000
# LDAP
#spring:
# ldap:
# urls:
# - ldap://192.168.0.2:389
# base: dc=nflg
# username: commpub@nflg
# password: Nflg2019#
management:
otlp:
tracing:
endpoint: http://192.168.163.83:4318/v1/traces

View File

@ -20,10 +20,10 @@ import java.util.List;
@Slf4j
public class DeployDevTest {
private static final String serviceName = "admin-dev";
private static final String serviceName = "admin";
private static final String localPath = System.getProperty("user.dir") + "//target//";
private static final String remotePath = "/mnt/app/wms/" + serviceName + "/";
private static final String jarName = "nflg-wms-admin-1.0.0-SNAPSHOT.jar";
private static final String remotePath = "/mnt/app/wms-dev/" + serviceName + "/";
private static final String jarName = "nflg-wms-" + serviceName + "-1.0.0-SNAPSHOT.jar";
@Test
public void DeployToSit() throws Exception {
@ -34,7 +34,7 @@ public class DeployDevTest {
//处理字体目录
// handleDir(sshUtil, localPath, remotePath, "fonts");
//处理lib目录
handleDir(sshUtil, localPath, remotePath, "lib");
// handleDir(sshUtil, localPath, remotePath, "lib");
//执行脚本启动服务
sshUtil.exec("cd " + remotePath + " && ./restart.sh");
sshUtil.disconnect();

View File

@ -0,0 +1,10 @@
logging:
loki:
url: http://192.168.163.83:3100/loki/api/v1/push
level:
root: info
com:
nflg: debug
alibaba:
cloud:
nacos: debug

View File

@ -0,0 +1,332 @@
package com.nflg.wms.auth;
import cn.hutool.core.util.StrUtil;
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.junit.jupiter.api.Test;
import java.io.*;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class DeployDevTest {
private static final String serviceName = "auth";
private static final String localPath = System.getProperty("user.dir") + "\\target\\";
private static final String remotePath = "/mnt/app/wms-dev/" + serviceName + "/";
private static final String jarName = "nflg-wms-" + serviceName + "-1.0.0-SNAPSHOT.jar";
@Test
public void DeployToSit() throws Exception {
SSHUtil sshUtil = new SSHUtil();
sshUtil.connect("192.168.163.84", 22, "root", "CMP2025nf");
//处理主jar包
handleFile(sshUtil, localPath + jarName, remotePath + jarName);
//处理lib目录
// handleDir(sshUtil, localPath, remotePath, "lib");
//执行脚本启动服务
sshUtil.exec("cd " + remotePath + " && ./restart.sh");
sshUtil.disconnect();
}
private void handleDir(SSHUtil sshUtil, String localPath, String remotePath, String dirName) throws Exception {
printInfo("处理目录:" + dirName);
List<Path> files = getFileList(localPath + "lib");
for (Path file : files) {
handleFile(sshUtil, file.toString(), remotePath + "lib/" + file.getFileName().toString());
}
printInfo("处理目录完成");
}
public List<Path> getFileList(String folderPath) throws IOException {
Path path = Paths.get(folderPath);
if (Files.exists(path) && Files.isDirectory(path)) {
List<Path> fileList = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
for (Path entry : stream) {
fileList.add(entry);
}
}
return fileList;
}
return null;
}
private void handleFile(SSHUtil sshUtil, String localPath, String remotePath) throws Exception {
BasicFileAttributes localFileAttr = Files.readAttributes(Paths.get(localPath), BasicFileAttributes.class);
printInfo("处理文件:{},大小:{}", localPath, getSize(localFileAttr.size()));
if (sshUtil.fileExists(remotePath)) {
if (!StrUtil.equals(getRemoteFileMD5(sshUtil, remotePath), getLocalFileMD5(localPath), true)) {
printError("文件不一致,开始上传");
sshUtil.uploadFile(localPath, remotePath);
} else {
printInfo("文件一致");
}
} else {
printError("文件不存在,开始上传");
sshUtil.uploadFile(localPath, remotePath);
}
printInfo("处理完成");
}
private String getRemoteFileMD5(SSHUtil sshUtil, String remotePath) throws Exception {
String md5 = StrUtil.subPre(sshUtil.execWithReturn("md5sum " + remotePath),32);
printInfo("远程文件MD5为" + md5);
return md5;
}
private String getLocalFileMD5(String localPath) throws Exception {
String md5 = DigestUtils.md5Hex(new FileInputStream(localPath));
printInfo("本地文件MD5为" + md5);
return md5;
}
private String getSize(long size) {
long s = 1024;
if (size < s) {
return size + "B";
}
s = s * 1024;
if (size < s) {
return String.format("%.2f", size / 1.00 / 1024) + "KB";
}
s = s * 1024;
if (size < s) {
return String.format("%.2f", size / 1.00 / 1024 / 1024) + "MB";
}
s = s * 1024;
return String.format("%.2f", size / 1.00 / 1024 / 1024 / 1024) + "GB";
}
private static class SSHUtil {
private Session session;
private ChannelSftp channelSftp;
/**
* 建立SSH连接
*/
public void connect(String host, int port, String userName, String password) throws JSchException {
printInfo("开始连接服务器,ip:{},port:{},userName:{},password:{}", host, port, userName, password);
JSch jsch = new JSch();
session = jsch.getSession(userName, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
printInfo("连接成功");
Channel channel = session.openChannel("sftp");
channel.connect();
channelSftp = (ChannelSftp) channel;
}
/**
* 执行远程命令并返回输出
*/
public void exec(String command) {
printInfo("开始执行命令:{}", command);
if (session == null || !session.isConnected()) {
throw new IllegalStateException("SSH未连接");
}
ChannelExec channel = null;
SshResultCallback callback = new SshResultCallback() {
@Override
public void onOutput(String output) {
printInfo(false, output);
}
@Override
public void onErrorOutput(String errorOutput) {
printError(false, errorOutput);
}
@Override
public void onCompleted(int exitStatus) {
printInfo("输出完毕,退出状态:" + exitStatus);
}
@Override
public void onError(Exception e) {
printError(false, e.getMessage());
}
};
try {
// 创建执行命令的通道
channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(command);
// 获取输入流以读取命令输出
InputStream in = channel.getInputStream();
InputStream err = channel.getExtInputStream();
channel.connect();
// 读取命令输出
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
BufferedReader errReader = new BufferedReader(new InputStreamReader(err));
String line;
while ((line = reader.readLine()) != null) {
callback.onOutput(line);
}
// 读取错误输出
String errLine;
while ((errLine = errReader.readLine()) != null) {
callback.onErrorOutput(errLine);
}
// 获取退出状态
int exitStatus = channel.getExitStatus();
callback.onCompleted(exitStatus);
} catch (JSchException | IOException e) {
callback.onError(e);
} finally {
if (channel != null) {
channel.disconnect();
}
if (session != null) {
session.disconnect();
}
printInfo("执行命令完毕");
}
}
public String execWithReturn(String command) throws Exception {
printInfo("开始执行命令:{}", command);
if (session == null || !session.isConnected()) {
throw new IllegalStateException("SSH未连接");
}
ChannelExec channel = null;
BufferedReader reader = null;
try {
// 创建执行命令的通道
channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(command);
// 获取输入流以读取命令输出
InputStream in = channel.getInputStream();
InputStream err = channel.getExtInputStream();
channel.connect();
reader = new BufferedReader(new InputStreamReader(in));
String data = reader.readLine();
// log.info("执行命令成功,返回数据:" + data);
BufferedReader errReader = new BufferedReader(new InputStreamReader(err));
String errData = errReader.readLine();
// log.info("执行命令失败,返回数据:" + errData);
if (StrUtil.isBlank(errData)) {
return data;
} else {
errReader.close();
throw new Exception("执行命令失败:" + errData);
}
} finally {
if (channel != null) {
channel.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (Exception ignored) {
}
}
printInfo("执行命令完毕");
}
}
/**
* 检查远程文件是否存在
*/
public boolean fileExists(String remotePath) throws SftpException {
try {
channelSftp.stat(remotePath);
return true;
} catch (SftpException e) {
if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
return false;
}
throw e;
}
}
/**
* 上传文件
*/
public void uploadFile(String localPath, String remotePath) throws SftpException {
printInfo("开始上传本地文件{}到远程{}", localPath, remotePath);
channelSftp.put(localPath, remotePath);
printInfo("上传完成");
}
/**
* 关闭连接
*/
public void disconnect() {
if (channelSftp != null) {
channelSftp.disconnect();
}
if (session != null) {
session.disconnect();
}
}
}
public interface SshResultCallback {
void onOutput(String output);
void onErrorOutput(String errorOutput);
void onCompleted(int exitStatus);
void onError(Exception e);
}
private static void printError(String msg) {
if (StrUtil.isNotBlank(msg)) {
System.out.println(red + msg + reset);
}
}
private static void printError(boolean addTime, String msg) {
if (addTime) {
System.out.println(red + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + " " + msg + reset);
} else {
System.out.println(red + msg + reset);
}
}
private static void printInfo(String msg) {
printInfo(true, msg);
}
private static void printInfo(boolean addTime, String msg) {
if (addTime) {
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + " " + msg);
} else {
System.out.println(msg);
}
}
private static void printInfo(String format, Object... args) {
printInfo(true, format, args);
}
private static void printInfo(boolean addTime, String format, Object... args) {
if (addTime) {
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + " " + StrUtil.format(format, args));
} else {
System.out.println(StrUtil.format(format, args));
}
}
public static final String red = "\u001B[31m";
public static final String reset = "\u001B[0m";
}

View File

@ -16,11 +16,9 @@ import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.TimeUnit;
@Slf4j
public class DeployTest {
public class DeploySitTest {
private static final String serviceName = "auth";
private static final String localPath = System.getProperty("user.dir") + "\\target\\";

View File

@ -61,4 +61,10 @@ public class WarehouseAddQO {
*/
@NotNull
private Boolean isDisableLocation;
/**
* 是否使用大箱二维码一键收货
*/
@NotNull
private Boolean bigBoxFastReceipt;
}

View File

@ -72,4 +72,9 @@ public class WarehouseVO extends WarehouseSimpleVO {
* 是否启储位管理
*/
private Boolean isDisableLocation;
/**
* 是否使用大箱二维码一键收货
*/
private Boolean bigBoxFastReceipt;
}

View File

@ -0,0 +1,10 @@
logging:
loki:
url: http://192.168.163.83:3100/loki/api/v1/push
level:
root: info
com:
nflg: debug
alibaba:
cloud:
nacos: warn

View File

@ -0,0 +1,332 @@
package com.nflg.wms.gateway;
import cn.hutool.core.util.StrUtil;
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.junit.jupiter.api.Test;
import java.io.*;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class DeployDevTest {
private static final String serviceName = "gateway";
private static final String localPath = System.getProperty("user.dir") + "\\target\\";
private static final String remotePath = "/mnt/app/wms-dev/" + serviceName + "/";
private static final String jarName = "nflg-wms-" + serviceName + "-1.0.0-SNAPSHOT.jar";
@Test
public void DeployToSit() throws Exception {
SSHUtil sshUtil = new SSHUtil();
sshUtil.connect("192.168.163.84", 22, "root", "CMP2025nf");
//处理主jar包
handleFile(sshUtil, localPath + jarName, remotePath + jarName);
//处理lib目录
// handleDir(sshUtil, localPath, remotePath, "lib");
//执行脚本启动服务
sshUtil.exec("cd " + remotePath + " && ./restart.sh");
sshUtil.disconnect();
}
private void handleDir(SSHUtil sshUtil, String localPath, String remotePath, String dirName) throws Exception {
printInfo("处理目录:" + dirName);
List<Path> files = getFileList(localPath + "lib");
for (Path file : files) {
handleFile(sshUtil, file.toString(), remotePath + "lib/" + file.getFileName().toString());
}
printInfo("处理目录完成");
}
public List<Path> getFileList(String folderPath) throws IOException {
Path path = Paths.get(folderPath);
if (Files.exists(path) && Files.isDirectory(path)) {
List<Path> fileList = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
for (Path entry : stream) {
fileList.add(entry);
}
}
return fileList;
}
return null;
}
private void handleFile(SSHUtil sshUtil, String localPath, String remotePath) throws Exception {
BasicFileAttributes localFileAttr = Files.readAttributes(Paths.get(localPath), BasicFileAttributes.class);
printInfo("处理文件:{},大小:{}", localPath, getSize(localFileAttr.size()));
if (sshUtil.fileExists(remotePath)) {
if (!StrUtil.equals(getRemoteFileMD5(sshUtil, remotePath), getLocalFileMD5(localPath), true)) {
printError("文件不一致,开始上传");
sshUtil.uploadFile(localPath, remotePath);
} else {
printInfo("文件一致");
}
} else {
printError("文件不存在,开始上传");
sshUtil.uploadFile(localPath, remotePath);
}
printInfo("处理完成");
}
private String getRemoteFileMD5(SSHUtil sshUtil, String remotePath) throws Exception {
String md5 = StrUtil.subPre(sshUtil.execWithReturn("md5sum " + remotePath),32);
printInfo("远程文件MD5为" + md5);
return md5;
}
private String getLocalFileMD5(String localPath) throws Exception {
String md5 = DigestUtils.md5Hex(new FileInputStream(localPath));
printInfo("本地文件MD5为" + md5);
return md5;
}
private String getSize(long size) {
long s = 1024;
if (size < s) {
return size + "B";
}
s = s * 1024;
if (size < s) {
return String.format("%.2f", size / 1.00 / 1024) + "KB";
}
s = s * 1024;
if (size < s) {
return String.format("%.2f", size / 1.00 / 1024 / 1024) + "MB";
}
s = s * 1024;
return String.format("%.2f", size / 1.00 / 1024 / 1024 / 1024) + "GB";
}
private static class SSHUtil {
private Session session;
private ChannelSftp channelSftp;
/**
* 建立SSH连接
*/
public void connect(String host, int port, String userName, String password) throws JSchException {
printInfo("开始连接服务器,ip:{},port:{},userName:{},password:{}", host, port, userName, password);
JSch jsch = new JSch();
session = jsch.getSession(userName, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
printInfo("连接成功");
Channel channel = session.openChannel("sftp");
channel.connect();
channelSftp = (ChannelSftp) channel;
}
/**
* 执行远程命令并返回输出
*/
public void exec(String command) {
printInfo("开始执行命令:{}", command);
if (session == null || !session.isConnected()) {
throw new IllegalStateException("SSH未连接");
}
ChannelExec channel = null;
SshResultCallback callback = new SshResultCallback() {
@Override
public void onOutput(String output) {
printInfo(false, output);
}
@Override
public void onErrorOutput(String errorOutput) {
printError(false, errorOutput);
}
@Override
public void onCompleted(int exitStatus) {
printInfo("输出完毕,退出状态:" + exitStatus);
}
@Override
public void onError(Exception e) {
printError(false, e.getMessage());
}
};
try {
// 创建执行命令的通道
channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(command);
// 获取输入流以读取命令输出
InputStream in = channel.getInputStream();
InputStream err = channel.getExtInputStream();
channel.connect();
// 读取命令输出
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
BufferedReader errReader = new BufferedReader(new InputStreamReader(err));
String line;
while ((line = reader.readLine()) != null) {
callback.onOutput(line);
}
// 读取错误输出
String errLine;
while ((errLine = errReader.readLine()) != null) {
callback.onErrorOutput(errLine);
}
// 获取退出状态
int exitStatus = channel.getExitStatus();
callback.onCompleted(exitStatus);
} catch (JSchException | IOException e) {
callback.onError(e);
} finally {
if (channel != null) {
channel.disconnect();
}
if (session != null) {
session.disconnect();
}
printInfo("执行命令完毕");
}
}
public String execWithReturn(String command) throws Exception {
printInfo("开始执行命令:{}", command);
if (session == null || !session.isConnected()) {
throw new IllegalStateException("SSH未连接");
}
ChannelExec channel = null;
BufferedReader reader = null;
try {
// 创建执行命令的通道
channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(command);
// 获取输入流以读取命令输出
InputStream in = channel.getInputStream();
InputStream err = channel.getExtInputStream();
channel.connect();
reader = new BufferedReader(new InputStreamReader(in));
String data = reader.readLine();
// log.info("执行命令成功,返回数据:" + data);
BufferedReader errReader = new BufferedReader(new InputStreamReader(err));
String errData = errReader.readLine();
// log.info("执行命令失败,返回数据:" + errData);
if (StrUtil.isBlank(errData)) {
return data;
} else {
errReader.close();
throw new Exception("执行命令失败:" + errData);
}
} finally {
if (channel != null) {
channel.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (Exception ignored) {
}
}
printInfo("执行命令完毕");
}
}
/**
* 检查远程文件是否存在
*/
public boolean fileExists(String remotePath) throws SftpException {
try {
channelSftp.stat(remotePath);
return true;
} catch (SftpException e) {
if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
return false;
}
throw e;
}
}
/**
* 上传文件
*/
public void uploadFile(String localPath, String remotePath) throws SftpException {
printInfo("开始上传本地文件{}到远程{}", localPath, remotePath);
channelSftp.put(localPath, remotePath);
printInfo("上传完成");
}
/**
* 关闭连接
*/
public void disconnect() {
if (channelSftp != null) {
channelSftp.disconnect();
}
if (session != null) {
session.disconnect();
}
}
}
public interface SshResultCallback {
void onOutput(String output);
void onErrorOutput(String errorOutput);
void onCompleted(int exitStatus);
void onError(Exception e);
}
private static void printError(String msg) {
if (StrUtil.isNotBlank(msg)) {
System.out.println(red + msg + reset);
}
}
private static void printError(boolean addTime, String msg) {
if (addTime) {
System.out.println(red + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + " " + msg + reset);
} else {
System.out.println(red + msg + reset);
}
}
private static void printInfo(String msg) {
printInfo(true, msg);
}
private static void printInfo(boolean addTime, String msg) {
if (addTime) {
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + " " + msg);
} else {
System.out.println(msg);
}
}
private static void printInfo(String format, Object... args) {
printInfo(true, format, args);
}
private static void printInfo(boolean addTime, String format, Object... args) {
if (addTime) {
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + " " + StrUtil.format(format, args));
} else {
System.out.println(StrUtil.format(format, args));
}
}
public static final String red = "\u001B[31m";
public static final String reset = "\u001B[0m";
}

View File

@ -16,11 +16,9 @@ import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.TimeUnit;
@Slf4j
public class DeployTest {
public class DeploySitTest {
private static final String serviceName = "gateway";
private static final String localPath = System.getProperty("user.dir") + "\\target\\";
@ -34,7 +32,7 @@ public class DeployTest {
//处理主jar包
handleFile(sshUtil, localPath + jarName, remotePath + jarName);
//处理lib目录
handleDir(sshUtil, localPath, remotePath, "lib");
// handleDir(sshUtil, localPath, remotePath, "lib");
//执行脚本启动服务
sshUtil.exec("cd " + remotePath + " && ./restart.sh");
sshUtil.disconnect();

View File

@ -110,4 +110,9 @@ public class WmsWarehouse implements Serializable {
* 是否启储位管理
*/
private Boolean isDisableLocation;
/**
* 是否使用大箱二维码一键收货
*/
private Boolean bigBoxFastReceipt;
}

View File

@ -65,8 +65,8 @@
SELECT pc.*,di."name" AS "type_name"
FROM wms_shipment_packaging_code pc
LEFT JOIN dictionary_item di ON pc."type"=di."id"
INNER JOIN wms_shipment_delivery_item di ON di.packaging_code_id=pc."id"
INNER JOIN wms_shipment_delivery d ON di.delivery_id=d."id"
INNER JOIN wms_shipment_delivery_item sdi ON sdi.packaging_code_id=pc."id"
INNER JOIN wms_shipment_delivery d ON sdi.delivery_id=d."id"
where pc.status=3 and d.no=#{code}
</select>

View File

@ -161,6 +161,7 @@ public class H5Controller extends BaseController {
return ApiResult.success(packagingCodeService.getForInstall(packagingCode.getId()));
} else {
ShipmentMaterialCodeQRVO vo = materialCodeItemQrService.getInfoByQRCode(code);
VUtil.trueThrowBusinessError(Objects.isNull(vo)).throwMessage("未找到该物料");
VUtil.trueThrowBusinessError(vo.getStatus() == 5).throwMessage("该物料已安装");
return ApiResult.success(List.of(vo));
}

View File

@ -0,0 +1,30 @@
logging:
loki:
url: http://192.168.163.83:3100/loki/api/v1/push
level:
root: info
com:
nflg: trace
alibaba:
cloud:
nacos: debug
org:
springframework: debug
# sa-token配置
sa-token:
# SSO-相关配置
sso-client:
# SSO-Server 用户中心地址
server-url: http://sa-sso-server.com:9000
# LDAP
#spring:
# ldap:
# urls:
# - ldap://192.168.0.2:389
# base: dc=nflg
# username: commpub@nflg
# password: Nflg2019#
management:
otlp:
tracing:
endpoint: http://192.168.163.83:4318/v1/traces

View File

@ -0,0 +1,334 @@
package com.nflg.wms.shipment;
import cn.hutool.core.util.StrUtil;
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.junit.jupiter.api.Test;
import java.io.*;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class DeployDevTest {
private static final String serviceName = "shipment";
private static final String localPath = System.getProperty("user.dir") + "//target//";
private static final String remotePath = "/mnt/app/wms-dev/" + serviceName + "/";
private static final String jarName = "nflg-wms-" + serviceName + "-1.0.0-SNAPSHOT.jar";
@Test
public void DeployToSit() throws Exception {
SSHUtil sshUtil = new SSHUtil();
sshUtil.connect("192.168.163.84", 22, "root", "CMP2025nf");
//处理主jar包
handleFile(sshUtil, localPath + jarName, remotePath + jarName);
//处理字体目录
// handleDir(sshUtil, localPath, remotePath, "fonts");
//处理lib目录
// handleDir(sshUtil, localPath, remotePath, "lib");
//执行脚本启动服务
sshUtil.exec("cd " + remotePath + " && ./restart.sh");
sshUtil.disconnect();
}
private void handleDir(SSHUtil sshUtil, String localPath, String remotePath, String dirName) throws Exception {
printInfo("处理目录:" + dirName);
List<Path> files = getFileList(localPath + dirName);
for (Path file : files) {
handleFile(sshUtil, file.toString(), remotePath + dirName + "/" + file.getFileName().toString());
}
printInfo("处理目录完成");
}
public List<Path> getFileList(String folderPath) throws IOException {
Path path = Paths.get(folderPath);
if (Files.exists(path) && Files.isDirectory(path)) {
List<Path> fileList = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
for (Path entry : stream) {
fileList.add(entry);
}
}
return fileList;
}
return null;
}
private void handleFile(SSHUtil sshUtil, String localPath, String remotePath) throws Exception {
BasicFileAttributes localFileAttr = Files.readAttributes(Paths.get(localPath), BasicFileAttributes.class);
printInfo("处理文件:{},大小:{}", localPath, getSize(localFileAttr.size()));
if (sshUtil.fileExists(remotePath)) {
if (!StrUtil.equals(getRemoteFileMD5(sshUtil, remotePath), getLocalFileMD5(localPath), true)) {
printError("文件不一致,开始上传");
sshUtil.uploadFile(localPath, remotePath);
} else {
printInfo("文件一致");
}
} else {
printError("文件不存在,开始上传");
sshUtil.uploadFile(localPath, remotePath);
}
printInfo("处理完成");
}
private String getRemoteFileMD5(SSHUtil sshUtil, String remotePath) throws Exception {
String md5 = StrUtil.subPre(sshUtil.execWithReturn("md5sum " + remotePath), 32);
printInfo("远程文件MD5为" + md5);
return md5;
}
private String getLocalFileMD5(String localPath) throws Exception {
String md5 = DigestUtils.md5Hex(new FileInputStream(localPath));
printInfo("本地文件MD5为" + md5);
return md5;
}
private String getSize(long size) {
long s = 1024;
if (size < s) {
return size + "B";
}
s = s * 1024;
if (size < s) {
return String.format("%.2f", size / 1.00 / 1024) + "KB";
}
s = s * 1024;
if (size < s) {
return String.format("%.2f", size / 1.00 / 1024 / 1024) + "MB";
}
s = s * 1024;
return String.format("%.2f", size / 1.00 / 1024 / 1024 / 1024) + "GB";
}
private static class SSHUtil {
private Session session;
private ChannelSftp channelSftp;
/**
* 建立SSH连接
*/
public void connect(String host, int port, String userName, String password) throws JSchException {
printInfo("开始连接服务器,ip:{},port:{},userName:{},password:{}", host, port, userName, password);
JSch jsch = new JSch();
session = jsch.getSession(userName, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
printInfo("连接成功");
Channel channel = session.openChannel("sftp");
channel.connect();
channelSftp = (ChannelSftp) channel;
}
public String execWithReturn(String command) throws Exception {
printInfo("开始执行命令:{}", command);
if (session == null || !session.isConnected()) {
throw new IllegalStateException("SSH未连接");
}
ChannelExec channel = null;
BufferedReader reader = null;
try {
// 创建执行命令的通道
channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(command);
// 获取输入流以读取命令输出
InputStream in = channel.getInputStream();
InputStream err = channel.getExtInputStream();
channel.connect();
reader = new BufferedReader(new InputStreamReader(in));
String data = reader.readLine();
// log.info("执行命令成功,返回数据:" + data);
BufferedReader errReader = new BufferedReader(new InputStreamReader(err));
String errData = errReader.readLine();
// log.info("执行命令失败,返回数据:" + errData);
if (StrUtil.isBlank(errData)) {
return data;
} else {
errReader.close();
throw new Exception("执行命令失败:" + errData);
}
} finally {
if (channel != null) {
channel.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (Exception ignored) {
}
}
printInfo("执行命令完毕");
}
}
/**
* 执行远程命令并返回输出
*/
public void exec(String command) {
printInfo("开始执行命令:{}", command);
if (session == null || !session.isConnected()) {
throw new IllegalStateException("SSH未连接");
}
ChannelExec channel = null;
SshResultCallback callback = new SshResultCallback() {
@Override
public void onOutput(String output) {
printInfo(false, output);
}
@Override
public void onErrorOutput(String errorOutput) {
printError(false, errorOutput);
}
@Override
public void onCompleted(int exitStatus) {
printInfo("输出完毕,退出状态:" + exitStatus);
}
@Override
public void onError(Exception e) {
printError(false, e.getMessage());
}
};
try {
// 创建执行命令的通道
channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(command);
// 获取输入流以读取命令输出
InputStream in = channel.getInputStream();
InputStream err = channel.getExtInputStream();
channel.connect();
// 读取命令输出
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
BufferedReader errReader = new BufferedReader(new InputStreamReader(err));
String line;
while ((line = reader.readLine()) != null) {
callback.onOutput(line);
}
// 读取错误输出
String errLine;
while ((errLine = errReader.readLine()) != null) {
callback.onErrorOutput(errLine);
}
// 获取退出状态
int exitStatus = channel.getExitStatus();
callback.onCompleted(exitStatus);
} catch (JSchException | IOException e) {
callback.onError(e);
} finally {
if (channel != null) {
channel.disconnect();
}
if (session != null) {
session.disconnect();
}
printInfo("执行命令完毕");
}
}
/**
* 检查远程文件是否存在
*/
public boolean fileExists(String remotePath) throws SftpException {
try {
channelSftp.stat(remotePath);
return true;
} catch (SftpException e) {
if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
return false;
}
throw e;
}
}
/**
* 上传文件
*/
public void uploadFile(String localPath, String remotePath) throws SftpException {
printInfo("开始上传本地文件{}到远程{}", localPath, remotePath);
channelSftp.put(localPath, remotePath);
printInfo("上传完成");
}
/**
* 关闭连接
*/
public void disconnect() {
if (channelSftp != null) {
channelSftp.disconnect();
}
if (session != null) {
session.disconnect();
}
}
}
public interface SshResultCallback {
void onOutput(String output);
void onErrorOutput(String errorOutput);
void onCompleted(int exitStatus);
void onError(Exception e);
}
private static void printError(String msg) {
if (StrUtil.isNotBlank(msg)) {
System.out.println(red + msg + reset);
}
}
private static void printError(boolean addTime, String msg) {
if (addTime) {
System.out.println(red + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + " " + msg + reset);
} else {
System.out.println(red + msg + reset);
}
}
private static void printInfo(String msg) {
printInfo(true, msg);
}
private static void printInfo(boolean addTime, String msg) {
if (addTime) {
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + " " + msg);
} else {
System.out.println(msg);
}
}
private static void printInfo(String format, Object... args) {
printInfo(true, format, args);
}
private static void printInfo(boolean addTime, String format, Object... args) {
if (addTime) {
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + " " + StrUtil.format(format, args));
} else {
System.out.println(StrUtil.format(format, args));
}
}
public static final String red = "\u001B[31m";
public static final String reset = "\u001B[0m";
}

View File

@ -18,7 +18,7 @@ import java.util.ArrayList;
import java.util.List;
@Slf4j
public class DeployTest {
public class DeploySitTest {
private static final String serviceName = "shipment";
private static final String localPath = System.getProperty("user.dir") + "//target//";