├── .gitignore ├── LICENSE ├── README.md ├── auto-imports.d.ts ├── components.d.ts ├── index.html ├── package-lock.json ├── package.json ├── src-tauri ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── build.rs ├── capabilities │ └── default.json ├── icons │ ├── 128x128.png │ ├── 128x128@2x.png │ ├── 32x32.png │ ├── Square107x107Logo.png │ ├── Square142x142Logo.png │ ├── Square150x150Logo.png │ ├── Square284x284Logo.png │ ├── Square30x30Logo.png │ ├── Square310x310Logo.png │ ├── Square44x44Logo.png │ ├── Square71x71Logo.png │ ├── Square89x89Logo.png │ ├── StoreLogo.png │ ├── icon.icns │ ├── icon.ico │ └── icon.png ├── src │ ├── api │ │ ├── launcher_api.rs │ │ ├── mod.rs │ │ ├── setting_api.rs │ │ └── window_api.rs │ ├── constants.rs │ ├── db │ │ ├── launcher.rs │ │ ├── launcher_resource.rs │ │ ├── mod.rs │ │ └── settings.rs │ ├── error.rs │ ├── events.rs │ ├── events │ │ ├── system_listeners.rs │ │ └── types.rs │ ├── lib.rs │ └── main.rs └── tauri.conf.json ├── src ├── App.vue ├── DragDropResource.vue ├── assets │ ├── home_desc.png │ ├── read_mode_desc.png │ ├── settings.png │ └── tray_desc.png ├── home.vue ├── launcher.vue ├── launcherLite.vue ├── main.ts ├── settings.vue └── vite-env.d.ts ├── tsconfig.json ├── tsconfig.node.json ├── vite.config.ts └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | .vscode 26 | .idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 一键启动 2 | 3 | ## 项目简介 4 | 5 | **一键启动** 是专注于提升操作效率的资源管理工具,支持快速批量启动多种类型资源。核心解决多任务场景下的重复操作痛点。 6 | 7 | ### 核心能力 8 | 9 | - **批量启动**:单次操作同时打开多个文件/网址/应用程序 10 | - **场景分类**:自由创建「办公」「开发」「日常」等不同场景启动组 11 | - **灵活管理**: 12 | - 拖放文件/网址快速创建启动项 13 | - 支持窗口布局记忆与主题切换(深色/浅色模式) 14 | - 提供便携版无需安装 15 | 16 | ### 适用场景 17 | 18 | - 日常需要同时打开多个办公文档 19 | - 开发人员需要快速启动编程环境套件 20 | - 设计师需一键加载创意工具集 21 | - 开机自动加载办公文档与通讯软件 22 | - PPT制作时同步启动素材库与设计工具 23 | 24 | **视频介绍:** 25 | [BiliBili视频介绍](https://www.bilibili.com/video/BV1LgN8ejEsS/) 26 | 27 | ## 安装方式 28 | 29 | 提供两种安装版本供用户选择: 30 | 31 | ### 安装版 32 | 33 | **1. 使用`setup.exe`或`.msi`文件安装** 34 | 适合大部分 Windows 用户,提供简洁的安装引导界面: 35 | 36 | 1. 下载 `一键启动_x64-setup.exe`或`一键启动_x64_zh-CN.msi` ( 37 | 如:一键启动_1.0.0_x64-setup.exe,一键启动_1.0.0_x64_zh-CN.msi)。 38 | 2. 双击文件后,按照提示完成安装。 39 | 3. 安装完成后,桌面和“开始菜单”会创建快捷方式,点击即可启动程序。 40 | 41 | ### 便携版 42 | 43 | **使用`portable.exe`文件直接打开** 44 | 45 | 1. **下载便携版**: 46 | - 下载 `一键启动_portable.exe` (如:一键启动_1.0.2_portable.exe)。 47 | 48 | 2. **直接运行**: 49 | - 双击 `一键启动_portable.exe` 文件即可启动程序,无需安装。 50 | - 所有数据(如配置文件、数据库)将存储在可执行文件所在的目录中,方便携带和迁移。 51 | 52 | ## 版本说明 53 | 54 | ### v1.0.2 | 2025-03-02 55 | 56 | **✨ 新增功能** 57 | 58 | - 新增主题功能(浅色模式/深色模式) 59 | - 支持文件拖放快捷添加资源或创建编组 60 | - 新增“自启动编组”功能(开机启动时自动运行指定编组) 61 | - 支持窗口自定义大小 62 | - 新增保存窗口位置与大小功能(重启后自动恢复) 63 | - 支持打开单个资源 64 | - 支持便携版应用程序 65 | - 新增退出选项(退出程序或最小化到系统托盘) 66 | 67 | **🛠 优化与改进** 68 | 69 | - 优化人机交互体验 70 | - 代码结构与性能优化 71 | - 多显示器分辨率适配 72 | 73 | **⚙️ 技术更新** 74 | 75 | - 升级 Rust 依赖至 2024 版本 76 | 77 | **历史版本** 78 | 79 | - v1.0.1 | 2025-01-23 80 | 81 | **🎯 功能改进** 82 | - 优化系统图标与系统托盘的展示。 83 | 84 | - v1.0.0 | 2025-01-19 85 | 86 | **🎉 基础功能** 87 | - 启动器编组管理核心功能上线 88 | - 实现一键打开多文件/文件夹/网址 89 | - 支持开机自启基础功能 90 | 91 | ## 使用方式 92 | 93 | ### 1. 初次启动 94 | 95 | 安装完成后,运行“一键启动”程序,默认会进入编辑模式,用户可以开始创建启动器: 96 | 97 | 1. 点击 `创建启动器` 按钮,会生成一个带有随机名称的空启动器,双击名称为启动器重命名(如“工作”、“娱乐”)。 98 | 2. 在启动器中添加资源: 99 | - 点击 `添加` 或 `添加文件夹` ,选择需要打开的资源(可以是任意文档,应用程序等)。 100 | - 点击 `添加网址` ,输入网址名称和链接。 101 | 3. 添加完成后,点击 `启动` 按钮即可打开启动器中的所有资源。启动成功后主窗口将自动隐藏。 102 | 103 | ![主界面操作](src/assets/home_desc.png) 104 | 105 | ### 2. 切换阅读模式 106 | 107 | 取消勾选 `编辑模式` ,启动器界面将变为`阅读模式`,此时不能编辑启动器内容,仅用于启动资源和调整资源顺序。 108 | 109 | ![阅读模式操作](src/assets/read_mode_desc.png) 110 | 111 | ### 3. 系统托盘操作 112 | 113 | “一键启动”关闭后默认最小化到系统托盘,并提供右键菜单: 114 | 115 | - **快速启动:** 直接点击某个启动器名称即可启动其资源。 116 | - **退出程序:** 关闭“一键启动”。 117 | 118 | ![系统托盘操作](src/assets/tray_desc.png) 119 | 120 | ### 4. 设置页面 121 | 122 | ![设置页面](src/assets/settings.png) 123 | 124 | ## 手动运行源码 125 | 126 | 如果希望自定义或基于源码运行程序,可以按照以下步骤操作: 127 | 128 | ### 1. 环境要求 129 | 130 | 在开始之前,请确保你已经安装以下必要的环境: 131 | 132 | - **Rust 环境:** 安装 [Rust编译器](https://www.rust-lang.org/) (推荐使用最新的稳定版本)。 133 | - 安装后,运行以下命令确保 Rust 和 cargo 可用: 134 | 135 | ```bash 136 | rustc --version 137 | cargo --version 138 | ``` 139 | 140 | - **Node.js环境:** [安装Node.js](https://nodejs.org/) (推荐使用 18.x 或以上版本)。 141 | - 安装后,运行以下命令检查 Node.js 和 npm 是否可用: 142 | 143 | ```bash 144 | node -v 145 | npm -v 146 | ``` 147 | 148 | - **Tauri CLI:** 安装 [Tauri CLI](https://tauri.app/),用于管理 Tauri 的开发和构建: 149 | 150 | ```bash 151 | cargo install create-tauri-app --locked 152 | ``` 153 | 154 | - SQLite: 确保系统上支持 SQLite 数据库,因为项目使用 `sqlx` 和 `SQLite` 作为数据存储后端。 155 | 156 | ### 2. 克隆项目 157 | 158 | 使用 Git 克隆项目代码到本地: 159 | 160 | ```bash 161 | git clone https://gitee.com/silwings/one-click-launch.git 162 | cd one-click-launch 163 | ``` 164 | 165 | ### 3. 安装前端依赖 166 | 167 | 进入项目目录后,通过 `npm` 安装前端依赖: 168 | 169 | ```bash 170 | npm install 171 | ``` 172 | 173 | 如果使用的是 `yarn` 或 `pnpm`,可以替换为: 174 | 175 | ```bash 176 | yarn install 177 | # 或 178 | pnpm install 179 | ``` 180 | 181 | ### 4. 开发环境运行 182 | 183 | 运行 Tauri 开发模式 184 | 185 | ```bash 186 | cargo tauri dev 187 | ``` 188 | 189 | 若页面无法右键检查,可先将`index.html`文件中的`阻止默认右键菜单`代码块注释。 190 | 191 | 由于设置了单例模式,无法启动多个应用程序实例,若启动应用程序失败,请检查是否已存在正在运行的当前应用程序。 192 | 193 | ### 5. 构建生产版本 194 | 195 | 运行 Tauri 生产模式 196 | 197 | ```bash 198 | # 构建安装版 199 | cargo tauri build 200 | 201 | # 构建便携版 202 | cargo tauri build --features portable 203 | ``` 204 | 205 | 构建完成后,生成的可执行文件将在 `/src-tauri/target/release/` 目录中,你可以将其分发给用户。 206 | 207 | ### 6. 修改和自定义代码 208 | 209 | **修改前端代码** 210 | 前端使用 Vue 3 和 TypeScript 开发,源代码位于 src/ 目录。 211 | 212 | - 例如:你可以在 src/components 中修改 UI 组件或逻辑。 213 | 214 | **修改后端代码** 215 | 后端使用 Rust 开发,源代码位于 `src-tauri/` 目录。 216 | 217 | - 插件配置可以在 `src-tauri/tauri.conf.json` 中调整。 218 | - 业务逻辑可以在 `src-tauri/src/` 中编写或修改。 219 | 220 | 修改后可以使用以下命令进行开发测试或重新构建: 221 | 222 | ```bash 223 | cargo tauri dev # 开发模式 224 | cargo tauri build # 生产模式 225 | ``` 226 | 227 | ## 联系我们 228 | 229 | 如有任何问题或反馈,请通过以下方式联系我: 230 | 231 | - 邮箱: 232 | -------------------------------------------------------------------------------- /auto-imports.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* prettier-ignore */ 3 | // @ts-nocheck 4 | // noinspection JSUnusedGlobalSymbols 5 | // Generated by unplugin-auto-import 6 | // biome-ignore lint: disable 7 | export {} 8 | declare global { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /components.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // @ts-nocheck 3 | // Generated by unplugin-vue-components 4 | // Read more: https://github.com/vuejs/core/pull/3399 5 | // biome-ignore lint: disable 6 | export {} 7 | 8 | /* prettier-ignore */ 9 | declare module 'vue' { 10 | export interface GlobalComponents { 11 | ElInput: typeof import('element-plus/es')['ElInput'] 12 | ElOption: typeof import('element-plus/es')['ElOption'] 13 | ElPopconfirm: typeof import('element-plus/es')['ElPopconfirm'] 14 | ElRadio: typeof import('element-plus/es')['ElRadio'] 15 | ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] 16 | ElSelect: typeof import('element-plus/es')['ElSelect'] 17 | ElTooltip: typeof import('element-plus/es')['ElTooltip'] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 一键启动 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 38 | 39 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "one-click-launch", 3 | "private": true, 4 | "version": "1.0.3", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview", 10 | "tauri": "tauri" 11 | }, 12 | "dependencies": { 13 | "@fortawesome/fontawesome-free": "^6.7.2", 14 | "@icon-park/vue-next": "^1.4.2", 15 | "@tauri-apps/api": "^2.2.0", 16 | "@tauri-apps/plugin-autostart": "^2.2.0", 17 | "@tauri-apps/plugin-dialog": "^2.2.0", 18 | "@tauri-apps/plugin-os": "^2.2.0", 19 | "@tauri-apps/plugin-shell": "^2", 20 | "element-plus": "^2.9.5", 21 | "pinia": "^3.0.1", 22 | "vue": "^3.3.4", 23 | "vue-toastification": "^2.0.0-rc.5" 24 | }, 25 | "devDependencies": { 26 | "@tauri-apps/cli": "^2", 27 | "@vitejs/plugin-vue": "^5.0.5", 28 | "babel-plugin-component": "^1.1.1", 29 | "typescript": "^5.2.2", 30 | "unplugin-auto-import": "^19.1.1", 31 | "unplugin-vue-components": "^28.4.1", 32 | "vite": "^5.3.1", 33 | "vue-tsc": "^2.1.10" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src-tauri/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Generated by Tauri 6 | # will have schema files for capabilities auto-completion 7 | /gen/schemas 8 | -------------------------------------------------------------------------------- /src-tauri/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "one-click-launch" 3 | version = "1.0.3" 4 | description = "One Click Launch" 5 | authors = ["Silwings"] 6 | edition = "2024" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [lib] 11 | # The `_lib` suffix may seem redundant but it is necessary 12 | # to make the lib name unique and wouldn't conflict with the bin name. 13 | # This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519 14 | name = "one_click_start_lib" 15 | crate-type = ["staticlib", "cdylib", "rlib"] 16 | 17 | [build-dependencies] 18 | tauri-build = { version = "2", features = [] } 19 | 20 | [dependencies] 21 | tauri = { version = "2", features = [ "tray-icon"] } 22 | tauri-plugin-opener = "2.2.4" 23 | tauri-plugin-shell = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } 24 | tauri-plugin-dialog = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } 25 | tauri-plugin-persisted-scope = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } 26 | tauri-plugin-autostart = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } 27 | tauri-plugin-os = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } 28 | tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } 29 | tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } 30 | serde = { version = "1", features = ["derive"] } 31 | serde_json = "1" 32 | thiserror = "2.0.3" 33 | anyhow = "1.0.93" 34 | tracing = "0.1" # 日志处理 35 | tracing-subscriber = "0.3" # 日志处理 36 | windows = "0.58.0" 37 | sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite"] } 38 | tokio = { version = "1.43.0", features = ["full"] } 39 | rand = "0.8.5" 40 | lazy_static = "1.5.0" 41 | itertools = "0.14.0" 42 | 43 | [features] 44 | portable = [] 45 | -------------------------------------------------------------------------------- /src-tauri/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | tauri_build::build() 3 | } 4 | -------------------------------------------------------------------------------- /src-tauri/capabilities/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../gen/schemas/desktop-schema.json", 3 | "identifier": "default", 4 | "description": "Capability for the main window", 5 | "windows": ["main"], 6 | "permissions": [ 7 | "core:default", 8 | "shell:allow-open", 9 | "dialog:allow-open", 10 | "dialog:allow-message", 11 | "dialog:allow-confirm", 12 | "core:window:allow-is-resizable", 13 | "autostart:allow-enable", 14 | "autostart:allow-disable", 15 | "autostart:allow-is-enabled" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /src-tauri/icons/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src-tauri/icons/128x128.png -------------------------------------------------------------------------------- /src-tauri/icons/128x128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src-tauri/icons/128x128@2x.png -------------------------------------------------------------------------------- /src-tauri/icons/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src-tauri/icons/32x32.png -------------------------------------------------------------------------------- /src-tauri/icons/Square107x107Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src-tauri/icons/Square107x107Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square142x142Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src-tauri/icons/Square142x142Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square150x150Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src-tauri/icons/Square150x150Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square284x284Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src-tauri/icons/Square284x284Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square30x30Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src-tauri/icons/Square30x30Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square310x310Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src-tauri/icons/Square310x310Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square44x44Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src-tauri/icons/Square44x44Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square71x71Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src-tauri/icons/Square71x71Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square89x89Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src-tauri/icons/Square89x89Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src-tauri/icons/StoreLogo.png -------------------------------------------------------------------------------- /src-tauri/icons/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src-tauri/icons/icon.icns -------------------------------------------------------------------------------- /src-tauri/icons/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src-tauri/icons/icon.ico -------------------------------------------------------------------------------- /src-tauri/icons/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src-tauri/icons/icon.png -------------------------------------------------------------------------------- /src-tauri/src/api/launcher_api.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use rand::{Rng, distributions::Alphanumeric}; 3 | use serde::Deserialize; 4 | use tauri::{AppHandle, State}; 5 | use tauri_plugin_opener::OpenerExt; 6 | use tracing::info; 7 | 8 | use crate::{ 9 | DatabaseManager, 10 | db::{ 11 | launcher, 12 | launcher_resource::{self, CreateResourceParam, LauncherResource}, 13 | }, 14 | error::OneClickLaunchError, 15 | events::{ 16 | EventDispatcher, 17 | types::{ 18 | LauncherBasicInfoUpdated, LauncherBasicInfoUpdatedPayload, LauncherLaunched, 19 | LauncherLaunchedPayload, 20 | }, 21 | }, 22 | }; 23 | 24 | /// 创建新的启动器 25 | #[tauri::command] 26 | pub async fn craete_launcher( 27 | app: AppHandle, 28 | db: State<'_, DatabaseManager>, 29 | name: Option, 30 | ) -> Result { 31 | let name = name 32 | .filter(|s| !s.is_empty()) 33 | .unwrap_or_else(generate_default_launcher_name); 34 | let launcher_id = launcher::create(&db.pool, &name, None).await?; 35 | 36 | let _ = EventDispatcher::::send_event( 37 | &app, 38 | LauncherBasicInfoUpdatedPayload { 39 | launcher_ids: vec![launcher_id], 40 | }, 41 | ); 42 | 43 | Ok(launcher_id) 44 | } 45 | 46 | fn generate_default_launcher_name() -> String { 47 | let mut name = "双击编辑".to_string(); 48 | let rad_str = generate_random_string(4); 49 | name.push_str(&rad_str); 50 | name 51 | } 52 | 53 | fn generate_random_string(length: usize) -> String { 54 | rand::thread_rng() 55 | .sample_iter(&Alphanumeric) 56 | .take(length) 57 | .map(char::from) 58 | .collect() 59 | } 60 | 61 | /// 修改启动器名称 62 | #[tauri::command] 63 | pub async fn modify_launcher_name( 64 | app: AppHandle, 65 | db: State<'_, DatabaseManager>, 66 | launcher_id: i64, 67 | name: String, 68 | ) -> Result<(), OneClickLaunchError> { 69 | launcher::modify_launcher_name(&db.pool, launcher_id, &name).await?; 70 | 71 | let _ = EventDispatcher::::send_event( 72 | &app, 73 | LauncherBasicInfoUpdatedPayload { 74 | launcher_ids: vec![launcher_id], 75 | }, 76 | ); 77 | 78 | Ok(()) 79 | } 80 | 81 | /// 复制启动器,包含启动器关联的资源数据 82 | #[tauri::command] 83 | pub async fn copy_launcher( 84 | app: AppHandle, 85 | db: State<'_, DatabaseManager>, 86 | launcher_id: i64, 87 | ) -> Result { 88 | let mut tx = db.pool.begin().await?; 89 | 90 | // 1. 复制启动器 91 | let launcher = launcher::find_by_id(&mut tx, launcher_id).await?; 92 | 93 | let launcher_resoures = launcher_resource::query_by_launcher_id(&mut tx, launcher_id).await?; 94 | 95 | let new_name = format!("{}-副本", launcher.name); 96 | 97 | // 2. 复制资源 98 | let new_launcher_id = launcher::create(&mut tx, &new_name, Some(launcher.sort)).await?; 99 | 100 | for res in launcher_resoures.iter() { 101 | launcher_resource::create(&mut tx, new_launcher_id, &res.name, &res.path).await?; 102 | } 103 | 104 | tx.commit().await?; 105 | 106 | let _ = EventDispatcher::::send_event( 107 | &app, 108 | LauncherBasicInfoUpdatedPayload { 109 | launcher_ids: vec![launcher_id], 110 | }, 111 | ); 112 | 113 | Ok(new_launcher_id) 114 | } 115 | 116 | /// 查询启动器列表 117 | #[tauri::command] 118 | pub async fn query_launchers( 119 | db: State<'_, DatabaseManager>, 120 | ) -> Result, OneClickLaunchError> { 121 | let launchers = launcher::query(&db.pool).await?; 122 | 123 | let resources = launcher_resource::query_all(&db.pool).await?; 124 | 125 | let launcher_vos = launchers 126 | .into_iter() 127 | .map(|launcher| { 128 | let res_vos = resources 129 | .iter() 130 | .filter(|resource| resource.launcher_id == launcher.id) 131 | .map(|resource| LauncherResourceVo { 132 | id: resource.id, 133 | launcher_id: resource.launcher_id, 134 | name: resource.name.clone(), 135 | path: resource.path.clone(), 136 | }) 137 | .collect(); 138 | LauncherVo { 139 | id: launcher.id, 140 | name: launcher.name, 141 | resources: res_vos, 142 | } 143 | }) 144 | .collect(); 145 | 146 | Ok(launcher_vos) 147 | } 148 | 149 | #[derive(Debug, serde::Deserialize, serde::Serialize)] 150 | pub struct LauncherVo { 151 | pub id: i64, 152 | pub name: String, 153 | pub resources: Vec, 154 | } 155 | 156 | #[derive(Debug, serde::Deserialize, serde::Serialize)] 157 | pub struct LauncherResourceVo { 158 | pub id: i64, 159 | pub launcher_id: i64, 160 | pub name: String, 161 | pub path: String, 162 | } 163 | 164 | /// 删除启动器 165 | #[tauri::command] 166 | pub async fn delete_launcher( 167 | app: AppHandle, 168 | db: State<'_, DatabaseManager>, 169 | launcher_id: i64, 170 | ) -> Result<(), OneClickLaunchError> { 171 | let mut tx = db.pool.begin().await?; 172 | 173 | launcher::delete_by_id(&mut tx, launcher_id).await?; 174 | 175 | launcher_resource::delete_by_launcher(&mut tx, launcher_id).await?; 176 | 177 | tx.commit().await?; 178 | 179 | let _ = EventDispatcher::::send_event( 180 | &app, 181 | LauncherBasicInfoUpdatedPayload { 182 | launcher_ids: vec![launcher_id], 183 | }, 184 | ); 185 | 186 | Ok(()) 187 | } 188 | 189 | #[derive(serde::Deserialize, serde::Serialize)] 190 | pub struct LauncherSort { 191 | id: i64, 192 | sort: i32, 193 | } 194 | 195 | /// 调整启动器顺序 196 | #[tauri::command] 197 | pub async fn modify_launcher_sort( 198 | app: AppHandle, 199 | db: State<'_, DatabaseManager>, 200 | launchers: Vec, 201 | ) -> Result<(), OneClickLaunchError> { 202 | let mut tx = db.pool.begin().await?; 203 | 204 | for ls in launchers.iter() { 205 | launcher::modify_launcher_sort(&mut tx, ls.id, ls.sort).await? 206 | } 207 | 208 | tx.commit().await?; 209 | 210 | let _ = EventDispatcher::::send_event( 211 | &app, 212 | LauncherBasicInfoUpdatedPayload { 213 | launcher_ids: launchers.iter().map(|e| e.id).collect(), 214 | }, 215 | ); 216 | 217 | Ok(()) 218 | } 219 | 220 | /// 为启动器添加资源 221 | #[tauri::command] 222 | pub async fn add_resource( 223 | db: State<'_, DatabaseManager>, 224 | launcher_id: i64, 225 | name: Option, 226 | path: &str, 227 | ) -> Result { 228 | let name = name.unwrap_or_else(|| generate_name(path)); 229 | 230 | let resource_id = launcher_resource::create(&db.pool, launcher_id, &name, path).await?; 231 | 232 | Ok(resource_id) 233 | } 234 | 235 | /// 为启动器添加资源 236 | #[tauri::command] 237 | pub async fn add_resources( 238 | db: State<'_, DatabaseManager>, 239 | launcher_id: i64, 240 | resources: Vec, 241 | ) -> Result<(), OneClickLaunchError> { 242 | let crps = resources 243 | .into_iter() 244 | .map(|r| CreateResourceParam { 245 | name: r 246 | .name 247 | .filter(|s| !s.is_empty()) 248 | .unwrap_or_else(|| generate_name(r.path.as_str())), 249 | path: r.path, 250 | }) 251 | .collect::>(); 252 | 253 | launcher_resource::create_resources(&db.pool, launcher_id, &crps).await?; 254 | 255 | Ok(()) 256 | } 257 | 258 | #[derive(Deserialize, Debug)] 259 | pub struct ResourceParam { 260 | pub name: Option, 261 | pub path: String, 262 | } 263 | 264 | fn generate_name(path: &str) -> String { 265 | if path.starts_with("http") { 266 | return path.to_string(); 267 | } 268 | 269 | match path.rfind('\\') { 270 | Some(index) => path[index + 1..].to_string(), 271 | None => path.to_string(), 272 | } 273 | } 274 | 275 | /// 修改资源名称 276 | #[tauri::command] 277 | pub async fn modify_resource_name( 278 | db: State<'_, DatabaseManager>, 279 | resource_id: i64, 280 | name: &str, 281 | ) -> Result<(), OneClickLaunchError> { 282 | launcher_resource::modify_name(&db.pool, resource_id, name).await?; 283 | Ok(()) 284 | } 285 | 286 | /// 删除启动器中的资源 287 | #[tauri::command] 288 | pub async fn delete_resource( 289 | db: State<'_, DatabaseManager>, 290 | resource_id: i64, 291 | ) -> Result<(), OneClickLaunchError> { 292 | launcher_resource::delete_by_id(&db.pool, resource_id).await?; 293 | Ok(()) 294 | } 295 | 296 | /// 启动启动器 297 | #[tauri::command] 298 | pub async fn launch( 299 | app: AppHandle, 300 | db: State<'_, DatabaseManager>, 301 | launcher_id: i64, 302 | ) -> Result<(), OneClickLaunchError> { 303 | let resources = launcher_resource::query_by_launcher_id(&db.pool, launcher_id).await?; 304 | 305 | launch_resources(&app, &resources); 306 | 307 | EventDispatcher::::send_event( 308 | &app, 309 | LauncherLaunchedPayload { 310 | launcher_ids: vec![launcher_id], 311 | }, 312 | )?; 313 | 314 | Ok(()) 315 | } 316 | 317 | /// 打开路径 318 | #[tauri::command] 319 | pub async fn open_path(app: AppHandle, path: &str) -> Result<(), OneClickLaunchError> { 320 | open_using_default_program(&app, path)?; 321 | Ok(()) 322 | } 323 | 324 | pub fn launch_resources(app: &AppHandle, resources: &[LauncherResource]) { 325 | for resource in resources.iter() { 326 | if let Err(e) = open_using_default_program(app, resource.path.as_str()) { 327 | info!( 328 | "启动资源失败,资源名称: {:?},资源路径: {:?},错误信息: {:?}", 329 | &resource.name, &resource.path, e 330 | ); 331 | } 332 | } 333 | } 334 | 335 | /// 使用系统默认的程序打开指定的文件或 URL。 336 | /// 337 | /// # 参数 338 | /// - `app`: 应用程序状态的引用,用于访问 Tauri 的应用句柄。 339 | /// - `path`: 表示文件路径或 URL 的字符串切片。 340 | /// 341 | /// # 返回值 342 | /// - `Ok(())` 表示操作成功。 343 | /// - `Err(OneClickLaunchError)` 表示操作失败。 344 | pub fn open_using_default_program(app: &AppHandle, path: &str) -> Result<(), OneClickLaunchError> { 345 | app.opener() 346 | .open_path(path, None::<&str>) 347 | .map_err(|e| OneClickLaunchError::ExecutionError(e.to_string()))?; 348 | Ok(()) 349 | } 350 | -------------------------------------------------------------------------------- /src-tauri/src/api/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod launcher_api; 2 | pub mod setting_api; 3 | pub mod window_api; 4 | -------------------------------------------------------------------------------- /src-tauri/src/api/setting_api.rs: -------------------------------------------------------------------------------- 1 | use sqlx::{Executor, Sqlite}; 2 | use tauri::{AppHandle, State}; 3 | 4 | use crate::{ 5 | DatabaseManager, 6 | db::settings::{self, Settings}, 7 | error::OneClickLaunchError, 8 | events::{ 9 | EventDispatcher, 10 | types::{SettingUpdated, SettingUpdatedPayload}, 11 | }, 12 | }; 13 | 14 | /// 保存设置 15 | #[tauri::command] 16 | pub async fn save_setting( 17 | app: AppHandle, 18 | db: State<'_, DatabaseManager>, 19 | key: String, 20 | value: String, 21 | ) -> Result<(), OneClickLaunchError> { 22 | let setting = Settings { key, value }; 23 | settings::save(&db.pool, &setting).await?; 24 | 25 | let _ = EventDispatcher::::send_event( 26 | &app, 27 | SettingUpdatedPayload { 28 | key: setting.key.clone(), 29 | value: setting.value.clone(), 30 | }, 31 | ); 32 | 33 | Ok(()) 34 | } 35 | 36 | /// 读取设置 37 | #[tauri::command] 38 | pub async fn read_setting( 39 | db: State<'_, DatabaseManager>, 40 | key: &str, 41 | ) -> Result, OneClickLaunchError> { 42 | let setting = settings::read(&db.pool, key).await?; 43 | Ok(setting) 44 | } 45 | 46 | /// 读取全部设置 47 | #[tauri::command] 48 | pub async fn read_all_setting( 49 | db: State<'_, DatabaseManager>, 50 | ) -> Result, OneClickLaunchError> { 51 | let setting = settings::read_all(&db.pool).await?; 52 | Ok(setting) 53 | } 54 | 55 | pub async fn check_launch_then_exit<'a, E>(executor: E) -> Result 56 | where 57 | E: Executor<'a, Database = Sqlite>, 58 | { 59 | match settings::read(executor, "launch_then_exit").await { 60 | Ok(Some(setting)) => Ok(string_to_bool(&setting.value)), 61 | _ => Ok(false), 62 | } 63 | } 64 | 65 | pub fn string_to_bool(s: &str) -> bool { 66 | matches!(s.trim().to_lowercase().as_str(), "true") 67 | } 68 | -------------------------------------------------------------------------------- /src-tauri/src/api/window_api.rs: -------------------------------------------------------------------------------- 1 | use std::{sync::Mutex, time::Instant}; 2 | 3 | use anyhow::Result; 4 | use tauri::{ 5 | AppHandle, DragDropEvent, Manager, State, Theme, 6 | menu::{MenuBuilder, MenuItem}, 7 | tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent}, 8 | }; 9 | use tracing::{debug, info}; 10 | 11 | use crate::{ 12 | DatabaseManager, WindowContext, 13 | constants::{self, WINDOW_MIN_HEIGHT, WINDOW_MIN_WIDTH}, 14 | db::launcher, 15 | error::OneClickLaunchError, 16 | events::{ 17 | EventDispatcher, 18 | types::{DragDropResource, DragDropResourcePaylod}, 19 | }, 20 | }; 21 | 22 | use super::{launcher_api, setting_api}; 23 | 24 | pub fn hide_window(app: &AppHandle) -> Result<(), OneClickLaunchError> { 25 | let window = app 26 | .get_webview_window(constants::MAIN_WINDOW_LABEL) 27 | .unwrap(); 28 | window.hide()?; 29 | Ok(()) 30 | } 31 | 32 | /// 刷新系统图标菜单 33 | pub async fn refresh_tray(app: AppHandle) -> Result<(), OneClickLaunchError> { 34 | // 获取全局状态 35 | let window_context: State<'_, WindowContext> = app.state(); 36 | let database_manager: State<'_, DatabaseManager> = app.state(); 37 | let launchers = launcher::query(&database_manager.pool).await?; 38 | 39 | let mut menu_builder = MenuBuilder::new(&app); 40 | // 创建动态菜单项 41 | for launcher in &launchers { 42 | let id = format!("launch_{}", launcher.id); 43 | let title = format!("启动: {}", launcher.name); 44 | menu_builder = 45 | menu_builder.item(&MenuItem::with_id(&app, &id, &title, true, None::<&str>)?); 46 | } 47 | 48 | if !launchers.is_empty() { 49 | menu_builder = menu_builder.separator(); 50 | } 51 | 52 | // 添加退出按钮 53 | let quit_item = MenuItem::with_id(&app, "quit", "退出", true, None::<&str>)?; 54 | let menu = menu_builder.item(&quit_item).build()?; 55 | 56 | // 设置菜单到托盘图标 57 | window_context.tray_icon.set_menu(Some(menu))?; 58 | Ok(()) 59 | } 60 | 61 | pub fn change_windows_theme(app: &AppHandle, theme: &str) -> Result<(), OneClickLaunchError> { 62 | if let Some(window) = app.get_webview_window(constants::MAIN_WINDOW_LABEL) { 63 | window.set_theme(match theme { 64 | "dark" => Some(Theme::Dark), 65 | "light" => Some(Theme::Light), 66 | _ => None, 67 | })?; 68 | } 69 | Ok(()) 70 | } 71 | 72 | pub fn handle_window_event(window: &tauri::Window, event: &tauri::WindowEvent) { 73 | match event { 74 | tauri::WindowEvent::CloseRequested { api, .. } => { 75 | api.prevent_close(); 76 | let _ = window.hide(); 77 | 78 | let app_handle = window.app_handle().clone(); 79 | tauri::async_runtime::spawn(async move { 80 | let db = app_handle.state::(); 81 | let setting = setting_api::read_setting(db, constants::CLOSE_MAIN_PANEL_KEY).await; 82 | 83 | match setting { 84 | Ok(Some(setting)) if constants::CLOSE_MAIN_PANEL_EXIT == setting.value => { 85 | app_handle.exit(0); 86 | } 87 | _ => {} 88 | } 89 | }); 90 | } 91 | tauri::WindowEvent::ScaleFactorChanged { 92 | scale_factor, 93 | new_inner_size, 94 | .. 95 | } => { 96 | print!( 97 | "ScaleFactorChanged scale_factor: {}, new_inner_size: {:?}", 98 | scale_factor, new_inner_size 99 | ); 100 | 101 | let now = Instant::now(); 102 | let state = window.state::(); 103 | let mut lock = state.last_reset.try_lock(); 104 | 105 | if let Ok(ref mut last_reset) = lock { 106 | // 500ms防抖间隔 107 | if last_reset.map_or(true, |t| now.duration_since(t).as_millis() > 500) { 108 | if let Ok(physical_size) = window.inner_size() { 109 | // 如果窗口大小异常,强制调整到正常大小 110 | if physical_size.width != WINDOW_MIN_WIDTH 111 | || physical_size.height != WINDOW_MIN_HEIGHT 112 | { 113 | let _ = window.set_size(tauri::Size::Logical(tauri::LogicalSize { 114 | width: WINDOW_MIN_WIDTH as f64, 115 | height: WINDOW_MIN_HEIGHT as f64, 116 | })); 117 | **last_reset = Some(now); 118 | debug!("DPI发生变化,触发窗口大小重置"); 119 | } 120 | } 121 | } else { 122 | debug!("DPI重置窗口防抖生效"); 123 | } 124 | } 125 | } 126 | tauri::WindowEvent::DragDrop(drag_drop_event) => match drag_drop_event { 127 | DragDropEvent::Drop { paths, .. } if !paths.is_empty() => { 128 | let _ = window.set_focus(); 129 | let _ = EventDispatcher::::send_event( 130 | window.app_handle(), 131 | DragDropResourcePaylod { 132 | paths: paths.clone(), 133 | }, 134 | ); 135 | } 136 | _ => {} 137 | }, 138 | _ => {} 139 | } 140 | } 141 | 142 | /// 初始化窗口 143 | pub fn setup_tray(app: &AppHandle) -> Result<()> { 144 | let tray_icon = TrayIconBuilder::new() 145 | // 设置系统托盘的提示,鼠标悬浮时会显示 146 | .tooltip(constants::APPLICATION_NAME) 147 | // 左键系统托盘时不显示菜单 148 | .show_menu_on_left_click(false) 149 | // 使用主窗口的icon作为系统托盘的图标 150 | .icon(app.default_window_icon().unwrap().clone()) 151 | // 系统托盘的点击事件 152 | .on_tray_icon_event(|tray, event| match event { 153 | TrayIconEvent::Click { 154 | button: MouseButton::Left, 155 | button_state: MouseButtonState::Up, 156 | .. 157 | } => { 158 | // 当用户点击系统托盘时使应用程序取消最小化,显示并聚焦 159 | let app = tray.app_handle(); 160 | if let Some(window) = app.get_webview_window(constants::MAIN_WINDOW_LABEL) { 161 | let _ = window.unminimize(); 162 | let _ = window.show(); 163 | let _ = window.set_focus(); 164 | } 165 | } 166 | _ => { 167 | debug!("unhandled event {event:?}"); 168 | } 169 | }) 170 | .on_menu_event(|app, event| match event.id.as_ref() { 171 | "quit" => { 172 | // 退出应用程序 173 | info!("quit menu item was clicked"); 174 | app.exit(0); 175 | } 176 | id if id.starts_with("launch_") => { 177 | // 系统托盘的菜单id由"launch_"与启动器id拼接而成, 点击菜单后通过解析id,找到要启动的启动器触发启动 178 | let id = &id["launch_".len()..]; 179 | if let Ok(launcher_id) = id.parse::() { 180 | let app_cloned = app.clone(); 181 | tauri::async_runtime::spawn(async move { 182 | let inner_app = app_cloned.clone(); 183 | let db = inner_app.state(); 184 | launcher_api::launch(app_cloned, db, launcher_id).await 185 | }); 186 | } 187 | } 188 | _ => { 189 | tracing::error!("menu item {:?} not handled", event.id); 190 | } 191 | }) 192 | .build(app)?; 193 | 194 | let window_context = WindowContext { tray_icon }; 195 | 196 | app.manage(window_context); 197 | 198 | Ok(()) 199 | } 200 | 201 | /// 用于保存上次处理分辨率变更事件的时间 202 | pub struct ScaleFactorChangedState { 203 | pub last_reset: Mutex>, 204 | } 205 | -------------------------------------------------------------------------------- /src-tauri/src/constants.rs: -------------------------------------------------------------------------------- 1 | use lazy_static::lazy_static; 2 | 3 | lazy_static! { 4 | pub static ref AUTO_START_FLAG: String = "--auto".to_string(); 5 | } 6 | 7 | pub static APPLICATION_NAME: &str = "一键启动"; 8 | pub static MAIN_WINDOW_LABEL: &str = "main"; 9 | pub static THEME_KEY: &str = "theme"; 10 | pub static CLOSE_MAIN_PANEL_KEY: &str = "close_main_panel"; 11 | pub static AUTO_START_LAUNCHER_IDS_KEY: &str = "auto_start_launcher_ids"; 12 | pub static HIDE_AFTER_AUTO_START_KEY: &str = "hide_after_auto_start"; 13 | pub static CLOSE_MAIN_PANEL_EXIT: &str = "m2"; 14 | pub static WINDOW_MIN_WIDTH: u32 = 800; 15 | pub static WINDOW_MIN_HEIGHT: u32 = 600; 16 | -------------------------------------------------------------------------------- /src-tauri/src/db/launcher.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use sqlx::{Executor, Sqlite}; 3 | 4 | /// 使用 FromRow 派生宏把从数据库中读取出来的数据转换成 Launcher 结构 5 | #[allow(dead_code)] 6 | #[derive(sqlx::FromRow, Debug)] 7 | pub struct Launcher { 8 | pub id: i64, 9 | pub name: String, 10 | pub sort: i32, 11 | } 12 | 13 | pub async fn initialize<'a, E>(executor: E) -> Result<()> 14 | where 15 | E: Executor<'a, Database = Sqlite>, 16 | { 17 | sqlx::query( 18 | r#"CREATE TABLE IF NOT EXISTS launcher( 19 | id INTEGER PRIMARY KEY NOT NULL, 20 | name VARCHAR NOT NULL, 21 | sort INTEGER NOT NULL DEFAULT 1)"#, 22 | ) 23 | .execute(executor) 24 | .await?; 25 | Ok(()) 26 | } 27 | 28 | /// 存储一个新的启动器 29 | pub async fn create<'a, E>(executor: E, launcher_name: &str, sort: Option) -> Result 30 | where 31 | E: Executor<'a, Database = Sqlite>, 32 | { 33 | let id = sqlx::query("INSERT INTO launcher (name,sort) VALUES (?,?)") 34 | .bind(launcher_name) 35 | .bind(sort.unwrap_or_default()) 36 | .execute(executor) 37 | .await? 38 | .last_insert_rowid(); 39 | Ok(id) 40 | } 41 | 42 | /// 修改启动器名称 43 | pub async fn modify_launcher_name<'a, E>(executor: E, id: i64, name: &str) -> Result<()> 44 | where 45 | E: Executor<'a, Database = Sqlite>, 46 | { 47 | sqlx::query("UPDATE launcher SET name = ? WHERE id = ?") 48 | .bind(name) 49 | .bind(id) 50 | .execute(executor) 51 | .await?; 52 | Ok(()) 53 | } 54 | 55 | /// 修改启动器顺序 56 | pub async fn modify_launcher_sort<'a, E>(executor: E, id: i64, sort: i32) -> Result<()> 57 | where 58 | E: Executor<'a, Database = Sqlite>, 59 | { 60 | sqlx::query("UPDATE launcher SET sort = ? WHERE id = ?") 61 | .bind(sort) 62 | .bind(id) 63 | .execute(executor) 64 | .await?; 65 | Ok(()) 66 | } 67 | 68 | /// 删除启动器 69 | pub async fn delete_by_id<'a, E>(executor: E, id: i64) -> Result<()> 70 | where 71 | E: Executor<'a, Database = Sqlite>, 72 | { 73 | sqlx::query("DELETE FROM launcher WHERE id = ?") 74 | .bind(id) 75 | .execute(executor) 76 | .await?; 77 | Ok(()) 78 | } 79 | 80 | /// 查询启动器列表 81 | pub async fn query<'a, E>(executor: E) -> Result> 82 | where 83 | E: Executor<'a, Database = Sqlite>, 84 | { 85 | let launchers: Vec = 86 | sqlx::query_as("SELECT id,name,sort FROM launcher ORDER BY sort ASC, id DESC") 87 | .fetch_all(executor) 88 | .await?; 89 | Ok(launchers) 90 | } 91 | 92 | /// 查询单个启动器信息 93 | pub async fn find_by_id<'a, E>(executor: E, id: i64) -> Result 94 | where 95 | E: Executor<'a, Database = Sqlite>, 96 | { 97 | let launcher = sqlx::query_as("SELECT id,name,sort FROM launcher WHERE id = ?") 98 | .bind(id) 99 | .fetch_one(executor) 100 | .await?; 101 | 102 | Ok(launcher) 103 | } 104 | -------------------------------------------------------------------------------- /src-tauri/src/db/launcher_resource.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use itertools::Itertools; 3 | use sqlx::{Executor, Sqlite}; 4 | 5 | /// 使用FromRow宏把数据库中读取出来的数据转换成LauncherResource结构 6 | #[allow(dead_code)] 7 | #[derive(sqlx::FromRow, Debug)] 8 | pub struct LauncherResource { 9 | pub id: i64, 10 | pub launcher_id: i64, 11 | pub name: String, 12 | pub path: String, 13 | } 14 | 15 | pub struct CreateResourceParam { 16 | pub name: String, 17 | pub path: String, 18 | } 19 | 20 | pub async fn initialize<'a, E>(executor: E) -> Result<()> 21 | where 22 | E: Executor<'a, Database = Sqlite>, 23 | { 24 | sqlx::query( 25 | r#"CREATE TABLE IF NOT EXISTS launcher_resource( 26 | id INTEGER PRIMARY KEY NOT NULL, 27 | launcher_id INTEGER NOT NULL, 28 | name VARCHAR NOT NULL, 29 | path VARCHAR NOT NULL); 30 | CREATE INDEX IF NOT EXISTS idx_launcherresource_launcherid ON launcher_resource(launcher_id);"#, 31 | ) 32 | .execute(executor) 33 | .await?; 34 | Ok(()) 35 | } 36 | 37 | // 新增 38 | pub async fn create<'a, E>(executor: E, launcher_id: i64, name: &str, path: &str) -> Result 39 | where 40 | E: Executor<'a, Database = Sqlite>, 41 | { 42 | let id = sqlx::query("INSERT INTO launcher_resource (launcher_id,name,path) VALUES (?,?,?)") 43 | .bind(launcher_id) 44 | .bind(name) 45 | .bind(path) 46 | .execute(executor) 47 | .await? 48 | .last_insert_rowid(); 49 | Ok(id) 50 | } 51 | 52 | // 批量新增 53 | pub async fn create_resources<'a, E>( 54 | executor: E, 55 | launcher_id: i64, 56 | resources: &[CreateResourceParam], 57 | ) -> Result<()> 58 | where 59 | E: Executor<'a, Database = Sqlite>, 60 | { 61 | let mut query = String::from("INSERT INTO launcher_resource (launcher_id,name,path) VALUES "); 62 | 63 | let values = resources 64 | .iter() 65 | .map(|r| format!(r#"('{}','{}','{}')"#, launcher_id, r.name, r.path)) 66 | .join(","); 67 | 68 | query.push_str(values.as_str()); 69 | 70 | sqlx::query(&query).execute(executor).await?; 71 | 72 | Ok(()) 73 | } 74 | 75 | // 修改名称 76 | pub async fn modify_name<'a, E>(executor: E, resource_id: i64, name: &str) -> Result<()> 77 | where 78 | E: Executor<'a, Database = Sqlite>, 79 | { 80 | sqlx::query("UPDATE launcher_resource SET name = ? WHERE id = ?") 81 | .bind(name) 82 | .bind(resource_id) 83 | .execute(executor) 84 | .await?; 85 | Ok(()) 86 | } 87 | 88 | // 按launcher_id删除 89 | pub async fn delete_by_launcher<'a, E>(executor: E, launcher_id: i64) -> Result<()> 90 | where 91 | E: Executor<'a, Database = Sqlite>, 92 | { 93 | sqlx::query("DELETE FROM launcher_resource WHERE launcher_id = ?") 94 | .bind(launcher_id) 95 | .execute(executor) 96 | .await?; 97 | Ok(()) 98 | } 99 | 100 | // 按id删除 101 | pub async fn delete_by_id<'a, E>(executor: E, id: i64) -> Result<()> 102 | where 103 | E: Executor<'a, Database = Sqlite>, 104 | { 105 | sqlx::query("DELETE FROM launcher_resource WHERE id = ?") 106 | .bind(id) 107 | .execute(executor) 108 | .await?; 109 | Ok(()) 110 | } 111 | 112 | // 按launcher_id查询 113 | pub async fn query_by_launcher_id<'a, E>( 114 | executor: E, 115 | launcher_id: i64, 116 | ) -> Result> 117 | where 118 | E: Executor<'a, Database = Sqlite>, 119 | { 120 | let resources = sqlx::query_as( 121 | "SELECT id,launcher_id,name,path FROM launcher_resource WHERE launcher_id=?", 122 | ) 123 | .bind(launcher_id) 124 | .fetch_all(executor) 125 | .await?; 126 | Ok(resources) 127 | } 128 | 129 | // 按launcher_id查询 130 | pub async fn query_by_launcher_ids<'a, E>( 131 | executor: E, 132 | launcher_ids: &[i64], 133 | ) -> Result> 134 | where 135 | E: Executor<'a, Database = Sqlite>, 136 | { 137 | if launcher_ids.is_empty() { 138 | return Ok(vec![]); 139 | } 140 | 141 | let ids = launcher_ids 142 | .iter() 143 | .map(|id| id.to_string()) 144 | .collect::>() 145 | .join(","); 146 | let query = format!( 147 | "SELECT id, launcher_id, name, path FROM launcher_resource WHERE launcher_id IN ({})", 148 | ids 149 | ); 150 | 151 | let resources = sqlx::query_as(&query).fetch_all(executor).await?; 152 | 153 | Ok(resources) 154 | } 155 | 156 | // 查询全部 157 | pub async fn query_all<'a, E>(executor: E) -> Result> 158 | where 159 | E: Executor<'a, Database = Sqlite>, 160 | { 161 | let resources = 162 | sqlx::query_as("SELECT id,launcher_id,name,path FROM launcher_resource ORDER BY id DESC") 163 | .fetch_all(executor) 164 | .await?; 165 | Ok(resources) 166 | } 167 | -------------------------------------------------------------------------------- /src-tauri/src/db/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod launcher; 2 | pub mod launcher_resource; 3 | pub mod settings; 4 | -------------------------------------------------------------------------------- /src-tauri/src/db/settings.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use sqlx::Executor; 3 | use sqlx::Sqlite; 4 | 5 | #[derive(Debug, sqlx::FromRow, serde::Serialize, serde::Deserialize)] 6 | pub struct Settings { 7 | pub key: String, 8 | pub value: String, 9 | } 10 | 11 | pub async fn initialize<'a, E>(executor: E) -> Result<()> 12 | where 13 | E: Executor<'a, Database = Sqlite>, 14 | { 15 | sqlx::query( 16 | r#"CREATE TABLE IF NOT EXISTS settings( 17 | key String PRIMARY KEY NOT NULL, 18 | value String NOT NULL); 19 | CREATE INDEX IF NOT EXISTS idx_settings_key ON settings(key);"#, 20 | ) 21 | .execute(executor) 22 | .await?; 23 | 24 | Ok(()) 25 | } 26 | 27 | /// 存储一个设置 28 | pub async fn save<'a, E>(executor: E, settings: &Settings) -> Result<()> 29 | where 30 | E: Executor<'a, Database = Sqlite>, 31 | { 32 | sqlx::query("INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?);") 33 | .bind(&settings.key) 34 | .bind(&settings.value) 35 | .execute(executor) 36 | .await?; 37 | Ok(()) 38 | } 39 | 40 | /// 读取一个设置 41 | pub async fn read<'a, E>(executor: E, key: &str) -> Result> 42 | where 43 | E: Executor<'a, Database = Sqlite>, 44 | { 45 | let settings = sqlx::query_as("SELECT key,value FROM settings WHERE key = ?;") 46 | .bind(key) 47 | .fetch_optional(executor) 48 | .await?; 49 | Ok(settings) 50 | } 51 | 52 | /// 读取全部设置 53 | pub async fn read_all<'a, E>(executor: E) -> Result> 54 | where 55 | E: Executor<'a, Database = Sqlite>, 56 | { 57 | let settings = sqlx::query_as("SELECT key,value FROM settings;") 58 | .fetch_all(executor) 59 | .await?; 60 | Ok(settings) 61 | } 62 | -------------------------------------------------------------------------------- /src-tauri/src/error.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, thiserror::Error)] 2 | #[non_exhaustive] 3 | pub enum OneClickLaunchError { 4 | #[error("Failed to execute command: {0}")] 5 | ExecutionError(String), 6 | 7 | #[error("{0}")] 8 | SystemError(#[from] std::fmt::Error), 9 | 10 | #[error("{0}")] 11 | DatebaseError(#[from] sqlx::Error), 12 | 13 | #[error("{0}")] 14 | AnyhowError(#[from] anyhow::Error), 15 | 16 | #[error("{0}")] 17 | InfoError(#[from] std::io::Error), 18 | 19 | #[error("{0}")] 20 | TauriError(#[from] tauri::Error), 21 | 22 | #[error("Unable to convert from {0} to Event")] 23 | EventConvertError(String), 24 | } 25 | 26 | // we must manually implement serde::Serialize 27 | impl serde::Serialize for OneClickLaunchError { 28 | fn serialize(&self, serializer: S) -> Result 29 | where 30 | S: serde::ser::Serializer, 31 | { 32 | serializer.serialize_str(self.to_string().as_ref()) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src-tauri/src/events.rs: -------------------------------------------------------------------------------- 1 | pub mod system_listeners; 2 | pub mod types; 3 | 4 | use std::marker::PhantomData; 5 | 6 | use serde::{Deserialize, Serialize}; 7 | use tauri::{AppHandle, Emitter, Listener}; 8 | use tracing::error; 9 | 10 | use crate::error::OneClickLaunchError; 11 | 12 | pub trait Event { 13 | type Payload: Serialize + for<'a> Deserialize<'a> + Clone; 14 | 15 | fn name() -> &'static str; 16 | } 17 | 18 | // 事件发送器 19 | pub struct EventDispatcher { 20 | _marker: PhantomData, 21 | } 22 | 23 | impl EventDispatcher { 24 | pub fn send_event(app: &AppHandle, payload: E::Payload) -> Result<(), OneClickLaunchError> { 25 | app.emit(E::name(), payload)?; 26 | Ok(()) 27 | } 28 | } 29 | 30 | // 事件监听器注册系统 31 | pub struct EventSystem; 32 | 33 | impl EventSystem { 34 | pub fn register_listener(app: &AppHandle, _event: E, callback: F) 35 | where 36 | E: Event + 'static, 37 | F: Fn(E::Payload) + Send + 'static, 38 | { 39 | app.listen(E::name(), move |e| { 40 | if let Ok(payload) = serde_json::from_str(e.payload()) { 41 | callback(payload); 42 | } else { 43 | error!("{}事件payload反序列化失败.原始数据: {}", "", e.payload()); 44 | } 45 | }); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src-tauri/src/events/system_listeners.rs: -------------------------------------------------------------------------------- 1 | use tauri::{AppHandle, Manager}; 2 | use tracing::{debug, error}; 3 | 4 | use crate::{ 5 | DatabaseManager, 6 | api::{ 7 | launcher_api, 8 | setting_api::{self, check_launch_then_exit}, 9 | window_api, 10 | }, 11 | constants::{ 12 | self, AUTO_START_FLAG, AUTO_START_LAUNCHER_IDS_KEY, HIDE_AFTER_AUTO_START_KEY, THEME_KEY, 13 | }, 14 | db::{launcher_resource, settings}, 15 | events::EventDispatcher, 16 | }; 17 | 18 | use super::{ 19 | EventSystem, 20 | types::{ 21 | ApplicationStartupComplete, ApplicationStartupCompletePayload, LauncherBasicInfoUpdated, 22 | LauncherLaunched, LauncherLaunchedPayload, SettingUpdated, SettingUpdatedPayload, 23 | }, 24 | }; 25 | 26 | pub fn register_system_listeners(app: &AppHandle) { 27 | register_launcher_launched_listeners(app); 28 | register_launcher_basic_info_updated_listeners(app); 29 | register_application_startup_complete_listeners(app); 30 | register_setting_updated_listeners(app); 31 | } 32 | 33 | /// 注册启动器启动事件监听器 34 | fn register_launcher_launched_listeners(app: &AppHandle) { 35 | let app_handle = app.clone(); 36 | EventSystem::register_listener(app, LauncherLaunched, move |payload| { 37 | debug!("launcher_launched_listeners 处理中"); 38 | hide_window(&app_handle, &payload); 39 | launch_then_exit(&app_handle); 40 | debug!("launcher_launched_listeners 处理完成"); 41 | }); 42 | } 43 | 44 | /// 注册启动器基础信息变更事件 45 | fn register_launcher_basic_info_updated_listeners(app: &AppHandle) { 46 | let app_handle = app.clone(); 47 | EventSystem::register_listener(app, LauncherBasicInfoUpdated, move |_payload| { 48 | debug!("launcher_basic_info_updated_listeners 处理中"); 49 | refresh_tray(&app_handle); 50 | debug!("launcher_basic_info_updated_listeners 处理完成"); 51 | }); 52 | } 53 | 54 | /// 注册应用程序启动完成监听器 55 | fn register_application_startup_complete_listeners(app: &AppHandle) { 56 | let app_cloned = app.clone(); 57 | EventSystem::register_listener(app, ApplicationStartupComplete, move |payload| { 58 | debug!("application_startup_complete_listeners 处理中"); 59 | hide_after_auto_start(&app_cloned, &payload); 60 | refresh_tray(&app_cloned); 61 | launch_auto_start_launchers(&app_cloned, &payload); 62 | debug!("application_startup_complete_listeners 处理完成"); 63 | }); 64 | } 65 | 66 | /// 注册应用程序设置修改监听器 67 | fn register_setting_updated_listeners(app: &AppHandle) { 68 | let app_cloned = app.clone(); 69 | EventSystem::register_listener(app, SettingUpdated, move |payload| { 70 | debug!("setting_updated_listeners 处理中"); 71 | change_theme(&app_cloned, &payload); 72 | debug!("setting_updated_listeners 处理完成"); 73 | }); 74 | } 75 | 76 | /// 刷新系统图标 77 | fn refresh_tray(app: &AppHandle) { 78 | let app_cloned = app.clone(); 79 | tauri::async_runtime::spawn(async move { 80 | if let Err(e) = window_api::refresh_tray(app_cloned).await { 81 | error!("刷新系统图标失败.{:?}", e); 82 | } else { 83 | debug!("刷新系统图标成功."); 84 | } 85 | }); 86 | } 87 | 88 | /// 应用程序自动启动后隐藏 89 | fn hide_after_auto_start(app: &AppHandle, payload: &ApplicationStartupCompletePayload) { 90 | if payload.args.contains(&AUTO_START_FLAG) { 91 | debug!( 92 | "hide_after_auto_start 判断为自动启动, 命令行参数: {:?}", 93 | payload.args 94 | ); 95 | 96 | let inner_app = app.clone(); 97 | 98 | tauri::async_runtime::spawn(async move { 99 | let app_cloned = inner_app.clone(); 100 | 101 | let db_manager = app_cloned.state::(); 102 | 103 | let window = app_cloned 104 | .get_webview_window(constants::MAIN_WINDOW_LABEL) 105 | .unwrap(); 106 | 107 | match settings::read(&db_manager.pool, HIDE_AFTER_AUTO_START_KEY) 108 | .await 109 | .ok() 110 | .flatten() 111 | { 112 | Some(settings) if setting_api::string_to_bool(&settings.value) => { 113 | let _ = window.hide(); 114 | } 115 | _ => { 116 | let _ = window.show(); 117 | } 118 | } 119 | }); 120 | } else { 121 | let window = app 122 | .get_webview_window(constants::MAIN_WINDOW_LABEL) 123 | .unwrap(); 124 | let _ = window.show(); 125 | } 126 | } 127 | 128 | fn launch_auto_start_launchers(app: &AppHandle, payload: &ApplicationStartupCompletePayload) { 129 | // 检查启动参数, 当命令包含`--auto`时表示是操作系统触发的自动启动 130 | if payload.args.contains(&AUTO_START_FLAG) { 131 | debug!( 132 | "launch_auto_start_launchers 判断为自动启动, 命令行参数: {:?}", 133 | payload.args 134 | ); 135 | 136 | let inner_app = app.clone(); 137 | 138 | tauri::async_runtime::spawn(async move { 139 | let app_cloned = inner_app.clone(); 140 | 141 | let db_manager = app_cloned.state::(); 142 | 143 | if let Ok(Some(settings)) = 144 | settings::read(&db_manager.pool, AUTO_START_LAUNCHER_IDS_KEY).await 145 | { 146 | if let Ok(auto_start_launcher_ids) = 147 | serde_json::from_str::>(&settings.value) 148 | { 149 | if let Ok(launcher_resources) = launcher_resource::query_by_launcher_ids( 150 | &db_manager.pool, 151 | &auto_start_launcher_ids, 152 | ) 153 | .await 154 | { 155 | // 如果用户设置的自启启动器为空则不执行启动 156 | if !launcher_resources.is_empty() { 157 | launcher_api::launch_resources(&app_cloned, &launcher_resources); 158 | debug!("自启启动器已启动. 启动器信息: {:?}", launcher_resources); 159 | let _ = EventDispatcher::::send_event( 160 | &app_cloned, 161 | LauncherLaunchedPayload { 162 | launcher_ids: auto_start_launcher_ids.clone(), 163 | }, 164 | ); 165 | } else { 166 | debug!("开启了自启启动器,但启动器为空"); 167 | } 168 | } 169 | } else { 170 | debug!( 171 | "launch_auto_start_launchers 自启动启动器反序列化失败,原始数据: {}", 172 | &settings.value 173 | ); 174 | } 175 | } else { 176 | debug!("launch_auto_start_launchers 没有找到自启动启动器"); 177 | } 178 | }); 179 | } else { 180 | debug!( 181 | "launch_auto_start_launchers 判断为非自动启动, 命令行参数: {:?}", 182 | payload.args 183 | ); 184 | } 185 | } 186 | 187 | fn launch_then_exit(app: &AppHandle) { 188 | let app_cloned = app.clone(); 189 | tauri::async_runtime::spawn(async move { 190 | let db = app_cloned.state::(); 191 | if let Ok(_exit @ true) = check_launch_then_exit(&db.pool).await { 192 | debug!("launch_then_exit 已设置启动后退出, 正在退出程序."); 193 | app_cloned.exit(0); 194 | } else { 195 | debug!("launch_then_exit 未设置启动后退出"); 196 | } 197 | }); 198 | } 199 | 200 | /// 隐藏窗口: 启动器启动隐藏窗口 201 | fn hide_window(app: &AppHandle, payload: &LauncherLaunchedPayload) { 202 | if !payload.launcher_ids.is_empty() && payload.launcher_ids.len() == 1 { 203 | let _ = window_api::hide_window(app); 204 | debug!("hide_window 已隐藏"); 205 | } else { 206 | debug!("hide_window 启动的启动器数量不是1, 不执行隐藏"); 207 | } 208 | } 209 | 210 | /// 隐藏窗口: 启动器启动隐藏窗口 211 | fn change_theme(app: &AppHandle, payload: &SettingUpdatedPayload) { 212 | if THEME_KEY == payload.key { 213 | match window_api::change_windows_theme(app, &payload.value) { 214 | Ok(_) => { 215 | debug!("修改主题成功,新主题: {}", payload.value) 216 | } 217 | Err(_) => { 218 | error!("修改主题失败,新主题: {}", payload.value) 219 | } 220 | } 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /src-tauri/src/events/types.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | 3 | use serde::{Deserialize, Serialize}; 4 | 5 | use super::Event; 6 | 7 | /// 启动器被启动的事件 8 | pub struct LauncherLaunched; 9 | 10 | /// 启动器被启动的事件载荷 11 | #[derive(Serialize, Deserialize, Clone, Debug)] 12 | pub struct LauncherLaunchedPayload { 13 | /// 启动器id集 14 | pub launcher_ids: Vec, 15 | } 16 | 17 | impl Event for LauncherLaunched { 18 | type Payload = LauncherLaunchedPayload; 19 | 20 | fn name() -> &'static str { 21 | "launcher:launched" 22 | } 23 | } 24 | 25 | /// 应用程序启动完成的事件 26 | pub struct ApplicationStartupComplete; 27 | 28 | /// 应用程序启动完成的事件载荷 29 | #[derive(Serialize, Deserialize, Clone, Debug)] 30 | pub struct ApplicationStartupCompletePayload { 31 | /// 应用程序启动参数 32 | pub args: Vec, 33 | } 34 | 35 | impl Event for ApplicationStartupComplete { 36 | type Payload = ApplicationStartupCompletePayload; 37 | 38 | fn name() -> &'static str { 39 | "application:startup-complete" 40 | } 41 | } 42 | 43 | /// 启动器基础信息编辑完成事件 44 | pub struct LauncherBasicInfoUpdated; 45 | 46 | /// 启动器基础信息编辑完成事件载荷 47 | #[derive(Serialize, Deserialize, Clone, Debug)] 48 | pub struct LauncherBasicInfoUpdatedPayload { 49 | /// 启动器id集 50 | pub launcher_ids: Vec, 51 | } 52 | 53 | impl Event for LauncherBasicInfoUpdated { 54 | type Payload = LauncherBasicInfoUpdatedPayload; 55 | 56 | fn name() -> &'static str { 57 | "launcher:basic_info_updated" 58 | } 59 | } 60 | 61 | /// 设置被更新 62 | pub struct SettingUpdated; 63 | 64 | /// 设置被更新载荷 65 | #[derive(Serialize, Deserialize, Clone, Debug)] 66 | pub struct SettingUpdatedPayload { 67 | /// 设置项 68 | pub key: String, 69 | /// 设置值 70 | pub value: String, 71 | } 72 | 73 | impl Event for SettingUpdated { 74 | type Payload = SettingUpdatedPayload; 75 | 76 | fn name() -> &'static str { 77 | "setting:updated" 78 | } 79 | } 80 | 81 | /// 拖放资源 82 | pub struct DragDropResource; 83 | /// 拖放资源载荷 84 | #[derive(Serialize, Deserialize, Clone, Debug)] 85 | pub struct DragDropResourcePaylod { 86 | /// 拖放到窗口上的路径列表。 87 | pub paths: Vec, 88 | } 89 | 90 | impl Event for DragDropResource { 91 | type Payload = DragDropResourcePaylod; 92 | 93 | fn name() -> &'static str { 94 | "launcher:drag_drop_resource" 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src-tauri/src/lib.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use api::window_api::{ScaleFactorChangedState, setup_tray}; 3 | use api::{launcher_api, setting_api, window_api}; 4 | use constants::AUTO_START_FLAG; 5 | use db::{launcher, launcher_resource, settings}; 6 | use events::EventDispatcher; 7 | use events::system_listeners::register_system_listeners; 8 | use events::types::{ApplicationStartupComplete, ApplicationStartupCompletePayload}; 9 | use sqlx::{SqlitePool, sqlite::SqlitePoolOptions}; 10 | use std::path::PathBuf; 11 | use std::sync::Mutex; 12 | use std::{env, fs}; 13 | use tauri::Emitter; 14 | use tauri::tray::TrayIcon; 15 | use tauri::{AppHandle, Manager}; 16 | use tauri_plugin_autostart::MacosLauncher; 17 | use tracing::{debug, info}; 18 | mod api; 19 | mod constants; 20 | mod db; 21 | pub mod error; 22 | mod events; 23 | 24 | pub struct DatabaseManager { 25 | pub pool: SqlitePool, 26 | } 27 | 28 | #[derive(Clone, serde::Serialize)] 29 | struct Payload { 30 | args: Vec, 31 | cwd: String, 32 | } 33 | 34 | pub struct WindowContext { 35 | pub tray_icon: TrayIcon, 36 | } 37 | 38 | #[cfg(not(feature = "portable"))] 39 | fn get_db_path() -> Result { 40 | // 获取用户的 AppData 目录路径 41 | let app_data = env::var("APPDATA")?; 42 | 43 | // 拼接到特定的文件夹路径 44 | let db_path = PathBuf::from(app_data) 45 | .join("one_click_launch") 46 | .join("data") 47 | .join("one_click_launch.db"); 48 | 49 | Ok(db_path) 50 | } 51 | 52 | #[cfg(feature = "portable")] 53 | fn get_db_path() -> Result { 54 | // 便携版:使用当前可执行文件的目录 55 | let exe_path = env::current_exe()?; 56 | let db_path = exe_path 57 | .parent() 58 | .ok_or_else(|| { 59 | std::io::Error::new(std::io::ErrorKind::Other, "Cannot get executable directory") 60 | })? 61 | .join("data") 62 | .join("one_click_launch.db"); 63 | 64 | Ok(db_path) 65 | } 66 | 67 | async fn init_db() -> Result { 68 | let db_path = get_db_path()?; 69 | 70 | debug!("db_path:{:?}", db_path); 71 | 72 | // 确保目录存在 73 | if let Some(parent) = db_path.parent() { 74 | if !parent.exists() { 75 | fs::create_dir_all(parent)?; 76 | } 77 | } 78 | 79 | // 检查数据库文件是否存在,如果不存在则创建空文件 80 | if !db_path.exists() { 81 | // 创建空的数据库文件 82 | fs::File::create(&db_path)?; 83 | info!("Database file created at {:?}", db_path); 84 | } 85 | 86 | // 创建连接池 87 | let pool = SqlitePoolOptions::new() 88 | .max_connections(5) 89 | .connect(db_path.to_string_lossy().as_ref()) 90 | .await?; 91 | 92 | launcher::initialize(&pool).await?; 93 | 94 | launcher_resource::initialize(&pool).await?; 95 | 96 | settings::initialize(&pool).await?; 97 | 98 | Ok(DatabaseManager { pool }) 99 | } 100 | 101 | #[cfg_attr(mobile, tauri::mobile_entry_point)] 102 | pub async fn run() -> Result<()> { 103 | let db_manager = init_db().await?; 104 | 105 | tauri::Builder::default() 106 | .setup(move |app| { 107 | // 注册监听器,之后添加新的监听器时在这个方法内部添加 108 | register_listeners(app.handle()); 109 | 110 | // 初始化窗口 111 | setup_tray(app.handle())?; 112 | 113 | // 当所有初始化都完成后发送应用程序启动完成事件 114 | EventDispatcher::::send_event( 115 | app.handle(), 116 | ApplicationStartupCompletePayload { 117 | args: env::args().collect(), 118 | }, 119 | )?; 120 | 121 | Ok(()) 122 | }) 123 | .on_window_event(window_api::handle_window_event) 124 | .manage(db_manager) 125 | .manage(ScaleFactorChangedState { 126 | last_reset: Mutex::new(None), 127 | }) 128 | // 优先注册单例插件 129 | .plugin(tauri_plugin_single_instance::init(|app, argv, cwd| { 130 | info!("{}, {argv:?}, {cwd}", app.package_info().name); 131 | let windows = app 132 | .get_webview_window(constants::MAIN_WINDOW_LABEL) 133 | .unwrap(); 134 | if windows.is_visible().unwrap() { 135 | let _ = windows.unmaximize(); 136 | } 137 | let _ = windows.show(); 138 | let _ = windows.set_focus(); 139 | app.emit("single-instance", Payload { args: argv, cwd }) 140 | .unwrap(); 141 | })) 142 | .plugin(tauri_plugin_window_state::Builder::default().build()) 143 | .plugin(tauri_plugin_shell::init()) 144 | .plugin(tauri_plugin_dialog::init()) 145 | .plugin(tauri_plugin_os::init()) 146 | .plugin(tauri_plugin_opener::init()) 147 | .plugin(tauri_plugin_autostart::init( 148 | MacosLauncher::LaunchAgent, 149 | // 操作系统以开机自启启动应用程序时携带的参数 150 | Some(vec![AUTO_START_FLAG.as_str()]), 151 | )) 152 | .invoke_handler(tauri::generate_handler![ 153 | launcher_api::craete_launcher, 154 | launcher_api::modify_launcher_name, 155 | launcher_api::copy_launcher, 156 | launcher_api::delete_launcher, 157 | launcher_api::modify_launcher_sort, 158 | launcher_api::add_resource, 159 | launcher_api::add_resources, 160 | launcher_api::modify_resource_name, 161 | launcher_api::delete_resource, 162 | launcher_api::query_launchers, 163 | launcher_api::launch, 164 | launcher_api::open_path, 165 | setting_api::save_setting, 166 | setting_api::read_setting, 167 | setting_api::read_all_setting, 168 | ]) 169 | .run(tauri::generate_context!()) 170 | .expect("error while running tauri application"); 171 | Ok(()) 172 | } 173 | 174 | fn register_listeners(app: &AppHandle) { 175 | // 注册系统级别的监听器 176 | register_system_listeners(app); 177 | } 178 | -------------------------------------------------------------------------------- /src-tauri/src/main.rs: -------------------------------------------------------------------------------- 1 | // Prevents additional console window on Windows in release, DO NOT REMOVE!! 2 | #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] 3 | use anyhow::Result; 4 | use one_click_start_lib::error::OneClickLaunchError; 5 | use tracing_subscriber::fmt; 6 | 7 | #[tokio::main] 8 | async fn main() -> Result<(), OneClickLaunchError> { 9 | // 只在开发模式下调用日志初始化 10 | #[cfg(debug_assertions)] 11 | { 12 | fmt() 13 | .with_writer(std::io::stderr) // 将日志发送到标准错误输出 14 | .with_max_level(tracing::Level::DEBUG) // 设置最大日志级别 15 | .init(); 16 | } 17 | 18 | one_click_start_lib::run().await?; 19 | Ok(()) 20 | } 21 | -------------------------------------------------------------------------------- /src-tauri/tauri.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.tauri.app/config/2", 3 | "productName": "一键启动", 4 | "version": "1.0.3", 5 | "identifier": "one-click-launch", 6 | "build": { 7 | "beforeDevCommand": "yarn dev", 8 | "devUrl": "http://localhost:1420", 9 | "beforeBuildCommand": "yarn build", 10 | "frontendDist": "../dist" 11 | }, 12 | "app": { 13 | "windows": [ 14 | { 15 | "label": "main", 16 | "title": "一键启动", 17 | "width": 800, 18 | "height": 600, 19 | "visible": false 20 | } 21 | ], 22 | "security": { 23 | "csp": null 24 | } 25 | }, 26 | "bundle": { 27 | "active": true, 28 | "targets": "all", 29 | "icon": [ 30 | "icons/32x32.png", 31 | "icons/128x128.png", 32 | "icons/128x128@2x.png", 33 | "icons/icon.icns", 34 | "icons/icon.ico" 35 | ], 36 | "windows": { 37 | "wix": { 38 | "language": "zh-CN" 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 51 | 52 | -------------------------------------------------------------------------------- /src/DragDropResource.vue: -------------------------------------------------------------------------------- 1 | 45 | 46 | 126 | 127 | -------------------------------------------------------------------------------- /src/assets/home_desc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src/assets/home_desc.png -------------------------------------------------------------------------------- /src/assets/read_mode_desc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src/assets/read_mode_desc.png -------------------------------------------------------------------------------- /src/assets/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src/assets/settings.png -------------------------------------------------------------------------------- /src/assets/tray_desc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Silwings-git/one-click-launch/21775bc5498f87e22f545588015b5a48b8066d5c/src/assets/tray_desc.png -------------------------------------------------------------------------------- /src/home.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 173 | 174 | -------------------------------------------------------------------------------- /src/launcher.vue: -------------------------------------------------------------------------------- 1 | 93 | 94 | 295 | -------------------------------------------------------------------------------- /src/launcherLite.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 77 | 78 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from "vue"; 2 | import { createPinia } from 'pinia'; 3 | import App from "./App.vue"; 4 | import '@fortawesome/fontawesome-free/css/all.css'; 5 | import '@fortawesome/fontawesome-free/js/all.js'; 6 | import '@icon-park/vue-next/styles/index.css'; 7 | 8 | import Toast, { PluginOptions, POSITION } from "vue-toastification"; 9 | import "vue-toastification/dist/index.css"; 10 | 11 | const options: PluginOptions = { 12 | position: POSITION.TOP_CENTER, // 设置Toast的位置 13 | timeout: 3000, // 自动关闭的时间,单位为毫秒 14 | closeOnClick: true, // 是否点击关闭Toast 15 | pauseOnFocusLoss: false, // 当窗口失去焦点时暂停倒计时 16 | pauseOnHover: true, // 鼠标悬停时暂停倒计时 17 | draggable: true, // 是否可以拖动Toast 18 | draggablePercent: 0.6, // 拖动百分比 19 | showCloseButtonOnHover: true, // 是否在鼠标悬停时显示关闭按钮 20 | hideProgressBar: false, // 是否隐藏进度条 21 | closeButton: 'button', // 关闭按钮类型 22 | icon: true, // 是否显示图标 23 | rtl: false, // 是否支持从右向左的语言 24 | }; 25 | 26 | const app = createApp(App); 27 | 28 | app.use(Toast, options); 29 | app.use(createPinia()); 30 | 31 | app.mount("#app"); 32 | -------------------------------------------------------------------------------- /src/settings.vue: -------------------------------------------------------------------------------- 1 | 61 | 62 | 206 | 207 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module "*.vue" { 4 | import type { DefineComponent } from "vue"; 5 | const component: DefineComponent<{}, {}, any>; 6 | export default component; 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | "jsx": "preserve", 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true 22 | }, 23 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "src/App2.vue", "src/scripts/reload-theme.js"], 24 | "references": [{ "path": "./tsconfig.node.json" }] 25 | } 26 | -------------------------------------------------------------------------------- /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 { defineConfig } from "vite"; 2 | import vue from "@vitejs/plugin-vue"; 3 | import AutoImport from 'unplugin-auto-import/vite' 4 | import Components from 'unplugin-vue-components/vite' 5 | import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' 6 | 7 | // @ts-expect-error process is a nodejs global 8 | const host = process.env.TAURI_DEV_HOST; 9 | 10 | // https://vitejs.dev/config/ 11 | export default defineConfig(async () => ({ 12 | plugins: [vue(), 13 | AutoImport({ 14 | resolvers: [ElementPlusResolver()], 15 | }), 16 | Components({ 17 | resolvers: [ElementPlusResolver()], 18 | }), 19 | ], 20 | 21 | // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` 22 | // 23 | // 1. prevent vite from obscuring rust errors 24 | clearScreen: false, 25 | // 2. tauri expects a fixed port, fail if that port is not available 26 | server: { 27 | port: 1420, 28 | strictPort: true, 29 | host: host || false, 30 | hmr: host 31 | ? { 32 | protocol: "ws", 33 | host, 34 | port: 1421, 35 | } 36 | : undefined, 37 | watch: { 38 | // 3. tell vite to ignore watching `src-tauri` 39 | ignored: ["**/src-tauri/**"], 40 | }, 41 | }, 42 | })); 43 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/helper-module-imports@7.0.0-beta.35": 6 | version "7.0.0-beta.35" 7 | resolved "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.35.tgz" 8 | integrity sha512-vaC1KyIZSuyWb3Lj277fX0pxivyHwuDU4xZsofqgYAbkDxNieMg2vuhzP5AgMweMY7fCQUMTi+BgPqTLjkxXFg== 9 | dependencies: 10 | "@babel/types" "7.0.0-beta.35" 11 | lodash "^4.2.0" 12 | 13 | "@babel/helper-string-parser@^7.25.9": 14 | version "7.25.9" 15 | resolved "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz" 16 | integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== 17 | 18 | "@babel/helper-validator-identifier@^7.25.9": 19 | version "7.25.9" 20 | resolved "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz" 21 | integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== 22 | 23 | "@babel/parser@^7.25.3": 24 | version "7.26.2" 25 | resolved "https://registry.npmmirror.com/@babel/parser/-/parser-7.26.2.tgz" 26 | integrity sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ== 27 | dependencies: 28 | "@babel/types" "^7.26.0" 29 | 30 | "@babel/types@7.0.0-beta.35": 31 | version "7.0.0-beta.35" 32 | resolved "https://registry.npmmirror.com/@babel/types/-/types-7.0.0-beta.35.tgz" 33 | integrity sha512-y9XT11CozHDgjWcTdxmhSj13rJVXpa5ZXwjjOiTedjaM0ba5ItqdS02t31EhPl7HtOWxsZkYCCUNrSfrOisA6w== 34 | dependencies: 35 | esutils "^2.0.2" 36 | lodash "^4.2.0" 37 | to-fast-properties "^2.0.0" 38 | 39 | "@babel/types@^7.26.0": 40 | version "7.26.0" 41 | resolved "https://registry.npmmirror.com/@babel/types/-/types-7.26.0.tgz" 42 | integrity sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA== 43 | dependencies: 44 | "@babel/helper-string-parser" "^7.25.9" 45 | "@babel/helper-validator-identifier" "^7.25.9" 46 | 47 | "@ctrl/tinycolor@^3.4.1": 48 | version "3.6.1" 49 | resolved "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz" 50 | integrity sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA== 51 | 52 | "@element-plus/icons-vue@^2.3.1": 53 | version "2.3.1" 54 | resolved "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz" 55 | integrity sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg== 56 | 57 | "@esbuild/aix-ppc64@0.21.5": 58 | version "0.21.5" 59 | resolved "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" 60 | integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== 61 | 62 | "@esbuild/android-arm64@0.21.5": 63 | version "0.21.5" 64 | resolved "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" 65 | integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== 66 | 67 | "@esbuild/android-arm@0.21.5": 68 | version "0.21.5" 69 | resolved "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" 70 | integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== 71 | 72 | "@esbuild/android-x64@0.21.5": 73 | version "0.21.5" 74 | resolved "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" 75 | integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== 76 | 77 | "@esbuild/darwin-arm64@0.21.5": 78 | version "0.21.5" 79 | resolved "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" 80 | integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== 81 | 82 | "@esbuild/darwin-x64@0.21.5": 83 | version "0.21.5" 84 | resolved "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" 85 | integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== 86 | 87 | "@esbuild/freebsd-arm64@0.21.5": 88 | version "0.21.5" 89 | resolved "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" 90 | integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== 91 | 92 | "@esbuild/freebsd-x64@0.21.5": 93 | version "0.21.5" 94 | resolved "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" 95 | integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== 96 | 97 | "@esbuild/linux-arm64@0.21.5": 98 | version "0.21.5" 99 | resolved "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" 100 | integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== 101 | 102 | "@esbuild/linux-arm@0.21.5": 103 | version "0.21.5" 104 | resolved "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" 105 | integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== 106 | 107 | "@esbuild/linux-ia32@0.21.5": 108 | version "0.21.5" 109 | resolved "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" 110 | integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== 111 | 112 | "@esbuild/linux-loong64@0.21.5": 113 | version "0.21.5" 114 | resolved "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" 115 | integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== 116 | 117 | "@esbuild/linux-mips64el@0.21.5": 118 | version "0.21.5" 119 | resolved "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" 120 | integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== 121 | 122 | "@esbuild/linux-ppc64@0.21.5": 123 | version "0.21.5" 124 | resolved "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" 125 | integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== 126 | 127 | "@esbuild/linux-riscv64@0.21.5": 128 | version "0.21.5" 129 | resolved "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" 130 | integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== 131 | 132 | "@esbuild/linux-s390x@0.21.5": 133 | version "0.21.5" 134 | resolved "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" 135 | integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== 136 | 137 | "@esbuild/linux-x64@0.21.5": 138 | version "0.21.5" 139 | resolved "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" 140 | integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== 141 | 142 | "@esbuild/netbsd-x64@0.21.5": 143 | version "0.21.5" 144 | resolved "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" 145 | integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== 146 | 147 | "@esbuild/openbsd-x64@0.21.5": 148 | version "0.21.5" 149 | resolved "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" 150 | integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== 151 | 152 | "@esbuild/sunos-x64@0.21.5": 153 | version "0.21.5" 154 | resolved "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" 155 | integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== 156 | 157 | "@esbuild/win32-arm64@0.21.5": 158 | version "0.21.5" 159 | resolved "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" 160 | integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== 161 | 162 | "@esbuild/win32-ia32@0.21.5": 163 | version "0.21.5" 164 | resolved "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" 165 | integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== 166 | 167 | "@esbuild/win32-x64@0.21.5": 168 | version "0.21.5" 169 | resolved "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz" 170 | integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== 171 | 172 | "@floating-ui/core@^1.6.0": 173 | version "1.6.9" 174 | resolved "https://registry.npmmirror.com/@floating-ui/core/-/core-1.6.9.tgz" 175 | integrity sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw== 176 | dependencies: 177 | "@floating-ui/utils" "^0.2.9" 178 | 179 | "@floating-ui/dom@^1.0.1": 180 | version "1.6.13" 181 | resolved "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.6.13.tgz" 182 | integrity sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w== 183 | dependencies: 184 | "@floating-ui/core" "^1.6.0" 185 | "@floating-ui/utils" "^0.2.9" 186 | 187 | "@floating-ui/utils@^0.2.9": 188 | version "0.2.9" 189 | resolved "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.9.tgz" 190 | integrity sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg== 191 | 192 | "@fortawesome/fontawesome-free@^6.7.2": 193 | version "6.7.2" 194 | resolved "https://registry.npmmirror.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.7.2.tgz" 195 | integrity sha512-JUOtgFW6k9u4Y+xeIaEiLr3+cjoUPiAuLXoyKOJSia6Duzb7pq+A76P9ZdPDoAoxHdHzq6gE9/jKBGXlZT8FbA== 196 | 197 | "@icon-park/vue-next@^1.4.2": 198 | version "1.4.2" 199 | resolved "https://registry.npmmirror.com/@icon-park/vue-next/-/vue-next-1.4.2.tgz" 200 | integrity sha512-+QklF255wkfBOabY+xw6FAI0Bwln/RhdwCunNy/9sKdKuChtaU67QZqU67KGAvZUTeeBgsL+yaHHxqfQeGZXEQ== 201 | 202 | "@jridgewell/sourcemap-codec@^1.5.0": 203 | version "1.5.0" 204 | resolved "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz" 205 | integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== 206 | 207 | "@popperjs/core@npm:@sxzz/popperjs-es@^2.11.7": 208 | version "2.11.7" 209 | resolved "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz" 210 | integrity sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ== 211 | 212 | "@rollup/rollup-android-arm-eabi@4.28.0": 213 | version "4.28.0" 214 | resolved "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.0.tgz#462e7ecdd60968bc9eb95a20d185e74f8243ec1b" 215 | integrity sha512-wLJuPLT6grGZsy34g4N1yRfYeouklTgPhH1gWXCYspenKYD0s3cR99ZevOGw5BexMNywkbV3UkjADisozBmpPQ== 216 | 217 | "@rollup/rollup-android-arm64@4.28.0": 218 | version "4.28.0" 219 | resolved "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.0.tgz#78a2b8a8a55f71a295eb860a654ae90a2b168f40" 220 | integrity sha512-eiNkznlo0dLmVG/6wf+Ifi/v78G4d4QxRhuUl+s8EWZpDewgk7PX3ZyECUXU0Zq/Ca+8nU8cQpNC4Xgn2gFNDA== 221 | 222 | "@rollup/rollup-darwin-arm64@4.28.0": 223 | version "4.28.0" 224 | resolved "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.0.tgz#5b783af714f434f1e66e3cdfa3817e0b99216d84" 225 | integrity sha512-lmKx9yHsppblnLQZOGxdO66gT77bvdBtr/0P+TPOseowE7D9AJoBw8ZDULRasXRWf1Z86/gcOdpBrV6VDUY36Q== 226 | 227 | "@rollup/rollup-darwin-x64@4.28.0": 228 | version "4.28.0" 229 | resolved "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.0.tgz#f72484e842521a5261978034e18e20f778a2850d" 230 | integrity sha512-8hxgfReVs7k9Js1uAIhS6zq3I+wKQETInnWQtgzt8JfGx51R1N6DRVy3F4o0lQwumbErRz52YqwjfvuwRxGv1w== 231 | 232 | "@rollup/rollup-freebsd-arm64@4.28.0": 233 | version "4.28.0" 234 | resolved "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.0.tgz#3c919dff72b2fe344811a609c674a8347b033f62" 235 | integrity sha512-lA1zZB3bFx5oxu9fYud4+g1mt+lYXCoch0M0V/xhqLoGatbzVse0wlSQ1UYOWKpuSu3gyN4qEc0Dxf/DII1bhQ== 236 | 237 | "@rollup/rollup-freebsd-x64@4.28.0": 238 | version "4.28.0" 239 | resolved "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.0.tgz#b62a3a8365b363b3fdfa6da11a9188b6ab4dca7c" 240 | integrity sha512-aI2plavbUDjCQB/sRbeUZWX9qp12GfYkYSJOrdYTL/C5D53bsE2/nBPuoiJKoWp5SN78v2Vr8ZPnB+/VbQ2pFA== 241 | 242 | "@rollup/rollup-linux-arm-gnueabihf@4.28.0": 243 | version "4.28.0" 244 | resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.0.tgz#0d02cc55bd229bd8ca5c54f65f916ba5e0591c94" 245 | integrity sha512-WXveUPKtfqtaNvpf0iOb0M6xC64GzUX/OowbqfiCSXTdi/jLlOmH0Ba94/OkiY2yTGTwteo4/dsHRfh5bDCZ+w== 246 | 247 | "@rollup/rollup-linux-arm-musleabihf@4.28.0": 248 | version "4.28.0" 249 | resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.0.tgz#c51d379263201e88a60e92bd8e90878f0c044425" 250 | integrity sha512-yLc3O2NtOQR67lI79zsSc7lk31xjwcaocvdD1twL64PK1yNaIqCeWI9L5B4MFPAVGEVjH5k1oWSGuYX1Wutxpg== 251 | 252 | "@rollup/rollup-linux-arm64-gnu@4.28.0": 253 | version "4.28.0" 254 | resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.0.tgz#93ce2addc337b5cfa52b84f8e730d2e36eb4339b" 255 | integrity sha512-+P9G9hjEpHucHRXqesY+3X9hD2wh0iNnJXX/QhS/J5vTdG6VhNYMxJ2rJkQOxRUd17u5mbMLHM7yWGZdAASfcg== 256 | 257 | "@rollup/rollup-linux-arm64-musl@4.28.0": 258 | version "4.28.0" 259 | resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.0.tgz#730af6ddc091a5ba5baac28a3510691725dc808b" 260 | integrity sha512-1xsm2rCKSTpKzi5/ypT5wfc+4bOGa/9yI/eaOLW0oMs7qpC542APWhl4A37AENGZ6St6GBMWhCCMM6tXgTIplw== 261 | 262 | "@rollup/rollup-linux-powerpc64le-gnu@4.28.0": 263 | version "4.28.0" 264 | resolved "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.0.tgz#b5565aac20b4de60ca1e557f525e76478b5436af" 265 | integrity sha512-zgWxMq8neVQeXL+ouSf6S7DoNeo6EPgi1eeqHXVKQxqPy1B2NvTbaOUWPn/7CfMKL7xvhV0/+fq/Z/J69g1WAQ== 266 | 267 | "@rollup/rollup-linux-riscv64-gnu@4.28.0": 268 | version "4.28.0" 269 | resolved "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.0.tgz#d488290bf9338bad4ae9409c4aa8a1728835a20b" 270 | integrity sha512-VEdVYacLniRxbRJLNtzwGt5vwS0ycYshofI7cWAfj7Vg5asqj+pt+Q6x4n+AONSZW/kVm+5nklde0qs2EUwU2g== 271 | 272 | "@rollup/rollup-linux-s390x-gnu@4.28.0": 273 | version "4.28.0" 274 | resolved "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.0.tgz#eb2e3f3a06acf448115045c11a5a96868c95a556" 275 | integrity sha512-LQlP5t2hcDJh8HV8RELD9/xlYtEzJkm/aWGsauvdO2ulfl3QYRjqrKW+mGAIWP5kdNCBheqqqYIGElSRCaXfpw== 276 | 277 | "@rollup/rollup-linux-x64-gnu@4.28.0": 278 | version "4.28.0" 279 | resolved "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.0.tgz#065952ef2aea7e837dc7e02aa500feeaff4fc507" 280 | integrity sha512-Nl4KIzteVEKE9BdAvYoTkW19pa7LR/RBrT6F1dJCV/3pbjwDcaOq+edkP0LXuJ9kflW/xOK414X78r+K84+msw== 281 | 282 | "@rollup/rollup-linux-x64-musl@4.28.0": 283 | version "4.28.0" 284 | resolved "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.0.tgz#3435d484d05f5c4d1ffd54541b4facce2887103a" 285 | integrity sha512-eKpJr4vBDOi4goT75MvW+0dXcNUqisK4jvibY9vDdlgLx+yekxSm55StsHbxUsRxSTt3JEQvlr3cGDkzcSP8bw== 286 | 287 | "@rollup/rollup-win32-arm64-msvc@4.28.0": 288 | version "4.28.0" 289 | resolved "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.0.tgz#69682a2a10d9fedc334f87583cfca83c39c08077" 290 | integrity sha512-Vi+WR62xWGsE/Oj+mD0FNAPY2MEox3cfyG0zLpotZdehPFXwz6lypkGs5y38Jd/NVSbOD02aVad6q6QYF7i8Bg== 291 | 292 | "@rollup/rollup-win32-ia32-msvc@4.28.0": 293 | version "4.28.0" 294 | resolved "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.0.tgz#b64470f9ac79abb386829c56750b9a4711be3332" 295 | integrity sha512-kN/Vpip8emMLn/eOza+4JwqDZBL6MPNpkdaEsgUtW1NYN3DZvZqSQrbKzJcTL6hd8YNmFTn7XGWMwccOcJBL0A== 296 | 297 | "@rollup/rollup-win32-x64-msvc@4.28.0": 298 | version "4.28.0" 299 | resolved "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.0.tgz" 300 | integrity sha512-Bvno2/aZT6usSa7lRDL2+hMjVAGjuqaymF1ApZm31JXzniR/hvr14jpU+/z4X6Gt5BPlzosscyJZGUvguXIqeQ== 301 | 302 | "@tauri-apps/api@^2.0.0", "@tauri-apps/api@^2.2.0": 303 | version "2.2.0" 304 | resolved "https://registry.npmmirror.com/@tauri-apps/api/-/api-2.2.0.tgz" 305 | integrity sha512-R8epOeZl1eJEl603aUMIGb4RXlhPjpgxbGVEaqY+0G5JG9vzV/clNlzTeqc+NLYXVqXcn8mb4c5b9pJIUDEyAg== 306 | 307 | "@tauri-apps/cli-darwin-arm64@2.1.0": 308 | version "2.1.0" 309 | resolved "https://registry.npmmirror.com/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.1.0.tgz#e9b020d25bc3be1ba86a7e330c65f27c2438cb0f" 310 | integrity sha512-ESc6J6CE8hl1yKH2vJ+ALF+thq4Be+DM1mvmTyUCQObvezNCNhzfS6abIUd3ou4x5RGH51ouiANeT3wekU6dCw== 311 | 312 | "@tauri-apps/cli-darwin-x64@2.1.0": 313 | version "2.1.0" 314 | resolved "https://registry.npmmirror.com/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.1.0.tgz#08c5f446b65bc351a8e74c0c8019324ae6864351" 315 | integrity sha512-TasHS442DFs8cSH2eUQzuDBXUST4ECjCd0yyP+zZzvAruiB0Bg+c8A+I/EnqCvBQ2G2yvWLYG8q/LI7c87A5UA== 316 | 317 | "@tauri-apps/cli-linux-arm-gnueabihf@2.1.0": 318 | version "2.1.0" 319 | resolved "https://registry.npmmirror.com/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.1.0.tgz#681d0967d0335b93ed8ab4b8bb5d820c72cc8abf" 320 | integrity sha512-aP7ZBGNL4ny07Cbb6kKpUOSrmhcIK2KhjviTzYlh+pPhAptxnC78xQGD3zKQkTi2WliJLPmBYbOHWWQa57lQ9w== 321 | 322 | "@tauri-apps/cli-linux-arm64-gnu@2.1.0": 323 | version "2.1.0" 324 | resolved "https://registry.npmmirror.com/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.1.0.tgz#922ddc50849ae9f2976f30fdb4b79708badb767b" 325 | integrity sha512-ZTdgD5gLeMCzndMT2f358EkoYkZ5T+Qy6zPzU+l5vv5M7dHVN9ZmblNAYYXmoOuw7y+BY4X/rZvHV9pcGrcanQ== 326 | 327 | "@tauri-apps/cli-linux-arm64-musl@2.1.0": 328 | version "2.1.0" 329 | resolved "https://registry.npmmirror.com/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.1.0.tgz#063020d217faf90b226d93b5054546ae0db14c16" 330 | integrity sha512-NzwqjUCilhnhJzusz3d/0i0F1GFrwCQbkwR6yAHUxItESbsGYkZRJk0yMEWkg3PzFnyK4cWTlQJMEU52TjhEzA== 331 | 332 | "@tauri-apps/cli-linux-x64-gnu@2.1.0": 333 | version "2.1.0" 334 | resolved "https://registry.npmmirror.com/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.1.0.tgz#7d7991a2b956232f96ec614f15189d408421dc03" 335 | integrity sha512-TyiIpMEtZxNOQmuFyfJwaaYbg3movSthpBJLIdPlKxSAB2BW0VWLY3/ZfIxm/G2YGHyREkjJvimzYE0i37PnMA== 336 | 337 | "@tauri-apps/cli-linux-x64-musl@2.1.0": 338 | version "2.1.0" 339 | resolved "https://registry.npmmirror.com/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.1.0.tgz#af6293ce56296619d656342f11d83c35c8465979" 340 | integrity sha512-/dQd0TlaxBdJACrR72DhynWftzHDaX32eBtS5WBrNJ+nnNb+znM3gON6nJ9tSE9jgDa6n1v2BkI/oIDtypfUXw== 341 | 342 | "@tauri-apps/cli-win32-arm64-msvc@2.1.0": 343 | version "2.1.0" 344 | resolved "https://registry.npmmirror.com/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.1.0.tgz#adb2b17d9939cdbcb136c5e24bf90d15485265dc" 345 | integrity sha512-NdQJO7SmdYqOcE+JPU7bwg7+odfZMWO6g8xF9SXYCMdUzvM2Gv/AQfikNXz5yS7ralRhNFuW32i5dcHlxh4pDg== 346 | 347 | "@tauri-apps/cli-win32-ia32-msvc@2.1.0": 348 | version "2.1.0" 349 | resolved "https://registry.npmmirror.com/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.1.0.tgz#5356a56a30bfc50a0edde3e91c16ccd3fa837d71" 350 | integrity sha512-f5h8gKT/cB8s1ticFRUpNmHqkmaLutT62oFDB7N//2YTXnxst7EpMIn1w+QimxTvTk2gcx6EcW6bEk/y2hZGzg== 351 | 352 | "@tauri-apps/cli-win32-x64-msvc@2.1.0": 353 | version "2.1.0" 354 | resolved "https://registry.npmmirror.com/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.1.0.tgz" 355 | integrity sha512-P/+LrdSSb5Xbho1LRP4haBjFHdyPdjWvGgeopL96OVtrFpYnfC+RctB45z2V2XxqFk3HweDDxk266btjttfjGw== 356 | 357 | "@tauri-apps/cli@^2": 358 | version "2.1.0" 359 | resolved "https://registry.npmmirror.com/@tauri-apps/cli/-/cli-2.1.0.tgz" 360 | integrity sha512-K2VhcKqBhAeS5pNOVdnR/xQRU6jwpgmkSL2ejHXcl0m+kaTggT0WRDQnFtPq6NljA7aE03cvwsbCAoFG7vtkJw== 361 | optionalDependencies: 362 | "@tauri-apps/cli-darwin-arm64" "2.1.0" 363 | "@tauri-apps/cli-darwin-x64" "2.1.0" 364 | "@tauri-apps/cli-linux-arm-gnueabihf" "2.1.0" 365 | "@tauri-apps/cli-linux-arm64-gnu" "2.1.0" 366 | "@tauri-apps/cli-linux-arm64-musl" "2.1.0" 367 | "@tauri-apps/cli-linux-x64-gnu" "2.1.0" 368 | "@tauri-apps/cli-linux-x64-musl" "2.1.0" 369 | "@tauri-apps/cli-win32-arm64-msvc" "2.1.0" 370 | "@tauri-apps/cli-win32-ia32-msvc" "2.1.0" 371 | "@tauri-apps/cli-win32-x64-msvc" "2.1.0" 372 | 373 | "@tauri-apps/plugin-autostart@^2.2.0": 374 | version "2.2.0" 375 | resolved "https://registry.npmmirror.com/@tauri-apps/plugin-autostart/-/plugin-autostart-2.2.0.tgz" 376 | integrity sha512-TzVcDZdOvdot0avkpstUWJKKEl4cyxLpFB9DZZRW5zH8k+Bv8IVJmO0zyYuw+7oKlGdHOINbD/7Je7GHMViw5w== 377 | dependencies: 378 | "@tauri-apps/api" "^2.0.0" 379 | 380 | "@tauri-apps/plugin-dialog@^2.2.0": 381 | version "2.2.0" 382 | resolved "https://registry.npmmirror.com/@tauri-apps/plugin-dialog/-/plugin-dialog-2.2.0.tgz" 383 | integrity sha512-6bLkYK68zyK31418AK5fNccCdVuRnNpbxquCl8IqgFByOgWFivbiIlvb79wpSXi0O+8k8RCSsIpOquebusRVSg== 384 | dependencies: 385 | "@tauri-apps/api" "^2.0.0" 386 | 387 | "@tauri-apps/plugin-os@^2.2.0": 388 | version "2.2.0" 389 | resolved "https://registry.npmmirror.com/@tauri-apps/plugin-os/-/plugin-os-2.2.0.tgz" 390 | integrity sha512-HszbCdbisMlu5QhCNAN8YIWyz2v33abAWha6+uvV2CKX8P5VSct/y+kEe22JeyqrxCnWlQ3DRx7s49Byg7/0EA== 391 | dependencies: 392 | "@tauri-apps/api" "^2.0.0" 393 | 394 | "@tauri-apps/plugin-shell@^2": 395 | version "2.0.1" 396 | resolved "https://registry.npmmirror.com/@tauri-apps/plugin-shell/-/plugin-shell-2.0.1.tgz" 397 | integrity sha512-akU1b77sw3qHiynrK0s930y8zKmcdrSD60htjH+mFZqv5WaakZA/XxHR3/sF1nNv9Mgmt/Shls37HwnOr00aSw== 398 | dependencies: 399 | "@tauri-apps/api" "^2.0.0" 400 | 401 | "@types/estree@1.0.6", "@types/estree@^1.0.0": 402 | version "1.0.6" 403 | resolved "https://registry.npmmirror.com/@types/estree/-/estree-1.0.6.tgz" 404 | integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== 405 | 406 | "@types/lodash-es@^4.17.6": 407 | version "4.17.12" 408 | resolved "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz" 409 | integrity sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ== 410 | dependencies: 411 | "@types/lodash" "*" 412 | 413 | "@types/lodash@*", "@types/lodash@^4.14.182": 414 | version "4.17.15" 415 | resolved "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.15.tgz" 416 | integrity sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw== 417 | 418 | "@types/web-bluetooth@^0.0.16": 419 | version "0.0.16" 420 | resolved "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz" 421 | integrity sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ== 422 | 423 | "@vitejs/plugin-vue@^5.0.5": 424 | version "5.2.1" 425 | resolved "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.1.tgz" 426 | integrity sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ== 427 | 428 | "@volar/language-core@2.4.10", "@volar/language-core@~2.4.8": 429 | version "2.4.10" 430 | resolved "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.10.tgz" 431 | integrity sha512-hG3Z13+nJmGaT+fnQzAkS0hjJRa2FCeqZt6Bd+oGNhUkQ+mTFsDETg5rqUTxyzIh5pSOGY7FHCWUS8G82AzLCA== 432 | dependencies: 433 | "@volar/source-map" "2.4.10" 434 | 435 | "@volar/source-map@2.4.10": 436 | version "2.4.10" 437 | resolved "https://registry.npmmirror.com/@volar/source-map/-/source-map-2.4.10.tgz" 438 | integrity sha512-OCV+b5ihV0RF3A7vEvNyHPi4G4kFa6ukPmyVocmqm5QzOd8r5yAtiNvaPEjl8dNvgC/lj4JPryeeHLdXd62rWA== 439 | 440 | "@volar/typescript@~2.4.8": 441 | version "2.4.10" 442 | resolved "https://registry.npmmirror.com/@volar/typescript/-/typescript-2.4.10.tgz" 443 | integrity sha512-F8ZtBMhSXyYKuBfGpYwqA5rsONnOwAVvjyE7KPYJ7wgZqo2roASqNWUnianOomJX5u1cxeRooHV59N0PhvEOgw== 444 | dependencies: 445 | "@volar/language-core" "2.4.10" 446 | path-browserify "^1.0.1" 447 | vscode-uri "^3.0.8" 448 | 449 | "@vue/compiler-core@3.5.13": 450 | version "3.5.13" 451 | resolved "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.13.tgz" 452 | integrity sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q== 453 | dependencies: 454 | "@babel/parser" "^7.25.3" 455 | "@vue/shared" "3.5.13" 456 | entities "^4.5.0" 457 | estree-walker "^2.0.2" 458 | source-map-js "^1.2.0" 459 | 460 | "@vue/compiler-dom@3.5.13", "@vue/compiler-dom@^3.5.0": 461 | version "3.5.13" 462 | resolved "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz" 463 | integrity sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA== 464 | dependencies: 465 | "@vue/compiler-core" "3.5.13" 466 | "@vue/shared" "3.5.13" 467 | 468 | "@vue/compiler-sfc@3.5.13": 469 | version "3.5.13" 470 | resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz" 471 | integrity sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ== 472 | dependencies: 473 | "@babel/parser" "^7.25.3" 474 | "@vue/compiler-core" "3.5.13" 475 | "@vue/compiler-dom" "3.5.13" 476 | "@vue/compiler-ssr" "3.5.13" 477 | "@vue/shared" "3.5.13" 478 | estree-walker "^2.0.2" 479 | magic-string "^0.30.11" 480 | postcss "^8.4.48" 481 | source-map-js "^1.2.0" 482 | 483 | "@vue/compiler-ssr@3.5.13": 484 | version "3.5.13" 485 | resolved "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz" 486 | integrity sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA== 487 | dependencies: 488 | "@vue/compiler-dom" "3.5.13" 489 | "@vue/shared" "3.5.13" 490 | 491 | "@vue/compiler-vue2@^2.7.16": 492 | version "2.7.16" 493 | resolved "https://registry.npmmirror.com/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz" 494 | integrity sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A== 495 | dependencies: 496 | de-indent "^1.0.2" 497 | he "^1.2.0" 498 | 499 | "@vue/devtools-api@^7.7.2": 500 | version "7.7.2" 501 | resolved "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-7.7.2.tgz" 502 | integrity sha512-1syn558KhyN+chO5SjlZIwJ8bV/bQ1nOVTG66t2RbG66ZGekyiYNmRO7X9BJCXQqPsFHlnksqvPhce2qpzxFnA== 503 | dependencies: 504 | "@vue/devtools-kit" "^7.7.2" 505 | 506 | "@vue/devtools-kit@^7.7.2": 507 | version "7.7.2" 508 | resolved "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-7.7.2.tgz" 509 | integrity sha512-CY0I1JH3Z8PECbn6k3TqM1Bk9ASWxeMtTCvZr7vb+CHi+X/QwQm5F1/fPagraamKMAHVfuuCbdcnNg1A4CYVWQ== 510 | dependencies: 511 | "@vue/devtools-shared" "^7.7.2" 512 | birpc "^0.2.19" 513 | hookable "^5.5.3" 514 | mitt "^3.0.1" 515 | perfect-debounce "^1.0.0" 516 | speakingurl "^14.0.1" 517 | superjson "^2.2.1" 518 | 519 | "@vue/devtools-shared@^7.7.2": 520 | version "7.7.2" 521 | resolved "https://registry.npmmirror.com/@vue/devtools-shared/-/devtools-shared-7.7.2.tgz" 522 | integrity sha512-uBFxnp8gwW2vD6FrJB8JZLUzVb6PNRG0B0jBnHsOH8uKyva2qINY8PTF5Te4QlTbMDqU5K6qtJDr6cNsKWhbOA== 523 | dependencies: 524 | rfdc "^1.4.1" 525 | 526 | "@vue/language-core@2.1.10": 527 | version "2.1.10" 528 | resolved "https://registry.npmmirror.com/@vue/language-core/-/language-core-2.1.10.tgz" 529 | integrity sha512-DAI289d0K3AB5TUG3xDp9OuQ71CnrujQwJrQnfuZDwo6eGNf0UoRlPuaVNO+Zrn65PC3j0oB2i7mNmVPggeGeQ== 530 | dependencies: 531 | "@volar/language-core" "~2.4.8" 532 | "@vue/compiler-dom" "^3.5.0" 533 | "@vue/compiler-vue2" "^2.7.16" 534 | "@vue/shared" "^3.5.0" 535 | alien-signals "^0.2.0" 536 | minimatch "^9.0.3" 537 | muggle-string "^0.4.1" 538 | path-browserify "^1.0.1" 539 | 540 | "@vue/reactivity@3.5.13": 541 | version "3.5.13" 542 | resolved "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.13.tgz" 543 | integrity sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg== 544 | dependencies: 545 | "@vue/shared" "3.5.13" 546 | 547 | "@vue/runtime-core@3.5.13": 548 | version "3.5.13" 549 | resolved "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.13.tgz" 550 | integrity sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw== 551 | dependencies: 552 | "@vue/reactivity" "3.5.13" 553 | "@vue/shared" "3.5.13" 554 | 555 | "@vue/runtime-dom@3.5.13": 556 | version "3.5.13" 557 | resolved "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz" 558 | integrity sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog== 559 | dependencies: 560 | "@vue/reactivity" "3.5.13" 561 | "@vue/runtime-core" "3.5.13" 562 | "@vue/shared" "3.5.13" 563 | csstype "^3.1.3" 564 | 565 | "@vue/server-renderer@3.5.13": 566 | version "3.5.13" 567 | resolved "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.13.tgz" 568 | integrity sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA== 569 | dependencies: 570 | "@vue/compiler-ssr" "3.5.13" 571 | "@vue/shared" "3.5.13" 572 | 573 | "@vue/shared@3.5.13", "@vue/shared@^3.5.0": 574 | version "3.5.13" 575 | resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.13.tgz" 576 | integrity sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ== 577 | 578 | "@vueuse/core@^9.1.0": 579 | version "9.13.0" 580 | resolved "https://registry.npmmirror.com/@vueuse/core/-/core-9.13.0.tgz" 581 | integrity sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw== 582 | dependencies: 583 | "@types/web-bluetooth" "^0.0.16" 584 | "@vueuse/metadata" "9.13.0" 585 | "@vueuse/shared" "9.13.0" 586 | vue-demi "*" 587 | 588 | "@vueuse/metadata@9.13.0": 589 | version "9.13.0" 590 | resolved "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz" 591 | integrity sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ== 592 | 593 | "@vueuse/shared@9.13.0": 594 | version "9.13.0" 595 | resolved "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.13.0.tgz" 596 | integrity sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw== 597 | dependencies: 598 | vue-demi "*" 599 | 600 | acorn@^8.14.0: 601 | version "8.14.0" 602 | resolved "https://registry.npmmirror.com/acorn/-/acorn-8.14.0.tgz" 603 | integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== 604 | 605 | alien-signals@^0.2.0: 606 | version "0.2.2" 607 | resolved "https://registry.npmmirror.com/alien-signals/-/alien-signals-0.2.2.tgz" 608 | integrity sha512-cZIRkbERILsBOXTQmMrxc9hgpxglstn69zm+F1ARf4aPAzdAFYd6sBq87ErO0Fj3DV94tglcyHG5kQz9nDC/8A== 609 | 610 | anymatch@~3.1.2: 611 | version "3.1.3" 612 | resolved "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz" 613 | integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== 614 | dependencies: 615 | normalize-path "^3.0.0" 616 | picomatch "^2.0.4" 617 | 618 | async-validator@^4.2.5: 619 | version "4.2.5" 620 | resolved "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz" 621 | integrity sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg== 622 | 623 | babel-plugin-component@^1.1.1: 624 | version "1.1.1" 625 | resolved "https://registry.npmmirror.com/babel-plugin-component/-/babel-plugin-component-1.1.1.tgz" 626 | integrity sha512-WUw887kJf2GH80Ng/ZMctKZ511iamHNqPhd9uKo14yzisvV7Wt1EckIrb8oq/uCz3B3PpAW7Xfl7AkTLDYT6ag== 627 | dependencies: 628 | "@babel/helper-module-imports" "7.0.0-beta.35" 629 | 630 | balanced-match@^1.0.0: 631 | version "1.0.2" 632 | resolved "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz" 633 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 634 | 635 | binary-extensions@^2.0.0: 636 | version "2.3.0" 637 | resolved "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz" 638 | integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== 639 | 640 | birpc@^0.2.19: 641 | version "0.2.19" 642 | resolved "https://registry.npmmirror.com/birpc/-/birpc-0.2.19.tgz" 643 | integrity sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ== 644 | 645 | brace-expansion@^2.0.1: 646 | version "2.0.1" 647 | resolved "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz" 648 | integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== 649 | dependencies: 650 | balanced-match "^1.0.0" 651 | 652 | braces@~3.0.2: 653 | version "3.0.3" 654 | resolved "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz" 655 | integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== 656 | dependencies: 657 | fill-range "^7.1.1" 658 | 659 | chokidar@^3.6.0: 660 | version "3.6.0" 661 | resolved "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz" 662 | integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== 663 | dependencies: 664 | anymatch "~3.1.2" 665 | braces "~3.0.2" 666 | glob-parent "~5.1.2" 667 | is-binary-path "~2.1.0" 668 | is-glob "~4.0.1" 669 | normalize-path "~3.0.0" 670 | readdirp "~3.6.0" 671 | optionalDependencies: 672 | fsevents "~2.3.2" 673 | 674 | confbox@^0.1.8: 675 | version "0.1.8" 676 | resolved "https://registry.npmmirror.com/confbox/-/confbox-0.1.8.tgz" 677 | integrity sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== 678 | 679 | copy-anything@^3.0.2: 680 | version "3.0.5" 681 | resolved "https://registry.npmmirror.com/copy-anything/-/copy-anything-3.0.5.tgz" 682 | integrity sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w== 683 | dependencies: 684 | is-what "^4.1.8" 685 | 686 | csstype@^3.1.3: 687 | version "3.1.3" 688 | resolved "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz" 689 | integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== 690 | 691 | dayjs@^1.11.13: 692 | version "1.11.13" 693 | resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz" 694 | integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== 695 | 696 | de-indent@^1.0.2: 697 | version "1.0.2" 698 | resolved "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz" 699 | integrity sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg== 700 | 701 | debug@^4.4.0: 702 | version "4.4.0" 703 | resolved "https://registry.npmmirror.com/debug/-/debug-4.4.0.tgz" 704 | integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== 705 | dependencies: 706 | ms "^2.1.3" 707 | 708 | element-plus@^2.9.5: 709 | version "2.9.5" 710 | resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.9.5.tgz" 711 | integrity sha512-r+X79oogLbYq8p9L5f9fHSHhUFNM0AL72aikqiZVxSc2/08mK6m/PotiB9e/D90QmWTIHIaFnFmW65AcXmneig== 712 | dependencies: 713 | "@ctrl/tinycolor" "^3.4.1" 714 | "@element-plus/icons-vue" "^2.3.1" 715 | "@floating-ui/dom" "^1.0.1" 716 | "@popperjs/core" "npm:@sxzz/popperjs-es@^2.11.7" 717 | "@types/lodash" "^4.14.182" 718 | "@types/lodash-es" "^4.17.6" 719 | "@vueuse/core" "^9.1.0" 720 | async-validator "^4.2.5" 721 | dayjs "^1.11.13" 722 | escape-html "^1.0.3" 723 | lodash "^4.17.21" 724 | lodash-es "^4.17.21" 725 | lodash-unified "^1.0.2" 726 | memoize-one "^6.0.0" 727 | normalize-wheel-es "^1.2.0" 728 | 729 | entities@^4.5.0: 730 | version "4.5.0" 731 | resolved "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz" 732 | integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== 733 | 734 | esbuild@^0.21.3: 735 | version "0.21.5" 736 | resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz" 737 | integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== 738 | optionalDependencies: 739 | "@esbuild/aix-ppc64" "0.21.5" 740 | "@esbuild/android-arm" "0.21.5" 741 | "@esbuild/android-arm64" "0.21.5" 742 | "@esbuild/android-x64" "0.21.5" 743 | "@esbuild/darwin-arm64" "0.21.5" 744 | "@esbuild/darwin-x64" "0.21.5" 745 | "@esbuild/freebsd-arm64" "0.21.5" 746 | "@esbuild/freebsd-x64" "0.21.5" 747 | "@esbuild/linux-arm" "0.21.5" 748 | "@esbuild/linux-arm64" "0.21.5" 749 | "@esbuild/linux-ia32" "0.21.5" 750 | "@esbuild/linux-loong64" "0.21.5" 751 | "@esbuild/linux-mips64el" "0.21.5" 752 | "@esbuild/linux-ppc64" "0.21.5" 753 | "@esbuild/linux-riscv64" "0.21.5" 754 | "@esbuild/linux-s390x" "0.21.5" 755 | "@esbuild/linux-x64" "0.21.5" 756 | "@esbuild/netbsd-x64" "0.21.5" 757 | "@esbuild/openbsd-x64" "0.21.5" 758 | "@esbuild/sunos-x64" "0.21.5" 759 | "@esbuild/win32-arm64" "0.21.5" 760 | "@esbuild/win32-ia32" "0.21.5" 761 | "@esbuild/win32-x64" "0.21.5" 762 | 763 | escape-html@^1.0.3: 764 | version "1.0.3" 765 | resolved "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz" 766 | integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== 767 | 768 | escape-string-regexp@^5.0.0: 769 | version "5.0.0" 770 | resolved "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz" 771 | integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== 772 | 773 | estree-walker@^2.0.2: 774 | version "2.0.2" 775 | resolved "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz" 776 | integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== 777 | 778 | estree-walker@^3.0.3: 779 | version "3.0.3" 780 | resolved "https://registry.npmmirror.com/estree-walker/-/estree-walker-3.0.3.tgz" 781 | integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== 782 | dependencies: 783 | "@types/estree" "^1.0.0" 784 | 785 | esutils@^2.0.2: 786 | version "2.0.3" 787 | resolved "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz" 788 | integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== 789 | 790 | fdir@^6.4.3: 791 | version "6.4.3" 792 | resolved "https://registry.npmmirror.com/fdir/-/fdir-6.4.3.tgz" 793 | integrity sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw== 794 | 795 | fill-range@^7.1.1: 796 | version "7.1.1" 797 | resolved "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz" 798 | integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== 799 | dependencies: 800 | to-regex-range "^5.0.1" 801 | 802 | fsevents@~2.3.2, fsevents@~2.3.3: 803 | version "2.3.3" 804 | resolved "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" 805 | integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== 806 | 807 | glob-parent@~5.1.2: 808 | version "5.1.2" 809 | resolved "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz" 810 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 811 | dependencies: 812 | is-glob "^4.0.1" 813 | 814 | he@^1.2.0: 815 | version "1.2.0" 816 | resolved "https://registry.npmmirror.com/he/-/he-1.2.0.tgz" 817 | integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== 818 | 819 | hookable@^5.5.3: 820 | version "5.5.3" 821 | resolved "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz" 822 | integrity sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ== 823 | 824 | is-binary-path@~2.1.0: 825 | version "2.1.0" 826 | resolved "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz" 827 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 828 | dependencies: 829 | binary-extensions "^2.0.0" 830 | 831 | is-extglob@^2.1.1: 832 | version "2.1.1" 833 | resolved "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz" 834 | integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 835 | 836 | is-glob@^4.0.1, is-glob@~4.0.1: 837 | version "4.0.3" 838 | resolved "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz" 839 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 840 | dependencies: 841 | is-extglob "^2.1.1" 842 | 843 | is-number@^7.0.0: 844 | version "7.0.0" 845 | resolved "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz" 846 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 847 | 848 | is-what@^4.1.8: 849 | version "4.1.16" 850 | resolved "https://registry.npmmirror.com/is-what/-/is-what-4.1.16.tgz" 851 | integrity sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A== 852 | 853 | js-tokens@^9.0.1: 854 | version "9.0.1" 855 | resolved "https://registry.npmmirror.com/js-tokens/-/js-tokens-9.0.1.tgz" 856 | integrity sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ== 857 | 858 | local-pkg@^1.0.0: 859 | version "1.0.0" 860 | resolved "https://registry.npmmirror.com/local-pkg/-/local-pkg-1.0.0.tgz" 861 | integrity sha512-bbgPw/wmroJsil/GgL4qjDzs5YLTBMQ99weRsok1XCDccQeehbHA/I1oRvk2NPtr7KGZgT/Y5tPRnAtMqeG2Kg== 862 | dependencies: 863 | mlly "^1.7.3" 864 | pkg-types "^1.3.0" 865 | 866 | lodash-es@^4.17.21: 867 | version "4.17.21" 868 | resolved "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz" 869 | integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== 870 | 871 | lodash-unified@^1.0.2: 872 | version "1.0.3" 873 | resolved "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz" 874 | integrity sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ== 875 | 876 | lodash@^4.17.21, lodash@^4.2.0: 877 | version "4.17.21" 878 | resolved "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz" 879 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 880 | 881 | magic-string@^0.30.11, magic-string@^0.30.17: 882 | version "0.30.17" 883 | resolved "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.17.tgz" 884 | integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA== 885 | dependencies: 886 | "@jridgewell/sourcemap-codec" "^1.5.0" 887 | 888 | memoize-one@^6.0.0: 889 | version "6.0.0" 890 | resolved "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz" 891 | integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw== 892 | 893 | minimatch@^9.0.3: 894 | version "9.0.5" 895 | resolved "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz" 896 | integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== 897 | dependencies: 898 | brace-expansion "^2.0.1" 899 | 900 | mitt@^3.0.1: 901 | version "3.0.1" 902 | resolved "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz" 903 | integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== 904 | 905 | mlly@^1.7.3, mlly@^1.7.4: 906 | version "1.7.4" 907 | resolved "https://registry.npmmirror.com/mlly/-/mlly-1.7.4.tgz" 908 | integrity sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw== 909 | dependencies: 910 | acorn "^8.14.0" 911 | pathe "^2.0.1" 912 | pkg-types "^1.3.0" 913 | ufo "^1.5.4" 914 | 915 | ms@^2.1.3: 916 | version "2.1.3" 917 | resolved "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz" 918 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 919 | 920 | muggle-string@^0.4.1: 921 | version "0.4.1" 922 | resolved "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz" 923 | integrity sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ== 924 | 925 | nanoid@^3.3.7: 926 | version "3.3.8" 927 | resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.8.tgz" 928 | integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== 929 | 930 | normalize-path@^3.0.0, normalize-path@~3.0.0: 931 | version "3.0.0" 932 | resolved "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz" 933 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 934 | 935 | normalize-wheel-es@^1.2.0: 936 | version "1.2.0" 937 | resolved "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz" 938 | integrity sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw== 939 | 940 | path-browserify@^1.0.1: 941 | version "1.0.1" 942 | resolved "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz" 943 | integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== 944 | 945 | pathe@^2.0.1, pathe@^2.0.2, pathe@^2.0.3: 946 | version "2.0.3" 947 | resolved "https://registry.npmmirror.com/pathe/-/pathe-2.0.3.tgz" 948 | integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== 949 | 950 | perfect-debounce@^1.0.0: 951 | version "1.0.0" 952 | resolved "https://registry.npmmirror.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz" 953 | integrity sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA== 954 | 955 | picocolors@^1.1.1: 956 | version "1.1.1" 957 | resolved "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz" 958 | integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== 959 | 960 | picomatch@^2.0.4, picomatch@^2.2.1: 961 | version "2.3.1" 962 | resolved "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz" 963 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 964 | 965 | picomatch@^4.0.2: 966 | version "4.0.2" 967 | resolved "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.2.tgz" 968 | integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== 969 | 970 | pinia@^3.0.1: 971 | version "3.0.1" 972 | resolved "https://registry.npmmirror.com/pinia/-/pinia-3.0.1.tgz" 973 | integrity sha512-WXglsDzztOTH6IfcJ99ltYZin2mY8XZCXujkYWVIJlBjqsP6ST7zw+Aarh63E1cDVYeyUcPCxPHzJpEOmzB6Wg== 974 | dependencies: 975 | "@vue/devtools-api" "^7.7.2" 976 | 977 | pkg-types@^1.3.0, pkg-types@^1.3.1: 978 | version "1.3.1" 979 | resolved "https://registry.npmmirror.com/pkg-types/-/pkg-types-1.3.1.tgz" 980 | integrity sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ== 981 | dependencies: 982 | confbox "^0.1.8" 983 | mlly "^1.7.4" 984 | pathe "^2.0.1" 985 | 986 | postcss@^8.4.43, postcss@^8.4.48: 987 | version "8.4.49" 988 | resolved "https://registry.npmmirror.com/postcss/-/postcss-8.4.49.tgz" 989 | integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA== 990 | dependencies: 991 | nanoid "^3.3.7" 992 | picocolors "^1.1.1" 993 | source-map-js "^1.2.1" 994 | 995 | readdirp@~3.6.0: 996 | version "3.6.0" 997 | resolved "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz" 998 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== 999 | dependencies: 1000 | picomatch "^2.2.1" 1001 | 1002 | rfdc@^1.4.1: 1003 | version "1.4.1" 1004 | resolved "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz" 1005 | integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== 1006 | 1007 | rollup@^4.20.0: 1008 | version "4.28.0" 1009 | resolved "https://registry.npmmirror.com/rollup/-/rollup-4.28.0.tgz" 1010 | integrity sha512-G9GOrmgWHBma4YfCcX8PjH0qhXSdH8B4HDE2o4/jaxj93S4DPCIDoLcXz99eWMji4hB29UFCEd7B2gwGJDR9cQ== 1011 | dependencies: 1012 | "@types/estree" "1.0.6" 1013 | optionalDependencies: 1014 | "@rollup/rollup-android-arm-eabi" "4.28.0" 1015 | "@rollup/rollup-android-arm64" "4.28.0" 1016 | "@rollup/rollup-darwin-arm64" "4.28.0" 1017 | "@rollup/rollup-darwin-x64" "4.28.0" 1018 | "@rollup/rollup-freebsd-arm64" "4.28.0" 1019 | "@rollup/rollup-freebsd-x64" "4.28.0" 1020 | "@rollup/rollup-linux-arm-gnueabihf" "4.28.0" 1021 | "@rollup/rollup-linux-arm-musleabihf" "4.28.0" 1022 | "@rollup/rollup-linux-arm64-gnu" "4.28.0" 1023 | "@rollup/rollup-linux-arm64-musl" "4.28.0" 1024 | "@rollup/rollup-linux-powerpc64le-gnu" "4.28.0" 1025 | "@rollup/rollup-linux-riscv64-gnu" "4.28.0" 1026 | "@rollup/rollup-linux-s390x-gnu" "4.28.0" 1027 | "@rollup/rollup-linux-x64-gnu" "4.28.0" 1028 | "@rollup/rollup-linux-x64-musl" "4.28.0" 1029 | "@rollup/rollup-win32-arm64-msvc" "4.28.0" 1030 | "@rollup/rollup-win32-ia32-msvc" "4.28.0" 1031 | "@rollup/rollup-win32-x64-msvc" "4.28.0" 1032 | fsevents "~2.3.2" 1033 | 1034 | scule@^1.3.0: 1035 | version "1.3.0" 1036 | resolved "https://registry.npmmirror.com/scule/-/scule-1.3.0.tgz" 1037 | integrity sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g== 1038 | 1039 | semver@^7.5.4: 1040 | version "7.6.3" 1041 | resolved "https://registry.npmmirror.com/semver/-/semver-7.6.3.tgz" 1042 | integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== 1043 | 1044 | source-map-js@^1.2.0, source-map-js@^1.2.1: 1045 | version "1.2.1" 1046 | resolved "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz" 1047 | integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== 1048 | 1049 | speakingurl@^14.0.1: 1050 | version "14.0.1" 1051 | resolved "https://registry.npmmirror.com/speakingurl/-/speakingurl-14.0.1.tgz" 1052 | integrity sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ== 1053 | 1054 | strip-literal@^3.0.0: 1055 | version "3.0.0" 1056 | resolved "https://registry.npmmirror.com/strip-literal/-/strip-literal-3.0.0.tgz" 1057 | integrity sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA== 1058 | dependencies: 1059 | js-tokens "^9.0.1" 1060 | 1061 | superjson@^2.2.1: 1062 | version "2.2.2" 1063 | resolved "https://registry.npmmirror.com/superjson/-/superjson-2.2.2.tgz" 1064 | integrity sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q== 1065 | dependencies: 1066 | copy-anything "^3.0.2" 1067 | 1068 | tinyglobby@^0.2.11, tinyglobby@^0.2.12: 1069 | version "0.2.12" 1070 | resolved "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.12.tgz" 1071 | integrity sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww== 1072 | dependencies: 1073 | fdir "^6.4.3" 1074 | picomatch "^4.0.2" 1075 | 1076 | to-fast-properties@^2.0.0: 1077 | version "2.0.0" 1078 | resolved "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz" 1079 | integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== 1080 | 1081 | to-regex-range@^5.0.1: 1082 | version "5.0.1" 1083 | resolved "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz" 1084 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1085 | dependencies: 1086 | is-number "^7.0.0" 1087 | 1088 | typescript@^5.2.2: 1089 | version "5.7.2" 1090 | resolved "https://registry.npmmirror.com/typescript/-/typescript-5.7.2.tgz" 1091 | integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg== 1092 | 1093 | ufo@^1.5.4: 1094 | version "1.5.4" 1095 | resolved "https://registry.npmmirror.com/ufo/-/ufo-1.5.4.tgz" 1096 | integrity sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ== 1097 | 1098 | unimport@^4.1.2: 1099 | version "4.1.2" 1100 | resolved "https://registry.npmmirror.com/unimport/-/unimport-4.1.2.tgz" 1101 | integrity sha512-oVUL7PSlyVV3QRhsdcyYEMaDX8HJyS/CnUonEJTYA3//bWO+o/4gG8F7auGWWWkrrxBQBYOO8DKe+C53ktpRXw== 1102 | dependencies: 1103 | acorn "^8.14.0" 1104 | escape-string-regexp "^5.0.0" 1105 | estree-walker "^3.0.3" 1106 | local-pkg "^1.0.0" 1107 | magic-string "^0.30.17" 1108 | mlly "^1.7.4" 1109 | pathe "^2.0.3" 1110 | picomatch "^4.0.2" 1111 | pkg-types "^1.3.1" 1112 | scule "^1.3.0" 1113 | strip-literal "^3.0.0" 1114 | tinyglobby "^0.2.11" 1115 | unplugin "^2.2.0" 1116 | unplugin-utils "^0.2.4" 1117 | 1118 | unplugin-auto-import@^19.1.1: 1119 | version "19.1.1" 1120 | resolved "https://registry.npmmirror.com/unplugin-auto-import/-/unplugin-auto-import-19.1.1.tgz" 1121 | integrity sha512-sCGZZrSR1Bc8RfN8Q0RUDxXtC20rdAt7UB4lDyq8MNtKVHiXXh+5af6Nz4JRp9Q+7HjnbgQfQox0TkEymjdUAQ== 1122 | dependencies: 1123 | local-pkg "^1.0.0" 1124 | magic-string "^0.30.17" 1125 | picomatch "^4.0.2" 1126 | unimport "^4.1.2" 1127 | unplugin "^2.2.0" 1128 | unplugin-utils "^0.2.4" 1129 | 1130 | unplugin-utils@^0.2.4: 1131 | version "0.2.4" 1132 | resolved "https://registry.npmmirror.com/unplugin-utils/-/unplugin-utils-0.2.4.tgz" 1133 | integrity sha512-8U/MtpkPkkk3Atewj1+RcKIjb5WBimZ/WSLhhR3w6SsIj8XJuKTacSP8g+2JhfSGw0Cb125Y+2zA/IzJZDVbhA== 1134 | dependencies: 1135 | pathe "^2.0.2" 1136 | picomatch "^4.0.2" 1137 | 1138 | unplugin-vue-components@^28.4.1: 1139 | version "28.4.1" 1140 | resolved "https://registry.npmmirror.com/unplugin-vue-components/-/unplugin-vue-components-28.4.1.tgz" 1141 | integrity sha512-niGSc0vJD9ueAnsqcfAldmtpkppZ09B6p2G1dL7X5S8KPdgbk1P+txPwaaDCe7N+eZh2VG1aAypLXkuJs3OSUg== 1142 | dependencies: 1143 | chokidar "^3.6.0" 1144 | debug "^4.4.0" 1145 | local-pkg "^1.0.0" 1146 | magic-string "^0.30.17" 1147 | mlly "^1.7.4" 1148 | tinyglobby "^0.2.12" 1149 | unplugin "^2.2.0" 1150 | unplugin-utils "^0.2.4" 1151 | 1152 | unplugin@^2.2.0: 1153 | version "2.2.0" 1154 | resolved "https://registry.npmmirror.com/unplugin/-/unplugin-2.2.0.tgz" 1155 | integrity sha512-m1ekpSwuOT5hxkJeZGRxO7gXbXT3gF26NjQ7GdVHoLoF8/nopLcd/QfPigpCy7i51oFHiRJg/CyHhj4vs2+KGw== 1156 | dependencies: 1157 | acorn "^8.14.0" 1158 | webpack-virtual-modules "^0.6.2" 1159 | 1160 | vite@^5.3.1: 1161 | version "5.4.11" 1162 | resolved "https://registry.npmmirror.com/vite/-/vite-5.4.11.tgz" 1163 | integrity sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q== 1164 | dependencies: 1165 | esbuild "^0.21.3" 1166 | postcss "^8.4.43" 1167 | rollup "^4.20.0" 1168 | optionalDependencies: 1169 | fsevents "~2.3.3" 1170 | 1171 | vscode-uri@^3.0.8: 1172 | version "3.0.8" 1173 | resolved "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.0.8.tgz" 1174 | integrity sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw== 1175 | 1176 | vue-demi@*: 1177 | version "0.14.10" 1178 | resolved "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz" 1179 | integrity sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg== 1180 | 1181 | vue-toastification@^2.0.0-rc.5: 1182 | version "2.0.0-rc.5" 1183 | resolved "https://registry.npmmirror.com/vue-toastification/-/vue-toastification-2.0.0-rc.5.tgz" 1184 | integrity sha512-q73e5jy6gucEO/U+P48hqX+/qyXDozAGmaGgLFm5tXX4wJBcVsnGp4e/iJqlm9xzHETYOilUuwOUje2Qg1JdwA== 1185 | 1186 | vue-tsc@^2.1.10: 1187 | version "2.1.10" 1188 | resolved "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-2.1.10.tgz" 1189 | integrity sha512-RBNSfaaRHcN5uqVqJSZh++Gy/YUzryuv9u1aFWhsammDJXNtUiJMNoJ747lZcQ68wUQFx6E73y4FY3D8E7FGMA== 1190 | dependencies: 1191 | "@volar/typescript" "~2.4.8" 1192 | "@vue/language-core" "2.1.10" 1193 | semver "^7.5.4" 1194 | 1195 | vue@^3.3.4: 1196 | version "3.5.13" 1197 | resolved "https://registry.npmmirror.com/vue/-/vue-3.5.13.tgz" 1198 | integrity sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ== 1199 | dependencies: 1200 | "@vue/compiler-dom" "3.5.13" 1201 | "@vue/compiler-sfc" "3.5.13" 1202 | "@vue/runtime-dom" "3.5.13" 1203 | "@vue/server-renderer" "3.5.13" 1204 | "@vue/shared" "3.5.13" 1205 | 1206 | webpack-virtual-modules@^0.6.2: 1207 | version "0.6.2" 1208 | resolved "https://registry.npmmirror.com/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz" 1209 | integrity sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ== 1210 | --------------------------------------------------------------------------------