From 68d1968376cc4f690eefa1b9f87af2e659659469 Mon Sep 17 00:00:00 2001 From: 24kycj <1637269896@qq.com> Date: Tue, 12 May 2026 21:42:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .electron-vue/webpack.renderer.config.js | 1 + .electron-vue/webpack.web.config.js | 22 +- docs/BAOTA_DEPLOY.md | 226 ++++++++++++++++++ docs/WEBSOCKET_DEPLOY.md | 82 +++++++ docs/WEB_FEATURE_LIST.md | 154 ++++++++++++ package.json | 1 + src/index.ejs | 8 +- src/renderer/components/workAdd/files/calc.js | 34 ++- .../components/workAdd/files/file-back.vue | 108 ++++----- .../components/workAdd/files/file.vue | 89 +++---- src/renderer/components/workAdd/workAdd.vue | 159 ++++++------ src/renderer/main.js | 5 +- src/renderer/platform/desktop.js | 138 +++++++++++ src/renderer/platform/index.js | 31 +++ src/renderer/platform/web.js | 187 +++++++++++++++ src/renderer/store/index.js | 13 +- src/renderer/store/modules/chat.js | 14 +- src/renderer/utils/fileSize.js | 6 +- src/renderer/utils/index.js | 16 +- src/renderer/views/dashboard/index.vue | 56 +++-- src/renderer/views/login/index.vue | 43 +++- 21 files changed, 1120 insertions(+), 273 deletions(-) create mode 100644 docs/BAOTA_DEPLOY.md create mode 100644 docs/WEBSOCKET_DEPLOY.md create mode 100644 docs/WEB_FEATURE_LIST.md create mode 100644 src/renderer/platform/desktop.js create mode 100644 src/renderer/platform/index.js create mode 100644 src/renderer/platform/web.js diff --git a/.electron-vue/webpack.renderer.config.js b/.electron-vue/webpack.renderer.config.js index d83fb6d..e4b605b 100644 --- a/.electron-vue/webpack.renderer.config.js +++ b/.electron-vue/webpack.renderer.config.js @@ -139,6 +139,7 @@ let rendererConfig = { options: options, }, process, + isWeb: false, }; }, minify: { diff --git a/.electron-vue/webpack.web.config.js b/.electron-vue/webpack.web.config.js index b8b0708..dc741be 100644 --- a/.electron-vue/webpack.web.config.js +++ b/.electron-vue/webpack.web.config.js @@ -4,6 +4,8 @@ process.env.BABEL_ENV = 'web' const path = require('path') const webpack = require('webpack') +const config = require('../config') +const env = process.env.NODE_ENV === 'production' ? config.build.env : config.dev.env const MinifyPlugin = require("babel-minify-webpack-plugin") const CopyWebpackPlugin = require('copy-webpack-plugin') @@ -107,6 +109,7 @@ let webConfig = { options: options, }, process, + isWeb: true, }; }, minify: { @@ -117,7 +120,9 @@ let webConfig = { nodeModules: false }), new webpack.DefinePlugin({ - 'process.env.IS_WEB': 'true' + 'process.env.IS_WEB': '"true"', + 'process.env.BASE_API': env.BASE_API || '"https://easy-mock.com/mock/5950a2419adc231f356a6636/vue-admin"', + 'process.env.VUE_APP_SOCKET_API': env.VUE_APP_SOCKET_API || '"ws://127.0.0.1:10010"' }), new webpack.HotModuleReplacementPlugin(), new webpack.NoEmitOnErrorsPlugin() @@ -129,11 +134,24 @@ let webConfig = { resolve: { alias: { '@': path.join(__dirname, '../src/renderer'), + '@/platform': path.join(__dirname, '../src/renderer/platform/web.js'), 'vue$': 'vue/dist/vue.esm.js' }, extensions: ['.js', '.vue', '.json', '.css'] }, - target: 'web' + node: { + fs: 'empty', + path: 'empty', + child_process: 'empty' + }, + target: 'web', + devServer: process.env.NODE_ENV !== 'production' ? { + port: 9081, + hot: true, + open: true, + contentBase: path.join(__dirname, '../'), + publicPath: '/' + } : undefined } /** diff --git a/docs/BAOTA_DEPLOY.md b/docs/BAOTA_DEPLOY.md new file mode 100644 index 0000000..c906d0c --- /dev/null +++ b/docs/BAOTA_DEPLOY.md @@ -0,0 +1,226 @@ +# 宝塔部署 Web 端说明 + +## 一、构建前配置 + +### 1. 配置后端 API 地址 + +编辑 `config/prod.env.js`,将 `BASE_API` 改为实际的后端接口地址: + +```javascript +module.exports = { + NODE_ENV: '"production"', + BASE_API: '"https://your-api-domain.com/api"', // 改为实际后端地址 + VUE_APP_SOCKET_API: '"ws://127.0.0.1:10010"' // WebSocket 默认地址(用户可在登录页修改) +} +``` + +**注意:** +- `BASE_API` 是 HTTP 接口地址(登录、数据请求等) +- `VUE_APP_SOCKET_API` 是 WebSocket 默认地址,用户可在登录页修改,所以这里可以保持默认或设为公网地址 + +### 2. 执行构建 + +在项目根目录执行: + +```bash +npm run build:web +``` + +构建完成后,产物在 `dist/web/` 目录下,包含: +- `index.html`(入口文件) +- `web.js`(主 JS 文件,包含所有代码和样式) +- `1.js` ~ `7.js`(代码分割的 chunk 文件) +- `fonts/`(字体文件) +- `imgs/`(图片资源) + +**注意**:CSS 样式被打包进 `web.js` 中,运行时动态注入,无需单独引用 CSS 文件。 + +--- + +## 二、宝塔部署步骤 + +### 1. 创建网站 + +1. 登录宝塔面板 +2. 点击「网站」→「添加站点」 +3. 填写: + - **域名**:例如 `your-domain.com` 或 `192.168.1.100`(内网 IP) + - **根目录**:例如 `/www/wwwroot/your-domain.com` + - **PHP 版本**:选择「纯静态」或任意版本(前端不需要 PHP) + +### 2. 上传文件 + +将 `dist/web/` 目录下的**所有文件**上传到网站根目录: + +``` +/www/wwwroot/your-domain.com/ +├── index.html +├── web.js +├── styles.css +└── static/ + ├── imgs/ + └── fonts/ +``` + +**上传方式:** +- 方式一:在宝塔「文件」中直接上传压缩包并解压 +- 方式二:使用 FTP/SFTP 工具上传 +- 方式三:使用宝塔「终端」执行 `scp` 或 `rsync` 命令 + +### 3. 配置 Nginx(重要) + +由于是 Vue Router 的 hash 模式(`#/login`、`#/manage`),通常不需要特殊配置。但建议添加以下配置以确保正常访问: + +在宝塔「网站」→ 选择站点 →「设置」→「配置文件」中,在 `server` 块内添加: + +```nginx +server { + listen 80; + server_name your-domain.com; + root /www/wwwroot/your-domain.com; + index index.html; + + # 前端路由支持(hash 模式通常不需要,但加上更稳妥) + location / { + try_files $uri $uri/ /index.html; + } + + # 静态资源缓存 + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # 禁止访问隐藏文件 + location ~ /\. { + deny all; + } +} +``` + +### 4. 配置 HTTPS(可选但推荐) + +如果使用域名且需要 HTTPS: + +1. 在宝塔「网站」→ 选择站点 →「SSL」→「Let's Encrypt」申请免费证书 +2. 开启「强制 HTTPS」 +3. **注意**:如果后端 API 或 WebSocket 使用 HTTPS/WSS,确保: + - `BASE_API` 使用 `https://` + - WebSocket 地址使用 `wss://`(或在登录页填写 `wss://` 地址) + +### 5. 配置跨域(如需要) + +如果后端 API 与前端不在同一域名,后端需要配置 CORS: + +- 允许的源:`https://your-domain.com`(或 `*` 用于开发) +- 允许的请求头:`Content-Type, X-Token`(根据实际后端要求) +- 允许的方法:`GET, POST, PUT, DELETE` 等 + +--- + +## 三、WebSocket 配置 + +### 情况 1:WebSocket 服务在服务器本机 + +如果 WebSocket 服务运行在**宝塔服务器本机**(例如 `ws://127.0.0.1:10010`): + +- 用户访问网页时,浏览器会尝试连接**用户电脑**的 `127.0.0.1`,**无法连接** +- **解决方案**: + 1. 在登录页填写 `ws://服务器公网IP:10010` 或 `ws://服务器域名:10010` + 2. 或配置 Nginx 反向代理 WebSocket(见下方) + +### 情况 2:使用 Nginx 反向代理 WebSocket(推荐) + +在宝塔「网站」→ 选择站点 →「设置」→「配置文件」中添加: + +```nginx +# WebSocket 代理(假设后端 WebSocket 在 127.0.0.1:10010) +location /ws { + proxy_pass http://127.0.0.1:10010; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; +} +``` + +然后在登录页填写:`wss://your-domain.com/ws`(HTTPS 用 `wss://`,HTTP 用 `ws://`) + +### 情况 3:WebSocket 服务在公网服务器 + +如果 WebSocket 服务部署在**公网服务器**(例如 `wss://ws-api.xxx.com`): + +- 在登录页填写该地址即可 +- 或在构建时设置 `VUE_APP_SOCKET_API` 为 `wss://ws-api.xxx.com` + +--- + +## 四、访问测试 + +1. 打开浏览器访问:`http://your-domain.com` 或 `https://your-domain.com` +2. 应能看到登录页 +3. 点击「设置 WebSocket 服务地址」,填写实际可访问的 WebSocket 地址 +4. 输入账号密码登录 +5. 检查: + - 登录是否成功 + - WebSocket 是否连接成功(查看浏览器控制台 Network → WS) + - 各功能页面是否正常加载 + +--- + +## 五、常见问题 + +### 1. 页面空白 + +- **检查**:浏览器控制台是否有 JS 错误 +- **解决**:确认 `index.html` 中引用的 `web.js`、`styles.css` 路径正确;检查 Nginx 配置是否正确 + +### 2. 接口请求失败(404 或 CORS) + +- **检查**:`BASE_API` 是否正确;后端是否允许跨域 +- **解决**:修改 `config/prod.env.js` 中的 `BASE_API` 后重新构建;后端配置 CORS + +### 3. WebSocket 连接失败 + +- **检查**:浏览器控制台 Network → WS,查看连接地址和错误信息 +- **解决**: + - 确认 WebSocket 服务已启动 + - 在登录页填写正确的地址(本机用 `ws://127.0.0.1:10010`,服务器用 `ws://服务器IP:10010`,HTTPS 用 `wss://`) + - 如使用 Nginx 代理,确认代理配置正确 + +### 4. 静态资源 404 + +- **检查**:`static/` 目录是否上传完整 +- **解决**:重新上传 `dist/web/static/` 目录 + +### 5. 路由跳转异常 + +- **检查**:Nginx 配置中是否有 `try_files $uri $uri/ /index.html;` +- **解决**:添加该配置后重启 Nginx + +--- + +## 六、更新部署 + +当代码更新后: + +1. 修改 `config/prod.env.js`(如需要) +2. 执行 `npm run build:web` +3. 将 `dist/web/` 下的文件**覆盖上传**到宝塔网站根目录 +4. 清除浏览器缓存或强制刷新(Ctrl+F5) + +--- + +## 七、总结 + +- **构建产物**:`dist/web/` 目录 +- **上传位置**:宝塔网站根目录 +- **配置要点**: + - `BASE_API`:后端 HTTP 接口地址 + - WebSocket:用户可在登录页配置,或通过 Nginx 反向代理 +- **访问方式**:`http(s)://your-domain.com` + +部署完成后,用户访问网站即可使用,首次登录时记得在登录页配置 WebSocket 服务地址。 diff --git a/docs/WEBSOCKET_DEPLOY.md b/docs/WEBSOCKET_DEPLOY.md new file mode 100644 index 0000000..d7d96ca --- /dev/null +++ b/docs/WEBSOCKET_DEPLOY.md @@ -0,0 +1,82 @@ +# WebSocket 与网页端部署说明 + +## 问题说明 + +程序通过 **WebSocket** 与后端服务通信(设备状态、作业列表、系统配置等)。该服务在**桌面端**场景下是 Windows 本机运行的服务(默认 `ws://127.0.0.1:10010`)。 + +**网页端打包部署后能否连接,取决于“浏览器连的是谁”:** + +- 网页运行在**用户浏览器**里,`new WebSocket("ws://127.0.0.1:10010")` 会连接的是**当前用户所在设备**的 127.0.0.1,而不是你放网页的那台服务器。 +- 因此: + - **用户和 Windows 服务在同一台电脑**:例如在本机浏览器打开部署在本机的页面,用 `ws://127.0.0.1:10010` 可以连到本机服务,**可以连接**。 + - **用户和 Windows 服务不在同一台电脑**:例如网页部署在服务器 A,用户在手机或另一台电脑 B 打开,此时 127.0.0.1 指向的是 B,连不到 A 上的服务,**无法连接**。 + +所以:**把程序打包放到网页端后,只有在“能访问到 WebSocket 服务”的情况下才可以连接**;默认写死 127.0.0.1 时,只适合“网页和服务在同一台机器”或“用户本机也跑了该服务”的场景。 + +--- + +## 已做改造:可配置 WebSocket 地址 + +为支持不同部署方式,已做两点改动: + +### 1. 连接时优先读“用户配置” + +- 连接 WebSocket 时**优先使用**本地存储中的 **`WS_SOCKET_API`**(localStorage)。 +- 若未配置,再使用构建时注入的 **`process.env.VUE_APP_SOCKET_API`**(默认 `ws://127.0.0.1:10010`)。 + +因此同一套网页包可以: + +- 部署在服务器上,由用户在登录页填写“实际要连的 WebSocket 地址”; +- 或由部署方在构建时通过环境变量写死一个公网/内网地址。 + +### 2. 登录页可填写并保存地址 + +- 在**登录页**增加 **“设置 WebSocket 服务地址”**(可展开/收起)。 +- 用户可输入例如: + - `ws://127.0.0.1:10010`(本机服务) + - `ws://192.168.1.100:10010`(内网某台机器上的服务) + - `wss://your-domain.com/ws`(通过域名 + HTTPS 的 WSS 服务) +- 失焦或保存后写入 **localStorage**,下次进入或刷新后,连接会使用该地址。 + +这样**网页端打包部署后**,只要用户(或管理员)在登录页把地址改成“实际可访问的 WebSocket 服务地址”,就可以正常连接。 + +--- + +## 常见部署方式与是否可连接 + +| 部署方式 | 网页访问方式 | WebSocket 地址建议 | 能否连接 | +|----------|--------------|--------------------|----------| +| 网页和 Windows 服务都在**同一台电脑** | 本机浏览器打开(如 http://localhost:9081 或 file://) | `ws://127.0.0.1:10010`(默认即可) | 可以 | +| 网页在**服务器**,服务仍在**用户本机** | 用户在本机浏览器打开网站 | 在登录页设为 `ws://127.0.0.1:10010`(本机须已运行该服务) | 可以(仅限本机也跑服务时) | +| 网页在**服务器**,服务在**内网另一台机器** | 用户在内网任意电脑打开网站 | 在登录页设为 `ws://内网机器IP:10010`(或该机域名) | 可以(需网络可达、无策略拦截) | +| 网页在**公网**,服务在**公网服务器** | 任意设备打开网站 | 构建时设 `VUE_APP_SOCKET_API=wss://api.xxx.com/ws`,或在登录页填写该地址 | 可以(需后端提供 wss 与跨域策略) | + +--- + +## 使用步骤(网页端部署后) + +1. 打开登录页,点击 **“设置 WebSocket 服务地址”**。 +2. 填入实际可访问的地址,例如: + - 本机:`ws://127.0.0.1:10010` + - 内网机器:`ws://192.168.1.100:10010` + - 公网:`wss://your-api.com/ws` +3. 失焦后会自动保存到当前浏览器;之后登录或刷新页面,会使用该地址连接。 +4. 若更换环境(换电脑/换网络),在同一浏览器重新打开登录页,修改并保存新地址即可。 + +--- + +## 构建时写死地址(可选) + +若部署环境固定(例如始终连同一台服务器),可在构建网页时注入默认地址,减少用户手动填写: + +- 开发/测试:在 `config/dev.env.js` 中设置 `VUE_APP_SOCKET_API`。 +- 生产:在 `config/prod.env.js` 或 CI 中设置 `VUE_APP_SOCKET_API`(如 `wss://api.xxx.com/ws`)。 + +未在登录页保存过地址时,会使用该默认值;保存过后以登录页配置为准。 + +--- + +## 总结 + +- **默认 `ws://127.0.0.1:10010` 只适合“浏览器所在机器 = 运行 WebSocket 服务的机器”的情况。** +- **网页端打包部署后**:通过**登录页可配置 WebSocket 地址**并写入 localStorage,连接时**优先使用该配置**,因此只要用户填写的地址在浏览器侧可达(本机/内网/公网),就可以正常连接。 diff --git a/docs/WEB_FEATURE_LIST.md b/docs/WEB_FEATURE_LIST.md new file mode 100644 index 0000000..6854119 --- /dev/null +++ b/docs/WEB_FEATURE_LIST.md @@ -0,0 +1,154 @@ +# DiscWorker 网页端功能清单与实现情况 + +本文档列出全部功能,并标明:**无改动**(桌面/网页一致)、**有改动**(为兼容网页做了适配)、**网页端无法实现**(仅桌面端或需后端扩展)。 + +--- + +## 一、全局与基础设施 + +| 功能 | 实现情况 | 说明 | +|------|----------|------| +| 路由(/、/login、/manage、/set、/user、/404) | 无改动 | 使用 Vue Router,hash 模式,网页端可直接部署 | +| 登录鉴权(permission.js) | 无改动 | 基于 token 与 store,与运行环境无关 | +| 路由守卫(白名单、未登录跳转登录) | 无改动 | 纯前端逻辑 | +| HTTP 请求(request.js、BASE_API) | 有改动 | 网页构建通过 DefinePlugin 注入 BASE_API,需配置后端地址 | +| 多语言(vue-i18n) | 无改动 | 纯前端 | +| Element UI、主题与尺寸 | 无改动 | 纯前端 | +| Vuex Store(user、chat、app 等) | 有改动 | store 仅桌面端条件引入 vuex-electron,网页端不引入 | + +--- + +## 二、登录页(/login) + +| 功能 | 实现情况 | 说明 | +|------|----------|------| +| 用户名/密码输入、记住账号 | 无改动 | 纯表单 + localStorage | +| 登录请求(/user/login) | 无改动 | 走 axios + BASE_API,网页端需后端可用 | +| 新手引导(第一步) | 无改动 | 纯前端弹窗与步骤 | +| **WebSocket 服务地址设置** | **有改动** | 登录页可展开「设置 WebSocket 服务地址」,填写后写入 localStorage(key: `WS_SOCKET_API`),连接时优先使用该地址,便于网页端部署后连接本机/内网/公网服务。详见 [WEBSOCKET_DEPLOY.md](./WEBSOCKET_DEPLOY.md) | + +--- + +## 三、首页 / 看板(/) + +### 3.1 顶部与状态 + +| 功能 | 实现情况 | 说明 | +|------|----------|------| +| 回到主界面、系统设置入口 | 无改动 | 路由跳转 | +| 服务启停开关(打开/关闭服务) | **网页端无法实现** | 依赖桌面端执行 `control.sh`,网页端显示「网页端」占位与 tooltip「仅桌面端支持启停服务」 | +| 完成刻录数/废弃刻录数/错误数 | 无改动 | 来自 WebSocket 的 task_list,与端无关 | +| 试用版天数、前往激活 | 有改动 | 「前往激活」仅桌面端显示(依赖 runCmd 执行 regist.sh);网页端不显示该按钮 | +| 用户信息组件 | 无改动 | 展示 store 中的用户信息 | + +### 3.2 设备与作业 + +| 功能 | 实现情况 | 说明 | +|------|----------|------| +| 设备状态展示(图示、状态文案) | 无改动 | 数据来自 WebSocket printer_info | +| 运行选项(重启设备、清除错误、设置光盘桶、刷新光盘桶等) | 无改动 | 通过 WebSocket 下发,网页端在已连接服务时可用 | +| 作业列表(表格、重试/取消) | 无改动 | WebSocket task_list + websocketsend | +| 新建作业、打开作业 | 有改动 | **打开作业**:桌面端用系统对话框选 .dwk 后读文件;网页端用 `` 选文件并 FileReader 读内容,再解析填入 workAdd,**可正常使用**。新建作业为打开弹窗,无改动 | +| 保存作业(workAdd 内) | 有改动 | 桌面端:系统保存对话框 + 写入本地路径;网页端:无保存对话框,直接触发浏览器下载 .dwk 文件,**可正常使用** | +| 动态/日志(最新日志、全部日志) | 无改动 | 数据来自 WebSocket log,与端无关 | + +### 3.3 帮助与其它 + +| 功能 | 实现情况 | 说明 | +|------|----------|------| +| 帮助(打开帮助文档) | 有改动 | 桌面端:IPC 打开本机 PDF;网页端:`window.open(HELP_PDF_URL)`,需部署或配置帮助 PDF 地址 | +| 关于我们弹窗 | 无改动 | 纯前端 | + +--- + +## 四、作业弹窗(WorkAdd 组件) + +### 4.1 作业配置 + +| 功能 | 实现情况 | 说明 | +|------|----------|------| +| 任务名称、CD 类型、刻录类型、标签、UDF、关联任务等表单 | 无改动 | 纯表单与校验 | +| 模板下拉(从 User Templates 加载) | 有改动 | 桌面端:读本地「User Templates」目录;网页端:readdir 不可用,模板列表为空,**网页端无法使用本地模板列表**;若需网页端模板,需后端提供列表接口 | +| 选择模板(加载 .soon 文件) | 有改动 | 仅桌面端可用(依赖本地路径 + readFile);网页端无模板列表,该入口不适用 | +| 「···」选择作业文件(.soon) | 有改动 | 桌面端:系统对话框选文件;网页端:可用平台 showOpenFileDialog(input file),**单文件选择可用**;多选仍仅桌面端 | +| 新建标签(打开 SoonDesign) | **网页端无法实现** | 依赖桌面端 exec('soondesign'),网页端按钮改为灰色 + tooltip「仅桌面端支持」 | + +### 4.2 文件与路径 + +| 功能 | 实现情况 | 说明 | +|------|----------|------| +| 添加文件(单/多选) | 有改动 | 桌面端:系统对话框 + 本地路径 + stat;网页端:input file 单文件,以「web://」虚拟路径加入列表,**可添加单文件** | +| 添加文件夹 | **网页端无法实现** | 依赖系统选择目录,网页端 showOpenDirectoryDialog 拒绝,提示「仅桌面端支持」 | +| 拖放添加文件/文件夹 | 有改动 | 桌面端:支持路径与 calcSize;网页端:仅支持 File 对象(无 path),用 name 与 size,不计算目录大小,**可拖放文件** | +| 选择路径(归档路径) | **网页端无法实现** | 依赖系统选择目录,网页端不支持 | +| 保存作业为 .dwk | 见「三、首页」保存作业 | 网页端为下载 | + +### 4.3 提交与打包 + +| 功能 | 实现情况 | 说明 | +|------|----------|------| +| 提交任务(刻录/打印) | 有改动 | 桌面端:提交本地路径 + mtime 等,由本机服务访问本地文件;网页端:当前提交的为「web://」虚拟路径,**后端无法按路径读文件,故网页端提交任务需后端提供文件上传接口**,否则仅桌面端可完整使用 | +| 复制文件到某路径(file-back 复制) | **网页端无法实现** | 依赖 fs.cp,仅桌面端;网页端点击会提示「仅桌面端支持」 | +| 压缩为 zip/加密 zip(file-back) | **网页端无法实现** | 依赖 fs stream + archiver,仅桌面端;网页端会提示「仅桌面端支持」 | + +--- + +## 五、系统管理(/manage) + +| 功能 | 实现情况 | 说明 | +|------|----------|------| +| 设置光驱(手动设置光驱、设置光盘桶类型) | 无改动 | 全部通过 WebSocket 与后端/设备通信,网页端在连接服务后**可正常使用** | +| 校准设备、维护设备 | 无改动 | WebSocket 下发指令,网页端可用 | +| 刷新时间、执行 | 无改动 | WebSocket,网页端可用 | +| 清除任务(服务重启时是否删除已完成/已取消任务) | 无改动 | WebSocket/配置,网页端可用 | +| 新手引导开关 | 无改动 | 本地存储,网页端可用 | +| 光盘类型列表(getCurrentOSDiscTypes) | 有改动 | fileSize 在网页端返回固定 1024 与 web 类型,manage 仅读配置列表,**网页端可正常使用** | + +--- + +## 六、系统配置(/set) + +| 功能 | 实现情况 | 说明 | +|------|----------|------| +| LogLevel、AutoRetryTimes、PrintQuality、CacheDir、SkipSr0Check 等 | 无改动 | 通过 WebSocket 获取/提交系统配置,网页端**可正常使用** | +| 保存 | 无改动 | websocketsend,网页端可用 | + +--- + +## 七、用户管理(/user) + +| 功能 | 实现情况 | 说明 | +|------|----------|------| +| 用户列表展示(当前为静态示例数据) | 无改动 | 纯前端表格,若后续接真实接口则与端无关 | + +--- + +## 八、其它 + +| 功能 | 实现情况 | 说明 | +|------|----------|------| +| 404 页 | 无改动 | 纯静态 | +| TabBar 导航 | 无改动 | 路由跳转 | +| WebSocket 连接(chat 模块) | 有改动 | 网页端通过 VUE_APP_SOCKET_API 连接,需后端或本机服务提供 WebSocket;**网页端需能访问该地址**(同源或 CORS/代理) | +| 文件大小显示(filterSize、fileSize) | 有改动 | fileSize 在网页端 getOS 返回 'web'、getBaseSize 固定 1024,**显示正常** | +| 右键菜单(show-context-menu) | 有改动 | 桌面端 IPC;网页端 no-op,无影响 | + +--- + +## 九、总结表 + +| 类型 | 数量 | 说明 | +|------|------|------| +| **无改动** | 绝大多数 | 登录、配置、设备指令、作业列表、重试/取消、日志、系统管理、系统配置等均与运行环境无关或仅依赖 WebSocket/HTTP | +| **有改动且网页端可用** | 若干 | 打开作业(选文件 + 读内容)、保存作业(下载)、帮助(新标签打开 PDF)、添加单文件、拖放文件、服务开关/激活 UI 占位与提示 | +| **网页端无法实现** | 少量 | 服务启停(执行 control.sh)、前往激活(执行 regist.sh)、新建标签(打开 SoonDesign)、选择目录、复制到本地路径、本地 zip 打包;提交任务在无上传接口时仅桌面端完整可用 | + +--- + +## 十、网页端使用前提 + +1. **后端与 WebSocket**:配置 `BASE_API`、`VUE_APP_SOCKET_API`,确保登录接口与 WebSocket 可访问(同源或代理/CORS)。 +2. **帮助文档**:如需帮助入口,部署帮助 PDF 并配置 `HELP_PDF_URL`(或使用默认 `/help/User Manual.pdf`)。 +3. **提交任务**:若要在网页端完整使用「提交刻录/打印任务」,需后端提供文件上传接口,前端改为先上传再提交任务参数;当前实现仍为提交路径,仅桌面端可被本机服务访问。 + +按当前实现,网页端可正常完成:登录、看板查看、设备状态与指令、作业列表与重试/取消、打开/保存作业(选文件与下载)、系统管理、系统配置、日志查看等;仅上述「网页端无法实现」项在网页端为禁用或提示。 diff --git a/package.json b/package.json index 6089d42..065f890 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "build:dir": "node .electron-vue/build.js && electron-builder --dir", "build:clean": "cross-env BUILD_TARGET=clean node .electron-vue/build.js", "build:web": "cross-env BUILD_TARGET=web node .electron-vue/build.js", + "dev:web": "cross-env NODE_ENV=development node node_modules/webpack-dev-server/bin/webpack-dev-server.js --config .electron-vue/webpack.web.config.js --open", "electron:linux": "vue-cli-service electron:build -l --x64", "electron:arm": "vue-cli-service electron:build -l --arm64", "dev": "node .electron-vue/dev-runner.js", diff --git a/src/index.ejs b/src/index.ejs index 6175ce5..c2fa254 100644 --- a/src/index.ejs +++ b/src/index.ejs @@ -3,8 +3,8 @@ DiscWorker V1.01 - <% if (htmlWebpackPlugin.options.nodeModules) { %> - + <% if (typeof isWeb === 'undefined' ? htmlWebpackPlugin.options.nodeModules : !isWeb && htmlWebpackPlugin.options.nodeModules) { %> + @@ -12,8 +12,8 @@
- - <% if (!process.browser) { %> + + <% if (typeof isWeb === 'undefined' ? !process.browser : !isWeb) { %> diff --git a/src/renderer/components/workAdd/files/calc.js b/src/renderer/components/workAdd/files/calc.js index 54ff7a6..e338a36 100644 --- a/src/renderer/components/workAdd/files/calc.js +++ b/src/renderer/components/workAdd/files/calc.js @@ -1,12 +1,19 @@ -const fs = require("fs"); -const path = require("path"); -// 使用promisify方法来promise化指定方法 -const { promisify } = require("util"); -const stat = promisify(fs.stat); -const readdir = promisify(fs.readdir); +const IS_WEB = process.env.IS_WEB === 'true'; +let fs, path, stat, readdir; +if (!IS_WEB) { + fs = require("fs"); + path = require("path"); + const { promisify } = require("util"); + stat = promisify(fs.stat); + readdir = promisify(fs.readdir); +} -// 异步 +// 异步(网页端不计算目录大小,直接 callback 0) export async function calcSize(dirPath, callback) { + if (IS_WEB || !stat) { + callback(null, 0, dirPath); + return; + } let fileSize = 0; let error = null; async function calc(dirPath) { @@ -14,9 +21,7 @@ export async function calcSize(dirPath, callback) { const statObj = await stat(dirPath); if (statObj.isDirectory()) { const files = await readdir(dirPath); - let dirs = files.map((item) => { - return path.join(dirPath, item); - }); + let dirs = files.map((item) => path.join(dirPath, item)); let index = 0; async function next() { if (index < dirs.length) { @@ -38,7 +43,9 @@ export async function calcSize(dirPath, callback) { } export function getFileName(name) { - return name.substring(name.lastIndexOf("\\") + 1); + if (!name) return ''; + const i = Math.max(name.lastIndexOf('\\'), name.lastIndexOf('/')); + return i < 0 ? name : name.substring(i + 1); } export function getExtension(name) { return name.substring(name.lastIndexOf(".") + 1); @@ -52,7 +59,8 @@ export function bytesToSize(bytes) { return (bytes / Math.pow(k, i)).toPrecision(3) + " " + sizes[i]; } -export function isFolder(path) { - let _stat = fs.lstatSync(path); +export function isFolder(filePath) { + if (IS_WEB || !fs) return false; + let _stat = fs.lstatSync(filePath); return _stat.isDirectory(); } diff --git a/src/renderer/components/workAdd/files/file-back.vue b/src/renderer/components/workAdd/files/file-back.vue index acee0f6..8119522 100644 --- a/src/renderer/components/workAdd/files/file-back.vue +++ b/src/renderer/components/workAdd/files/file-back.vue @@ -52,15 +52,14 @@