├── .browserslistrc ├── .editorconfig ├── .gitattributes ├── .gitignore ├── .npmrc ├── .prettierignore ├── .vscode ├── extensions.json └── settings.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build └── source │ ├── CoCo.png │ ├── billd.png │ └── billd2.png ├── deploy ├── deploy.json ├── handleSyncCodeup.mjs ├── handleSyncGitee.mjs └── tsconfig.json ├── docs ├── benchmarking.md ├── faq.md ├── features.md ├── start-app.md ├── start-client.md ├── start-server.md ├── 思路.md ├── 本地环境.md └── 流程.md ├── electron-builder.json5 ├── eslint.config.js ├── index.html ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── prettier.config.js ├── public └── favicon.ico ├── script └── urlProtoco.nsh ├── src ├── App.vue ├── api │ ├── deskUser.ts │ ├── deskVersion.ts │ ├── globalMsg.ts │ ├── inivte.ts │ ├── screenWall.ts │ └── ws.ts ├── assets │ ├── css │ │ ├── constant.scss │ │ └── main.scss │ ├── img │ │ ├── arrow_down.png │ │ ├── billd.jpg │ │ ├── button-back.png │ │ ├── button-home.png │ │ ├── button-menu.png │ │ ├── check.png │ │ ├── clipboard.png │ │ ├── copy.png │ │ ├── edit.png │ │ ├── link.png │ │ ├── logo.png │ │ ├── message.png │ │ ├── my-wechat.png │ │ ├── refresh.png │ │ ├── screenshot.png │ │ ├── sync.png │ │ ├── view.png │ │ ├── view_off.png │ │ ├── volume-down.png │ │ ├── volume-up.png │ │ └── volume.png │ └── readme_img │ │ ├── 111.png │ │ ├── 222.png │ │ ├── 333.png │ │ ├── 444.png │ │ ├── 555.png │ │ ├── 666.png │ │ └── wechat_group.jpg ├── components │ ├── DisableModal │ │ └── index.vue │ ├── Dropdown │ │ └── index.vue │ ├── GlobalMsgModal │ │ └── index.vue │ ├── Modal │ │ └── index.vue │ ├── NaiveMessage │ │ └── index.vue │ ├── NaiveModal │ │ └── index.vue │ ├── NaiveNotification │ │ └── index.vue │ ├── UpdateModal │ │ └── index.vue │ └── icons │ │ ├── VPIconChevronDown.vue │ │ └── VPIconExternalLink.vue ├── constant.ts ├── interface.ts ├── layout │ └── index.vue ├── main.ts ├── pure-constant.ts ├── pure-interface.ts ├── router │ └── index.ts └── spec-config.ts ├── test ├── test copy.js ├── test.html ├── test.js ├── test.json └── test.ts ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 version 3 | not dead 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org 2 | # 控制编辑器代码规范,如按下回车的时候,缩进几个空格等等。 3 | # 最顶层的EditorConfig文件 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | indent_style = space # 缩进样式为空格,也可以设置成:tab 9 | indent_size = 2 # 一个缩进2个空格 10 | # tab_width默认为indent_size的值,通常不需要指定。 11 | end_of_line = lf # 结尾符,也可以设置成:crlf 12 | insert_final_newline = true # 设置为true以确保文件在保存时以换行符结尾,设置为false以确保文件不以换行符号结尾。 13 | trim_trailing_whitespace = true # 设置为true以删除换行符之前的任何空白字符,设置为false以确保不会。 14 | 15 | [*.md] 16 | insert_final_newline = false 17 | trim_trailing_whitespace = false 18 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | components.d.ts 4 | auto-imports.d.ts 5 | .DS_Store 6 | .eslintcache 7 | deploy/index.js 8 | deploy/index.cjs 9 | electron-release 10 | electron-dist 11 | build/output/ 12 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | # 将所有依赖提升到最外层 2 | shamefully-hoist=true 3 | 4 | # 设置淘宝镜像 5 | registry=https://registry.npmmirror.com/ 6 | 7 | # 设置@billd*包使用的镜像 8 | @billd:registry=https://registry.hsslive.cn/ 9 | 10 | # https://sharp.pixelplumbing.com/install#chinese-mirror 11 | sharp_binary_host=https://npmmirror.com/mirrors/sharp 12 | sharp_libvips_binary_host=https://npmmirror.com/mirrors/sharp-libvips 13 | 14 | canvas_binary_host_mirror=https://npmmirror.com/mirrors/canvas 15 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | pnpm-lock.yaml 3 | dist 4 | components.d.ts 5 | .eslintcache 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar"], 3 | "unwantedRecommendations": [ 4 | "octref.vetur", 5 | "Vue.vscode-typescript-vue-plugin" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // 指定行尾序列为\n(LF)或者\r\n(CRLF)或者auto 3 | // "files.eol": "\n", 4 | 5 | // 在保存时格式化 6 | "editor.formatOnSave": true, 7 | 8 | // 保存时进行一些操作 9 | "editor.codeActionsOnSave": { 10 | "source.fixAll.eslint": "explicit", 11 | "source.organizeImports": "explicit" 12 | }, 13 | 14 | // "eslint.autoFixOnSave": true, // 废弃,使用editor.codeActionsOnSave替代 15 | 16 | // Path Autocomplete,这个插件能够支持路径补全,默认vsc默认的路径提示可能不会提示一些css或者jpg等资源,用这个插件可以完善vscode的路径提示 17 | // 主要作用是你输入@、components、layouts的时候,会有路径提示 18 | "path-autocomplete.pathMappings": { 19 | "@": "${folder}/src", 20 | "components": "${folder}/src/components", 21 | "layouts": "${folder}/src/layouts" 22 | }, 23 | 24 | // 别名路径跳转,这个插件可以完善vscode的跳转 25 | "alias-skip.allowedsuffix": [ 26 | "css", 27 | "less", 28 | "sass", 29 | "scss", 30 | "png", 31 | "jpg", 32 | "jpeg", 33 | "webp", 34 | "gif", 35 | "svg", 36 | "js", 37 | "jsx", 38 | "ts", 39 | "tsx", 40 | "vue" 41 | ], 42 | "typescript.tsdk": "node_modules/typescript/lib" 43 | } 44 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ## [0.10.0](https://github.com/billd-project/billd-desk-pro/compare/v0.9.0...v0.10.0) (2025-04-21) 6 | 7 | 8 | ### Bug Fixes 9 | 10 | * 消息中心 ([59bdd31](https://github.com/billd-project/billd-desk-pro/commit/59bdd31f9f34af5f540bf8d77ca8c99d8912afaf)) 11 | * 优化 ([37d1896](https://github.com/billd-project/billd-desk-pro/commit/37d18967c54e6468bfb07cd49359bf2a2a2758e9)) 12 | 13 | ## [0.9.0](https://github.com/billd-project/billd-desk-pro/compare/v0.8.0...v0.9.0) (2025-04-19) 14 | 15 | 16 | ### Features 17 | 18 | * 优化 ([776797f](https://github.com/billd-project/billd-desk-pro/commit/776797f547183a02c453ae05d8a0a1416d3d3c83)) 19 | 20 | 21 | ### Bug Fixes 22 | 23 | * 完善代码 ([a1c20fd](https://github.com/billd-project/billd-desk-pro/commit/a1c20fd1869abc1e213c5b2942a0adfbbc5b4ba7)) 24 | * 优化 ([7994386](https://github.com/billd-project/billd-desk-pro/commit/799438669646c6637d99557a3ce7fe56c6fc7f30)) 25 | * 优化 ([9a74bc5](https://github.com/billd-project/billd-desk-pro/commit/9a74bc51e3004c8d272089f311f63d45ae53d480)) 26 | * 支持移动端 ([ece2624](https://github.com/billd-project/billd-desk-pro/commit/ece26242783a68ff4d73fe77a113253d42112be5)) 27 | * readme ([6c4715d](https://github.com/billd-project/billd-desk-pro/commit/6c4715d8f1dd537e255f147deef67c24bc500b88)) 28 | 29 | ## [0.8.0](https://github.com/billd-project/billd-desk-pro/compare/v0.7.0...v0.8.0) (2025-04-08) 30 | 31 | 32 | ### Bug Fixes 33 | 34 | * 右键 ([eb6fd7f](https://github.com/billd-project/billd-desk-pro/commit/eb6fd7ff6a041a5a128a99d41e068c2a034fe256)) 35 | 36 | ## [0.7.0](https://github.com/billd-project/billd-desk-pro/compare/v0.6.0...v0.7.0) (2025-04-08) 37 | 38 | 39 | ### Bug Fixes 40 | 41 | * 屏幕前 ([b64f6a2](https://github.com/billd-project/billd-desk-pro/commit/b64f6a2064413400749c03c0d55b7a76077aca1a)) 42 | 43 | ## [0.6.0](https://github.com/billd-project/billd-desk-pro/compare/v0.5.0...v0.6.0) (2025-04-08) 44 | 45 | ## [0.5.0](https://github.com/billd-project/billd-desk-pro/compare/v0.4.0...v0.5.0) (2025-04-08) 46 | 47 | ## [0.4.0](https://github.com/billd-project/billd-desk-pro/compare/v0.3.0...v0.4.0) (2025-04-08) 48 | 49 | ## [0.3.0](https://github.com/billd-project/billd-desk-pro/compare/v0.2.0...v0.3.0) (2025-04-08) 50 | 51 | ## [0.2.0](https://github.com/billd-project/billd-desk-pro/compare/v0.1.88...v0.2.0) (2025-04-08) 52 | 53 | 54 | ### Bug Fixes 55 | 56 | * 优化 ([30370ea](https://github.com/billd-project/billd-desk-pro/commit/30370ea5f9325eb8ee8344ea61cb3448fd6574da)) 57 | * 优化 ([951b4c6](https://github.com/billd-project/billd-desk-pro/commit/951b4c61b6a83cd5e54de310c5deafc24bd464be)) 58 | 59 | ### [0.1.88](https://github.com/billd-project/billd-desk-pro/compare/v0.1.87...v0.1.88) (2025-03-28) 60 | 61 | 62 | ### Bug Fixes 63 | 64 | * 优化 ([2276506](https://github.com/billd-project/billd-desk-pro/commit/22765066b7941e708bd7e1f1d3b59b72e972490a)) 65 | 66 | ### [0.1.87](https://github.com/billd-project/billd-desk-pro/compare/v0.1.86...v0.1.87) (2025-03-28) 67 | 68 | 69 | ### Bug Fixes 70 | 71 | * 删除无用 ([59074b1](https://github.com/billd-project/billd-desk-pro/commit/59074b1fe6bfd466c52a81e3ffd7b2ba6113ed60)) 72 | * 完善版本 ([3722dd0](https://github.com/billd-project/billd-desk-pro/commit/3722dd07f7038e0e7717a369c51383c749c240b8)) 73 | * 优化代码 ([27a5618](https://github.com/billd-project/billd-desk-pro/commit/27a5618608427f646dbf2a1ceccd7881349fb561)) 74 | 75 | ### [0.1.86](https://github.com/billd-project/billd-desk-pro/compare/v0.1.85...v0.1.86) (2025-03-28) 76 | 77 | ### [0.1.85](https://github.com/billd-project/billd-desk-pro/compare/v0.1.84...v0.1.85) (2025-03-28) 78 | 79 | ### [0.1.84](https://github.com/billd-project/billd-desk-pro/compare/v0.1.83...v0.1.84) (2025-03-28) 80 | 81 | ### [0.1.83](https://github.com/billd-project/billd-desk-pro/compare/v0.1.82...v0.1.83) (2025-03-28) 82 | 83 | ### [0.1.82](https://github.com/billd-project/billd-desk-pro/compare/v0.1.81...v0.1.82) (2025-03-28) 84 | 85 | ### [0.1.81](https://github.com/billd-project/billd-desk-pro/compare/v0.1.80...v0.1.81) (2025-03-28) 86 | 87 | ### [0.1.80](https://github.com/billd-project/billd-desk-pro/compare/v0.1.79...v0.1.80) (2025-03-28) 88 | 89 | ### [0.1.79](https://github.com/billd-project/billd-desk-pro/compare/v0.1.78...v0.1.79) (2025-03-28) 90 | 91 | ### [0.1.78](https://github.com/billd-project/billd-desk-pro/compare/v0.1.77...v0.1.78) (2025-03-28) 92 | 93 | ### [0.1.77](https://github.com/billd-project/billd-desk-pro/compare/v0.1.76...v0.1.77) (2025-03-27) 94 | 95 | ### [0.1.76](https://github.com/billd-project/billd-desk-pro/compare/v0.1.75...v0.1.76) (2025-03-27) 96 | 97 | ### [0.1.75](https://github.com/billd-project/billd-desk-pro/compare/v0.1.74...v0.1.75) (2025-03-27) 98 | 99 | ### [0.1.74](https://github.com/billd-project/billd-desk-pro/compare/v0.1.73...v0.1.74) (2025-03-27) 100 | 101 | 102 | ### Bug Fixes 103 | 104 | * 修复架构 ([72fc2d6](https://github.com/billd-project/billd-desk-pro/commit/72fc2d6bad0a94b19ba32bf64d49937e3aca0b9b)) 105 | 106 | ### [0.1.73](https://github.com/billd-project/billd-desk-pro/compare/v0.1.72...v0.1.73) (2025-03-26) 107 | 108 | ### [0.1.72](https://github.com/billd-project/billd-desk-pro/compare/v0.1.71...v0.1.72) (2025-03-26) 109 | 110 | 111 | ### Bug Fixes 112 | 113 | * 优化 ([98f1fdd](https://github.com/billd-project/billd-desk-pro/commit/98f1fddc9f1240142bae8cbecd9fe5017accf6f6)) 114 | * 优化架构 ([d29c0b2](https://github.com/billd-project/billd-desk-pro/commit/d29c0b22b3ba20c9f5442e1b73c3f353215925a6)) 115 | 116 | ### [0.1.71](https://github.com/billd-project/billd-desk-pro/compare/v0.1.70...v0.1.71) (2025-03-24) 117 | 118 | 119 | ### Bug Fixes 120 | 121 | * 保存 ([a34e3df](https://github.com/billd-project/billd-desk-pro/commit/a34e3df4606d34e7d88cb0cc780e723f8603a6b9)) 122 | * 优化架构 ([9c42f17](https://github.com/billd-project/billd-desk-pro/commit/9c42f17ef0654b57ea111428363516c026883bad)) 123 | 124 | ### [0.1.70](https://github.com/billd-project/billd-desk-pro/compare/v0.1.69...v0.1.70) (2025-03-21) 125 | 126 | 127 | ### Bug Fixes 128 | 129 | * 邀请 ([b11963e](https://github.com/billd-project/billd-desk-pro/commit/b11963e7e3ca5053a91ac7ac520b411b08f34f26)) 130 | 131 | ### [0.1.69](https://github.com/billd-project/billd-desk-pro/compare/v0.1.68...v0.1.69) (2025-03-20) 132 | 133 | 134 | ### Bug Fixes 135 | 136 | * 优化 ([63fb9d4](https://github.com/billd-project/billd-desk-pro/commit/63fb9d472b18a8543e3ae1eeb8f808fca8e75b6e)) 137 | 138 | ### [0.1.68](https://github.com/billd-project/billd-desk-pro/compare/v0.1.67...v0.1.68) (2025-03-20) 139 | 140 | 141 | ### Bug Fixes 142 | 143 | * 优化 ([9f12880](https://github.com/billd-project/billd-desk-pro/commit/9f128804cb9451fc02d4ffc5990d2bc22d8381ff)) 144 | 145 | ### [0.1.67](https://github.com/billd-project/billd-desk-pro/compare/v0.1.66...v0.1.67) (2025-03-20) 146 | 147 | 148 | ### Bug Fixes 149 | 150 | * 优化 ([9344e5e](https://github.com/billd-project/billd-desk-pro/commit/9344e5e15d35d275a2f9a31a5400bda1d0cb340e)) 151 | 152 | ### [0.1.66](https://github.com/billd-project/billd-desk-pro/compare/v0.1.65...v0.1.66) (2025-03-20) 153 | 154 | ### [0.1.65](https://github.com/billd-project/billd-desk-pro/compare/v0.1.60...v0.1.65) (2025-03-20) 155 | 156 | 157 | ### Features 158 | 159 | * 保存 ([6b92438](https://github.com/billd-project/billd-desk-pro/commit/6b92438af5e406d59b1d776b86808e28e98be741)) 160 | 161 | 162 | ### Bug Fixes 163 | 164 | * 优化 ([383a1ce](https://github.com/billd-project/billd-desk-pro/commit/383a1cea17a91fed1a12c1b76b26b7b40da7ab66)) 165 | 166 | ### [0.1.64](https://github.com/billd-project/billd-desk-pro/compare/v0.1.60...v0.1.64) (2025-03-20) 167 | 168 | 169 | ### Features 170 | 171 | * 保存 ([6b92438](https://github.com/billd-project/billd-desk-pro/commit/6b92438af5e406d59b1d776b86808e28e98be741)) 172 | 173 | 174 | ### Bug Fixes 175 | 176 | * 优化 ([383a1ce](https://github.com/billd-project/billd-desk-pro/commit/383a1cea17a91fed1a12c1b76b26b7b40da7ab66)) 177 | 178 | ### [0.1.63](https://github.com/billd-project/billd-desk-pro/compare/v0.1.60...v0.1.63) (2025-03-20) 179 | 180 | 181 | ### Features 182 | 183 | * 保存 ([6b92438](https://github.com/billd-project/billd-desk-pro/commit/6b92438af5e406d59b1d776b86808e28e98be741)) 184 | 185 | 186 | ### Bug Fixes 187 | 188 | * 优化 ([383a1ce](https://github.com/billd-project/billd-desk-pro/commit/383a1cea17a91fed1a12c1b76b26b7b40da7ab66)) 189 | 190 | ### [0.1.62](https://github.com/billd-project/billd-desk-pro/compare/v0.1.60...v0.1.62) (2025-03-20) 191 | 192 | 193 | ### Features 194 | 195 | * 保存 ([6b92438](https://github.com/billd-project/billd-desk-pro/commit/6b92438af5e406d59b1d776b86808e28e98be741)) 196 | 197 | 198 | ### Bug Fixes 199 | 200 | * 优化 ([383a1ce](https://github.com/billd-project/billd-desk-pro/commit/383a1cea17a91fed1a12c1b76b26b7b40da7ab66)) 201 | 202 | ### [0.1.61](https://github.com/billd-project/billd-desk-pro/compare/v0.1.60...v0.1.61) (2025-03-20) 203 | 204 | 205 | ### Features 206 | 207 | * 保存 ([6b92438](https://github.com/billd-project/billd-desk-pro/commit/6b92438af5e406d59b1d776b86808e28e98be741)) 208 | 209 | 210 | ### Bug Fixes 211 | 212 | * 优化 ([383a1ce](https://github.com/billd-project/billd-desk-pro/commit/383a1cea17a91fed1a12c1b76b26b7b40da7ab66)) 213 | 214 | ### [0.1.60](https://github.com/billd-project/billd-desk-pro/compare/v0.1.59...v0.1.60) (2025-03-16) 215 | 216 | 217 | ### Bug Fixes 218 | 219 | * 保存 ([506743e](https://github.com/billd-project/billd-desk-pro/commit/506743e7c6188840d0ac4d93ee8e5f90a6fed826)) 220 | 221 | ### [0.1.59](https://github.com/billd-project/billd-desk-pro/compare/v0.1.58...v0.1.59) (2025-03-16) 222 | 223 | ### [0.1.58](https://github.com/billd-project/billd-desk-pro/compare/v0.1.57...v0.1.58) (2025-03-16) 224 | 225 | ### [0.1.57](https://github.com/billd-project/billd-desk-pro/compare/v0.1.56...v0.1.57) (2025-03-16) 226 | 227 | ### [0.1.56](https://github.com/billd-project/billd-desk-pro/compare/v0.1.55...v0.1.56) (2025-03-16) 228 | 229 | ### [0.1.55](https://github.com/billd-project/billd-desk-pro/compare/v0.1.54...v0.1.55) (2025-03-16) 230 | 231 | ### [0.1.54](https://github.com/billd-project/billd-desk-pro/compare/v0.1.53...v0.1.54) (2025-03-16) 232 | 233 | ### [0.1.53](https://github.com/billd-project/billd-desk-pro/compare/v0.1.52...v0.1.53) (2025-03-16) 234 | 235 | ### [0.1.52](https://github.com/billd-project/billd-desk-pro/compare/v0.1.51...v0.1.52) (2025-03-16) 236 | 237 | 238 | ### Bug Fixes 239 | 240 | * 保存 ([a068e5d](https://github.com/billd-project/billd-desk-pro/commit/a068e5d3575ee669360cc5152bdd60a13a641aea)) 241 | * 定价 ([c3753f4](https://github.com/billd-project/billd-desk-pro/commit/c3753f44c8ec3e5965a73d1dafc8dc89d66f3b88)) 242 | * 配置调整 ([334124f](https://github.com/billd-project/billd-desk-pro/commit/334124fe780dbc004ab32a6dd5bc1dec974cf2d1)) 243 | * 文字 ([a7398db](https://github.com/billd-project/billd-desk-pro/commit/a7398db0f9dbbffcfc86462073feda4d7ea86a1f)) 244 | * 优化 ([29abbc9](https://github.com/billd-project/billd-desk-pro/commit/29abbc9f54f2ca4d3fdcfe16979f65a80a896cda)) 245 | * 优化 ([167b4ac](https://github.com/billd-project/billd-desk-pro/commit/167b4ac044aa57a3c98bf51eb0f62f7271999f29)) 246 | * deploy ([3515ce6](https://github.com/billd-project/billd-desk-pro/commit/3515ce61736aa73187e6e77f7bdb9ed15deb548d)) 247 | * release ([9752c0f](https://github.com/billd-project/billd-desk-pro/commit/9752c0f6260dbb3858a4d6776e711102b0de444d)) 248 | 249 | ### [0.1.51](https://github.com/billd-project/billd-desk-pro/compare/v0.1.50...v0.1.51) (2025-02-13) 250 | 251 | 252 | ### Features 253 | 254 | * 浏览器打开客户端 ([a505f90](https://github.com/billd-project/billd-desk-pro/commit/a505f90d12ab374370199f7f300ce68417ac8d57)) 255 | * 同步仓库 ([341b578](https://github.com/billd-project/billd-desk-pro/commit/341b5786a5d3ff9486ecd6bd3f9b45a1d3a3e3a1)) 256 | 257 | ### [0.1.50](https://github.com/billd-project/billd-desk-pro/compare/v0.1.49...v0.1.50) (2025-02-05) 258 | 259 | ### [0.1.49](https://github.com/billd-project/billd-desk-pro/compare/v0.1.48...v0.1.49) (2025-02-05) 260 | 261 | ### [0.1.48](https://github.com/billd-project/billd-desk-pro/compare/v0.1.47...v0.1.48) (2025-02-05) 262 | 263 | ### [0.1.47](https://github.com/billd-project/billd-desk-pro/compare/v0.1.46...v0.1.47) (2025-02-05) 264 | 265 | 266 | ### Bug Fixes 267 | 268 | * 稳定 ([1156eec](https://github.com/billd-project/billd-desk-pro/commit/1156eec74974ff7f304727ed0d5f36ce6a757807)) 269 | * 优化 ([b1940ce](https://github.com/billd-project/billd-desk-pro/commit/b1940ce9e59a6938fb1d0d038d7d3672cad1bd0d)) 270 | * 优化 ([d7d65c1](https://github.com/billd-project/billd-desk-pro/commit/d7d65c1578c07438dc86e12da4d5480e54390fe9)) 271 | * 优化 ([022dba1](https://github.com/billd-project/billd-desk-pro/commit/022dba10693d9acd702265efa16307f17849f75b)) 272 | * 优化 ([9f030c7](https://github.com/billd-project/billd-desk-pro/commit/9f030c72a673b27316ffbece995bbc7d84ab0f17)) 273 | * 优化 ([d029fd3](https://github.com/billd-project/billd-desk-pro/commit/d029fd38bf1e8ce1a115d5cae7f8e9e4d75543c2)) 274 | * 优化 ([aba04b1](https://github.com/billd-project/billd-desk-pro/commit/aba04b167a3db169a05018c9620bf923f555fafa)) 275 | * 优化 ([c7ca68a](https://github.com/billd-project/billd-desk-pro/commit/c7ca68a1f7783d4e4fac29e2dad8069e36851bde)) 276 | * 优化 ([0e2fe65](https://github.com/billd-project/billd-desk-pro/commit/0e2fe654358615eb02ca92411a600c78165f386c)) 277 | * 优化 ([e76dbae](https://github.com/billd-project/billd-desk-pro/commit/e76dbaea80ae688a9be351a50fffd31cfafa93b5)) 278 | 279 | ### [0.1.46](https://github.com/billd-project/billd-desk-pro/compare/v0.1.45...v0.1.46) (2024-12-28) 280 | 281 | ### [0.1.45](https://github.com/billd-project/billd-desk-pro/compare/v0.1.44...v0.1.45) (2024-12-27) 282 | 283 | ### [0.1.44](https://github.com/billd-project/billd-desk-pro/compare/v0.1.43...v0.1.44) (2024-12-27) 284 | 285 | ### [0.1.43](https://github.com/billd-project/billd-desk-pro/compare/v0.1.42...v0.1.43) (2024-12-27) 286 | 287 | ### [0.1.42](https://github.com/billd-project/billd-desk-pro/compare/v0.1.41...v0.1.42) (2024-12-27) 288 | 289 | ### [0.1.41](https://github.com/billd-project/billd-desk-pro/compare/v0.1.40...v0.1.41) (2024-12-27) 290 | 291 | ### [0.1.40](https://github.com/billd-project/billd-desk-pro/compare/v0.1.39...v0.1.40) (2024-12-27) 292 | 293 | ### [0.1.39](https://github.com/billd-project/billd-desk-pro/compare/v0.1.38...v0.1.39) (2024-12-27) 294 | 295 | ### [0.1.38](https://github.com/billd-project/billd-desk-pro/compare/v0.1.37...v0.1.38) (2024-12-27) 296 | 297 | ### [0.1.37](https://github.com/billd-project/billd-desk-pro/compare/v0.1.36...v0.1.37) (2024-12-27) 298 | 299 | ### [0.1.36](https://github.com/billd-project/billd-desk-pro/compare/v0.1.35...v0.1.36) (2024-12-27) 300 | 301 | ### [0.1.35](https://github.com/billd-project/billd-desk-pro/compare/v0.1.34...v0.1.35) (2024-12-27) 302 | 303 | ### [0.1.34](https://github.com/billd-project/billd-desk-pro/compare/v0.1.33...v0.1.34) (2024-12-27) 304 | 305 | ### [0.1.33](https://github.com/billd-project/billd-desk-pro/compare/v0.1.32...v0.1.33) (2024-12-27) 306 | 307 | ### [0.1.32](https://github.com/billd-project/billd-desk-pro/compare/v0.1.31...v0.1.32) (2024-12-27) 308 | 309 | ### [0.1.31](https://github.com/billd-project/billd-desk-pro/compare/v0.1.30...v0.1.31) (2024-12-27) 310 | 311 | ### [0.1.30](https://github.com/billd-project/billd-desk-pro/compare/v0.1.29...v0.1.30) (2024-12-27) 312 | 313 | ### [0.1.29](https://github.com/billd-project/billd-desk-pro/compare/v0.1.28...v0.1.29) (2024-12-27) 314 | 315 | ### [0.1.28](https://github.com/billd-project/billd-desk-pro/compare/v0.1.27...v0.1.28) (2024-12-27) 316 | 317 | ### [0.1.27](https://github.com/billd-project/billd-desk-pro/compare/v0.1.26...v0.1.27) (2024-12-27) 318 | 319 | ### [0.1.26](https://github.com/billd-project/billd-desk-pro/compare/v0.1.25...v0.1.26) (2024-12-27) 320 | 321 | ### [0.1.25](https://github.com/billd-project/billd-desk-pro/compare/v0.1.24...v0.1.25) (2024-12-27) 322 | 323 | ### [0.1.24](https://github.com/billd-project/billd-desk-pro/compare/v0.1.23...v0.1.24) (2024-12-27) 324 | 325 | ### [0.1.23](https://github.com/billd-project/billd-desk-pro/compare/v0.1.22...v0.1.23) (2024-12-27) 326 | 327 | ### [0.1.22](https://github.com/billd-project/billd-desk-pro/compare/v0.1.21...v0.1.22) (2024-12-27) 328 | 329 | ### [0.1.21](https://github.com/billd-project/billd-desk-pro/compare/v0.1.20...v0.1.21) (2024-12-27) 330 | 331 | ### [0.1.20](https://github.com/billd-project/billd-desk-pro/compare/v0.1.19...v0.1.20) (2024-12-27) 332 | 333 | ### [0.1.19](https://github.com/billd-project/billd-desk-pro/compare/v0.1.18...v0.1.19) (2024-12-27) 334 | 335 | ### [0.1.18](https://github.com/billd-project/billd-desk-pro/compare/v0.1.17...v0.1.18) (2024-12-27) 336 | 337 | ### [0.1.17](https://github.com/billd-project/billd-desk-pro/compare/v0.1.16...v0.1.17) (2024-12-27) 338 | 339 | 340 | ### Bug Fixes 341 | 342 | * 优化 ([899b9f1](https://github.com/billd-project/billd-desk-pro/commit/899b9f10d15a26d4f0f4328c73116fd41d74e3b1)) 343 | * 优化 ([0d017a4](https://github.com/billd-project/billd-desk-pro/commit/0d017a47b379f256fdbc87753fbce20008694be5)) 344 | * 优化 ([a8729a3](https://github.com/billd-project/billd-desk-pro/commit/a8729a30f27022acd3c4dd5c34957dfc8e33cd80)) 345 | 346 | ### [0.1.16](https://github.com/billd-project/billd-desk-pro/compare/v0.1.15...v0.1.16) (2024-12-26) 347 | 348 | ### [0.1.15](https://github.com/billd-project/billd-desk-pro/compare/v0.1.14...v0.1.15) (2024-12-26) 349 | 350 | ### [0.1.14](https://github.com/billd-project/billd-desk-pro/compare/v0.1.13...v0.1.14) (2024-12-26) 351 | 352 | ### [0.1.13](https://github.com/billd-project/billd-desk-pro/compare/v0.1.12...v0.1.13) (2024-12-26) 353 | 354 | ### [0.1.12](https://github.com/billd-project/billd-desk-pro/compare/v0.1.11...v0.1.12) (2024-12-26) 355 | 356 | ### [0.1.11](https://github.com/billd-project/billd-desk-pro/compare/v0.1.10...v0.1.11) (2024-12-26) 357 | 358 | ### [0.1.10](https://github.com/billd-project/billd-desk-pro/compare/v0.1.9...v0.1.10) (2024-12-26) 359 | 360 | ### [0.1.9](https://github.com/billd-project/billd-desk-pro/compare/v0.1.8...v0.1.9) (2024-12-26) 361 | 362 | ### [0.1.8](https://github.com/billd-project/billd-desk-pro/compare/v0.1.7...v0.1.8) (2024-12-26) 363 | 364 | ### [0.1.7](https://github.com/billd-project/billd-desk-pro/compare/v0.1.6...v0.1.7) (2024-12-26) 365 | 366 | ### [0.1.6](https://github.com/billd-project/billd-desk-pro/compare/v0.1.5...v0.1.6) (2024-12-26) 367 | 368 | ### [0.1.5](https://github.com/billd-project/billd-desk-pro/compare/v0.1.4...v0.1.5) (2024-12-26) 369 | 370 | ### [0.1.4](https://github.com/billd-project/billd-desk-pro/compare/v0.1.3...v0.1.4) (2024-12-26) 371 | 372 | ### [0.1.3](https://github.com/billd-project/billd-desk-pro/compare/v0.1.2...v0.1.3) (2024-12-26) 373 | 374 | ### [0.1.2](https://github.com/billd-project/billd-desk-pro/compare/v0.1.1...v0.1.2) (2024-12-26) 375 | 376 | ### 0.1.1 (2024-12-26) 377 | 378 | 379 | ### Features 380 | 381 | * init ([97bf4b4](https://github.com/billd-project/billd-desk-pro/commit/97bf4b476f8a3fbf22b82f3ec04a70e1ebca51c7)) 382 | 383 | 384 | ### Bug Fixes 385 | 386 | * 优化 ([34ae9f3](https://github.com/billd-project/billd-desk-pro/commit/34ae9f37fc6d2fadc7d7d530fcc519c9c3979223)) 387 | * 优化 ([1f11264](https://github.com/billd-project/billd-desk-pro/commit/1f11264404b9cfcde7de96f0378a1e24a92c2600)) 388 | * 优化 ([abe25d6](https://github.com/billd-project/billd-desk-pro/commit/abe25d62eeecb6196cd9d86bfbe953d23346271f)) 389 | * 优化 ([fb6e544](https://github.com/billd-project/billd-desk-pro/commit/fb6e54433aac17d43865b637db97932e9960d836)) 390 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023-PRESENT shuisheng 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | BilldDesk logo 8 | 9 |

