Compare commits
47 Commits
5ec87f67c9
...
d66df5e2cf
Author | SHA1 | Date |
---|---|---|
|
d66df5e2cf | |
|
7d53c34651 | |
|
a929a7b47d | |
|
7c8b2477d5 | |
|
95f8374a13 | |
|
1b9ff88922 | |
|
a08559f55f | |
|
b71aaf4ff7 | |
|
9646a4ae8c | |
|
f697d427ad | |
|
34108a2186 | |
|
4d0d6c2ab9 | |
|
cd708e9eb9 | |
|
902ba88c2f | |
|
fa641c5a28 | |
|
68e29d3ace | |
|
16c8adc1f4 | |
|
57cf6523ef | |
|
e97b8516ae | |
|
20a8a95141 | |
|
c8dd26aec2 | |
|
d36ad16535 | |
|
6c6a3ba4e7 | |
|
3bb9a938d5 | |
|
297d998365 | |
|
9a143c26b0 | |
|
b38b07e5bb | |
|
5c8ec926f9 | |
|
2d4d509ef0 | |
|
9364ef8412 | |
|
1c024beeb8 | |
|
d12381feb3 | |
|
1d67888b56 | |
|
3af303b605 | |
|
6257501187 | |
|
69756af817 | |
|
b9f2b30c57 | |
|
d56f84f631 | |
|
06edc35679 | |
|
5a0304a8d6 | |
|
206de9e618 | |
|
57d766fab0 | |
|
8567ec8c2e | |
|
17164687b6 | |
|
1152321c30 | |
|
7b98fca398 | |
|
9bb8ff8942 |
|
@ -1,5 +1,7 @@
|
|||
node_modules
|
||||
dist
|
||||
out
|
||||
.DS_Store
|
||||
*.log*
|
||||
/dist/
|
||||
/dist.zip
|
||||
.idea
|
||||
|
|
|
@ -2,14 +2,12 @@
|
|||
<code_scheme name="Project" version="173">
|
||||
<HTMLCodeStyleSettings>
|
||||
<option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
|
||||
<option name="HTML_QUOTE_STYLE" value="Single" />
|
||||
<option name="HTML_ENFORCE_QUOTES" value="true" />
|
||||
</HTMLCodeStyleSettings>
|
||||
<JSCodeStyleSettings version="0">
|
||||
<option name="USE_SEMICOLON_AFTER_STATEMENT" value="false" />
|
||||
<option name="FORCE_SEMICOLON_STYLE" value="true" />
|
||||
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
|
||||
<option name="USE_DOUBLE_QUOTES" value="false" />
|
||||
<option name="FORCE_QUOTE_STYlE" value="true" />
|
||||
<option name="ENFORCE_TRAILING_COMMA" value="Remove" />
|
||||
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/node_modules" />
|
||||
</content>
|
||||
<content url="file://$MODULE_DIR$/node_modules" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptSettings">
|
||||
<option name="languageLevel" value="FLOW" />
|
||||
</component>
|
||||
</project>
|
|
@ -1,4 +1,18 @@
|
|||
#singleQuote: true
|
||||
#semi: false
|
||||
#printWidth: 100
|
||||
#trailingComma: none
|
||||
printWidth: 220
|
||||
tabWidth: 4
|
||||
useTabs: true
|
||||
semi: true
|
||||
singleQuote: true
|
||||
semi: false
|
||||
printWidth: 100
|
||||
trailingComma: none
|
||||
quoteProps: "as-needed"
|
||||
trailingComma: "none"
|
||||
bracketSpacing: true
|
||||
jsxBracketSameLine: false
|
||||
arrowParens: "avoid"
|
||||
endOfLine: "lf"
|
||||
jsxSingleQuote: false
|
||||
vueIndentScriptAndStyle: false
|
||||
Prettier:HTMLWhitespaceSensitivity: 'ignore'
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
BIN
build/icon.icns
BIN
build/icon.ico
Before Width: | Height: | Size: 121 KiB |
BIN
build/icon.png
Before Width: | Height: | Size: 35 KiB |
|
@ -1,44 +1,76 @@
|
|||
appId: com.electron.app
|
||||
productName: gateway-ui
|
||||
# 应用程序的唯一标识符
|
||||
appId: gy.calibration.pc
|
||||
# 应用程序的名称
|
||||
productName: 谷云校表产测
|
||||
# 定义构建资源和输出文件的目录
|
||||
directories:
|
||||
buildResources: build
|
||||
# 定义要包含或排除在构建输出中的文件
|
||||
files:
|
||||
- '!**/.vscode/*'
|
||||
- '!src/*'
|
||||
- '!electron.vite.config.{js,ts,mjs,cjs}'
|
||||
- '!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}'
|
||||
- '!{.env,.env.*,.npmrc,pnpm-lock.yaml}'
|
||||
- '!**/.vscode/*' # 排除VSCode配置文件
|
||||
- '!**/.cursor/*' # 排除cursor配置文件
|
||||
- '!**/.idea/*' # 排除idea配置文件
|
||||
- '!src/*' # 排除源代码目录
|
||||
- '!**/*.log' # 排除日志文件
|
||||
- '!electron.vite.config.{js,ts,mjs,cjs}' # 排除Electron构建配置文件
|
||||
- '!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}' # 排除开发和文档文件
|
||||
- '!{.env,.env.*,.npmrc,pnpm-lock.yaml,*.zip,app.log}' # 排除环境和包管理配置文件
|
||||
# 定义需要解压的asar文件
|
||||
asarUnpack:
|
||||
- resources/**
|
||||
- resources/** # 解压资源目录下的所有文件
|
||||
# 针对Windows平台的配置
|
||||
win:
|
||||
executableName: gateway-ui
|
||||
icon: resources/icon.png # 应用程序图标的路径
|
||||
# 针对NSIS安装程序的配置
|
||||
nsis:
|
||||
artifactName: ${name}-${version}-setup.${ext}
|
||||
shortcutName: ${productName}
|
||||
uninstallDisplayName: ${productName}
|
||||
createDesktopShortcut: always
|
||||
artifactName: ${productName}-${version}-setup.${ext} # 安装程序的文件名格式
|
||||
shortcutName: ${productName} # 快捷方式的名称
|
||||
uninstallDisplayName: ${productName} # 卸载程序显示的名称
|
||||
createDesktopShortcut: always # 总是在桌面创建快捷方式
|
||||
allowToChangeInstallationDirectory: true # 允许用户选择安装目录
|
||||
oneClick: false # 设置为非一键安装
|
||||
installerIcon: resources/icon.ico # 安装程序的图标
|
||||
uninstallerIcon: resources/icon.ico # 卸载程序的图标
|
||||
installerHeader: resources/icon.png # 安装程序头部的图像
|
||||
installerHeaderIcon: resources/icon.png # 安装程序头部图标的路径
|
||||
# 针对macOS平台的配置
|
||||
mac:
|
||||
entitlementsInherit: build/entitlements.mac.plist
|
||||
extendInfo:
|
||||
- NSCameraUsageDescription: Application requests access to the device's camera.
|
||||
- NSMicrophoneUsageDescription: Application requests access to the device's microphone.
|
||||
- NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder.
|
||||
- NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder.
|
||||
notarize: false
|
||||
entitlementsInherit: build/entitlements.mac.plist # 继承权限配置文件
|
||||
extendInfo: # 添加macOS应用的元数据
|
||||
- NSCameraUsageDescription: Application requests access to the device's camera. # 摄像头使用权限描述
|
||||
- NSMicrophoneUsageDescription: Application requests access to the device's microphone. # 麦克风使用权限描述
|
||||
- NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder. # 文档夹使用权限描述
|
||||
- NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder. # 下载夹使用权限描述
|
||||
notarize: false # 是否进行苹果的公证
|
||||
icon: resources/icon.png # 应用程序的图标路径
|
||||
identity: null # 签名身份
|
||||
# 针对dmg安装包的配置
|
||||
dmg:
|
||||
artifactName: ${name}-${version}.${ext}
|
||||
artifactName: ${name}-${version}.${ext} # dmg文件的命名格式
|
||||
# 针对Linux平台的配置
|
||||
linux:
|
||||
target:
|
||||
target: # 目标包类型
|
||||
- AppImage
|
||||
- snap
|
||||
- deb
|
||||
maintainer: electronjs.org
|
||||
category: Utility
|
||||
maintainer: GuyunDevelopment # 维护者信息
|
||||
category: Utility # 应用程序类别
|
||||
icon: resources/icon.png # 应用程序图标路径
|
||||
# 针对AppImage包的配置
|
||||
appImage:
|
||||
artifactName: ${name}-${version}.${ext}
|
||||
artifactName: ${name}-${version}.${ext} # AppImage文件的命名格式
|
||||
# 是否在npm安装时重建asar包
|
||||
npmRebuild: false
|
||||
# 配置自动更新的信息
|
||||
publish:
|
||||
provider: generic
|
||||
url: https://example.com/auto-updates
|
||||
provider: generic # 更新服务提供者
|
||||
url: https://example.com/auto-updates # 更新信息的URL
|
||||
# provider: github # 更新服务提供者
|
||||
# owner: fanhuayishiy # GitHub用户名
|
||||
# repo: mygit1 # GitHub仓库名称
|
||||
# token: ${env:GITHUB_TOKEN}
|
||||
# releaseType: release
|
||||
|
||||
# 配置Electron下载的镜像地址
|
||||
electronDownload:
|
||||
mirror: https://npmmirror.com/mirrors/electron/
|
||||
mirror: https://npmmirror.com/mirrors/electron/ # Electron下载的镜像地址
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { resolve } from 'path'
|
||||
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import VueDevTools from 'vite-plugin-vue-devtools';
|
||||
|
||||
export default defineConfig({
|
||||
main: {
|
||||
|
@ -15,6 +16,9 @@ export default defineConfig({
|
|||
'@renderer': resolve('src/renderer/src')
|
||||
}
|
||||
},
|
||||
plugins: [vue()]
|
||||
plugins: [
|
||||
vue(),
|
||||
VueDevTools()
|
||||
]
|
||||
}
|
||||
})
|
||||
|
|
12
package.json
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "gateway-ui",
|
||||
"name": "gy-calibration",
|
||||
"version": "1.0.0",
|
||||
"description": "An Electron application with Vue",
|
||||
"description": "谷云开发部开发的断路器标定软件",
|
||||
"main": "./out/main/index.js",
|
||||
"author": "example.com",
|
||||
"homepage": "https://electron-vite.org",
|
||||
|
@ -21,10 +21,13 @@
|
|||
"@electron-toolkit/preload": "^3.0.1",
|
||||
"@electron-toolkit/utils": "^3.0.0",
|
||||
"axios": "^1.7.2",
|
||||
"dayjs": "^1.11.13",
|
||||
"electron-updater": "^6.1.7",
|
||||
"element-plus": "^2.7.6",
|
||||
"file-saver": "^2.0.5",
|
||||
"pinia": "^2.1.7",
|
||||
"vue-router": "^4.4.0"
|
||||
"vue-router": "^4.4.0",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron-toolkit/eslint-config": "^1.0.2",
|
||||
|
@ -36,8 +39,11 @@
|
|||
"electron-vite": "^2.3.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-vue": "^9.26.0",
|
||||
"less": "^4.2.0",
|
||||
"prettier": "^3.3.2",
|
||||
"sass": "^1.77.6",
|
||||
"vite": "^5.3.1",
|
||||
"vite-plugin-vue-devtools": "^7.7.6",
|
||||
"vue": "^3.4.30"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
module.exports = {
|
||||
//打包配置
|
||||
|
||||
url: 'http://127.0.0.1:8000',
|
||||
wsUrl: 'ws://127.0.0.1:8000',
|
||||
swichWsUrl: 'ws://127.0.0.1:8001',
|
||||
serialPortUrl: 'http://127.0.0.1:8000',
|
||||
|
||||
//开发配置
|
||||
|
||||
// url: 'http://192.168.1.17:8000',
|
||||
// wsUrl: 'ws://192.168.1.17:8000',
|
||||
// swichWsUrl: 'ws://192.168.1.17:8001',
|
||||
// serialPortUrl: 'http://192.168.1.17:8000',
|
||||
|
||||
// 远程连接串口使用
|
||||
// serialPortUrl: 'http://120.77.172.42:7202',
|
||||
// serialPortUrl: 'http://192.168.1.17:8888',
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
[{"name":"属性1","addr":"60000","len":"2","data":"15"},{"name":"属性2","addr":"50000","len":"1","data":"1"}]
|
After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 45 KiB |
|
@ -0,0 +1,21 @@
|
|||
server:
|
||||
serverMain:
|
||||
address: "8000"
|
||||
#serverRoot: "resource/public"
|
||||
|
||||
logger:
|
||||
path: "logs"
|
||||
level: "info"
|
||||
|
||||
#台体编号
|
||||
equipment: HS-9203M-0001
|
||||
#设备总数
|
||||
totalNum: 16
|
||||
#起始端口号
|
||||
startAddr: 22
|
||||
#测试源电压波动比例
|
||||
fluctuateRatioU: 90
|
||||
#测试源电压波动比例
|
||||
fluctuateRatioI: 90
|
||||
#配置密钥
|
||||
secretKey: "1dd53c82958d1de56df4035d3ed9fd82"
|
|
@ -0,0 +1,29 @@
|
|||
[Delay]
|
||||
ErrWaittime=0.5
|
||||
SourceWaittime=1
|
||||
StdmeterWaittime=2
|
||||
Waittime4open=0.2
|
||||
PurgeCommDelay=0.05
|
||||
SampleTIME=3
|
||||
HarmStableTime=3
|
||||
HarmReviseTime=2
|
||||
IntervalWaitTime=0.05
|
||||
BpGrade1=0.05
|
||||
BpGrade2=0.1
|
||||
DelayAfterGearChange=0.5
|
||||
IFCheckGear=0
|
||||
CheckGearIntervalTime=1
|
||||
CheckGearMaxWaitTIme=7
|
||||
ReviseTIme=0
|
||||
|
||||
[System]
|
||||
SetMode5300b=0
|
||||
ReadMode5300b=1
|
||||
HarmReviseMode=0
|
||||
IfHarmRevise=1
|
||||
HS5300ReadUacSupport=1
|
||||
ifThreadLog=1
|
||||
HS5300UURevise=0
|
||||
|
||||
[Debug]
|
||||
Mode=0
|
|
@ -0,0 +1,28 @@
|
|||
server:
|
||||
address: ":8888"
|
||||
staticRoot: "./resource/template"
|
||||
apiPrefix: "/api/v1"
|
||||
pluginPrefix: "/plugins"
|
||||
file:
|
||||
upload_path: "./resource/upload"
|
||||
dir_mode: "byDate"
|
||||
|
||||
|
||||
|
||||
|
||||
logger:
|
||||
level: debug
|
||||
path: "./resource/logs/server.log"
|
||||
max_size: 10
|
||||
max_age: 30
|
||||
|
||||
|
||||
database:
|
||||
default:
|
||||
kind: "mysql"
|
||||
dsn: "root:mysql_YiniNx@tcp(123.60.30.87:3306)/goside?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
max_idle_conns: 10
|
||||
max_open_conns: 100
|
||||
# kind: "SQLite"
|
||||
# dsn: "./resource/db/db.db"
|
||||
# max_idle_conns: 10
|
|
@ -0,0 +1,713 @@
|
|||
[
|
||||
{
|
||||
"key": "c_id",
|
||||
"name": "芯片id",
|
||||
"addr": 0,
|
||||
"len": 4,
|
||||
"dataType": "string",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "",
|
||||
"unit": ""
|
||||
},
|
||||
{
|
||||
"id": 0,
|
||||
"key": "calibration_conf",
|
||||
"name": "标定参数",
|
||||
"addr": 30018,
|
||||
"len": 5,
|
||||
"dataType": "struct",
|
||||
"rwType": "R",
|
||||
"default": "",
|
||||
"precision": "",
|
||||
"unit": "",
|
||||
"format": [
|
||||
{
|
||||
"index": 0,
|
||||
"size": 16,
|
||||
"key": "ec",
|
||||
"name": "脉冲常数",
|
||||
"unit": "",
|
||||
"value": "3200"
|
||||
},
|
||||
{
|
||||
"index": 16,
|
||||
"size": 16,
|
||||
"key": "u",
|
||||
"name": "电压",
|
||||
"unit": "V",
|
||||
"value": "220"
|
||||
},
|
||||
{
|
||||
"index": 32,
|
||||
"size": 16,
|
||||
"key": "i",
|
||||
"name": "电流",
|
||||
"unit": "A",
|
||||
"value": "10"
|
||||
},
|
||||
{
|
||||
"index": 48,
|
||||
"size": 16,
|
||||
"key": "pt",
|
||||
"name": "电压比",
|
||||
"unit": "",
|
||||
"value": "1981"
|
||||
},
|
||||
{
|
||||
"index": 64,
|
||||
"size": 16,
|
||||
"key": "ct",
|
||||
"name": "电流比",
|
||||
"unit": "",
|
||||
"value": "2000"
|
||||
},
|
||||
{
|
||||
"index": 80,
|
||||
"size": 16,
|
||||
"key": "ileak",
|
||||
"name": "漏电流",
|
||||
"unit": "mA",
|
||||
"value": "20"
|
||||
},
|
||||
{
|
||||
"index": 96,
|
||||
"size": 8,
|
||||
"key": "ig",
|
||||
"name": "电流通道放大倍数",
|
||||
"unit": "",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"index": 104,
|
||||
"size": 8,
|
||||
"key": "vg",
|
||||
"name": "电压通道放大倍数",
|
||||
"unit": "",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"index": 112,
|
||||
"size": 8,
|
||||
"key": "ilg",
|
||||
"name": "漏电流通道放大倍数",
|
||||
"unit": "",
|
||||
"value": "3"
|
||||
},
|
||||
{
|
||||
"index": 120,
|
||||
"size": 8,
|
||||
"key": "reserve",
|
||||
"name": "保留位",
|
||||
"unit": "",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"index": 128,
|
||||
"size": 32,
|
||||
"key": "isr",
|
||||
"name": "电流采样电阻",
|
||||
"unit": "10mΩ",
|
||||
"value": "440"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "last_event",
|
||||
"name": "事件",
|
||||
"addr": 50000,
|
||||
"len": 1,
|
||||
"dataType": "string",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "",
|
||||
"unit": ""
|
||||
},
|
||||
{
|
||||
"key": "last_event_time",
|
||||
"name": "事件发生时间",
|
||||
"addr": 50001,
|
||||
"len": 1,
|
||||
"dataType": "time",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "",
|
||||
"unit": ""
|
||||
},
|
||||
{
|
||||
"key": "update_time",
|
||||
"name": "时间戳",
|
||||
"addr": 50002,
|
||||
"len": 1,
|
||||
"dataType": "time",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "",
|
||||
"unit": ""
|
||||
},
|
||||
{
|
||||
"key": "switch",
|
||||
"name": "开关状态",
|
||||
"addr": 50003,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "",
|
||||
"precision": "",
|
||||
"unit": ""
|
||||
},
|
||||
{
|
||||
"key": "Freq",
|
||||
"name": "电网频率",
|
||||
"addr": 50004,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.01",
|
||||
"unit": "Hz"
|
||||
},
|
||||
{
|
||||
"key": "Leak_I",
|
||||
"name": "漏电流/N相电流",
|
||||
"addr": 50005,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "1",
|
||||
"unit": "mA"
|
||||
},
|
||||
{
|
||||
"key": "Tn_1",
|
||||
"name": "N相进线温度",
|
||||
"addr": 50006,
|
||||
"len": 1,
|
||||
"dataType": "int32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.1",
|
||||
"unit": "℃"
|
||||
},
|
||||
{
|
||||
"key": "Tn_2",
|
||||
"name": "N相出线温度",
|
||||
"addr": 50007,
|
||||
"len": 1,
|
||||
"dataType": "int32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.1",
|
||||
"unit": "℃"
|
||||
},
|
||||
{
|
||||
"key": "Ua",
|
||||
"name": "A/L相电压",
|
||||
"addr": 50008,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.01",
|
||||
"unit": "V"
|
||||
},
|
||||
{
|
||||
"key": "Ia",
|
||||
"name": "A/L相电流",
|
||||
"addr": 50009,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": "A",
|
||||
"critical": "0.2"
|
||||
},
|
||||
{
|
||||
"key": "Pa",
|
||||
"name": "A/L相有功功率",
|
||||
"addr": 50010,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": "W"
|
||||
},
|
||||
{
|
||||
"key": "Qa",
|
||||
"name": "A/L相无功功率",
|
||||
"addr": 50011,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": "var"
|
||||
},
|
||||
{
|
||||
"key": "Sa",
|
||||
"name": "A/L相视在功率",
|
||||
"addr": 50012,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": "va"
|
||||
},
|
||||
{
|
||||
"key": "Pfa",
|
||||
"name": "A/L相功率因数",
|
||||
"addr": 50013,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": ""
|
||||
},
|
||||
{
|
||||
"key": "EPa_H",
|
||||
"name": "A/L相有功电能高32位",
|
||||
"addr": 50014,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "1",
|
||||
"unit": "Wh"
|
||||
},
|
||||
{
|
||||
"key": "EPa_L",
|
||||
"name": "A/L相有功电能低32位",
|
||||
"addr": 50015,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "1",
|
||||
"unit": "Wh"
|
||||
},
|
||||
{
|
||||
"key": "EQa_H",
|
||||
"name": "A/L相无功电能高32位",
|
||||
"addr": 50016,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "1",
|
||||
"unit": "varh"
|
||||
},
|
||||
{
|
||||
"key": "EQa_L",
|
||||
"name": "A/L相无功电能低32位",
|
||||
"addr": 50017,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "1",
|
||||
"unit": "varh"
|
||||
},
|
||||
{
|
||||
"key": "Ta_1",
|
||||
"name": "L/A相进线温度",
|
||||
"addr": 50018,
|
||||
"len": 1,
|
||||
"dataType": "int32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.1",
|
||||
"unit": "℃"
|
||||
},
|
||||
{
|
||||
"key": "Ta_2",
|
||||
"name": "L/A相出线温度",
|
||||
"addr": 50019,
|
||||
"len": 1,
|
||||
"dataType": "int32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.1",
|
||||
"unit": "℃"
|
||||
},
|
||||
{
|
||||
"key": "Ub",
|
||||
"name": "B相电压",
|
||||
"addr": 50020,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.01",
|
||||
"unit": "V"
|
||||
},
|
||||
{
|
||||
"key": "Ib",
|
||||
"name": "B相电流",
|
||||
"addr": 50021,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": "A",
|
||||
"critical": "0.2"
|
||||
},
|
||||
{
|
||||
"key": "Pb",
|
||||
"name": "B相有功功率 ",
|
||||
"addr": 50022,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": "W"
|
||||
},
|
||||
{
|
||||
"key": "Qb",
|
||||
"name": "B相无功功率",
|
||||
"addr": 50023,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": "var"
|
||||
},
|
||||
{
|
||||
"key": "Sb",
|
||||
"name": "B相视在功率",
|
||||
"addr": 50024,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": "va"
|
||||
},
|
||||
{
|
||||
"key": "Pfb",
|
||||
"name": "B相功率因数",
|
||||
"addr": 50025,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": ""
|
||||
},
|
||||
{
|
||||
"key": "EPb_H",
|
||||
"name": "B相有功电能高32位",
|
||||
"addr": 50026,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "1",
|
||||
"unit": "Wh"
|
||||
},
|
||||
{
|
||||
"key": "EPb_L",
|
||||
"name": "B相有功电能低32位",
|
||||
"addr": 50027,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "1",
|
||||
"unit": "Wh"
|
||||
},
|
||||
{
|
||||
"key": "EQb_H",
|
||||
"name": "B相无功电能高32位",
|
||||
"addr": 50028,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "1",
|
||||
"unit": "varh"
|
||||
},
|
||||
{
|
||||
"key": "EQb_L",
|
||||
"name": "B相无功电能低32位",
|
||||
"addr": 50029,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "1",
|
||||
"unit": "varh"
|
||||
},
|
||||
{
|
||||
"key": "Tb_1",
|
||||
"name": "B相进线温度",
|
||||
"addr": 50030,
|
||||
"len": 1,
|
||||
"dataType": "int32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.1",
|
||||
"unit": "℃"
|
||||
},
|
||||
{
|
||||
"key": "Tb_2",
|
||||
"name": "B相出线温度",
|
||||
"addr": 50031,
|
||||
"len": 1,
|
||||
"dataType": "int32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.1",
|
||||
"unit": "℃"
|
||||
},
|
||||
{
|
||||
"key": "Uc",
|
||||
"name": "C相电压",
|
||||
"addr": 50032,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.01",
|
||||
"unit": "V"
|
||||
},
|
||||
{
|
||||
"key": "Ic",
|
||||
"name": "C相电流",
|
||||
"addr": 50033,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": "A",
|
||||
"critical": "0.2"
|
||||
},
|
||||
{
|
||||
"key": "Pc",
|
||||
"name": "C相有功功率 ",
|
||||
"addr": 50034,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": "W"
|
||||
},
|
||||
{
|
||||
"key": "Qc",
|
||||
"name": "C相无功功率",
|
||||
"addr": 50035,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": "var"
|
||||
},
|
||||
{
|
||||
"key": "Sc",
|
||||
"name": "C相视在功率",
|
||||
"addr": 50036,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": "va"
|
||||
},
|
||||
{
|
||||
"key": "Pfc",
|
||||
"name": "C相功率因数",
|
||||
"addr": 50037,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": ""
|
||||
},
|
||||
{
|
||||
"key": "EPc_H",
|
||||
"name": "C相有功电能高32位",
|
||||
"addr": 50038,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "1",
|
||||
"unit": "Wh"
|
||||
},
|
||||
{
|
||||
"key": "EPc_L",
|
||||
"name": "C相有功电能低32位",
|
||||
"addr": 50039,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "1",
|
||||
"unit": "Wh"
|
||||
},
|
||||
{
|
||||
"key": "EQc_H",
|
||||
"name": "C相无功电能高32位",
|
||||
"addr": 50040,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "1",
|
||||
"unit": "varh"
|
||||
},
|
||||
{
|
||||
"key": "EQc_L",
|
||||
"name": "C相无功电能低32位",
|
||||
"addr": 50041,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "1",
|
||||
"unit": "varh"
|
||||
},
|
||||
{
|
||||
"key": "Tc_1",
|
||||
"name": "C相进线温度",
|
||||
"addr": 50042,
|
||||
"len": 1,
|
||||
"dataType": "int32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.1",
|
||||
"unit": "℃"
|
||||
},
|
||||
{
|
||||
"key": "Tc_2",
|
||||
"name": "C相出线温度",
|
||||
"addr": 50043,
|
||||
"len": 1,
|
||||
"dataType": "int32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.1",
|
||||
"unit": "℃"
|
||||
},
|
||||
{
|
||||
"key": "Usum",
|
||||
"name": "合相电压",
|
||||
"addr": 50044,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.01",
|
||||
"unit": "V"
|
||||
},
|
||||
{
|
||||
"key": "Isum",
|
||||
"name": "合相电流/剩余电流",
|
||||
"addr": 50045,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": "A",
|
||||
"critical": "0.2"
|
||||
},
|
||||
{
|
||||
"key": "Psum",
|
||||
"name": "合相有功功率",
|
||||
"addr": 50046,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": "W"
|
||||
},
|
||||
{
|
||||
"key": "Qsum",
|
||||
"name": "合相无功功率",
|
||||
"addr": 50047,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": "var"
|
||||
},
|
||||
{
|
||||
"key": "Ssum",
|
||||
"name": "RMS 合相视在功率",
|
||||
"addr": 50048,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": "va"
|
||||
},
|
||||
{
|
||||
"key": "Pfsum",
|
||||
"name": "RMS 合相功率因数",
|
||||
"addr": 50049,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "0.001",
|
||||
"unit": ""
|
||||
},
|
||||
{
|
||||
"key": "EPsum_H;",
|
||||
"name": "合相有功电能高32位",
|
||||
"addr": 50050,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "1",
|
||||
"unit": "Wh"
|
||||
},
|
||||
{
|
||||
"key": "EPsum_L;",
|
||||
"name": "合相有功电能低32位",
|
||||
"addr": 50051,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "1",
|
||||
"unit": "Wh"
|
||||
},
|
||||
{
|
||||
"key": "EQsum_H,;",
|
||||
"name": "合相无功电能高32位",
|
||||
"addr": 50052,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "1",
|
||||
"unit": "varh"
|
||||
},
|
||||
{
|
||||
"key": "EQsum_L;",
|
||||
"name": "合相无功电能低32位",
|
||||
"addr": 50053,
|
||||
"len": 1,
|
||||
"dataType": "uint32",
|
||||
"rwType": "R",
|
||||
"default": "0",
|
||||
"precision": "1",
|
||||
"unit": "varh"
|
||||
}
|
||||
]
|
|
@ -1,75 +1,229 @@
|
|||
import { app, shell, BrowserWindow, ipcMain } from 'electron'
|
||||
import { join } from 'path'
|
||||
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
|
||||
import icon from '../../resources/icon.png?asset'
|
||||
import { app, shell, BrowserWindow, ipcMain, globalShortcut, dialog } from 'electron';
|
||||
import { join } from 'path';
|
||||
import { electronApp, optimizer, is } from '@electron-toolkit/utils';
|
||||
import icon from '../../resources/icon.png?asset';
|
||||
|
||||
function createWindow() {
|
||||
// Create the browser window.
|
||||
const mainWindow = new BrowserWindow({
|
||||
width: 900,
|
||||
height: 670,
|
||||
show: false,
|
||||
autoHideMenuBar: true,
|
||||
...(process.platform === 'linux' ? { icon } : {}),
|
||||
webPreferences: {
|
||||
preload: join(__dirname, '../preload/index.js'),
|
||||
sandbox: false
|
||||
}
|
||||
})
|
||||
//开启调试
|
||||
// mainWindow.webContents.openDevTools()
|
||||
mainWindow.on('ready-to-show', () => {
|
||||
mainWindow.show()
|
||||
})
|
||||
//关闭exe命令
|
||||
function killProcessByName(processName) {
|
||||
const command = `taskkill /IM ${processName} /F`;
|
||||
const { exec } = require('child_process');
|
||||
|
||||
mainWindow.webContents.setWindowOpenHandler((details) => {
|
||||
shell.openExternal(details.url)
|
||||
return { action: 'deny' }
|
||||
})
|
||||
|
||||
// HMR for renderer base on electron-vite cli.
|
||||
// Load the remote URL for development or the local html file for production.
|
||||
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
|
||||
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
|
||||
} else {
|
||||
mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
|
||||
}
|
||||
exec(command, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
console.error(`执行的错误: ${error}`);
|
||||
return;
|
||||
}
|
||||
console.log(`stdout: ${stdout}`);
|
||||
console.error(`stderr: ${stderr}`);
|
||||
});
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(() => {
|
||||
// Set app user model id for windows
|
||||
electronApp.setAppUserModelId('com.electron')
|
||||
app.commandLine.appendSwitch('disable-web-security');
|
||||
function createWindow() {
|
||||
// Create the browser window.
|
||||
const mainWindow = new BrowserWindow({
|
||||
width: 1280,
|
||||
height: 1024,
|
||||
show: false,
|
||||
autoHideMenuBar: true,
|
||||
icon,
|
||||
webPreferences: {
|
||||
preload: join(__dirname, '../preload/index.js'),
|
||||
sandbox: false,
|
||||
nodeIntegration: true,
|
||||
// 禁用同源策略,允许跨域请求
|
||||
webSecurity: false,
|
||||
contextIsolation: false,
|
||||
// csp: "default-src 'self'; connect-src 'self' *",
|
||||
// 禁止build环境使用DevTool
|
||||
// devTools: is.dev ? true : false
|
||||
devTools: true
|
||||
}
|
||||
});
|
||||
//开发模式 开启调试
|
||||
if (is.dev) {
|
||||
mainWindow.webContents.openDevTools();
|
||||
}
|
||||
|
||||
// Default open or close DevTools by F12 in development
|
||||
// and ignore CommandOrControl + R in production.
|
||||
// see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
|
||||
app.on('browser-window-created', (_, window) => {
|
||||
optimizer.watchWindowShortcuts(window)
|
||||
})
|
||||
mainWindow.on('ready-to-show', () => {
|
||||
mainWindow.show();
|
||||
});
|
||||
|
||||
// IPC test
|
||||
ipcMain.on('ping', () => console.log('pong'))
|
||||
mainWindow.webContents.setWindowOpenHandler(details => {
|
||||
shell.openExternal(details.url);
|
||||
return { action: 'deny' };
|
||||
});
|
||||
//基于electronic-vite-cli的渲染器HMR。
|
||||
//加载用于开发的远程URL或用于生产的本地html文件。
|
||||
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
|
||||
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL']);
|
||||
} else {
|
||||
mainWindow.loadFile(join(__dirname, '../renderer/index.html'));
|
||||
}
|
||||
|
||||
createWindow()
|
||||
// 设置DevTools快捷键
|
||||
// 设置DevTools快捷键
|
||||
globalShortcut.register('CommandOrControl+Shift+i', function () {
|
||||
mainWindow.webContents.openDevTools();
|
||||
});
|
||||
return mainWindow;
|
||||
}
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
// 程序单例模式
|
||||
let myWindow = null;
|
||||
const gotTheLock = app.requestSingleInstanceLock();
|
||||
if (!gotTheLock) {
|
||||
// 如果已经有同样的该程序正在运行,则不启动
|
||||
app.quit();
|
||||
} else {
|
||||
// 如果检测到有同样的该程序正在试图启动...
|
||||
app.on('second-instance', () => {
|
||||
if (myWindow) {
|
||||
// 弹出系统提示对话框
|
||||
dialog.showMessageBox({
|
||||
message: '此程序已经正在运行'
|
||||
});
|
||||
// 如果该程序窗口处于最小化状态,则恢复窗口
|
||||
if (myWindow.isMinimized()) myWindow.restore();
|
||||
// 将该程序窗口置为当前聚焦态
|
||||
myWindow.focus();
|
||||
}
|
||||
});
|
||||
|
||||
// Quit when all windows are closed, except on macOS. There, it's common
|
||||
// for applications and their menu bar to stay active until the user quits
|
||||
// explicitly with Cmd + Q.
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
//当Electron完成时,将调用此方法
|
||||
//初始化并准备创建浏览器窗口。
|
||||
//某些API只能在此事件发生后使用。
|
||||
const { spawn } = require('child_process');
|
||||
let child = null;
|
||||
let exePluginsExeList = [];
|
||||
app.whenReady().then(() => {
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// In this file you can include the rest of your app"s specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
const logStream = fs.createWriteStream('app.log', { flags: 'a' }); // 日志文件
|
||||
let exePath = path.resolve('./resources/app.asar.unpacked/resources/service');
|
||||
let exePluginsPath = path.resolve('./resources/app.asar.unpacked/resources/service/plugins');
|
||||
//单独配置测试环境
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
exePath = path.resolve('./resources/service');
|
||||
exePluginsPath = path.resolve('./resources/service/plugins');
|
||||
}
|
||||
|
||||
//查询所有插件目录下的exe文件
|
||||
fs.readdir(exePluginsPath, (err, files) => {
|
||||
if (err) {
|
||||
return console.log('Unable to scan directory: ' + err);
|
||||
}
|
||||
// 筛选出以.exe结尾的文件
|
||||
exePluginsExeList = files.filter(file => path.extname(file).toLowerCase() === '.exe');
|
||||
});
|
||||
const userDataPath = app.getPath('userData');
|
||||
child = spawn('./main.exe', ['--args', userDataPath], { cwd: exePath, stdio: ['ignore', 'pipe', 'pipe'] });
|
||||
|
||||
//监听进程的输出
|
||||
child.stdout.on('data', data => {
|
||||
console.log('stdout:', data.toString());
|
||||
logStream.write(data);
|
||||
});
|
||||
|
||||
child.stderr.on('data', data => {
|
||||
console.error('stderr:', data.toString());
|
||||
logStream.write(data);
|
||||
});
|
||||
|
||||
child.on('close', code => {
|
||||
console.log(`子进程已退出,退出码 ${code}`);
|
||||
logStream.end();
|
||||
});
|
||||
|
||||
child.on('exit', (code, signal) => {
|
||||
console.log(`子进程已退出,退出码 ${code},信号: ${signal}`);
|
||||
logStream.write(`子进程已退出,退出码 ${code},信号: ${signal}`);
|
||||
logStream.end();
|
||||
});
|
||||
|
||||
// Set app user model id for windows
|
||||
electronApp.setAppUserModelId('com.electron');
|
||||
|
||||
//开发中默认按F12打开或关闭DevTools
|
||||
//在生产中忽略CommandOrControl+R。
|
||||
//看https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
|
||||
app.on('browser-window-created', (_, window) => {
|
||||
optimizer.watchWindowShortcuts(window);
|
||||
});
|
||||
|
||||
// IPC test
|
||||
ipcMain.on('ping', () => console.log('pong'));
|
||||
|
||||
myWindow = createWindow();
|
||||
|
||||
app.on('activate', function () {
|
||||
//在macOS上,当出现以下情况时,通常会在应用程序中重新创建窗口
|
||||
//单击dock图标后,没有其他打开的窗口。
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow();
|
||||
});
|
||||
});
|
||||
|
||||
// 处理来自渲染进程的请求
|
||||
// ipcMain.handle('readFile', async (event, path) => {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// fs.readFile(join(__dirname, path), 'utf8', (err, data) => {
|
||||
// if (err) {
|
||||
// reject(err);
|
||||
// } else {
|
||||
// resolve(data);
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// ipcMain.handle('writeFile', async (event, path, content) => {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// fs.writeFile(join(__dirname, path), content, 'utf8', (err) => {
|
||||
// if (err) {
|
||||
// reject(err);
|
||||
// } else {
|
||||
// resolve();
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// // 处理来自渲染进程的请求
|
||||
// ipcMain.handle('readDirectory', async (event, directoryPath) => {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// fs.readdir(join(__dirname, directoryPath), (err, files) => {
|
||||
// if (err) {
|
||||
// reject(err);
|
||||
// } else {
|
||||
// resolve(files);
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
//关闭所有窗口后退出,macOS除外。在那里,这很常见
|
||||
//让应用程序及其菜单栏保持活动状态,直到用户退出
|
||||
//显式使用Cmd+Q。
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
// 循环关闭插件 EXE 列表
|
||||
exePluginsExeList.forEach(exe => {
|
||||
killProcessByName(exe);
|
||||
});
|
||||
// child.kill('SIGTERM'); // 或者使用 'SIGKILL' 来强制关闭
|
||||
// killProcessByName('gateway.exe');
|
||||
// 循环关闭后端服务
|
||||
killProcessByName('main.exe');
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//在此文件中,您可以包含应用程序的其他特定主进程
|
||||
//代码。您也可以将它们放在单独的文件中,并在此处要求它们。
|
||||
|
||||
//获取应用程序版本
|
||||
ipcMain.handle('get-app-version', () => {
|
||||
return app.getVersion();
|
||||
});
|
||||
|
|
|
@ -1,20 +1,103 @@
|
|||
import { contextBridge } from 'electron'
|
||||
import { contextBridge, ipcRenderer } from 'electron'
|
||||
import { electronAPI } from '@electron-toolkit/preload'
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { shell } = require('electron');
|
||||
|
||||
// Custom APIs for renderer
|
||||
const api = {}
|
||||
// 自定义的主进程方法API
|
||||
// const api = {
|
||||
// readFile: async (path) => {
|
||||
// const result = await ipcRenderer.invoke('readFile', path);
|
||||
// return result;
|
||||
// },
|
||||
// writeFile: async (path, content) => {
|
||||
// await ipcRenderer.invoke('writeFile', path, content);
|
||||
// },
|
||||
// readDirectory: async (directoryPath) => {
|
||||
// const result = await ipcRenderer.invoke('readDirectory', directoryPath);
|
||||
// return result;
|
||||
// }
|
||||
// }
|
||||
// // 暴露获取版本号的方法
|
||||
// ipcMain.handle('get-app-version', () => {
|
||||
// return app.getVersion(); // 返回当前应用版本(来自 package.json)
|
||||
// });
|
||||
|
||||
// 获取config.js的绝对路径
|
||||
function getConfigPath() {
|
||||
// __dirname 是 win-unpacked/resources/app
|
||||
|
||||
let configPath = path.resolve('./resources/app.asar.unpacked/resources/config/config.js');
|
||||
//单独配置测试环境
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
configPath = path.resolve('./resources/config/config.js');
|
||||
}
|
||||
|
||||
return configPath;
|
||||
}
|
||||
|
||||
function getExportPath() {
|
||||
// __dirname 是 win-unpacked/resources/app
|
||||
|
||||
let configPath = path.resolve('./resources/app.asar.unpacked/resources/service');
|
||||
//单独配置测试环境
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
configPath = path.resolve('./resources/service');
|
||||
}
|
||||
|
||||
return configPath;
|
||||
}
|
||||
|
||||
|
||||
// Use `contextBridge` APIs to expose Electron APIs to
|
||||
// renderer only if context isolation is enabled, otherwise
|
||||
// just add to the DOM global.
|
||||
// 使用contextBridge将Electron API和自定义的主进程方法API暴露给渲染进程页面。
|
||||
if (process.contextIsolated) {
|
||||
try {
|
||||
contextBridge.exposeInMainWorld('electron', electronAPI)
|
||||
contextBridge.exposeInMainWorld('api', api)
|
||||
contextBridge.exposeInMainWorld('electron', {
|
||||
...electronAPI,
|
||||
getAppVersion: async () => {
|
||||
return await ipcRenderer.invoke('get-app-version');
|
||||
},
|
||||
readConfig: () => {
|
||||
const configPath = getConfigPath();
|
||||
if (fs.existsSync(configPath)) {
|
||||
// 用require动态加载,确保每次都是最新内容
|
||||
delete require.cache[require.resolve(configPath)];
|
||||
return require(configPath);
|
||||
}
|
||||
return {};
|
||||
},
|
||||
shell: {
|
||||
openPath: shell.openPath
|
||||
},
|
||||
exePath: getExportPath()
|
||||
})
|
||||
// contextBridge.exposeInMainWorld('api', api)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
} else {
|
||||
window.electron = electronAPI
|
||||
window.api = api
|
||||
window.electron = {
|
||||
...electronAPI,
|
||||
getAppVersion: async () => {
|
||||
return await ipcRenderer.invoke('get-app-version');
|
||||
},
|
||||
readConfig: () => {
|
||||
const configPath = getConfigPath();
|
||||
if (fs.existsSync(configPath)) {
|
||||
// 用require动态加载,确保每次都是最新内容
|
||||
delete require.cache[require.resolve(configPath)];
|
||||
return require(configPath);
|
||||
}
|
||||
return {};
|
||||
},
|
||||
shell: {
|
||||
openPath: shell.openPath
|
||||
},
|
||||
exePath: getExportPath()
|
||||
}
|
||||
// window.api = api
|
||||
}
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Electron</title>
|
||||
<title>谷云校表产测</title>
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:"
|
||||
/>
|
||||
<link rel="stylesheet" href="/src/assets/iconfont/iconfont.css">
|
||||
<!-- <meta-->
|
||||
<!-- http-equiv="Content-Security-Policy"-->
|
||||
<!-- content="default-src 'self'; connect-src 'self' *; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:"-->
|
||||
<!-- />-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -1,11 +1,52 @@
|
|||
<script setup>
|
||||
import { RouterView } from "vue-router"
|
||||
import { RouterView } from 'vue-router'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RouterView></RouterView>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<style lang="scss">
|
||||
:root {
|
||||
--el-input-height: 36px;
|
||||
--el-color-primary: #0066cc;
|
||||
--el-fill-color-blank: #e6e6e6;
|
||||
--el-disabled-bg-color: #f7f7f7;
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
}
|
||||
|
||||
</script>
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 5px;
|
||||
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
|
||||
background: #ddd;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
width: 5px;
|
||||
}
|
||||
/*全局覆盖样式*/
|
||||
.el-collapse-item {
|
||||
color: #333333;
|
||||
.el-collapse-item__header {
|
||||
font-family: Source Han Sans CN;
|
||||
background: #e6e6e6;
|
||||
padding: 0 30px;
|
||||
color: #333333;
|
||||
font-size: 16px;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
font-weight: 500;
|
||||
&.is-active {
|
||||
color: #0066cc;
|
||||
}
|
||||
}
|
||||
.el-collapse-item__wrap {
|
||||
background-color: #f2f2f2 !important;
|
||||
}
|
||||
.el-input__wrapper {
|
||||
background: #e6e6e6;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 4622943 */
|
||||
src: url('iconfont.woff2?t=1753694081375') format('woff2'),
|
||||
url('iconfont.woff?t=1753694081375') format('woff'),
|
||||
url('iconfont.ttf?t=1753694081375') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-zhakai:before {
|
||||
content: "\e797";
|
||||
}
|
||||
|
||||
.icon-zhahe:before {
|
||||
content: "\e798";
|
||||
}
|
||||
|
||||
.icon-kuaijiejian:before {
|
||||
content: "\e603";
|
||||
}
|
||||
|
||||
.icon-sousuo:before {
|
||||
content: "\e60e";
|
||||
}
|
||||
|
||||
.icon-xwtubiaoku-13:before {
|
||||
content: "\e61a";
|
||||
}
|
||||
|
||||
.icon-xwtubiaoku-15:before {
|
||||
content: "\e61d";
|
||||
}
|
||||
|
||||
.icon-rizhi:before {
|
||||
content: "\e61c";
|
||||
}
|
||||
|
||||
.icon-bug:before {
|
||||
content: "\e725";
|
||||
}
|
||||
|
||||
.icon-caozuorizhi:before {
|
||||
content: "\e610";
|
||||
}
|
||||
|
||||
.icon-rizhishenji:before {
|
||||
content: "\e666";
|
||||
}
|
||||
|
||||
.icon-chenggong:before {
|
||||
content: "\e615";
|
||||
}
|
||||
|
||||
.icon-rizhi1:before {
|
||||
content: "\e613";
|
||||
}
|
||||
|
||||
.icon-chenggong1:before {
|
||||
content: "\e616";
|
||||
}
|
||||
|
||||
.icon-bug-fill:before {
|
||||
content: "\e773";
|
||||
}
|
||||
|
||||
.icon-bug-line:before {
|
||||
content: "\e774";
|
||||
}
|
||||
|
||||
.icon-kongtiaoguizhuduanluqiAA:before {
|
||||
content: "\e68e";
|
||||
}
|
||||
|
||||
.icon--_saomaqiang:before {
|
||||
content: "\e640";
|
||||
}
|
||||
|
||||
.icon-qianzhaoyiqibiaoding:before {
|
||||
content: "\e633";
|
||||
}
|
||||
|
||||
.icon-zuobiaobiaoding:before {
|
||||
content: "\e602";
|
||||
}
|
||||
|
||||
.icon-com001:before {
|
||||
content: "\e62c";
|
||||
}
|
||||
|
||||
.icon-chuankou:before {
|
||||
content: "\e6be";
|
||||
}
|
||||
|
||||
.icon-chuankou1:before {
|
||||
content: "\e60a";
|
||||
}
|
||||
|
||||
.icon-chuankoushezhi:before {
|
||||
content: "\e600";
|
||||
}
|
||||
|
||||
.icon-chuankou2:before {
|
||||
content: "\e6fc";
|
||||
}
|
||||
|
||||
.icon-shousuoshangjiantou:before {
|
||||
content: "\e9b6";
|
||||
}
|
||||
|
||||
.icon-up-arrow:before {
|
||||
content: "\e9c1";
|
||||
}
|
||||
|
||||
.icon-unlock:before {
|
||||
content: "\e882";
|
||||
}
|
||||
|
||||
.icon-gexinghuabobao:before {
|
||||
content: "\e66d";
|
||||
}
|
||||
|
||||
.icon-icon_suoding:before {
|
||||
content: "\e76c";
|
||||
}
|
||||
|
||||
.icon-icon_shanchu:before {
|
||||
content: "\e76d";
|
||||
}
|
||||
|
||||
.icon-icon_shanghang:before {
|
||||
content: "\e76e";
|
||||
}
|
||||
|
||||
.icon-icon_xiahang:before {
|
||||
content: "\e76f";
|
||||
}
|
||||
|
||||
.icon-icon_shezhi:before {
|
||||
content: "\e770";
|
||||
}
|
||||
|
||||
.icon-icon_xitong:before {
|
||||
content: "\e771";
|
||||
}
|
||||
|
||||
.icon-icon_jiankong:before {
|
||||
content: "\e772";
|
||||
}
|
||||
|
||||
.icon-icon_duanluqi2:before {
|
||||
content: "\e9c2";
|
||||
}
|
||||
|
||||
.icon-icon_caid:before {
|
||||
content: "\e75f";
|
||||
}
|
||||
|
||||
.icon-icon_chajian:before {
|
||||
content: "\e767";
|
||||
}
|
||||
|
||||
.icon-icon_xiaoxi:before {
|
||||
content: "\e768";
|
||||
}
|
||||
|
||||
.icon-icon_gengxin:before {
|
||||
content: "\e769";
|
||||
}
|
||||
|
||||
.icon-icon_fuzhi:before {
|
||||
content: "\e76a";
|
||||
}
|
||||
|
||||
.icon-icon_duanluqi:before {
|
||||
content: "\e76b";
|
||||
}
|
||||
|
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 45 KiB |
|
@ -31,7 +31,8 @@ code {
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
margin-bottom: 80px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.logo {
|
||||
|
|
|
@ -13,13 +13,13 @@ const settings = defineProps({
|
|||
<el-aside :width="settings.width">
|
||||
<el-scrollbar>
|
||||
<el-menu
|
||||
:default-openeds="['1', '3']"
|
||||
default-active="/switch"
|
||||
:collapse="settings.collapse"
|
||||
router="true"
|
||||
:router="true"
|
||||
>
|
||||
<el-menu-item index="/versions"><el-icon> <House /> </el-icon>首页</el-menu-item>
|
||||
<el-menu-item index="/about"><el-icon> <Menu /> </el-icon>文章管理列表</el-menu-item>
|
||||
<el-menu-item index="/test"><el-icon> <Menu /> </el-icon>测试</el-menu-item>
|
||||
<el-menu-item index="/switch"><el-icon> <Connection /> </el-icon>断路器调试</el-menu-item>
|
||||
<!-- <el-menu-item index="/about"><el-icon> <Menu /> </el-icon>文章管理列表</el-menu-item>-->
|
||||
<!-- <el-menu-item index="/test"><el-icon> <Menu /> </el-icon>测试</el-menu-item>-->
|
||||
</el-menu>
|
||||
</el-scrollbar>
|
||||
</el-aside>
|
||||
|
@ -29,7 +29,23 @@ const settings = defineProps({
|
|||
.el-aside {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
box-shadow: var(--el-box-shadow-lighter);
|
||||
border-right: 1px solid #e6e6e6;
|
||||
background-color: #f6f6f6;
|
||||
padding-top: 10px;
|
||||
}
|
||||
.el-menu{
|
||||
background: #f6f6f6;
|
||||
padding: 0 10px;
|
||||
}
|
||||
.el-menu-item{
|
||||
border-radius: 10px;
|
||||
/*padding-left: 5px !important;*/
|
||||
}
|
||||
.el-menu-item.is-active{
|
||||
background: #c8cde4;
|
||||
border-radius: 10px;
|
||||
/*margin: 0 10px;*/
|
||||
color: #0066cc;
|
||||
}
|
||||
|
||||
.el-scrollbar {
|
||||
|
|
|
@ -5,9 +5,5 @@ const versions = reactive({ ...window.electron.process.versions })
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ul class="versions">
|
||||
<li class="electron-version">Electron v{{ versions.electron }}</li>
|
||||
<li class="chrome-version">Chromium v{{ versions.chrome }}</li>
|
||||
<li class="node-version">Node v{{ versions.node }}</li>
|
||||
</ul>
|
||||
view
|
||||
</template>
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<template>
|
||||
<el-container direction="vertical" style="height: 100%; width: 100%; ">
|
||||
<el-main>
|
||||
<router-view v-slot="{ Component }">
|
||||
<keep-alive>
|
||||
<component :is="Component" />
|
||||
</keep-alive>
|
||||
</router-view>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
// 组件注册
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
body {
|
||||
background-color: #eee;
|
||||
max-width: 100vw;
|
||||
}
|
||||
.el-container {
|
||||
/*padding: 10px 0;*/
|
||||
}
|
||||
.el-main {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
/*height: 100vh;*/
|
||||
overflow-x: hidden;
|
||||
background: #fff;
|
||||
/*padding-right: 10px;*/
|
||||
}
|
||||
</style>
|
|
@ -2,21 +2,26 @@ import '@renderer/assets/main.css'
|
|||
|
||||
import { createPinia } from 'pinia'
|
||||
import { createApp } from 'vue'
|
||||
import dayjs from 'dayjs'
|
||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||
import ElementPlus from 'element-plus'
|
||||
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
||||
import 'element-plus/dist/index.css'
|
||||
|
||||
import App from '@renderer/App.vue'
|
||||
import router from '@renderer/router'
|
||||
|
||||
const app = createApp(App)
|
||||
app.config.globalProperties.$dayjs = dayjs
|
||||
|
||||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||
app.component(key, component)
|
||||
}
|
||||
|
||||
app.use(createPinia())
|
||||
app.use(ElementPlus)
|
||||
app.use(ElementPlus, {
|
||||
locale: zhCn,
|
||||
})
|
||||
app.use(router)
|
||||
|
||||
app.mount('#app')
|
||||
|
|
|
@ -1,46 +1,32 @@
|
|||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import HomeView from '@renderer/views/HomeView.vue'
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
import Layout from '@renderer/layout/index.vue';
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
name: 'home',
|
||||
component: HomeView,
|
||||
redirect: {name: 'versions'},
|
||||
children:[
|
||||
{
|
||||
path: 'versions',
|
||||
name: 'versions',
|
||||
component: () => import("@renderer/components/Versions.vue"),
|
||||
meta: {
|
||||
menu: 'versions',
|
||||
keepAlive: true,
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'about',
|
||||
name: 'about',
|
||||
component: () => import("@renderer/views/AboutView.vue"),
|
||||
meta: {
|
||||
menu: 'about',
|
||||
keepAlive: true,
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'test',
|
||||
name: 'test',
|
||||
component: () => import("@renderer/views/test.vue"),
|
||||
meta: {
|
||||
menu: 'test',
|
||||
keepAlive: true,
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{ path: '/:pathMatch(.*)', redirect: '/' },
|
||||
]
|
||||
})
|
||||
history: createWebHistory(),
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
component: Layout,
|
||||
meta: { title: '整体页面布局' },
|
||||
redirect: '/calibration',
|
||||
children: [
|
||||
{
|
||||
path: 'calibration',
|
||||
name: 'calibration',
|
||||
component: () => import('@renderer/views/calibration/index.vue'),
|
||||
meta: {
|
||||
menu: 'calibration',
|
||||
keepAlive: true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/', // 这个是根路由,现在我们让它重定向到 /system
|
||||
redirect: '/calibration'
|
||||
},
|
||||
{ path: '/:pathMatch(.*)', redirect: '/' }
|
||||
]
|
||||
});
|
||||
|
||||
export default router
|
||||
export default router;
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
import { defineStore } from 'pinia'
|
||||
// import config from '@renderer/util/config.js'
|
||||
const config = window.electron.readConfig();
|
||||
|
||||
// 定义一个名为logWebSocketStore的store,用于管理WebSocket连接的状态和操作
|
||||
export const logWebSocketStore = defineStore('websocket', {
|
||||
state: () => ({
|
||||
websocket: null, // WebSocket实例
|
||||
connectURL: config.wsUrl + '/ws/log', // WebSocket连接的URL
|
||||
socket_open: false, // 标记WebSocket是否连接
|
||||
hearbeat_timer: null, // 心跳检测的定时器
|
||||
hearbeat_interval: 2 * 1000, // 心跳检测的间隔时间
|
||||
is_reonnect: true, // 是否尝试重新连接
|
||||
reconnect_count: 3, // 最大重连次数
|
||||
reconnect_current: 1, // 当前重连次数
|
||||
reconnect_timer: null, // 重连定时器
|
||||
reconnect_interval: 5 * 1000, // 重连间隔时间
|
||||
}),
|
||||
|
||||
actions: {
|
||||
// 初始化WebSocket连接
|
||||
init(overrideReceiveMessage) {
|
||||
let receiveMessage = overrideReceiveMessage || (() => {})
|
||||
// 检查浏览器是否支持WebSocket
|
||||
if (!('WebSocket' in window)) {
|
||||
this.$router.push({ name: 'ErrorPage', params: { error: '浏览器不支持WebSocket' } })
|
||||
return null
|
||||
}
|
||||
// 创建WebSocket实例并设置事件处理函数
|
||||
this.websocket = new WebSocket(this.connectURL)
|
||||
this.websocket.onmessage = (e) => {
|
||||
receiveMessage(e)
|
||||
}
|
||||
this.websocket.onclose = () => {
|
||||
console.log('socket连接关闭----------------------')
|
||||
this.socket_open = false
|
||||
// 尝试重新连接
|
||||
if (this.is_reonnect) {
|
||||
this.reconnect_timer = setTimeout(() => {
|
||||
if (this.reconnect_current > this.reconnect_count) {
|
||||
clearTimeout(this.reconnect_timer)
|
||||
this.is_reonnect = false
|
||||
return
|
||||
}
|
||||
console.log('socket重连次数:' + this.reconnect_current)
|
||||
this.reconnect_current++
|
||||
this.reconnect()
|
||||
}, this.reconnect_interval)
|
||||
}
|
||||
}
|
||||
this.websocket.onopen = () => {
|
||||
this.socket_open = true
|
||||
this.is_reonnect = true
|
||||
// this.heartbeat()
|
||||
}
|
||||
this.websocket.onerror = () => {}
|
||||
},
|
||||
|
||||
// 发送心跳包
|
||||
heartbeat() {
|
||||
this.hearbeat_timer && clearInterval(this.hearbeat_timer)
|
||||
this.hearbeat_timer = setInterval(() => {
|
||||
let data = {}
|
||||
this.send(data)
|
||||
}, this.hearbeat_interval)
|
||||
},
|
||||
|
||||
// 发送数据
|
||||
send(data, callback = null) {
|
||||
// 如果WebSocket连接已建立,则发送数据
|
||||
if (this.websocket.readyState === this.websocket.OPEN) {
|
||||
this.websocket.send(JSON.stringify(data))
|
||||
callback && callback()
|
||||
} else {
|
||||
// 如果WebSocket连接断开,则跳转到错误页面
|
||||
clearInterval(this.hearbeat_timer)
|
||||
this.$router.push({ name: 'ErrorPage', params: { error: 'socket链接已断开' } })
|
||||
}
|
||||
},
|
||||
|
||||
// 关闭WebSocket连接
|
||||
close() {
|
||||
this.is_reonnect = false
|
||||
this.websocket.close()
|
||||
},
|
||||
|
||||
// 重新连接WebSocket
|
||||
reconnect() {
|
||||
// 如果已存在WebSocket实例且不尝试重新连接,则关闭连接
|
||||
if (this.websocket && !this.is_reonnect) {
|
||||
this.close()
|
||||
}
|
||||
// 初始化WebSocket连接
|
||||
this.init()
|
||||
},
|
||||
},
|
||||
})
|
|
@ -0,0 +1,18 @@
|
|||
import { defineStore } from 'pinia';
|
||||
|
||||
export const useSerialPortStore = defineStore('seralPort', {
|
||||
state: () => ({
|
||||
serialport: {
|
||||
port: '',
|
||||
baudrate: 115200,
|
||||
databits: 8,
|
||||
parity: 0,
|
||||
stopbits: 0
|
||||
}
|
||||
}),
|
||||
actions: {
|
||||
setSerialport(data) {
|
||||
this.serialport = data;
|
||||
}
|
||||
}
|
||||
});
|
|
@ -0,0 +1,42 @@
|
|||
// // // 手动配置的地址
|
||||
// window.config = {
|
||||
// url: 'http://192.168.1.17:8000',
|
||||
// wsUrl: 'ws://192.168.1.17:8000',
|
||||
// ws1Url: 'ws://192.168.1.17:8001',
|
||||
// }
|
||||
|
||||
// 手动配置的地址
|
||||
// window.config = {
|
||||
// url: 'http://127.0.0.1:8000',
|
||||
// wsUrl: 'ws://127.0.0.1:8000',
|
||||
// }
|
||||
|
||||
// export default {
|
||||
// url: 'http://127.0.0.1:8000',
|
||||
// wsUrl: 'ws://127.0.0.1:8000'
|
||||
// }
|
||||
|
||||
export default {
|
||||
// url: 'http://127.0.0.1:8000',
|
||||
// wsUrl: 'ws://127.0.0.1:8000',
|
||||
// swichWsUrl: 'ws://127.0.0.1:8001',
|
||||
// serialPortUrl: 'http://127.0.0.1:8000',
|
||||
|
||||
url: 'http://192.168.1.17:8000',
|
||||
wsUrl: 'ws://192.168.1.17:8000',
|
||||
swichWsUrl: 'ws://192.168.1.17:8001',
|
||||
serialPortUrl: 'http://192.168.1.17:8000',
|
||||
|
||||
// 远程连接串口使用
|
||||
// serialPortUrl: 'http://120.77.172.42:7202',
|
||||
// serialPortUrl: 'http://192.168.1.17:8888',
|
||||
}
|
||||
|
||||
|
||||
// 手动配置的地址
|
||||
// export default {
|
||||
// url: 'http://192.168.1.17:8000',
|
||||
// wsUrl: 'ws://192.168.1.17:8000',
|
||||
// swichWsUrl: 'ws://192.168.1.17:8001',
|
||||
// serialPortUrl: 'http://192.168.1.17:8000',
|
||||
// }
|
|
@ -0,0 +1,6 @@
|
|||
export function guidGenerator() {
|
||||
var S4 = function() {
|
||||
return ((1 + Math.random())*0X10000|0).toString(16).substring(1);
|
||||
};
|
||||
return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
import { ElMessage as message } from 'element-plus'
|
||||
// import storage from 'store'
|
||||
// import config from '@renderer/util/config.js'
|
||||
const config = window.electron.readConfig();
|
||||
let receiveMessage = null
|
||||
import { reactive } from 'vue'
|
||||
const socket = reactive({
|
||||
websocket: null,
|
||||
connectURL: config.swichWsUrl + '/ws/log',
|
||||
// 开启标识
|
||||
socket_open: false,
|
||||
// 心跳timer
|
||||
hearbeat_timer: null,
|
||||
// 心跳发送频率
|
||||
hearbeat_interval: 2 * 1000,
|
||||
// 是否自动重连
|
||||
is_reonnect: true,
|
||||
// 重连次数
|
||||
reconnect_count: 3,
|
||||
// 已发起重连次数
|
||||
reconnect_current: 1,
|
||||
// 重连timer
|
||||
reconnect_timer: null,
|
||||
// 重连频率
|
||||
reconnect_interval: 5 * 1000,
|
||||
init: (overrideReceiveMessage) => {
|
||||
if (overrideReceiveMessage) {
|
||||
receiveMessage = overrideReceiveMessage
|
||||
}
|
||||
if (!('WebSocket' in window)) {
|
||||
message.warning('浏览器不支持WebSocket')
|
||||
return null
|
||||
}
|
||||
socket.websocket = new WebSocket(socket.connectURL)
|
||||
socket.websocket.onmessage = (e) => {
|
||||
if (receiveMessage) {
|
||||
receiveMessage(e)
|
||||
}
|
||||
}
|
||||
socket.websocket.onclose = () => {
|
||||
console.log('socket连接关闭----------------------')
|
||||
socket.socket_open = false
|
||||
// 需要重新连接
|
||||
if (socket.is_reonnect) {
|
||||
socket.reconnect_timer = setTimeout(() => {
|
||||
// 超过重连次数
|
||||
if (socket.reconnect_current > socket.reconnect_count) {
|
||||
clearTimeout(socket.reconnect_timer)
|
||||
socket.is_reonnect = false
|
||||
return
|
||||
}
|
||||
console.log('socket重连次数:' + socket.reconnect_current)
|
||||
// 记录重连次数
|
||||
socket.reconnect_current++
|
||||
socket.reconnect()
|
||||
}, socket.reconnect_interval)
|
||||
}
|
||||
}
|
||||
// 连接成功
|
||||
socket.websocket.onopen = function () {
|
||||
socket.socket_open = true
|
||||
socket.is_reonnect = true
|
||||
// 开启心跳
|
||||
// socket.heartbeat()
|
||||
}
|
||||
// 连接发生错误
|
||||
socket.websocket.onerror = function () {}
|
||||
},
|
||||
heartbeat: () => {
|
||||
socket.hearbeat_timer && clearInterval(socket.hearbeat_timer)
|
||||
|
||||
socket.hearbeat_timer = setInterval(() => {
|
||||
let data = {
|
||||
// token: storage.get('token')
|
||||
}
|
||||
socket.send(data)
|
||||
}, socket.hearbeat_interval)
|
||||
},
|
||||
send: (data, callback = null) => {
|
||||
// 开启状态直接发送
|
||||
if (socket.websocket.readyState === socket.websocket.OPEN) {
|
||||
socket.websocket.send(JSON.stringify(data))
|
||||
callback && callback()
|
||||
} else {
|
||||
clearInterval(socket.hearbeat_timer)
|
||||
message({
|
||||
type: 'warning',
|
||||
message: 'socket链接已断开',
|
||||
duration: 1000
|
||||
})
|
||||
}
|
||||
},
|
||||
close: () => {
|
||||
socket.is_reonnect = false
|
||||
socket.websocket.close()
|
||||
},
|
||||
/**
|
||||
* 重新连接
|
||||
*/
|
||||
reconnect: () => {
|
||||
if (socket.websocket && !socket.is_reonnect) {
|
||||
socket.close()
|
||||
}
|
||||
socket.init(receiveMessage)
|
||||
}
|
||||
})
|
||||
export default socket
|
|
@ -1,15 +0,0 @@
|
|||
<template>
|
||||
<div class="about">
|
||||
<h1>This is an about page</h1>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
@media (min-width: 1024px) {
|
||||
.about {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,59 +0,0 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
|
||||
// 组件注册
|
||||
import Header from '@renderer/components/Header.vue'
|
||||
|
||||
import Aside from '@renderer/components/Aside.vue'
|
||||
|
||||
|
||||
|
||||
const asideSettings = ref({
|
||||
isCollapse:true,
|
||||
width:'200'
|
||||
})
|
||||
|
||||
// 给子组件绑定事件,通过子组件emit从而改变父组件的值
|
||||
const changeAside = ()=>{
|
||||
asideSettings.value.isCollapse = !asideSettings.value.isCollapse
|
||||
if(asideSettings.value.isCollapse){
|
||||
asideSettings.value.width = "64"
|
||||
}else{
|
||||
asideSettings.value.width = "200"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<el-container direction="vertical" style="min-height: 100vh;min-width: 100vw;overflow: hidden;">
|
||||
<Header></Header>
|
||||
<el-container >
|
||||
<Aside :width="200"></Aside>
|
||||
<el-main>
|
||||
<RouterView/>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
<style scoped>
|
||||
|
||||
body{
|
||||
background-color: #eee;
|
||||
max-width: 100vw;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.el-main {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
height: 100vh;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,296 @@
|
|||
/*
|
||||
* @Descripttion:
|
||||
* @version:
|
||||
* @Author: lfzxs@qq.com
|
||||
* @Date: 2024-10-16 13:52:11
|
||||
* @LastEditors: lfzxs@qq.com
|
||||
* @LastEditTime: 2024-10-18 16:33:31
|
||||
*/
|
||||
|
||||
export function buildHead(d_length,d_remote_id,d_local_id,d_cmd,d_dev_type,d_data_type,dataStart,dataLength,dataValue,activeData) {
|
||||
// 初始化data为一个32位2进制数
|
||||
|
||||
let data = "0000" + d_data_type + d_dev_type + d_cmd + toBinaryString(d_local_id,9) + toBinaryString(d_remote_id,9) + d_length;
|
||||
|
||||
console.log("获取头部",data);
|
||||
|
||||
let hex_data = binaryToHex(data);
|
||||
let dataBuffer = '';
|
||||
let buffer = hexToBuffer(hex_data);
|
||||
//根据d_cmd的值拼接命令格式
|
||||
switch (d_cmd) {
|
||||
case "0000"://特殊指令
|
||||
break;
|
||||
case "0011"://地址读
|
||||
buffer = concatenateBuffers(htonl(buffer),htonl(toFixedSizeBuffer(parseInt(dataStart),4)),htonl(toFixedSizeBuffer(parseInt(dataLength),4)));
|
||||
break;
|
||||
case "0100"://地址写
|
||||
|
||||
if(activeData.dataType === 'hex'){
|
||||
dataValue = rearrangeHexStr(dataValue);
|
||||
dataBuffer = hexToBuffer(dataValue);
|
||||
}else if(activeData.dataType === 'hexString'){
|
||||
dataBuffer = hexToBuffer(dataValue);
|
||||
}else{
|
||||
dataBuffer = stringToHexBuffer(dataValue,dataLength*4*2);
|
||||
}
|
||||
console.log("dataBuffer",dataBuffer)
|
||||
buffer = concatenateBuffers(htonl(buffer),htonl(toFixedSizeBuffer(parseInt(dataStart),4)),htonl(toFixedSizeBuffer(parseInt(dataLength),4)),dataBuffer)
|
||||
break;
|
||||
}
|
||||
console.log("dataValue-buffer",dataValue,buffer)
|
||||
|
||||
let result = bufferToHex(buffer);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function allBuildHead(d_length,d_remote_id,d_local_id,d_cmd,d_dev_type,d_data_type,dataStart,dataLength,dataValue,allList) {
|
||||
// 初始化data为一个32位2进制数
|
||||
|
||||
let data = "0000" + d_data_type + d_dev_type + d_cmd + toBinaryString(d_local_id,9) + toBinaryString(d_remote_id,9) + d_length;
|
||||
|
||||
console.log("获取头部",data);
|
||||
|
||||
let hex_data = binaryToHex(data);
|
||||
|
||||
let buffer = hexToBuffer(hex_data);
|
||||
let allBufferList = [];
|
||||
//根据d_cmd的值拼接命令格式
|
||||
switch (d_cmd) {
|
||||
case "0000"://特殊指令
|
||||
break;
|
||||
case "0011"://地址读
|
||||
buffer = concatenateBuffers(htonl(buffer),htonl(toFixedSizeBuffer(parseInt(dataStart),4)),htonl(toFixedSizeBuffer(parseInt(dataLength),4)));
|
||||
break;
|
||||
case "0100"://地址写
|
||||
allBufferList = allList.map(item=>{
|
||||
return stringToHexBuffer(item.inputValue,item.lengthValue*4*2);
|
||||
})
|
||||
buffer = concatenateBuffers(htonl(buffer),htonl(toFixedSizeBuffer(parseInt(dataStart),4)),htonl(toFixedSizeBuffer(parseInt(dataLength),4)),...allBufferList)
|
||||
break;
|
||||
}
|
||||
|
||||
let result = bufferToHex(buffer);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function bufferToHex(buffer) {
|
||||
let hexString = '';
|
||||
const view = new Uint8Array(buffer);
|
||||
for (let i = 0; i < view.length; i++) {
|
||||
const hex = view[i].toString(16).padStart(2, '0');
|
||||
hexString += hex;
|
||||
}
|
||||
return hexString;
|
||||
}
|
||||
|
||||
export function toBinaryString(number, length) {
|
||||
let binaryString = number.toString(2);
|
||||
return binaryString.padStart(length, '0');
|
||||
}
|
||||
|
||||
export function binaryToHex(binaryStr) {
|
||||
// 确保二进制字符串长度是4的倍数
|
||||
if (binaryStr.length % 4 !== 0) {
|
||||
binaryStr = binaryStr.padStart(binaryStr.length + 4 - (binaryStr.length % 4), '0');
|
||||
}
|
||||
|
||||
let hexStr = '';
|
||||
for (let i = 0; i < binaryStr.length; i += 4) {
|
||||
// 取出每4位二进制字符串
|
||||
const binaryChunk = binaryStr.slice(i, i + 4);
|
||||
// 转换成十六进制字符并追加到结果字符串中
|
||||
hexStr += parseInt(binaryChunk, 2).toString(16);
|
||||
}
|
||||
|
||||
return hexStr;
|
||||
}
|
||||
|
||||
|
||||
export function hexToBuffer(hexStr) {
|
||||
if (hexStr.length % 2 !== 0) {
|
||||
throw new Error('Invalid hex string');
|
||||
}
|
||||
|
||||
let buffer = new ArrayBuffer(hexStr.length / 2);
|
||||
let view = new Uint8Array(buffer);
|
||||
|
||||
for (let i = 0; i < hexStr.length; i += 2) {
|
||||
view[i / 2] = parseInt(hexStr.substr(i, 2), 16);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
export function swapEndian(buffer) {
|
||||
const swappedBuffer = new ArrayBuffer(buffer.byteLength);
|
||||
const view = new DataView(buffer);
|
||||
const swappedView = new DataView(swappedBuffer);
|
||||
|
||||
for (let i = 0; i < buffer.byteLength; i++) {
|
||||
swappedView.setUint8(i, view.getUint8(buffer.byteLength - 1 - i));
|
||||
}
|
||||
|
||||
return swappedBuffer;
|
||||
}
|
||||
|
||||
|
||||
export function htonl(buffer) {
|
||||
if (buffer.byteLength !== 4) {
|
||||
throw new Error('Buffer must be exactly 4 bytes.');
|
||||
}
|
||||
|
||||
let view = new DataView(buffer);
|
||||
let number = view.getUint32(0);
|
||||
|
||||
let swappedNumber = ((number & 0xFF) << 24) |
|
||||
((number & 0xFF00) << 8) |
|
||||
((number & 0xFF0000) >> 8) |
|
||||
((number >> 24) & 0xFF);
|
||||
|
||||
let swappedBuffer = new ArrayBuffer(4);
|
||||
let swappedView = new DataView(swappedBuffer);
|
||||
swappedView.setUint32(0, swappedNumber);
|
||||
|
||||
return swappedBuffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//将数字转换成指定字节大小的buffer
|
||||
export function toFixedSizeBuffer(number, byteSize) {
|
||||
if (byteSize <= 0) {
|
||||
throw new Error('Byte size must be greater than zero.');
|
||||
}
|
||||
|
||||
let buffer = new ArrayBuffer(byteSize);
|
||||
let view = new DataView(buffer);
|
||||
|
||||
// 根据指定字节数设置数值到缓冲区中
|
||||
for (let i = 0; i < byteSize; i++) {
|
||||
view.setUint8(byteSize - 1 - i, number & 0xFF);
|
||||
number = number >> 8;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
export function concatenateBuffers(...buffers) {
|
||||
|
||||
// 确保所有元素均为 ArrayBuffer
|
||||
buffers.forEach(buffer => {
|
||||
if (!(buffer instanceof ArrayBuffer)) {
|
||||
throw new TypeError('All arguments must be ArrayBuffers');
|
||||
}
|
||||
});
|
||||
// 计算总长度
|
||||
let totalLength = buffers.reduce((sum, buffer) => sum + buffer.byteLength, 0);
|
||||
|
||||
// 创建一个新的 ArrayBuffer 并使用 Uint8Array 进行操作
|
||||
let concatenatedBuffer = new Uint8Array(totalLength);
|
||||
let offset = 0;
|
||||
|
||||
// 逐个复制每个缓冲区的内容
|
||||
buffers.forEach(buffer => {
|
||||
concatenatedBuffer.set(new Uint8Array(buffer), offset);
|
||||
offset += buffer.byteLength;
|
||||
});
|
||||
|
||||
return concatenatedBuffer.buffer;
|
||||
}
|
||||
|
||||
export function stringToHexBuffer(str,length) {
|
||||
// return new TextEncoder().encode(str).buffer;
|
||||
const bufferView = new TextEncoder().encode(str);
|
||||
|
||||
// 计算需要补充的00的数量
|
||||
const targetLength = length / 2; // 目标长度(字节数)
|
||||
const paddingLength = targetLength - bufferView.length;
|
||||
|
||||
// 创建一个新的Uint8Array,长度为目标长度
|
||||
const paddedBufferView = new Uint8Array(targetLength);
|
||||
|
||||
// 将原始Uint8Array的内容复制到新的Uint8Array中
|
||||
paddedBufferView.set(bufferView);
|
||||
|
||||
// 填充00
|
||||
if (paddingLength > 0) {
|
||||
paddedBufferView.fill(0, bufferView.length, targetLength);
|
||||
}
|
||||
|
||||
// 返回格式化后的Uint8Array
|
||||
return paddedBufferView.buffer;
|
||||
}
|
||||
|
||||
export function hexToString(hexStr) {
|
||||
let str = '';
|
||||
for (let i = 0; i < hexStr.length; i += 2) {
|
||||
if(hexStr.substr(i, 2)!=='00'){
|
||||
str += String.fromCharCode(parseInt(hexStr.substr(i, 2), 16));
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
export function rearrangeHexStr(hexStr) {
|
||||
// 将输入的十六进制字符串解析为字节数组
|
||||
// 将输入的十六进制字符串按每8位分组
|
||||
const groups = [];
|
||||
for (let i = 0; i < hexStr.length; i += 8) {
|
||||
groups.push(hexStr.slice(i, i + 8));
|
||||
}
|
||||
|
||||
// 对每个组内的每两位进行倒序拼接
|
||||
const rearrangedGroups = groups.map(group => {
|
||||
let rearrangedGroup = '';
|
||||
for (let i = 0; i < group.length; i += 2) {
|
||||
rearrangedGroup = group.substr(i, 2) + rearrangedGroup;
|
||||
}
|
||||
return rearrangedGroup;
|
||||
});
|
||||
|
||||
// 将所有组重新拼接成一个字符串
|
||||
const rearrangedHexStr = rearrangedGroups.join('');
|
||||
|
||||
return rearrangedHexStr;
|
||||
}
|
||||
|
||||
//高低位交换
|
||||
export function rearrangeHexStr4(hexStr) {
|
||||
let rearrangedGroup = '';
|
||||
for (let i = 0; i < hexStr.length; i += 2) {
|
||||
rearrangedGroup = hexStr.substr(i, 2) + rearrangedGroup;
|
||||
}
|
||||
return rearrangedGroup;
|
||||
}
|
||||
|
||||
export function hexToVersion(hexStr) {
|
||||
let str = rearrangeHexStr(hexStr);
|
||||
str = hexToDec(str);
|
||||
return str;
|
||||
}
|
||||
|
||||
export function versionToHex(hexStr) {
|
||||
let str = decToHex(hexStr);
|
||||
str = rearrangeHexStr(str);
|
||||
return str;
|
||||
}
|
||||
|
||||
// 十六进制转十进制
|
||||
export function hexToDec(hexStr) {
|
||||
// 去除前缀 "0x"(如果存在)
|
||||
hexStr = hexStr.replace(/^0x/, '');
|
||||
// 将十六进制字符串转换为十进制数字
|
||||
return parseInt(hexStr, 16);
|
||||
}
|
||||
|
||||
// 十进制转十六进制
|
||||
export function decToHex(decNum) {
|
||||
// 将十进制数字转换为十六进制字符串
|
||||
let hexStr = decNum.toString(16);
|
||||
// 可选:添加前缀 "0x"
|
||||
return `0x${hexStr}`;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
<template>
|
||||
<div>测试test</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'test'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|