Compare commits
12 Commits
2025-11
...
647afd9fc9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
647afd9fc9 | ||
| 4c477ae22a | |||
|
|
5708afb816 | ||
|
|
cd33151920 | ||
|
|
0e0b753126 | ||
|
|
61ee760f52 | ||
|
|
03d1db3bb4 | ||
|
|
6334681dc5 | ||
|
|
211b727b47 | ||
|
|
389857ac7e | ||
|
|
dde3f11bbe | ||
|
|
ff90f51cf1 |
@@ -8,7 +8,19 @@
|
|||||||
"Bash(iconv:*)",
|
"Bash(iconv:*)",
|
||||||
"Bash(powershell:*)",
|
"Bash(powershell:*)",
|
||||||
"Bash(del:*)",
|
"Bash(del:*)",
|
||||||
"Bash(git -C \"c:\\code\\gitea\\NPQS-9100\\pqs-9100_client\" log -1 --oneline)"
|
"Bash(git -C \"c:\\code\\gitea\\NPQS-9100\\pqs-9100_client\" log -1 --oneline)",
|
||||||
|
"Bash(npm run icon:*)",
|
||||||
|
"Bash(node:*)",
|
||||||
|
"Bash(xxd:*)",
|
||||||
|
"Bash(awk:*)",
|
||||||
|
"Bash(md5sum:*)",
|
||||||
|
"Bash(if exist \"out\" rd /s /q \"out\")",
|
||||||
|
"Bash(findstr:*)",
|
||||||
|
"Read(//c/code/gitea/NPQS-9100/pqs-9100_tool_client/cmd/**)",
|
||||||
|
"Bash(copy:*)",
|
||||||
|
"Bash(npm run build-w:*)",
|
||||||
|
"Read(//c/code/gitea/NPQS-9100/pqs-9100_tool_client/**)",
|
||||||
|
"Bash(npm install:*)"
|
||||||
],
|
],
|
||||||
"deny": [],
|
"deny": [],
|
||||||
"ask": []
|
"ask": []
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
server:
|
server:
|
||||||
port: 18092
|
port: 18093
|
||||||
spring:
|
spring:
|
||||||
application:
|
application:
|
||||||
name: entrance
|
name: entrance
|
||||||
@@ -51,7 +51,7 @@ socket:
|
|||||||
port: 61000
|
port: 61000
|
||||||
|
|
||||||
webSocket:
|
webSocket:
|
||||||
port: 7777
|
port: 7778
|
||||||
|
|
||||||
#源参数下发,暂态数据默认值
|
#源参数下发,暂态数据默认值
|
||||||
Dip:
|
Dip:
|
||||||
|
|||||||
BIN
build/extraResources/templates/比对检测报告/V1.0.0/base-template.docx
Normal file
BIN
build/extraResources/templates/比对检测报告/V1.0.0/data-template.docx
Normal file
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 930 B |
|
Before Width: | Height: | Size: 87 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 254 KiB |
|
Before Width: | Height: | Size: 7.1 KiB |
BIN
build/icons/favicon.ico
Normal file
|
After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 87 KiB |
BIN
build/icons/icon-reference.ico
Normal file
|
After Width: | Height: | Size: 256 KiB |
|
Before Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 368 KiB |
|
Before Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 26 KiB |
@@ -1,81 +0,0 @@
|
|||||||
@echo off
|
|
||||||
chcp 65001 >nul
|
|
||||||
title 检查并清除 MySQL9100 服务
|
|
||||||
color 0E
|
|
||||||
|
|
||||||
echo ========================================
|
|
||||||
echo 检查并清除 MySQL9100 服务
|
|
||||||
echo ========================================
|
|
||||||
echo.
|
|
||||||
|
|
||||||
REM 检查是否有管理员权限
|
|
||||||
net session >nul 2>&1
|
|
||||||
if %errorlevel% neq 0 (
|
|
||||||
echo [错误] 需要管理员权限来操作 Windows 服务
|
|
||||||
echo.
|
|
||||||
echo 请右键点击此脚本,选择"以管理员身份运行"
|
|
||||||
echo.
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
echo [✓] 已具有管理员权限
|
|
||||||
echo.
|
|
||||||
|
|
||||||
REM 检查服务是否存在
|
|
||||||
echo [1/4] 检查 mysql9100 服务是否存在...
|
|
||||||
sc query mysql9100 >nul 2>&1
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo [✓] 发现 mysql9100 服务
|
|
||||||
echo.
|
|
||||||
|
|
||||||
REM 显示服务状态
|
|
||||||
echo [2/4] 服务状态信息:
|
|
||||||
sc query mysql9100
|
|
||||||
echo.
|
|
||||||
|
|
||||||
REM 停止服务
|
|
||||||
echo [3/4] 正在停止 mysql9100 服务...
|
|
||||||
sc stop mysql9100 >nul 2>&1
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo [✓] 服务已停止
|
|
||||||
) else (
|
|
||||||
echo [!] 服务可能已经停止或停止失败(继续删除)
|
|
||||||
)
|
|
||||||
|
|
||||||
REM 等待服务完全停止
|
|
||||||
timeout /t 2 /nobreak >nul
|
|
||||||
echo.
|
|
||||||
|
|
||||||
REM 删除服务
|
|
||||||
echo [4/4] 正在删除 mysql9100 服务...
|
|
||||||
sc delete mysql9100
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo [✓] 服务已成功删除
|
|
||||||
echo.
|
|
||||||
echo ========================================
|
|
||||||
echo 清除完成!
|
|
||||||
echo ========================================
|
|
||||||
) else (
|
|
||||||
echo [✗] 删除服务失败
|
|
||||||
echo.
|
|
||||||
echo 可能的原因:
|
|
||||||
echo 1. 服务仍在运行中(请重启电脑后重试)
|
|
||||||
echo 2. 权限不足
|
|
||||||
echo 3. 服务被其他程序锁定
|
|
||||||
echo.
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
) else (
|
|
||||||
echo [!] 未发现 mysql9100 服务
|
|
||||||
echo.
|
|
||||||
echo 系统中没有名为 mysql9100 的服务,无需清除。
|
|
||||||
)
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo 提示:如果需要完全清理,还可以:
|
|
||||||
echo 1. 删除 MySQL 数据目录(mysql/data)
|
|
||||||
echo 2. 删除 MySQL 配置文件(mysql/my.ini)
|
|
||||||
echo.
|
|
||||||
pause
|
|
||||||
20
build/upgrade/README.txt
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# 升级包放置目录
|
||||||
|
|
||||||
|
## 使用方法
|
||||||
|
|
||||||
|
1. 将升级文件放入此目录:
|
||||||
|
- app.asar (前端升级包 - 文件)
|
||||||
|
- app.asar.unpacked/ (前端升级包 - 文件夹)
|
||||||
|
- entrance.jar (后端升级包)
|
||||||
|
|
||||||
|
2. 双击运行根目录的 upgrade.bat 脚本
|
||||||
|
|
||||||
|
3. 升级完成后重启应用
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
- 可以只放前端或只放后端,支持单独升级
|
||||||
|
- 升级前会自动备份到 backup/ 目录
|
||||||
|
- 如果升级失败,运行 rollback.bat 可回滚
|
||||||
|
|
||||||
|
详细说明请参考:README-升级回滚.txt
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
"directories": {
|
"directories": {
|
||||||
"output": "out"
|
"output": "out"
|
||||||
},
|
},
|
||||||
|
"npmRebuild": false,
|
||||||
"asar": true,
|
"asar": true,
|
||||||
"asarUnpack": [
|
"asarUnpack": [
|
||||||
"public/images/**/*"
|
"public/images/**/*"
|
||||||
@@ -21,23 +22,19 @@
|
|||||||
"!python/"
|
"!python/"
|
||||||
],
|
],
|
||||||
"extraResources": [
|
"extraResources": [
|
||||||
{
|
|
||||||
"from": "build/extraResources/dll",
|
|
||||||
"to": "extraResources/dll",
|
|
||||||
"filter": ["**/*"]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"from": "build/extraResources/java",
|
"from": "build/extraResources/java",
|
||||||
"to": "extraResources/java",
|
"to": "extraResources/java",
|
||||||
"filter": ["**/*"]
|
"filter": ["**/*"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"from": "build/extraResources/read.txt",
|
"from": "build/extraResources/templates",
|
||||||
"to": "extraResources/read.txt"
|
"to": "extraResources/templates",
|
||||||
|
"filter": ["**/*"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"from": "build/extraResources/使用说明.txt",
|
"from": "build/extraResources/read.txt",
|
||||||
"to": "extraResources/使用说明.txt"
|
"to": "extraResources/read.txt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"from": "scripts/",
|
"from": "scripts/",
|
||||||
@@ -57,12 +54,9 @@
|
|||||||
"filter": ["**/*"]
|
"filter": ["**/*"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"from": "build/NPQS9100.bat",
|
"from": "build/upgrade",
|
||||||
"to": "NPQS9100.bat"
|
"to": "upgrade",
|
||||||
},
|
"filter": ["**/*"]
|
||||||
{
|
|
||||||
"from": "build/extraResources/使用说明.txt",
|
|
||||||
"to": "使用说明.txt"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"from": "build/upgrade.bat",
|
"from": "build/upgrade.bat",
|
||||||
@@ -78,7 +72,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"win": {
|
"win": {
|
||||||
"icon": "public/images/icon.png",
|
"icon": "build/icons/icon.ico",
|
||||||
"requestedExecutionLevel": "requireAdministrator",
|
"requestedExecutionLevel": "requireAdministrator",
|
||||||
"signAndEditExecutable": false,
|
"signAndEditExecutable": false,
|
||||||
"verifyUpdateCodeSignature": false,
|
"verifyUpdateCodeSignature": false,
|
||||||
@@ -90,5 +84,16 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"nsis": {
|
||||||
|
"oneClick": false,
|
||||||
|
"allowElevation": true,
|
||||||
|
"allowToChangeInstallationDirectory": true,
|
||||||
|
"installerIcon": "build/icons/icon.ico",
|
||||||
|
"uninstallerIcon": "build/icons/icon.ico",
|
||||||
|
"installerHeaderIcon": "build/icons/icon.ico",
|
||||||
|
"createDesktopShortcut": true,
|
||||||
|
"createStartMenuShortcut": true,
|
||||||
|
"shortcutName": "NPQS9100"
|
||||||
|
},
|
||||||
"compression": "store"
|
"compression": "store"
|
||||||
}
|
}
|
||||||
|
|||||||
65
doc/管理员权限说明.md
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# 管理员权限说明
|
||||||
|
|
||||||
|
> ⚠️ **文档已过期** - 本文档描述的是旧版服务模式,自 2025-12-01 起已改用**进程模式(绿色包)**。
|
||||||
|
>
|
||||||
|
> 🎉 **新版本不再需要管理员权限!**
|
||||||
|
>
|
||||||
|
> 参考最新文档:`MySQL进程模式改造方案.md` 和 `NPQS-9100绿色包完整指南.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ~~🔐 为什么需要管理员权限?~~(已废弃)
|
||||||
|
|
||||||
|
~~NPQS9100 需要管理 MySQL Windows 服务,执行以下操作:~~
|
||||||
|
- ~~✅ 安装 MySQL 服务 (`mysql9100`)~~
|
||||||
|
- ~~✅ 启动/停止服务~~
|
||||||
|
- ~~✅ 删除服务(重新安装时)~~
|
||||||
|
|
||||||
|
~~这些操作都需要 **Windows 管理员权限**。~~
|
||||||
|
|
||||||
|
**现状**:已改用进程模式,直接启动 `mysqld.exe` 进程,无需注册 Windows 服务,**完全不需要管理员权限**。
|
||||||
|
|
||||||
|
## 🎉 新版启动方式(进程模式)
|
||||||
|
|
||||||
|
**当前版本启动非常简单**:
|
||||||
|
|
||||||
|
1. ✅ 双击 `NPQS9100.exe` 即可启动
|
||||||
|
2. ✅ 无需管理员权限
|
||||||
|
3. ✅ 无 UAC 弹窗
|
||||||
|
4. ✅ 解压即用,完全绿色
|
||||||
|
|
||||||
|
**MySQL 和 Spring Boot 会在应用启动时自动启动,退出时自动清理。**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ~~以下内容已废弃(保留作为历史参考)~~
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>点击展开查看旧版(服务模式)说明</summary>
|
||||||
|
|
||||||
|
### ~~两种启动方式(已废弃)~~
|
||||||
|
|
||||||
|
#### ~~方式 1:使用启动器(推荐)~~
|
||||||
|
|
||||||
|
~~打包后的目录中有一个 `NPQS9100-启动器.bat` 文件。~~
|
||||||
|
|
||||||
|
#### ~~方式 2:手动以管理员身份运行~~
|
||||||
|
|
||||||
|
~~右键点击 `NPQS9100.exe` 选择"以管理员身份运行"~~
|
||||||
|
|
||||||
|
### ~~常见问题(已废弃)~~
|
||||||
|
|
||||||
|
~~Q: MySQL 服务安装后还需要管理员权限吗?~~
|
||||||
|
A: **新版本不使用 Windows 服务,因此完全不需要管理员权限。**
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 版本历史
|
||||||
|
|
||||||
|
| 日期 | 版本 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 2025-12-01 | v2.0 | 改用进程模式,无需管理员权限 ✅ |
|
||||||
|
| 2025-10-17 | v1.0 | 服务模式,需要管理员权限(已废弃)|
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ module.exports = () => {
|
|||||||
},
|
},
|
||||||
frame: true,
|
frame: true,
|
||||||
show: false, // 初始不显示,等待服务启动完成后再显示
|
show: false, // 初始不显示,等待服务启动完成后再显示
|
||||||
icon: path.join(getBaseDir(), 'public', 'images', 'icon.png'),
|
icon: path.join(getBaseDir(), 'public', 'images', 'logo-32.png'),
|
||||||
},
|
},
|
||||||
logger: {
|
logger: {
|
||||||
level: 'INFO',
|
level: 'INFO',
|
||||||
|
|||||||
@@ -125,34 +125,34 @@ class Lifecycle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 步骤5: 检测 Java 端口
|
// 步骤5: 检测 Java 端口
|
||||||
this.logWindowManager.addLog('system', '▶ 步骤7: 检测可用的 Java 端口(从18092开始)...');
|
this.logWindowManager.addLog('system', '▶ 步骤7: 检测可用的 Java 端口(从18093开始)...');
|
||||||
this.startupManager.updateProgress('check-java-port', { mysqlPort: this.mysqlPort });
|
this.startupManager.updateProgress('check-java-port', { mysqlPort: this.mysqlPort });
|
||||||
|
|
||||||
this.javaPort = await PortChecker.findAvailablePort(18092, 100);
|
this.javaPort = await PortChecker.findAvailablePort(18093, 100);
|
||||||
|
|
||||||
if (this.javaPort === -1) {
|
if (this.javaPort === -1) {
|
||||||
this.logWindowManager.addLog('error', 'Java 端口检测失败:18092-18191 全部被占用');
|
this.logWindowManager.addLog('error', 'Java 端口检测失败:18093-18192 全部被占用');
|
||||||
throw new Error('无法找到可用的后端服务端口(18092-18191 全部被占用)');
|
throw new Error('无法找到可用的后端服务端口(18093-18192 全部被占用)');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 步骤5.5: 检测 WebSocket 端口
|
// 步骤5.5: 检测 WebSocket 端口
|
||||||
this.logWindowManager.addLog('system', '▶ 步骤8: 检测可用的 WebSocket 端口(从7777开始)...');
|
this.logWindowManager.addLog('system', '▶ 步骤8: 检测可用的 WebSocket 端口(从7778开始)...');
|
||||||
|
|
||||||
this.websocketPort = await PortChecker.findAvailablePort(7777, 100);
|
this.websocketPort = await PortChecker.findAvailablePort(7778, 100);
|
||||||
|
|
||||||
if (this.websocketPort === -1) {
|
if (this.websocketPort === -1) {
|
||||||
this.logWindowManager.addLog('error', 'WebSocket 端口检测失败:7777-7876 全部被占用');
|
this.logWindowManager.addLog('error', 'WebSocket 端口检测失败:7778-7877 全部被占用');
|
||||||
throw new Error('无法找到可用的 WebSocket 端口(7777-7876 全部被占用)');
|
throw new Error('无法找到可用的 WebSocket 端口(7778-7877 全部被占用)');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.javaPort !== 18092) {
|
if (this.javaPort !== 18093) {
|
||||||
this.logWindowManager.addLog('warn', `⚠ Java 默认端口 18092 已被占用,自动切换到端口: ${this.javaPort}`);
|
this.logWindowManager.addLog('warn', `⚠ Java 默认端口 18093 已被占用,自动切换到端口: ${this.javaPort}`);
|
||||||
} else {
|
} else {
|
||||||
this.logWindowManager.addLog('success', `✓ Java 将使用默认端口: ${this.javaPort}`);
|
this.logWindowManager.addLog('success', `✓ Java 将使用默认端口: ${this.javaPort}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.websocketPort !== 7777) {
|
if (this.websocketPort !== 7778) {
|
||||||
this.logWindowManager.addLog('warn', `⚠ WebSocket 默认端口 7777 已被占用,自动切换到端口: ${this.websocketPort}`);
|
this.logWindowManager.addLog('warn', `⚠ WebSocket 默认端口 7778 已被占用,自动切换到端口: ${this.websocketPort}`);
|
||||||
} else {
|
} else {
|
||||||
this.logWindowManager.addLog('success', `✓ WebSocket 将使用默认端口: ${this.websocketPort}`);
|
this.logWindowManager.addLog('success', `✓ WebSocket 将使用默认端口: ${this.websocketPort}`);
|
||||||
}
|
}
|
||||||
@@ -434,8 +434,17 @@ class Lifecycle {
|
|||||||
? path.join(__dirname, '..', 'build', 'extraResources', 'java', 'entrance.jar')
|
? path.join(__dirname, '..', 'build', 'extraResources', 'java', 'entrance.jar')
|
||||||
: path.join(process.resourcesPath, 'extraResources', 'java', 'entrance.jar');
|
: path.join(process.resourcesPath, 'extraResources', 'java', 'entrance.jar');
|
||||||
|
|
||||||
|
// 获取日志路径(与 config-generator.js 中的 dataPath 保持一致)
|
||||||
|
const isDev2 = !process.resourcesPath;
|
||||||
|
const baseDir = isDev2
|
||||||
|
? path.join(__dirname, '..', '..')
|
||||||
|
: path.dirname(process.resourcesPath);
|
||||||
|
const dataPath = path.join(baseDir, 'NPQS9100_Data');
|
||||||
|
const logPath = path.join(dataPath, 'logs');
|
||||||
|
|
||||||
const javaProcess = this.javaRunner.runSpringBoot(jarPath, configPath, {
|
const javaProcess = this.javaRunner.runSpringBoot(jarPath, configPath, {
|
||||||
javaPort: this.javaPort
|
javaPort: this.javaPort,
|
||||||
|
logPath: logPath // 传递日志路径
|
||||||
});
|
});
|
||||||
|
|
||||||
// 监听Java进程输出
|
// 监听Java进程输出
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ VITE_API_URL=/api
|
|||||||
|
|
||||||
#VITE_PROXY=[["/api","http://127.0.0.1:18092/"]]
|
#VITE_PROXY=[["/api","http://127.0.0.1:18092/"]]
|
||||||
#VITE_PROXY=[["/api","http://192.168.1.124:18092/"]]
|
#VITE_PROXY=[["/api","http://192.168.1.124:18092/"]]
|
||||||
VITE_PROXY=[["/api","http://192.168.1.125:18092/"]]
|
VITE_PROXY=[["/api","http://192.168.2.125:18092/"]]
|
||||||
# VITE_PROXY=[["/api","http://192.168.1.138:8080/"]]张文
|
# VITE_PROXY=[["/api","http://192.168.1.138:8080/"]]张文
|
||||||
# 开启激活验证
|
# 开启激活验证
|
||||||
VITE_ACTIVATE_OPEN=true
|
VITE_ACTIVATE_OPEN=false
|
||||||
@@ -23,6 +23,6 @@ VITE_PWA=true
|
|||||||
|
|
||||||
# 线上环境接口地址
|
# 线上环境接口地址
|
||||||
#VITE_API_URL="/api" # 打包时用
|
#VITE_API_URL="/api" # 打包时用
|
||||||
VITE_API_URL="http://127.0.0.1:18092/"
|
VITE_API_URL="http://127.0.0.1:18093/"
|
||||||
# 开启激活验证
|
# 开启激活验证
|
||||||
VITE_ACTIVATE_OPEN=true
|
VITE_ACTIVATE_OPEN=true
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
"dayjs": "^1.11.9",
|
"dayjs": "^1.11.9",
|
||||||
"driver.js": "^1.3.0",
|
"driver.js": "^1.3.0",
|
||||||
"echarts": "^5.4.3",
|
"echarts": "^5.4.3",
|
||||||
|
"echarts-gl": "^2.0.9",
|
||||||
"echarts-liquidfill": "^3.1.0",
|
"echarts-liquidfill": "^3.1.0",
|
||||||
"element-plus": "^2.7.8",
|
"element-plus": "^2.7.8",
|
||||||
"event-source-polyfill": "^1.0.31",
|
"event-source-polyfill": "^1.0.31",
|
||||||
|
|||||||
@@ -83,7 +83,8 @@ export const reCalculate = (params: {
|
|||||||
deviceId: string
|
deviceId: string
|
||||||
code: string
|
code: string
|
||||||
patternId: string,
|
patternId: string,
|
||||||
chnNum: string
|
chnNum?: string,
|
||||||
|
dataRuleId: string
|
||||||
}) => {
|
}) => {
|
||||||
return http.post('/result/reCalculate', params, {loading: true})
|
return http.post('/result/reCalculate', params, {loading: true})
|
||||||
}
|
}
|
||||||
@@ -115,6 +116,7 @@ export const getContrastResult = (params: {
|
|||||||
waveNum: number | null
|
waveNum: number | null
|
||||||
isWave: boolean
|
isWave: boolean
|
||||||
patternId: string
|
patternId: string
|
||||||
|
code: string
|
||||||
}) => {
|
}) => {
|
||||||
return http.post('/result/getContrastResult', params, {loading: true})
|
return http.post('/result/getContrastResult', params, {loading: true})
|
||||||
}
|
}
|
||||||
@@ -130,7 +132,8 @@ export const changeErrorSystem = (params: {
|
|||||||
deviceId: string
|
deviceId: string
|
||||||
code: string
|
code: string
|
||||||
patternId: string,
|
patternId: string,
|
||||||
chnNum: string
|
chnNum?: string,
|
||||||
|
dataRuleId: string
|
||||||
}) => {
|
}) => {
|
||||||
return http.post('/result/changeErrorSystem', params, {loading: true})
|
return http.post('/result/changeErrorSystem', params, {loading: true})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||||
// import echarts from './echarts'
|
// import echarts from './echarts'
|
||||||
import * as echarts from 'echarts' // 全引入
|
import * as echarts from 'echarts' // 全引入
|
||||||
// import 'echarts/lib/component/dataZoom'
|
import 'echarts-gl'
|
||||||
|
import 'echarts-liquidfill'
|
||||||
|
import 'echarts/lib/component/dataZoom'
|
||||||
|
|
||||||
const color = [
|
const color = [
|
||||||
'var(--el-color-primary)',
|
'var(--el-color-primary)',
|
||||||
@@ -39,11 +41,13 @@ const resizeHandler = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
const initChart = () => {
|
const initChart = () => {
|
||||||
|
|
||||||
if (!props.isInterVal && !props.pieInterVal) {
|
if (!props.isInterVal && !props.pieInterVal) {
|
||||||
chart?.dispose()
|
chart?.dispose()
|
||||||
}
|
}
|
||||||
// chart?.dispose()
|
// chart?.dispose()
|
||||||
chart = echarts.init(chartRef.value as HTMLDivElement)
|
chart = echarts.init(chartRef.value as HTMLDivElement)
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
title: {
|
title: {
|
||||||
left: 'center',
|
left: 'center',
|
||||||
|
|||||||
72
frontend/src/utils/echartMethod.ts
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
const dataProcessing = (arr: any[]) => {
|
||||||
|
return arr
|
||||||
|
.filter(item => typeof item === 'number' || (typeof item === 'string' && !isNaN(parseFloat(item))))
|
||||||
|
.map(item => (typeof item === 'number' ? item : parseFloat(item)))
|
||||||
|
}
|
||||||
|
|
||||||
|
const calculateValue = (o: number, value: number, num: number, isMin: boolean) => {
|
||||||
|
if (value === 0) {
|
||||||
|
return 0
|
||||||
|
} else if (value > 0 && Math.abs(value) < 1 && isMin == true) {
|
||||||
|
return 0
|
||||||
|
} else if (value > -1 && value < 0 && isMin == false) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
let base
|
||||||
|
if (Math.abs(o) >= 100) {
|
||||||
|
base = 100
|
||||||
|
} else if (Math.abs(o) >= 10) {
|
||||||
|
base = 10
|
||||||
|
} else if (Math.abs(o) >= 1) {
|
||||||
|
base = 1
|
||||||
|
} else {
|
||||||
|
const multiple = 1 / 0.1
|
||||||
|
|
||||||
|
base = Math.ceil(Math.abs(o) * multiple) / multiple
|
||||||
|
}
|
||||||
|
|
||||||
|
let calculatedValue
|
||||||
|
if (isMin) {
|
||||||
|
if (value < 0) {
|
||||||
|
calculatedValue = value + num * value
|
||||||
|
} else {
|
||||||
|
calculatedValue = value - num * value
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (value < 0) {
|
||||||
|
calculatedValue = value - num * value
|
||||||
|
} else {
|
||||||
|
calculatedValue = value + num * value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (base === 0.1) {
|
||||||
|
return parseFloat(calculatedValue.toFixed(1))
|
||||||
|
} else if (isMin) {
|
||||||
|
return Math.floor(calculatedValue / base) * base
|
||||||
|
} else {
|
||||||
|
return Math.ceil(calculatedValue / base) * base
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理y轴最大最小值
|
||||||
|
export const yMethod = (arr: any) => {
|
||||||
|
const num = 0.2
|
||||||
|
const numList = dataProcessing(arr)
|
||||||
|
let maxValue = 0
|
||||||
|
let minValue = 0
|
||||||
|
let max = 0
|
||||||
|
let min = 0
|
||||||
|
maxValue = Math.max(...numList)
|
||||||
|
minValue = Math.min(...numList)
|
||||||
|
const o = maxValue - minValue == 0 ? maxValue : maxValue - minValue
|
||||||
|
min = calculateValue(o, minValue, num, true)
|
||||||
|
|
||||||
|
max = calculateValue(o, maxValue, num, false)
|
||||||
|
|
||||||
|
return [min, max]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -190,8 +190,8 @@ export default class SocketService {
|
|||||||
* WebSocket连接配置
|
* WebSocket连接配置
|
||||||
*/
|
*/
|
||||||
private config: SocketConfig = {
|
private config: SocketConfig = {
|
||||||
url: 'ws://127.0.0.1:7777/hello',
|
url: 'ws://127.0.0.1:7778/hello',
|
||||||
// url: 'ws://192.168.1.124:7777/hello',
|
//url: 'ws://192.168.1.124:7777/hello',
|
||||||
heartbeatInterval: 9000, // 9秒心跳间隔
|
heartbeatInterval: 9000, // 9秒心跳间隔
|
||||||
reconnectDelay: 5000, // 5秒重连延迟
|
reconnectDelay: 5000, // 5秒重连延迟
|
||||||
maxReconnectAttempts: 5, // 最多重连5次
|
maxReconnectAttempts: 5, // 最多重连5次
|
||||||
|
|||||||
430
frontend/src/views/home/components/compareDataCheckChart.vue
Normal file
@@ -0,0 +1,430 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 历史趋势数据 -->
|
||||||
|
<div class="history_chart">
|
||||||
|
<MyEchart ref="historyChart" :options="echartsData"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
|
||||||
|
import { nextTick, ref, watch } from 'vue'
|
||||||
|
import { yMethod } from '@/utils/echartMethod'
|
||||||
|
import MyEchart from '@/components/echarts/line/index.vue'
|
||||||
|
import { CheckData } from '@/api/check/interface'
|
||||||
|
|
||||||
|
const prop = defineProps({
|
||||||
|
tableData: {
|
||||||
|
type: Array as () => CheckData.TableRow[],
|
||||||
|
default: []
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
const color = [
|
||||||
|
'var(--el-color-primary)',
|
||||||
|
'#07CCCA',
|
||||||
|
'#00BFF5',
|
||||||
|
'#FFBF00',
|
||||||
|
'#77DA63',
|
||||||
|
'#D5FF6B',
|
||||||
|
'#Ff6600',
|
||||||
|
'#FF9100',
|
||||||
|
'#5B6E96',
|
||||||
|
'#66FFCC',
|
||||||
|
'#B3B3B3'
|
||||||
|
]
|
||||||
|
|
||||||
|
const chartsList = ref<any>([])
|
||||||
|
|
||||||
|
const echartsData = ref<any>(null)
|
||||||
|
//初始化趋势图
|
||||||
|
const lineStyle = [{ type: 'solid' }, { type: 'dashed' }, { type: 'dotted' }]
|
||||||
|
|
||||||
|
const setEchart = () => {
|
||||||
|
echartsData.value = {}
|
||||||
|
// y轴单位数组
|
||||||
|
let unitList: any = []
|
||||||
|
|
||||||
|
let groupedData = chartsList.value.reduce((acc: any, item: any) => {
|
||||||
|
let key = ''
|
||||||
|
if (item.phase == null) {
|
||||||
|
key = item.unit
|
||||||
|
} else {
|
||||||
|
key = item.anotherName
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!acc[key]) {
|
||||||
|
acc[key] = []
|
||||||
|
}
|
||||||
|
acc[key].push(item)
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
let result = Object.values(groupedData)
|
||||||
|
if (chartsList.value.length > 0) {
|
||||||
|
unitList = result.map((item: any) => {
|
||||||
|
return item[0].unit
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
echartsData.value = {
|
||||||
|
legend: {
|
||||||
|
itemWidth: 20,
|
||||||
|
itemHeight: 20,
|
||||||
|
itemStyle: { opacity: 0 }, //去圆点
|
||||||
|
type: 'scroll', // 开启滚动分页
|
||||||
|
// orient: 'vertical', // 垂直排列
|
||||||
|
top: 5,
|
||||||
|
right: 70
|
||||||
|
// width: 550,
|
||||||
|
// height: 50
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
top: '30px',
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
axisPointer: {
|
||||||
|
type: 'cross',
|
||||||
|
label: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 16
|
||||||
|
}
|
||||||
|
},
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
fontStyle: 'normal',
|
||||||
|
opacity: 0.35,
|
||||||
|
fontSize: 14
|
||||||
|
},
|
||||||
|
backgroundColor: 'rgba(0,0,0,0.55)',
|
||||||
|
borderWidth: 0,
|
||||||
|
formatter(params: any) {
|
||||||
|
const xname = params[0].value[0]
|
||||||
|
let str = `${xname}<br>`
|
||||||
|
params.forEach((el: any, index: any) => {
|
||||||
|
let marker = ''
|
||||||
|
|
||||||
|
if (el.value[3] == 'dashed') {
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
marker += `<span style="display:inline-block;border: 2px ${el.color} solid;margin-right:5px;width:10px;height:0px;background-color:#ffffff00;"></span>`
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
marker = `<span style="display:inline-block;border: 2px ${el.color} ${el.value[3]};margin-right:5px;width:40px;height:0px;background-color:#ffffff00;"></span>`
|
||||||
|
}
|
||||||
|
let unit = el.value[2] ? el.value[2] : ''
|
||||||
|
// 格式化数值显示为4位小数
|
||||||
|
const value = parseFloat(el.value[1]);
|
||||||
|
const formattedValue = value.toFixed(4);
|
||||||
|
|
||||||
|
str += `${marker}${el.seriesName.split('(')[0]}:${formattedValue}${unit}<br>`
|
||||||
|
})
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
},
|
||||||
|
color: ['#DAA520', '#2E8B57', '#A52a2a', ...color],
|
||||||
|
xAxis: {
|
||||||
|
type: 'time',
|
||||||
|
axisLabel: {
|
||||||
|
formatter: function(value) {
|
||||||
|
const date = new Date(value);
|
||||||
|
const hours = String(date.getHours()).padStart(2, '0');
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||||
|
const seconds = String(date.getSeconds()).padStart(2, '0');
|
||||||
|
return `${hours}:${minutes}:${seconds}`;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
splitNumber: 8
|
||||||
|
},
|
||||||
|
yAxis: [{}],
|
||||||
|
|
||||||
|
options: {
|
||||||
|
series: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (chartsList.value.length > 0) {
|
||||||
|
let yData: any = []
|
||||||
|
echartsData.value.yAxis = []
|
||||||
|
let setList = [...new Set(unitList)]
|
||||||
|
|
||||||
|
setList.forEach((item: any, index: any) => {
|
||||||
|
if (index > 2) {
|
||||||
|
echartsData.value.grid.right = (index - 1) * 80
|
||||||
|
}
|
||||||
|
yData.push([])
|
||||||
|
let right = {
|
||||||
|
position: 'right',
|
||||||
|
offset: (index - 1) * 80
|
||||||
|
}
|
||||||
|
echartsData.value.yAxis.push({
|
||||||
|
name: item,
|
||||||
|
yAxisIndex: index,
|
||||||
|
splitNumber: 5,
|
||||||
|
minInterval: 0,
|
||||||
|
splitLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
// 添加标签格式化,支持小数显示
|
||||||
|
formatter: function(value) {
|
||||||
|
return value.toFixed(5);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
...(index > 0 ? right : null)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
let ABCName = [
|
||||||
|
...new Set(
|
||||||
|
chartsList.value.map((item: any) => {
|
||||||
|
return item.anotherName == '电压负序分量'
|
||||||
|
? '电压不平衡'
|
||||||
|
: item.anotherName == '电压正序分量'
|
||||||
|
? '电压不平衡'
|
||||||
|
: item.anotherName == '电压零序分量'
|
||||||
|
? '电压不平衡'
|
||||||
|
: item.anotherName
|
||||||
|
})
|
||||||
|
)
|
||||||
|
]
|
||||||
|
result.forEach((item: any, index: any) => {
|
||||||
|
let yMethodList: any = []
|
||||||
|
|
||||||
|
let ABCList = Object.values(
|
||||||
|
item.reduce((acc, item) => {
|
||||||
|
let key = ''
|
||||||
|
if (item.phase == null) {
|
||||||
|
key = item.anotherName
|
||||||
|
} else {
|
||||||
|
key = item.phase
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!acc[key]) {
|
||||||
|
acc[key] = []
|
||||||
|
}
|
||||||
|
acc[key].push(item)
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
)
|
||||||
|
|
||||||
|
ABCList.forEach((kk: any) => {
|
||||||
|
let colorName = kk[0].phase?.charAt(0).toUpperCase()
|
||||||
|
let lineS = ABCName.findIndex(
|
||||||
|
item =>
|
||||||
|
item ===
|
||||||
|
(kk[0].anotherName == '电压负序分量'
|
||||||
|
? '电压不平衡'
|
||||||
|
: kk[0].anotherName == '电压正序分量'
|
||||||
|
? '电压不平衡'
|
||||||
|
: kk[0].anotherName == '电压零序分量'
|
||||||
|
? '电压不平衡'
|
||||||
|
: kk[0].anotherName)
|
||||||
|
)
|
||||||
|
let seriesList: any = []
|
||||||
|
kk.forEach((cc: any) => {
|
||||||
|
if (cc.statisticalData !== null) {
|
||||||
|
yData[setList.indexOf(kk[0].unit)].push(cc.statisticalData?.toFixed(4))
|
||||||
|
}
|
||||||
|
|
||||||
|
seriesList.push([cc.time, cc.statisticalData, cc.unit, lineStyle[lineS].type])
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
echartsData.value.options.series.push({
|
||||||
|
name: kk[0].phase ? kk[0].phase + '相' + kk[0].anotherName : kk[0].anotherName,
|
||||||
|
type: 'line',
|
||||||
|
smooth: true,
|
||||||
|
color:
|
||||||
|
colorName == 'A' ? '#DAA520' : colorName == 'B' ? '#2E8B57' : colorName == 'C' ? '#A52a2a' : '',
|
||||||
|
symbol: 'none',
|
||||||
|
data: seriesList,
|
||||||
|
lineStyle: lineStyle[lineS],
|
||||||
|
yAxisIndex: setList.indexOf(kk[0].unit)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// yData.forEach((item: any, index: any) => {
|
||||||
|
// let [min, max] = yMethod(item)
|
||||||
|
// echartsData.value.yAxis[index].min = min
|
||||||
|
// echartsData.value.yAxis[index].max = max
|
||||||
|
// })
|
||||||
|
let allValues: number[] = [];
|
||||||
|
yData.forEach(item => {
|
||||||
|
item.forEach((val: string) => {
|
||||||
|
allValues.push(val);
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 计算全局最大最小值
|
||||||
|
let globalMin = Math.min(...allValues) - 0.0001;
|
||||||
|
let globalMax = Math.max(...allValues) +0.0001
|
||||||
|
|
||||||
|
// 确保最小值不小于0
|
||||||
|
globalMin = Math.max(0, globalMin);
|
||||||
|
|
||||||
|
// 特殊情况:如果所有值都是0
|
||||||
|
if (globalMin === 0 && globalMax === 0) {
|
||||||
|
globalMax = 1;
|
||||||
|
}
|
||||||
|
// 为所有Y轴应用相同的范围
|
||||||
|
yData.forEach((item: any, index: any) => {
|
||||||
|
echartsData.value.yAxis[index].min = globalMin ;
|
||||||
|
echartsData.value.yAxis[index].max = globalMax;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听 tableData 变化并触发 setEchart
|
||||||
|
watch(() => prop.tableData, (newTableData) => {
|
||||||
|
// 处理数据转换
|
||||||
|
const processedData: any[] = []
|
||||||
|
|
||||||
|
newTableData.forEach(item => {
|
||||||
|
// 处理标准设备数据
|
||||||
|
processDeviceData(item, '标准设备', item.uaStdDev, item.ubStdDev, item.ucStdDev, item.utStdDev, item.timeStdDev, item.unit)
|
||||||
|
.forEach(data => processedData.push(data));
|
||||||
|
// 处理被检设备数据
|
||||||
|
processDeviceData(item, '被检设备', item.uaDev, item.ubDev, item.ucDev, item.utDev, item.timeDev, item.unit)
|
||||||
|
.forEach(data => processedData.push(data));
|
||||||
|
});
|
||||||
|
// 更新 chartsList 数据
|
||||||
|
chartsList.value = processedData
|
||||||
|
// 延迟执行确保 DOM 已经渲染
|
||||||
|
nextTick(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
setEchart()
|
||||||
|
}, 100)
|
||||||
|
})
|
||||||
|
}, {
|
||||||
|
immediate: true, // 立即执行一次
|
||||||
|
deep: true // 深度监听
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// 处理单个设备的数据
|
||||||
|
function processDeviceData(
|
||||||
|
item: any,
|
||||||
|
deviceType: string,
|
||||||
|
aValue: number | null,
|
||||||
|
bValue: number | null,
|
||||||
|
cValue: number | null,
|
||||||
|
tValue: number | null,
|
||||||
|
time: string,
|
||||||
|
unit: string
|
||||||
|
): any[] {
|
||||||
|
const result: any[] = [];
|
||||||
|
|
||||||
|
// 判断各相是否存在有效数据
|
||||||
|
const hasA = aValue !== null;
|
||||||
|
const hasB = bValue !== null;
|
||||||
|
const hasC = cValue !== null;
|
||||||
|
const hasT = tValue !== null;
|
||||||
|
|
||||||
|
// 计算有多少相有数据
|
||||||
|
const phaseCount = (hasA ? 1 : 0) + (hasB ? 1 : 0) + (hasC ? 1 : 0);
|
||||||
|
// 时间四舍五入到秒
|
||||||
|
const roundedTime = roundTimeToSecond(time);
|
||||||
|
|
||||||
|
if (hasA) {
|
||||||
|
result.push({
|
||||||
|
anotherName: deviceType,
|
||||||
|
phase: phaseCount > 1 ? 'A' : null,
|
||||||
|
statisticalData: aValue,
|
||||||
|
time: roundedTime,
|
||||||
|
unit: unit,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasB) {
|
||||||
|
result.push({
|
||||||
|
anotherName: deviceType,
|
||||||
|
phase: phaseCount > 1 ? 'B' : null,
|
||||||
|
statisticalData: bValue,
|
||||||
|
time: roundedTime,
|
||||||
|
unit: unit,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasC) {
|
||||||
|
result.push({
|
||||||
|
anotherName: deviceType,
|
||||||
|
phase: phaseCount > 1 ? 'C' : null,
|
||||||
|
statisticalData: cValue,
|
||||||
|
time: roundedTime,
|
||||||
|
unit: unit,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasT) {
|
||||||
|
result.push({
|
||||||
|
anotherName: deviceType,
|
||||||
|
phase: null,
|
||||||
|
statisticalData: tValue,
|
||||||
|
time: roundedTime,
|
||||||
|
unit: unit,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 时间四舍五入到秒的辅助函数
|
||||||
|
function roundTimeToSecond(timeStr: string): string {
|
||||||
|
if (!timeStr) return timeStr;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 直接使用本地时间解析,避免时区转换问题
|
||||||
|
// 替换空格为 T 以符合 ISO 格式
|
||||||
|
const isoString = timeStr.replace(' ', 'T');
|
||||||
|
const date = new Date(isoString);
|
||||||
|
|
||||||
|
// 检查日期是否有效
|
||||||
|
if (isNaN(date.getTime())) {
|
||||||
|
return timeStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取毫秒部分
|
||||||
|
const milliseconds = date.getMilliseconds();
|
||||||
|
|
||||||
|
// 如果毫秒数大于等于500,则加一秒
|
||||||
|
if (milliseconds >= 500) {
|
||||||
|
date.setSeconds(date.getSeconds() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清除毫秒部分
|
||||||
|
date.setMilliseconds(0);
|
||||||
|
|
||||||
|
// 手动格式化为 YYYY-MM-DD HH:mm:ss 格式(使用本地时间)
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
const hours = String(date.getHours()).padStart(2, '0');
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||||
|
const seconds = String(date.getSeconds()).padStart(2, '0');
|
||||||
|
|
||||||
|
const formattedTime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||||
|
|
||||||
|
|
||||||
|
return formattedTime;
|
||||||
|
} catch (error) {
|
||||||
|
// 如果解析失败,返回原始时间字符串
|
||||||
|
console.error('时间解析错误:', error);
|
||||||
|
return timeStr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.history_chart {
|
||||||
|
width: 100%;
|
||||||
|
height: 360px; /* 明确指定高度 */
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 或者设置最小高度 */
|
||||||
|
.history_chart {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 300px; /* 确保有最小高度 */
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -12,14 +12,14 @@
|
|||||||
<el-table-column type="index" label="序号" width="70" fixed="left"/>
|
<el-table-column type="index" label="序号" width="70" fixed="left"/>
|
||||||
|
|
||||||
|
|
||||||
<el-table-column prop="dataA" :label="'标准设备'">
|
<el-table-column :label="'标准设备'">
|
||||||
<el-table-column prop="timeStdDev" label="数据时间" width="200"/>
|
<el-table-column prop="timeStdDev" label="数据时间" width="200"/>
|
||||||
<el-table-column prop="uaStdDev" :label="'A相'+(outerUnit==''?'':'('+outerUnit+')')" v-if="prop.tableData.length==0||prop.tableData[0]?.uaStdDev != null"/>
|
<el-table-column prop="uaStdDev" :label="'A相'+(outerUnit==''?'':'('+outerUnit+')')" v-if="prop.tableData.length==0||prop.tableData[0]?.uaStdDev != null"/>
|
||||||
<el-table-column prop="ubStdDev" :label="setB+(outerUnit==''?'':'('+outerUnit+')')" v-if="prop.tableData.length==0||prop.tableData[0]?.ubStdDev != null"/>
|
<el-table-column prop="ubStdDev" :label="setB+(outerUnit==''?'':'('+outerUnit+')')" v-if="prop.tableData.length==0||prop.tableData[0]?.ubStdDev != null"/>
|
||||||
<el-table-column prop="ucStdDev" :label="'C相'+(outerUnit==''?'':'('+outerUnit+')')" v-if="prop.tableData.length==0||prop.tableData[0]?.ucStdDev != null"/>
|
<el-table-column prop="ucStdDev" :label="'C相'+(outerUnit==''?'':'('+outerUnit+')')" v-if="prop.tableData.length==0||prop.tableData[0]?.ucStdDev != null"/>
|
||||||
<el-table-column prop="utStdDev" :label="setT+(outerUnit==''?'':'('+outerUnit+')')" v-if="prop.tableData[0]?.utStdDev != null"/>
|
<el-table-column prop="utStdDev" :label="setT+(outerUnit==''?'':'('+outerUnit+')')" v-if="prop.tableData[0]?.utStdDev != null"/>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="dataA" :label="'被检设备'">
|
<el-table-column :label="'被检设备'">
|
||||||
<el-table-column prop="timeDev" label="数据时间" width="200"/>
|
<el-table-column prop="timeDev" label="数据时间" width="200"/>
|
||||||
<el-table-column prop="uaDev" :label="'A相'+(outerUnit==''?'':'('+outerUnit+')')" v-if="prop.tableData.length==0||prop.tableData[0]?.uaDev != null"/>
|
<el-table-column prop="uaDev" :label="'A相'+(outerUnit==''?'':'('+outerUnit+')')" v-if="prop.tableData.length==0||prop.tableData[0]?.uaDev != null"/>
|
||||||
<el-table-column prop="ubDev" :label="setB+(outerUnit==''?'':'('+outerUnit+')')" v-if="prop.tableData.length==0||prop.tableData[0]?.ubDev != null"/>
|
<el-table-column prop="ubDev" :label="setB+(outerUnit==''?'':'('+outerUnit+')')" v-if="prop.tableData.length==0||prop.tableData[0]?.ubDev != null"/>
|
||||||
|
|||||||
@@ -2,11 +2,13 @@
|
|||||||
<div class="table-main">
|
<div class="table-main">
|
||||||
<el-table
|
<el-table
|
||||||
:data="prop.tableData"
|
:data="prop.tableData"
|
||||||
height="368px"
|
stripe
|
||||||
|
border
|
||||||
:header-cell-style="{ textAlign: 'center' }"
|
:header-cell-style="{ textAlign: 'center' }"
|
||||||
:cell-style="{ textAlign: 'center' }"
|
:cell-style="{ textAlign: 'center' }"
|
||||||
|
height="368px"
|
||||||
|
style="width: 100%"
|
||||||
>
|
>
|
||||||
<!-- <el-table-column type="index" label="序号" width="70" fixed="left" />-->
|
|
||||||
<el-table-column label="A相" v-if="prop.tableData.length==0|| prop.tableData[0]?.dataA">
|
<el-table-column label="A相" v-if="prop.tableData.length==0|| prop.tableData[0]?.dataA">
|
||||||
|
|
||||||
<el-table-column prop="dataA" :label="'标准值'+(outerUnit==''?'':'('+outerUnit+')')">
|
<el-table-column prop="dataA" :label="'标准值'+(outerUnit==''?'':'('+outerUnit+')')">
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
v-model="formContent.errorSysId"
|
v-model="formContent.errorSysId"
|
||||||
placeholder="请选择误差体系"
|
placeholder="请选择误差体系"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
@change="handleErrorSysChange"
|
@change="handleErrorSysChange('切换误差体系成功')"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="option in pqErrorList"
|
v-for="option in pqErrorList"
|
||||||
@@ -29,7 +29,20 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="数据原则">
|
<el-form-item label="数据原则">
|
||||||
<el-input v-model="formContent.dataRule" :disabled="true" />
|
<!-- <el-input v-model="formContent.dataRule" :disabled="true" />-->
|
||||||
|
<el-select
|
||||||
|
:disabled="checkStore.showDetailType === 2 || checkStore.showDetailType === 0"
|
||||||
|
v-model="formContent.dataRule"
|
||||||
|
placeholder="请选择数据原则"
|
||||||
|
autocomplete="off"
|
||||||
|
@change="handleErrorSysChange('切换数据处理原则成功')">
|
||||||
|
<el-option
|
||||||
|
v-for="item in dictStore.getDictData('Data_Rule')"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备名称">
|
<el-form-item label="设备名称">
|
||||||
<el-input v-model="formContent.deviceName" :disabled="true" />
|
<el-input v-model="formContent.deviceName" :disabled="true" />
|
||||||
@@ -55,7 +68,7 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="checkStore.showDetailType === 1">
|
<el-form-item v-if="checkStore.showDetailType === 1">
|
||||||
<el-button type="primary" :icon="Postcard">报告生成</el-button>
|
<el-button type="primary" :icon="Postcard" @click="handleGenerateReport">报告生成</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="checkStore.showDetailType === 0">
|
<el-form-item v-if="checkStore.showDetailType === 0">
|
||||||
<el-button type="primary" :icon="Histogram" @click="handleReCalculate">重新计算</el-button>
|
<el-button type="primary" :icon="Histogram" @click="handleReCalculate">重新计算</el-button>
|
||||||
@@ -146,10 +159,10 @@
|
|||||||
<el-tabs type="border-card" v-model="activeTab">
|
<el-tabs type="border-card" v-model="activeTab">
|
||||||
<el-tab-pane label="检测结果" name="resultTab">
|
<el-tab-pane label="检测结果" name="resultTab">
|
||||||
<CompareDataCheckResultTable
|
<CompareDataCheckResultTable
|
||||||
|
v-if="activeTab === 'resultTab'"
|
||||||
:tableData="checkResultData.length == 0 ? [] : currentCheckResultData"
|
:tableData="checkResultData.length == 0 ? [] : currentCheckResultData"
|
||||||
:currentCheckItem="currentCheckItem"
|
:currentCheckItem="currentCheckItem"
|
||||||
:currentScriptTypeName="currentScriptTypeName"
|
:currentScriptTypeName="currentScriptTypeName"
|
||||||
v-if="activeTab === 'resultTab'"
|
|
||||||
/>
|
/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="原始数据" name="rawDataTab">
|
<el-tab-pane label="原始数据" name="rawDataTab">
|
||||||
@@ -160,6 +173,12 @@
|
|||||||
:currentScriptTypeName="currentScriptTypeName"
|
:currentScriptTypeName="currentScriptTypeName"
|
||||||
/>
|
/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="历史趋势" name="chartTab">
|
||||||
|
<CompareDataCheckChart
|
||||||
|
v-if="activeTab === 'chartTab'"
|
||||||
|
:tableData="rawTableData.length == 0 ? [] : currentRawTableData"
|
||||||
|
/>
|
||||||
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -172,10 +191,11 @@ import { dialogBig } from '@/utils/elementBind'
|
|||||||
import { computed, reactive, ref } from 'vue'
|
import { computed, reactive, ref } from 'vue'
|
||||||
import CompareDataCheckResultTable from './compareDataCheckResultTable.vue'
|
import CompareDataCheckResultTable from './compareDataCheckResultTable.vue'
|
||||||
import CompareDataCheckRawDataTable from './compareDataCheckRawDataTable.vue'
|
import CompareDataCheckRawDataTable from './compareDataCheckRawDataTable.vue'
|
||||||
|
import CompareDataCheckChart from './compareDataCheckChart.vue'
|
||||||
import { CheckData } from '@/api/check/interface'
|
import { CheckData } from '@/api/check/interface'
|
||||||
import { useCheckStore } from '@/stores/modules/check'
|
import { useCheckStore } from '@/stores/modules/check'
|
||||||
import { Histogram, Postcard } from '@element-plus/icons-vue'
|
import { Histogram, Postcard } from '@element-plus/icons-vue'
|
||||||
import { getPqErrSysList } from '@/api/plan/plan'
|
import {generateDevReport, getPqErrSysList} from '@/api/plan/plan'
|
||||||
import { useModeStore } from '@/stores/modules/mode' // 引入模式 store
|
import { useModeStore } from '@/stores/modules/mode' // 引入模式 store
|
||||||
import { useDictStore } from '@/stores/modules/dict'
|
import { useDictStore } from '@/stores/modules/dict'
|
||||||
import {
|
import {
|
||||||
@@ -256,6 +276,7 @@ const currentRawTableData = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const open = async (row: any, chnNum: string, deviceId: string | null, source: number) => {
|
const open = async (row: any, chnNum: string, deviceId: string | null, source: number) => {
|
||||||
|
activeTab.value = 'resultTab'
|
||||||
isWaveData.value = false
|
isWaveData.value = false
|
||||||
pattern.value = dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? '' //获取数据字典中对应的id
|
pattern.value = dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? '' //获取数据字典中对应的id
|
||||||
rowList.value = {}
|
rowList.value = {}
|
||||||
@@ -507,6 +528,7 @@ const getResults = async (code: any) => {
|
|||||||
// 判断是否为录波数据请求
|
// 判断是否为录波数据请求
|
||||||
const isWaveDataRequest = code === 'wave_data' || isWaveData.value
|
const isWaveDataRequest = code === 'wave_data' || isWaveData.value
|
||||||
|
|
||||||
|
|
||||||
getContrastResult({
|
getContrastResult({
|
||||||
planId: checkStore.plan.id,
|
planId: checkStore.plan.id,
|
||||||
scriptType: rowList.value.scriptType,
|
scriptType: rowList.value.scriptType,
|
||||||
@@ -515,7 +537,8 @@ const getResults = async (code: any) => {
|
|||||||
num: formContent.num == '' ? null : formContent.num,
|
num: formContent.num == '' ? null : formContent.num,
|
||||||
waveNum: isWaveDataRequest ? waveNumber.value : null,
|
waveNum: isWaveDataRequest ? waveNumber.value : null,
|
||||||
isWave: isWaveDataRequest,
|
isWave: isWaveDataRequest,
|
||||||
patternId: pattern.value
|
patternId: pattern.value,
|
||||||
|
code: checkStore.plan.code + (formContent.errorSysId!=checkStore.plan.errorSysId || formContent.dataRule!=checkStore.plan.dataRule? '_temp':'')
|
||||||
}).then((res: any) => {
|
}).then((res: any) => {
|
||||||
let list: string[] = []
|
let list: string[] = []
|
||||||
for (let key in res.data.resultMap) {
|
for (let key in res.data.resultMap) {
|
||||||
@@ -556,7 +579,7 @@ const close = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleErrorSysChange = async () => {
|
const handleErrorSysChange = async (msg:string) => {
|
||||||
changeErrorSystem({
|
changeErrorSystem({
|
||||||
planId: checkStore.plan.id,
|
planId: checkStore.plan.id,
|
||||||
scriptId: '',
|
scriptId: '',
|
||||||
@@ -564,10 +587,11 @@ const handleErrorSysChange = async () => {
|
|||||||
deviceId: formContent.deviceId,
|
deviceId: formContent.deviceId,
|
||||||
code: checkStore.plan.code + '',
|
code: checkStore.plan.code + '',
|
||||||
patternId: dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? '',
|
patternId: dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? '',
|
||||||
chnNum: formContent.chnNum
|
chnNum: formContent.chnNum,
|
||||||
|
dataRuleId: formContent.dataRule
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res.code === ResultEnum.SUCCESS) {
|
if (res.code === ResultEnum.SUCCESS) {
|
||||||
ElMessage.success('切换误差体系成功')
|
ElMessage.success(msg)
|
||||||
handleChnNumChange(formContent.chnNum)
|
handleChnNumChange(formContent.chnNum)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -581,7 +605,8 @@ const handleReCalculate = async () => {
|
|||||||
deviceId: formContent.deviceId,
|
deviceId: formContent.deviceId,
|
||||||
code: checkStore.plan.code + '',
|
code: checkStore.plan.code + '',
|
||||||
patternId: dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? '',
|
patternId: dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? '',
|
||||||
chnNum: formContent.chnNum
|
chnNum: formContent.chnNum,
|
||||||
|
dataRuleId: formContent.dataRule,
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res.code === ResultEnum.SUCCESS) {
|
if (res.code === ResultEnum.SUCCESS) {
|
||||||
ElMessage.success('重新计算成功!')
|
ElMessage.success('重新计算成功!')
|
||||||
@@ -590,6 +615,20 @@ const handleReCalculate = async () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleGenerateReport = async () => {
|
||||||
|
generateDevReport({
|
||||||
|
planId: checkStore.plan.id,
|
||||||
|
devIdList: [formContent.deviceId],
|
||||||
|
scriptId: checkStore.plan.scriptId,
|
||||||
|
planCode: checkStore.plan.code + (formContent.errorSysId!=checkStore.plan.errorSysId ? '_temp':'')
|
||||||
|
}).then(res => {
|
||||||
|
if (res.code === ResultEnum.SUCCESS) {
|
||||||
|
ElMessage.success({ message: `报告生成成功!` })
|
||||||
|
handleChnNumChange(formContent.chnNum)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
open
|
open
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
<el-step :status="step1" title="设备通讯校验"/>
|
<el-step :status="step1" title="设备通讯校验"/>
|
||||||
<el-step :status="step2" title="模型一致性校验"/>
|
<el-step :status="step2" title="模型一致性校验"/>
|
||||||
<el-step :status="step3" title="数据对齐验证" v-if="!props.onlyWave"/>
|
<el-step :status="step3" title="数据对齐验证" v-if="!props.onlyWave"/>
|
||||||
<el-step :status="step4" title="相序校验"/>
|
<el-step :status="step4" title="相序校验" v-if="props.xiangXuIsShow"/>
|
||||||
<!-- <el-step :status="step6" title="遥控录波功能验证"/> -->
|
<!-- <el-step :status="step6" title="遥控录波功能验证"/> -->
|
||||||
<el-step :status="step5" :title="ts === 'error'? '检测失败':ts === 'process'? '检测中':ts === 'success'? '检测成功':'待检测'"/>
|
<el-step :status="step5" :title="ts === 'error'? '检测失败':ts === 'process'? '检测中':ts === 'success'? '检测成功':'待检测'"/>
|
||||||
</el-steps>
|
</el-steps>
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
<el-collapse-item title="相序校验" name="4">
|
<el-collapse-item title="相序校验" name="4" v-if="props.xiangXuIsShow">
|
||||||
<div class="div-log">
|
<div class="div-log">
|
||||||
<p v-for="(item, index) in step4InitLog" :key="index"
|
<p v-for="(item, index) in step4InitLog" :key="index"
|
||||||
:style="{ color: item.type === 'error' ? '#F56C6C' : 'var(--el-text-color-regular)' }">
|
:style="{ color: item.type === 'error' ? '#F56C6C' : 'var(--el-text-color-regular)' }">
|
||||||
@@ -84,6 +84,28 @@
|
|||||||
import { ElMessage, ElMessageBox, StepProps } from 'element-plus'
|
import { ElMessage, ElMessageBox, StepProps } from 'element-plus'
|
||||||
import { computed, PropType, ref, toRef, watch } from 'vue'
|
import { computed, PropType, ref, toRef, watch } from 'vue'
|
||||||
import RealTimeData from './realTimeDataAlign.vue'
|
import RealTimeData from './realTimeDataAlign.vue'
|
||||||
|
const props = defineProps({
|
||||||
|
testStatus: {
|
||||||
|
type: String,
|
||||||
|
default: 'wait'
|
||||||
|
},
|
||||||
|
webMsgSend: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
mapping: {
|
||||||
|
type: Object as PropType<Record<string, Record<string, string>>>,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
onlyWave: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
xiangXuIsShow:{
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const realTimeDataRef = ref()
|
const realTimeDataRef = ref()
|
||||||
|
|
||||||
@@ -122,10 +144,13 @@ const isShowDialog = ref(false)
|
|||||||
const collapseActiveName = ref('1')
|
const collapseActiveName = ref('1')
|
||||||
const activeIndex = ref(0)
|
const activeIndex = ref(0)
|
||||||
const activeTotalNum = computed(() => {
|
const activeTotalNum = computed(() => {
|
||||||
let count = 4; // 基础步骤数:设备通讯校验、模型一致性校验、相序校验、最终状态
|
let count = 3; // 基础步骤数:设备通讯校验、模型一致性校验、最终状态
|
||||||
if (props.onlyWave) {
|
if (!props.onlyWave) {
|
||||||
count++; // 添加数据对齐验证步骤
|
count++; // 添加数据对齐验证步骤
|
||||||
}
|
}
|
||||||
|
if(props.xiangXuIsShow){//添加相序校验
|
||||||
|
count++;
|
||||||
|
}
|
||||||
return count;
|
return count;
|
||||||
});
|
});
|
||||||
const step1 = ref<StepProps['status']>('wait')
|
const step1 = ref<StepProps['status']>('wait')
|
||||||
@@ -150,35 +175,18 @@ const detectionOptions = ref([
|
|||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
name: "数据对齐验证",
|
name: "数据对齐验证",
|
||||||
selected: true,
|
selected: !props.onlyWave,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
name: "相序校验",
|
name: "相序校验",
|
||||||
selected: true,
|
selected: props.xiangXuIsShow,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const currentStepStatus = ref<'error' | 'finish' | 'wait' | 'success' | 'process'>('finish');
|
const currentStepStatus = ref<'error' | 'finish' | 'wait' | 'success' | 'process'>('finish');
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
testStatus: {
|
|
||||||
type: String,
|
|
||||||
default: 'wait'
|
|
||||||
},
|
|
||||||
webMsgSend: {
|
|
||||||
type: Object,
|
|
||||||
default: () => ({})
|
|
||||||
},
|
|
||||||
mapping: {
|
|
||||||
type: Object as PropType<Record<string, Record<string, string>>>,
|
|
||||||
default: () => ({})
|
|
||||||
},
|
|
||||||
onlyWave: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
const testStatus = toRef(props, 'testStatus');
|
const testStatus = toRef(props, 'testStatus');
|
||||||
@@ -332,6 +340,11 @@ watch(webMsgSend, function (newValue, oldValue) {
|
|||||||
if (newValue.code == 25001) { //最终成功
|
if (newValue.code == 25001) { //最终成功
|
||||||
step2.value = 'success'
|
step2.value = 'success'
|
||||||
step3.value = 'process'
|
step3.value = 'process'
|
||||||
|
if(props.onlyWave === true && props.xiangXuIsShow === false )//只有录波,相序不选
|
||||||
|
{
|
||||||
|
step5.value = 'success'
|
||||||
|
ts.value = 'success'
|
||||||
|
}
|
||||||
activeIndex.value = 2
|
activeIndex.value = 2
|
||||||
}
|
}
|
||||||
if (newValue.code == 25003) { //最终失败
|
if (newValue.code == 25003) { //最终失败
|
||||||
@@ -374,6 +387,11 @@ watch(webMsgSend, function (newValue, oldValue) {
|
|||||||
isShowDialog.value = true
|
isShowDialog.value = true
|
||||||
step3.value = 'success'
|
step3.value = 'success'
|
||||||
step4.value = 'process'
|
step4.value = 'process'
|
||||||
|
if(props.onlyWave === false && props.xiangXuIsShow === false )//相序不选
|
||||||
|
{
|
||||||
|
step5.value = 'success'
|
||||||
|
ts.value = 'success'
|
||||||
|
}
|
||||||
activeIndex.value = 3
|
activeIndex.value = 3
|
||||||
testDataStructure.value = newValue.data
|
testDataStructure.value = newValue.data
|
||||||
}
|
}
|
||||||
@@ -514,18 +532,30 @@ watch(webMsgSend, function (newValue, oldValue) {
|
|||||||
// })
|
// })
|
||||||
|
|
||||||
watch(activeIndex, function (newValue, oldValue) {
|
watch(activeIndex, function (newValue, oldValue) {
|
||||||
if(props.onlyWave === true)
|
|
||||||
|
if(props.onlyWave === true && props.xiangXuIsShow === false )
|
||||||
{
|
{
|
||||||
if (Number(collapseActiveName.value) < activeTotalNum.value - 2) {
|
if (Number(collapseActiveName.value) < activeTotalNum.value) {
|
||||||
|
if(newValue == 2){
|
||||||
|
collapseActiveName.value = '2'
|
||||||
|
}else{
|
||||||
|
collapseActiveName.value = (newValue + 1).toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(props.onlyWave === true && props.xiangXuIsShow === true )
|
||||||
|
{
|
||||||
|
if (Number(collapseActiveName.value) < activeTotalNum.value) {
|
||||||
if(newValue == 2){
|
if(newValue == 2){
|
||||||
collapseActiveName.value = '4'
|
collapseActiveName.value = '4'
|
||||||
}else{
|
}else{
|
||||||
collapseActiveName.value = (newValue + 1).toString()
|
collapseActiveName.value = (newValue + 1).toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (Number(collapseActiveName.value) < activeTotalNum.value) {
|
if (Number(collapseActiveName.value) < activeTotalNum.value - 1) {
|
||||||
collapseActiveName.value = (newValue + 1).toString()
|
collapseActiveName.value = (newValue + 1).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,7 @@
|
|||||||
:webMsgSend="webMsgSend"
|
:webMsgSend="webMsgSend"
|
||||||
:mapping="channelMapping"
|
:mapping="channelMapping"
|
||||||
:onlyWave="onlyWave"
|
:onlyWave="onlyWave"
|
||||||
|
:xiangXuIsShow="xiangXuIsShow"
|
||||||
/>
|
/>
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
@@ -170,6 +171,9 @@ const preTestRef = ref<InstanceType<typeof ComparePreTest> | null>(null)
|
|||||||
const testRef: any = ref(null)
|
const testRef: any = ref(null)
|
||||||
const windowWidth = ref(window.innerWidth)
|
const windowWidth = ref(window.innerWidth)
|
||||||
const computedDialogWidth = ref(0)
|
const computedDialogWidth = ref(0)
|
||||||
|
|
||||||
|
const xiangXuIsShow = ref(true)//预检测是否展示相序检测
|
||||||
|
|
||||||
// 监听窗口大小变化
|
// 监听窗口大小变化
|
||||||
const handleResize = () => {
|
const handleResize = () => {
|
||||||
windowWidth.value = window.innerWidth
|
windowWidth.value = window.innerWidth
|
||||||
@@ -342,7 +346,8 @@ const handleSubmitAgain = async () => {
|
|||||||
standardDevIds: standardDevIds.value,
|
standardDevIds: standardDevIds.value,
|
||||||
pairs: pairs.value,
|
pairs: pairs.value,
|
||||||
testItemList: [checkStore.selectTestItems.preTest, false, checkStore.selectTestItems.test],
|
testItemList: [checkStore.selectTestItems.preTest, false, checkStore.selectTestItems.test],
|
||||||
userId: userStore.userInfo.id
|
userId: userStore.userInfo.id,
|
||||||
|
phaseCheck: xiangXuIsShow.value ? 1 : 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
preTestStatus.value = 'start'
|
preTestStatus.value = 'start'
|
||||||
@@ -350,6 +355,26 @@ const handleSubmitAgain = async () => {
|
|||||||
|
|
||||||
//开始检测
|
//开始检测
|
||||||
const handleSubmitFast = async () => {
|
const handleSubmitFast = async () => {
|
||||||
|
|
||||||
|
try {
|
||||||
|
await ElMessageBox.confirm('是否需要进行相序检测?', '确认检测', {
|
||||||
|
confirmButtonText: '是',
|
||||||
|
cancelButtonText: '否',
|
||||||
|
distinguishCancelAndClose: true, // 区分取消和关闭操作
|
||||||
|
type: 'warning'
|
||||||
|
});
|
||||||
|
xiangXuIsShow.value = true;
|
||||||
|
} catch (action) {
|
||||||
|
// 区分用户点击关闭按钮和其他情况
|
||||||
|
if (action === 'cancel') {
|
||||||
|
// 用户点击了"否"按钮
|
||||||
|
xiangXuIsShow.value = false;
|
||||||
|
} else {
|
||||||
|
// 用户点击了关闭按钮或按了ESC键,中断流程
|
||||||
|
return; // 直接返回,不继续执行后续代码
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (channelPairingRef.value) {
|
if (channelPairingRef.value) {
|
||||||
const res = await channelPairingRef.value.handleNext()
|
const res = await channelPairingRef.value.handleNext()
|
||||||
|
|
||||||
@@ -390,7 +415,8 @@ const handleSubmitFast = async () => {
|
|||||||
pairs: pairs.value,
|
pairs: pairs.value,
|
||||||
testItemList: [checkStore.selectTestItems.preTest, false, checkStore.selectTestItems.test],
|
testItemList: [checkStore.selectTestItems.preTest, false, checkStore.selectTestItems.test],
|
||||||
|
|
||||||
userId: userStore.userInfo.id
|
userId: userStore.userInfo.id,
|
||||||
|
phaseCheck: xiangXuIsShow.value ? 1 : 0,
|
||||||
})
|
})
|
||||||
preTestStatus.value = 'start'
|
preTestStatus.value = 'start'
|
||||||
if (checkStore.selectTestItems.test) {
|
if (checkStore.selectTestItems.test) {
|
||||||
@@ -414,7 +440,8 @@ const handleSubmitFast = async () => {
|
|||||||
pairs: pairs.value,
|
pairs: pairs.value,
|
||||||
testItemList: [checkStore.selectTestItems.preTest, false, checkStore.selectTestItems.test],
|
testItemList: [checkStore.selectTestItems.preTest, false, checkStore.selectTestItems.test],
|
||||||
|
|
||||||
userId: userStore.userInfo.id
|
userId: userStore.userInfo.id,
|
||||||
|
phaseCheck: xiangXuIsShow.value ? 1 : 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
TestStatus.value = 'start'
|
TestStatus.value = 'start'
|
||||||
@@ -508,8 +535,6 @@ const sendPause = () => {
|
|||||||
pauseTest()
|
pauseTest()
|
||||||
}
|
}
|
||||||
const sendResume = () => {
|
const sendResume = () => {
|
||||||
|
|
||||||
|
|
||||||
resumeTest({
|
resumeTest({
|
||||||
userPageId: JwtUtil.getLoginName(),
|
userPageId: JwtUtil.getLoginName(),
|
||||||
devIds: checkStore.devices.map(item => item.deviceId),
|
devIds: checkStore.devices.map(item => item.deviceId),
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
v-model="formContent.errorSysId"
|
v-model="formContent.errorSysId"
|
||||||
placeholder="请选择误差体系"
|
placeholder="请选择误差体系"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
@change="handleErrorSysChange"
|
@change="handleErrorSysChange('切换误差体系成功')"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="option in pqErrorList"
|
v-for="option in pqErrorList"
|
||||||
@@ -33,7 +33,20 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="数据原则">
|
<el-form-item label="数据原则">
|
||||||
<el-input v-model="formContent.dataRule" :disabled="true" />
|
<!-- <el-input v-model="formContent.dataRule" :disabled="true" />-->
|
||||||
|
<el-select
|
||||||
|
:disabled="checkStore.showDetailType === 2 || checkStore.showDetailType === 0"
|
||||||
|
v-model="formContent.dataRule"
|
||||||
|
placeholder="请选择数据原则"
|
||||||
|
autocomplete="off"
|
||||||
|
@change="handleErrorSysChange('切换数据处理原则成功')">
|
||||||
|
<el-option
|
||||||
|
v-for="item in dictStore.getDictData('Data_Rule')"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备名称">
|
<el-form-item label="设备名称">
|
||||||
<el-input v-model="formContent.deviceName" :disabled="true" />
|
<el-input v-model="formContent.deviceName" :disabled="true" />
|
||||||
@@ -203,7 +216,6 @@ const formContent = reactive<CheckData.DataCheck>({
|
|||||||
})
|
})
|
||||||
// 原始误差体系id
|
// 原始误差体系id
|
||||||
let originErrorSysId: string = ''
|
let originErrorSysId: string = ''
|
||||||
let planCode: string = ''
|
|
||||||
// 谐波次数列表
|
// 谐波次数列表
|
||||||
// const harmNumList = reactive<{ value: string, label: string }[]>([])
|
// const harmNumList = reactive<{ value: string, label: string }[]>([])
|
||||||
// 当前选中的检测项
|
// 当前选中的检测项
|
||||||
@@ -273,7 +285,7 @@ const handleNodeClick = async (data: any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleErrorSysChange = async () => {
|
const handleErrorSysChange = async (msg:string) => {
|
||||||
|
|
||||||
changeErrorSystem({
|
changeErrorSystem({
|
||||||
planId: checkStore.plan.id,
|
planId: checkStore.plan.id,
|
||||||
@@ -281,15 +293,11 @@ const handleErrorSysChange = async () => {
|
|||||||
errorSysId: formContent.errorSysId,
|
errorSysId: formContent.errorSysId,
|
||||||
deviceId: deviceId,
|
deviceId: deviceId,
|
||||||
code: checkStore.plan.code + '',
|
code: checkStore.plan.code + '',
|
||||||
patternId: dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? ''
|
patternId: dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? '',
|
||||||
|
dataRuleId: formContent.dataRule
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res.code === ResultEnum.SUCCESS) {
|
if (res.code === ResultEnum.SUCCESS) {
|
||||||
ElMessage.success('切换误差体系成功')
|
ElMessage.success(msg)
|
||||||
if (originErrorSysId != formContent.errorSysId) {
|
|
||||||
planCode = checkStore.plan.code + '_temp'
|
|
||||||
} else {
|
|
||||||
planCode = checkStore.plan.code + ''
|
|
||||||
}
|
|
||||||
if (formContent.chnNum != chnList[0].value) {
|
if (formContent.chnNum != chnList[0].value) {
|
||||||
formContent.chnNum = chnList[0].value
|
formContent.chnNum = chnList[0].value
|
||||||
} else {
|
} else {
|
||||||
@@ -317,7 +325,7 @@ const handleChnNumChange = async () => {
|
|||||||
devId: deviceId,
|
devId: deviceId,
|
||||||
devNum: formContent.chnNum + '',
|
devNum: formContent.chnNum + '',
|
||||||
scriptType: originScriptType,
|
scriptType: originScriptType,
|
||||||
code: planCode
|
code: checkStore.plan.code + (formContent.errorSysId!=checkStore.plan.errorSysId || formContent.dataRule!=checkStore.plan.dataRule? '_temp':'')
|
||||||
})
|
})
|
||||||
updateTreeFly(resTreeDataTemp, 4)
|
updateTreeFly(resTreeDataTemp, 4)
|
||||||
updateTreeFly(resTreeDataTemp, 2)
|
updateTreeFly(resTreeDataTemp, 2)
|
||||||
@@ -379,7 +387,7 @@ const updateTableData = async () => {
|
|||||||
scriptId: checkStore.plan.scriptId,
|
scriptId: checkStore.plan.scriptId,
|
||||||
devId: deviceId,
|
devId: deviceId,
|
||||||
devNum: formContent.chnNum + '',
|
devNum: formContent.chnNum + '',
|
||||||
code: planCode,
|
code: checkStore.plan.code + (formContent.errorSysId!=checkStore.plan.errorSysId || formContent.dataRule!=checkStore.plan.dataRule? '_temp':''),
|
||||||
index: parseInt(checkIndex.value)
|
index: parseInt(checkIndex.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -473,7 +481,6 @@ const doCurrentCheckItemUpdate = (newVal: string) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const open = async (_deviceId: string, chnNum: string, _scriptType: string | null) => {
|
const open = async (_deviceId: string, chnNum: string, _scriptType: string | null) => {
|
||||||
planCode = checkStore.plan.code + ''
|
|
||||||
deviceId = _deviceId
|
deviceId = _deviceId
|
||||||
originScriptType = _scriptType
|
originScriptType = _scriptType
|
||||||
scriptType = _scriptType
|
scriptType = _scriptType
|
||||||
@@ -510,7 +517,7 @@ const handleGenerateReport = async () => {
|
|||||||
planId: checkStore.plan.id,
|
planId: checkStore.plan.id,
|
||||||
devIdList: [deviceId],
|
devIdList: [deviceId],
|
||||||
scriptId: checkStore.plan.scriptId,
|
scriptId: checkStore.plan.scriptId,
|
||||||
planCode: planCode
|
planCode: checkStore.plan.code + (formContent.errorSysId!=checkStore.plan.errorSysId || formContent.dataRule!=checkStore.plan.dataRule? '_temp':'')
|
||||||
})
|
})
|
||||||
ElMessage.success({ message: `报告生成成功!` })
|
ElMessage.success({ message: `报告生成成功!` })
|
||||||
}
|
}
|
||||||
@@ -522,14 +529,10 @@ const handleReCalculate = async () => {
|
|||||||
errorSysId: formContent.errorSysId,
|
errorSysId: formContent.errorSysId,
|
||||||
deviceId: deviceId,
|
deviceId: deviceId,
|
||||||
code: checkStore.plan.code + '',
|
code: checkStore.plan.code + '',
|
||||||
patternId: dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? ''
|
patternId: dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? '',
|
||||||
|
dataRuleId: formContent.dataRule
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
ElMessage.success('重新计算成功!')
|
ElMessage.success('重新计算成功!')
|
||||||
// if (originErrorSysId != formContent.errorSysId) {
|
|
||||||
// planCode = checkStore.plan.code + "_temp"
|
|
||||||
// } else {
|
|
||||||
// planCode = checkStore.plan.code + ''
|
|
||||||
// }
|
|
||||||
if (formContent.chnNum != chnList[0].value) {
|
if (formContent.chnNum != chnList[0].value) {
|
||||||
formContent.chnNum = chnList[0].value
|
formContent.chnNum = chnList[0].value
|
||||||
} else {
|
} else {
|
||||||
@@ -560,7 +563,6 @@ const close = async () => {
|
|||||||
currentScriptTypeName.value = ''
|
currentScriptTypeName.value = ''
|
||||||
currentDesc.value = ''
|
currentDesc.value = ''
|
||||||
pqErrorList.length = 0
|
pqErrorList.length = 0
|
||||||
planCode = ''
|
|
||||||
|
|
||||||
visible.value = false
|
visible.value = false
|
||||||
|
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ const open = async (mapping : Record<string, Record<string, string>>,data : any)
|
|||||||
|
|
||||||
// 导出数据
|
// 导出数据
|
||||||
const exportData =async () => {
|
const exportData =async () => {
|
||||||
useDownload(exportAlignData, '原始数据', null, false, '.xlsx')
|
useDownload(exportAlignData, '对齐数据', null, false, '.xlsx')
|
||||||
ElMessage.success('数据导出成功');
|
ElMessage.success('数据导出成功');
|
||||||
// 这里可以添加实际的数据导出逻辑
|
// 这里可以添加实际的数据导出逻辑
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1131,7 +1131,7 @@ const open = async (sign: string, data: Plan.ReqPlan, currentMode: string, plan:
|
|||||||
formContent.name = ''
|
formContent.name = ''
|
||||||
// 新建子计划允许选择数据源
|
// 新建子计划允许选择数据源
|
||||||
const datasourceDicts = dictStore.getDictData('Datasource')
|
const datasourceDicts = dictStore.getDictData('Datasource')
|
||||||
formContent.datasourceIds = [datasourceDicts[0]?.code] ?? []
|
formContent.datasourceIds = datasourceDicts[0]?.code ? [datasourceDicts[0].code] : []
|
||||||
formContent.memberIds = []
|
formContent.memberIds = []
|
||||||
}
|
}
|
||||||
generateData()
|
generateData()
|
||||||
|
|||||||
@@ -35,7 +35,8 @@
|
|||||||
"debug": "^4.4.0",
|
"debug": "^4.4.0",
|
||||||
"ee-bin": "^4.1.4",
|
"ee-bin": "^4.1.4",
|
||||||
"electron": "^31.7.6",
|
"electron": "^31.7.6",
|
||||||
"electron-builder": "^25.1.8"
|
"electron-builder": "^25.1.8",
|
||||||
|
"icon-gen": "^5.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"autofit.js": "^3.2.8",
|
"autofit.js": "^3.2.8",
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 739 KiB |
|
Before Width: | Height: | Size: 95 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 204 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 137 KiB |
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 95 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 95 KiB |
|
Before Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 114 KiB |
BIN
public/images/icon.ico
Normal file
|
After Width: | Height: | Size: 169 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 786 B After Width: | Height: | Size: 943 B |
@@ -88,15 +88,15 @@ class ConfigGenerator {
|
|||||||
console.log('[ConfigGenerator] Data path:', this.dataPath);
|
console.log('[ConfigGenerator] Data path:', this.dataPath);
|
||||||
console.log('[ConfigGenerator] MySQL port:', options.mysqlPort || 3306);
|
console.log('[ConfigGenerator] MySQL port:', options.mysqlPort || 3306);
|
||||||
console.log('[ConfigGenerator] MySQL password:', options.mysqlPassword || 'njcnpqs');
|
console.log('[ConfigGenerator] MySQL password:', options.mysqlPassword || 'njcnpqs');
|
||||||
console.log('[ConfigGenerator] Java port:', options.javaPort || 18092);
|
console.log('[ConfigGenerator] Java port:', options.javaPort || 18093);
|
||||||
console.log('[ConfigGenerator] WebSocket port:', options.websocketPort || 7777);
|
console.log('[ConfigGenerator] WebSocket port:', options.websocketPort || 7778);
|
||||||
|
|
||||||
resolve({
|
resolve({
|
||||||
configPath: this.configPath,
|
configPath: this.configPath,
|
||||||
dataPath: this.dataPath,
|
dataPath: this.dataPath,
|
||||||
mysqlPort: options.mysqlPort || 3306,
|
mysqlPort: options.mysqlPort || 3306,
|
||||||
javaPort: options.javaPort || 18092,
|
javaPort: options.javaPort || 18093,
|
||||||
websocketPort: options.websocketPort || 7777
|
websocketPort: options.websocketPort || 7778
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[ConfigGenerator] Failed to generate config:', error);
|
console.error('[ConfigGenerator] Failed to generate config:', error);
|
||||||
@@ -123,6 +123,75 @@ class ConfigGenerator {
|
|||||||
console.log('[ConfigGenerator] Created directory:', dir);
|
console.log('[ConfigGenerator] Created directory:', dir);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 复制内置的报告模板文件
|
||||||
|
this.copyBuiltInTemplates();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制内置的报告模板文件到用户数据目录
|
||||||
|
*/
|
||||||
|
copyBuiltInTemplates() {
|
||||||
|
try {
|
||||||
|
const isDev = !process.resourcesPath;
|
||||||
|
const baseDir = isDev
|
||||||
|
? path.join(__dirname, '..')
|
||||||
|
: path.dirname(process.resourcesPath);
|
||||||
|
|
||||||
|
// 内置模板源路径
|
||||||
|
const templateSource = isDev
|
||||||
|
? path.join(baseDir, 'build', 'extraResources', 'templates')
|
||||||
|
: path.join(process.resourcesPath, 'extraResources', 'templates');
|
||||||
|
|
||||||
|
// 目标路径:用户数据目录/template/
|
||||||
|
const templateDest = path.join(this.dataPath, 'template');
|
||||||
|
|
||||||
|
// 检查源模板是否存在
|
||||||
|
if (!fs.existsSync(templateSource)) {
|
||||||
|
console.log('[ConfigGenerator] Built-in templates not found, skipping copy');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归复制模板文件(只复制不存在的文件,不覆盖已有文件)
|
||||||
|
this.copyTemplatesRecursive(templateSource, templateDest);
|
||||||
|
|
||||||
|
console.log('[ConfigGenerator] Built-in templates copied successfully');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[ConfigGenerator] Failed to copy templates:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 递归复制模板文件(不覆盖已存在的文件)
|
||||||
|
* @param {string} src 源目录
|
||||||
|
* @param {string} dest 目标目录
|
||||||
|
*/
|
||||||
|
copyTemplatesRecursive(src, dest) {
|
||||||
|
// 确保目标目录存在
|
||||||
|
if (!fs.existsSync(dest)) {
|
||||||
|
fs.mkdirSync(dest, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取源目录内容
|
||||||
|
const entries = fs.readdirSync(src, { withFileTypes: true });
|
||||||
|
|
||||||
|
entries.forEach(entry => {
|
||||||
|
const srcPath = path.join(src, entry.name);
|
||||||
|
const destPath = path.join(dest, entry.name);
|
||||||
|
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
// 递归复制子目录
|
||||||
|
this.copyTemplatesRecursive(srcPath, destPath);
|
||||||
|
} else {
|
||||||
|
// 只复制不存在的文件(不覆盖用户修改过的文件)
|
||||||
|
if (!fs.existsSync(destPath)) {
|
||||||
|
fs.copyFileSync(srcPath, destPath);
|
||||||
|
console.log('[ConfigGenerator] Copied template:', destPath);
|
||||||
|
} else {
|
||||||
|
console.log('[ConfigGenerator] Template already exists, skipping:', destPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -166,11 +166,20 @@ class JavaRunner {
|
|||||||
'-Dfile.encoding=UTF-8', // 设置文件编码为UTF-8,解决中文乱码
|
'-Dfile.encoding=UTF-8', // 设置文件编码为UTF-8,解决中文乱码
|
||||||
'-Duser.language=zh', // 设置语言为中文
|
'-Duser.language=zh', // 设置语言为中文
|
||||||
'-Duser.region=CN', // 设置地区为中国
|
'-Duser.region=CN', // 设置地区为中国
|
||||||
'-jar',
|
|
||||||
jarPath,
|
|
||||||
`--spring.config.location=${configPath}`
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// 如果提供了 logPath,通过 JVM 系统属性传递给 logback
|
||||||
|
if (options.logPath) {
|
||||||
|
// Windows 路径使用正斜杠或保持原样,JVM 会自动处理
|
||||||
|
// 方案1:转换为正斜杠(跨平台兼容)
|
||||||
|
const normalizedLogPath = options.logPath.replace(/\\/g, '/');
|
||||||
|
javaArgs.push(`-DlogHomeDir=${normalizedLogPath}`);
|
||||||
|
console.log('[Java] Setting log path to:', normalizedLogPath);
|
||||||
|
console.log('[Java] Original log path:', options.logPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
javaArgs.push('-jar', jarPath, `--spring.config.location=${configPath}`);
|
||||||
|
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
cwd: path.dirname(jarPath),
|
cwd: path.dirname(jarPath),
|
||||||
stdio: ['ignore', 'pipe', 'pipe'],
|
stdio: ['ignore', 'pipe', 'pipe'],
|
||||||
|
|||||||
@@ -300,6 +300,7 @@ default-character-set=utf8mb4
|
|||||||
// 如果还没退出,强制杀死
|
// 如果还没退出,强制杀死
|
||||||
this.log('warn', '优雅关闭超时,强制终止...');
|
this.log('warn', '优雅关闭超时,强制终止...');
|
||||||
this.mysqlProcess.kill('SIGTERM');
|
this.mysqlProcess.kill('SIGTERM');
|
||||||
|
await this.sleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log('success', 'MySQL 进程已关闭');
|
this.log('success', 'MySQL 进程已关闭');
|
||||||
@@ -309,16 +310,30 @@ default-character-set=utf8mb4
|
|||||||
|
|
||||||
if (this.mysqlProcess) {
|
if (this.mysqlProcess) {
|
||||||
this.mysqlProcess.kill('SIGTERM');
|
this.mysqlProcess.kill('SIGTERM');
|
||||||
|
await this.sleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确保进程被杀死
|
// 确保进程被杀死
|
||||||
try {
|
try {
|
||||||
await this.execCommand('taskkill /F /IM mysqld.exe');
|
await this.execCommand('taskkill /F /IM mysqld.exe');
|
||||||
|
await this.sleep(2000); // 等待文件句柄释放
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// 忽略
|
// 忽略
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 最终检查:确保所有 mysqld.exe 进程都被终止
|
||||||
|
try {
|
||||||
|
const { stdout } = await this.execCommand('tasklist /FI "IMAGENAME eq mysqld.exe" /FO CSV /NH');
|
||||||
|
if (stdout.includes('mysqld.exe')) {
|
||||||
|
this.log('warn', '检测到残留进程,强制清理...');
|
||||||
|
await this.execCommand('taskkill /F /IM mysqld.exe');
|
||||||
|
await this.sleep(2000); // 额外等待以确保文件句柄释放
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// 忽略
|
||||||
|
}
|
||||||
|
|
||||||
this.mysqlProcess = null;
|
this.mysqlProcess = null;
|
||||||
this.currentPort = null;
|
this.currentPort = null;
|
||||||
}
|
}
|
||||||
|
|||||||