From ac566846c937fb602dce60c672b51e9018b2ec00 Mon Sep 17 00:00:00 2001 From: 24kycj <1637269896@qq.com> Date: Wed, 9 Sep 2026 10:36:42 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/electron.vite.config.ts | 6 + app/package-lock.json | 186 ++++++++++------- app/package.json | 12 +- app/src/main/index.ts | 24 +-- app/src/main/ipc/register-handlers.ts | 30 ++- app/src/main/services/open-design-app.ts | 4 +- app/src/main/services/work-dll.service.ts | 42 +++- app/src/main/utils/ensure-console-utf8.ts | 21 ++ app/src/renderer/src/api/cardsoon.ts | 10 + app/src/renderer/src/assets/icons/index.ts | 8 +- app/src/renderer/src/components/AppFooter.vue | 14 +- app/src/renderer/src/components/AppHeader.vue | 74 ++++++- .../src/components/NetworkPathDialog.vue | 36 ++-- .../renderer/src/components/WorkflowSteps.vue | 27 +-- .../src/composables/useAppBootstrap.ts | 15 +- app/src/renderer/src/composables/useNotify.ts | 13 +- .../src/composables/usePrinterStatus.ts | 4 +- .../renderer/src/constants/selectOptions.ts | 52 +++-- app/src/renderer/src/env.d.ts | 2 + app/src/renderer/src/i18n/index.ts | 45 +++++ app/src/renderer/src/i18n/locales/en-US.ts | 190 +++++++++++++++++ app/src/renderer/src/i18n/locales/zh-CN.ts | 191 ++++++++++++++++++ app/src/renderer/src/i18n/locales/zh-TW.ts | 191 ++++++++++++++++++ app/src/renderer/src/main.ts | 4 + app/src/renderer/src/styles/pages/page2.css | 18 ++ app/src/renderer/src/styles/pages/page4.css | 10 + app/src/renderer/src/types/printer.ts | 8 +- .../renderer/src/utils/createDistributeJob.ts | 11 +- .../renderer/src/utils/validateJobConfig.ts | 11 +- .../src/utils/validateJobPreflight.ts | 31 ++- .../renderer/src/views/DataCollectView.vue | 34 ++-- .../src/views/DistributeConfigView.vue | 126 ++++++++---- .../src/views/DistributeRunningView.vue | 60 +++--- app/src/renderer/src/views/HomeView.vue | 74 +++++-- app/src/shared/printer-info.ts | 29 ++- app/tsconfig.web.tsbuildinfo | 2 +- 36 files changed, 1325 insertions(+), 290 deletions(-) create mode 100644 app/src/main/utils/ensure-console-utf8.ts create mode 100644 app/src/renderer/src/i18n/index.ts create mode 100644 app/src/renderer/src/i18n/locales/en-US.ts create mode 100644 app/src/renderer/src/i18n/locales/zh-CN.ts create mode 100644 app/src/renderer/src/i18n/locales/zh-TW.ts diff --git a/app/electron.vite.config.ts b/app/electron.vite.config.ts index d761a31..2ac4f7c 100644 --- a/app/electron.vite.config.ts +++ b/app/electron.vite.config.ts @@ -1,7 +1,10 @@ import { resolve } from 'path' +import { readFileSync } from 'fs' import { defineConfig, externalizeDepsPlugin } from 'electron-vite' import vue from '@vitejs/plugin-vue' +const pkg = JSON.parse(readFileSync(resolve('package.json'), 'utf-8')) as { version: string } + const sharedAlias = { '@shared': resolve('src/shared') } export default defineConfig({ @@ -19,6 +22,9 @@ export default defineConfig({ ...sharedAlias } }, + define: { + __APP_VERSION__: JSON.stringify(pkg.version) + }, plugins: [vue()] } }) diff --git a/app/package-lock.json b/app/package-lock.json index ca92590..96ff68d 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -10,7 +10,8 @@ "dependencies": { "electron-log": "^5.1.2", "electron-store": "^8.1.0", - "koffi": "^2.9.0" + "koffi": "^2.9.0", + "vue-i18n": "^9.14.4" }, "devDependencies": { "@vitejs/plugin-vue": "^4.6.2", @@ -166,7 +167,6 @@ "version": "7.27.1", "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -175,7 +175,6 @@ "version": "7.28.5", "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -206,7 +205,6 @@ "version": "7.29.3", "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.3.tgz", "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", - "dev": true, "dependencies": { "@babel/types": "^7.29.0" }, @@ -268,7 +266,6 @@ "version": "7.29.0", "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.0.tgz", "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", - "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" @@ -932,6 +929,50 @@ "node": ">=12" } }, + "node_modules/@intlify/core-base": { + "version": "9.14.4", + "resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-9.14.4.tgz", + "integrity": "sha512-vtZCt7NqWhKEtHa3SD/322DlgP5uR9MqWxnE0y8Q0tjDs9H5Lxhss+b5wv8rmuXRoHKLESNgw9d+EN9ybBbj9g==", + "license": "MIT", + "dependencies": { + "@intlify/message-compiler": "9.14.4", + "@intlify/shared": "9.14.4" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/message-compiler": { + "version": "9.14.4", + "resolved": "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-9.14.4.tgz", + "integrity": "sha512-vcyCLiVRN628U38c3PbahrhbbXrckrM9zpy0KZVlDk2Z0OnGwv8uQNNXP3twwGtfLsCf4gu3ci6FMIZnPaqZsw==", + "license": "MIT", + "dependencies": { + "@intlify/shared": "9.14.4", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/shared": { + "version": "9.14.4", + "resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-9.14.4.tgz", + "integrity": "sha512-P9zv6i1WvMc9qDBWvIgKkymjY2ptIiQ065PjDv7z7fDqH3J/HBRBN5IoiR46r/ujRcU7hCuSIZWvCAFCyuOYZA==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmmirror.com/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1060,8 +1101,7 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", @@ -1585,7 +1625,6 @@ "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.34.tgz", "integrity": "sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==", - "dev": true, "dependencies": { "@babel/parser": "^7.29.3", "@vue/shared": "3.5.34", @@ -1598,7 +1637,6 @@ "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.34.tgz", "integrity": "sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==", - "dev": true, "dependencies": { "@vue/compiler-core": "3.5.34", "@vue/shared": "3.5.34" @@ -1608,7 +1646,6 @@ "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.34.tgz", "integrity": "sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg==", - "dev": true, "dependencies": { "@babel/parser": "^7.29.3", "@vue/compiler-core": "3.5.34", @@ -1625,7 +1662,6 @@ "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.34.tgz", "integrity": "sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ==", - "dev": true, "dependencies": { "@vue/compiler-dom": "3.5.34", "@vue/shared": "3.5.34" @@ -1634,8 +1670,7 @@ "node_modules/@vue/devtools-api": { "version": "6.6.4", "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz", - "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", - "dev": true + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==" }, "node_modules/@vue/language-core": { "version": "1.8.27", @@ -1666,7 +1701,6 @@ "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.34.tgz", "integrity": "sha512-y9XDjCEuBp+98k+UL5dbYkh57AHU4o6cxZedOPXw3bmrZZYLQsVHguGurq7hVrPCSrQtrnz1f9dssyFr+dMXfQ==", - "dev": true, "dependencies": { "@vue/shared": "3.5.34" } @@ -1675,7 +1709,6 @@ "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.34.tgz", "integrity": "sha512-mKeBYvu8tcMSLhypAHBmriUFfWXKTCF/23Z4jiCoYK3UtWepkliViNLuR90V9XOyD62mUxs9p1jsrpK3CCGIzw==", - "dev": true, "dependencies": { "@vue/reactivity": "3.5.34", "@vue/shared": "3.5.34" @@ -1685,7 +1718,6 @@ "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.34.tgz", "integrity": "sha512-e8kZzERmCwUnBRVsgSQlAfrfU2rGoy0FFKPBXSlfEjc/O3KfA7QP0t1/2ZylrbchjmIKB4dPTd07A6WPr0eOrg==", - "dev": true, "dependencies": { "@vue/reactivity": "3.5.34", "@vue/runtime-core": "3.5.34", @@ -1697,7 +1729,6 @@ "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.34.tgz", "integrity": "sha512-nHxmJoTrKsmrkbILRhkC9gY1G3moZbJTqCzDd7DOOzG5KH9oeJ0Unqrff5f9v0pW//jES05ZkJcNtfE8JjOIew==", - "dev": true, "dependencies": { "@vue/compiler-ssr": "3.5.34", "@vue/shared": "3.5.34" @@ -1709,8 +1740,7 @@ "node_modules/@vue/shared": { "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.34.tgz", - "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==", - "dev": true + "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==" }, "node_modules/@xmldom/xmldom": { "version": "0.9.10", @@ -2676,8 +2706,7 @@ "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "dev": true + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==" }, "node_modules/de-indent": { "version": "1.0.2", @@ -3275,7 +3304,6 @@ "version": "7.0.1", "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz", "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", - "dev": true, "engines": { "node": ">=0.12" }, @@ -3411,8 +3439,7 @@ "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, "node_modules/extract-zip": { "version": "2.0.1", @@ -4396,7 +4423,6 @@ "version": "0.30.21", "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } @@ -4565,7 +4591,6 @@ "version": "3.3.12", "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.12.tgz", "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", - "dev": true, "funding": [ { "type": "github", @@ -4777,8 +4802,7 @@ "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "4.0.4", @@ -4854,7 +4878,6 @@ "version": "8.5.15", "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.15.tgz", "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", - "dev": true, "funding": [ { "type": "opencollective", @@ -5272,7 +5295,6 @@ "version": "1.2.1", "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -5539,7 +5561,7 @@ "version": "5.3.3", "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.3.3.tgz", "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "dev": true, + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -5695,7 +5717,6 @@ "version": "3.5.34", "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.34.tgz", "integrity": "sha512-WdLBG9gm02OgJIG9axd5Hpx0TFLdzVgfG2evFFu8Rur5O/IoGc5cMjnjh3tPL6GnRGsYvUhBSKVPYVcxRKpMCA==", - "dev": true, "dependencies": { "@vue/compiler-dom": "3.5.34", "@vue/compiler-sfc": "3.5.34", @@ -5738,6 +5759,26 @@ } } }, + "node_modules/vue-i18n": { + "version": "9.14.4", + "resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-9.14.4.tgz", + "integrity": "sha512-B934C8yUyWLT0EMud3DySrwSUJI7ZNiWYsEEz2gknTthqKiG4dzWE/WSa8AzCuSQzwBEv4HtG1jZDhgzPfWSKQ==", + "license": "MIT", + "dependencies": { + "@intlify/core-base": "9.14.4", + "@intlify/shared": "9.14.4", + "@vue/devtools-api": "^6.5.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, "node_modules/vue-router": { "version": "4.6.4", "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.6.4.tgz", @@ -6050,14 +6091,12 @@ "@babel/helper-string-parser": { "version": "7.27.1", "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==" }, "@babel/helper-validator-identifier": { "version": "7.28.5", "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==" }, "@babel/helper-validator-option": { "version": "7.27.1", @@ -6079,7 +6118,6 @@ "version": "7.29.3", "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.3.tgz", "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", - "dev": true, "requires": { "@babel/types": "^7.29.0" } @@ -6123,7 +6161,6 @@ "version": "7.29.0", "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.0.tgz", "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", - "dev": true, "requires": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" @@ -6523,6 +6560,29 @@ "dev": true, "optional": true }, + "@intlify/core-base": { + "version": "9.14.4", + "resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-9.14.4.tgz", + "integrity": "sha512-vtZCt7NqWhKEtHa3SD/322DlgP5uR9MqWxnE0y8Q0tjDs9H5Lxhss+b5wv8rmuXRoHKLESNgw9d+EN9ybBbj9g==", + "requires": { + "@intlify/message-compiler": "9.14.4", + "@intlify/shared": "9.14.4" + } + }, + "@intlify/message-compiler": { + "version": "9.14.4", + "resolved": "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-9.14.4.tgz", + "integrity": "sha512-vcyCLiVRN628U38c3PbahrhbbXrckrM9zpy0KZVlDk2Z0OnGwv8uQNNXP3twwGtfLsCf4gu3ci6FMIZnPaqZsw==", + "requires": { + "@intlify/shared": "9.14.4", + "source-map-js": "^1.0.2" + } + }, + "@intlify/shared": { + "version": "9.14.4", + "resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-9.14.4.tgz", + "integrity": "sha512-P9zv6i1WvMc9qDBWvIgKkymjY2ptIiQ065PjDv7z7fDqH3J/HBRBN5IoiR46r/ujRcU7hCuSIZWvCAFCyuOYZA==" + }, "@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmmirror.com/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -6617,8 +6677,7 @@ "@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" }, "@jridgewell/trace-mapping": { "version": "0.3.31", @@ -6923,7 +6982,6 @@ "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.34.tgz", "integrity": "sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==", - "dev": true, "requires": { "@babel/parser": "^7.29.3", "@vue/shared": "3.5.34", @@ -6936,7 +6994,6 @@ "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.34.tgz", "integrity": "sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==", - "dev": true, "requires": { "@vue/compiler-core": "3.5.34", "@vue/shared": "3.5.34" @@ -6946,7 +7003,6 @@ "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.34.tgz", "integrity": "sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg==", - "dev": true, "requires": { "@babel/parser": "^7.29.3", "@vue/compiler-core": "3.5.34", @@ -6963,7 +7019,6 @@ "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.34.tgz", "integrity": "sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ==", - "dev": true, "requires": { "@vue/compiler-dom": "3.5.34", "@vue/shared": "3.5.34" @@ -6972,8 +7027,7 @@ "@vue/devtools-api": { "version": "6.6.4", "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz", - "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", - "dev": true + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==" }, "@vue/language-core": { "version": "1.8.27", @@ -6996,7 +7050,6 @@ "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.34.tgz", "integrity": "sha512-y9XDjCEuBp+98k+UL5dbYkh57AHU4o6cxZedOPXw3bmrZZYLQsVHguGurq7hVrPCSrQtrnz1f9dssyFr+dMXfQ==", - "dev": true, "requires": { "@vue/shared": "3.5.34" } @@ -7005,7 +7058,6 @@ "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.34.tgz", "integrity": "sha512-mKeBYvu8tcMSLhypAHBmriUFfWXKTCF/23Z4jiCoYK3UtWepkliViNLuR90V9XOyD62mUxs9p1jsrpK3CCGIzw==", - "dev": true, "requires": { "@vue/reactivity": "3.5.34", "@vue/shared": "3.5.34" @@ -7015,7 +7067,6 @@ "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.34.tgz", "integrity": "sha512-e8kZzERmCwUnBRVsgSQlAfrfU2rGoy0FFKPBXSlfEjc/O3KfA7QP0t1/2ZylrbchjmIKB4dPTd07A6WPr0eOrg==", - "dev": true, "requires": { "@vue/reactivity": "3.5.34", "@vue/runtime-core": "3.5.34", @@ -7027,7 +7078,6 @@ "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.34.tgz", "integrity": "sha512-nHxmJoTrKsmrkbILRhkC9gY1G3moZbJTqCzDd7DOOzG5KH9oeJ0Unqrff5f9v0pW//jES05ZkJcNtfE8JjOIew==", - "dev": true, "requires": { "@vue/compiler-ssr": "3.5.34", "@vue/shared": "3.5.34" @@ -7036,8 +7086,7 @@ "@vue/shared": { "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.34.tgz", - "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==", - "dev": true + "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==" }, "@xmldom/xmldom": { "version": "0.9.10", @@ -7758,8 +7807,7 @@ "csstype": { "version": "3.2.3", "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "dev": true + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==" }, "de-indent": { "version": "1.0.2", @@ -8223,8 +8271,7 @@ "entities": { "version": "7.0.1", "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz", - "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", - "dev": true + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==" }, "env-paths": { "version": "2.2.1", @@ -8323,8 +8370,7 @@ "estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, "extract-zip": { "version": "2.0.1", @@ -9091,7 +9137,6 @@ "version": "0.30.21", "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, "requires": { "@jridgewell/sourcemap-codec": "^1.5.5" } @@ -9213,8 +9258,7 @@ "nanoid": { "version": "3.3.12", "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", - "dev": true + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==" }, "node-addon-api": { "version": "7.1.1", @@ -9367,8 +9411,7 @@ "picocolors": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "picomatch": { "version": "4.0.4", @@ -9417,7 +9460,6 @@ "version": "8.5.15", "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.15.tgz", "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", - "dev": true, "requires": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", @@ -9709,8 +9751,7 @@ "source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" }, "source-map-support": { "version": "0.5.21", @@ -9926,7 +9967,7 @@ "version": "5.3.3", "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.3.3.tgz", "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "dev": true + "devOptional": true }, "universalify": { "version": "0.1.2", @@ -10003,7 +10044,6 @@ "version": "3.5.34", "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.34.tgz", "integrity": "sha512-WdLBG9gm02OgJIG9axd5Hpx0TFLdzVgfG2evFFu8Rur5O/IoGc5cMjnjh3tPL6GnRGsYvUhBSKVPYVcxRKpMCA==", - "dev": true, "requires": { "@vue/compiler-dom": "3.5.34", "@vue/compiler-sfc": "3.5.34", @@ -10019,6 +10059,16 @@ "dev": true, "requires": {} }, + "vue-i18n": { + "version": "9.14.4", + "resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-9.14.4.tgz", + "integrity": "sha512-B934C8yUyWLT0EMud3DySrwSUJI7ZNiWYsEEz2gknTthqKiG4dzWE/WSa8AzCuSQzwBEv4HtG1jZDhgzPfWSKQ==", + "requires": { + "@intlify/core-base": "9.14.4", + "@intlify/shared": "9.14.4", + "@vue/devtools-api": "^6.5.0" + } + }, "vue-router": { "version": "4.6.4", "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.6.4.tgz", diff --git a/app/package.json b/app/package.json index 470533f..c934c0b 100644 --- a/app/package.json +++ b/app/package.json @@ -17,12 +17,15 @@ "predist:zip": "node scripts/check-native-dlls.js && node scripts/clean-release-artifacts.js", "dist": "electron-vite build && electron-builder", "dist:dir": "electron-vite build && electron-builder --dir", - "dist:zip": "electron-vite build && electron-builder --win zip" + "dist:zip": "electron-vite build && electron-builder --win zip", + "prerelease": "node scripts/check-native-dlls.js && node scripts/clean-release-artifacts.js", + "release": "electron-vite build && electron-builder --win nsis" }, "dependencies": { "electron-log": "^5.1.2", "electron-store": "^8.1.0", - "koffi": "^2.9.0" + "koffi": "^2.9.0", + "vue-i18n": "^9.14.4" }, "build": { "appId": "com.cardsoon.machine", @@ -70,6 +73,11 @@ ], "signAndEditExecutable": false }, + "nsis": { + "oneClick": false, + "allowToChangeInstallationDirectory": true, + "perMachine": false + }, "mac": { "target": [ "dmg" diff --git a/app/src/main/index.ts b/app/src/main/index.ts index ebc80af..ea2e963 100644 --- a/app/src/main/index.ts +++ b/app/src/main/index.ts @@ -1,4 +1,4 @@ -import { app, BrowserWindow, dialog, globalShortcut, screen } from 'electron' +import { app, BrowserWindow, dialog, globalShortcut } from 'electron' import { join } from 'path' app.commandLine.appendSwitch('disable-gpu-shader-disk-cache') @@ -14,10 +14,12 @@ if (!gotSingleInstanceLock) { app.quit() } +import { ensureConsoleUtf8 } from './utils/ensure-console-utf8' import { suppressKnownDllStderr } from './utils/suppress-dll-stderr' import { loadAppFileConfig, applyFileConfigToStore } from './services/app-config' import { migrateTraceConfig, setTraceWebContents } from './utils/trace-bridge' +ensureConsoleUtf8() suppressKnownDllStderr() process.on('uncaughtException', (err) => { @@ -41,24 +43,12 @@ function focusMainWindow(): void { mainWindow.focus() } -function getDefaultWindowSize(): { width: number; height: number } { - const { width: sw, height: sh } = screen.getPrimaryDisplay().workAreaSize - let w = Math.max(1280, Math.min(Math.floor(sw * 0.85), 1600)) - let h = contentHeightForWidth(w) - const maxH = Math.floor(sh * 0.85) - if (h > maxH) { - h = Math.max(contentHeightForWidth(MIN_CONTENT_WIDTH), maxH) - w = Math.round((h * DESIGN_WIDTH) / DESIGN_HEIGHT) - } - return { width: w, height: h } -} - function createWindow(): void { - const { width, height } = getDefaultWindowSize() + // 目标设备屏幕为 720x360,窗口默认 1:1 显示设计稿大小 mainWindow = new BrowserWindow({ useContentSize: true, - width, - height, + width: DESIGN_WIDTH, + height: DESIGN_HEIGHT, minWidth: MIN_CONTENT_WIDTH, minHeight: contentHeightForWidth(MIN_CONTENT_WIDTH), show: false, @@ -94,6 +84,8 @@ function createWindow(): void { mainWindow.on('resize', () => { if (!mainWindow) return + // 最大化时让窗口填满屏幕,不强制 2:1 内容比例 + if (mainWindow.isMaximized()) return const [cw, ch] = mainWindow.getContentSize() const wantH = contentHeightForWidth(cw) if (Math.abs(ch - wantH) > 2) { diff --git a/app/src/main/ipc/register-handlers.ts b/app/src/main/ipc/register-handlers.ts index dc304db..5a7c0a0 100644 --- a/app/src/main/ipc/register-handlers.ts +++ b/app/src/main/ipc/register-handlers.ts @@ -107,7 +107,9 @@ export function registerIpcHandlers(): void { ribbonType: cached?.ribbonType ?? '—', ribbonAmount: cached?.ribbonAmount ?? '—', statusText: parsed.statusText, - serialNo: cached?.serialNo ?? '—' + serialNo: cached?.serialNo ?? '—', + printerName: cached?.printerName ?? '—', + isSingleSide: cached?.isSingleSide ?? false } configStore.set('lastPrinterStatus', snapshot) return ok({ statusText: parsed.statusText, statusCode: code }) @@ -152,6 +154,32 @@ export function registerIpcHandlers(): void { } }) + // 读卡:移动卡片到读取区(SAPI_PrinterMovetousbreader) + tracedHandle('dll:printer-read-card', async () => { + try { + assertReady() + const dll = await loadDllModule() + if (!dll.isUsbReaderApiAvailable()) return fail(CS_FAIL, 'USB_READER_API_UNAVAILABLE') + const code = dll.dllPrinterMoveToUsbReader() + return code === CS_OK ? ok() : fail(code, '读卡失败') + } catch (err) { + return fail(CS_FAIL, String(err)) + } + }) + + // 退卡:移动卡片到出卡区(SAPI_PrinterMovetohopper) + tracedHandle('dll:printer-eject-card', async () => { + try { + assertReady() + const dll = await loadDllModule() + if (!dll.isHopperApiAvailable()) return fail(CS_FAIL, 'HOPPER_API_UNAVAILABLE') + const code = dll.dllPrinterMoveToHopper() + return code === CS_OK ? ok() : fail(code, '退卡失败') + } catch (err) { + return fail(CS_FAIL, String(err)) + } + }) + tracedHandle('dll:printer-error-str', async (_e, errorNo?: number) => { if (!mainAppState.initialized) return ok({ text: '' }) try { diff --git a/app/src/main/services/open-design-app.ts b/app/src/main/services/open-design-app.ts index 97435df..08cbcb0 100644 --- a/app/src/main/services/open-design-app.ts +++ b/app/src/main/services/open-design-app.ts @@ -23,7 +23,9 @@ export async function openDesignApp( const target = path.resolve(exePath.trim()) const err = await shell.openPath(target) if (err) { - return { ok: false, message: err } + // 用户在 UAC/系统弹窗中点击"否"或被系统拒绝时,shell.openPath 返回通用错误字符串 + // 不把原始 "Failed to Open Path" 直接抛给用户,给出可读说明 + return { ok: false, message: '打开设计软件失败,可能已被取消或需要管理员权限' } } return { ok: true } } diff --git a/app/src/main/services/work-dll.service.ts b/app/src/main/services/work-dll.service.ts index 5c77371..878b8c7 100644 --- a/app/src/main/services/work-dll.service.ts +++ b/app/src/main/services/work-dll.service.ts @@ -24,6 +24,8 @@ let SAPI_Init: any = null // eslint-disable-next-line @typescript-eslint/no-explicit-any let SAPI_GetPrinterInfo: any = null // eslint-disable-next-line @typescript-eslint/no-explicit-any +let SAPI_FreePrinterInfo: any = null +// eslint-disable-next-line @typescript-eslint/no-explicit-any let SAPI_GetPrinterErrorStr: any = null // eslint-disable-next-line @typescript-eslint/no-explicit-any let SAPI_RestJobEx: any = null @@ -77,6 +79,20 @@ function traceCall(name: string, args: Record | undefined, f } } +function freePrinterInfoPtr(ptr: number): void { + if (!ptr) return + // DLL 堆分配的缓冲区必须用 DLL 导出的释放函数;koffi.free 会触发 STATUS_HEAP_CORRUPTION + if (SAPI_FreePrinterInfo) { + try { + SAPI_FreePrinterInfo(ptr) + } catch (e) { + log.warn('SAPI_FreePrinterInfo failed', e) + } + return + } + log.warn('SAPI_FreePrinterInfo unavailable; printer info buffer not freed') +} + function readPrinterJsonFromOutPtr(len: number, outPtr: Buffer): { code: number; json?: Record } { if (len <= 0) return { code: len } const ptr = koffi.decode(outPtr, 0, 'void *') as number @@ -90,7 +106,7 @@ function readPrinterJsonFromOutPtr(len: number, outPtr: Buffer): { code: number; return { code: len } } } finally { - koffi.free(ptr) + freePrinterInfoPtr(ptr) } } @@ -110,6 +126,13 @@ function loadLibrary(): void { SAPI_GetUsbCopyState = lib.func('int __stdcall SAPI_GetUsbCopyState(_Out_ int *, _Out_ int *)') SAPI_PrinterResetprinter = lib.func('int __stdcall SAPI_PrinterResetprinter()') + try { + SAPI_FreePrinterInfo = lib.func('void __stdcall SAPI_FreePrinterInfo(void *)') + } catch { + SAPI_FreePrinterInfo = null + log.warn('SAPI_FreePrinterInfo not in workDll') + } + try { SAPI_UploadFile = lib.func('int __stdcall SAPI_UploadFile(str, str, str)') hasUploadApi = true @@ -151,6 +174,15 @@ function loadLibrary(): void { emitTrace('[dll] SAPI_PrinterMovetousbreader not in workDll (optional)') } + try { + SAPI_PrinterMovetohopper = lib.func('int __stdcall SAPI_PrinterMovetohopper()') + hasHopperApi = true + } catch { + SAPI_PrinterMovetohopper = null + hasHopperApi = false + emitTrace('[dll] SAPI_PrinterMovetohopper not in workDll (optional)') + } + try { SAPI_GetPrinterCardPosition = lib.func('int __stdcall SAPI_GetPrinterCardPosition(_Out_ int *)') hasCardPositionApi = true @@ -354,6 +386,14 @@ export function dllPrinterMoveToUsbReader(): number { }) } +export function dllPrinterMoveToHopper(): number { + return traceCall('SAPI_PrinterMovetohopper', undefined, () => { + loadLibrary() + if (!SAPI_PrinterMovetohopper) throw new Error('HOPPER_API_UNAVAILABLE') + return SAPI_PrinterMovetohopper() as number + }) +} + export function dllPrinterReject(): number { return traceCall('SAPI_PrinterMovetoreject', undefined, () => { loadLibrary() diff --git a/app/src/main/utils/ensure-console-utf8.ts b/app/src/main/utils/ensure-console-utf8.ts new file mode 100644 index 0000000..df4f156 --- /dev/null +++ b/app/src/main/utils/ensure-console-utf8.ts @@ -0,0 +1,21 @@ +import koffi from 'koffi' + +/** Windows 控制台默认多为 GBK,DLL 日志为 UTF-8,会导致中文乱码。 */ +export function ensureConsoleUtf8(): void { + if (process.platform !== 'win32') return + try { + const kernel32 = koffi.load('kernel32.dll') + const SetConsoleOutputCP = kernel32.func('bool __stdcall SetConsoleOutputCP(uint32)') + const SetConsoleCP = kernel32.func('bool __stdcall SetConsoleCP(uint32)') + SetConsoleOutputCP(65001) + SetConsoleCP(65001) + } catch { + /* ignore: no console or API unavailable */ + } + try { + if (process.stdout.setDefaultEncoding) process.stdout.setDefaultEncoding('utf8') + if (process.stderr.setDefaultEncoding) process.stderr.setDefaultEncoding('utf8') + } catch { + /* ignore */ + } +} diff --git a/app/src/renderer/src/api/cardsoon.ts b/app/src/renderer/src/api/cardsoon.ts index c816512..002fff2 100644 --- a/app/src/renderer/src/api/cardsoon.ts +++ b/app/src/renderer/src/api/cardsoon.ts @@ -34,6 +34,16 @@ export async function dllPrinterReject(): Promise { return api().invoke('dll:printer-reject') as Promise } +/** 读卡:移动卡片到读取区(SAPI_PrinterMovetousbreader) */ +export async function dllPrinterReadCard(): Promise { + return api().invoke('dll:printer-read-card') as Promise +} + +/** 退卡:移动卡片到出卡区(SAPI_PrinterMovetohopper) */ +export async function dllPrinterEjectCard(): Promise { + return api().invoke('dll:printer-eject-card') as Promise +} + export async function dllRejectAvailable(): Promise> { return api().invoke('dll:reject-available') as Promise> } diff --git a/app/src/renderer/src/assets/icons/index.ts b/app/src/renderer/src/assets/icons/index.ts index 7a56a8c..5a3baeb 100644 --- a/app/src/renderer/src/assets/icons/index.ts +++ b/app/src/renderer/src/assets/icons/index.ts @@ -13,7 +13,9 @@ export const ICON_NAMES = [ 'plus', 'exchange', 'stop', - 'warning' + 'warning', + 'id-card', + 'eject' ] as const export type IconName = (typeof ICON_NAMES)[number] @@ -34,5 +36,7 @@ export const ICON_FA_CLASS: Record = { plus: 'fas fa-plus', exchange: 'fas fa-exchange-alt', stop: 'fas fa-stop', - warning: 'fas fa-exclamation-triangle' + warning: 'fas fa-exclamation-triangle', + 'id-card': 'fas fa-id-card', + eject: 'fas fa-eject' } diff --git a/app/src/renderer/src/components/AppFooter.vue b/app/src/renderer/src/components/AppFooter.vue index a80e0ed..86b9005 100644 --- a/app/src/renderer/src/components/AppFooter.vue +++ b/app/src/renderer/src/components/AppFooter.vue @@ -1,7 +1,15 @@ + + diff --git a/app/src/renderer/src/components/AppHeader.vue b/app/src/renderer/src/components/AppHeader.vue index 46e2276..e4595f9 100644 --- a/app/src/renderer/src/components/AppHeader.vue +++ b/app/src/renderer/src/components/AppHeader.vue @@ -5,16 +5,24 @@
{{ mode }}
- 色带: {{ status.ribbonType }} - 余量: {{ status.ribbonAmount }} - 状态: {{ status.statusText }} - 序列号: {{ status.serialNo }} + {{ t('header.ribbon') }}: {{ status.ribbonType }} + {{ t('header.ribbonAmount') }}: {{ status.ribbonAmount }} + {{ t('header.status') }}: {{ displayStatusText }} + {{ t('header.serialNo') }}: {{ status.serialNo }}
+
@@ -24,16 +32,64 @@ + + diff --git a/app/src/renderer/src/components/NetworkPathDialog.vue b/app/src/renderer/src/components/NetworkPathDialog.vue index 11d5426..7abdee4 100644 --- a/app/src/renderer/src/components/NetworkPathDialog.vue +++ b/app/src/renderer/src/components/NetworkPathDialog.vue @@ -4,69 +4,69 @@
@@ -77,6 +77,7 @@