10 | 11 |

12 | BilldDesk 13 |

14 | 15 |

16 | 基于Vue3 + WebRTC + Nodejs + Electron搭建的远程桌面控制 17 |

18 | 19 |
20 | 21 | ![stars](https://img.shields.io/github/stars/galaxy-s10/billd-desk) 22 | ![forks](https://img.shields.io/github/forks/galaxy-s10/billd-desk) 23 | 24 | ![version](https://img.shields.io/github/package-json/v/galaxy-s10/billd-desk) 25 | ![License](https://img.shields.io/github/license/galaxy-s10/billd-desk) 26 | ![language](https://img.shields.io/github/languages/top/galaxy-s10/billd-desk) 27 | ![language](https://img.shields.io/github/languages/top/galaxy-s10/billd-desk-server) 28 | ![language](https://img.shields.io/github/languages/top/galaxy-s10/billd-desk-flutter) 29 | 30 |
31 | 32 | ## 简介 33 | 34 | BilldDesk 远程桌面控制,目前实现了类似 ToDesk、向日葵等远程桌面的功能。 35 | 36 | ## 对比ToDesk免费个人版 37 | 38 | > 作者使用过很多远程软件:TeamViewer、向日葵、ToTesk、AnyDesk、RustDesk、UU远程、连连控,还有qq自带的远程协助等等,但用ToDesk免费个人版比较多,因此用ToTesk和BilldDesk作对比~ 39 | 40 | | | BilldDesk | ToDesk免费个人版 | 41 | | ------------------------- | -------------- | ---------------------------------------------------- | 42 | | 连接限制 | 无限制,免费 | 300次连接和120小时限制,超出需要购买专业版(¥24/月) | 43 | | 画质限制 | 无限制,免费 | 最高1080p,30帧 | 44 | | 安卓被控 | 支持,免费 | 不支持,需要购买专业版(¥24/月)或购买插件(¥15/月) | 45 | | 同时显示多屏 | 支持,免费 | 不支持,需要购买性能版(¥95/月) | 46 | | 屏幕墙 | 支持,免费 | 不支持,需要购买ToDesk企业版(¥805/年) | 47 | | 远程时录屏 | 支持,免费 | 不支持 | 48 | | web网页发起远程控制 | 支持,免费 | 不支持,需要购买ToDesk企业版(¥805/年) | 49 | | 远程控制web网页(仅观看) | 支持,免费 | 不支持 | 50 | | 同账号多主控同时发起远控 | 支持,免费 | 支持,需要购买插件(¥233/月) | 51 | | 私有化部署/二次开发 | 支持,开源免费 | 不支持,需要ToDesk企业版,定价未知 | 52 | 53 | ## 生态 54 | 55 | | 项目名称 | 代码仓库 | star & fork | 线上地址/下载地址 | 56 | | ------------------- | ---------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | 57 | | 远程桌面网页/客户端 | [billd-desk](https://github.com/galaxy-s10/billd-desk) | [![github](https://img.shields.io/github/stars/galaxy-s10/billd-desk?label=star&logo=GitHub)](https://github.com/galaxy-s10/billd-desk) [![github](https://img.shields.io/github/forks/galaxy-s10/billd-desk?label=fork&logo=GitHub)](https://github.com/galaxy-s10/billd-desk) | [https://desk.hsslive.cn](https://desk.hsslive.cn) | 58 | | 远程桌面后台 | [billd-desk-admin](https://github.com/galaxy-s10/billd-desk-admin) | [![github](https://img.shields.io/github/stars/galaxy-s10/billd-desk-admin?label=star&logo=GitHub)](https://github.com/galaxy-s10/billd-desk) [![github](https://img.shields.io/github/forks/galaxy-s10/billd-desk-admin?label=fork&logo=GitHub)](https://github.com/galaxy-s10/billd-desk-admin) | [https://desk-admin.hsslive.cn](https://desk-admin.hsslive.cn) | 59 | | 远程桌面移动端 | [billd-desk-flutter](https://github.com/galaxy-s10/billd-desk-flutter) | [![github](https://img.shields.io/github/stars/galaxy-s10/billd-desk-flutter?label=star&logo=GitHub)](https://github.com/galaxy-s10/billd-desk-flutter) [![github](https://img.shields.io/github/forks/galaxy-s10/billd-desk-flutter?label=fork&logo=GitHub)](https://github.com/galaxy-s10/billd-desk-flutter) | [https://desk.hsslive.cn/#/download](https://desk.hsslive.cn/#/download) | 60 | | 远程桌面服务端 | [billd-desk-server](https://github.com/galaxy-s10/billd-desk-server) | [![github](https://img.shields.io/github/stars/galaxy-s10/billd-desk-server?label=star&logo=GitHub)](https://github.com/galaxy-s10/billd-desk-server) [![github](https://img.shields.io/github/forks/galaxy-s10/billd-desk-server?label=fork&logo=GitHub)](https://github.com/galaxy-s10/billd-desk-server) | [https://desk-api.hsslive.cn](https://desk-api.hsslive.cn) | 61 | 62 | ## 功能 63 | 64 | - [x] `web网页` 控制 `电脑端` 65 | - [x] `web网页` 控制 `安卓端` 66 | - [x] `web网页` 控制 `web网页`(仅观看) 67 | - [x] `电脑端` 控制 `电脑端` 68 | - [x] `电脑端` 控制 `安卓端` 69 | - [x] `电脑端` 控制 `web网页`(仅观看) 70 | - [ ] `安卓端` 控制 `电脑端` 71 | - [ ] `安卓端` 控制 `安卓端` 72 | - [ ] `安卓端` 控制 `web网页`(仅观看) 73 | - [x] 多台设备同时远程一台设备 74 | - [x] 一台设备同时远程多台设备 75 | - [x] 多屏操作 76 | - [x] 连接鉴权 77 | - [ ] 自定义设备码 78 | - [x] 按键组合键 79 | - [x] 支持 macOS 系统 80 | - [x] 支持 Windows 系统 81 | - [x] 支持 Linux 系统(未实际测试) 82 | - [x] 文件传输 83 | - [x] 开机自启 84 | - [x] 锁屏保活 85 | - [x] 屏幕墙 86 | - [x] 安卓端(Flutter) 87 | - [ ] 苹果端(Flutter) 88 | - [ ] 后台管理 89 | - [x] 支持私有化部署 90 | 91 | > 更多功能请查看:[features.md](docs/features.md) 92 | 93 | ## 预览 94 | 95 | 快速体验:[https://desk.hsslive.cn](https://desk.hsslive.cn) 96 | 97 | ### web网页/电脑端控制电脑端 98 | 99 | ![img](https://github.com/galaxy-s10/billd-desk/blob/main/src/assets/readme_img/111.png?raw=true) 100 | 101 | ### web网页/电脑端控制安卓端 102 | 103 | ![img](https://github.com/galaxy-s10/billd-desk/blob/main/src/assets/readme_img/222.png?raw=true) 104 | 105 | ### web网页/电脑端控制web网页 106 | 107 | > 仅观看模式 108 | 109 | ![img](https://github.com/galaxy-s10/billd-desk/blob/main/src/assets/readme_img/333.png?raw=true) 110 | 111 | ### 屏幕墙 112 | 113 | ![img](https://github.com/galaxy-s10/billd-desk/blob/main/src/assets/readme_img/444.png?raw=true) 114 | 115 | ### 安卓端控制电脑端【TODO】 116 | 117 | ### 安卓端控制安卓端【TODO】 118 | 119 | ### 安卓端控制web网页【TODO】 120 | 121 | > 仅观看模式 122 | 123 | ### 文件传输 124 | 125 | ![img](https://github.com/galaxy-s10/billd-desk/blob/main/src/assets/readme_img/666.png?raw=true) 126 | 127 | ### 跨平台支持 128 | 129 | ![img](https://github.com/galaxy-s10/billd-desk/blob/main/src/assets/readme_img/555.png?raw=true) 130 | 131 | ## 技术栈 132 | 133 | - 前端相关:[Vue3](https://vuejs.org) 以及相关技术栈、`Typescript`、`WebRTC`、`WebCodecs`、`Web Workder`、`Web Audio`、`Canvas` 134 | - 后端相关:[Nodejs](https://nodejs.org) 以及相关技术栈、`Koa2`、`Typescript`、`Sequelize`、`Mysql`、`Redis`、`Socket.io` 135 | - 桌面客户端相关:[Electron](https://www.electronjs.org)以及相关技术栈、`WebRTC` 136 | - 移动客户端相关:[Flutter3](https://flutter.dev)以及相关技术栈、`WebRTC` 137 | - 流媒体服务器相关:[SRS](https://ossrs.net)、 [FFmpeg](https://ffmpeg.org)、[Coturn](https://github.com/coturn/coturn) 138 | - Docker 相关:[Docker](https://www.docker.com) 139 | - 部署相关:[阿里云云效](https://devops.aliyun.com)、[billd-deploy](https://github.com/galaxy-s10/billd-deploy) 140 | 141 | ## 本地启动 142 | 143 | > https://desk.hsslive.cn/s/qk 144 | 145 | - [x] billd-desk(pro) 查看 [start-client.md](docs/start-client.md) 146 | 147 | - [x] billd-desk-server(pro) 查看 [start-server.md](docs/start-server.md) 148 | 149 | - [x] billd-desk-fultter(pro) 查看 [start-app.md](docs/start-app.md) 150 | 151 | ## 接口文档 152 | 153 | 查看 [apifox](https://apifox.com/apidoc/shared-a8ba9715-7730-432d-896c-97f983050795) 154 | 155 | ## 性能测试 156 | 157 | 查看 [benchmarking.md](docs/benchmarking.md) 158 | 159 | ## 常见问题 160 | 161 | 查看 [faq.md](docs/faq.md) 162 | 163 | ## 问题反馈 164 | 165 | 欢迎提 [issue](https://github.com/galaxy-s10/billd-desk/issues) 166 | 167 | ## 参与贡献 168 | 169 | 欢迎提 [pr](https://github.com/galaxy-s10/billd-desk/pulls) 170 | 171 | ## 私有化部署 172 | 173 | billd-desk完全开源(可商用),欢迎部署! 174 | 175 | ## 客户端下载 176 | 177 | > https://desk.hsslive.cn/s/bd 178 | > 179 | > 备用链接:https://pan.quark.cn/s/2acbf2d49603 180 | 181 | ## 官方交流群 182 | 183 | ![img](https://github.com/galaxy-s10/billd-desk/blob/main/src/assets/readme_img/wechat_group.jpg?raw=true) 184 | 185 | ## 兼容性 186 | 187 | - [x] Windows 188 | - [x] macOS 189 | - [x] Linux 190 | - [x] Android 12 191 | 192 | ## 贡献者 193 | 194 | 195 | BilldDesk logo 200 | 201 | 202 | ## 初心 203 | 204 | 该项目初心只是作为[billd-live](https://github.com/galaxy-s10/billd-live)的衍生项目,但后面觉得远程桌面也挺有意思的,就一直坚持完善下去。 205 | 206 | ## 愿景 207 | 208 | 各大远程软件虽然免费都能用,但免费版的功能覆盖不够全面,比如有些普通个人用户可能只是临时需要远程一下安卓手机,但却需要开通一个月的服务才可以。BilldDesk完善了这些基本功能,让普通用户也能用上~ 209 | -------------------------------------------------------------------------------- /build/source/CoCo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/build/source/CoCo.png -------------------------------------------------------------------------------- /build/source/billd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/build/source/billd.png -------------------------------------------------------------------------------- /build/source/billd2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/build/source/billd2.png -------------------------------------------------------------------------------- /deploy/deploy.json: -------------------------------------------------------------------------------- 1 | {"name":"billd-desk","version":"0.10.0","buildDate":"2025/4/21 22:54:17"} -------------------------------------------------------------------------------- /deploy/handleSyncCodeup.mjs: -------------------------------------------------------------------------------- 1 | // WARN 该文件只是方便我将当前项目复制一份到我电脑的另一个位置(gitee私有仓库的位置),其他人不需要管这个文件~ 2 | 3 | import { execSync } from 'node:child_process'; 4 | import fs from 'node:fs'; 5 | import path from 'node:path'; 6 | import trash from 'trash'; 7 | 8 | const allFile = []; 9 | const ignore = ['.DS_Store', '.git', 'node_modules', 'dist']; 10 | const localDir = 11 | '/Users/huangshuisheng/Desktop/hss/billd-project/billd-desk-pro'; 12 | const targetDir = '/Users/huangshuisheng/Desktop/hss/codeup/billd-desk'; 13 | 14 | const dir = fs.readdirSync(localDir).filter((item) => { 15 | if (ignore.includes(item)) { 16 | return false; 17 | } 18 | return true; 19 | }); 20 | 21 | function findFile(inputDir) { 22 | for (let i = 0; i < inputDir.length; i += 1) { 23 | const file = inputDir[i]; 24 | const filePath = `${localDir}/${file}`; 25 | const stat = fs.statSync(filePath); 26 | const isDir = stat.isDirectory(); 27 | if (!isDir) { 28 | allFile.push(filePath); 29 | } else { 30 | findFile(fs.readdirSync(filePath).map((key) => `${file}/${key}`)); 31 | } 32 | } 33 | } 34 | 35 | function putFile() { 36 | for (let i = 0; i < allFile.length; i += 1) { 37 | const file = allFile[i]; 38 | const arr = []; 39 | const githubFile = file.replace(localDir, ''); 40 | const githubFileArr = githubFile.split('/').filter((item) => item !== ''); 41 | githubFileArr.forEach((item) => { 42 | if (arr.length) { 43 | arr.push(path.resolve(arr[arr.length - 1], item)); 44 | } else { 45 | arr.push(path.resolve(targetDir, item)); 46 | } 47 | }); 48 | arr.forEach((item, index) => { 49 | // 数组的最后一个一定是文件,因此不需要判断它是不是目录 50 | if (index !== arr.length - 1) { 51 | const flag = fs.existsSync(item); 52 | 53 | !flag && fs.mkdirSync(item); 54 | } 55 | }); 56 | fs.copyFileSync( 57 | file, 58 | path.join(targetDir, './', file.replace(localDir, '')) 59 | ); 60 | } 61 | } 62 | 63 | async function clearOld() { 64 | const targetDirAllFile = fs.readdirSync(targetDir); 65 | const queue = []; 66 | targetDirAllFile.forEach((url) => { 67 | const fullurl = `${targetDir}/${url}`; 68 | if (!['node_modules', '.git'].includes(url)) { 69 | queue.push(trash(fullurl)); 70 | } 71 | }); 72 | await Promise.all(queue); 73 | } 74 | 75 | const newPkgStr = fs.readFileSync( 76 | path.resolve(localDir, 'package.json'), 77 | 'utf-8' 78 | ); 79 | // const viteConfigStr = fs.readFileSync( 80 | // path.resolve(localDir, './deploy/vite.config.ts'), 81 | // 'utf-8' 82 | // ); 83 | const tsconfigStr = fs.readFileSync( 84 | path.resolve(localDir, './deploy/tsconfig.json'), 85 | 'utf-8' 86 | ); 87 | const newPkg = JSON.parse(newPkgStr); 88 | delete newPkg['devDependencies']['@electron-toolkit/preload']; 89 | delete newPkg['devDependencies']['@electron/rebuild']; 90 | delete newPkg['devDependencies']['electron']; 91 | delete newPkg['devDependencies']['electron-builder']; 92 | delete newPkg['devDependencies']['electron-icon-builder']; 93 | 94 | if (process.cwd().indexOf('codeup') !== -1) { 95 | console.log('当前目录错误'); 96 | } else { 97 | clearOld().then(() => { 98 | findFile(dir); 99 | putFile(); 100 | const gitignoreArr = [ 101 | 'node_modules', 102 | 'electron-release', 103 | 'electron-dist', 104 | 'dist', 105 | 'components.d.ts', 106 | 'auto-imports.d.ts', 107 | '.eslintcache', 108 | '.DS_Store', 109 | ]; 110 | const gitignoreTxt = gitignoreArr.join('\n'); 111 | fs.writeFileSync(path.resolve(targetDir, './.gitignore'), gitignoreTxt); 112 | fs.writeFileSync( 113 | path.resolve(targetDir, 'package.json'), 114 | JSON.stringify({ ...newPkg }, Object.create({}), 2) 115 | ); 116 | // fs.writeFileSync(path.resolve(targetDir, 'vite.config.ts'), viteConfigStr); 117 | fs.writeFileSync(path.resolve(targetDir, 'tsconfig.json'), tsconfigStr); 118 | fs.writeFileSync( 119 | path.resolve(targetDir, 'deploy/jenkins.json'), 120 | JSON.stringify({ 121 | buildDate: new Date().toLocaleString(), 122 | }) 123 | ); 124 | 125 | execSync(`pnpm i`, { cwd: targetDir }); 126 | execSync(`git rm -r --cached .`, { cwd: targetDir }); 127 | execSync(`git add .`, { cwd: targetDir }); 128 | execSync(`git commit -m 'feat: ${new Date().toLocaleString()}'`, { 129 | cwd: targetDir, 130 | }); 131 | execSync(`git push`, { cwd: targetDir }); 132 | }); 133 | } 134 | -------------------------------------------------------------------------------- /deploy/handleSyncGitee.mjs: -------------------------------------------------------------------------------- 1 | // WARN 该文件只是方便我将当前项目复制一份到我电脑的另一个位置(gitee私有仓库的位置),其他人不需要管这个文件~ 2 | 3 | import { execSync } from 'node:child_process'; 4 | import fs from 'node:fs'; 5 | import path from 'node:path'; 6 | 7 | import trash from 'trash'; 8 | 9 | const allFile = []; 10 | const ignore = [ 11 | '.DS_Store', 12 | '.git', 13 | 'node_modules', 14 | 'dist', 15 | 'electron-dist', 16 | 'electron-release', 17 | ]; 18 | const localDir = 19 | '/Users/huangshuisheng/Desktop/hss/billd-project/billd-desk-pro'; 20 | const giteeDir = '/Users/huangshuisheng/Desktop/hss/jenkins/billd-desk'; 21 | 22 | const dir = fs.readdirSync(localDir).filter((item) => { 23 | if (ignore.includes(item)) { 24 | return false; 25 | } 26 | return true; 27 | }); 28 | 29 | function findFile(inputDir) { 30 | for (let i = 0; i < inputDir.length; i += 1) { 31 | const file = inputDir[i]; 32 | const filePath = `${localDir}/${file}`; 33 | const stat = fs.statSync(filePath); 34 | const isDir = stat.isDirectory(); 35 | if (!isDir) { 36 | allFile.push(filePath); 37 | } else { 38 | findFile(fs.readdirSync(filePath).map((key) => `${file}/${key}`)); 39 | } 40 | } 41 | } 42 | 43 | function putFile() { 44 | for (let i = 0; i < allFile.length; i += 1) { 45 | const file = allFile[i]; 46 | const arr = []; 47 | const githubFile = file.replace(localDir, ''); 48 | const githubFileArr = githubFile.split('/').filter((item) => item !== ''); 49 | githubFileArr.forEach((item) => { 50 | if (arr.length) { 51 | arr.push(path.resolve(arr[arr.length - 1], item)); 52 | } else { 53 | arr.push(path.resolve(giteeDir, item)); 54 | } 55 | }); 56 | arr.forEach((item, index) => { 57 | // 数组的最后一个一定是文件,因此不需要判断它是不是目录 58 | if (index !== arr.length - 1) { 59 | const flag = fs.existsSync(item); 60 | 61 | !flag && fs.mkdirSync(item); 62 | } 63 | }); 64 | fs.copyFileSync( 65 | file, 66 | path.join(giteeDir, './', file.replace(localDir, '')) 67 | ); 68 | } 69 | } 70 | 71 | async function clearOld() { 72 | const giteeDirAllFile = fs.readdirSync(giteeDir); 73 | const queue = []; 74 | giteeDirAllFile.forEach((url) => { 75 | const fullurl = `${giteeDir}/${url}`; 76 | if (!['node_modules', '.git'].includes(url)) { 77 | queue.push(trash(fullurl)); 78 | } 79 | }); 80 | await Promise.all(queue); 81 | } 82 | 83 | const newPkgStr = fs.readFileSync( 84 | path.resolve(localDir, 'package.json'), 85 | 'utf-8' 86 | ); 87 | const viteConfigStr = fs.readFileSync( 88 | path.resolve(localDir, './deploy/vite.config.ts'), 89 | 'utf-8' 90 | ); 91 | const tsconfigStr = fs.readFileSync( 92 | path.resolve(localDir, './deploy/tsconfig.json'), 93 | 'utf-8' 94 | ); 95 | const newPkg = JSON.parse(newPkgStr); 96 | delete newPkg['devDependencies']['@electron-toolkit/preload']; 97 | delete newPkg['devDependencies']['@electron/rebuild']; 98 | delete newPkg['devDependencies']['electron']; 99 | delete newPkg['devDependencies']['electron-builder']; 100 | delete newPkg['devDependencies']['electron-icon-builder']; 101 | 102 | if (process.cwd().indexOf('jenkins') !== -1) { 103 | console.log('当前目录错误'); 104 | } else { 105 | clearOld().then(() => { 106 | findFile(dir); 107 | putFile(); 108 | const gitignoreArr = [ 109 | 'node_modules', 110 | 'electron-release', 111 | 'electron-dist', 112 | 'dist', 113 | 'components.d.ts', 114 | 'auto-imports.d.ts', 115 | '.eslintcache', 116 | '.DS_Store', 117 | ]; 118 | const gitignoreTxt = gitignoreArr.join('\n'); 119 | fs.writeFileSync(path.resolve(giteeDir, './.gitignore'), gitignoreTxt); 120 | fs.writeFileSync( 121 | path.resolve(giteeDir, 'package.json'), 122 | // @ts-ignore 123 | JSON.stringify({ ...newPkg }, {}, 2) 124 | ); 125 | fs.writeFileSync( 126 | path.resolve(giteeDir, 'vite.config.ts'), 127 | // @ts-ignore 128 | viteConfigStr 129 | ); 130 | fs.writeFileSync( 131 | path.resolve(giteeDir, 'tsconfig.json'), 132 | // @ts-ignore 133 | tsconfigStr 134 | ); 135 | fs.writeFileSync( 136 | path.resolve(giteeDir, 'deploy/jenkins.json'), 137 | // @ts-ignore 138 | JSON.stringify({ 139 | buildDate: new Date().toLocaleString(), 140 | }) 141 | ); 142 | execSync(`pnpm i`, { cwd: giteeDir }); 143 | execSync(`git rm -r --cached .`, { cwd: giteeDir }); 144 | execSync(`git add .`, { cwd: giteeDir }); 145 | execSync(`git commit -m 'feat: ${new Date().toLocaleString()}'`, { 146 | cwd: giteeDir, 147 | }); 148 | execSync(`git push`, { cwd: giteeDir }); 149 | }); 150 | } 151 | -------------------------------------------------------------------------------- /deploy/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "skipLibCheck": true, 8 | "noImplicitAny": false, 9 | 10 | /* Bundler mode */ 11 | "moduleResolution": "bundler", 12 | "allowImportingTsExtensions": true, 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "noEmit": true, 16 | "jsx": "preserve", 17 | 18 | "baseUrl": "./", 19 | "paths": { 20 | "@/*": ["src/*"] 21 | }, 22 | 23 | /* Linting */ 24 | "strict": true, 25 | "noUnusedLocals": true, 26 | "noUnusedParameters": true, 27 | "noFallthroughCasesInSwitch": true 28 | }, 29 | 30 | "include": [ 31 | "src/**/*.ts", 32 | "src/**/*.d.ts", 33 | "src/**/*.tsx", 34 | "src/**/*.vue", 35 | "config/**/*.ts", 36 | "components.d.ts" 37 | ], // 仅仅匹配这些文件,除了src以外的文件都不会被匹配 38 | "references": [{ "path": "./tsconfig.node.json" }] 39 | } 40 | -------------------------------------------------------------------------------- /docs/benchmarking.md: -------------------------------------------------------------------------------- 1 | 主要测试各个端之间远程时候的延迟。 2 | 3 | > TODO 4 | -------------------------------------------------------------------------------- /docs/faq.md: -------------------------------------------------------------------------------- 1 | ## 应用图标缓存问题 2 | 3 | 如果应用图标不更新,可以尝试替换一个图标图片再打包,或者你不希望换图标图片的话,可以将现在的图标图片拿去压缩一下,亲测也能解决问题。 4 | 5 | ## pnpm 安装 electron 时卡在 postinstall 6 | 7 | 1. 直接 ctrl+c 退出 npm 安装 8 | 2. 进入 node_modules/electron/install.js,将 9 | ```js 10 | downloadArtifact({ 11 | version, 12 | artifactName: 'electron', 13 | force: process.env.force_no_cache === 'true', 14 | cacheRoot: process.env.electron_config_cache, 15 | checksums: 16 | (process.env.electron_use_remote_checksums ?? 17 | process.env.npm_config_electron_use_remote_checksums) 18 | ? undefined 19 | : require('./checksums.json'), 20 | platform, 21 | arch, 22 | }) 23 | .then(extractFile) 24 | .catch((err) => { 25 | console.error(err.stack); 26 | process.exit(1); 27 | }); 28 | ``` 29 | 修改为: 30 | ```js 31 | downloadArtifact({ 32 | version, 33 | artifactName: 'electron', 34 | force: process.env.force_no_cache === 'true', 35 | cacheRoot: process.env.electron_config_cache, 36 | checksums: 37 | (process.env.electron_use_remote_checksums ?? 38 | process.env.npm_config_electron_use_remote_checksums) 39 | ? undefined 40 | : require('./checksums.json'), 41 | platform, 42 | arch, 43 | mirrorOptions: { 44 | mirror: 'https://npmmirror.com/mirrors/electron/', 45 | platform, 46 | arch, 47 | }, 48 | }) 49 | .then(extractFile) 50 | .catch((err) => { 51 | console.error(err.stack); 52 | process.exit(1); 53 | }); 54 | ``` 55 | 3. 在 node_modules/electron 目录下执行 node install 56 | 57 | ## rebuild 58 | 59 | ```bash 60 | npm config set registry https://registry.npmmirror.com 61 | ``` 62 | 63 | ```bash 64 | ./node_modules/.bin/electron-rebuild 65 | ``` 66 | 67 | ## rebuild 时 cpu-feature 报错 68 | 69 | 直接删了 node_modules 的 cpu-feature,然后重新 rebuild 70 | 71 | ## windows下,desktopCapturer.getSources获取不到自身窗口 72 | 73 | - 最开始Issue:https://github.com/electron/electron/issues/36037 74 | - 升级到最新版35.0.2解决:https://github.com/electron/electron/pull/45000 75 | - 好家伙,隔了两年才修复哈哈哈。 76 | -------------------------------------------------------------------------------- /docs/features.md: -------------------------------------------------------------------------------- 1 | ## 基础功能 2 | 3 | | | BilldDesk | 4 | | ------------------------- | ----------------- | 5 | | 远程控制 | 支持 | 6 | | 画质 | 最高支持8K、120帧 | 7 | | 快速邀请远程 | 支持 | 8 | | 文件传输 | 支持 | 9 | | 安卓被控 | 支持 | 10 | | 多屏操作 | 支持 | 11 | | 屏幕墙 | 支持 | 12 | | web网页发起远程控制 | 支持 | 13 | | 远程控制web网页(仅观看) | 支持 | 14 | | 远程控制时保存截图 | 支持 | 15 | | 远程控制时保存录制视频 | TODO | 16 | 17 | ## web网页/客户端 18 | 19 | | | BilldDesk | 20 | | ---------------- | --------- | 21 | | 常用按键 | 支持 | 22 | | 常用组合键 | 支持 | 23 | | 自定义组合键映射 | TODO | 24 | 25 | ## 安卓端 26 | 27 | | | BilldDesk | 28 | | ------------ | ---------------------------------------- | 29 | | 物理按键控制 | 支持返回键、主页键、任务键、音量+、音量- | 30 | | 剪贴板 | 支持 | 31 | 32 | ## 更多功能敬请期待 33 | -------------------------------------------------------------------------------- /docs/start-app.md: -------------------------------------------------------------------------------- 1 | ## billd-desk-flutter(pro) 2 | 3 | ## 调试 4 | 5 | ```bash 6 | flutter pub get 7 | ``` 8 | 9 | 使用 vscode 开发,用 vscode 自带的调试 10 | 11 | ## 打包 12 | 13 | > https://docs.flutter.cn/deployment/android/#build-an-apk 14 | 15 | ### 安卓 16 | 17 | ```bash 18 | flutter build apk --release 19 | ``` 20 | 21 | > 默认输出项项目的 build/app/outputs/flutter-apk/app-release.apk 目录 22 | 23 | ### 苹果(TODO) 24 | 25 | ```bash 26 | flutter build ipa --release 27 | ``` 28 | 29 | ### 生成 app 图标 30 | 31 | > 生成的图标在 android/app/src/main/res/目录里 32 | 33 | ```bash 34 | dart run flutter_launcher_icons:main 35 | ## 或者 36 | flutter pub run flutter_launcher_icons:main 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/start-client.md: -------------------------------------------------------------------------------- 1 | ## billd-desk(pro) 2 | 3 | ## 安装依赖 4 | 5 | > 使用 node 版本:v18.19.0,建议18版本 6 | > 使用 pnpm 版本:9.1.3,建议9版本 7 | 8 | ```bash 9 | pnpm i 10 | ``` 11 | 12 | > 更新 billd 相关依赖: 13 | 14 | ```bash 15 | pnpm i billd-deploy@latest billd-utils@latest billd-scss@latest billd-html-webpack-plugin@latest 16 | ``` 17 | 18 | ## 运行 19 | 20 | > 配置文件:**`src/spec-config.ts`**,请在该文件填写对应的信息。 21 | 22 | ```bash 23 | npm run dev 24 | ``` 25 | 26 | ## 打包 27 | 28 | > 打包时会先使用[`standard-version`](https://github.com/conventional-changelog/standard-version#readme)进行发版,请确保当前项目初始化了 git,否则打包会失败。 29 | 30 | - web 31 | 32 | > 打包成功后,资源输出在`dist`目录 33 | 34 | ```bash 35 | npm run build:web 36 | ``` 37 | 38 | - windows、macos、linux 包 39 | 40 | > 打包成功后,资源输出在`electron-release`目录 41 | 42 | ```bash 43 | npm run build 44 | ``` 45 | 46 | - windows 包 47 | 48 | > 打包成功后,资源输出在`electron-release`目录 49 | 50 | ```bash 51 | npm run build:win 52 | ``` 53 | 54 | - macos 包 55 | 56 | > 打包成功后,资源输出在`electron-release`目录 57 | 58 | ```bash 59 | npm run build:mac 60 | ``` 61 | 62 | - linux 包 63 | 64 | > 打包成功后,资源输出在`electron-release`目录 65 | 66 | ```bash 67 | npm run build:linux 68 | ``` 69 | -------------------------------------------------------------------------------- /docs/start-server.md: -------------------------------------------------------------------------------- 1 | ## billd-desk-server(pro) 2 | 3 | ## 安装依赖 4 | 5 | > 使用 node 版本:v18.19.0,建议18版本 6 | > 使用 pnpm 版本:9.1.3,建议9版本 7 | 8 | ```bash 9 | pnpm i 10 | ``` 11 | 12 | > 更新 billd 相关依赖: 13 | 14 | ```bash 15 | pnpm i billd-utils@latest billd-html-webpack-plugin@latest 16 | ``` 17 | 18 | ## 运行 19 | 20 | > 1. 项目使用到了 mysql 和 redis,他们都是用 docker 来启动的。 21 | > 2. 项目启动后,会在项目的 src/secret/目录下生成 secret-beta、secret-dev、secret-prod 文件,请填写里面的信息,MYSQL_CONFIG、REDIS_CONFIG 必填! 22 | > 3. 配置文件:**`src/spec-config.ts`**,请填写里面的信息。 23 | 24 | 1. 初始化 docker 容器 25 | 26 | 如果你用 docker 启动 mysql 和 redis,就需要初始化 docker 容器。 27 | 28 | 如果你不用 docker,你本地 mysql 和 redis,只要你连上 mysql 和 redis 即可,不需要初始化 docker 容器。 29 | 30 | ```bash 31 | npm run docker:dev 32 | ``` 33 | 34 | 执行效果: 35 | 36 | ```bash 37 | ➜ billd-desk-server-pro git:(main) ✗ npm run docker:dev 38 | 39 | > billd-desk-server@0.1.0 docker:dev 40 | > cross-env NODE_ENV=development NODE_APP_RELEASE_PROJECT_ALIAS=src NODE_APP_RELEASE_PROJECT_NAME=billd-desk-server NODE_APP_RELEASE_PROJECT_ENV=dev NODE_APP_RELEASE_PROJECT_PORT=5300 nodemon --exec node -r @swc-node/register ./src/init/docker.ts 41 | 42 | [nodemon] 2.0.15 43 | [nodemon] to restart at any time, enter `rs` 44 | [nodemon] watching path(s): *.* 45 | [nodemon] watching extensions: ts,json 46 | [nodemon] starting `node -r @swc-node/register ./src/init/docker.ts` 47 | [2025/2/17 21:06:33] SUCCESS 添加路径别名成功! 48 | [2025/2/17 21:06:33] SUCCESS docker已安装 49 | [2025/2/17 21:06:33] WARN 开始启动Mysql 50 | [2025/2/17 21:06:36] SUCCESS 启动Mysql成功! ✅ 51 | [2025/2/17 21:06:36] WARN 开始启动Redis 52 | [2025/2/17 21:06:37] SUCCESS 启动Redis成功! ✅ 53 | [nodemon] clean exit - waiting for changes before restart 54 | 55 | ``` 56 | 57 | > 看到 `[nodemon] clean exit - waiting for changes before restart`后,就 ctrl+c 退出命令即可。 58 | 59 | 2. 初始化数据库 60 | 61 | 这个命令只需要执行一次,执行后就会自动创建数据库(src/secret/secret-dev 的 MYSQL_CONFIG.database)和数据库表。 62 | 63 | 执行一次后,以后都不需要执行了。 64 | 65 | ```bash 66 | npm run mysql:dev 67 | ``` 68 | 69 | 执行效果: 70 | 71 | ```bash 72 | ➜ billd-desk-server-pro git:(main) ✗ npm run mysql:dev 73 | 74 | > billd-desk-server@0.1.0 mysql:dev 75 | > cross-env NODE_APP_INIT_MYSQL=true NODE_ENV=development NODE_APP_RELEASE_PROJECT_NAME=billd-desk-server NODE_APP_RELEASE_PROJECT_ENV=dev NODE_APP_RELEASE_PROJECT_PORT=5300 nodemon --exec node -r @swc-node/register ./src/index.ts 76 | 77 | [nodemon] 2.0.15 78 | [nodemon] to restart at any time, enter `rs` 79 | [nodemon] watching path(s): *.* 80 | [nodemon] watching extensions: ts,json 81 | [nodemon] starting `node -r @swc-node/register ./src/index.ts` 82 | [2025/2/17 21:21:47] SUCCESS 添加路径别名成功! 83 | [2025/2/17 21:21:48] INFO 开始连接127.0.0.1:3307服务器的billd_desk_test数据库... 84 | [2025/2/17 21:21:48] SUCCESS 新建billd_desk_test数据库成功! 85 | [2025/2/17 21:21:48] WARN 开始校正数据库所有表 86 | [2025/2/17 21:21:48] SUCCESS 校正数据库所有表完成! 87 | [2025/2/17 21:21:48] INFO 加载数据库表: auth 88 | [2025/2/17 21:21:48] INFO 加载数据库表: desk_config 89 | [2025/2/17 21:21:48] INFO 加载数据库表: desk_user 90 | [2025/2/17 21:21:48] INFO 加载数据库表: desk_version 91 | [2025/2/17 21:21:48] INFO 加载数据库表: live 92 | [2025/2/17 21:21:48] INFO 加载数据库表: mock_day_data 93 | [2025/2/17 21:21:48] INFO 加载数据库表: mock_hour_data 94 | [2025/2/17 21:21:48] INFO 加载数据库表: mock_minute_ten_data 95 | [2025/2/17 21:21:48] INFO 加载数据库表: mock_minute_thirty_data 96 | [2025/2/17 21:21:48] INFO 加载数据库表: qq_user 97 | [2025/2/17 21:21:48] INFO 加载数据库表: role 98 | [2025/2/17 21:21:48] INFO 加载数据库表: role_auth 99 | [2025/2/17 21:21:48] INFO 加载数据库表: third_user 100 | [2025/2/17 21:21:48] INFO 加载数据库表: user 101 | [2025/2/17 21:21:48] INFO 加载数据库表: user_role 102 | [2025/2/17 21:21:48] INFO 加载数据库表: wechat_user 103 | [2025/2/17 21:21:48] SUCCESS 加载所有数据库表成功! 104 | [2025/2/17 21:21:48] WARN 开始初始化数据库所有表 105 | [2025/2/17 21:21:48] WARN 需要删除外键的表: 106 | [2025/2/17 21:21:48] SUCCESS 删除表的外键成功! 107 | [2025/2/17 21:21:48] WARN 需要删除索引的表: 108 | [2025/2/17 21:21:48] SUCCESS 删除表的索引成功! 109 | [2025/2/17 21:21:48] SUCCESS 删除所有表成功! 110 | [2025/2/17 21:21:48] SUCCESS 初始化数据库所有表完成! 111 | [2025/2/17 21:21:48] SUCCESS 初始化数据库数据完成!请退出该命令! 112 | 113 | ``` 114 | 115 | > 看到 `初始化数据库数据完成!请退出该命令!`后,就 ctrl+c 退出命令即可。 116 | 117 | 3. 运行,默认运行在 5300 端口 118 | 119 | ```bash 120 | npm run dev 121 | ``` 122 | 123 | 执行效果: 124 | 125 | ```bash 126 | ➜ billd-desk-server-pro git:(main) ✗ npm run dev 127 | 128 | > billd-desk-server@0.1.0 dev 129 | > cross-env NODE_ENV=development NODE_APP_RELEASE_PROJECT_NAME=billd-desk-server NODE_APP_RELEASE_PROJECT_ENV=dev NODE_APP_RELEASE_PROJECT_PORT=5300 nodemon --exec node -r @swc-node/register ./src/index.ts 130 | 131 | [nodemon] 2.0.15 132 | [nodemon] to restart at any time, enter `rs` 133 | [nodemon] watching path(s): *.* 134 | [nodemon] watching extensions: ts,json 135 | [nodemon] starting `node -r @swc-node/register ./src/index.ts` 136 | [2025/2/17 21:27:17] SUCCESS 添加路径别名成功! 137 | [2025/2/17 21:27:17] INFO 开始连接127.0.0.1:3307服务器的billd_desk_test数据库... 138 | [2025/2/17 21:27:17] INFO 开始连接127.0.0.1:6380服务器的redis数据库... 139 | [2025/2/17 21:27:17] INFO 开始连接127.0.0.1:6380服务器的redis Pub... 140 | [2025/2/17 21:27:17] INFO 开始连接127.0.0.1:6380服务器的redis Sub... 141 | [2025/2/17 21:27:17] SUCCESS 连接127.0.0.1:6380服务器的redis数据库成功! 142 | [2025/2/17 21:27:17] SUCCESS 连接127.0.0.1:6380服务器的redis Sub 成功! 143 | [2025/2/17 21:27:17] SUCCESS 连接127.0.0.1:6380服务器的redis Pub 成功! 144 | [2025/2/17 21:27:17] INFO 加载数据库表: auth 145 | [2025/2/17 21:27:17] INFO 加载数据库表: desk_config 146 | [2025/2/17 21:27:17] INFO 加载数据库表: desk_user 147 | [2025/2/17 21:27:17] INFO 加载数据库表: desk_version 148 | [2025/2/17 21:27:17] INFO 加载数据库表: live 149 | [2025/2/17 21:27:17] INFO 加载数据库表: mock_day_data 150 | [2025/2/17 21:27:17] INFO 加载数据库表: mock_hour_data 151 | [2025/2/17 21:27:17] INFO 加载数据库表: mock_minute_ten_data 152 | [2025/2/17 21:27:17] INFO 加载数据库表: mock_minute_thirty_data 153 | [2025/2/17 21:27:17] INFO 加载数据库表: qq_user 154 | [2025/2/17 21:27:17] INFO 加载数据库表: role 155 | [2025/2/17 21:27:17] INFO 加载数据库表: role_auth 156 | [2025/2/17 21:27:17] INFO 加载数据库表: third_user 157 | [2025/2/17 21:27:17] INFO 加载数据库表: user 158 | [2025/2/17 21:27:17] INFO 加载数据库表: user_role 159 | [2025/2/17 21:27:17] INFO 加载数据库表: wechat_user 160 | [2025/2/17 21:27:17] SUCCESS 加载所有数据库表成功! 161 | [2025/2/17 21:27:17] SUCCESS 连接127.0.0.1:3307服务器的billd_desk_test数据库成功! 162 | [2025/2/17 21:27:17] INFO 加载路由: auth.router.ts 163 | [2025/2/17 21:27:17] INFO 加载路由: deskUser.router.ts 164 | [2025/2/17 21:27:17] INFO 加载路由: deskVersion.router.ts 165 | [2025/2/17 21:27:17] INFO 加载路由: init.router.ts 166 | [2025/2/17 21:27:17] INFO 加载路由: qqUser.router.ts 167 | [2025/2/17 21:27:17] INFO 加载路由: role.router.ts 168 | [2025/2/17 21:27:17] INFO 加载路由: user.router.ts 169 | [2025/2/17 21:27:17] INFO 加载路由: wechatUser.router.ts 170 | [2025/2/17 21:27:17] SUCCESS 加载所有路由成功! 171 | [2025/2/17 21:27:17] SUCCESS 初始化websocket成功! 172 | 173 | [2025/2/17 21:27:17] WARN 监听端口: 5300 174 | [2025/2/17 21:27:17] WARN 项目名称: billd-desk-server 175 | [2025/2/17 21:27:17] WARN 项目环境: dev 176 | [2025/2/17 21:27:17] WARN mysql host: 127.0.0.1 177 | [2025/2/17 21:27:17] WARN mysql数据库: billd_desk_test 178 | [2025/2/17 21:27:17] SUCCESS http://127.0.0.1:5300/ 179 | [2025/2/17 21:27:17] SUCCESS http://192.168.1.102:5300/ 180 | [2025/2/17 21:27:17] SUCCESS http://10.211.55.2:5300/ 181 | [2025/2/17 21:27:17] SUCCESS http://10.37.129.2:5300/ 182 | [2025/2/17 21:27:17] SUCCESS 项目启动成功!耗时:233ms 183 | 184 | [2025/2/17 21:27:17] INFO 联系作者: https://desk.hsslive.cn/#/hi 185 | [2025/2/17 21:27:17] INFO 订阅仓库: https://desk.hsslive.cn/#/price 186 | [2025/2/17 21:27:17] INFO 私有化部署: https://desk.hsslive.cn/#/privatizationDeployment 187 | [2025/2/17 21:27:17] INFO 欢迎PR: billd-desk目前只有作者一人开发,难免有不足的地方,欢迎提PR或Issue 188 | 189 | 190 | ``` 191 | -------------------------------------------------------------------------------- /docs/思路.md: -------------------------------------------------------------------------------- 1 | - 客户端打开后,判断缓存有无uid 2 | 3 | - 有uid和token,验证uid和token,连接Websocket 4 | - 没有uid和token,调接口获取uid 5 | 6 | - 打开客户端,ws连接,join的时候,带上desk_user_id,在redis里添加一个记录desk_user_uuid,设置他的过期时间为10秒 7 | - 设置心跳为5秒一次,每次心跳都更新desk_user_uuid的过期时间 8 | - 给desk_user_uuid添加过期订阅,过期的时候判断为远程连接断开 9 | - 发起远程连接的时候,发送startRemote,带上desk信息 10 | 11 | - 锁屏的时候 12 | 13 | - websocket是否会断开 14 | - 会断开。 15 | - webrtc是否会断开 16 | - 会断开。 17 | 18 | - 主动断开远程连接如何判定? 19 | -------------------------------------------------------------------------------- /docs/本地环境.md: -------------------------------------------------------------------------------- 1 | ## docker 安装 mysql 2 | 3 | ### 拉镜像 4 | 5 | ```bash 6 | docker pull mysql:8.0 7 | ``` 8 | 9 | ### 复制配置文件到本地 10 | 11 | 先查看配置文件位置: 12 | 13 | ```bash 14 | docker run --rm mysql:8.0 mysql --help | grep my.cnf 15 | ``` 16 | 17 | 查看配置文件位置结果: 18 | 19 | ```bash 20 | ➜ billd-desk-server git:(master) ✗ docker run --rm mysql:8.0 mysql --help | grep my.cnf 21 | order of preference, my.cnf, $MYSQL_TCP_PORT, 22 | /etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf 23 | ➜ billd-desk-server git:(master) ✗ 24 | ``` 25 | 26 | 意思是按照/etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf 路径按优先排序。 27 | 28 | ```bash 29 | ➜ billd-desk-server git:(master) ✗ docker run --rm mysql cat /etc/my.cnf 30 | # For advice on how to change settings please see 31 | # http://dev.mysql.com/doc/refman/8.0/en/server-configuration-defaults.html 32 | 33 | [mysqld] 34 | # 35 | # Remove leading # and set to the amount of RAM for the most important data 36 | 省略... 37 | ➜ billd-desk-server git:(master) ✗ 38 | ``` 39 | 40 | 可以得到镜像中 mysql 配置文件路径为:/etc/my.cnf 41 | 42 | 创建一个临时的容器,在它里面复制配置文件到本地: 43 | 44 | > 注意,本地需要存在/Users/huangshuisheng/Desktop/docker/mysql/conf 这个目录 45 | 46 | 本地复制时用这个命令: 47 | 48 | ```bash 49 | LOCAL_DOCKER_MYSQL_PATH=/Users/huangshuisheng/Desktop/docker/mysql \ 50 | DOCKER_MYSQL_TMP=`docker run -d mysql:8.0` \ 51 | && docker cp $DOCKER_MYSQL_TMP:/etc/my.cnf $LOCAL_DOCKER_MYSQL_PATH/conf \ 52 | && docker stop $DOCKER_MYSQL_TMP \ 53 | && docker rm $DOCKER_MYSQL_TMP 54 | ``` 55 | 56 | ### 启动容器 57 | 58 | ```bash 59 | # 使用自定义 MySQL 配置文件 60 | # billd-desk-mysql是docker容器名,/Users/huangshuisheng/Desktop/docker/mysql是映射到本机的mysql,123456是密码 61 | 62 | LOCAL_DOCKER_MYSQL_PATH=/Users/huangshuisheng/Desktop/docker/mysql \ 63 | && docker run -d \ 64 | -p 3306:3306 \ 65 | --name billd-desk-mysql \ 66 | -e MYSQL_ROOT_PASSWORD=mysql123. \ 67 | -v $LOCAL_DOCKER_MYSQL_PATH/conf/my.cnf:/etc/my.cnf \ 68 | -v $LOCAL_DOCKER_MYSQL_PATH/data:/var/lib/mysql/ \ 69 | mysql:8.0 70 | ``` 71 | 72 | ## docker 安装 redis 73 | 74 | ### 拉镜像 75 | 76 | ```bash 77 | docker pull redis:7.0 78 | ``` 79 | 80 | ### 复制配置文件到本地 81 | 82 | > https://raw.githubusercontent.com/redis/redis/7.0/redis.conf 83 | 84 | 在/Users/huangshuisheng/Desktop/docker/redis/新建 conf 目录 85 | 在/Users/huangshuisheng/Desktop/docker/redis/新建 data 目录 86 | 87 | 将项目根目录的/docker/redis/conf/redis.conf 和 users.acl 复制到/Users/huangshuisheng/Desktop/docker/redis/conf 88 | 89 | ### 本地启动容器 90 | 91 | ```bash 92 | # 使用自定义 redis 配置文件 93 | # billd-desk-redis是docker容器名,/Users/huangshuisheng/Desktop/docker/redis是映射到本机的redis 94 | 95 | LOCAL_DOCKER_RESIS_PATH=/Users/huangshuisheng/Desktop/docker/redis \ 96 | && docker run -d \ 97 | -p 6379:6379 \ 98 | --name billd-desk-redis \ 99 | -v $LOCAL_DOCKER_RESIS_PATH/data:/data \ 100 | -v $LOCAL_DOCKER_RESIS_PATH/conf/redis.conf:/etc/redis/redis.conf \ 101 | -v $LOCAL_DOCKER_RESIS_PATH/conf/users.acl:/etc/redis/users.acl \ 102 | redis:7.0 redis-server /etc/redis/redis.conf 103 | ``` 104 | 105 | ## docker 安装 coturn 106 | 107 | > 本地环境时,不需要用 coturn 108 | 109 | ### 拉镜像 110 | 111 | ```bash 112 | docker pull coturn/coturn 113 | ``` 114 | 115 | ### 启动容器 116 | 117 | ```bash 118 | LOCAL_DOCKER_COTURN_PATH=/Users/huangshuisheng/Desktop/docker/coturn \ 119 | && docker run -d --network=host \ 120 | --name billd-desk-coturn \ 121 | -v $LOCAL_DOCKER_COTURN_PATH/coturn.conf:/my/coturn.conf \ 122 | coturn/coturn -c /my/coturn.conf 123 | ``` 124 | -------------------------------------------------------------------------------- /docs/流程.md: -------------------------------------------------------------------------------- 1 | # 一对一远程 2 | 3 | 没什么好说的 4 | 5 | # 多对一远程 6 | 7 | > 多个用户同时控制一个客户端 8 | > 被控端都有自己的房间(唯一) 9 | 10 | - 开始远程控制 11 | - 控制端,用户点击连接,发送startRemote消息,开始远程控制。 12 | - 被控端,监听startRemote消息,收到startRemote消息后,判断stream 13 | - 没有stream,调原生接口获取stream 14 | - 有stream,开始updateWebRtcRemoteDeskConfig,开始走webrtc流程(offer、answer等) 15 | - 操作问题,所有进入远程控制的用户都可以进行操作(或者可以加个限制或者切换,一种是控制模式,另一种是观看模式)。 16 | - 结束远程控制,用户结束远程控制。 17 | - 一对多,断开一个不能影响其他连接 18 | - 被控端判断有没有用户连接,只有当所有用户都断开连接的时候,才显示已断开远程连接。 19 | 20 | # 实际 21 | 22 | - a用户远程客户端 23 | - 客户端收到a用户的远程请求,获取stream,然后和a用户进行webrtc处理 24 | - b用户远程客户端 25 | - 客户端收到b用户的远程请求,获取stream,然后和a用户进行webrtc处理 26 | -------------------------------------------------------------------------------- /electron-builder.json5: -------------------------------------------------------------------------------- 1 | /** 2 | * https://www.electron.build/configuration/configuration 3 | * https://github.com/electron-vite/electron-vite-vue/blob/main/electron-builder.json5 4 | */ 5 | { 6 | $schema: 'https://raw.githubusercontent.com/electron-userland/electron-builder/master/packages/app-builder-lib/scheme.json', 7 | appId: 'com.billddesk.app', 8 | // asar: false, 9 | // 优先读取这个文件的productName,没有就会读取package.json的productName 10 | // productName: 'BilldDesk', 11 | directories: { 12 | output: 'electron-release/${version}', 13 | }, 14 | files: ['dist', 'electron-dist'], 15 | mac: { 16 | target: { 17 | target: 'dmg', 18 | // https://github.com/electron-userland/electron-builder/issues/5392 19 | arch: ['x64', 'arm64'], 20 | // arch: ['arm64'], 21 | }, 22 | artifactName: '${productName}-mac-${platform}-${version}-${arch}-installer.${ext}', 23 | icon: 'build/output/icons/icon.icns', 24 | }, 25 | protocols: [ 26 | // for macOS - 用于在主机注册指定协议 27 | { 28 | name: 'BilldDesk', 29 | schemes: ['BilldDesk'], 30 | }, 31 | ], 32 | linux: { 33 | artifactName: '${productName}-linux-${platform}-${version}-${arch}-installer.${ext}', 34 | // amd是x64 35 | target: [ 36 | { 37 | target: 'AppImage', 38 | arch: ['x64', 'arm64'], 39 | }, 40 | ], 41 | }, 42 | win: { 43 | artifactName: '${productName}-win-${platform}-${version}-${arch}-installer.${ext}', 44 | // highestAvailable,可用的最高权限 45 | // requireAdministrator,管理员权限 46 | requestedExecutionLevel: 'requireAdministrator', 47 | target: [ 48 | { 49 | // portable、nsis 50 | target: 'nsis', 51 | arch: ['x64', 'arm64'], 52 | // arch: ['x64'], 53 | }, 54 | ], 55 | icon: 'build/output/icons/icon.ico', 56 | }, 57 | // https://www.electron.build/generated/nsisoptions 58 | nsis: { 59 | // oneClick,是否创建一键安装程序或辅助安装程序 60 | oneClick: false, 61 | // perMachine,是否显示辅助安装程序的安装模式安装程序页面(按计算机或按用户选择)。或者是否始终为所有用户(每台计算机)安装。 62 | perMachine: true, 63 | // allowToChangeInstallationDirectory,仅辅助安装程序。是否允许用户更改安装目录。 64 | allowToChangeInstallationDirectory: true, 65 | // removeDefaultUninstallWelcomePage,仅辅助安装程序。删除默认卸载欢迎页面。 66 | removeDefaultUninstallWelcomePage: false, 67 | // deleteAppDataOnUninstall,仅限一键安装程序。卸载时是否删除应用程序数据。 68 | deleteAppDataOnUninstall: false, 69 | // for win - 将协议写入主机的脚本 70 | include: 'script/urlProtoco.nsh', 71 | // installerIcon: 'build/output/icons/icon.ico', 72 | // uninstallerIcon: 'build/output/icons/icon.ico', 73 | }, 74 | } 75 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from '@eslint/js'; 2 | import pluginTypeScript from '@typescript-eslint/eslint-plugin'; 3 | import * as parserTypeScript from '@typescript-eslint/parser'; 4 | import configPrettier from 'eslint-config-prettier'; 5 | import { defineFlatConfig } from 'eslint-define-config'; 6 | import importPlugin from 'eslint-plugin-import'; 7 | import pluginPrettier from 'eslint-plugin-prettier'; 8 | import pluginVue from 'eslint-plugin-vue'; 9 | import * as parserVue from 'vue-eslint-parser'; 10 | 11 | console.log( 12 | '\x1B[0;37;44m INFO \x1B[0m', 13 | '\x1B[0;;34m ' + `读取了: eslint配置文件` + ' \x1B[0m' 14 | ); 15 | 16 | export default defineFlatConfig([ 17 | { 18 | ...js.configs.recommended, 19 | ...importPlugin.flatConfigs.recommended, 20 | ignores: [ 21 | 'node_modules', 22 | 'pnpm-lock.yaml', 23 | 'dist', 24 | 'components.d.ts', 25 | 'auto-imports.d.ts', 26 | 'electron-dist/**/*', 27 | 'deploy/**/*', 28 | '.DS_Store', 29 | '.eslintcache', 30 | ], 31 | languageOptions: { 32 | globals: {}, 33 | }, 34 | plugins: { 35 | prettier: pluginPrettier, 36 | import: importPlugin, 37 | }, 38 | rules: { 39 | ...configPrettier.rules, 40 | ...pluginPrettier.configs.recommended.rules, 41 | /** 42 | * 0 => off 43 | * 1 => warn 44 | * 2 => error 45 | */ 46 | 'no-unused-vars': 0, // 禁止出现未使用过的变量 47 | 'no-shadow': 0, // 禁止变量声明与外层作用域的变量同名 48 | 'class-methods-use-this': 0, // 类方法如果不使用this的话会报错 49 | 'no-console': 0, // 此规则不允许调用console对象的方法。 50 | 'spaced-comment': ['error', 'always', { exceptions: ['-', '+'] }], // 该规则强制注释中 // 或 /* 后空格的一致性 51 | 'no-var': 2, // 要求let或const代替var 52 | camelcase: [ 53 | 'error', 54 | { properties: 'never' }, // properties默认always,即检查属性名;可以设置为never,即不检查属性名 55 | ], // 强制执行驼峰命名约定 56 | 'no-underscore-dangle': 2, // 此规则不允许在标识符中使用悬空下划线。 57 | 'no-param-reassign': 2, // 禁止对 function 的参数进行重新赋值 58 | 'no-nested-ternary': 2, // 禁止嵌套三元 59 | 'no-plusplus': 2, // 禁用一元操作符 ++ 和 -- 60 | 'vars-on-top': 2, // 要求所有的 var 声明出现在它们所在的作用域顶部 61 | 'prefer-const': 2, // 要求使用 const 声明那些声明后不再被修改的变量 62 | 'prefer-template': 2, // 要求使用模板字符串代替字符串连接 63 | 'new-cap': 2, // 要求构造函数名称以大写字母开头 64 | 'no-restricted-syntax': [ 65 | // 禁用一些语法 66 | 'error', 67 | // 'ForInStatement', 68 | // 'ForOfStatement', 69 | { 70 | selector: 'ForInStatement', 71 | /** 72 | * 用 map() / every() / filter() / find() / findIndex() / reduce() / some() / ... 遍历数组, 73 | * 和使用 Object.keys() / Object.values() / Object.entries() 迭代你的对象生成数组。 74 | * 拥有返回值得纯函数比这个更容易解释 75 | */ 76 | message: 77 | 'for in会迭代遍历原型链(__proto__),建议使用map/every/filter等遍历数组,使用Object.{keys,values,entries}等遍历对象', 78 | }, 79 | { 80 | selector: 'ForOfStatement', 81 | message: 82 | '建议使用map/every/filter等遍历数组,使用Object.{keys,values,entries}等遍历对象', 83 | }, 84 | ], // https://github.com/BingKui/javascript-zh#%E8%BF%AD%E4%BB%A3%E5%99%A8%E5%92%8C%E5%8F%91%E7%94%9F%E5%99%A8 85 | 'no-iterator': 2, // 禁止使用__iterator__迭代器 86 | 'require-await': 2, // 禁止使用不带 await 表达式的 async 函数 87 | 'no-empty': 2, // 禁止空块语句 88 | 'guard-for-in': 2, // 要求for-in循环包含if语句 89 | 'global-require': 2, // 此规则要求所有调用require()都在模块的顶层,此规则在 ESLint v7.0.0中已弃用。请使用 中的相应规则eslint-plugin-node:https://github.com/mysticatea/eslint-plugin-node 90 | 'no-unused-expressions': [ 91 | 2, 92 | { 93 | allowShortCircuit: true, // 允许短路 94 | allowTernary: true, // 允许三元 95 | }, 96 | ], // 禁止未使用的表达式,即let a = true && console.log(1)允许,但是true && console.log(1)不行 97 | 'object-shorthand': ['error', 'always'], // (默认)希望尽可能使用速记。var foo = {x:x};替换为var foo = {x}; 98 | 'no-useless-escape': 2, // 禁止不必要的转义字符 99 | 100 | 'import/order': [ 101 | 'error', 102 | { 103 | groups: [ 104 | 'builtin', // 如:import fs from 'fs'; 105 | 'external', // 如:import _ from 'lodash'; 106 | 'internal', // 如:import foo from 'src/foo'; 107 | 'parent', // 如:import foo from '../foo'; 108 | 'sibling', // 如:import bar from './bar'; 109 | // ['sibling', 'parent'], 110 | // ['parent', 'sibling'], 111 | 'index', // 如:import main from './'; 112 | 'object', // 如:import log = console.log; 113 | 'type', // 如:import type { Foo } from 'foo'; 114 | ], 115 | pathGroups: [ 116 | { 117 | pattern: '@/**', 118 | group: 'internal', 119 | }, 120 | ], 121 | 'newlines-between': 'always', // 强制或禁止导入组之间的新行 122 | // 根据导入路径以字母顺序排列每个组中的顺序 123 | alphabetize: { 124 | order: 'asc', // 使用asc按升序排序,使用desc按降序排序(默认值:ignore)。 125 | caseInsensitive: true, // 使用true忽略大小写,而false考虑大小写(默认值:false)。 126 | orderImportKind: 'asc', // 使用asc以升序对各种导入类型进行排序,例如以type或typeof为前缀的导入,具有相同的导入路径。使用desc按降序排序(默认值:忽略) 127 | }, 128 | }, 129 | ], 130 | 'import/newline-after-import': 2, // 强制在最后一个顶级导入语句或 require 调用之后有一个或多个空行 131 | 'import/no-extraneous-dependencies': 2, // 禁止导入未在package.json中声明的外部模块。 132 | }, 133 | }, 134 | { 135 | files: ['**/*.?([cm])ts', '**/*.?([cm])tsx'], 136 | languageOptions: { 137 | parser: parserTypeScript, 138 | parserOptions: { 139 | sourceType: 'module', 140 | }, 141 | }, 142 | plugins: { 143 | '@typescript-eslint': pluginTypeScript, 144 | }, 145 | rules: { 146 | ...pluginTypeScript.configs.strict.rules, 147 | 148 | // @typescript-eslint插件 149 | '@typescript-eslint/no-unused-vars': 2, 150 | 151 | // '@typescript-eslint/restrict-template-expressions': [ 152 | // 'error', 153 | // { 154 | // allowBoolean: true, 155 | // allowNumber: true, 156 | // }, 157 | // ], // 强制模板文字表达式为string类型。即const a = {};console.log(`${a}`);会报错 158 | '@typescript-eslint/no-floating-promises': 0, // 要求适当处理类似 Promise 的语句。即将await或者return Promise,或者对promise进行.then或者.catch 159 | '@typescript-eslint/no-explicit-any': 0, // 不允许定义any类型。即let a: any;会报错 160 | '@typescript-eslint/no-non-null-assertion': 0, // 禁止使用非空断言(后缀运算符!)。即const el = document.querySelector('.app');console.log(el!.tagName);会报错 161 | '@typescript-eslint/ban-ts-comment': 0, // 禁止使用@ts-注释 162 | '@typescript-eslint/no-unsafe-assignment': 0, // 不允许将具有类型的值分配any给变量和属性。即const a: any = {};const b = a;会报错 163 | '@typescript-eslint/no-unsafe-argument': 0, // 不允许用any类型的值调用一个函数。即let a: any;Object.keys(a);会报错 164 | '@typescript-eslint/no-unsafe-member-access': 0, // 不允许对类型为any的值进行成员访问。即const a: any = [];console.log(a[0]);会报错 165 | '@typescript-eslint/no-unsafe-return': 0, // 不允许从一个函数中返回一个类型为any的值 166 | '@typescript-eslint/no-unsafe-call': 0, // 不允许调用any类型的值 167 | '@typescript-eslint/no-var-requires': 0, // 即不允许var foo = require('foo');。但是允许import foo = require('foo'); 168 | '@typescript-eslint/restrict-plus-operands': 0, // 要求加法的两个操作数是相同的类型并且是bigint, number, 或string。即const a = '1';console.log(a + 1);会报错 169 | }, 170 | }, 171 | 172 | { 173 | files: ['**/*.vue'], 174 | languageOptions: { 175 | globals: {}, 176 | parser: parserVue, 177 | parserOptions: { 178 | ecmaFeatures: { 179 | jsx: true, 180 | }, 181 | extraFileExtensions: ['.vue'], 182 | parser: '@typescript-eslint/parser', 183 | sourceType: 'module', 184 | }, 185 | }, 186 | plugins: { 187 | vue: pluginVue, 188 | }, 189 | processor: pluginVue.processors['.vue'], 190 | rules: { 191 | ...pluginVue.configs.base.rules, 192 | ...pluginVue.configs['vue3-essential'].rules, 193 | ...pluginVue.configs['vue3-recommended'].rules, 194 | 'vue/multi-word-component-names': 0, 195 | }, 196 | }, 197 | ]); 198 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | <%= title %> 15 | 58 | 59 | 60 |
61 | 65 |
66 | 67 |
68 | 69 | 70 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "billd-desk", 3 | "version": "0.10.0", 4 | "description": "基于Vue3 + WebRTC + Electron + Nodejs搭建的远程桌面", 5 | "keywords": [ 6 | "billd", 7 | "remote-desk", 8 | "webrtc", 9 | "turn", 10 | "turnserver", 11 | "todesk", 12 | "rustdesk", 13 | "向日葵" 14 | ], 15 | "homepage": "https://desk.hsslive.cn", 16 | "bugs": { 17 | "url": "https://github.com/galaxy-s10/billd-desk/issues" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/galaxy-s10/billd-desk" 22 | }, 23 | "license": "MIT", 24 | "author": "shuisheng <2274751790@qq.com>", 25 | "type": "module", 26 | "main": "electron-dist/index.cjs", 27 | "scripts": { 28 | "build:beta": "cross-env VITE_APP_RELEASE_PROJECT_ISWEB=true vite build", 29 | "build:deb": "vite build && electron-builder --linux deb", 30 | "build:linux": "vite build && electron-builder --linux", 31 | "build:mac": "vite build && electron-builder --mac", 32 | "build:mw": "npm run release-prod && vite build && electron-builder --mac --win", 33 | "build:mwl": "npm run release-prod && vite build && electron-builder --mac --win --linux", 34 | "build:prod": "cross-env VITE_APP_RELEASE_PROJECT_ISWEB=true vite build", 35 | "build:web": "cross-env VITE_APP_RELEASE_PROJECT_ISWEB=true vite build", 36 | "build:win": "vite build && electron-builder --win", 37 | "cz": "cz", 38 | "deploy:beta": "node ./deploy/index.cjs --beta", 39 | "deploy:prod": "node ./deploy/index.cjs --prod", 40 | "dev": "rimraf electron-dist dist && vite", 41 | "gen-icons": "rimraf build/output/ && electron-icon-builder --input=./build/source/billd.png --output=./build/output/ --flatten", 42 | "lint": "eslint . --config ./eslint.config.js --cache", 43 | "lint:fix": "eslint . --config ./eslint.config.js --cache --fix", 44 | "preview": "vite preview", 45 | "release": "standard-version", 46 | "release-bigversion": "npm run release -- --release-as major", 47 | "release-fix": "npm run release -- --release-as patch", 48 | "release-prod": "npm run release -- --release-as minor", 49 | "release-version": "npm run release -- --release-as 1.0.0", 50 | "sync-codeup": "ts-node ./deploy/handleSyncCodeup.mjs", 51 | "sync-doc": "ts-node ./deploy/handleSyncDoc.mjs", 52 | "sync-public": "ts-node ./deploy/handleSyncPublic.mjs" 53 | }, 54 | "config": {}, 55 | "dependencies": {}, 56 | "devDependencies": { 57 | "@electron-toolkit/preload": "^3.0.0", 58 | "@electron/rebuild": "^3.7.1", 59 | "@eslint/js": "^9.10.0", 60 | "@types/node": "^20.4.1", 61 | "@typescript-eslint/eslint-plugin": "^7.18.0", 62 | "@typescript-eslint/parser": "^7.18.0", 63 | "@vitejs/plugin-legacy": "^5.3.1", 64 | "@vitejs/plugin-vue": "^5.2.1", 65 | "@vue/eslint-config-prettier": "^8.0.0", 66 | "@vue/eslint-config-typescript": "^11.0.3", 67 | "commitizen": "^4.3.1", 68 | "cross-env": "^7.0.3", 69 | "electron": "^35.0.2", 70 | "electron-builder": "^24.12.0", 71 | "electron-icon-builder": "^2.0.1", 72 | "eslint": "^9.10.0", 73 | "eslint-config-prettier": "^9.1.0", 74 | "eslint-define-config": "^2.1.0", 75 | "eslint-import-resolver-typescript": "^3.6.0", 76 | "eslint-plugin-import": "^2.31.0", 77 | "eslint-plugin-prettier": "^5.2.1", 78 | "eslint-plugin-vue": "^9.28.0", 79 | "node-abi": "^3.71.0", 80 | "postcss-preset-env": "^10.1.2", 81 | "prettier": "^3.4.2", 82 | "rimraf": "^6.0.1", 83 | "sass": "^1.63.6", 84 | "standard-version": "^9.5.0", 85 | "trash": "^8.1.1", 86 | "ts-node": "^10.9.2", 87 | "typescript": "^5.6.2", 88 | "unplugin-auto-import": "^0.17.6", 89 | "unplugin-vue-components": "^0.25.1", 90 | "vite": "^6.0.3", 91 | "vite-plugin-bundle-prefetch": "^0.0.4", 92 | "vite-plugin-checker": "^0.8.0", 93 | "vite-plugin-chunk-split": "^0.5.0", 94 | "vite-plugin-commonjs": "^0.10.1", 95 | "vite-plugin-electron": "^0.28.2", 96 | "vite-plugin-electron-renderer": "^0.14.5", 97 | "vite-plugin-eslint2": "^5.0.3", 98 | "vite-plugin-html": "^3.2.2", 99 | "vue-eslint-parser": "^9.4.3", 100 | "vue-tsc": "^2.1.10" 101 | }, 102 | "productName": "BilldDesk" 103 | } -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | console.log( 2 | '\x1B[0;37;44m INFO \x1B[0m', 3 | '\x1B[0;;34m ' + `读取了: postcss配置文件` + ' \x1B[0m' 4 | ); 5 | 6 | // 把.browserslistrc的last 2 version改成last 20 version就可以看到明显效果 7 | // user-select:none 8 | export default { 9 | plugins: { 10 | 'postcss-preset-env': {}, 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | console.log( 2 | '\x1B[0;37;44m INFO \x1B[0m', 3 | '\x1B[0;;34m ' + `读取了: prettier配置文件` + ' \x1B[0m' 4 | ); 5 | 6 | /** 7 | * @see https://prettier.io/docs/en/configuration.html 8 | * @type {import("prettier").Config} 9 | */ 10 | const config = { 11 | bracketSpacing: true, // 默认为true。即要求:{ foo: bar };可改为false,即要求{foo: bar} 12 | singleQuote: true, // 默认为false。即要求:const a = "1";可改为true,即要求const a = '1' 13 | semi: true, // 默认值true,即要求在所有代码语句的末尾添加分号;可改为false,即要求仅在可能导致 ASI 失败的行的开头添加分号。 14 | singleAttributePerLine: true, // 默认false。即在HTML、Vue和JSX中不要每行强制执行单个属性;可改为true,即要求每行强制执行单个属性。 15 | /** 16 | * jsxBracketSameLine 17 | * 注意是多行,如果是类似这种:1,基本不会触发换行,因此也就不会触发这个bracketSameLine 18 | * 但是如果是类似这种:1,它有多个属性,或者说他的一个属性值很长,可能会导致换行, 19 | * 如果换行了,那么就会触发bracketSameLine,将最后的>单独放在一行或者最后一行的末尾 20 | */ 21 | bracketSameLine: false, // 默认为false。即将多行HTML(HTML、JSX、Vue、Angular)元素的 > 单独放在下一行;可改为true,即将 > 放在最后一行的末尾。 22 | // jsxBracketSameLine: false, // 此选项已在v2.4.0中弃用,使用bracketSameLine替换,https://prettier.io/blog/2021/09/09/2.4.0.html 23 | 24 | /** 25 | * trailingComma 26 | * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Trailing_commas 27 | * 尾后逗号 (有时叫做“终止逗号”)在向 JavaScript 代码添加元素、参数、属性时十分有用。 28 | * 如果你想要添加新的属性,并且上一行已经使用了尾后逗号,你可以仅仅添加新的一行,而不需要修改上一行。 29 | * 这使得版本控制的代码比较(diff)更加清晰,代码编辑过程中遇到的麻烦更少。 30 | */ 31 | trailingComma: 'es5', // 默认值在v2.0.0中none更改为es5。即在ES5中有效的尾随逗号(对象、数组等)。可选:"none":没有尾随逗号;"all":尽可能尾随逗号 32 | 33 | /** 34 | * printWidth 35 | * 如果设置了printWidth值,则以设置的printWidth值为准 36 | * 如果没有设置printWidth值,且.editorconfig文件有设置max_line_length值,则使用.editorconfig文件的max_line_length 37 | */ 38 | printWidth: 80, // 默认80,printWidth不是硬性的允许行长度上限,不要试图将 printWidth 当作 ESLint 的max-len 来使用——它们不一样 39 | 40 | /** 41 | * tabWidth 42 | * 如果设置了tabWidth值,则以设置的tabWidth值为准 43 | * 如果没有设置tabWidth值,且.editorconfig文件有设置indent_size或者tab_width值,则使用.editorconfig文件的indent_size或者tab_width 44 | */ 45 | tabWidth: 2, // 指定每个缩进级别的空格数。 46 | // parser: 'babel', // 指定要使用的解析器。Prettier 会自动从输入文件路径推断解析器,因此您不必更改此设置。 47 | }; 48 | 49 | export default config; 50 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/public/favicon.ico -------------------------------------------------------------------------------- /script/urlProtoco.nsh: -------------------------------------------------------------------------------- 1 | !macro customInstall 2 | DetailPrint "Register BilldDesk URI Handler" 3 | DeleteRegKey HKCR "BilldDesk" 4 | WriteRegStr HKCR "BilldDesk" "" "URL:BilldDesk" 5 | WriteRegStr HKCR "BilldDesk" "URL Protocol" "" 6 | WriteRegStr HKCR "BilldDesk\shell" "" "" 7 | WriteRegStr HKCR "BilldDesk\shell\Open" "" "" 8 | WriteRegStr HKCR "BilldDesk\shell\Open\command" "" "$INSTDIR\${APP_EXECUTABLE_FILENAME} %1" 9 | !macroend 10 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 39 | 40 | 41 | 42 | 47 | -------------------------------------------------------------------------------- /src/api/deskUser.ts: -------------------------------------------------------------------------------- 1 | import { IDeskUser } from '@/interface'; 2 | import request from '@/utils/request'; 3 | 4 | export function fetchFindReceiverByUuid(uuid) { 5 | return request.get(`/desk_user/find_receiver_by_uuid`, { params: { uuid } }); 6 | } 7 | 8 | export function fetchDeskUserLogin(data: IDeskUser) { 9 | return request.post(`/desk_user/login`, data); 10 | } 11 | 12 | export function fetchDeskUserLinkVerify(data: IDeskUser) { 13 | return request.post(`/desk_user/link_verify`, data); 14 | } 15 | 16 | export function fetchDeskUserCreate() { 17 | return request.post(`/desk_user/create`); 18 | } 19 | 20 | export function fetchDeskUserUpdateByUuid(data: IDeskUser) { 21 | return request.put(`/desk_user/update_by_uuid`, data); 22 | } 23 | -------------------------------------------------------------------------------- /src/api/deskVersion.ts: -------------------------------------------------------------------------------- 1 | import { IDeskVersion, IList } from '@/interface'; 2 | import request from '@/utils/request'; 3 | 4 | export function fetchDeskVersionLatest(params) { 5 | return request.get(`/desk_version/latest`, { params }); 6 | } 7 | 8 | export function fetchDeskVersionCheck({ version, type }) { 9 | return request.get(`/desk_version/check`, { params: { version, type } }); 10 | } 11 | 12 | export function fetchDeskVersionByVersion({ version, type }) { 13 | return request.get(`/desk_version/find_by_version`, { 14 | params: { version, type }, 15 | }); 16 | } 17 | export function fetchDeskVersionAllVersion(params: IList) { 18 | return request.get(`/desk_version/find_all_version`, { 19 | params, 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /src/api/globalMsg.ts: -------------------------------------------------------------------------------- 1 | import { IGlobalMsg, IList, IPaging } from '@/interface'; 2 | import request from '@/utils/request'; 3 | 4 | export function fetchGlobalMsgMyList(params: IList) { 5 | return request.get>('/global_msg/my_list', { 6 | params, 7 | }); 8 | } 9 | 10 | export function fetchGlobalMsgGlobal(params: IList) { 11 | return request.get('/global_msg/global', { 12 | params, 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /src/api/inivte.ts: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | 3 | export function fetchInviteCreate(data) { 4 | return request.post('/invite/create', data); 5 | } 6 | 7 | export function fetchInviteDel(data) { 8 | return request.post('/invite/del', data); 9 | } 10 | 11 | export function fetchInviteGet(params) { 12 | return request.get('/invite/get', { params }); 13 | } 14 | -------------------------------------------------------------------------------- /src/api/screenWall.ts: -------------------------------------------------------------------------------- 1 | import { IScreenWall } from '@/interface'; 2 | import request from '@/utils/request'; 3 | 4 | export function fetchScreenWallSetImg(data) { 5 | return request.post('/screen_wall/set_img', data); 6 | } 7 | 8 | export function fetchScreenWallGetImg(params) { 9 | return request.get('/screen_wall/get_img', { params }); 10 | } 11 | 12 | export function fetchScreenWallGetAllImg(params) { 13 | return request.get('/screen_wall/get_all_img', { params }); 14 | } 15 | 16 | export function fetchScreenWallGetImgBySuperAdmin(params) { 17 | return request.get('/screen_wall/get_img_by_superadmin', { params }); 18 | } 19 | 20 | export function fetchScreenWallAddGroup(data) { 21 | return request.post('/screen_wall/add_group', data); 22 | } 23 | 24 | export function fetchScreenWallDelData(data) { 25 | return request.post('/screen_wall/del_data', data); 26 | } 27 | 28 | export function fetchScreenWallDelGroup(data) { 29 | return request.post('/screen_wall/del_group', data); 30 | } 31 | 32 | export function fetchScreenWallEditData(data) { 33 | return request.post('/screen_wall/edit_data', data); 34 | } 35 | 36 | export function fetchScreenWallEditGroup(data) { 37 | return request.post('/screen_wall/edit_group', data); 38 | } 39 | 40 | export function fetchScreenWallAddData(data) { 41 | return request.post('/screen_wall/add_data', data); 42 | } 43 | 44 | export function fetchScreenWallGetData(params) { 45 | return request.get('/screen_wall/get_data', { params }); 46 | } 47 | -------------------------------------------------------------------------------- /src/api/ws.ts: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | 3 | export function fetchWsKeepAlive(data) { 4 | return request.post('/ws/keep_alive', data); 5 | } 6 | -------------------------------------------------------------------------------- /src/assets/css/constant.scss: -------------------------------------------------------------------------------- 1 | $theme-color-gold: #ffd700; 2 | $top-system-bar-height: 50px; 3 | 4 | // 自定义滚动条:https://developer.mozilla.org/zh-CN/docs/Web/CSS/::-webkit-scrollbar 5 | %customScrollbar { 6 | // 整个滚动条 7 | &::-webkit-scrollbar { 8 | width: 8px; 9 | height: 0px; 10 | border-radius: 0px; 11 | background: rgba(0, 0, 0, 0); 12 | } 13 | 14 | // 滚动条轨道 15 | &::-webkit-scrollbar-track { 16 | border-radius: 0px; 17 | background: rgba(0, 0, 0, 0); 18 | box-shadow: rgba(0, 0, 0, 0); 19 | } 20 | 21 | // 滚动条上的滚动滑块 22 | &::-webkit-scrollbar-thumb { 23 | border-radius: 3px; 24 | background: #e0e0e0; 25 | } 26 | } 27 | 28 | // 自定义滚动条:https://developer.mozilla.org/zh-CN/docs/Web/CSS/::-webkit-scrollbar 29 | %hideScrollbar { 30 | // 整个滚动条 31 | &::-webkit-scrollbar { 32 | width: 0px; 33 | height: 0px; 34 | border-radius: 0px; 35 | background: rgba(0, 0, 0, 0); 36 | } 37 | 38 | // 滚动条轨道 39 | &::-webkit-scrollbar-track { 40 | border-radius: 0px; 41 | background: rgba(0, 0, 0, 0); 42 | box-shadow: rgba(0, 0, 0, 0); 43 | } 44 | 45 | // 滚动条上的滚动滑块 46 | &::-webkit-scrollbar-thumb { 47 | border-radius: 3px; 48 | background: transparent; 49 | } 50 | } 51 | 52 | // 自定义滚动条:https://developer.mozilla.org/zh-CN/docs/Web/CSS/::-webkit-scrollbar 53 | %customScrollbarHide { 54 | // 整个滚动条 55 | &::-webkit-scrollbar { 56 | width: 8px; 57 | height: 0px; 58 | border-radius: 0px; 59 | background: rgba(0, 0, 0, 0); 60 | } 61 | 62 | // 滚动条轨道 63 | &::-webkit-scrollbar-track { 64 | border-radius: 0px; 65 | background: rgba(0, 0, 0, 0); 66 | box-shadow: rgba(0, 0, 0, 0); 67 | } 68 | 69 | // 滚动条上的滚动滑块 70 | &::-webkit-scrollbar-thumb { 71 | border-radius: 3px; 72 | background: transparent; 73 | } 74 | } 75 | 76 | // 自定义横向滚动条:https://developer.mozilla.org/zh-CN/docs/Web/CSS/::-webkit-scrollbar 77 | %customHengScrollbar { 78 | /* 滚动条的宽度 */ 79 | &::-webkit-scrollbar { 80 | width: 8px; 81 | height: 4px; 82 | } 83 | 84 | /* 滚动条的滑块 */ 85 | &::-webkit-scrollbar-thumb { 86 | background-color: #888; 87 | border-radius: 3px; 88 | } 89 | } 90 | 91 | // 自定义横向滚动条:https://developer.mozilla.org/zh-CN/docs/Web/CSS/::-webkit-scrollbar 92 | %customHengScrollbarHide { 93 | /* 滚动条的宽度 */ 94 | &::-webkit-scrollbar { 95 | width: 8px; 96 | height: 4px; 97 | } 98 | 99 | /* 滚动条的滑块 */ 100 | &::-webkit-scrollbar-thumb { 101 | background-color: transparent; 102 | border-radius: 3px; 103 | } 104 | } 105 | 106 | // 自定义滚动条:https://developer.mozilla.org/zh-CN/docs/Web/CSS/::-webkit-scrollbar 107 | %customMiniScrollbar { 108 | // 整个滚动条 109 | &::-webkit-scrollbar { 110 | width: 4px; 111 | height: 0px; 112 | border-radius: 0px; 113 | background: rgba(0, 0, 0, 0); 114 | } 115 | 116 | // 滚动条轨道 117 | &::-webkit-scrollbar-track { 118 | border-radius: 0px; 119 | background: rgba(0, 0, 0, 0); 120 | box-shadow: rgba(0, 0, 0, 0); 121 | } 122 | 123 | // 滚动条上的滚动滑块 124 | &::-webkit-scrollbar-thumb { 125 | border-radius: 3px; 126 | background: #e0e0e0; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/assets/css/main.scss: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0; 3 | margin: 0; 4 | } 5 | -------------------------------------------------------------------------------- /src/assets/img/arrow_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/arrow_down.png -------------------------------------------------------------------------------- /src/assets/img/billd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/billd.jpg -------------------------------------------------------------------------------- /src/assets/img/button-back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/button-back.png -------------------------------------------------------------------------------- /src/assets/img/button-home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/button-home.png -------------------------------------------------------------------------------- /src/assets/img/button-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/button-menu.png -------------------------------------------------------------------------------- /src/assets/img/check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/check.png -------------------------------------------------------------------------------- /src/assets/img/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/clipboard.png -------------------------------------------------------------------------------- /src/assets/img/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/copy.png -------------------------------------------------------------------------------- /src/assets/img/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/edit.png -------------------------------------------------------------------------------- /src/assets/img/link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/link.png -------------------------------------------------------------------------------- /src/assets/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/logo.png -------------------------------------------------------------------------------- /src/assets/img/message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/message.png -------------------------------------------------------------------------------- /src/assets/img/my-wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/my-wechat.png -------------------------------------------------------------------------------- /src/assets/img/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/refresh.png -------------------------------------------------------------------------------- /src/assets/img/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/screenshot.png -------------------------------------------------------------------------------- /src/assets/img/sync.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/sync.png -------------------------------------------------------------------------------- /src/assets/img/view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/view.png -------------------------------------------------------------------------------- /src/assets/img/view_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/view_off.png -------------------------------------------------------------------------------- /src/assets/img/volume-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/volume-down.png -------------------------------------------------------------------------------- /src/assets/img/volume-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/volume-up.png -------------------------------------------------------------------------------- /src/assets/img/volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/img/volume.png -------------------------------------------------------------------------------- /src/assets/readme_img/111.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/readme_img/111.png -------------------------------------------------------------------------------- /src/assets/readme_img/222.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/readme_img/222.png -------------------------------------------------------------------------------- /src/assets/readme_img/333.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/readme_img/333.png -------------------------------------------------------------------------------- /src/assets/readme_img/444.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/readme_img/444.png -------------------------------------------------------------------------------- /src/assets/readme_img/555.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/readme_img/555.png -------------------------------------------------------------------------------- /src/assets/readme_img/666.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/readme_img/666.png -------------------------------------------------------------------------------- /src/assets/readme_img/wechat_group.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxy-s10/billd-desk/0b3548fea2147f1b855909f63419f77239a18b1c/src/assets/readme_img/wechat_group.jpg -------------------------------------------------------------------------------- /src/components/DisableModal/index.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 50 | 51 | 116 | -------------------------------------------------------------------------------- /src/components/Dropdown/index.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 52 | 53 | 96 | -------------------------------------------------------------------------------- /src/components/GlobalMsgModal/index.vue: -------------------------------------------------------------------------------- 1 | 40 | 41 | 56 | 57 | 140 | -------------------------------------------------------------------------------- /src/components/Modal/index.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 57 | 58 | 108 | -------------------------------------------------------------------------------- /src/components/NaiveMessage/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 11 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/components/NaiveModal/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 11 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/components/NaiveNotification/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 11 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/components/UpdateModal/index.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 103 | 104 | 176 | -------------------------------------------------------------------------------- /src/components/icons/VPIconChevronDown.vue: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /src/components/icons/VPIconExternalLink.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 11 | -------------------------------------------------------------------------------- /src/constant.ts: -------------------------------------------------------------------------------- 1 | import { Key } from '@nut-tree-fork/shared'; 2 | 3 | import type { BilldHtmlWebpackPluginLog } from '@/interface'; 4 | 5 | export const PROJECT_GITHUB = `https://github.com/galaxy-s10/billd-desk`; 6 | export const WEB_DESK_URL = `https://desk.hsslive.cn`; 7 | 8 | export const AUTHOR_INFO = { 9 | github: 'https://github.com/galaxy-s10', 10 | wechat: 'shuisheng9905', 11 | qq: '2274751790', 12 | }; 13 | 14 | export const COMMON_URL = { 15 | privatizationDeployment: 'https://desk.hsslive.cn/#/privatizationDeployment', 16 | price: 'https://desk.hsslive.cn/#/price', 17 | hi: 'https://desk.hsslive.cn/#/hi', 18 | payCoursesArticle: `https://www.hsslive.cn/article/151`, 19 | }; 20 | 21 | // @ts-ignore 22 | export const APP_BUILD_INFO = process.env 23 | .BilldHtmlWebpackPlugin as BilldHtmlWebpackPluginLog; 24 | 25 | export const NODE_ENV = process.env.NODE_ENV; 26 | 27 | export const THEME_COLOR = '#ffd700'; 28 | 29 | export const PRODUCT_NAME = 'BilldDesk'; 30 | 31 | export const NUT_KEY_MAP = { 32 | Escape: Key.Escape, // esc 33 | Fn: Key.Fn, 34 | F1: Key.F1, 35 | F2: Key.F2, 36 | F3: Key.F3, 37 | F4: Key.F4, 38 | F5: Key.F5, 39 | F6: Key.F6, 40 | F7: Key.F7, 41 | F8: Key.F8, 42 | F9: Key.F9, 43 | F10: Key.F10, 44 | F11: Key.F11, 45 | F12: Key.F12, 46 | F13: Key.F13, 47 | F14: Key.F14, 48 | F15: Key.F15, 49 | F16: Key.F16, 50 | F17: Key.F17, 51 | F18: Key.F18, 52 | F19: Key.F19, 53 | F20: Key.F20, 54 | F21: Key.F21, 55 | F22: Key.F22, 56 | F23: Key.F23, 57 | F24: Key.F24, 58 | 59 | Backquote: Key.Grave, // 波浪号 60 | Digit1: Key.Num1, 61 | Digit2: Key.Num2, 62 | Digit3: Key.Num3, 63 | Digit4: Key.Num4, 64 | Digit5: Key.Num5, 65 | Digit6: Key.Num6, 66 | Digit7: Key.Num7, 67 | Digit8: Key.Num8, 68 | Digit9: Key.Num9, 69 | Digit0: Key.Num0, 70 | Minus: Key.Minus, // 减号 71 | Equal: Key.Equal, // 等号 72 | Backspace: Key.Backspace, // 删除 73 | 74 | Tab: Key.Tab, 75 | KeyQ: Key.Q, 76 | KeyW: Key.W, 77 | KeyE: Key.E, 78 | KeyR: Key.R, 79 | KeyT: Key.T, 80 | KeyY: Key.Y, 81 | KeyU: Key.U, 82 | KeyI: Key.I, 83 | KeyO: Key.O, 84 | KeyP: Key.P, 85 | BracketLeft: Key.LeftBracket, // 左方括号 86 | BracketRight: Key.RightBracket, // 右方括号 87 | Backslash: Key.Backslash, // 反斜杠 88 | Delete: Key.Delete, // del 89 | 90 | CapsLock: Key.CapsLock, // 大小写切换 91 | KeyA: Key.A, 92 | KeyS: Key.S, 93 | KeyD: Key.D, 94 | KeyF: Key.F, 95 | KeyG: Key.G, 96 | KeyH: Key.H, 97 | KeyJ: Key.J, 98 | KeyK: Key.K, 99 | KeyL: Key.L, 100 | Semicolon: Key.Semicolon, // 分号 101 | Quote: Key.Quote, // 引号 102 | Enter: Key.Enter, // 回车enter 103 | 104 | ShiftLeft: Key.LeftShift, // 左边的shift 105 | KeyZ: Key.Z, 106 | KeyX: Key.X, 107 | KeyC: Key.C, 108 | KeyV: Key.V, 109 | KeyB: Key.B, 110 | KeyN: Key.N, 111 | KeyM: Key.M, 112 | Comma: Key.Comma, // 逗号 113 | Period: Key.Period, // 句号 114 | Slash: Key.Slash, // 斜杠 115 | ShiftRight: Key.RightShift, // 右边边的shift 116 | 117 | fn: 'fn', 118 | ControlLeft: Key.LeftControl, 119 | Alt: Key.LeftAlt, 120 | MetaLeft: Key.LeftCmd, 121 | Space: Key.Space, 122 | MetaRight: Key.RightCmd, 123 | AltRight: Key.RightAlt, 124 | ControlRight: Key.RightControl, 125 | 126 | ArrowUp: Key.Up, 127 | ArrowDown: Key.Down, 128 | ArrowLeft: Key.Left, 129 | ArrowRight: Key.Right, 130 | 131 | // 右侧小键盘 132 | Home: Key.Home, 133 | End: Key.End, 134 | Insert: Key.Insert, 135 | Print: Key.Print, 136 | PageUp: Key.PageUp, 137 | PageDown: Key.PageDown, 138 | Pause: Key.Pause, 139 | ScrollLock: Key.ScrollLock, 140 | 141 | // 数字小键盘 142 | Numpad1: Key.Num1, 143 | Numpad2: Key.Num2, 144 | Numpad3: Key.Num3, 145 | Numpad4: Key.Num4, 146 | Numpad5: Key.Num5, 147 | Numpad6: Key.Num6, 148 | Numpad7: Key.Num7, 149 | Numpad8: Key.Num8, 150 | Numpad9: Key.Num9, 151 | Numpad0: Key.Num0, 152 | 153 | // 没用到 154 | // RightCmd: Key.RightCmd, 155 | }; 156 | 157 | // 全局的cookie的key 158 | export const COOKIE_KEY = {}; 159 | 160 | export const LS_KEY_PREFIX = 'billd_desk___'; 161 | 162 | // 全局的localStorage的key 163 | export const LS_KEY = { 164 | lastBuildDate: 'lastBuildDate', 165 | uuid: 'uuid', 166 | password: 'password', 167 | token: 'token', 168 | axiosBaseUrl: 'axiosBaseUrl', 169 | wssUrl: 'wssUrl', 170 | turnUrl: 'turnUrl', 171 | }; 172 | -------------------------------------------------------------------------------- /src/interface.ts: -------------------------------------------------------------------------------- 1 | export interface BilldHtmlWebpackPluginLog { 2 | pkgName: string; 3 | pkgVersion: string; 4 | pkgRepository: string; 5 | commitSubject: string; 6 | commitBranch: string; 7 | committerDate: string; 8 | commitHash: string; 9 | committerName: string; 10 | committerEmail: string; 11 | lastBuildDate: string; 12 | } 13 | 14 | export interface IDeskVersion { 15 | id?: number; 16 | type?: string; 17 | /** 1:强制更新; 2:不强制更新 */ 18 | force?: number; 19 | /** 版本 */ 20 | version?: string; 21 | /** 显示版本 */ 22 | show_version?: string; 23 | /** 更新内容 */ 24 | update_content?: string; 25 | /** 更新日期 */ 26 | update_date?: string; 27 | /** 是否禁用,1:禁用; 2:不禁用 */ 28 | disable?: number; 29 | /** 禁用消息 */ 30 | disable_msg?: number; 31 | /** macos 32位ARM */ 32 | download_macos_arm_dmg?: string; 33 | /** macos 64位ARM */ 34 | download_macos_arm64_dmg?: string; 35 | /** macos 64位X86,X86是x86_64 或 amd64的别名 */ 36 | download_macos_x64_dmg?: string; 37 | /** windows 32位ARM */ 38 | download_windows_arm_exe?: string; 39 | /** windows 64位ARM */ 40 | download_windows_arm64_exe?: string; 41 | /** windows 64位X86,X86是x86_64 或 amd64的别名 */ 42 | download_windows_x64_exe?: string; 43 | /** linux 32位ARM */ 44 | download_linux_arm_appimage?: string; 45 | /** linux 64位ARM */ 46 | download_linux_arm64_appimage?: string; 47 | /** linux 64位X86,X86是x86_64 或 amd64的别名 */ 48 | download_linux_x64_appimage?: string; 49 | /** linux deb 32位ARM */ 50 | download_linux_arm_deb?: string; 51 | /** linux deb 64位ARM */ 52 | download_linux_arm64_deb?: string; 53 | /** linux deb 64位X86,X86是x86_64 或 amd64的别名 */ 54 | download_linux_x64_deb?: string; 55 | download_android_apk?: string; 56 | download_ios_ipa?: string; 57 | download_ios_deb?: string; 58 | download_ios_pxl?: string; 59 | remark?: string; 60 | 61 | created_at?: string; 62 | updated_at?: string; 63 | deleted_at?: string; 64 | } 65 | 66 | export enum MediaTypeEnum { 67 | camera, 68 | screen, 69 | microphone, 70 | txt, 71 | img, 72 | media, 73 | time, 74 | stopwatch, 75 | webAudio, 76 | pk, 77 | metting, 78 | } 79 | 80 | export enum ClientEnvEnum { 81 | android = 'android', 82 | ios = 'ios', 83 | ipad = 'ipad', 84 | web = 'web', 85 | web_mobile = 'web_mobile', 86 | web_pc = 'web_pc', 87 | windows = 'windows', 88 | macos = 'macos', 89 | linux = 'linux', 90 | } 91 | 92 | export enum ClientAppEnum { 93 | billd_live = 'billd_live', 94 | billd_live_admin = 'billd_live_admin', 95 | billd_desk = 'billd_desk', 96 | billd_desk_admin = 'billd_desk_admin', 97 | } 98 | 99 | export interface IDeskUser { 100 | id?: number; 101 | uuid?: string; 102 | password?: string; 103 | new_password?: string; 104 | /** status: 1正常;2非法 */ 105 | status?: number; 106 | created_at?: string; 107 | updated_at?: string; 108 | deleted_at?: string; 109 | } 110 | 111 | export interface IScreenWall { 112 | id?: number; 113 | uuid?: string; 114 | group_name?: string; 115 | c_uuid?: string; 116 | c_password?: string; 117 | 118 | created_at?: string; 119 | updated_at?: string; 120 | deleted_at?: string; 121 | } 122 | 123 | export enum DeskConfigTypeEnum { 124 | electronVersionConfig = 'electronVersionConfig', 125 | flutterVersionConfig = 'flutterVersionConfig', 126 | } 127 | 128 | export type IListBase = { 129 | nowPage?: number | string; 130 | pageSize?: number | string; 131 | orderBy?: string; 132 | orderName?: string; 133 | keyWord?: string; 134 | childNowPage?: number | string; 135 | childPageSize?: number | string; 136 | childOrderBy?: string; 137 | childOrderName?: string; 138 | childKeyWord?: string; 139 | rangTimeType?: 'created_at' | 'updated_at' | 'deleted_at'; 140 | rangTimeStart?: number | string; 141 | rangTimeEnd?: number | string; 142 | }; 143 | 144 | export type IList = IListBase & T; 145 | 146 | export interface IPaging { 147 | nowPage: number; 148 | pageSize: number; 149 | hasMore: boolean; 150 | total: number; 151 | rows: T[]; 152 | } 153 | 154 | export enum GlobalMsgTypeEnum { 155 | user = 'user', 156 | system = 'system', 157 | activity = 'activity', 158 | notification = 'notification', 159 | } 160 | 161 | export enum SwitchEnum { 162 | yes, 163 | no, 164 | } 165 | 166 | export interface IGlobalMsg { 167 | id?: number; 168 | user_id?: number; 169 | client_ip?: string; 170 | type?: GlobalMsgTypeEnum; 171 | show?: SwitchEnum; 172 | show_date?: string; 173 | priority?: number; 174 | title?: string; 175 | content?: string; 176 | remark?: string; 177 | 178 | created_at?: string; 179 | updated_at?: string; 180 | deleted_at?: string; 181 | } 182 | -------------------------------------------------------------------------------- /src/layout/index.vue: -------------------------------------------------------------------------------- 1 | 156 | 157 | 613 | 614 | 801 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import '@/assets/css/main.scss'; 2 | import { createApp } from 'vue'; 3 | 4 | import router from '@/router/index'; 5 | import store from '@/store/index'; 6 | 7 | import App from './App.vue'; 8 | 9 | const app = createApp(App); 10 | 11 | app.use(store); 12 | app.use(router); 13 | 14 | app.mount('#app'); 15 | -------------------------------------------------------------------------------- /src/pure-constant.ts: -------------------------------------------------------------------------------- 1 | export const WINDOW_ID_MAP = { 2 | remote: 1, 3 | webrtc: 2, 4 | about: 3, 5 | layout: 4, 6 | }; 7 | 8 | export const ENGLISH_LETTER = [ 9 | 'a', 10 | 'b', 11 | 'c', 12 | 'd', 13 | 'e', 14 | 'f', 15 | 'g', 16 | 'h', 17 | 'i', 18 | 'j', 19 | 'k', 20 | 'l', 21 | 'm', 22 | 'n', 23 | 'o', 24 | 'p', 25 | 'q', 26 | 'r', 27 | 's', 28 | 't', 29 | 'u', 30 | 'v', 31 | 'w', 32 | 'x', 33 | 'y', 34 | 'z', 35 | ]; 36 | 37 | export const IPC_EVENT = { 38 | powerSaveBlockerStart: 'powerSaveBlockerStart', 39 | closeAllWindow: 'closeAllWindow', 40 | closeWindow: 'closeWindow', 41 | windowMinimize: 'windowMinimize', 42 | windowMaximize: 'windowMaximize', 43 | handleOpenDevTools: 'handleOpenDevTools', 44 | handleMoveScreenRightBottom: 'handleMoveScreenRightBottom', 45 | mouseScrollDown: 'mouseScrollDown', 46 | mouseScrollUp: 'mouseScrollUp', 47 | mouseScrollLeft: 'mouseScrollLeft', 48 | mouseScrollRight: 'mouseScrollRight', 49 | mouseSetPosition: 'mouseSetPosition', 50 | mouseMove: 'mouseMove', 51 | mouseDrag: 'mouseDrag', 52 | keyboardType: 'keyboardType', 53 | keyboardReleaseKey: 'keyboardReleaseKey', 54 | keyboardPressKey: 'keyboardPressKey', 55 | mousePressButtonLeft: 'mousePressButtonLeft', 56 | mouseReleaseButtonLeft: 'mouseReleaseButtonLeft', 57 | mouseDoubleClick: 'mouseDoubleClick', 58 | mouseLeftClick: 'mouseLeftClick', 59 | mouseRightClick: 'mouseRightClick', 60 | getMousePosition: 'getMousePosition', 61 | setWindowBounds: 'setWindowBounds', 62 | getWindowTitlebarHeight: 'getWindowTitlebarHeight', 63 | setWindowPosition: 'setWindowPosition', 64 | getWindowPosition: 'getWindowPosition', 65 | getScreenStream: 'getScreenStream', 66 | getThumbnail: 'getThumbnail', 67 | getWindowStream: 'getWindowStream', 68 | setAlwaysOnTop: 'setAlwaysOnTop', 69 | createWindow: 'createWindow', 70 | powerMonitorSuspend: 'powerMonitorSuspend', 71 | powerMonitorResume: 'powerMonitorResume', 72 | shellOpenExternal: 'shellOpenExternal', 73 | globalShortcut: 'globalShortcut', 74 | getArch: 'getArch', 75 | writeFile: 'writeFile', 76 | powerBoot: 'powerBoot', 77 | powerBootStatus: 'powerBootStatus', 78 | windowManager: 'windowManager', 79 | getAllWindowName: 'getAllWindowName', 80 | 81 | response_powerSaveBlockerStart: 'response_powerSaveBlockerStart', 82 | response_closeAllWindow: 'response_closeAllWindow', 83 | response_closeWindow: 'response_closeWindow', 84 | response_closeWindowed: 'response_closeWindowed', 85 | response_windowMinimize: 'response_windowMinimize', 86 | response_windowMaximize: 'response_windowMaximize', 87 | response_handleOpenDevTools: 'response_handleOpenDevTools', 88 | response_handleMoveScreenRightBottom: 'response_handleMoveScreenRightBottom', 89 | response_mouseScrollDown: 'response_mouseScrollDown', 90 | response_mouseScrollUp: 'response_mouseScrollUp', 91 | response_mouseScrollLeft: 'response_mouseScrollLeft', 92 | response_mouseScrollRight: 'response_mouseScrollRight', 93 | response_mouseSetPosition: 'response_mouseSetPosition', 94 | response_mouseMove: 'response_mouseMove', 95 | response_mouseDrag: 'response_mouseDrag', 96 | response_keyboardType: 'response_keyboardType', 97 | response_keyboardReleaseKey: 'response_keyboardReleaseKey', 98 | response_keyboardPressKey: 'response_keyboardPressKey', 99 | response_mousePressButtonLeft: 'response_mousePressButtonLeft', 100 | response_mouseReleaseButtonLeft: 'response_mouseReleaseButtonLeft', 101 | response_mouseDoubleClick: 'response_mouseDoubleClick', 102 | response_mouseLeftClick: 'response_mouseLeftClick', 103 | response_mouseRightClick: 'response_mouseRightClick', 104 | response_getMousePosition: 'response_getMousePosition', 105 | response_setWindowBounds: 'response_setWindowBounds', 106 | response_setWindowPosition: 'response_setWindowPosition', 107 | response_getWindowPosition: 'response_getWindowPosition', 108 | response_getScreenStream: 'response_getScreenStream', 109 | response_setAlwaysOnTop: 'response_setAlwaysOnTop', 110 | response_createWindow: 'response_createWindow', 111 | response_powerMonitorSuspend: 'response_powerMonitorSuspend', 112 | response_powerMonitorResume: 'response_powerMonitorResume', 113 | response_globalShortcut: 'response_globalShortcut', 114 | response_open_about: 'response_open_about', 115 | response_open_version: 'response_open_version', 116 | response_open_url: 'response_open_url', 117 | response_getAllWindowName: 'response_getAllWindowName', 118 | }; 119 | 120 | export const GLOBAL_SHORTCUT = { 121 | // 'CommandOrControl+A': 'CommandOrControl+A', 122 | // 'CommandOrControl+C': 'CommandOrControl+C', 123 | // 'CommandOrControl+V': 'CommandOrControl+V', 124 | // 'CommandOrControl+S': 'CommandOrControl+S', 125 | }; 126 | -------------------------------------------------------------------------------- /src/pure-interface.ts: -------------------------------------------------------------------------------- 1 | export interface IIpcRendererData { 2 | windowId: number; 3 | channel: any; 4 | requestId: string; 5 | data: any; 6 | code?: number; 7 | msg?: string; 8 | } 9 | -------------------------------------------------------------------------------- /src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { isIPad, isMobile } from 'billd-utils'; 2 | import { createRouter, createWebHashHistory } from 'vue-router'; 3 | 4 | import Layout from '@/layout/index.vue'; 5 | 6 | import type { RouteRecordRaw } from 'vue-router'; 7 | 8 | export const commonRouterName = { 9 | qrcodeLogin: 'qrcodeLogin', 10 | notFound: 'notFound', 11 | }; 12 | 13 | export const mobileRouterName = { 14 | h5PrivatizationDeployment: 'h5PrivatizationDeployment', 15 | h5Price: 'h5Price', 16 | }; 17 | 18 | export const routerName = { 19 | remote: 'remote', 20 | home: 'home', 21 | about: 'about', 22 | version: 'version', 23 | webrtc: 'webrtc', 24 | deviceManage: 'deviceManage', 25 | screenWall: 'screenWall', 26 | screenWallAdmin: 'screenWallAdmin', 27 | setting: 'setting', 28 | hi: 'hi', 29 | privatizationDeployment: 'privatizationDeployment', 30 | price: 'price', 31 | invite: 'invite', 32 | download: 'download', 33 | release: 'release', 34 | 35 | pull: 'pull', 36 | push: 'push', 37 | ...mobileRouterName, 38 | ...commonRouterName, 39 | }; 40 | 41 | // 默认路由 42 | export const defaultRoutes: RouteRecordRaw[] = [ 43 | { 44 | name: routerName.home, 45 | path: '/', 46 | component: Layout, 47 | redirect: routerName.remote, 48 | children: [ 49 | { 50 | name: routerName.remote, 51 | path: '/remote', 52 | component: () => import('@/views/remote/index.vue'), 53 | }, 54 | { 55 | name: routerName.deviceManage, 56 | path: '/deviceManage', 57 | component: () => import('@/views/deviceManage/index.vue'), 58 | }, 59 | { 60 | name: routerName.screenWall, 61 | path: '/screenWall', 62 | component: () => import('@/views/screenWall/index.vue'), 63 | }, 64 | { 65 | name: routerName.screenWallAdmin, 66 | path: '/screenWallAdmin', 67 | component: () => import('@/views/screenWallAdmin/index.vue'), 68 | }, 69 | { 70 | name: routerName.setting, 71 | path: '/setting', 72 | component: () => import('@/views/setting/index.vue'), 73 | }, 74 | { 75 | name: routerName.download, 76 | path: '/download', 77 | component: () => import('@/views/download/index.vue'), 78 | }, 79 | { 80 | name: routerName.release, 81 | path: '/release', 82 | component: () => import('@/views/release/index.vue'), 83 | }, 84 | { 85 | name: routerName.hi, 86 | path: '/hi', 87 | component: () => import('@/views/hi/index.vue'), 88 | }, 89 | ], 90 | }, 91 | { 92 | name: routerName.privatizationDeployment, 93 | path: '/privatizationDeployment', 94 | component: () => import('@/views/privatizationDeployment/index.vue'), 95 | }, 96 | { 97 | name: routerName.price, 98 | path: '/price', 99 | component: () => import('@/views/price/index.vue'), 100 | }, 101 | { 102 | name: routerName.webrtc, 103 | path: '/webrtc', 104 | component: () => import('@/views/webrtc/index.vue'), 105 | }, 106 | { 107 | name: routerName.about, 108 | path: '/about', 109 | component: () => import('@/views/about/index.vue'), 110 | }, 111 | { 112 | name: routerName.invite, 113 | path: '/invite', 114 | component: () => import('@/views/invite/index.vue'), 115 | }, 116 | { 117 | name: mobileRouterName.h5PrivatizationDeployment, 118 | path: '/h5/privatizationDeployment', 119 | component: () => import('@/views/h5/privatizationDeployment/index.vue'), 120 | }, 121 | { 122 | name: mobileRouterName.h5Price, 123 | path: '/h5/price', 124 | component: () => import('@/views/h5/price/index.vue'), 125 | }, 126 | ]; 127 | 128 | const router = createRouter({ 129 | routes: [ 130 | ...defaultRoutes, 131 | { 132 | path: '/:pathMatch(.*)*', 133 | name: routerName.notFound, 134 | component: () => import('@/views/notFound.vue'), 135 | }, 136 | ], 137 | history: createWebHashHistory(), 138 | }); 139 | 140 | router.beforeEach((to, _from, next) => { 141 | if (Object.keys(commonRouterName).includes(to.name as string)) { 142 | // 跳转通用路由 143 | return next(); 144 | } else if (isMobile() && !isIPad()) { 145 | console.log('当前是移动端', to.name); 146 | if (!Object.keys(mobileRouterName).includes(to.name as string)) { 147 | console.log('当前移动端,但是跳转了非移动端路由'); 148 | if (to.name === routerName.privatizationDeployment) { 149 | return next({ 150 | name: routerName.h5PrivatizationDeployment, 151 | }); 152 | } else if (to.name === routerName.price) { 153 | return next({ 154 | name: routerName.h5Price, 155 | }); 156 | } else { 157 | return next(); 158 | } 159 | } else { 160 | return next(); 161 | } 162 | } else { 163 | if (Object.keys(mobileRouterName).includes(to.name as string)) { 164 | console.log('当前非移动端,但是跳转了移动端路由', to.name); 165 | if (to.name === routerName.h5PrivatizationDeployment) { 166 | return next({ 167 | name: routerName.privatizationDeployment, 168 | }); 169 | } else if (to.name === routerName.h5Price) { 170 | return next({ 171 | name: routerName.price, 172 | }); 173 | } else { 174 | return next(); 175 | } 176 | } 177 | return next(); 178 | } 179 | }); 180 | 181 | export default router; 182 | -------------------------------------------------------------------------------- /src/spec-config.ts: -------------------------------------------------------------------------------- 1 | export const PROD_DOMAIN = 'hsslive.cn'; 2 | 3 | // 这个BACKEND_SERVER_PORT和vite.config.ts需要一致,改的话要一起改。 4 | const BACKEND_SERVER_PORT = 5300; // 后端服务的端口号 5 | 6 | // ======本地调试===== 7 | 8 | // const BACKEND_SERVER_IP = '10.10.20.29'; // 后端服务的IP(本机局域网地址) 9 | 10 | // export const WEBSOCKET_URL = 11 | // process.env.NODE_ENV === 'development' 12 | // ? `ws://${BACKEND_SERVER_IP}:${BACKEND_SERVER_PORT}` 13 | // : `ws://${BACKEND_SERVER_IP}:${BACKEND_SERVER_PORT}`; 14 | 15 | // export const AXIOS_BASEURL = 16 | // process.env.NODE_ENV === 'development' 17 | // ? `http://${BACKEND_SERVER_IP}:${BACKEND_SERVER_PORT}` 18 | // : `http://${BACKEND_SERVER_IP}:${BACKEND_SERVER_PORT}`; 19 | 20 | // ======本地调试===== 21 | 22 | // ======线上正式===== 23 | 24 | export const WEBSOCKET_URL = 25 | process.env.NODE_ENV === 'development' 26 | ? `ws://localhost:${BACKEND_SERVER_PORT}` 27 | : `wss://desk-api.${PROD_DOMAIN}`; 28 | 29 | export const AXIOS_BASEURL = 30 | process.env.NODE_ENV === 'development' 31 | ? `/api` 32 | : `https://desk-api.${PROD_DOMAIN}`; 33 | 34 | // ======线上正式===== 35 | 36 | // 本地测试时,TURN_URL可以随便填,其实用不到;但线上的时候,需要填对! 37 | export const TURN_URL = `turn:hk.${PROD_DOMAIN}`; 38 | 39 | export const COOKIE_DOMAIN = 40 | process.env.NODE_ENV === 'development' ? undefined : `.${PROD_DOMAIN}`; 41 | -------------------------------------------------------------------------------- /test/test copy.js: -------------------------------------------------------------------------------- 1 | // const url = new URLSearchParams('BilldDesk://remote?a=ahdFSXuR&b=2332'); 2 | // console.log(url.get('a')); 3 | 4 | // url.forEach((v, k) => { 5 | // console.log(v, k); 6 | // }); 7 | 8 | const a = 'BilldDesk://remote?a=ahdFSXuR&b=2332'; 9 | const str = a.split('?')[1]; 10 | console.log(str); 11 | 12 | const url = new URLSearchParams(str); 13 | console.log(url.get('a')); 14 | console.log(url.get('b')); 15 | -------------------------------------------------------------------------------- /test/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | Document 10 | 11 | 12 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 后端返回版本信息,前端判断更新逻辑 3 | * 可以这样设计:前端本地存有一个版本号,localVersion 4 | * 1.前端先判断checkUpdate,checkUpdate等于1才提示更新,否则直接不提示更新 5 | * 2.判断forceUpdateList,如果localVersion在forceUpdateList里面,就强制更新到最新版本 6 | * 3.判断newVersion, 7 | * 3.1如果localVersion小于newVersion,则判断localVersion是否小于minVersion,如果localVersion小于minVersion,则代表有版本更新,且是强制更新。 8 | * 3.2如果localVersion不小于newVersion,则代表当前是最新版本,不用更新 9 | * 4.判断noiceVersion,localVersion小于这个版本的就提示更新 10 | */ 11 | const versionInfo = { 12 | // 是否检查更新,1就代表检查更新 13 | checkUpdate: 1, 14 | // 最低版本 15 | minVersion: '0.0.100', 16 | // 最新版本 17 | newVersion: '0.0.100', 18 | // 显示的版本 19 | showNewVersion: 'v0.0.100', 20 | // 强更版本列表 21 | forceUpdateList: ['0.0.100', '0.0.101'], 22 | // 更新内容 23 | updateContent: '更新内容更新内容', 24 | // 更新日期 25 | updateDate: '2024年10月22日11:08:51', 26 | // 下载地址 27 | download: { 28 | macos_dmg: '', 29 | window_64_exe: '', 30 | window_32_exe: '', 31 | window_arm_exe: '', 32 | linux_64_deb: '', 33 | linux_64_tar: '', 34 | linux_arm_deb: '', 35 | linux_arm_tar: '', 36 | }, 37 | // 禁用版本 38 | disableList: [ 39 | { 40 | version: '0.0.100', 41 | msg: '当前版本过久,请前往官网更新最新版本', 42 | }, 43 | ], 44 | // 备注 45 | remark: '', 46 | }; 47 | 48 | /** 49 | * 后端返回版本信息 50 | * 前端判断status,status=1的话,则判断isUpdate、forceUpdate,download,下载对应的包 51 | * 前端判断status,status=2的话,则代表这个版本禁用,提示statusDesc 52 | */ 53 | const front = { 54 | // 是否提示更新,1:提示; 2:不提示 55 | isUpdate: 1, 56 | // 是否强制更新,1:强制; 2:不强制 57 | forceUpdate: 2, 58 | // 更新内容 59 | updateContent: '更新内容更新内容', 60 | // 更新日期 61 | updateDate: '2024年10月22日11:08:51', 62 | // 下载地址 63 | download: { 64 | macos_dmg: '', 65 | window_64_exe: '', 66 | window_32_exe: '', 67 | window_arm_exe: '', 68 | linux_64_deb: '', 69 | linux_64_tar: '', 70 | linux_arm_deb: '', 71 | linux_arm_tar: '', 72 | }, 73 | // 禁用版本 74 | disableList: [ 75 | { 76 | version: '0.0.100', 77 | msg: '当前版本过久,请前往官网更新最新版本', 78 | }, 79 | ], 80 | // 备注 81 | remark: '', 82 | }; 83 | -------------------------------------------------------------------------------- /test/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "forceVersion": "0.0.100", 3 | "noiceVersion": "0.0.100", 4 | "currentVersion": "0.0.100", 5 | "mustForceVersion": [ 6 | "0.0.100", 7 | "0.0.101" 8 | ], 9 | "versionList": [ 10 | { 11 | "version": "0.0.100", 12 | "showVersion": "v0.0.100", 13 | "download": "https://res.ldmnq.com/xdyun/download/XD-YunInst_v1.0.2.2.exe", 14 | "updateContent": "更新内容:
1、优化部分系统崩溃问题;
2、优化同步操作,批量操作交互体验;", 15 | "updateDate": "2024年10月22日11:08:51" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /test/test.ts: -------------------------------------------------------------------------------- 1 | function handleUrlQuery(obj: Record) { 2 | let res = ''; 3 | Object.keys(obj).forEach((item) => { 4 | res += `${item}=${obj[item]}&`; 5 | }); 6 | if (res.length > 0) { 7 | return res.slice(0, -1); 8 | } else { 9 | return res; 10 | } 11 | } 12 | 13 | console.log(handleUrlQuery({ a: '1', b: '32' })); 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "skipLibCheck": true, 8 | "noImplicitAny": false, 9 | 10 | /* Bundler mode */ 11 | "moduleResolution": "bundler", 12 | "allowImportingTsExtensions": true, 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "noEmit": true, 16 | "jsx": "preserve", 17 | 18 | "baseUrl": "./", 19 | "paths": { 20 | "@/*": ["src/*"] 21 | }, 22 | 23 | /* Linting */ 24 | "strict": true, 25 | "noUnusedLocals": true, 26 | "noUnusedParameters": true, 27 | "noFallthroughCasesInSwitch": true 28 | }, 29 | 30 | "include": [ 31 | "electron-main/**/*.ts", 32 | "src/**/*.ts", 33 | "src/**/*.d.ts", 34 | "src/**/*.tsx", 35 | "src/**/*.vue", 36 | "config/**/*.ts", 37 | "components.d.ts" 38 | ], // 仅仅匹配这些文件,除了src以外的文件都不会被匹配 39 | "references": [{ "path": "./tsconfig.node.json" }] 40 | } 41 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | 3 | import vue from '@vitejs/plugin-vue'; 4 | import { BilldHtmlWebpackPlugin, logData } from 'billd-html-webpack-plugin'; 5 | import autoImport from 'unplugin-auto-import/vite'; 6 | import { NaiveUiResolver as naiveUiResolver } from 'unplugin-vue-components/resolvers'; 7 | import unpluginVueComponents from 'unplugin-vue-components/vite'; 8 | import { defineConfig } from 'vite'; 9 | import prefetchPlugin from 'vite-plugin-bundle-prefetch'; 10 | import checker from 'vite-plugin-checker'; 11 | import { chunkSplitPlugin } from 'vite-plugin-chunk-split'; 12 | import electron from 'vite-plugin-electron/simple'; 13 | import eslint from 'vite-plugin-eslint2'; 14 | import { createHtmlPlugin } from 'vite-plugin-html'; 15 | 16 | import pkg from './package.json'; 17 | 18 | const BACKEND_SERVER_PORT = 5300; // 后端服务的端口号 19 | const isWeb = process.env['VITE_APP_RELEASE_PROJECT_ISWEB'] === 'true'; 20 | 21 | // https://vitejs.dev/config/ 22 | export default defineConfig(({ mode }) => { 23 | const isProduction = mode === 'production'; 24 | 25 | const outputStaticUrl = () => { 26 | if (isWeb) { 27 | if (isProduction) { 28 | return 'https://tencentcos-res.hsslive.cn/billd-desk/client/dist/'; 29 | } else { 30 | return './'; 31 | } 32 | } else { 33 | if (isProduction) { 34 | return './'; 35 | } else { 36 | return './'; 37 | } 38 | } 39 | }; 40 | 41 | return { 42 | base: outputStaticUrl(), 43 | css: { 44 | preprocessorOptions: { 45 | scss: { 46 | additionalData: `@use 'billd-scss/src/index.scss' as *;@import "@/assets/css/constant.scss";`, 47 | }, 48 | }, 49 | }, 50 | resolve: { 51 | alias: { '@': path.resolve(__dirname, 'src') }, 52 | /** 53 | * 不建议省略.vue后缀 54 | * https://cn.vitejs.dev/config/shared-options.html#resolve-extensions 55 | */ 56 | // extensions: ['.js', '.ts', '.jsx', '.tsx', '.vue'], 57 | }, 58 | build: { 59 | outDir: 'dist', 60 | }, 61 | plugins: [ 62 | // legacy(), 63 | // isProduction && legacy(), 64 | chunkSplitPlugin({ 65 | // 指定拆包策略 66 | // customSplitting: { 67 | // // `vue` and `vue-router` 会被打包到一个名为`vue-vendor`的 chunk 里面(包括它们的一些依赖,如 object-assign) 68 | // 'vue-vendor': [/vue/], 69 | // 'vue-router-vendor': [/vue-router/], 70 | // 'av-cliper-vendor': [/@webav\/av-cliper/], 71 | // // 源码中 utils 目录的代码都会打包进 `utils` 这个 chunk 中 72 | // // utils: [/src\/utils/], 73 | // views: [/src\/views/], 74 | // compoents: [/src\/compoents/], 75 | // }, 76 | }), 77 | prefetchPlugin(), 78 | vue(), 79 | createHtmlPlugin({ 80 | inject: { 81 | data: { 82 | // @ts-ignore 83 | title: pkg.productName, 84 | }, 85 | }, 86 | }), 87 | isWeb 88 | ? false 89 | : electron({ 90 | main: { 91 | entry: 'electron-main/index.ts', // 主进程文件 92 | vite: { 93 | build: { 94 | outDir: 'electron-dist', 95 | lib: { 96 | entry: 'electron-main/index.ts', // 主进程文件 97 | formats: ['cjs'], 98 | fileName: () => '[name].cjs', 99 | }, 100 | }, 101 | }, 102 | }, 103 | preload: { 104 | input: 'electron-main/preload.ts', 105 | vite: { 106 | build: { 107 | outDir: 'electron-dist', 108 | }, 109 | }, 110 | }, 111 | }), 112 | checker({ 113 | // typescript: true, 114 | vueTsc: true, 115 | // eslint: { 116 | // lintCommand: 'eslint "./src/**/*.{ts,tsx}"', // for example, lint .ts & .tsx 117 | // }, 118 | }), 119 | eslint({}), 120 | autoImport({ 121 | imports: [ 122 | { 123 | 'naive-ui': ['useMessage', 'useNotification'], 124 | }, 125 | ], 126 | }), 127 | unpluginVueComponents({ 128 | resolvers: [naiveUiResolver()], 129 | }), 130 | new BilldHtmlWebpackPlugin({ env: 'vite4' }).config, 131 | ].filter(Boolean), 132 | define: { 133 | 'process.env': { 134 | BilldHtmlWebpackPlugin: logData(null), 135 | NODE_ENV: JSON.stringify(isProduction ? 'production' : 'development'), 136 | PUBLIC_PATH: outputStaticUrl(), 137 | VUE_APP_RELEASE_PROJECT_NAME: JSON.stringify( 138 | process.env.VUE_APP_RELEASE_PROJECT_NAME 139 | ), 140 | VUE_APP_RELEASE_PROJECT_ENV: JSON.stringify( 141 | process.env.VUE_APP_RELEASE_PROJECT_ENV 142 | ), 143 | VUE_APP_RELEASE_PROJECT_VERSION: JSON.stringify(pkg.version), 144 | }, 145 | }, 146 | 147 | server: { 148 | host: '0.0.0.0', 149 | proxy: { 150 | '/api': { 151 | target: `http://localhost:${BACKEND_SERVER_PORT}`, 152 | secure: false, // 默认情况下(secure: true),不接受在HTTPS上运行的带有无效证书的后端服务器。设置secure: false后,后端服务器的HTTPS有无效证书也可运行 153 | /** 154 | * changeOrigin,是否修改请求地址的源 155 | * 默认changeOrigin: false,即发请求即使用devServer的localhost:port发起的,如果后端服务器有校验源,就会有问题 156 | * 设置changeOrigin: true,就会修改发起请求的源,将原本的localhost:port修改为target,这样就可以通过后端服务器对源的校验 157 | */ 158 | changeOrigin: true, 159 | rewrite: (path) => path.replace(/^\/api/, '/'), 160 | }, 161 | '/prodapi': { 162 | target: 'http://localhost:5200', 163 | secure: false, // 默认情况下(secure: true),不接受在HTTPS上运行的带有无效证书的后端服务器。设置secure: false后,后端服务器的HTTPS有无效证书也可运行 164 | /** 165 | * changeOrigin,是否修改请求地址的源 166 | * 默认changeOrigin: false,即发请求即使用devServer的localhost:port发起的,如果后端服务器有校验源,就会有问题 167 | * 设置changeOrigin: true,就会修改发起请求的源,将原本的localhost:port修改为target,这样就可以通过后端服务器对源的校验 168 | */ 169 | changeOrigin: true, 170 | rewrite: (path) => path.replace(/^\/prodapi/, '/'), 171 | }, 172 | }, 173 | }, 174 | }; 175 | }); 176 | --------------------------------------------------------------------------------