完善 DiscWorker 打包路径与产品命名,底部展示前后端版本,生产环境隐藏默认菜单。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
24kycj
2026-08-06 11:28:15 +08:00
parent 1d0d39995e
commit f28b5dc50a
9 changed files with 182 additions and 84 deletions
+6 -4
View File
@@ -15,6 +15,7 @@
"dev:web": "cross-env NODE_ENV=development node node_modules/webpack-dev-server/bin/webpack-dev-server.js --config .electron-vue/webpack.web.config.js --open", "dev:web": "cross-env NODE_ENV=development node node_modules/webpack-dev-server/bin/webpack-dev-server.js --config .electron-vue/webpack.web.config.js --open",
"electron:linux": "vue-cli-service electron:build -l --x64", "electron:linux": "vue-cli-service electron:build -l --x64",
"electron:arm": "vue-cli-service electron:build -l --arm64", "electron:arm": "vue-cli-service electron:build -l --arm64",
"build:deb:arm64": "bash scripts/build-deb-arm64.sh",
"dev": "node .electron-vue/dev-runner.js", "dev": "node .electron-vue/dev-runner.js",
"lint": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter src", "lint": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter src",
"lint:fix": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter --fix src", "lint:fix": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter --fix src",
@@ -24,12 +25,12 @@
"postinstall": "npm run lint:fix" "postinstall": "npm run lint:fix"
}, },
"build": { "build": {
"productName": "discworker", "productName": "DiscWorker",
"appId": "com.kashu.soonworkerdisk", "appId": "com.kashu.soonworkerdisk",
"extraFiles": [ "extraFiles": [
{ {
"from": "./User Templates", "from": "./User Templates",
"to": "." "to": "User Templates"
}, },
{ {
"from": "./CardsoonServer", "from": "./CardsoonServer",
@@ -37,7 +38,7 @@
}, },
{ {
"from": "./help", "from": "./help",
"to": "." "to": "help"
} }
], ],
"directories": { "directories": {
@@ -68,7 +69,8 @@
"icon": "build/icons/icon.ico" "icon": "build/icons/icon.ico"
}, },
"linux": { "linux": {
"icon": "build/icons" "icon": "build/icons",
"executableName": "DiscWorker"
} }
}, },
"dependencies": { "dependencies": {
+83
View File
@@ -0,0 +1,83 @@
#!/usr/bin/env bash
# 构建 Linux arm64 deb,并保证安装路径与 productName/executableName=DiscWorker 一致
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT"
EXE="DiscWorker"
SANITIZED="DiscWorker"
OPT_DIR="/opt/${SANITIZED}"
BIN_LINK="/usr/bin/${EXE}"
echo "[build-deb-arm64] executable: ${EXE}"
echo "[build-deb-arm64] opt dir: ${OPT_DIR}"
node .electron-vue/build.js
npx electron-builder --linux deb --arm64
shopt -s nullglob
mapfile -t DEBS < <(ls -t build/*.deb 2>/dev/null || true)
if [[ ${#DEBS[@]} -eq 0 ]]; then
echo "[build-deb-arm64] 未找到 build/*.deb" >&2
exit 1
fi
DEB="${DEBS[0]}"
WORK="$(mktemp -d)"
trap 'rm -rf "$WORK"' EXIT
echo "[build-deb-arm64] patching: $DEB"
dpkg-deb -R "$DEB" "$WORK/pkg"
CONTROL_DIR="$WORK/pkg/DEBIAN"
mkdir -p "$CONTROL_DIR"
# 若 builder 已生成钩子,把旧小写路径替换为 DiscWorker;否则写入默认钩子
patch_or_write() {
local file="$1"
local kind="$2"
if [[ -f "$file" ]]; then
sed -i \
-e "s|/opt/discworker|/opt/${SANITIZED}|g" \
-e "s|/usr/bin/discworker|/usr/bin/${EXE}|g" \
-e "s|discworker/chrome-sandbox|${SANITIZED}/chrome-sandbox|g" \
-e "s|/opt/discworker/discworker|${OPT_DIR}/${EXE}|g" \
"$file"
chmod 755 "$file"
echo "[build-deb-arm64] patched existing ${kind}"
return
fi
if [[ "$kind" == "postinst" ]]; then
cat > "$file" <<EOF
#!/bin/bash
set -e
if [ -f ${OPT_DIR}/chrome-sandbox ]; then
chown root:root ${OPT_DIR}/chrome-sandbox
chmod 4755 ${OPT_DIR}/chrome-sandbox
fi
if [ -x ${OPT_DIR}/${EXE} ]; then
ln -sfn ${OPT_DIR}/${EXE} ${BIN_LINK}
fi
exit 0
EOF
else
cat > "$file" <<EOF
#!/bin/bash
set -e
if [ "\$1" = "remove" ] || [ "\$1" = "purge" ]; then
rm -f ${BIN_LINK}
fi
exit 0
EOF
fi
chmod 755 "$file"
echo "[build-deb-arm64] wrote default ${kind}"
}
patch_or_write "$CONTROL_DIR/postinst" "postinst"
patch_or_write "$CONTROL_DIR/postrm" "postrm"
OUT="build/${SANITIZED}-arm64-patched.deb"
dpkg-deb -b "$WORK/pkg" "$OUT"
echo "[build-deb-arm64] done: $OUT"
+1 -1
View File
@@ -2,7 +2,7 @@
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>DiscWorker V1.01</title> <title>DiscWorker</title>
<link rel="icon" href="<%= process.env.NODE_ENV === 'development' ? '/static/favicon.ico' : './static/favicon.ico' %>" type="image/x-icon"> <link rel="icon" href="<%= process.env.NODE_ENV === 'development' ? '/static/favicon.ico' : './static/favicon.ico' %>" type="image/x-icon">
<% if (typeof isWeb === 'undefined' ? htmlWebpackPlugin.options.nodeModules : !isWeb && htmlWebpackPlugin.options.nodeModules) { %> <% if (typeof isWeb === 'undefined' ? htmlWebpackPlugin.options.nodeModules : !isWeb && htmlWebpackPlugin.options.nodeModules) { %>
<!-- Add `node_modules/` to global paths so `require` works properly in development (Electron only) --> <!-- Add `node_modules/` to global paths so `require` works properly in development (Electron only) -->
+4 -2
View File
@@ -54,8 +54,10 @@ function createWindow () {
}) })
require("@electron/remote/main").initialize(); require("@electron/remote/main").initialize();
require("@electron/remote/main").enable(mainWindow.webContents); require("@electron/remote/main").enable(mainWindow.webContents);
// 禁用默认菜单 // dev 保留 Electron 默认菜单;打包后隐藏
// Menu.setApplicationMenu(null); if (process.env.NODE_ENV !== 'development') {
Menu.setApplicationMenu(null)
}
// mainWindow.maximize() // mainWindow.maximize()
mainWindow.show() mainWindow.show()
mainWindow.loadURL(winURL) mainWindow.loadURL(winURL)
@@ -62,6 +62,7 @@
<console-status-bar <console-status-bar
:serial-no="printerInfo.serial_no" :serial-no="printerInfo.serial_no"
:cache-text="cacheText" :cache-text="cacheText"
:version-text="versionText"
@help="$emit('help')" @help="$emit('help')"
@about="$emit('about')" @about="$emit('about')"
/> />
@@ -111,7 +112,8 @@ export default {
diskTypes: { type: Object, default: () => ({}) }, diskTypes: { type: Object, default: () => ({}) },
taskList: { type: Array, default: () => [] }, taskList: { type: Array, default: () => [] },
logList: { type: Array, default: () => [] }, logList: { type: Array, default: () => [] },
showAllLogs: { type: Boolean, default: false } showAllLogs: { type: Boolean, default: false },
versionText: { type: String, default: '' }
}, },
computed: { computed: {
cacheText() { cacheText() {
@@ -1,147 +1,109 @@
<template> <template>
<div class="console-statusbar"> <div class="console-statusbar">
<div class="console-statusbar__left"> <div class="console-statusbar__left">
<span class="console-statusbar__version">{{ displayVersion }}</span>
<span v-if="serialNo" class="console-statusbar__item">SN: {{ serialNo }}</span> <span v-if="serialNo" class="console-statusbar__item">SN: {{ serialNo }}</span>
<span v-if="cacheText" class="console-statusbar__item">{{ cacheText }}</span> <span v-if="cacheText" class="console-statusbar__item">{{ cacheText }}</span>
</div> </div>
<div class="console-statusbar__links"> <div class="console-statusbar__links">
<a href="#" @click.prevent="$emit('help')"> <a href="#" @click.prevent="$emit('help')">
<console-icon name="help" :size="13" /> <console-icon name="help" :size="13" />
帮助 帮助
</a> </a>
<span class="console-statusbar__sep">|</span> <span class="console-statusbar__sep">|</span>
<a href="#" @click.prevent="$emit('about')">关于</a> <a href="#" @click.prevent="$emit('about')">关于</a>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import ConsoleIcon from '../icons/ConsoleIcon.vue' import ConsoleIcon from '../icons/ConsoleIcon.vue'
import { loadAppVersionLine } from '@/utils/console/appVersion'
export default { export default {
name: 'ConsoleStatusBar', name: 'ConsoleStatusBar',
components: { ConsoleIcon }, components: { ConsoleIcon },
props: { props: {
serialNo: { type: String, default: '' }, serialNo: { type: String, default: '' },
cacheText: { type: String, default: '' },
cacheText: { type: String, default: '' } versionText: { type: String, default: '' }
},
data() {
return {
localVersionText: ''
}
},
computed: {
displayVersion() {
return this.versionText || this.localVersionText || 'DiscWorker'
}
},
created() {
if (!this.versionText) {
loadAppVersionLine().then((text) => {
this.localVersionText = text
})
}
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.console-statusbar { .console-statusbar {
height: var(--dw-statusbar-h); height: var(--dw-statusbar-h);
padding: 0 20px; padding: 0 20px;
background: var(--dw-surface); background: var(--dw-surface);
border-top: 1px solid var(--dw-border); border-top: 1px solid var(--dw-border);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
gap: 12px;
font-size: 12px; font-size: 12px;
color: var(--dw-text-muted); color: var(--dw-text-muted);
flex-shrink: 0; flex-shrink: 0;
&__left { &__left {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 16px; gap: 16px;
min-width: 0;
flex: 1;
} }
&__version {
color: var(--dw-text-secondary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
&__item {
white-space: nowrap;
}
&__links { &__links {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: flex-end;
gap: 4px; gap: 4px;
flex-shrink: 0;
a { a {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 4px; gap: 4px;
color: var(--dw-text-secondary); color: var(--dw-text-secondary);
text-decoration: none; text-decoration: none;
} }
a:hover { a:hover {
color: var(--dw-primary); color: var(--dw-primary);
} }
} }
&__sep { &__sep {
margin: 0 6px; margin: 0 6px;
opacity: 0.45; opacity: 0.45;
} }
} }
</style> </style>
+36
View File
@@ -0,0 +1,36 @@
import platform from '@/platform'
const pkg = require('../../../../package.json')
export function getFrontendVersion() {
return String((pkg && pkg.version) || '0.0.0').replace(/^v/i, '')
}
export function formatAppVersionLine(front, back) {
const f = String(front || '').replace(/^v/i, '') || '—'
const b = String(back || '').replace(/^v/i, '').trim() || '—'
return `DiscWorker V${f} 基于DiscProducer 核心V${b}`
}
export function loadBackendVersion() {
if (!(platform.hasNativeFs && platform.hasNativeFs())) {
return Promise.resolve('')
}
const root = platform.getAppRoot()
const candidates = [
platform.pathJoin(root, 'CardsoonServer', 'VERSION'),
platform.pathJoin(root, 'cardsoonServer', 'VERSION')
]
const tryRead = (i) => {
if (i >= candidates.length) return Promise.resolve('')
return platform.readFile(candidates[i], 'utf8')
.then((text) => String(text || '').trim().split(/\r?\n/)[0] || '')
.catch(() => tryRead(i + 1))
}
return tryRead(0)
}
export function loadAppVersionLine() {
const front = getFrontendVersion()
return loadBackendVersion().then((back) => formatAppVersionLine(front, back))
}
+7 -1
View File
@@ -27,6 +27,7 @@
:task-list="task_list" :task-list="task_list"
:log-list="displayLogs" :log-list="displayLogs"
:show-all-logs="showAll" :show-all-logs="showAll"
:version-text="versionText"
@open-work="onOpenWork" @open-work="onOpenWork"
@go-settings="onGoSettings" @go-settings="onGoSettings"
@activate="onActivate" @activate="onActivate"
@@ -54,7 +55,7 @@
<el-dialog title="关于 DiscWorker" :visible.sync="aboutVisible" width="400px"> <el-dialog title="关于 DiscWorker" :visible.sync="aboutVisible" width="400px">
<div class="about-box"> <div class="about-box">
<div>国产光盘打印刻录系统 DiscWorker</div> <div>国产光盘打印刻录系统 DiscWorker</div>
<div>版本 1.0</div> <div>{{ versionText }}</div>
<div>© 2023 cardsoon Co., Ltd.</div> <div>© 2023 cardsoon Co., Ltd.</div>
</div> </div>
</el-dialog> </el-dialog>
@@ -92,6 +93,7 @@ import {
help, help,
getChangeCDDefault getChangeCDDefault
} from '@/utils/console/consoleActions' } from '@/utils/console/consoleActions'
import { loadAppVersionLine } from '@/utils/console/appVersion'
export default { export default {
name: 'ConsolePage', name: 'ConsolePage',
@@ -103,6 +105,7 @@ export default {
data() { data() {
return { return {
aboutVisible: false, aboutVisible: false,
versionText: '',
taskNum: [0, 0, 0], taskNum: [0, 0, 0],
task_list: [], task_list: [],
printer_info: {}, printer_info: {},
@@ -291,6 +294,9 @@ export default {
} }
}, },
created() { created() {
loadAppVersionLine().then((text) => {
this.versionText = text
})
if (this.isStaticView) { if (this.isStaticView) {
this.applyMock() this.applyMock()
} }
+7 -2
View File
@@ -492,7 +492,7 @@
</div> </div>
<!-- 底部 --> <!-- 底部 -->
<div class="flex_box flex_row_center footer_box"> <div class="flex_box flex_row_center footer_box">
<div>北京同方光盘股份有限公司</div> <div>{{ versionText }}</div>
<div class="footer_line"></div> <div class="footer_line"></div>
<div class="footer_text" @click="help">帮助</div> <div class="footer_text" @click="help">帮助</div>
<div class="footer_line"></div> <div class="footer_line"></div>
@@ -516,7 +516,7 @@
<el-dialog title="关于Disc Worker" :visible.sync="dialogVisible" width="400px"> <el-dialog title="关于Disc Worker" :visible.sync="dialogVisible" width="400px">
<div class="about_box"> <div class="about_box">
<div class="company-name">国产光盘打印刻录系统 DiscWorker</div> <div class="company-name">国产光盘打印刻录系统 DiscWorker</div>
<div class="version">版本1.0</div> <div class="version">{{ versionText }}</div>
<div class="copyright"> <div class="copyright">
© 2023 cardsoon Co., Ltd. All rights reserved. © 2023 cardsoon Co., Ltd. All rights reserved.
</div> </div>
@@ -534,12 +534,14 @@ import WorkAdd from '@/components/workAdd/workAdd.vue'
import platform from '@/platform' import platform from '@/platform'
import { transformTaskList } from '@/utils/console/taskListTransform' import { transformTaskList } from '@/utils/console/taskListTransform'
import { applyPrinterInfoSideEffects } from '@/utils/console/printerWatch' import { applyPrinterInfoSideEffects } from '@/utils/console/printerWatch'
import { loadAppVersionLine } from '@/utils/console/appVersion'
export default { export default {
name: 'dashboard', name: 'dashboard',
components: { UserInfo, WorkAdd }, components: { UserInfo, WorkAdd },
data() { data() {
return { return {
dialogVisible: false, dialogVisible: false,
versionText: '',
deviceImg: { deviceImg: {
4200: { 4200: {
img1: require('@/assets/images/4200.png'), img1: require('@/assets/images/4200.png'),
@@ -809,6 +811,9 @@ export default {
}, },
mounted() { mounted() {
that = this that = this
loadAppVersionLine().then((text) => {
this.versionText = text
})
this.setStep() this.setStep()
this.guideStep = JSON.parse(localStorage.getItem('guideStep')) this.guideStep = JSON.parse(localStorage.getItem('guideStep'))
this.currentStep = localStorage.getItem('currentStep') this.currentStep = localStorage.getItem('currentStep')