Compare commits

...

3 Commits

Author SHA1 Message Date
24kycj 057285ed89 优化 Electron 打包体积:排除源码与冗余依赖
配置 electron-builder files 仅打 out 产物,移除未用依赖并将 Vue 生态移至 devDependencies;koffi 仅解包 win32_x64 并在 afterPack 裁剪;打包前清理旧 zip。
2026-06-03 11:24:13 +08:00
24kycj 75490d8647 修复备卡位 13 自动续做:卡位 API 解析与会话同步
兼容 workDll 返回值即卡位编号的语义,启动卡位轮询时同步主进程 mode,并修正续做失败时的 phase 时序。
2026-06-03 10:27:04 +08:00
24kycj 3ec168350c 标签字段可编辑,Init 参数改从 cardsoon.config.json 读取
- 模板 type 3/4/5 文本可编辑,type 1 支持选图
- cardsoon.config.json 增加 sharedDir、logLevel、cleanTaskFile(默认 0)
- cleanTaskFile 默认改为 false,启动时同步 sharedDir 到运行时配置

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 09:43:10 +08:00
18 changed files with 373 additions and 401 deletions
+81 -342
View File
@@ -8,23 +8,21 @@
"name": "cardsoon-machine",
"version": "0.0.1",
"dependencies": {
"@fortawesome/fontawesome-free": "^6.4.0",
"electron-log": "^5.1.2",
"electron-store": "^8.1.0",
"element-plus": "^2.4.4",
"koffi": "^2.9.0",
"pinia": "^2.1.7",
"vue": "^3.4.21",
"vue-router": "^4.3.0"
"koffi": "^2.9.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.6.2",
"electron": "20.3.12",
"electron-builder": "^24.13.3",
"electron-vite": "^1.0.29",
"pinia": "^2.1.7",
"sass": "^1.69.5",
"typescript": "^5.3.3",
"vite": "^4.5.2",
"vue": "^3.4.21",
"vue-router": "^4.3.0",
"vue-tsc": "^1.8.27"
},
"engines": {
@@ -168,6 +166,7 @@
"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"
}
@@ -176,6 +175,7 @@
"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,6 +206,7 @@
"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"
},
@@ -267,6 +268,7 @@
"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"
@@ -275,14 +277,6 @@
"node": ">=6.9.0"
}
},
"node_modules/@ctrl/tinycolor": {
"version": "4.2.0",
"resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-4.2.0.tgz",
"integrity": "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==",
"engines": {
"node": ">=14"
}
},
"node_modules/@develar/schema-utils": {
"version": "2.6.5",
"resolved": "https://registry.npmmirror.com/@develar/schema-utils/-/schema-utils-2.6.5.tgz",
@@ -586,14 +580,6 @@
"node": ">= 10.0.0"
}
},
"node_modules/@element-plus/icons-vue": {
"version": "2.3.2",
"resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz",
"integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==",
"peerDependencies": {
"vue": "^3.2.0"
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.18.20",
"resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
@@ -946,37 +932,6 @@
"node": ">=12"
}
},
"node_modules/@floating-ui/core": {
"version": "1.7.5",
"resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.5.tgz",
"integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
"dependencies": {
"@floating-ui/utils": "^0.2.11"
}
},
"node_modules/@floating-ui/dom": {
"version": "1.7.6",
"resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.6.tgz",
"integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
"dependencies": {
"@floating-ui/core": "^1.7.5",
"@floating-ui/utils": "^0.2.11"
}
},
"node_modules/@floating-ui/utils": {
"version": "0.2.11",
"resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.11.tgz",
"integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="
},
"node_modules/@fortawesome/fontawesome-free": {
"version": "6.4.0",
"resolved": "https://registry.npmmirror.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.4.0.tgz",
"integrity": "sha512-0NyytTlPJwB/BF5LtRV8rrABDbe3TdTXqNB3PdZ+UUUZAEIrdOJdmABqKjt4AXwIoJNaRVVZEXxpNrqvE1GAYQ==",
"hasInstallScript": true,
"engines": {
"node": ">=6"
}
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmmirror.com/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -1105,7 +1060,8 @@
"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=="
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
"dev": true
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.31",
@@ -1496,16 +1452,6 @@
"node": ">=14"
}
},
"node_modules/@popperjs/core": {
"name": "@sxzz/popperjs-es",
"version": "2.11.8",
"resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.8.tgz",
"integrity": "sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@sindresorhus/is": {
"version": "0.14.0",
"resolved": "https://registry.npmmirror.com/@sindresorhus/is/-/is-0.14.0.tgz",
@@ -1554,19 +1500,6 @@
"@types/node": "*"
}
},
"node_modules/@types/lodash": {
"version": "4.17.24",
"resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.24.tgz",
"integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ=="
},
"node_modules/@types/lodash-es": {
"version": "4.17.12",
"resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz",
"integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
"dependencies": {
"@types/lodash": "*"
}
},
"node_modules/@types/ms": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/@types/ms/-/ms-2.1.0.tgz",
@@ -1597,11 +1530,6 @@
"dev": true,
"optional": true
},
"node_modules/@types/web-bluetooth": {
"version": "0.0.21",
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
"integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA=="
},
"node_modules/@types/yauzl": {
"version": "2.10.3",
"resolved": "https://registry.npmmirror.com/@types/yauzl/-/yauzl-2.10.3.tgz",
@@ -1657,6 +1585,7 @@
"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",
@@ -1669,6 +1598,7 @@
"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"
@@ -1678,6 +1608,7 @@
"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",
@@ -1694,6 +1625,7 @@
"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"
@@ -1702,7 +1634,8 @@
"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=="
"integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
"dev": true
},
"node_modules/@vue/language-core": {
"version": "1.8.27",
@@ -1733,6 +1666,7 @@
"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"
}
@@ -1741,6 +1675,7 @@
"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"
@@ -1750,6 +1685,7 @@
"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",
@@ -1761,6 +1697,7 @@
"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"
@@ -1772,42 +1709,8 @@
"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=="
},
"node_modules/@vueuse/core": {
"version": "14.3.0",
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-14.3.0.tgz",
"integrity": "sha512-aHfz47g0ZhMtTVHmIzMVpJy8ePhhOy68GY5bv110+5DVtZ+W7BsOx+m61UNQqfrWyPztIHIanWa3E2tib3NFIw==",
"dependencies": {
"@types/web-bluetooth": "^0.0.21",
"@vueuse/metadata": "14.3.0",
"@vueuse/shared": "14.3.0"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"vue": "^3.5.0"
}
},
"node_modules/@vueuse/metadata": {
"version": "14.3.0",
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-14.3.0.tgz",
"integrity": "sha512-BwxmbAzwAVF50+MW57GXOUEV61nFBGnlBvrTqj49PqWJu3uw7hdu72ztXeZ33RdZtDY6kO+bfCAE1PCn88Tktw==",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared": {
"version": "14.3.0",
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-14.3.0.tgz",
"integrity": "sha512-bZpge9eSXwa4ToSiqJ7j6KRwhAsneMFoSz3LMWKQDkqimm3D/tbFlrklrs/IOqC8tEcYmXQZJ6N0UrjhBirVCg==",
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"vue": "^3.5.0"
}
"integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==",
"dev": true
},
"node_modules/@xmldom/xmldom": {
"version": "0.9.10",
@@ -2113,11 +2016,6 @@
"node": ">=0.12.0"
}
},
"node_modules/async-validator": {
"version": "4.2.5",
"resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
"integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
@@ -2778,12 +2676,8 @@
"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=="
},
"node_modules/dayjs": {
"version": "1.11.20",
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.20.tgz",
"integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ=="
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
"dev": true
},
"node_modules/de-indent": {
"version": "1.0.2",
@@ -3352,31 +3246,6 @@
}
}
},
"node_modules/element-plus": {
"version": "2.14.0",
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.14.0.tgz",
"integrity": "sha512-POgH+TtoreaEKWqYYAVQyE6i8rQMEFqAEublyF29dBA5yASWPLKY6EzfeqBTr2Uv26mPss4vSrMrNPyaK7LX5w==",
"dependencies": {
"@ctrl/tinycolor": "^4.2.0",
"@element-plus/icons-vue": "^2.3.2",
"@floating-ui/dom": "^1.0.1",
"@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.8",
"@types/lodash": "^4.17.24",
"@types/lodash-es": "^4.17.12",
"@vueuse/core": "14.3.0",
"async-validator": "^4.2.5",
"dayjs": "^1.11.20",
"lodash": "^4.18.1",
"lodash-es": "^4.18.1",
"lodash-unified": "^1.0.3",
"memoize-one": "^6.0.0",
"normalize-wheel-es": "^1.2.0",
"vue-component-type-helpers": "^3.2.8"
},
"peerDependencies": {
"vue": "^3.3.7"
}
},
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -3406,6 +3275,7 @@
"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"
},
@@ -3541,7 +3411,8 @@
"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=="
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true
},
"node_modules/extract-zip": {
"version": "2.0.1",
@@ -4465,22 +4336,8 @@
"node_modules/lodash": {
"version": "4.18.1",
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.18.1.tgz",
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="
},
"node_modules/lodash-es": {
"version": "4.18.1",
"resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.18.1.tgz",
"integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A=="
},
"node_modules/lodash-unified": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz",
"integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==",
"peerDependencies": {
"@types/lodash-es": "*",
"lodash": "*",
"lodash-es": "*"
}
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
"dev": true
},
"node_modules/lodash.defaults": {
"version": "4.2.0",
@@ -4539,6 +4396,7 @@
"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,11 +4423,6 @@
"node": ">= 0.4"
}
},
"node_modules/memoize-one": {
"version": "6.0.0",
"resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz",
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
},
"node_modules/mime": {
"version": "2.6.0",
"resolved": "https://registry.npmmirror.com/mime/-/mime-2.6.0.tgz",
@@ -4712,6 +4565,7 @@
"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",
@@ -4757,11 +4611,6 @@
"node": ">=8"
}
},
"node_modules/normalize-wheel-es": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
"integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw=="
},
"node_modules/npm-conf": {
"version": "1.1.3",
"resolved": "https://registry.npmmirror.com/npm-conf/-/npm-conf-1.1.3.tgz",
@@ -4928,7 +4777,8 @@
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true
},
"node_modules/picomatch": {
"version": "4.0.4",
@@ -4957,6 +4807,7 @@
"version": "2.3.1",
"resolved": "https://registry.npmmirror.com/pinia/-/pinia-2.3.1.tgz",
"integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==",
"dev": true,
"dependencies": {
"@vue/devtools-api": "^6.6.3",
"vue-demi": "^0.14.10"
@@ -5003,6 +4854,7 @@
"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",
@@ -5420,6 +5272,7 @@
"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"
}
@@ -5686,7 +5539,7 @@
"version": "5.3.3",
"resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.3.3.tgz",
"integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
"devOptional": true,
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -5842,6 +5695,7 @@
"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",
@@ -5858,15 +5712,11 @@
}
}
},
"node_modules/vue-component-type-helpers": {
"version": "3.3.1",
"resolved": "https://registry.npmmirror.com/vue-component-type-helpers/-/vue-component-type-helpers-3.3.1.tgz",
"integrity": "sha512-pu58kqxmVyEH6VfNYW1UyEfR3XAnJ27ZXT3yzXxxpjLxVzAbyC35Zk/nm/RMs7ijWnJNSd9fWkeex2OhUsx3MA=="
},
"node_modules/vue-demi": {
"version": "0.14.10",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"dev": true,
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
@@ -5892,6 +5742,7 @@
"version": "4.6.4",
"resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.6.4.tgz",
"integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==",
"dev": true,
"dependencies": {
"@vue/devtools-api": "^6.6.4"
},
@@ -6199,12 +6050,14 @@
"@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=="
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
"dev": true
},
"@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=="
"integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
"dev": true
},
"@babel/helper-validator-option": {
"version": "7.27.1",
@@ -6226,6 +6079,7 @@
"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"
}
@@ -6269,16 +6123,12 @@
"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"
}
},
"@ctrl/tinycolor": {
"version": "4.2.0",
"resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-4.2.0.tgz",
"integrity": "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A=="
},
"@develar/schema-utils": {
"version": "2.6.5",
"resolved": "https://registry.npmmirror.com/@develar/schema-utils/-/schema-utils-2.6.5.tgz",
@@ -6519,12 +6369,6 @@
}
}
},
"@element-plus/icons-vue": {
"version": "2.3.2",
"resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz",
"integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==",
"requires": {}
},
"@esbuild/android-arm": {
"version": "0.18.20",
"resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
@@ -6679,33 +6523,6 @@
"dev": true,
"optional": true
},
"@floating-ui/core": {
"version": "1.7.5",
"resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.5.tgz",
"integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
"requires": {
"@floating-ui/utils": "^0.2.11"
}
},
"@floating-ui/dom": {
"version": "1.7.6",
"resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.6.tgz",
"integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
"requires": {
"@floating-ui/core": "^1.7.5",
"@floating-ui/utils": "^0.2.11"
}
},
"@floating-ui/utils": {
"version": "0.2.11",
"resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.11.tgz",
"integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="
},
"@fortawesome/fontawesome-free": {
"version": "6.4.0",
"resolved": "https://registry.npmmirror.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.4.0.tgz",
"integrity": "sha512-0NyytTlPJwB/BF5LtRV8rrABDbe3TdTXqNB3PdZ+UUUZAEIrdOJdmABqKjt4AXwIoJNaRVVZEXxpNrqvE1GAYQ=="
},
"@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmmirror.com/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -6800,7 +6617,8 @@
"@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=="
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
"dev": true
},
"@jridgewell/trace-mapping": {
"version": "0.3.31",
@@ -6987,11 +6805,6 @@
"dev": true,
"optional": true
},
"@popperjs/core": {
"version": "npm:@sxzz/popperjs-es@2.11.8",
"resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.8.tgz",
"integrity": "sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ=="
},
"@sindresorhus/is": {
"version": "0.14.0",
"resolved": "https://registry.npmmirror.com/@sindresorhus/is/-/is-0.14.0.tgz",
@@ -7031,19 +6844,6 @@
"@types/node": "*"
}
},
"@types/lodash": {
"version": "4.17.24",
"resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.24.tgz",
"integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ=="
},
"@types/lodash-es": {
"version": "4.17.12",
"resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz",
"integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
"requires": {
"@types/lodash": "*"
}
},
"@types/ms": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/@types/ms/-/ms-2.1.0.tgz",
@@ -7074,11 +6874,6 @@
"dev": true,
"optional": true
},
"@types/web-bluetooth": {
"version": "0.0.21",
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
"integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA=="
},
"@types/yauzl": {
"version": "2.10.3",
"resolved": "https://registry.npmmirror.com/@types/yauzl/-/yauzl-2.10.3.tgz",
@@ -7128,6 +6923,7 @@
"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",
@@ -7140,6 +6936,7 @@
"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"
@@ -7149,6 +6946,7 @@
"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",
@@ -7165,6 +6963,7 @@
"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"
@@ -7173,7 +6972,8 @@
"@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=="
"integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
"dev": true
},
"@vue/language-core": {
"version": "1.8.27",
@@ -7196,6 +6996,7 @@
"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"
}
@@ -7204,6 +7005,7 @@
"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"
@@ -7213,6 +7015,7 @@
"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",
@@ -7224,6 +7027,7 @@
"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"
@@ -7232,28 +7036,8 @@
"@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=="
},
"@vueuse/core": {
"version": "14.3.0",
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-14.3.0.tgz",
"integrity": "sha512-aHfz47g0ZhMtTVHmIzMVpJy8ePhhOy68GY5bv110+5DVtZ+W7BsOx+m61UNQqfrWyPztIHIanWa3E2tib3NFIw==",
"requires": {
"@types/web-bluetooth": "^0.0.21",
"@vueuse/metadata": "14.3.0",
"@vueuse/shared": "14.3.0"
}
},
"@vueuse/metadata": {
"version": "14.3.0",
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-14.3.0.tgz",
"integrity": "sha512-BwxmbAzwAVF50+MW57GXOUEV61nFBGnlBvrTqj49PqWJu3uw7hdu72ztXeZ33RdZtDY6kO+bfCAE1PCn88Tktw=="
},
"@vueuse/shared": {
"version": "14.3.0",
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-14.3.0.tgz",
"integrity": "sha512-bZpge9eSXwa4ToSiqJ7j6KRwhAsneMFoSz3LMWKQDkqimm3D/tbFlrklrs/IOqC8tEcYmXQZJ6N0UrjhBirVCg==",
"requires": {}
"integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==",
"dev": true
},
"@xmldom/xmldom": {
"version": "0.9.10",
@@ -7497,11 +7281,6 @@
"integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==",
"dev": true
},
"async-validator": {
"version": "4.2.5",
"resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
"integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
@@ -7979,12 +7758,8 @@
"csstype": {
"version": "3.2.3",
"resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz",
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="
},
"dayjs": {
"version": "1.11.20",
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.20.tgz",
"integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ=="
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
"dev": true
},
"de-indent": {
"version": "1.0.2",
@@ -8423,28 +8198,6 @@
"picocolors": "^1.0.0"
}
},
"element-plus": {
"version": "2.14.0",
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.14.0.tgz",
"integrity": "sha512-POgH+TtoreaEKWqYYAVQyE6i8rQMEFqAEublyF29dBA5yASWPLKY6EzfeqBTr2Uv26mPss4vSrMrNPyaK7LX5w==",
"requires": {
"@ctrl/tinycolor": "^4.2.0",
"@element-plus/icons-vue": "^2.3.2",
"@floating-ui/dom": "^1.0.1",
"@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.8",
"@types/lodash": "^4.17.24",
"@types/lodash-es": "^4.17.12",
"@vueuse/core": "14.3.0",
"async-validator": "^4.2.5",
"dayjs": "^1.11.20",
"lodash": "^4.18.1",
"lodash-es": "^4.18.1",
"lodash-unified": "^1.0.3",
"memoize-one": "^6.0.0",
"normalize-wheel-es": "^1.2.0",
"vue-component-type-helpers": "^3.2.8"
}
},
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -8470,7 +8223,8 @@
"entities": {
"version": "7.0.1",
"resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz",
"integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="
"integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
"dev": true
},
"env-paths": {
"version": "2.2.1",
@@ -8569,7 +8323,8 @@
"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=="
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true
},
"extract-zip": {
"version": "2.0.1",
@@ -9279,18 +9034,8 @@
"lodash": {
"version": "4.18.1",
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.18.1.tgz",
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="
},
"lodash-es": {
"version": "4.18.1",
"resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.18.1.tgz",
"integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A=="
},
"lodash-unified": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz",
"integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==",
"requires": {}
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
"dev": true
},
"lodash.defaults": {
"version": "4.2.0",
@@ -9346,6 +9091,7 @@
"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"
}
@@ -9366,11 +9112,6 @@
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"dev": true
},
"memoize-one": {
"version": "6.0.0",
"resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz",
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
},
"mime": {
"version": "2.6.0",
"resolved": "https://registry.npmmirror.com/mime/-/mime-2.6.0.tgz",
@@ -9472,7 +9213,8 @@
"nanoid": {
"version": "3.3.12",
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.12.tgz",
"integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ=="
"integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
"dev": true
},
"node-addon-api": {
"version": "7.1.1",
@@ -9500,11 +9242,6 @@
"integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==",
"dev": true
},
"normalize-wheel-es": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
"integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw=="
},
"npm-conf": {
"version": "1.1.3",
"resolved": "https://registry.npmmirror.com/npm-conf/-/npm-conf-1.1.3.tgz",
@@ -9630,7 +9367,8 @@
"picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true
},
"picomatch": {
"version": "4.0.4",
@@ -9650,6 +9388,7 @@
"version": "2.3.1",
"resolved": "https://registry.npmmirror.com/pinia/-/pinia-2.3.1.tgz",
"integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==",
"dev": true,
"requires": {
"@vue/devtools-api": "^6.6.3",
"vue-demi": "^0.14.10"
@@ -9678,6 +9417,7 @@
"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",
@@ -9969,7 +9709,8 @@
"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=="
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"dev": true
},
"source-map-support": {
"version": "0.5.21",
@@ -10185,7 +9926,7 @@
"version": "5.3.3",
"resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.3.3.tgz",
"integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
"devOptional": true
"dev": true
},
"universalify": {
"version": "0.1.2",
@@ -10262,6 +10003,7 @@
"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",
@@ -10270,21 +10012,18 @@
"@vue/shared": "3.5.34"
}
},
"vue-component-type-helpers": {
"version": "3.3.1",
"resolved": "https://registry.npmmirror.com/vue-component-type-helpers/-/vue-component-type-helpers-3.3.1.tgz",
"integrity": "sha512-pu58kqxmVyEH6VfNYW1UyEfR3XAnJ27ZXT3yzXxxpjLxVzAbyC35Zk/nm/RMs7ijWnJNSd9fWkeex2OhUsx3MA=="
},
"vue-demi": {
"version": "0.14.10",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"dev": true,
"requires": {}
},
"vue-router": {
"version": "4.6.4",
"resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.6.4.tgz",
"integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==",
"dev": true,
"requires": {
"@vue/devtools-api": "^6.6.4"
}
+22 -15
View File
@@ -12,30 +12,39 @@
"build": "electron-vite build",
"preview": "electron-vite preview",
"typecheck": "vue-tsc --noEmit -p tsconfig.web.json",
"predist": "node scripts/check-native-dlls.js",
"predist": "node scripts/check-native-dlls.js && node scripts/clean-release-artifacts.js",
"predist:dir": "node scripts/check-native-dlls.js",
"predist:zip": "node scripts/check-native-dlls.js",
"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"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^6.4.0",
"electron-log": "^5.1.2",
"electron-store": "^8.1.0",
"element-plus": "^2.4.4",
"koffi": "^2.9.0",
"pinia": "^2.1.7",
"vue": "^3.4.21",
"vue-router": "^4.3.0"
"koffi": "^2.9.0"
},
"build": {
"appId": "com.cardsoon.machine",
"productName": "卡树数据卡打印系统",
"asar": true,
"asarUnpack": [
"**/node_modules/koffi/**"
"node_modules/koffi/build/koffi/win32_x64/**"
],
"files": [
"out/**/*",
"!src/**",
"!scripts/**",
"!resources/**",
"!release/**",
"!release-pack/**",
"!electron.vite.config.ts",
"!tsconfig*.json",
"!tsconfig.web.tsbuildinfo",
"!.nvmrc"
],
"afterPack": "scripts/prune-pack.js",
"npmRebuild": false,
"directories": {
"output": "release"
},
@@ -53,16 +62,11 @@
{
"from": "resources/native/CapSettings.json",
"to": "CapSettings.json"
},
{
"from": "resources/cardsoon.config.json",
"to": "cardsoon.config.json"
}
],
"win": {
"target": [
"zip",
"nsis"
"zip"
],
"signAndEditExecutable": false
},
@@ -82,9 +86,12 @@
"electron": "20.3.12",
"electron-builder": "^24.13.3",
"electron-vite": "^1.0.29",
"pinia": "^2.1.7",
"sass": "^1.69.5",
"typescript": "^5.3.3",
"vite": "^4.5.2",
"vue": "^3.4.21",
"vue-router": "^4.3.0",
"vue-tsc": "^1.8.27"
}
}
+4 -1
View File
@@ -1,3 +1,6 @@
{
"designAppPath": "D:\\SoonProject\\SoonDesign\\build\\win-unpacked\\SoonDesign.exe"
"designAppPath": "D:\\SoonProject\\SoonDesign\\build\\win-unpacked\\SoonDesign.exe",
"sharedDir": "C:\\PrintTasks",
"logLevel": 3,
"cleanTaskFile": 0
}
+9
View File
@@ -14,6 +14,15 @@ const required = [
'opencv_world490d.dll'
]
const opencvRelease = path.join(nativeDir, 'opencv_world490.dll')
const opencvDebug = path.join(nativeDir, 'opencv_world490d.dll')
if (fs.existsSync(opencvRelease)) {
console.warn('提示: 检测到 opencv_world490.dll,生产环境建议用 Release 版替换 Debug 版 opencv_world490d.dll 以减小体积')
} else if (fs.existsSync(opencvDebug)) {
const mb = Math.round(fs.statSync(opencvDebug).size / 1024 / 1024)
console.warn(`提示: 当前使用 Debug 版 OpenCV (${mb} MB),可从 docs/API/lib 换 Release 版 opencv_world490.dll`)
}
const missing = required.filter((name) => !fs.existsSync(path.join(nativeDir, name)))
if (missing.length) {
console.error(`resources/native 缺少: ${missing.join(', ')}`)
+12
View File
@@ -0,0 +1,12 @@
/** 打包前清理 release 目录中的旧 zip,避免误统计体积 */
const fs = require('fs')
const path = require('path')
const releaseDir = path.join(__dirname, '..', 'release')
if (!fs.existsSync(releaseDir)) process.exit(0)
for (const name of fs.readdirSync(releaseDir)) {
if (name.endsWith('.zip')) {
fs.unlinkSync(path.join(releaseDir, name))
}
}
+31
View File
@@ -0,0 +1,31 @@
/** electron-builder afterPack:仅保留 Windows x64 的 koffi 原生模块 */
const fs = require('fs')
const path = require('path')
const KOFFI_KEEP = new Set(['build', 'index.js', 'indirect.js', 'package.json', 'LICENSE.txt'])
const NATIVE_PLATFORM = 'win32_x64'
exports.default = async function afterPack(context) {
const koffiRoot = path.join(
context.appOutDir,
'resources',
'app.asar.unpacked',
'node_modules',
'koffi'
)
if (!fs.existsSync(koffiRoot)) return
for (const name of fs.readdirSync(koffiRoot)) {
if (!KOFFI_KEEP.has(name)) {
fs.rmSync(path.join(koffiRoot, name), { recursive: true, force: true })
}
}
const buildDir = path.join(koffiRoot, 'build', 'koffi')
if (!fs.existsSync(buildDir)) return
for (const plat of fs.readdirSync(buildDir)) {
if (plat !== NATIVE_PLATFORM) {
fs.rmSync(path.join(buildDir, plat), { recursive: true, force: true })
}
}
}
+2 -1
View File
@@ -15,7 +15,7 @@ if (!gotSingleInstanceLock) {
}
import { suppressKnownDllStderr } from './utils/suppress-dll-stderr'
import { loadAppFileConfig } from './services/app-config'
import { loadAppFileConfig, applyFileConfigToStore } from './services/app-config'
import { migrateTraceConfig, setTraceWebContents } from './utils/trace-bridge'
suppressKnownDllStderr()
@@ -133,6 +133,7 @@ app.whenReady().then(async () => {
try {
migrateTraceConfig()
loadAppFileConfig()
applyFileConfigToStore()
log.info('app startup', { packaged: app.isPackaged, execPath: process.execPath })
registerIpcHandlers()
try {
+4 -1
View File
@@ -287,9 +287,12 @@ export function registerIpcHandlers(): void {
return ok()
})
tracedHandle('poll:card-position-start', async () => {
tracedHandle('poll:card-position-start', async (_e, sessionMode?: 'distributing' | 'usbCopying') => {
try {
assertReady()
if (sessionMode === 'distributing' || sessionMode === 'usbCopying') {
mainAppState.mode = sessionMode
}
const dll = await loadDllModule()
if (!dll.isCardPositionApiAvailable()) {
return fail(CS_FAIL, '当前 DLL 不支持卡位查询,无法自动续做')
+54 -3
View File
@@ -2,20 +2,59 @@ import { app } from 'electron'
import fs from 'fs'
import path from 'path'
import log from 'electron-log'
import { LOG_FATAL_FLAG } from '../constants'
import { configStore } from './config-store'
import { getProcessExecDir } from './native-path'
export const APP_CONFIG_FILENAME = 'cardsoon.config.json'
const DEFAULT_SHARED_DIR = path.join('C:', 'PrintTasks')
export interface AppFileConfig {
designAppPath: string
sharedDir: string
logLevel: number
cleanTaskFile: boolean
}
const defaults: AppFileConfig = {
designAppPath: ''
designAppPath: '',
sharedDir: DEFAULT_SHARED_DIR,
logLevel: LOG_FATAL_FLAG,
cleanTaskFile: false
}
let cached: AppFileConfig | null = null
function pickRaw(raw: Record<string, unknown>, ...keys: string[]): unknown {
for (const key of keys) {
const hit = Object.entries(raw).find(([name]) => name.toLowerCase() === key.toLowerCase())
if (hit && hit[1] != null && String(hit[1]).trim() !== '') return hit[1]
}
return undefined
}
function parseCleanTaskFile(raw: unknown): boolean {
if (raw === undefined || raw === null) return defaults.cleanTaskFile
if (typeof raw === 'boolean') return raw
if (typeof raw === 'number') return raw !== 0
const s = String(raw).trim().toLowerCase()
if (s === '0' || s === 'false') return false
if (s === '1' || s === 'true') return true
return defaults.cleanTaskFile
}
function parseLogLevel(raw: unknown): number {
if (raw === undefined || raw === null) return defaults.logLevel
const n = Number(raw)
return Number.isFinite(n) ? Math.round(n) : defaults.logLevel
}
function parseSharedDir(raw: unknown): string {
const s = String(raw ?? '').trim()
return s || DEFAULT_SHARED_DIR
}
function bundledConfigPath(): string {
if (app.isPackaged) {
return path.join(process.resourcesPath, APP_CONFIG_FILENAME)
@@ -33,7 +72,10 @@ function configSearchPaths(): string[] {
function parseConfigFile(filePath: string): AppFileConfig {
const raw = JSON.parse(fs.readFileSync(filePath, 'utf8')) as Record<string, unknown>
return {
designAppPath: String(raw.designAppPath ?? '').trim()
designAppPath: String(pickRaw(raw, 'designAppPath') ?? '').trim(),
sharedDir: parseSharedDir(pickRaw(raw, 'sharedDir', 'shareddir')),
logLevel: parseLogLevel(pickRaw(raw, 'logLevel', 'loglevel')),
cleanTaskFile: parseCleanTaskFile(pickRaw(raw, 'cleanTaskFile', 'cleantaskfile'))
}
}
@@ -44,7 +86,11 @@ export function loadAppFileConfig(): AppFileConfig {
if (!fs.existsSync(filePath)) continue
try {
cached = parseConfigFile(filePath)
log.info(`Loaded ${APP_CONFIG_FILENAME} from ${filePath}`)
log.info(`Loaded ${APP_CONFIG_FILENAME} from ${filePath}`, {
sharedDir: cached.sharedDir,
logLevel: cached.logLevel,
cleanTaskFile: cached.cleanTaskFile
})
return cached
} catch (e) {
log.warn(`Skip invalid ${APP_CONFIG_FILENAME}: ${filePath}`, e)
@@ -58,6 +104,11 @@ export function loadAppFileConfig(): AppFileConfig {
return cached
}
export function applyFileConfigToStore(): void {
const cfg = loadAppFileConfig()
configStore.set('sharedDir', cfg.sharedDir)
}
export function getDesignAppPath(): string {
return loadAppFileConfig().designAppPath
}
+5 -3
View File
@@ -3,6 +3,7 @@ import log from 'electron-log'
import { CS_OK } from '../constants'
import { mainAppState } from './app-state'
import { configStore } from './config-store'
import { loadAppFileConfig } from './app-config'
import { loadDllModule } from './dll-loader'
import type { InitParams } from './work-dll.service'
@@ -18,8 +19,9 @@ export async function ensureDllInitialized(
if (dllInitAttempted) {
return { code: CS_OK }
}
const fileCfg = loadAppFileConfig()
const sharedDir =
params?.sharedDir || (configStore.get('sharedDir') as string) || 'C:\\PrintTasks'
params?.sharedDir?.trim() || fileCfg.sharedDir || (configStore.get('sharedDir') as string)
try {
const dll = await loadDllModule()
fs.mkdirSync(sharedDir, { recursive: true })
@@ -27,10 +29,10 @@ export async function ensureDllInitialized(
sharedDir,
keepCombinedImage: params?.keepCombinedImage,
stopOnFailure: params?.stopOnFailure,
cleanTaskFile: params?.cleanTaskFile,
cleanTaskFile: params?.cleanTaskFile ?? fileCfg.cleanTaskFile,
autoRetryTimes: params?.autoRetryTimes,
rejectConfig: params?.rejectConfig,
logLevel: params?.logLevel,
logLevel: params?.logLevel ?? fileCfg.logLevel,
outBack: params?.outBack
})
dllInitAttempted = true
+6 -5
View File
@@ -1,6 +1,7 @@
import path from 'path'
import koffi from 'koffi'
import log from 'electron-log'
import { normalizeCardPositionQuery } from '@shared/card-position'
import { CS_OK, JOB_ID_BUF_SIZE, LOG_FATAL_FLAG } from '../constants'
import { emitTrace, isTraceEnabled } from '../utils/trace-bridge'
import { getNativeDir } from './native-path'
@@ -239,7 +240,7 @@ export function dllInit(params: InitParams): number {
sharedDir: params.sharedDir,
keepCombinedImage: params.keepCombinedImage ?? true,
stopOnFailure: params.stopOnFailure ?? false,
cleanTaskFile: params.cleanTaskFile ?? true,
cleanTaskFile: params.cleanTaskFile ?? false,
autoRetryTimes: params.autoRetryTimes ?? 0,
rejectConfig: params.rejectConfig ?? false,
logLevel: params.logLevel ?? LOG_FATAL_FLAG,
@@ -251,7 +252,7 @@ export function dllInit(params: InitParams): number {
params.sharedDir,
params.keepCombinedImage ?? true,
params.stopOnFailure ?? false,
params.cleanTaskFile ?? true,
params.cleanTaskFile ?? false,
params.autoRetryTimes ?? 0,
params.rejectConfig ?? false,
params.logLevel ?? LOG_FATAL_FLAG,
@@ -396,9 +397,9 @@ export function dllGetPrinterCardPosition(): { queryCode: number; position: numb
return traceCall('SAPI_GetPrinterCardPosition', undefined, () => {
loadLibrary()
if (!SAPI_GetPrinterCardPosition) throw new Error('CARD_POSITION_API_UNAVAILABLE')
const position = [0]
const queryCode = SAPI_GetPrinterCardPosition!(position) as number
return { queryCode, position: position[0] }
const out = [0]
const ret = SAPI_GetPrinterCardPosition!(out) as number
return normalizeCardPositionQuery(ret, out[0])
})
}
+5 -3
View File
@@ -5,6 +5,8 @@ export interface TemplateFieldRow {
label: string
value: string
originName: string
/** soon frontData/backData 的 type1=图片,3/4/5=文本可编辑 */
fieldType: number
}
export interface ParsedSoonTemplate {
@@ -80,7 +82,7 @@ function parseSoonWorkerDisk(soonPath: string, raw: Record<string, unknown>): Pa
const name = String(o.name ?? '').trim()
if (!name) continue
const value = o.DefaultText == null ? '' : String(o.DefaultText)
fields.push({ label: `${name}[${side}]`, value, originName: name })
fields.push({ label: `${name}[${side}]`, value, originName: name, fieldType: type })
}
}
@@ -115,7 +117,7 @@ function parseSoonLegacy(soonPath: string, raw: Record<string, unknown>): Parsed
if (side === 'front') {
if (!frontImageUrl) frontImageUrl = url
const name = pickStr(item, ['name', 'field', 'key']) || 'IMAGE'
fields.push({ label: toFieldLabel(name, 'front'), value: fileRef, originName: name })
fields.push({ label: toFieldLabel(name, 'front'), value: fileRef, originName: name, fieldType: 1 })
} else if (!backImageUrl) {
backImageUrl = url
}
@@ -127,7 +129,7 @@ function parseSoonLegacy(soonPath: string, raw: Record<string, unknown>): Parsed
const value = pickStr(item, ['value', 'text', 'default', 'content', 'data'])
let side = sideOf(item)
if (!side) side = /image|img|front/i.test(name) ? 'front' : 'back'
fields.push({ label: toFieldLabel(name, side), value, originName: name })
fields.push({ label: toFieldLabel(name, side), value, originName: name, fieldType: 5 })
})
return { frontImageUrl, backImageUrl, fields, printFlag: readSoonPrintFlag(raw) }
+12 -4
View File
@@ -73,8 +73,10 @@ export async function pollUsbStop(opts?: { resetMode?: boolean }): Promise<IpcRe
return api().invoke('poll:usb-stop', opts) as Promise<IpcResult>
}
export async function pollCardPositionStart(): Promise<IpcResult> {
return api().invoke('poll:card-position-start') as Promise<IpcResult>
export async function pollCardPositionStart(
sessionMode?: 'distributing' | 'usbCopying'
): Promise<IpcResult> {
return api().invoke('poll:card-position-start', sessionMode) as Promise<IpcResult>
}
export async function pollCardPositionStop(): Promise<IpcResult> {
@@ -103,6 +105,12 @@ export async function dialogOpenSoon(): Promise<IpcResult<{ path: string }>> {
>
}
export async function dialogOpenImage(): Promise<IpcResult<{ path: string }>> {
return api().invoke('dialog:open-file', [
{ name: 'Image', extensions: ['jpg', 'jpeg', 'png', 'bmp', 'gif', 'webp'] }
]) as Promise<IpcResult<{ path: string }>>
}
export async function fsPathExists(paths: string[]): Promise<IpcResult<{ missing: string[] }>> {
return api().invoke('fs:path-exists', paths) as Promise<IpcResult<{ missing: string[] }>>
}
@@ -126,7 +134,7 @@ export async function fsParseSoon(filePath: string): Promise<
IpcResult<{
frontImageUrl: string
backImageUrl: string
fields: { label: string; value: string; originName: string }[]
fields: { label: string; value: string; originName: string; fieldType: number }[]
printFlag: number
}>
> {
@@ -134,7 +142,7 @@ export async function fsParseSoon(filePath: string): Promise<
IpcResult<{
frontImageUrl: string
backImageUrl: string
fields: { label: string; value: string; originName: string }[]
fields: { label: string; value: string; originName: string; fieldType: number }[]
printFlag: number
}>
>
@@ -4,6 +4,7 @@ export interface TemplateFieldRow {
label: string
value: string
originName: string
fieldType: number
}
export interface TemplatePreview {
@@ -566,6 +566,43 @@
min-width: 0;
}
.c-data-table-mini .c-field-input {
width: 100%;
height: 16px;
border: none;
background: transparent;
font-size: inherit;
font-weight: inherit;
color: inherit;
outline: none;
min-width: 0;
padding: 0;
}
.c-field-pick {
flex-shrink: 0;
border: 1px solid #dcdfe6;
border-radius: 3px;
background: #fff;
font-size: 8px;
font-weight: 700;
color: #495057;
padding: 0 6px;
height: 18px;
cursor: pointer;
}
.c-field-pick:hover {
background: #f1f3f5;
}
.c-field-value {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.c-path-cell__text {
flex: 1;
min-width: 0;
@@ -117,7 +117,21 @@
<table class="c-data-table-mini">
<tr v-for="(row, idx) in formStore.templatePreview!.fields" :key="idx">
<td>{{ row.label }}</td>
<td>
<td v-if="isImageField(row)" class="c-path-cell">
<span class="c-path-cell__text" :title="row.value">{{
imageFieldLabel(row.value)
}}</span>
<button type="button" class="c-field-pick" @click="pickFieldImage(idx)">选择</button>
</td>
<td v-else-if="isTextField(row)">
<input
v-model="row.value"
type="text"
class="c-field-input"
:placeholder="row.label"
/>
</td>
<td v-else>
<span class="c-field-value" :title="row.value">{{ row.value || '—' }}</span>
</td>
</tr>
@@ -148,8 +162,10 @@ import { useAppStore } from '@/stores/app'
import { validateJobPreflight } from '@/utils/validateJobPreflight'
import { createDistributeJob } from '@/utils/createDistributeJob'
import { formatBytesAsGb, formatBytesCompact } from '@/utils/formatBytes'
import type { TemplateFieldRow } from '@/stores/distributeForm'
import {
dialogOpenDirectory,
dialogOpenImage,
dialogOpenSoon,
dllJobCancel,
fsDirSize,
@@ -185,6 +201,36 @@ const loadProgressText = computed(() => {
return `已加载: ${loadedGb} GB / ${CARD_CAPACITY_GB} GB (${loadPercent.value}%)`
})
function isTextField(row: TemplateFieldRow): boolean {
return row.fieldType === 3 || row.fieldType === 4 || row.fieldType === 5
}
function isImageField(row: TemplateFieldRow): boolean {
return row.fieldType === 1
}
function imageFieldLabel(value: string): string {
const v = value.trim()
if (!v) return '未选择图片'
const parts = v.replace(/\\/g, '/').split('/')
return parts[parts.length - 1] || v
}
async function pickFieldImage(idx: number): Promise<void> {
const preview = formStore.templatePreview
if (!preview) return
const row = preview.fields[idx]
if (!row || !isImageField(row)) return
const r = await dialogOpenImage()
if (!r.ok) {
notify.error(r.message || '打开图片选择失败')
return
}
const picked = r.data?.path?.trim()
if (!picked) return
row.value = picked
}
function onClear(): void {
formStore.reset()
notify.info('已清空,已恢复初始状态')
@@ -341,11 +387,4 @@ async function onSubmit(): Promise<void> {
.c-card-small--back {
background: #f8f9fa;
}
.c-field-value {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>
@@ -218,16 +218,18 @@ async function stopTaskPollsOnly(): Promise<void> {
}
}
async function startCardPositionWatch(): Promise<void> {
async function startCardPositionWatch(
sessionMode: 'distributing' | 'usbCopying'
): Promise<void> {
await pollCardPositionStop()
const cardStarted = await pollCardPositionStart()
if (!cardStarted.ok) {
notify.warning(cardStarted.message || '无法监控卡位,请手动点击返回或重新提交')
}
unsubCard?.()
unsubCard = onCardPositionTick((payload) =>
applyCardPosition(payload as CardPositionPollPayload)
)
const cardStarted = await pollCardPositionStart(sessionMode)
if (!cardStarted.ok) {
notify.warning(cardStarted.message || '无法监控卡位,请手动点击返回或重新提交')
}
}
async function enterWaitPhase(next: 'completed' | 'failed', errorText = ''): Promise<void> {
@@ -253,9 +255,10 @@ async function enterWaitPhase(next: 'completed' | 'failed', errorText = ''): Pro
failureErrorText.value = errorText
}
await stopTaskPollsOnly()
appStore.setMode(isCollect.value ? 'usbCopying' : 'distributing')
const sessionMode = isCollect.value ? 'usbCopying' : 'distributing'
appStore.setMode(sessionMode)
lastCardPosition = -1
await startCardPositionWatch()
await startCardPositionWatch(sessionMode)
}
async function enterFailedPhase(errorText = ''): Promise<void> {
@@ -287,16 +290,8 @@ async function resubmitTask(): Promise<void> {
await pollCardPositionStop()
unsubCard?.()
unsubCard = null
phase.value = 'running'
setProgress(0)
workflowStep.value = 1
collectHint.value = ''
waitCard.value = false
queryFailStreak = 0
usbQueryFailStreak = 0
const backToWait = async (message?: string): Promise<void> => {
resubmitting = false
if (message) notify.error(message)
if (fromWaitPhase === 'failed') {
await enterFailedPhase(message || failureErrorText.value)
@@ -312,6 +307,12 @@ async function resubmitTask(): Promise<void> {
await backToWait('导入目录无效,无法继续')
return
}
phase.value = 'running'
setProgress(0)
workflowStep.value = 1
collectHint.value = ''
queryFailStreak = 0
usbQueryFailStreak = 0
const r = await dllUsbCopy(dest, collectStore.cardOutput, { resubmit: true })
if (!r.ok) {
await backToWait(r.message || '重新提交收集任务失败')
@@ -329,6 +330,11 @@ async function resubmitTask(): Promise<void> {
await backToWait()
return
}
phase.value = 'running'
setProgress(0)
workflowStep.value = 1
waitCard.value = false
queryFailStreak = 0
const created = await createDistributeJob(formStore, { resubmit: true })
if (!created.ok) {
await backToWait(created.message)
@@ -341,6 +347,8 @@ async function resubmitTask(): Promise<void> {
return
}
unsubJob = onJobPollTick((payload) => applyJobProgress(payload as JobPollPayload))
} catch (e) {
await backToWait(String(e))
} finally {
resubmitting = false
}
+18
View File
@@ -1 +1,19 @@
/** workDll 备卡位:检测到后可自动续做 */
export const POSITION_PREPARE = 13
/** 卡位编号合理上限(用于解析 DLL 返回值) */
export const POSITION_MAX = 32
/** 归一化 SAPI_GetPrinterCardPosition:兼容返回值=CS_OK 与返回值=卡位编号两种 DLL */
export function normalizeCardPositionQuery(
ret: number,
outPosition: number
): { queryCode: number; position: number } {
if (ret === 0) {
return { queryCode: 0, position: outPosition }
}
if (ret > 0 && ret <= POSITION_MAX) {
return { queryCode: 0, position: ret }
}
return { queryCode: ret, position: outPosition }
}