diff --git a/.cursor/rules/aiclient-overview.mdc b/.cursor/rules/aiclient-overview.mdc index bd71bea..9e80d8a 100644 --- a/.cursor/rules/aiclient-overview.mdc +++ b/.cursor/rules/aiclient-overview.mdc @@ -5,32 +5,20 @@ alwaysApply: true # aiclient 项目约定 -## 技术栈 +## 仓库拆分 -- **桌面壳**:Tauri 2(Rust),单例、无边框、可拖动标题栏 -- **前端**:Vue 3 + Vite 6,**纯 JavaScript**(不使用 TypeScript) -- **UI**:Tailwind CSS v4(`@tailwindcss/vite`)+ PrimeVue 4(Aura 深色预设) -- **状态/路由**:Pinia + Vue Router +| 仓库 | 职责 | +|------|------| +| **aiclient**(本仓库) | Tauri 2 桌面壳、Rust 业务、updater、打包 | +| **aiclient_ui**(`../aiclient_ui`) | Vue 3 前端,Vite 开发/构建 | -## 目录结构 - -``` -src/ # Vue 前端 - main.js # 入口:插件与全局组件注册 - App.vue # 布局:标题栏 + router-view - styles/main.css # Tailwind + 科技感主题令牌 - router/ # 路由与守卫 - stores/ # Pinia(auth 等) - views/ # 页面 - components/ # 可复用组件 -src-tauri/ # Tauri Rust 与配置 -``` +`tauri.conf.json` 的 `frontendDist` 为占位目录 `frontend-stub`,**发布构建不编译前端**;运行时加载服务器上的 HTML/CSS/JS(见 `lib.rs` 中 `PROD_WEB_URL`)。前端开发/部署在 **aiclient_ui** 仓库。 ## 常用命令 -- `npm run dev` — 仅前端(端口 1420) -- `npm run tauri dev` — 桌面开发 -- `npm run build` / `npm run tauri:build` — 构建桌面端(仅生成 zip 便携包,不生成 MSI/NSIS 安装包;前端无 `tsc` 步骤) +- 在 **aiclient_ui**:`npm run dev` — 仅 Web;`npm run build:deploy` — 部署到服务器静态目录 +- 在 **aiclient**:`npm run dev` — `tauri dev`(调试时连本地 Vite) +- 在 **aiclient**:`npm run tauri:build` — 仅打包 Rust/updater,不构建前端 ## 后端 API 约定(pythonbackend) @@ -38,55 +26,23 @@ src-tauri/ # Tauri Rust 与配置 ### 统一响应 `ApiResponse` -所有 JSON 响应使用同一信封(与 `app/schemas/common.py` 一致): - | 字段 | 类型 | 说明 | |------|------|------| -| `ok` | `boolean` | `true` 表示业务成功,`false` 表示失败(如校验、鉴权、业务错误) | -| `message` | `string` | 提示文案,默认可为空;失败时展示给用户 | -| `data` | `T \| null` | 成功时的载荷;失败时通常为 `null` 或省略 | +| `ok` | `boolean` | 业务是否成功 | +| `message` | `string` | 用户可见提示 | +| `data` | `T \| null` | 成功载荷 | -前端处理模式: - -```js -const body = await res.json(); -if (!body.ok) { - // 用 body.message 提示用户 - return { ok: false, message: body.message }; -} -// 使用 body.data -``` - -- 业务失败(如用户名已存在)仍返回 **HTTP 200**,以 `ok: false` 区分,勿仅依赖状态码。 -- 未认证访问受保护接口返回 **HTTP 401**(FastAPI 标准错误体,非 `ApiResponse` 信封)。 +业务失败仍返回 **HTTP 200** + `ok: false`。未认证返回 **401**。 ### 认证 -- 登录/注册成功后,`data` 为 `TokenResponse`: - - `access_token`:JWT,前端持久化(如 localStorage `aiclient_token`) - - `token_type`:固定 `"bearer"` - - `user`:`{ id, username }` -- 需登录的请求请求头:`Authorization: Bearer ` -- 登出:`POST /api/v1/auth/logout`,带同上 Authorization;成功 `ok: true`,`message`: `"已退出登录"` +- JWT:`Authorization: Bearer ` +- 登出:`POST /api/v1/auth/logout` -### 认证相关端点 +### 环境 -| 方法 | 路径 | 请求体 | `data`(成功时) | -|------|------|--------|------------------| -| POST | `/api/v1/auth/register` | `{ username, password, confirmPassword }` | `TokenResponse` | -| POST | `/api/v1/auth/login` | `{ username, password }` | `TokenResponse` | -| POST | `/api/v1/auth/logout` | 无 | `null` | -| GET | `/api/v1/auth/me` | 无 | `{ id, username }` | - -- 注册请求体字段名与前端表单一致:`confirmPassword`(camelCase);其余 API JSON 字段为 **snake_case**(如 `access_token`)。 -- 密码规则与本地逻辑对齐:至少 6 位;用户名 trim 后非空。 - - -### 前端对接注意 - -- Pinia `auth` store 的 `login` / `register` 可逐步改为调用上述 API,保留 `{ ok, message }` 与视图层一致。 -- 开发时后端需配置 CORS 包含 `http://localhost:1420`(见 pythonbackend `.env` 的 `CORS_ORIGINS`)。 -- 开发时 Vite 将 `/api` 代理到 `http://127.0.0.1:8001`(见 `vite.config.js`);API 基址默认 `/api/v1`,生产可设 `VITE_API_BASE_URL`。 +- 前端 `VITE_*`:aiclient_ui 的 `.env` +- Rust `AICLIENT_*`:aiclient 根目录 `.env` ## 通用原则 diff --git a/.cursor/rules/tauri-desktop.mdc b/.cursor/rules/tauri-desktop.mdc index 70059a7..5cdf56a 100644 --- a/.cursor/rules/tauri-desktop.mdc +++ b/.cursor/rules/tauri-desktop.mdc @@ -31,7 +31,7 @@ alwaysApply: false ## 权限(`capabilities/default.json`) - 拖动窗口需:`core:window:allow-start-dragging` -- 前端标题栏元素使用 `data-tauri-drag-region`(在 `AppTitlebar.vue`) +- 前端标题栏元素使用 `data-tauri-drag-region`(在 aiclient_ui 的 `AppTitlebar.vue`) ## Rust 约定 @@ -41,6 +41,6 @@ alwaysApply: false ## 开发注意 -- Vite 固定端口 `1420`(见 `vite.config.js`),与 `tauri.conf.json` 的 `devUrl` 一致 +前端在 **`../aiclient_ui`** 开发并 **`npm run build:deploy`** 部署到服务器;**`tauri build` 不编译前端**。发布版 WebView 加载 `http://81.71.163.140/images/newyaoyan/`(见 `lib.rs`)。 - 修改 capabilities 或插件后需重新 `tauri dev` / `tauri:build` - 发布构建使用 `npm run tauri:build`:`bundle.targets` 为空,跳过 MSI/NSIS;构建结束后由 `src-tauri/scripts/zip-portable.cjs` 生成 `target/release/bundle/zip/*.zip` diff --git a/.env.example b/.env.example index 0e279c2..20ff1ed 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,3 @@ -# 开发默认走 Vite 代理 /api -> http://127.0.0.1:8001 -VITE_API_BASE_URL=http://81.70.234.81:8001/api/v1 - # Tauri Rust 请求后端基址(拉取 appConfig、脚本等) AICLIENT_API_BASE=http://81.70.234.81:8001 diff --git a/.env.production b/.env.production index 524c8b7..bd55896 100644 --- a/.env.production +++ b/.env.production @@ -1,13 +1,2 @@ -# 开发默认走 Vite 代理 /api -> http://127.0.0.1:8001 -VITE_API_BASE_URL=http://81.71.163.140:8001/api/v1 - - -# Tauri Rust 请求后端基址(拉取 appConfig、脚本等) +# Tauri Rust 请求后端基址 AICLIENT_API_BASE=http://81.71.163.140:8001 - -# ffmpeg(抖音流水线提音频必需):放入 src-tauri/binaries/ffmpeg.exe 或设置绝对路径 -# AICLIENT_FFMPEG_PATH=C:/path/to/ffmpeg.exe - -# 应用配置在 pythonbackend 的 MySQL 表 desktop_configs(name/value), -# 登录后自动同步;Node 流水线通过环境变量 AICLIENT_CFG_ 读取。 -# 常用键示例:LLM_API_KEY、LLM_API_URL、LLM_MODEL_ID、ASR_MODE、DASHSCOPE_API_KEY、OSS_CONFIG(JSON) diff --git a/.gitignore b/.gitignore index 7d93caf..eb5e0dc 100644 --- a/.gitignore +++ b/.gitignore @@ -11,9 +11,6 @@ lerna-debug.log* *.otf *.ttf node_modules -dist -dist-ssr -*.local # Editor directories and files .vscode/* @@ -35,4 +32,5 @@ src-tauri/resources/pythonruntimebackup/ src-tauri/resources/eSpeak/ src-tauri/permissions/autogenerated/ -root/yaoyan/yaoyan_admin/images/ +# 前端构建产物在 aiclient_ui 仓库(本仓库不打包前端) +../aiclient_ui/dist diff --git a/README.md b/README.md index b381dcf..6672007 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,25 @@ -# Tauri + Vanilla TS +# aiclient -This template should help get you started developing with Tauri in vanilla HTML, CSS and Typescript. +Tauri 2 桌面壳(Rust)+ 自动更新(updater)。 -## Recommended IDE Setup +前端代码已拆至同级目录 **[aiclient_ui](../aiclient_ui)**。 -- [VS Code](https://code.visualstudio.com/) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) +## 目录结构 + +``` +src-tauri/ # Rust、Tauri 配置、资源与脚本 +``` + +## 常用命令 + +```bash +npm install +npm run dev # tauri dev(调试时连 ../aiclient_ui 的 Vite) +npm run tauri:build # 仅打包桌面壳,不构建前端 +``` + +发布前请在 **aiclient_ui** 执行 `npm run build:deploy`,将静态资源部署到服务器。 + +## 环境变量 + +见 `.env.example`(`AICLIENT_*` 为 Rust 侧配置)。前端 `VITE_*` 见 aiclient_ui 仓库。 diff --git a/aiclient.code-workspace b/aiclient.code-workspace index 6bb14d3..aca9c75 100644 --- a/aiclient.code-workspace +++ b/aiclient.code-workspace @@ -11,6 +11,12 @@ }, { "path": "src-tauri/resources/resources-bundles/python-runtimebackup" + }, + { + "path": "../aiclient_ui" + }, + { + "path": "../npmrelease" } ], "settings": {} diff --git a/index.html b/index.html deleted file mode 100644 index 34643ac..0000000 --- a/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - aiclient - - -
- - - diff --git a/package-lock.json b/package-lock.json index 7c24926..924e353 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,1190 +6,8 @@ "packages": { "": { "name": "aiclient", - "version": "0.1.0", - "dependencies": { - "@primeuix/themes": "^1.2.1", - "@tauri-apps/api": "^2", - "@tauri-apps/plugin-dialog": "^2.7.1", - "@tauri-apps/plugin-opener": "^2", - "monaco-editor": "^0.55.1", - "monaco-editor-vue3": "^1.0.5", - "pinia": "^3.0.3", - "primeicons": "^7.0.0", - "primevue": "^4.3.6", - "vue": "^3.5.17", - "vue-router": "^4.5.1" - }, "devDependencies": { - "@tailwindcss/vite": "^4.1.11", - "@tauri-apps/cli": "^2", - "@vitejs/plugin-vue": "^6.0.0", - "autoprefixer": "^10.4.21", - "postcss": "^8.5.6", - "tailwindcss": "^4.1.11", - "vite": "^6.0.3", - "vite-plugin-monaco-editor": "^1.1.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.29.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", - "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", - "dependencies": { - "@babel/types": "^7.29.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@primeuix/styled": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/@primeuix/styled/-/styled-0.7.4.tgz", - "integrity": "sha512-QSO/NpOQg8e9BONWRBx9y8VGMCMYz0J/uKfNJEya/RGEu7ARx0oYW0ugI1N3/KB1AAvyGxzKBzGImbwg0KUiOQ==", - "dependencies": { - "@primeuix/utils": "^0.6.1" - }, - "engines": { - "node": ">=12.11.0" - } - }, - "node_modules/@primeuix/styles": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@primeuix/styles/-/styles-2.0.3.tgz", - "integrity": "sha512-2ykAB6BaHzR/6TwF8ShpJTsZrid6cVIEBVlookSdvOdmlWuevGu5vWOScgIwqWwlZcvkFYAGR/SUV3OHCTBMdw==", - "dependencies": { - "@primeuix/styled": "^0.7.4" - } - }, - "node_modules/@primeuix/themes": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@primeuix/themes/-/themes-1.2.5.tgz", - "integrity": "sha512-n3YkwJrHQaEESc/D/A/iD815sxp8cKnmzscA6a8Tm8YvMtYU32eCahwLLe6h5rywghVwxASWuG36XBgISYOIjQ==", - "dependencies": { - "@primeuix/styled": "^0.7.3" - } - }, - "node_modules/@primeuix/utils": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/@primeuix/utils/-/utils-0.6.4.tgz", - "integrity": "sha512-pZ5f+vj7wSzRhC7KoEQRU5fvYAe+RP9+m39CTscZ3UywCD1Y2o6Fe1rRgklMPSkzUcty2jzkA0zMYkiJBD1hgg==", - "engines": { - "node": ">=12.11.0" - } - }, - "node_modules/@primevue/core": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/@primevue/core/-/core-4.5.5.tgz", - "integrity": "sha512-JpkXhq1ddc70JdsC3CC4dM+UbeeWuCW/8DpS9dNBfrOk824TLSlRlMEGFyVKqRMn5WPQvYLiy3xXfLQeNdSqhQ==", - "dependencies": { - "@primeuix/styled": "^0.7.4", - "@primeuix/utils": "^0.6.2" - }, - "engines": { - "node": ">=12.11.0" - }, - "peerDependencies": { - "vue": "^3.5.0" - } - }, - "node_modules/@primevue/icons": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/@primevue/icons/-/icons-4.5.5.tgz", - "integrity": "sha512-eteOhTdAOXEYE9qW1AOrBBgDxQ2szHJxSkEK1XVdV2TKxGM5FQf03Ovms0VDyZTc16XBIgvwYjXJQS0BPbhPaA==", - "dependencies": { - "@primeuix/utils": "^0.6.2", - "@primevue/core": "4.5.5" - }, - "engines": { - "node": ">=12.11.0" - } - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", - "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", - "dev": true - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.4.tgz", - "integrity": "sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.4.tgz", - "integrity": "sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.4.tgz", - "integrity": "sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.4.tgz", - "integrity": "sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.4.tgz", - "integrity": "sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.4.tgz", - "integrity": "sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.4.tgz", - "integrity": "sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.4.tgz", - "integrity": "sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.4.tgz", - "integrity": "sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.4.tgz", - "integrity": "sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.4.tgz", - "integrity": "sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.4.tgz", - "integrity": "sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.4.tgz", - "integrity": "sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.4.tgz", - "integrity": "sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.4.tgz", - "integrity": "sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.4.tgz", - "integrity": "sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.4.tgz", - "integrity": "sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.4.tgz", - "integrity": "sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.4.tgz", - "integrity": "sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.4.tgz", - "integrity": "sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.4.tgz", - "integrity": "sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.4.tgz", - "integrity": "sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.4.tgz", - "integrity": "sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.4.tgz", - "integrity": "sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.4.tgz", - "integrity": "sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@tailwindcss/node": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.0.tgz", - "integrity": "sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==", - "dev": true, - "dependencies": { - "@jridgewell/remapping": "^2.3.5", - "enhanced-resolve": "^5.21.0", - "jiti": "^2.6.1", - "lightningcss": "1.32.0", - "magic-string": "^0.30.21", - "source-map-js": "^1.2.1", - "tailwindcss": "4.3.0" - } - }, - "node_modules/@tailwindcss/oxide": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.0.tgz", - "integrity": "sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==", - "dev": true, - "engines": { - "node": ">= 20" - }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.3.0", - "@tailwindcss/oxide-darwin-arm64": "4.3.0", - "@tailwindcss/oxide-darwin-x64": "4.3.0", - "@tailwindcss/oxide-freebsd-x64": "4.3.0", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.0", - "@tailwindcss/oxide-linux-arm64-gnu": "4.3.0", - "@tailwindcss/oxide-linux-arm64-musl": "4.3.0", - "@tailwindcss/oxide-linux-x64-gnu": "4.3.0", - "@tailwindcss/oxide-linux-x64-musl": "4.3.0", - "@tailwindcss/oxide-wasm32-wasi": "4.3.0", - "@tailwindcss/oxide-win32-arm64-msvc": "4.3.0", - "@tailwindcss/oxide-win32-x64-msvc": "4.3.0" - } - }, - "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.0.tgz", - "integrity": "sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.0.tgz", - "integrity": "sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.0.tgz", - "integrity": "sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.0.tgz", - "integrity": "sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.0.tgz", - "integrity": "sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.0.tgz", - "integrity": "sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.0.tgz", - "integrity": "sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.0.tgz", - "integrity": "sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.0.tgz", - "integrity": "sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.0.tgz", - "integrity": "sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==", - "bundleDependencies": [ - "@napi-rs/wasm-runtime", - "@emnapi/core", - "@emnapi/runtime", - "@tybys/wasm-util", - "@emnapi/wasi-threads", - "tslib" - ], - "cpu": [ - "wasm32" - ], - "dev": true, - "optional": true, - "dependencies": { - "@emnapi/core": "^1.10.0", - "@emnapi/runtime": "^1.10.0", - "@emnapi/wasi-threads": "^1.2.1", - "@napi-rs/wasm-runtime": "^1.1.4", - "@tybys/wasm-util": "^0.10.1", - "tslib": "^2.8.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.0.tgz", - "integrity": "sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.0.tgz", - "integrity": "sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/vite": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.0.tgz", - "integrity": "sha512-t6J3OrB5Fc0ExuhohouH0fWUGMYL6PTLhW+E7zIk/pdbnJARZDCwjBznFnkh5ynRnIRSI4YjtTH0t6USjJISrw==", - "dev": true, - "dependencies": { - "@tailwindcss/node": "4.3.0", - "@tailwindcss/oxide": "4.3.0", - "tailwindcss": "4.3.0" - }, - "peerDependencies": { - "vite": "^5.2.0 || ^6 || ^7 || ^8" - } - }, - "node_modules/@tauri-apps/api": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.11.0.tgz", - "integrity": "sha512-7CinYODhky9lmO23xHnUFv0Xt43fbtWMyxZcLcRBlFkcgXKuEirBvHpmtJ89YMhyeGcq20Wuc47Fa4XjyniywA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/tauri" + "@tauri-apps/cli": "^2" } }, "node_modules/@tauri-apps/cli": { @@ -1396,1162 +214,6 @@ "engines": { "node": ">= 10" } - }, - "node_modules/@tauri-apps/plugin-dialog": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-dialog/-/plugin-dialog-2.7.1.tgz", - "integrity": "sha512-OK1UBXYt+ojcmxMktzzuyonYIFta8CmAASpX+CA+DTGK24KlHjhYI6x2iOJ/TjZF4N7/ACK1oFmEOjIY9IhzOQ==", - "dependencies": { - "@tauri-apps/api": "^2.11.0" - } - }, - "node_modules/@tauri-apps/plugin-opener": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-opener/-/plugin-opener-2.5.4.tgz", - "integrity": "sha512-1HnPkb+AmgO29HBazm4uPLKB+r7zzcTBW1d0fyYp1uP+jwtpoiNDGKMMzz58SFp49nOIrxdE3aUJtT57lfO9CQ==", - "dependencies": { - "@tauri-apps/api": "^2.11.0" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true - }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", - "optional": true - }, - "node_modules/@vitejs/plugin-vue": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.7.tgz", - "integrity": "sha512-km+p+XdSz9Sxm5rqUbqcSfZYaAniKxWBj1KURl+Jr7UaPvvX7BmaWMdP69I5rrFDeQGyxAG7NXdc57vz+snhWg==", - "dev": true, - "dependencies": { - "@rolldown/pluginutils": "^1.0.1" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "peerDependencies": { - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", - "vue": "^3.2.25" - } - }, - "node_modules/@vue/compiler-core": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.34.tgz", - "integrity": "sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==", - "dependencies": { - "@babel/parser": "^7.29.3", - "@vue/shared": "3.5.34", - "entities": "^7.0.1", - "estree-walker": "^2.0.2", - "source-map-js": "^1.2.1" - } - }, - "node_modules/@vue/compiler-dom": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.34.tgz", - "integrity": "sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==", - "dependencies": { - "@vue/compiler-core": "3.5.34", - "@vue/shared": "3.5.34" - } - }, - "node_modules/@vue/compiler-sfc": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.34.tgz", - "integrity": "sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg==", - "dependencies": { - "@babel/parser": "^7.29.3", - "@vue/compiler-core": "3.5.34", - "@vue/compiler-dom": "3.5.34", - "@vue/compiler-ssr": "3.5.34", - "@vue/shared": "3.5.34", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.21", - "postcss": "^8.5.14", - "source-map-js": "^1.2.1" - } - }, - "node_modules/@vue/compiler-ssr": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.34.tgz", - "integrity": "sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ==", - "dependencies": { - "@vue/compiler-dom": "3.5.34", - "@vue/shared": "3.5.34" - } - }, - "node_modules/@vue/devtools-api": { - "version": "7.7.9", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.9.tgz", - "integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==", - "dependencies": { - "@vue/devtools-kit": "^7.7.9" - } - }, - "node_modules/@vue/devtools-kit": { - "version": "7.7.9", - "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz", - "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==", - "dependencies": { - "@vue/devtools-shared": "^7.7.9", - "birpc": "^2.3.0", - "hookable": "^5.5.3", - "mitt": "^3.0.1", - "perfect-debounce": "^1.0.0", - "speakingurl": "^14.0.1", - "superjson": "^2.2.2" - } - }, - "node_modules/@vue/devtools-shared": { - "version": "7.7.9", - "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz", - "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==", - "dependencies": { - "rfdc": "^1.4.1" - } - }, - "node_modules/@vue/reactivity": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.34.tgz", - "integrity": "sha512-y9XDjCEuBp+98k+UL5dbYkh57AHU4o6cxZedOPXw3bmrZZYLQsVHguGurq7hVrPCSrQtrnz1f9dssyFr+dMXfQ==", - "dependencies": { - "@vue/shared": "3.5.34" - } - }, - "node_modules/@vue/runtime-core": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.34.tgz", - "integrity": "sha512-mKeBYvu8tcMSLhypAHBmriUFfWXKTCF/23Z4jiCoYK3UtWepkliViNLuR90V9XOyD62mUxs9p1jsrpK3CCGIzw==", - "dependencies": { - "@vue/reactivity": "3.5.34", - "@vue/shared": "3.5.34" - } - }, - "node_modules/@vue/runtime-dom": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.34.tgz", - "integrity": "sha512-e8kZzERmCwUnBRVsgSQlAfrfU2rGoy0FFKPBXSlfEjc/O3KfA7QP0t1/2ZylrbchjmIKB4dPTd07A6WPr0eOrg==", - "dependencies": { - "@vue/reactivity": "3.5.34", - "@vue/runtime-core": "3.5.34", - "@vue/shared": "3.5.34", - "csstype": "^3.2.3" - } - }, - "node_modules/@vue/server-renderer": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.34.tgz", - "integrity": "sha512-nHxmJoTrKsmrkbILRhkC9gY1G3moZbJTqCzDd7DOOzG5KH9oeJ0Unqrff5f9v0pW//jES05ZkJcNtfE8JjOIew==", - "dependencies": { - "@vue/compiler-ssr": "3.5.34", - "@vue/shared": "3.5.34" - }, - "peerDependencies": { - "vue": "3.5.34" - } - }, - "node_modules/@vue/shared": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.34.tgz", - "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==" - }, - "node_modules/autoprefixer": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz", - "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "browserslist": "^4.28.2", - "caniuse-lite": "^1.0.30001787", - "fraction.js": "^5.3.4", - "picocolors": "^1.1.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/baseline-browser-mapping": { - "version": "2.10.29", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.29.tgz", - "integrity": "sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ==", - "dev": true, - "bin": { - "baseline-browser-mapping": "dist/cli.cjs" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/birpc": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", - "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/browserslist": { - "version": "4.28.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", - "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "baseline-browser-mapping": "^2.10.12", - "caniuse-lite": "^1.0.30001782", - "electron-to-chromium": "^1.5.328", - "node-releases": "^2.0.36", - "update-browserslist-db": "^1.2.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001792", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001792.tgz", - "integrity": "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/copy-anything": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz", - "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", - "dependencies": { - "is-what": "^5.2.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==" - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/dompurify": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz", - "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==", - "optionalDependencies": { - "@types/trusted-types": "^2.0.7" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.356", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.356.tgz", - "integrity": "sha512-9NgFd7m5t5MCJ5rUSjJITUXAH9mEGlrlofnMf4YEr+pz6JlP7cWmTAH+JFmbPnaSW8koVTkuW7pacORWAnA5Yw==", - "dev": true - }, - "node_modules/enhanced-resolve": { - "version": "5.21.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.3.tgz", - "integrity": "sha512-QyL119InA+XXEkNLNTPCXPugSvOfhwv0JOlGNzvxs0hZaiHLNvXSpudUWsOlsXGWJh8G6ckCScEkVHfX3kw/2Q==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/entities": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", - "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/fraction.js": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", - "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", - "dev": true, - "engines": { - "node": "*" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/hookable": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", - "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==" - }, - "node_modules/is-what": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz", - "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, - "node_modules/jiti": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", - "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", - "dev": true, - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, - "node_modules/lightningcss": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", - "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", - "dev": true, - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-android-arm64": "1.32.0", - "lightningcss-darwin-arm64": "1.32.0", - "lightningcss-darwin-x64": "1.32.0", - "lightningcss-freebsd-x64": "1.32.0", - "lightningcss-linux-arm-gnueabihf": "1.32.0", - "lightningcss-linux-arm64-gnu": "1.32.0", - "lightningcss-linux-arm64-musl": "1.32.0", - "lightningcss-linux-x64-gnu": "1.32.0", - "lightningcss-linux-x64-musl": "1.32.0", - "lightningcss-win32-arm64-msvc": "1.32.0", - "lightningcss-win32-x64-msvc": "1.32.0" - } - }, - "node_modules/lightningcss-android-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", - "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", - "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", - "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", - "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", - "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", - "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", - "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", - "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", - "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", - "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", - "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/marked": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz", - "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/mitt": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", - "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==" - }, - "node_modules/monaco-editor": { - "version": "0.55.1", - "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.55.1.tgz", - "integrity": "sha512-jz4x+TJNFHwHtwuV9vA9rMujcZRb0CEilTEwG2rRSpe/A7Jdkuj8xPKttCgOh+v/lkHy7HsZ64oj+q3xoAFl9A==", - "dependencies": { - "dompurify": "3.2.7", - "marked": "14.0.0" - } - }, - "node_modules/monaco-editor-vue3": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/monaco-editor-vue3/-/monaco-editor-vue3-1.0.5.tgz", - "integrity": "sha512-1n4ayGcuYpZcQ6A4PUYZYqXuf6n+A/2pUNdLnb8I39WZV0zkhfvSRNau3hB0qzq6vp6wSNZ7MgcjQRCJCiGHWQ==", - "peerDependencies": { - "monaco-editor": ">= 0.25.0 < 1", - "vue": "^3" - } - }, - "node_modules/nanoid": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/node-releases": { - "version": "2.0.44", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.44.tgz", - "integrity": "sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ==", - "dev": true - }, - "node_modules/perfect-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", - "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" - }, - "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pinia": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.4.tgz", - "integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==", - "dependencies": { - "@vue/devtools-api": "^7.7.7" - }, - "funding": { - "url": "https://github.com/sponsors/posva" - }, - "peerDependencies": { - "typescript": ">=4.5.0", - "vue": "^3.5.11" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/postcss": { - "version": "8.5.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", - "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/primeicons": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/primeicons/-/primeicons-7.0.0.tgz", - "integrity": "sha512-jK3Et9UzwzTsd6tzl2RmwrVY/b8raJ3QZLzoDACj+oTJ0oX7L9Hy+XnVwgo4QVKlKpnP/Ur13SXV/pVh4LzaDw==" - }, - "node_modules/primevue": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/primevue/-/primevue-4.5.5.tgz", - "integrity": "sha512-Kv5REIewCdP806QaoU+4nBXfmpzOGFKkZ9qH4KsL6MjiAQVc4PUzypt8erl4r3Vzh3nr3aWZIxkxYRRsLGiX2A==", - "dependencies": { - "@primeuix/styled": "^0.7.4", - "@primeuix/styles": "^2.0.3", - "@primeuix/utils": "^0.6.2", - "@primevue/core": "4.5.5", - "@primevue/icons": "4.5.5" - }, - "engines": { - "node": ">=12.11.0" - } - }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" - }, - "node_modules/rollup": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.4.tgz", - "integrity": "sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==", - "dev": true, - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.60.4", - "@rollup/rollup-android-arm64": "4.60.4", - "@rollup/rollup-darwin-arm64": "4.60.4", - "@rollup/rollup-darwin-x64": "4.60.4", - "@rollup/rollup-freebsd-arm64": "4.60.4", - "@rollup/rollup-freebsd-x64": "4.60.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.60.4", - "@rollup/rollup-linux-arm-musleabihf": "4.60.4", - "@rollup/rollup-linux-arm64-gnu": "4.60.4", - "@rollup/rollup-linux-arm64-musl": "4.60.4", - "@rollup/rollup-linux-loong64-gnu": "4.60.4", - "@rollup/rollup-linux-loong64-musl": "4.60.4", - "@rollup/rollup-linux-ppc64-gnu": "4.60.4", - "@rollup/rollup-linux-ppc64-musl": "4.60.4", - "@rollup/rollup-linux-riscv64-gnu": "4.60.4", - "@rollup/rollup-linux-riscv64-musl": "4.60.4", - "@rollup/rollup-linux-s390x-gnu": "4.60.4", - "@rollup/rollup-linux-x64-gnu": "4.60.4", - "@rollup/rollup-linux-x64-musl": "4.60.4", - "@rollup/rollup-openbsd-x64": "4.60.4", - "@rollup/rollup-openharmony-arm64": "4.60.4", - "@rollup/rollup-win32-arm64-msvc": "4.60.4", - "@rollup/rollup-win32-ia32-msvc": "4.60.4", - "@rollup/rollup-win32-x64-gnu": "4.60.4", - "@rollup/rollup-win32-x64-msvc": "4.60.4", - "fsevents": "~2.3.2" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/speakingurl": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", - "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/superjson": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz", - "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", - "dependencies": { - "copy-anything": "^4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/tailwindcss": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.0.tgz", - "integrity": "sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==", - "dev": true - }, - "node_modules/tapable": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", - "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", - "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", - "dev": true, - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", - "optional": true, - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/vite": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz", - "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==", - "dev": true, - "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.4.4", - "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "jiti": ">=1.21.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vite-plugin-monaco-editor": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vite-plugin-monaco-editor/-/vite-plugin-monaco-editor-1.1.0.tgz", - "integrity": "sha512-IvtUqZotrRoVqwT0PBBDIZPNraya3BxN/bfcNfnxZ5rkJiGcNtO5eAOWWSgT7zullIAEqQwxMU83yL9J5k7gww==", - "dev": true, - "peerDependencies": { - "monaco-editor": ">=0.33.0" - } - }, - "node_modules/vue": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.34.tgz", - "integrity": "sha512-WdLBG9gm02OgJIG9axd5Hpx0TFLdzVgfG2evFFu8Rur5O/IoGc5cMjnjh3tPL6GnRGsYvUhBSKVPYVcxRKpMCA==", - "dependencies": { - "@vue/compiler-dom": "3.5.34", - "@vue/compiler-sfc": "3.5.34", - "@vue/runtime-dom": "3.5.34", - "@vue/server-renderer": "3.5.34", - "@vue/shared": "3.5.34" - }, - "peerDependencies": { - "typescript": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/vue-router": { - "version": "4.6.4", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz", - "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==", - "dependencies": { - "@vue/devtools-api": "^6.6.4" - }, - "funding": { - "url": "https://github.com/sponsors/posva" - }, - "peerDependencies": { - "vue": "^3.5.0" - } - }, - "node_modules/vue-router/node_modules/@vue/devtools-api": { - "version": "6.6.4", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", - "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==" } } } diff --git a/package.json b/package.json index f58b112..9baad87 100644 --- a/package.json +++ b/package.json @@ -1,36 +1,12 @@ { "name": "aiclient", "private": true, - "version": "0.1.3", - "type": "module", "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview", "tauri": "tauri", + "dev": "tauri dev", "tauri:build": "node src-tauri/scripts/bump-version.cjs && tauri build && node src-tauri/scripts/zip-portable.cjs" }, - "dependencies": { - "@primeuix/themes": "^1.2.1", - "@tauri-apps/api": "^2", - "@tauri-apps/plugin-dialog": "^2.7.1", - "@tauri-apps/plugin-opener": "^2", - "monaco-editor": "^0.55.1", - "monaco-editor-vue3": "^1.0.5", - "pinia": "^3.0.3", - "primeicons": "^7.0.0", - "primevue": "^4.3.6", - "vue": "^3.5.17", - "vue-router": "^4.5.1" - }, "devDependencies": { - "@tailwindcss/vite": "^4.1.11", - "@tauri-apps/cli": "^2", - "@vitejs/plugin-vue": "^6.0.0", - "autoprefixer": "^10.4.21", - "postcss": "^8.5.6", - "tailwindcss": "^4.1.11", - "vite": "^6.0.3", - "vite-plugin-monaco-editor": "^1.1.0" + "@tauri-apps/cli": "^2" } } diff --git a/public/subtitle-templates/previews/subtitle-preview-template_system_11.png b/public/subtitle-templates/previews/subtitle-preview-template_system_11.png deleted file mode 100644 index 4291821..0000000 Binary files a/public/subtitle-templates/previews/subtitle-preview-template_system_11.png and /dev/null differ diff --git a/public/subtitle-templates/previews/subtitle-preview-template_system_22.png b/public/subtitle-templates/previews/subtitle-preview-template_system_22.png deleted file mode 100644 index 052dec3..0000000 Binary files a/public/subtitle-templates/previews/subtitle-preview-template_system_22.png and /dev/null differ diff --git a/public/subtitle-templates/previews/subtitle-preview-template_system_33.png b/public/subtitle-templates/previews/subtitle-preview-template_system_33.png deleted file mode 100644 index c1abcb4..0000000 Binary files a/public/subtitle-templates/previews/subtitle-preview-template_system_33.png and /dev/null differ diff --git a/public/subtitle-templates/previews/subtitle-preview-template_system_44.png b/public/subtitle-templates/previews/subtitle-preview-template_system_44.png deleted file mode 100644 index 9f6732e..0000000 Binary files a/public/subtitle-templates/previews/subtitle-preview-template_system_44.png and /dev/null differ diff --git a/public/subtitle-templates/previews/subtitle-preview-template_system_55.png b/public/subtitle-templates/previews/subtitle-preview-template_system_55.png deleted file mode 100644 index 0b66f46..0000000 Binary files a/public/subtitle-templates/previews/subtitle-preview-template_system_55.png and /dev/null differ diff --git a/public/subtitle-templates/previews/subtitle-preview-template_system_66.png b/public/subtitle-templates/previews/subtitle-preview-template_system_66.png deleted file mode 100644 index 7cb101d..0000000 Binary files a/public/subtitle-templates/previews/subtitle-preview-template_system_66.png and /dev/null differ diff --git a/public/subtitle-templates/previews/subtitle-preview-template_system_77.png b/public/subtitle-templates/previews/subtitle-preview-template_system_77.png deleted file mode 100644 index 78c6ba4..0000000 Binary files a/public/subtitle-templates/previews/subtitle-preview-template_system_77.png and /dev/null differ diff --git a/public/subtitle-templates/previews/subtitle-preview-template_system_88.png b/public/subtitle-templates/previews/subtitle-preview-template_system_88.png deleted file mode 100644 index deefdf8..0000000 Binary files a/public/subtitle-templates/previews/subtitle-preview-template_system_88.png and /dev/null differ diff --git a/public/subtitle-templates/previews/subtitle-preview-template_system_classic_11.png b/public/subtitle-templates/previews/subtitle-preview-template_system_classic_11.png deleted file mode 100644 index 4291821..0000000 Binary files a/public/subtitle-templates/previews/subtitle-preview-template_system_classic_11.png and /dev/null differ diff --git a/public/subtitle-templates/previews/subtitle-preview-template_system_classic_22.png b/public/subtitle-templates/previews/subtitle-preview-template_system_classic_22.png deleted file mode 100644 index 052dec3..0000000 Binary files a/public/subtitle-templates/previews/subtitle-preview-template_system_classic_22.png and /dev/null differ diff --git a/public/subtitle-templates/previews/subtitle-preview-template_system_classic_33.png b/public/subtitle-templates/previews/subtitle-preview-template_system_classic_33.png deleted file mode 100644 index c1abcb4..0000000 Binary files a/public/subtitle-templates/previews/subtitle-preview-template_system_classic_33.png and /dev/null differ diff --git a/public/subtitle-templates/previews/subtitle-preview-template_system_classic_44.png b/public/subtitle-templates/previews/subtitle-preview-template_system_classic_44.png deleted file mode 100644 index 9f6732e..0000000 Binary files a/public/subtitle-templates/previews/subtitle-preview-template_system_classic_44.png and /dev/null differ diff --git a/public/subtitle-templates/previews/subtitle-preview-template_system_classic_55.png b/public/subtitle-templates/previews/subtitle-preview-template_system_classic_55.png deleted file mode 100644 index 0b66f46..0000000 Binary files a/public/subtitle-templates/previews/subtitle-preview-template_system_classic_55.png and /dev/null differ diff --git a/public/subtitle-templates/previews/subtitle-preview-template_system_classic_66.png b/public/subtitle-templates/previews/subtitle-preview-template_system_classic_66.png deleted file mode 100644 index 7cb101d..0000000 Binary files a/public/subtitle-templates/previews/subtitle-preview-template_system_classic_66.png and /dev/null differ diff --git a/public/subtitle-templates/previews/subtitle-preview-template_system_classic_77.png b/public/subtitle-templates/previews/subtitle-preview-template_system_classic_77.png deleted file mode 100644 index 78c6ba4..0000000 Binary files a/public/subtitle-templates/previews/subtitle-preview-template_system_classic_77.png and /dev/null differ diff --git a/public/subtitle-templates/previews/subtitle-preview-template_system_classic_88.png b/public/subtitle-templates/previews/subtitle-preview-template_system_classic_88.png deleted file mode 100644 index deefdf8..0000000 Binary files a/public/subtitle-templates/previews/subtitle-preview-template_system_classic_88.png and /dev/null differ diff --git a/public/subtitle-templates/system-templates.json b/public/subtitle-templates/system-templates.json deleted file mode 100644 index bfafb84..0000000 --- a/public/subtitle-templates/system-templates.json +++ /dev/null @@ -1,4543 +0,0 @@ -{ - "version": "1.0.0", - "description": "System template config with 16 subtitle templates and 8 cover templates", - "subtitleTemplates": [ - { - "id": "template_system_11", - "name": "11 Inline", - "description": "System subtitle template 11 inline keyword emphasis", - "config": { - "subtitleStyleId": "system-subtitle-11", - "subtitleFontSizeScale": 100, - "subtitlePosition": "bottom", - "enableKeywordEffects": true, - "keywordRenderMode": "inline-emphasis", - "keywordGroupsStyles": [ - { - "groupName": "行动词", - "styleOverride": { - "fontColor": "#FFFF00", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 24, - "fontName": "胡晓波男神体" - }, - "effectId": "intense-flash", - "effectDuration": null, - "color": "#FFFF00", - "soundEffectId": "bubble", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "情感词", - "styleOverride": { - "fontColor": "#FFFF00", - "outlineColor": "#000000", - "outlineWidth": 0, - "fontSize": 24, - "fontName": "胡晓波男神体" - }, - "effectId": "danmaku", - "effectDuration": null, - "color": "#FFFF00", - "soundEffectId": null, - "soundEffectConfig": null - }, - { - "groupName": "描述词", - "styleOverride": { - "fontColor": "#FFFF00", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 24, - "fontName": "胡晓波男神体" - }, - "effectId": "flying-tilt", - "effectDuration": null, - "color": "#FFFF00", - "soundEffectId": null, - "soundEffectConfig": null - }, - { - "groupName": "重点词/成语词", - "styleOverride": { - "fontColor": "#FFFF00", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 24, - "fontName": "胡晓波男神体" - }, - "effectId": "fly-in", - "effectDuration": null, - "color": "#FFFF00", - "soundEffectId": "ding", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "12", - "styleOverride": null, - "effectId": null, - "effectDuration": null, - "color": null, - "soundEffectId": null, - "soundEffectConfig": null - } - ], - "screenWidth": 1920, - "screenHeight": 1080, - "fontSize": 48, - "fontFamily": "Arial, sans-serif", - "subtitleStyle": { - "id": "custom", - "name": "自定义样式", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "fontName": "胡晓波男神体", - "fontSize": 35, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 0, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "shadowOffset": 2, - "shadowBlur": 4, - "shadowColor": "#000000" - }, - "titleSubtitleConfig": { - "enabled": true, - "sourceTitle": "有娃家庭马桶清洁妙招", - "maxCharsPerLine": 8, - "maxLines": 5, - "lineSpacingPercent": 5, - "topMarginPercent": 5, - "lines": [ - { - "text": "有娃家庭马桶清洁", - "fontName": "优设标题黑", - "fontSize": 80, - "fontColor": "#ffff00", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 1, - "shadowColor": "#000000", - "shadowOffset": 3, - "yOffsetPercent": 5 - }, - { - "text": "妙招", - "fontName": "优设标题黑", - "fontSize": 80, - "fontColor": "#ffffff", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 10 - } - ], - "startTime": 0, - "fadeInDuration": 0, - "fadeOutDuration": 0 - }, - "previewConfig": { - "backgroundKey": "portrait", - "backgroundPosition": "center 28%", - "overlayStartColor": "rgba(0, 0, 0, 0.14)", - "overlayEndColor": "rgba(0, 0, 0, 0.58)", - "subtitleTexts": [ - "生活不会辜负认真[努力]的人", - "用心前行日子总会[温柔]以待" - ], - "backgroundImage": "extra/common/cover-templates/subtitle-preview-template_system_11.png", - "titleTexts": [ - "生活不会辜负认真努力的人", - "用心前行日子总会温柔以待" - ] - } - }, - "createdAt": 1768396885438, - "isSystem": true, - "is_system": 1 - }, - { - "id": "template_system_classic_11", - "name": "11 Classic", - "description": "System subtitle template 11 classic original style", - "config": { - "subtitleStyleId": "system-subtitle-11", - "subtitleFontSizeScale": 100, - "subtitlePosition": "bottom", - "enableKeywordEffects": true, - "keywordGroupsStyles": [ - { - "groupName": "行动词", - "styleOverride": { - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 3, - "fontSize": 68, - "fontName": "字玩哥特黑白无常 免费 超黑" - }, - "effectId": "intense-flash", - "effectDuration": null, - "color": "#FFFFFF", - "soundEffectId": "magic-sfx", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "情感词", - "styleOverride": { - "fontColor": "#DDE3EC", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 64, - "fontName": "庞门正道标题体免费版" - }, - "effectId": "danmaku", - "effectDuration": null, - "color": "#DDE3EC", - "soundEffectId": "cash-register", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "描述词", - "styleOverride": { - "fontColor": "#DBC541", - "outlineColor": "#000000", - "outlineWidth": 7, - "fontSize": 88, - "fontName": "优设标题黑" - }, - "effectId": "flying-tilt", - "effectDuration": null, - "color": "#DBC541", - "soundEffectId": "pop-1", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "重点词/成语词", - "styleOverride": { - "fontColor": "#980C0CEC", - "outlineColor": "#000000", - "outlineWidth": 10, - "fontSize": 104, - "fontName": "字玩哥特黑白无常 免费 超黑" - }, - "effectId": "fly-in", - "effectDuration": null, - "color": "#980C0CEC", - "soundEffectId": "punch", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "12", - "styleOverride": null, - "effectId": null, - "effectDuration": null, - "color": null, - "soundEffectId": null, - "soundEffectConfig": null - } - ], - "screenWidth": 1920, - "screenHeight": 1080, - "fontSize": 48, - "fontFamily": "Arial, sans-serif", - "subtitleStyle": { - "id": "system-subtitle-11", - "name": "11", - "description": "自定义字幕样式 - 黑底白字,精致描边", - "preview": "示例文字", - "fontName": "优设标题黑", - "fontSize": 48, - "fontColor": "#35A9E2", - "outlineColor": "#000000", - "outlineWidth": 1, - "backgroundColor": "transparent", - "backgroundOpacity": 0.3, - "position": "bottom", - "shadowOffset": 2, - "shadowBlur": 4, - "shadowColor": "#000000" - }, - "titleSubtitleConfig": { - "enabled": true, - "sourceTitle": "芒格稳赢几十年的三件事", - "maxCharsPerLine": 8, - "maxLines": 5, - "lineSpacingPercent": 5, - "topMarginPercent": 5, - "lines": [ - { - "text": "芒格稳赢几十年的", - "fontName": "优设标题黑", - "fontSize": 80, - "fontColor": "#FFFFFF", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 5 - }, - { - "text": "三件事", - "fontName": "优设标题黑", - "fontSize": 80, - "fontColor": "#6decee", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 10 - } - ], - "startTime": 0, - "fadeInDuration": 0, - "fadeOutDuration": 0 - }, - "previewConfig": { - "backgroundImage": "extra/common/cover-templates/subtitle-preview-template_system_classic_11.png", - "titleTexts": [ - "生活不会辜负认真努力的人", - "用心前行日子总会温柔以待" - ], - "subtitleTexts": [ - "生活不会辜负认真努力的人", - "用心前行日子总会温柔以待" - ] - } - }, - "createdAt": 1768396885438, - "isSystem": true, - "is_system": 1 - }, - { - "id": "template_system_22", - "name": "22 Inline", - "description": "System subtitle template 22 inline keyword emphasis", - "config": { - "subtitleStyleId": "system-subtitle-22", - "subtitleFontSizeScale": 100, - "subtitlePosition": "bottom", - "enableKeywordEffects": true, - "keywordRenderMode": "inline-emphasis", - "keywordGroupsStyles": [ - { - "groupName": "行动词", - "styleOverride": { - "fontColor": "#E25353EC", - "outlineColor": "#FBF3F3", - "outlineWidth": 3, - "fontSize": 24, - "fontName": "月星楷" - }, - "effectId": "intense-flash", - "effectDuration": null, - "color": "#E25353EC", - "soundEffectId": "bubble", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "情感词", - "styleOverride": { - "fontName": "月星楷", - "fontSize": 24, - "fontColor": "#E25353EC", - "outlineColor": "#FEFEFE", - "outlineWidth": 3 - }, - "effectId": "danmaku", - "effectDuration": null, - "color": "#E25353EC", - "soundEffectId": null, - "soundEffectConfig": null - }, - { - "groupName": "描述词", - "styleOverride": { - "fontName": "月星楷", - "fontSize": 24, - "fontColor": "#E25353EC", - "outlineColor": "#F8F8F8", - "outlineWidth": 3 - }, - "effectId": "flying-tilt", - "effectDuration": null, - "color": "#E25353EC", - "soundEffectId": null, - "soundEffectConfig": null - }, - { - "groupName": "重点词/成语词", - "styleOverride": { - "fontColor": "#E25353EC", - "outlineColor": "#FFFFFF", - "outlineWidth": 3, - "fontSize": 24, - "fontName": "月星楷" - }, - "effectId": "fly-in", - "effectDuration": null, - "color": "#E25353EC", - "soundEffectId": "ding", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "12", - "styleOverride": null, - "effectId": null, - "effectDuration": null, - "color": null, - "soundEffectId": null, - "soundEffectConfig": null - } - ], - "screenWidth": 1920, - "screenHeight": 1080, - "fontSize": 48, - "fontFamily": "Arial, sans-serif", - "subtitleStyle": { - "id": "custom", - "name": "自定义样式", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "fontName": "月星楷", - "fontSize": 48, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 3, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "shadowOffset": 2, - "shadowBlur": 4, - "shadowColor": "#000000" - }, - "titleSubtitleConfig": { - "enabled": true, - "sourceTitle": "有娃家庭马桶清洁妙招", - "maxCharsPerLine": 8, - "maxLines": 5, - "lineSpacingPercent": 5, - "topMarginPercent": 5, - "lines": [ - { - "text": "有娃家庭马桶清洁", - "fontName": "优设标题黑", - "fontSize": 80, - "fontColor": "#9b0808", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 5 - }, - { - "text": "妙招", - "fontName": "优设标题黑", - "fontSize": 80, - "fontColor": "#FFFFFF", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 10 - } - ], - "startTime": 0, - "fadeInDuration": 0, - "fadeOutDuration": 0 - }, - "previewConfig": { - "backgroundKey": "portrait", - "backgroundPosition": "center 26%", - "overlayStartColor": "rgba(15, 23, 42, 0.16)", - "overlayEndColor": "rgba(15, 23, 42, 0.62)", - "subtitleTexts": [ - "别让[焦虑]打乱你原本的节奏", - "慢慢变好才是给自己的[答案]" - ], - "backgroundImage": "extra/common/cover-templates/subtitle-preview-template_system_22.png", - "titleTexts": [ - "别让焦虑打乱你原本的节奏", - "慢慢变好才是给自己的答案" - ] - } - }, - "createdAt": 1768396885439, - "isSystem": true, - "is_system": 1 - }, - { - "id": "template_system_classic_22", - "name": "22 Classic", - "description": "System subtitle template 22 classic original style", - "config": { - "subtitleStyleId": "system-subtitle-22", - "subtitleFontSizeScale": 100, - "subtitlePosition": "bottom", - "enableKeywordEffects": true, - "keywordGroupsStyles": [ - { - "groupName": "行动词", - "styleOverride": { - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 3, - "fontSize": 68, - "fontName": "字玩哥特黑白无常 免费 超黑" - }, - "effectId": "intense-flash", - "color": "#FFFFFF", - "soundEffectId": "magic-sfx", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "情感词", - "styleOverride": { - "fontColor": "#DDE3EC", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 64, - "fontName": "庞门正道标题体免费版" - }, - "effectId": "danmaku", - "color": "#DDE3EC", - "soundEffectId": "cash-register", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "描述词", - "styleOverride": { - "fontColor": "#DBC541", - "outlineColor": "#000000", - "outlineWidth": 7, - "fontSize": 88, - "fontName": "优设标题黑" - }, - "effectId": "flying-tilt", - "color": "#DBC541", - "soundEffectId": "pop-1", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "重点词/成语词", - "styleOverride": { - "fontColor": "#980C0CEC", - "outlineColor": "#000000", - "outlineWidth": 10, - "fontSize": 104, - "fontName": "字玩哥特黑白无常 免费 超黑" - }, - "effectId": "fly-in", - "color": "#980C0CEC", - "soundEffectId": "punch", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "12", - "effectId": null, - "color": null, - "soundEffectId": null - } - ], - "screenWidth": 1920, - "screenHeight": 1080, - "fontSize": 48, - "fontFamily": "Arial, sans-serif", - "subtitleStyle": { - "id": "custom", - "name": "自定义样式", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "fontName": "月星楷", - "fontSize": 48, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 3, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "shadowOffset": 2, - "shadowBlur": 4, - "shadowColor": "#000000" - }, - "titleSubtitleConfig": { - "enabled": true, - "sourceTitle": "芒格稳赢几十年的三件事", - "maxCharsPerLine": 8, - "maxLines": 5, - "lineSpacingPercent": 5, - "topMarginPercent": 5, - "lines": [ - { - "text": "芒格稳赢几十年的", - "fontName": "优设标题黑", - "fontSize": 80, - "fontColor": "#9b0808", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 5 - }, - { - "text": "三件事", - "fontName": "优设标题黑", - "fontSize": 80, - "fontColor": "#FFFFFF", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 10 - } - ], - "startTime": 0, - "fadeInDuration": 0, - "fadeOutDuration": 0 - }, - "previewConfig": { - "backgroundImage": "extra/common/cover-templates/subtitle-preview-template_system_classic_22.png", - "titleTexts": [ - "别让焦虑打乱你原本的节奏", - "慢慢变好才是给自己的答案" - ], - "subtitleTexts": [ - "别让焦虑打乱你原本的节奏", - "慢慢变好才是给自己的答案" - ] - } - }, - "createdAt": 1768396885439, - "isSystem": true, - "is_system": 1 - }, - { - "id": "template_system_33", - "name": "33 Inline", - "description": "System subtitle template 33 inline keyword emphasis", - "config": { - "subtitleStyleId": "system-subtitle-33", - "subtitleFontSizeScale": 100, - "subtitlePosition": "bottom", - "enableKeywordEffects": true, - "keywordRenderMode": "inline-emphasis", - "keywordGroupsStyles": [ - { - "groupName": "行动词", - "styleOverride": { - "fontColor": "#FFFF00", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 24, - "fontName": "霞鹜文楷-Light" - }, - "effectId": "intense-flash", - "effectDuration": null, - "color": "#FFFF00", - "soundEffectId": "bubble", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "情感词", - "styleOverride": { - "fontColor": "#FFFF00", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 24, - "fontName": "霞鹜文楷-Light" - }, - "effectId": "danmaku", - "effectDuration": null, - "color": "#FFFF00", - "soundEffectId": null, - "soundEffectConfig": null - }, - { - "groupName": "描述词", - "styleOverride": { - "fontColor": "#FFFF00", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 24, - "fontName": "霞鹜文楷-Light" - }, - "effectId": "flying-tilt", - "effectDuration": null, - "color": "#FFFF00", - "soundEffectId": null, - "soundEffectConfig": null - }, - { - "groupName": "重点词/成语词", - "styleOverride": { - "fontColor": "#FFFF00", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 24, - "fontName": "霞鹜文楷-Light" - }, - "effectId": "fly-in", - "effectDuration": null, - "color": "#FFFF00", - "soundEffectId": "ding", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "12", - "styleOverride": null, - "effectId": null, - "effectDuration": null, - "color": null, - "soundEffectId": null, - "soundEffectConfig": null - } - ], - "screenWidth": 1920, - "screenHeight": 1080, - "fontSize": 48, - "fontFamily": "Arial, sans-serif", - "subtitleStyle": { - "id": "custom", - "name": "自定义样式", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "fontName": "霞鹜文楷-Light", - "fontSize": 48, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 3, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "shadowOffset": 2, - "shadowBlur": 4, - "shadowColor": "#000000" - }, - "titleSubtitleConfig": { - "enabled": true, - "sourceTitle": "有娃家庭马桶清洁妙招", - "maxCharsPerLine": 8, - "maxLines": 5, - "lineSpacingPercent": 7, - "topMarginPercent": 4, - "lines": [ - { - "text": "有娃家庭马桶清洁", - "fontName": "USMCCyuanjiantecu", - "fontSize": 75, - "fontColor": "#000000", - "backgroundColor": "#ffffff", - "backgroundOpacity": 0.8, - "outlineColor": "#ffffff", - "outlineWidth": 0, - "shadowColor": "#000000", - "shadowOffset": 1, - "yOffsetPercent": 4 - }, - { - "text": "妙招", - "fontName": "USMCCyuanjiantecu", - "fontSize": 75, - "fontColor": "#e2c018", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 11 - } - ], - "startTime": 0, - "fadeInDuration": 0, - "fadeOutDuration": 0 - }, - "previewConfig": { - "backgroundKey": "portrait", - "backgroundPosition": "center 25%", - "overlayStartColor": "rgba(0, 0, 0, 0.12)", - "overlayEndColor": "rgba(0, 0, 0, 0.56)", - "subtitleTexts": [ - "好好[爱自己]永远是头等大事", - "温柔岁月里做最[自在]的自己" - ], - "backgroundImage": "extra/common/cover-templates/subtitle-preview-template_system_33.png", - "titleTexts": [ - "好好爱自己永远是头等大事", - "温柔岁月里做最自在的自己" - ] - } - }, - "createdAt": 1768396885440, - "isSystem": true, - "is_system": 1 - }, - { - "id": "template_system_classic_33", - "name": "33 Classic", - "description": "System subtitle template 33 classic original style", - "config": { - "subtitleStyleId": "system-subtitle-33", - "subtitleFontSizeScale": 100, - "subtitlePosition": "bottom", - "enableKeywordEffects": true, - "keywordGroupsStyles": [ - { - "groupName": "行动词", - "styleOverride": { - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 3, - "fontSize": 68, - "fontName": "字玩哥特黑白无常 免费 超黑" - }, - "effectId": "intense-flash", - "effectDuration": null, - "color": "#FFFFFF", - "soundEffectId": "magic-sfx", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "情感词", - "styleOverride": { - "fontColor": "#DDE3EC", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 64, - "fontName": "庞门正道标题体免费版" - }, - "effectId": "danmaku", - "effectDuration": null, - "color": "#DDE3EC", - "soundEffectId": "cash-register", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "描述词", - "styleOverride": { - "fontColor": "#DBC541", - "outlineColor": "#000000", - "outlineWidth": 7, - "fontSize": 88, - "fontName": "优设标题黑" - }, - "effectId": "flying-tilt", - "effectDuration": null, - "color": "#DBC541", - "soundEffectId": "pop-1", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "重点词/成语词", - "styleOverride": { - "fontColor": "#980C0CEC", - "outlineColor": "#000000", - "outlineWidth": 10, - "fontSize": 104, - "fontName": "字玩哥特黑白无常 免费 超黑" - }, - "effectId": "fly-in", - "effectDuration": null, - "color": "#980C0CEC", - "soundEffectId": "punch", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "12", - "styleOverride": null, - "effectId": null, - "effectDuration": null, - "color": null, - "soundEffectId": null, - "soundEffectConfig": null - } - ], - "screenWidth": 1920, - "screenHeight": 1080, - "fontSize": 48, - "fontFamily": "Arial, sans-serif", - "subtitleStyle": { - "id": "custom", - "name": "自定义样式", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "fontName": "庞门正道标题体免费版", - "fontSize": 48, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 3, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "shadowOffset": 2, - "shadowBlur": 4, - "shadowColor": "#000000" - }, - "titleSubtitleConfig": { - "enabled": true, - "sourceTitle": "芒格稳赢几十年的三件事", - "maxCharsPerLine": 8, - "maxLines": 5, - "lineSpacingPercent": 7, - "topMarginPercent": 5, - "lines": [ - { - "text": "芒格稳赢几十年的", - "fontName": "USMCCyuanjiantecu", - "fontSize": 80, - "fontColor": "#FFFFFF", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 5 - }, - { - "text": "三件事", - "fontName": "USMCCyuanjiantecu", - "fontSize": 80, - "fontColor": "#e2c018", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 12 - } - ], - "startTime": 0, - "fadeInDuration": 0, - "fadeOutDuration": 0 - }, - "previewConfig": { - "backgroundImage": "extra/common/cover-templates/subtitle-preview-template_system_classic_33.png", - "titleTexts": [ - "好好爱自己永远是头等大事", - "温柔岁月里做最自在的自己" - ], - "subtitleTexts": [ - "好好爱自己永远是头等大事", - "温柔岁月里做最自在的自己" - ] - } - }, - "createdAt": 1768396885440, - "isSystem": true, - "is_system": 1 - }, - { - "id": "template_system_44", - "name": "44 Inline", - "description": "System subtitle template 44 inline keyword emphasis", - "config": { - "subtitleStyleId": "system-subtitle-44", - "subtitleFontSizeScale": 100, - "subtitlePosition": "bottom", - "enableKeywordEffects": true, - "keywordRenderMode": "inline-emphasis", - "keywordGroupsStyles": [ - { - "groupName": "行动词", - "styleOverride": { - "fontColor": "#850F0F", - "outlineColor": "#FFFFFF", - "outlineWidth": 3, - "fontSize": 68, - "fontName": "USMCCyuanjiantecu" - }, - "effectId": "intense-flash", - "effectDuration": null, - "color": "#850F0F", - "soundEffectId": "bubble", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "情感词", - "styleOverride": { - "fontName": "USMCCyuanjiantecu", - "fontSize": 24, - "fontColor": "#850F0F", - "outlineColor": "#FEFEFE", - "outlineWidth": 2 - }, - "effectId": "danmaku", - "effectDuration": null, - "color": "#850F0F", - "soundEffectId": null, - "soundEffectConfig": null - }, - { - "groupName": "描述词", - "styleOverride": { - "fontName": "USMCCyuanjiantecu", - "fontSize": 24, - "fontColor": "#850F0F", - "outlineColor": "#FFFFFF", - "outlineWidth": 3 - }, - "effectId": "flying-tilt", - "effectDuration": null, - "color": "#850F0F", - "soundEffectId": null, - "soundEffectConfig": null - }, - { - "groupName": "重点词/成语词", - "styleOverride": { - "fontColor": "#850F0F", - "outlineColor": "#FFFFFF", - "outlineWidth": 3, - "fontSize": 24, - "fontName": "USMCCyuanjiantecu" - }, - "effectId": "fly-in", - "effectDuration": null, - "color": "#850F0F", - "soundEffectId": "ding", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "12", - "styleOverride": null, - "effectId": null, - "effectDuration": null, - "color": null, - "soundEffectId": null, - "soundEffectConfig": null - } - ], - "screenWidth": 1920, - "screenHeight": 1080, - "fontSize": 48, - "fontFamily": "Arial, sans-serif", - "subtitleStyle": { - "id": "custom", - "name": "自定义样式", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "fontName": "USMCCyuanjiantecu", - "fontSize": 48, - "fontColor": "#EFE9E9", - "outlineColor": "#000000", - "outlineWidth": 3, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "shadowOffset": 0, - "shadowBlur": 4, - "shadowColor": "#000000" - }, - "titleSubtitleConfig": { - "enabled": true, - "sourceTitle": "有娃家庭马桶清洁妙招", - "maxCharsPerLine": 8, - "maxLines": 5, - "lineSpacingPercent": 5, - "topMarginPercent": 5, - "lines": [ - { - "text": "有娃家庭马桶清洁", - "fontName": "USMCCyuanjiantecu", - "fontSize": 80, - "fontColor": "#FFFFFF", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#a91919", - "outlineWidth": 3, - "shadowColor": "#850f0f", - "shadowOffset": 2, - "yOffsetPercent": 5 - }, - { - "text": "妙招", - "fontName": "USMCCyuanjiantecu", - "fontSize": 80, - "fontColor": "#a30f0f", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#ffffff", - "outlineWidth": 4, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 10 - } - ], - "startTime": 0, - "fadeInDuration": 0, - "fadeOutDuration": 0 - }, - "previewConfig": { - "backgroundKey": "portrait", - "backgroundPosition": "center 27%", - "overlayStartColor": "rgba(0, 0, 0, 0.08)", - "overlayEndColor": "rgba(0, 0, 0, 0.42)", - "subtitleTexts": [ - "平凡日常也能过得[闪闪发光]", - "心怀欢喜生活处处皆是[美好]" - ], - "backgroundImage": "extra/common/cover-templates/subtitle-preview-template_system_44.png", - "titleTexts": [ - "平凡日常也能过得闪闪发光", - "心怀欢喜生活处处皆是美好" - ] - } - }, - "createdAt": 1768396885441, - "isSystem": true, - "is_system": 1 - }, - { - "id": "template_system_classic_44", - "name": "44 Classic", - "description": "System subtitle template 44 classic original style", - "config": { - "subtitleStyleId": "system-subtitle-44", - "subtitleFontSizeScale": 100, - "subtitlePosition": "bottom", - "enableKeywordEffects": true, - "keywordGroupsStyles": [ - { - "groupName": "行动词", - "styleOverride": { - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 3, - "fontSize": 68, - "fontName": "字玩哥特黑白无常 免费 超黑" - }, - "effectId": "intense-flash", - "effectDuration": null, - "color": "#FFFFFF", - "soundEffectId": "magic-sfx", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "情感词", - "styleOverride": { - "fontColor": "#DDE3EC", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 64, - "fontName": "庞门正道标题体免费版" - }, - "effectId": "danmaku", - "effectDuration": null, - "color": "#DDE3EC", - "soundEffectId": "cash-register", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "描述词", - "styleOverride": { - "fontColor": "#DBC541", - "outlineColor": "#000000", - "outlineWidth": 7, - "fontSize": 88, - "fontName": "优设标题黑" - }, - "effectId": "flying-tilt", - "effectDuration": null, - "color": "#DBC541", - "soundEffectId": "pop-1", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "重点词/成语词", - "styleOverride": { - "fontColor": "#980C0CEC", - "outlineColor": "#000000", - "outlineWidth": 10, - "fontSize": 104, - "fontName": "字玩哥特黑白无常 免费 超黑" - }, - "effectId": "fly-in", - "effectDuration": null, - "color": "#980C0CEC", - "soundEffectId": "punch", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "12", - "styleOverride": null, - "effectId": null, - "effectDuration": null, - "color": null, - "soundEffectId": null, - "soundEffectConfig": null - } - ], - "screenWidth": 1920, - "screenHeight": 1080, - "fontSize": 48, - "fontFamily": "Arial, sans-serif", - "subtitleStyle": { - "id": "custom", - "name": "自定义样式", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "fontName": "USMCCyuanjiantecu", - "fontSize": 48, - "fontColor": "#EFE9E9", - "outlineColor": "#000000", - "outlineWidth": 3, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "shadowOffset": 0, - "shadowBlur": 4, - "shadowColor": "#000000" - }, - "titleSubtitleConfig": { - "enabled": true, - "sourceTitle": "芒格稳赢几十年的三件事", - "maxCharsPerLine": 8, - "maxLines": 5, - "lineSpacingPercent": 5, - "topMarginPercent": 5, - "lines": [ - { - "text": "芒格稳赢几十年的", - "fontName": "USMCCyuanjiantecu", - "fontSize": 80, - "fontColor": "#FFFFFF", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#a91919", - "outlineWidth": 3, - "shadowColor": "#850f0f", - "shadowOffset": 2, - "yOffsetPercent": 5 - }, - { - "text": "三件事", - "fontName": "USMCCyuanjiantecu", - "fontSize": 80, - "fontColor": "#a30f0f", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#ffffff", - "outlineWidth": 4, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 10 - } - ], - "startTime": 0, - "fadeInDuration": 0, - "fadeOutDuration": 0 - }, - "previewConfig": { - "backgroundImage": "extra/common/cover-templates/subtitle-preview-template_system_classic_44.png", - "titleTexts": [ - "平凡日常也能过得闪闪发光", - "心怀欢喜生活处处皆是美好" - ], - "subtitleTexts": [ - "平凡日常也能过得闪闪发光", - "心怀欢喜生活处处皆是美好" - ] - }, - "keywordRenderMode": "floating" - }, - "createdAt": 1768396885441, - "isSystem": true, - "is_system": 1 - }, - { - "id": "template_system_55", - "name": "55 Inline", - "description": "System subtitle template 55 inline keyword emphasis", - "config": { - "subtitleStyleId": "system-subtitle-55", - "subtitleFontSizeScale": 100, - "subtitlePosition": "bottom", - "enableKeywordEffects": true, - "keywordRenderMode": "inline-emphasis", - "keywordGroupsStyles": [ - { - "groupName": "行动词", - "styleOverride": { - "fontColor": "#FFFF00", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 24, - "fontName": "月星楷" - }, - "effectId": "intense-flash", - "effectDuration": null, - "color": "#FFFF00", - "soundEffectId": "bubble", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "情感词", - "styleOverride": { - "fontColor": "#FFFF00", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 24, - "fontName": "月星楷" - }, - "effectId": "danmaku", - "effectDuration": null, - "color": "#FFFF00", - "soundEffectId": null, - "soundEffectConfig": null - }, - { - "groupName": "描述词", - "styleOverride": { - "fontColor": "#FFFF00", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 24, - "fontName": "月星楷" - }, - "effectId": "flying-tilt", - "effectDuration": null, - "color": "#FFFF00", - "soundEffectId": null, - "soundEffectConfig": null - }, - { - "groupName": "重点词/成语词", - "styleOverride": { - "fontColor": "#FFFF00", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 24, - "fontName": "月星楷" - }, - "effectId": "fly-in", - "effectDuration": null, - "color": "#FFFF00", - "soundEffectId": "ding", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "12", - "styleOverride": null, - "effectId": null, - "effectDuration": null, - "color": null, - "soundEffectId": null, - "soundEffectConfig": null - } - ], - "screenWidth": 1920, - "screenHeight": 1080, - "fontSize": 48, - "fontFamily": "Arial, sans-serif", - "subtitleStyle": { - "id": "custom", - "name": "自定义样式", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "fontName": "月星楷", - "fontSize": 48, - "fontColor": "#FFFFFF", - "outlineColor": "#FFFFFF", - "outlineWidth": 0, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "shadowOffset": 3, - "shadowBlur": 4, - "shadowColor": "#000000" - }, - "titleSubtitleConfig": { - "enabled": true, - "sourceTitle": "有娃家庭马桶简直是灾难现场", - "maxCharsPerLine": 15, - "maxLines": 5, - "lineSpacingPercent": 7, - "topMarginPercent": 5, - "lines": [ - { - "text": "有娃家庭马桶简直是灾难现场", - "fontName": "千图厚黑体", - "fontSize": 75, - "fontColor": "#d2d459", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 0, - "shadowColor": "#000000", - "shadowOffset": 3, - "yOffsetPercent": 5 - } - ], - "startTime": 0, - "fadeInDuration": 0, - "fadeOutDuration": 0 - }, - "previewConfig": { - "backgroundKey": "portrait", - "backgroundPosition": "center 28%", - "overlayStartColor": "rgba(7, 10, 17, 0.12)", - "overlayEndColor": "rgba(7, 10, 17, 0.5)", - "subtitleTexts": [ - "不必讨好世界[取悦]自己就好", - "随心而行人生自在且[从容]" - ], - "backgroundImage": "extra/common/cover-templates/subtitle-preview-template_system_55.png", - "titleTexts": [ - "不必讨好世界取悦自己就好", - "随心而行人生自在且从容" - ] - } - }, - "createdAt": 1768396885442, - "isSystem": true, - "is_system": 1 - }, - { - "id": "template_system_classic_55", - "name": "55 Classic", - "description": "System subtitle template 55 classic original style", - "config": { - "subtitleStyleId": "system-subtitle-55", - "subtitleFontSizeScale": 100, - "subtitlePosition": "bottom", - "enableKeywordEffects": true, - "keywordGroupsStyles": [ - { - "groupName": "行动词", - "styleOverride": { - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 3, - "fontSize": 68, - "fontName": "字玩哥特黑白无常 免费 超黑" - }, - "effectId": "intense-flash", - "color": "#FFFFFF", - "soundEffectId": "magic-sfx", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "情感词", - "styleOverride": { - "fontColor": "#DDE3EC", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 64, - "fontName": "庞门正道标题体免费版" - }, - "effectId": "danmaku", - "color": "#DDE3EC", - "soundEffectId": "cash-register", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "描述词", - "styleOverride": { - "fontColor": "#DBC541", - "outlineColor": "#000000", - "outlineWidth": 7, - "fontSize": 88, - "fontName": "优设标题黑" - }, - "effectId": "flying-tilt", - "color": "#DBC541", - "soundEffectId": "pop-1", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "重点词/成语词", - "styleOverride": { - "fontColor": "#980C0CEC", - "outlineColor": "#000000", - "outlineWidth": 10, - "fontSize": 104, - "fontName": "字玩哥特黑白无常 免费 超黑" - }, - "effectId": "fly-in", - "color": "#980C0CEC", - "soundEffectId": "punch", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "12", - "effectId": null, - "color": null, - "soundEffectId": null - } - ], - "screenWidth": 1920, - "screenHeight": 1080, - "fontSize": 48, - "fontFamily": "Arial, sans-serif", - "subtitleStyle": { - "id": "custom", - "name": "自定义样式", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "fontName": "Microsoft YaHei Bold", - "fontSize": 48, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 4, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "shadowOffset": 2, - "shadowBlur": 4, - "shadowColor": "#000000" - }, - "titleSubtitleConfig": { - "enabled": true, - "sourceTitle": "芒格稳赢几十年的三件事", - "maxCharsPerLine": 15, - "maxLines": 5, - "lineSpacingPercent": 7, - "topMarginPercent": 5, - "lines": [ - { - "text": "芒格稳赢几十年的三件事", - "fontName": "千图厚黑体", - "fontSize": 100, - "fontColor": "#efc52e", - "backgroundColor": "#ffffff", - "backgroundOpacity": 0.5, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 3, - "yOffsetPercent": 5 - } - ], - "startTime": 0, - "fadeInDuration": 0, - "fadeOutDuration": 0 - }, - "previewConfig": { - "backgroundImage": "extra/common/cover-templates/subtitle-preview-template_system_classic_55.png", - "titleTexts": [ - "不必讨好世界取悦自己就好", - "随心而行人生自在且从容" - ], - "subtitleTexts": [ - "不必讨好世界取悦自己就好", - "随心而行人生自在且从容" - ] - } - }, - "createdAt": 1768396885442, - "isSystem": true, - "is_system": 1 - }, - { - "id": "template_system_66", - "name": "66 Inline", - "description": "System subtitle template 66 inline keyword emphasis", - "config": { - "subtitleStyleId": "system-subtitle-66", - "subtitleFontSizeScale": 100, - "subtitlePosition": "bottom", - "enableKeywordEffects": true, - "keywordRenderMode": "inline-emphasis", - "keywordGroupsStyles": [ - { - "groupName": "行动词", - "styleOverride": { - "fontColor": "#F13B83", - "outlineColor": "#FFFFFF", - "outlineWidth": 5, - "fontSize": 68, - "fontName": "杨任东竹石体" - }, - "effectId": "intense-flash", - "effectDuration": null, - "color": "#F13B83", - "soundEffectId": "bubble", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "情感词", - "styleOverride": { - "fontColor": "#F13B83", - "outlineColor": "#FFFFFF", - "outlineWidth": 5, - "fontSize": 24, - "fontName": "杨任东竹石体" - }, - "effectId": "danmaku", - "effectDuration": null, - "color": "#F13B83", - "soundEffectId": null, - "soundEffectConfig": null - }, - { - "groupName": "描述词", - "styleOverride": { - "fontColor": "#F13B83", - "outlineColor": "#FFFFFF", - "outlineWidth": 5, - "fontSize": 24, - "fontName": "杨任东竹石体" - }, - "effectId": "flying-tilt", - "effectDuration": null, - "color": "#F13B83", - "soundEffectId": null, - "soundEffectConfig": null - }, - { - "groupName": "重点词/成语词", - "styleOverride": { - "fontColor": "#F13B83", - "outlineColor": "#FEFEFE", - "outlineWidth": 5, - "fontSize": 24, - "fontName": "杨任东竹石体" - }, - "effectId": "fly-in", - "effectDuration": null, - "color": "#F13B83", - "soundEffectId": "ding", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "12", - "styleOverride": null, - "effectId": null, - "effectDuration": null, - "color": null, - "soundEffectId": null, - "soundEffectConfig": null - } - ], - "screenWidth": 1920, - "screenHeight": 1080, - "fontSize": 48, - "fontFamily": "Arial, sans-serif", - "subtitleStyle": { - "id": "custom", - "name": "自定义样式", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "fontName": "杨任东竹石体", - "fontSize": 48, - "fontColor": "#FFFFFF", - "outlineColor": "#F13B83", - "outlineWidth": 3, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "shadowOffset": 1, - "shadowBlur": 4, - "shadowColor": "#000000" - }, - "titleSubtitleConfig": { - "enabled": true, - "sourceTitle": "有娃家庭马桶简直是灾难现场", - "maxCharsPerLine": 15, - "maxLines": 5, - "lineSpacingPercent": 7, - "topMarginPercent": 5, - "lines": [ - { - "text": "有娃家庭马桶简直是灾难现场", - "fontName": "猫啃珠圆体 MaokenZhuyuanTi", - "fontSize": 90, - "fontColor": "#f59ed1", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 3, - "yOffsetPercent": 5 - } - ], - "startTime": 0, - "fadeInDuration": 0, - "fadeOutDuration": 0 - }, - "previewConfig": { - "backgroundKey": "portrait", - "backgroundPosition": "center 29%", - "overlayStartColor": "rgba(0, 0, 0, 0.1)", - "overlayEndColor": "rgba(0, 0, 0, 0.46)", - "subtitleTexts": [ - "把烦恼清空让[快乐]住进心里", - "保持[热爱]奔赴每一场新遇见" - ], - "backgroundImage": "extra/common/cover-templates/subtitle-preview-template_system_66.png", - "titleTexts": [ - "把烦恼清空让快乐住进心里", - "保持热爱奔赴每一场新遇见" - ] - } - }, - "createdAt": 1768396885443, - "isSystem": true, - "is_system": 1 - }, - { - "id": "template_system_classic_66", - "name": "66 Classic", - "description": "System subtitle template 66 classic original style", - "config": { - "subtitleStyleId": "system-subtitle-66", - "subtitleFontSizeScale": 100, - "subtitlePosition": "bottom", - "enableKeywordEffects": true, - "keywordGroupsStyles": [ - { - "groupName": "行动词", - "styleOverride": { - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 3, - "fontSize": 68, - "fontName": "字玩哥特黑白无常 免费 超黑" - }, - "effectId": "intense-flash", - "effectDuration": null, - "color": "#FFFFFF", - "soundEffectId": "magic-sfx", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "情感词", - "styleOverride": { - "fontColor": "#DDE3EC", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 64, - "fontName": "庞门正道标题体免费版" - }, - "effectId": "danmaku", - "effectDuration": null, - "color": "#DDE3EC", - "soundEffectId": "cash-register", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "描述词", - "styleOverride": { - "fontColor": "#DBC541", - "outlineColor": "#000000", - "outlineWidth": 7, - "fontSize": 88, - "fontName": "优设标题黑" - }, - "effectId": "flying-tilt", - "effectDuration": null, - "color": "#DBC541", - "soundEffectId": "pop-1", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "重点词/成语词", - "styleOverride": { - "fontColor": "#980C0CEC", - "outlineColor": "#000000", - "outlineWidth": 10, - "fontSize": 104, - "fontName": "字玩哥特黑白无常 免费 超黑" - }, - "effectId": "fly-in", - "effectDuration": null, - "color": "#980C0CEC", - "soundEffectId": "punch", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "12", - "styleOverride": null, - "effectId": null, - "effectDuration": null, - "color": null, - "soundEffectId": null, - "soundEffectConfig": null - } - ], - "screenWidth": 1920, - "screenHeight": 1080, - "fontSize": 48, - "fontFamily": "Arial, sans-serif", - "subtitleStyle": { - "id": "custom", - "name": "自定义样式", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "fontName": "杨任东竹石体", - "fontSize": 48, - "fontColor": "#FFFFFF", - "outlineColor": "#F13B83", - "outlineWidth": 3, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "shadowOffset": 1, - "shadowBlur": 4, - "shadowColor": "#000000" - }, - "titleSubtitleConfig": { - "enabled": true, - "sourceTitle": "芒格稳赢几十年的三件事", - "maxCharsPerLine": 15, - "maxLines": 5, - "lineSpacingPercent": 7, - "topMarginPercent": 5, - "lines": [ - { - "text": "芒格稳赢几十年的三件事", - "fontName": "千图厚黑体", - "fontSize": 90, - "fontColor": "#f59ed1", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 3, - "yOffsetPercent": 5 - } - ], - "startTime": 0, - "fadeInDuration": 0, - "fadeOutDuration": 0 - }, - "previewConfig": { - "backgroundImage": "extra/common/cover-templates/subtitle-preview-template_system_classic_66.png", - "titleTexts": [ - "把烦恼清空让快乐住进心里", - "保持热爱奔赴每一场新遇见" - ], - "subtitleTexts": [ - "把烦恼清空让快乐住进心里", - "保持热爱奔赴每一场新遇见" - ] - } - }, - "createdAt": 1768396885443, - "isSystem": true, - "is_system": 1 - }, - { - "id": "template_system_77", - "name": "77 Inline", - "description": "System subtitle template 77 inline keyword emphasis", - "config": { - "subtitleStyleId": "system-subtitle-77", - "subtitleFontSizeScale": 100, - "subtitlePosition": "bottom", - "enableKeywordEffects": true, - "keywordRenderMode": "inline-emphasis", - "keywordGroupsStyles": [ - { - "groupName": "行动词", - "styleOverride": { - "fontColor": "#FFFF00", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 68, - "fontName": "文鼎PL简中楷" - }, - "effectId": "intense-flash", - "effectDuration": null, - "color": "#FFFF00", - "soundEffectId": "bubble", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "情感词", - "styleOverride": { - "fontName": "文鼎PL简中楷", - "fontSize": 24, - "fontColor": "#FFFF00", - "outlineColor": "#000000", - "outlineWidth": 2 - }, - "effectId": "danmaku", - "effectDuration": null, - "color": "#FFFF00", - "soundEffectId": null, - "soundEffectConfig": null - }, - { - "groupName": "描述词", - "styleOverride": { - "fontName": "文鼎PL简中楷", - "fontSize": 24, - "fontColor": "#FFFF00", - "outlineColor": "#000000", - "outlineWidth": 2 - }, - "effectId": "flying-tilt", - "effectDuration": null, - "color": "#FFFF00", - "soundEffectId": null, - "soundEffectConfig": null - }, - { - "groupName": "重点词/成语词", - "styleOverride": { - "fontColor": "#FFFF00", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 24, - "fontName": "文鼎PL简中楷" - }, - "effectId": "fly-in", - "effectDuration": null, - "color": "#FFFF00", - "soundEffectId": "ding", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "12", - "styleOverride": null, - "effectId": null, - "effectDuration": null, - "color": null, - "soundEffectId": null, - "soundEffectConfig": null - } - ], - "screenWidth": 1920, - "screenHeight": 1080, - "fontSize": 48, - "fontFamily": "Arial, sans-serif", - "subtitleStyle": { - "id": "custom", - "name": "自定义样式", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "fontName": "文鼎PL简中楷", - "fontSize": 48, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 2, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "shadowOffset": 0, - "shadowBlur": 4, - "shadowColor": "#000000" - }, - "titleSubtitleConfig": { - "enabled": true, - "sourceTitle": "有娃家庭马桶简直是灾难现场", - "maxCharsPerLine": 8, - "maxLines": 5, - "lineSpacingPercent": 6, - "topMarginPercent": 5, - "lines": [ - { - "text": "有娃家庭马桶简直", - "fontName": "方正粗黑宋简体", - "fontSize": 80, - "fontColor": "#ffffff", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 5 - }, - { - "text": "是灾难现场", - "fontName": "方正粗黑宋简体", - "fontSize": 77, - "fontColor": "#0dade3", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 11 - } - ], - "startTime": 0, - "fadeInDuration": 0, - "fadeOutDuration": 0 - }, - "previewConfig": { - "backgroundKey": "portrait", - "backgroundPosition": "center 26%", - "overlayStartColor": "rgba(0, 0, 0, 0.08)", - "overlayEndColor": "rgba(0, 0, 0, 0.44)", - "subtitleTexts": [ - "努力活成自己[喜欢]的模样", - "不慌不忙静待时光的[绽放]" - ], - "backgroundImage": "extra/common/cover-templates/subtitle-preview-template_system_77.png", - "titleTexts": [ - "努力活成自己喜欢的模样", - "不慌不忙静待时光的绽放" - ] - } - }, - "createdAt": 1768396885444, - "isSystem": true, - "is_system": 1 - }, - { - "id": "template_system_classic_77", - "name": "77 Classic", - "description": "System subtitle template 77 classic original style", - "config": { - "subtitleStyleId": "system-subtitle-77", - "subtitleFontSizeScale": 100, - "subtitlePosition": "bottom", - "enableKeywordEffects": true, - "keywordGroupsStyles": [ - { - "groupName": "行动词", - "styleOverride": { - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 3, - "fontSize": 68, - "fontName": "字玩哥特黑白无常 免费 超黑" - }, - "effectId": "intense-flash", - "effectDuration": null, - "color": "#FFFFFF", - "soundEffectId": "magic-sfx", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "情感词", - "styleOverride": { - "fontColor": "#DDE3EC", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 64, - "fontName": "庞门正道标题体免费版" - }, - "effectId": "danmaku", - "effectDuration": null, - "color": "#DDE3EC", - "soundEffectId": "cash-register", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "描述词", - "styleOverride": { - "fontColor": "#DBC541", - "outlineColor": "#000000", - "outlineWidth": 7, - "fontSize": 88, - "fontName": "优设标题黑" - }, - "effectId": "flying-tilt", - "effectDuration": null, - "color": "#DBC541", - "soundEffectId": "pop-1", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "重点词/成语词", - "styleOverride": { - "fontColor": "#980C0CEC", - "outlineColor": "#000000", - "outlineWidth": 10, - "fontSize": 104, - "fontName": "字玩哥特黑白无常 免费 超黑" - }, - "effectId": "fly-in", - "effectDuration": null, - "color": "#980C0CEC", - "soundEffectId": "punch", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "12", - "styleOverride": null, - "effectId": null, - "effectDuration": null, - "color": null, - "soundEffectId": null, - "soundEffectConfig": null - } - ], - "screenWidth": 1920, - "screenHeight": 1080, - "fontSize": 48, - "fontFamily": "Arial, sans-serif", - "subtitleStyle": { - "id": "custom", - "name": "自定义样式", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "fontName": "杨任东竹石体", - "fontSize": 48, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 0, - "backgroundColor": "#000000", - "backgroundOpacity": 0.5, - "position": "bottom", - "shadowOffset": 0, - "shadowBlur": 4, - "shadowColor": "#000000" - }, - "titleSubtitleConfig": { - "enabled": true, - "sourceTitle": "芒格稳赢几十年的三件事", - "maxCharsPerLine": 8, - "maxLines": 5, - "lineSpacingPercent": 7, - "topMarginPercent": 5, - "lines": [ - { - "text": "芒格稳赢几十年的", - "fontName": "字玩哥特黑白无常 免费 超黑", - "fontSize": 80, - "fontColor": "#0a7194", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 5 - }, - { - "text": "三件事", - "fontName": "字玩哥特黑白无常 免费 超黑", - "fontSize": 77, - "fontColor": "#0a7194", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 12 - } - ], - "startTime": 0, - "fadeInDuration": 0, - "fadeOutDuration": 0 - }, - "previewConfig": { - "backgroundImage": "extra/common/cover-templates/subtitle-preview-template_system_classic_77.png", - "titleTexts": [ - "努力活成自己喜欢的模样", - "不慌不忙静待时光的绽放" - ], - "subtitleTexts": [ - "努力活成自己喜欢的模样", - "不慌不忙静待时光的绽放" - ] - }, - "keywordRenderMode": "floating" - }, - "createdAt": 1768396885444, - "isSystem": true, - "is_system": 1 - }, - { - "id": "template_system_88", - "name": "88 Inline", - "description": "System subtitle template 88 inline keyword emphasis", - "config": { - "subtitleStyleId": "system-subtitle-88", - "subtitleFontSizeScale": 90, - "subtitlePosition": "bottom", - "enableKeywordEffects": true, - "keywordRenderMode": "inline-emphasis", - "keywordGroupsStyles": [ - { - "groupName": "行动词", - "styleOverride": { - "fontColor": "#21A7EE", - "outlineColor": "#FFFFFF", - "outlineWidth": 2, - "fontSize": 24, - "fontName": "庞门正道标题体免费版" - }, - "effectId": "intense-flash", - "effectDuration": null, - "color": "#21A7EE", - "soundEffectId": "bubble", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "情感词", - "styleOverride": { - "fontColor": "#21A7EE", - "outlineColor": "#FFFFFF", - "outlineWidth": 2, - "fontSize": 24, - "fontName": "庞门正道标题体免费版" - }, - "effectId": "danmaku", - "effectDuration": null, - "color": "#21A7EE", - "soundEffectId": null, - "soundEffectConfig": null - }, - { - "groupName": "描述词", - "styleOverride": { - "fontColor": "#21A7EE", - "outlineColor": "#FFFFFF", - "outlineWidth": 2, - "fontSize": 24, - "fontName": "庞门正道标题体免费版" - }, - "effectId": "flying-tilt", - "effectDuration": null, - "color": "#21A7EE", - "soundEffectId": null, - "soundEffectConfig": null - }, - { - "groupName": "重点词/成语词", - "styleOverride": { - "fontColor": "#21A7EE", - "outlineColor": "#FFFFFF", - "outlineWidth": 2, - "fontSize": 28, - "fontName": "庞门正道标题体免费版" - }, - "effectId": "fly-in", - "effectDuration": null, - "color": "#21A7EE", - "soundEffectId": "ding", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "12", - "styleOverride": null, - "effectId": null, - "effectDuration": null, - "color": null, - "soundEffectId": null, - "soundEffectConfig": null - } - ], - "screenWidth": 1920, - "screenHeight": 1080, - "fontSize": 48, - "fontFamily": "Arial, sans-serif", - "subtitleStyle": { - "id": "custom", - "name": "自定义样式", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "fontName": "庞门正道标题体免费版", - "fontSize": 39, - "fontColor": "#000000", - "outlineColor": "#FFFFFF", - "outlineWidth": 2, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "shadowOffset": 0, - "shadowBlur": 4, - "shadowColor": "#000000" - }, - "titleSubtitleConfig": { - "enabled": true, - "sourceTitle": "有娃家庭马桶简直是灾难现场", - "maxCharsPerLine": 8, - "maxLines": 5, - "lineSpacingPercent": 5, - "topMarginPercent": 5, - "lines": [ - { - "text": "有娃家庭马桶简直", - "fontName": "优设标题黑", - "fontSize": 80, - "fontColor": "#FFFFFF", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 5 - }, - { - "text": "是灾难现场", - "fontName": "思源黑体 Normal", - "fontSize": 75, - "fontColor": "#000000", - "backgroundColor": "#ffffff", - "backgroundOpacity": 1, - "outlineColor": "#000000", - "outlineWidth": 0, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 10 - } - ], - "startTime": 0, - "fadeInDuration": 0, - "fadeOutDuration": 0 - }, - "previewConfig": { - "backgroundKey": "portrait", - "backgroundPosition": "center 27%", - "overlayStartColor": "rgba(0, 0, 0, 0.12)", - "overlayEndColor": "rgba(0, 0, 0, 0.5)", - "subtitleTexts": [ - "生活一半[烟火]一半诗意清欢", - "心怀[温柔]遇见所有小美好" - ], - "backgroundImage": "extra/common/cover-templates/subtitle-preview-template_system_88.png", - "titleTexts": [ - "生活一半烟火一半诗意清欢", - "心怀温柔遇见所有小美好" - ] - } - }, - "createdAt": 1768396885445, - "isSystem": true, - "is_system": 1 - }, - { - "id": "template_system_classic_88", - "name": "88 Classic", - "description": "System subtitle template 88 classic original style", - "config": { - "subtitleStyleId": "system-subtitle-88", - "subtitleFontSizeScale": 100, - "subtitlePosition": "bottom", - "enableKeywordEffects": true, - "keywordGroupsStyles": [ - { - "groupName": "行动词", - "styleOverride": { - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 3, - "fontSize": 68, - "fontName": "字玩哥特黑白无常 免费 超黑" - }, - "effectId": "intense-flash", - "effectDuration": null, - "color": "#FFFFFF", - "soundEffectId": "magic-sfx", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "情感词", - "styleOverride": { - "fontColor": "#DDE3EC", - "outlineColor": "#000000", - "outlineWidth": 2, - "fontSize": 64, - "fontName": "庞门正道标题体免费版" - }, - "effectId": "danmaku", - "effectDuration": null, - "color": "#DDE3EC", - "soundEffectId": "cash-register", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "描述词", - "styleOverride": { - "fontColor": "#DBC541", - "outlineColor": "#000000", - "outlineWidth": 7, - "fontSize": 88, - "fontName": "优设标题黑" - }, - "effectId": "flying-tilt", - "effectDuration": null, - "color": "#DBC541", - "soundEffectId": "pop-1", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "重点词/成语词", - "styleOverride": { - "fontColor": "#980C0CEC", - "outlineColor": "#000000", - "outlineWidth": 10, - "fontSize": 104, - "fontName": "字玩哥特黑白无常 免费 超黑" - }, - "effectId": "fly-in", - "effectDuration": null, - "color": "#980C0CEC", - "soundEffectId": "punch", - "soundEffectConfig": { - "volume": 0.7, - "pitch": 1, - "fadeIn": 0, - "fadeOut": 50, - "triggerTime": "start" - } - }, - { - "groupName": "12", - "styleOverride": null, - "effectId": null, - "effectDuration": null, - "color": null, - "soundEffectId": null, - "soundEffectConfig": null - } - ], - "screenWidth": 1920, - "screenHeight": 1080, - "fontSize": 48, - "fontFamily": "Arial, sans-serif", - "subtitleStyle": { - "id": "custom", - "name": "自定义样式", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "fontName": "庞门正道标题体免费版", - "fontSize": 48, - "fontColor": "#DC8A13", - "outlineColor": "#000000", - "outlineWidth": 2, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "shadowOffset": 0, - "shadowBlur": 4, - "shadowColor": "#000000" - }, - "titleSubtitleConfig": { - "enabled": true, - "sourceTitle": "芒格稳赢几十年的三件事", - "maxCharsPerLine": 8, - "maxLines": 5, - "lineSpacingPercent": 7, - "topMarginPercent": 5, - "lines": [ - { - "text": "芒格稳赢几十年的", - "fontName": "喜脉体", - "fontSize": 80, - "fontColor": "#FFFFFF", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 5 - }, - { - "text": "三件事", - "fontName": "喜脉体", - "fontSize": 80, - "fontColor": "#be6009", - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowColor": "#000000", - "shadowOffset": 2, - "yOffsetPercent": 12 - } - ], - "startTime": 0, - "fadeInDuration": 0, - "fadeOutDuration": 0 - }, - "previewConfig": { - "backgroundImage": "extra/common/cover-templates/subtitle-preview-template_system_classic_88.png", - "titleTexts": [ - "生活一半烟火一半诗意清欢", - "心怀温柔遇见所有小美好" - ], - "subtitleTexts": [ - "生活一半烟火一半诗意清欢", - "心怀温柔遇见所有小美好" - ] - } - }, - "createdAt": 1768396885445, - "isSystem": true, - "is_system": 1 - } - ], - "subtitleStyles": [ - { - "id": "custom", - "name": "自定义样式", - "description": null, - "preview": "示例文字", - "is_system": 1, - "fontName": "1.程荣光刻楷", - "fontSize": 48, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowOffset": 0, - "shadowColor": "#000000", - "shadowBlur": null, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": "center" - }, - { - "id": "system-subtitle-11", - "name": "11", - "description": "Clean short-video subtitle style", - "preview": "示例文案", - "is_system": 1, - "fontName": "Microsoft YaHei UI Bold", - "fontSize": 50, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 4, - "shadowOffset": 2, - "shadowColor": "#000000", - "shadowBlur": 4, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": null - }, - { - "id": "system-subtitle-22", - "name": "22", - "description": "Clean short-video subtitle style", - "preview": "示例文案", - "is_system": 1, - "fontName": "Microsoft YaHei UI Bold", - "fontSize": 50, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 4, - "shadowOffset": 2, - "shadowColor": "#000000", - "shadowBlur": 4, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": null - }, - { - "id": "system-subtitle-33", - "name": "33", - "description": "Clean short-video subtitle style", - "preview": "示例文案", - "is_system": 1, - "fontName": "Microsoft YaHei UI Bold", - "fontSize": 50, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 4, - "shadowOffset": 2, - "shadowColor": "#000000", - "shadowBlur": 4, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": null - }, - { - "id": "system-subtitle-44", - "name": "44", - "description": "Clean short-video subtitle style", - "preview": "示例文案", - "is_system": 1, - "fontName": "Microsoft YaHei UI Bold", - "fontSize": 50, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 4, - "shadowOffset": 2, - "shadowColor": "#000000", - "shadowBlur": 4, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": null - }, - { - "id": "system-subtitle-55", - "name": "55", - "description": "Clean short-video subtitle style", - "preview": "示例文案", - "is_system": 1, - "fontName": "Microsoft YaHei UI Bold", - "fontSize": 50, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 4, - "shadowOffset": 2, - "shadowColor": "#000000", - "shadowBlur": 4, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": null - }, - { - "id": "system-subtitle-66", - "name": "66", - "description": "Clean short-video subtitle style", - "preview": "示例文案", - "is_system": 1, - "fontName": "Microsoft YaHei UI Bold", - "fontSize": 50, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 4, - "shadowOffset": 2, - "shadowColor": "#000000", - "shadowBlur": 4, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": null - }, - { - "id": "system-subtitle-77", - "name": "77", - "description": "Clean short-video subtitle style", - "preview": "示例文案", - "is_system": 1, - "fontName": "Microsoft YaHei UI Bold", - "fontSize": 50, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 4, - "shadowOffset": 2, - "shadowColor": "#000000", - "shadowBlur": 4, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": null - }, - { - "id": "system-subtitle-88", - "name": "88", - "description": "Clean short-video subtitle style", - "preview": "示例文案", - "is_system": 1, - "fontName": "Microsoft YaHei UI Bold", - "fontSize": 50, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 4, - "shadowOffset": 2, - "shadowColor": "#000000", - "shadowBlur": 4, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": null - }, - { - "id": "system-subtitle-classic-11", - "name": "11 Classic", - "description": "自定义字幕样式 - 黑底白字,精致描边", - "preview": "示例文字", - "is_system": 1, - "fontName": "优设标题黑", - "fontSize": 34, - "fontColor": "#35A9E2", - "outlineColor": "#000000", - "outlineWidth": 1, - "shadowOffset": 2, - "shadowColor": "#000000", - "shadowBlur": 4, - "backgroundColor": "transparent", - "backgroundOpacity": 0.3, - "position": "bottom", - "alignment": null - }, - { - "id": "system-subtitle-classic-22", - "name": "22 Classic", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "is_system": 1, - "fontName": "月星楷", - "fontSize": 34, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowOffset": 2, - "shadowColor": "#000000", - "shadowBlur": 4, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": null - }, - { - "id": "system-subtitle-classic-33", - "name": "33 Classic", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "is_system": 1, - "fontName": "庞门正道标题体免费版", - "fontSize": 34, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowOffset": 2, - "shadowColor": "#000000", - "shadowBlur": 4, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": null - }, - { - "id": "system-subtitle-classic-44", - "name": "44 Classic", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "is_system": 1, - "fontName": "USMCCyuanjiantecu", - "fontSize": 34, - "fontColor": "#EFE9E9", - "outlineColor": "#000000", - "outlineWidth": 3, - "shadowOffset": 0, - "shadowColor": "#000000", - "shadowBlur": 4, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": null - }, - { - "id": "system-subtitle-classic-55", - "name": "55 Classic", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "is_system": 1, - "fontName": "Microsoft YaHei Bold", - "fontSize": 34, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 4, - "shadowOffset": 2, - "shadowColor": "#000000", - "shadowBlur": 4, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": null - }, - { - "id": "system-subtitle-classic-66", - "name": "66 Classic", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "is_system": 1, - "fontName": "杨任东竹石体", - "fontSize": 34, - "fontColor": "#FFFFFF", - "outlineColor": "#F13B83", - "outlineWidth": 3, - "shadowOffset": 1, - "shadowColor": "#000000", - "shadowBlur": 4, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": null - }, - { - "id": "system-subtitle-classic-77", - "name": "77 Classic", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "is_system": 1, - "fontName": "杨任东竹石体", - "fontSize": 34, - "fontColor": "#FFFFFF", - "outlineColor": "#000000", - "outlineWidth": 0, - "shadowOffset": 0, - "shadowColor": "#000000", - "shadowBlur": 4, - "backgroundColor": "#000000", - "backgroundOpacity": 0.5, - "position": "bottom", - "alignment": null - }, - { - "id": "system-subtitle-classic-88", - "name": "88 Classic", - "description": "完全自定义的字幕样式", - "preview": "示例文字", - "is_system": 1, - "fontName": "庞门正道标题体免费版", - "fontSize": 34, - "fontColor": "#DC8A13", - "outlineColor": "#000000", - "outlineWidth": 2, - "shadowOffset": 0, - "shadowColor": "#000000", - "shadowBlur": 4, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": null - }, - { - "id": "system-subtitle-template_system_100", - "name": "10 Inline", - "description": "Clean short-video subtitle style", - "preview": "示例文案", - "is_system": 1, - "fontName": "千图厚黑体", - "fontSize": 27, - "fontColor": "#111111", - "outlineColor": "#FFFFFF", - "outlineWidth": 1.1, - "shadowOffset": 0, - "shadowColor": "#FFFFFF", - "shadowBlur": 0, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": "center" - }, - { - "id": "system-subtitle-template_system_11", - "name": "11 Inline", - "description": "Clean short-video subtitle style", - "preview": "示例文案", - "is_system": 1, - "fontName": "优设标题黑", - "fontSize": 26, - "fontColor": "#FFFFFF", - "outlineColor": "#111111", - "outlineWidth": 1.1, - "shadowOffset": 0, - "shadowColor": "#111111", - "shadowBlur": 0, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": "center" - }, - { - "id": "system-subtitle-template_system_22", - "name": "22 Inline", - "description": "Clean short-video subtitle style", - "preview": "示例文案", - "is_system": 1, - "fontName": "优设标题黑", - "fontSize": 26, - "fontColor": "#FFFFFF", - "outlineColor": "#111111", - "outlineWidth": 1.1, - "shadowOffset": 0, - "shadowColor": "#111111", - "shadowBlur": 0, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": "center" - }, - { - "id": "system-subtitle-template_system_33", - "name": "33 Inline", - "description": "Clean short-video subtitle style", - "preview": "示例文案", - "is_system": 1, - "fontName": "字玩哥特黑白无常 免费 超黑", - "fontSize": 27, - "fontColor": "#FFFFFF", - "outlineColor": "#111111", - "outlineWidth": 1.1, - "shadowOffset": 0, - "shadowColor": "#111111", - "shadowBlur": 0, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": "center" - }, - { - "id": "system-subtitle-template_system_44", - "name": "44 Inline", - "description": "Clean short-video subtitle style", - "preview": "示例文案", - "is_system": 1, - "fontName": "千图厚黑体", - "fontSize": 26, - "fontColor": "#101010", - "outlineColor": "#FFFFFF", - "outlineWidth": 1.1, - "shadowOffset": 0, - "shadowColor": "#FFFFFF", - "shadowBlur": 0, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": "center" - }, - { - "id": "system-subtitle-template_system_55", - "name": "55 Inline", - "description": "Clean short-video subtitle style", - "preview": "示例文案", - "is_system": 1, - "fontName": "USMCCyuanjiantecu", - "fontSize": 27, - "fontColor": "#111111", - "outlineColor": "#FFFFFF", - "outlineWidth": 1.1, - "shadowOffset": 0, - "shadowColor": "#FFFFFF", - "shadowBlur": 0, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": "center" - }, - { - "id": "system-subtitle-template_system_66", - "name": "66 Inline", - "description": "Clean short-video subtitle style", - "preview": "示例文案", - "is_system": 1, - "fontName": "千图厚黑体", - "fontSize": 27, - "fontColor": "#FFF8D1", - "outlineColor": "#111111", - "outlineWidth": 1.1, - "shadowOffset": 0, - "shadowColor": "#111111", - "shadowBlur": 0, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": "center" - }, - { - "id": "system-subtitle-template_system_77", - "name": "77 Inline", - "description": "Clean short-video subtitle style", - "preview": "示例文案", - "is_system": 1, - "fontName": "字玩哥特黑白无常 免费 超黑", - "fontSize": 27, - "fontColor": "#111111", - "outlineColor": "#FFFFFF", - "outlineWidth": 1.1, - "shadowOffset": 0, - "shadowColor": "#FFFFFF", - "shadowBlur": 0, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": "center" - }, - { - "id": "system-subtitle-template_system_88", - "name": "88 Inline", - "description": "Clean short-video subtitle style", - "preview": "示例文案", - "is_system": 1, - "fontName": "优设标题黑", - "fontSize": 27, - "fontColor": "#FFFFFF", - "outlineColor": "#111111", - "outlineWidth": 1.1, - "shadowOffset": 0, - "shadowColor": "#111111", - "shadowBlur": 0, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": "center" - }, - { - "id": "system-subtitle-template_system_99", - "name": "09 Inline", - "description": "Clean short-video subtitle style", - "preview": "示例文案", - "is_system": 1, - "fontName": "优设标题黑", - "fontSize": 27, - "fontColor": "#FFFFFF", - "outlineColor": "#111111", - "outlineWidth": 1.1, - "shadowOffset": 0, - "shadowColor": "#111111", - "shadowBlur": 0, - "backgroundColor": "transparent", - "backgroundOpacity": 0, - "position": "bottom", - "alignment": "center" - } - ], - "coverTemplates": [ - { - "id": "8f17c467-c69c-45b2-8011-94a6c3071d16", - "name": "斜黄白", - "description": "系统模板 - 斜黄白", - "is_system": 1, - "config": { - "backgroundEnabled": false, - "backgroundImagePath": null, - "backgroundBlurEnabled": false, - "backgroundBlurIntensity": 10, - "backgroundSize": 100, - "backgroundPosition": { - "x": 50, - "y": 50 - }, - "personImagePath": null, - "personSize": 80, - "personPosition": { - "x": 50, - "y": 50 - }, - "personRotation": 0, - "personBorderEnabled": false, - "personBorderStyle": "solid", - "personBorderColor": "#FFFFFF", - "personBorderWidth": 8, - "personBorderDashLength": null, - "personBorderGapLength": null, - "autoSplitText": true, - "titleMaxLength": 4, - "subtitleMaxLength": 10, - "titleText": "礼貌回归", - "titleFontFamily": "斗鱼追光体2.0", - "titleFontSize": 120, - "titleFontWeight": 700, - "titleColor": "#f5d400", - "titleStrokeColor": "#000000", - "titleStrokeWidth": 3, - "titleShadowColor": "#000000", - "titleShadowOffsetX": 0, - "titleShadowOffsetY": 0, - "titleShadowBlur": 0, - "titleShadowEnabled": false, - "titleShadowLayers": [], - "titlePosition": { - "x": 42.59259259259258, - "y": 56.909722222222214 - }, - "titleRotation": 338, - "titleDirection": "horizontal", - "titleCharSpacing": 24, - "titleLineSpacing": 144, - "titleMaxCharsPerLine": 10, - "titleBackgroundEnabled": true, - "titleBackgroundColor": "#f5f5f5", - "titleBackgroundOpacity": 25, - "titleBackgroundShape": "polygon", - "titleBackgroundSize": { - "width": 30, - "height": 10 - }, - "titleBackgroundPosition": { - "x": 44.21296296296296, - "y": 32.951388888888886 - }, - "titleBackgroundPoints": [ - { - "x": 226.08024691358025, - "y": -79.67664930555557 - }, - { - "x": 250.7716049382716, - "y": 218.93446180555554 - }, - { - "x": -260.8024691358025, - "y": 691.1566840277777 - }, - { - "x": -290.12345679012344, - "y": 366.50390624999994 - } - ], - "titleBackgroundRadius": 10, - "titleBackgroundRotation": 0, - "subtitleText": "行动亲爱的观众朋友们", - "subtitleFontFamily": "斗鱼追光体2.0", - "subtitleFontSize": 82, - "subtitleFontWeight": 500, - "subtitleColor": "#FFFFFF", - "subtitleStrokeColor": "#000000", - "subtitleStrokeWidth": 1, - "subtitleShadowColor": "#000000", - "subtitleShadowOffsetX": 0, - "subtitleShadowOffsetY": 0, - "subtitleShadowBlur": 0, - "subtitleShadowEnabled": false, - "subtitleShadowLayers": [], - "subtitlePosition": { - "x": 45.37037037037037, - "y": 66.5625 - }, - "subtitleRotation": 338, - "subtitleDirection": "horizontal", - "subtitleCharSpacing": 23, - "subtitleLineSpacing": 72, - "subtitleMaxCharsPerLine": 17, - "subtitleBackgroundEnabled": false, - "subtitleBackgroundColor": "#000000", - "subtitleBackgroundOpacity": 70, - "subtitleBackgroundShape": "rectangle", - "subtitleBackgroundSize": { - "width": 30, - "height": 10 - }, - "subtitleBackgroundPosition": { - "x": 50, - "y": 60 - }, - "subtitleBackgroundPoints": [], - "subtitleBackgroundRadius": 10, - "subtitleBackgroundRotation": 0, - "maskEnabled": false, - "maskImagePath": null, - "maskSize": 100, - "maskPosition": { - "x": 50, - "y": 50 - }, - "maskColor": null, - "maskOpacity": 100, - "maskShape": "rectangle" - } - }, - { - "id": "705fa010-5bf3-4041-b624-0fd364bea5ad", - "name": "大四字报", - "description": "系统模板 - 大四字报", - "is_system": 1, - "config": { - "backgroundEnabled": true, - "backgroundImagePath": null, - "backgroundBlurEnabled": false, - "backgroundBlurIntensity": 30, - "backgroundSize": 100, - "backgroundPosition": { - "x": 50, - "y": 50 - }, - "personImagePath": null, - "personSize": 33.125, - "personPosition": { - "x": 22.68518518518519, - "y": 78.125 - }, - "personRotation": 0, - "personBorderEnabled": false, - "personBorderStyle": "solid", - "personBorderColor": "#FFFFFF", - "personBorderWidth": 8, - "personBorderDashLength": null, - "personBorderGapLength": null, - "autoSplitText": true, - "titleMaxLength": 4, - "subtitleMaxLength": 30, - "titleText": "礼貌回归", - "titleFontFamily": "USMCCyuanjiantecu", - "titleFontSize": 375, - "titleFontWeight": 400, - "titleColor": "#e6ca19", - "titleStrokeColor": "#000000", - "titleStrokeWidth": 0, - "titleShadowColor": "#000000", - "titleShadowOffsetX": 0, - "titleShadowOffsetY": 0, - "titleShadowBlur": 0, - "titleShadowEnabled": false, - "titleShadowLayers": [ - { - "id": 1765355385133.3418, - "offsetX": 20, - "offsetY": 20, - "blur": 30, - "color": "#000000", - "opacity": 100, - "enabled": true - }, - { - "id": 1765355385133.7036, - "offsetX": -20, - "offsetY": -20, - "blur": 30, - "color": "#000000", - "opacity": 100, - "enabled": true - } - ], - "titlePosition": { - "x": 52.54629629629629, - "y": 48.40277777777778 - }, - "titleRotation": 0, - "titleDirection": "horizontal", - "titleCharSpacing": 58, - "titleLineSpacing": 150, - "titleMaxCharsPerLine": 2, - "titleBackgroundEnabled": false, - "titleBackgroundColor": "#000000", - "titleBackgroundOpacity": 70, - "titleBackgroundShape": "polygon", - "titleBackgroundSize": { - "width": 30, - "height": 10 - }, - "titleBackgroundPosition": { - "x": 95.83333333333333, - "y": 68.88888888888889 - }, - "titleBackgroundPoints": [ - { - "x": -330.24691358024694, - "y": -15.440538194444414 - }, - { - "x": 40, - "y": -40 - }, - { - "x": 40, - "y": 40 - }, - { - "x": -40, - "y": 40 - }, - { - "x": -114.9691358024691, - "y": 36.642795138888864 - }, - { - "x": -96.45061728395058, - "y": -3.2877604166666865 - } - ], - "titleBackgroundRadius": 10, - "titleBackgroundRotation": 0, - "subtitleText": "行动亲爱的观众朋友们", - "subtitleFontFamily": "USMCCyuanjiantecu", - "subtitleFontSize": 122, - "subtitleFontWeight": 500, - "subtitleColor": "#e37a16", - "subtitleStrokeColor": "#000000", - "subtitleStrokeWidth": 5, - "subtitleShadowColor": "#ff0000", - "subtitleShadowOffsetX": 41, - "subtitleShadowOffsetY": 50, - "subtitleShadowBlur": 13, - "subtitleShadowEnabled": false, - "subtitleShadowLayers": [], - "subtitlePosition": { - "x": 51.15740740740741, - "y": 83.75 - }, - "subtitleRotation": 0, - "subtitleDirection": "horizontal", - "subtitleCharSpacing": 0, - "subtitleLineSpacing": 72, - "subtitleMaxCharsPerLine": 8, - "subtitleBackgroundEnabled": false, - "subtitleBackgroundColor": "#000000", - "subtitleBackgroundOpacity": 70, - "subtitleBackgroundShape": "rectangle", - "subtitleBackgroundSize": { - "width": 30, - "height": 10 - }, - "subtitleBackgroundPosition": { - "x": 50, - "y": 60 - }, - "subtitleBackgroundPoints": [], - "subtitleBackgroundRadius": 10, - "subtitleBackgroundRotation": 0, - "maskEnabled": false, - "maskImagePath": null, - "maskSize": 100, - "maskPosition": { - "x": 50, - "y": 50 - }, - "maskColor": null, - "maskOpacity": 100, - "maskShape": "rectangle" - } - }, - { - "id": "6404718a-1b1c-4148-9807-ad3c57a53e0c", - "name": "蓝底白字", - "description": "系统模板 - 蓝底白字", - "is_system": 1, - "config": { - "backgroundEnabled": false, - "backgroundImagePath": null, - "backgroundBlurEnabled": false, - "backgroundBlurIntensity": 10, - "backgroundSize": 100, - "backgroundPosition": { - "x": 50, - "y": 50 - }, - "personImagePath": null, - "personSize": 80, - "personPosition": { - "x": 50, - "y": 50 - }, - "personRotation": 0, - "personBorderEnabled": false, - "personBorderStyle": "solid", - "personBorderColor": "#FFFFFF", - "personBorderWidth": 8, - "personBorderDashLength": null, - "personBorderGapLength": null, - "autoSplitText": true, - "titleMaxLength": 4, - "subtitleMaxLength": 5, - "titleText": "礼貌回归", - "titleFontFamily": "USMCCyuanjiantecu", - "titleFontSize": 120, - "titleFontWeight": 700, - "titleColor": "#cbcdb1", - "titleStrokeColor": "#000000", - "titleStrokeWidth": 0, - "titleShadowColor": "#000000", - "titleShadowOffsetX": 0, - "titleShadowOffsetY": 0, - "titleShadowBlur": 0, - "titleShadowEnabled": false, - "titleShadowLayers": [ - { - "id": 1765449844664.8303, - "offsetX": 0, - "offsetY": 0, - "blur": 8, - "color": "#000000", - "opacity": 80, - "enabled": true - }, - { - "id": 1765449844664.415, - "offsetX": 0, - "offsetY": 0, - "blur": 16, - "color": "#000000", - "opacity": 40, - "enabled": true - } - ], - "titlePosition": { - "x": 50.694444444444436, - "y": 63.506944444444436 - }, - "titleRotation": 0, - "titleDirection": "horizontal", - "titleCharSpacing": 24, - "titleLineSpacing": 144, - "titleMaxCharsPerLine": 10, - "titleBackgroundEnabled": false, - "titleBackgroundColor": "#000000", - "titleBackgroundOpacity": 70, - "titleBackgroundShape": "rectangle", - "titleBackgroundSize": { - "width": 30, - "height": 10 - }, - "titleBackgroundPosition": { - "x": 50, - "y": 30 - }, - "titleBackgroundPoints": [], - "titleBackgroundRadius": 10, - "titleBackgroundRotation": 0, - "subtitleText": "行动亲爱的", - "subtitleFontFamily": "千图厚黑体", - "subtitleFontSize": 187, - "subtitleFontWeight": 100, - "subtitleColor": "#FFFFFF", - "subtitleStrokeColor": "#000000", - "subtitleStrokeWidth": 10, - "subtitleShadowColor": "#000000", - "subtitleShadowOffsetX": 0, - "subtitleShadowOffsetY": 0, - "subtitleShadowBlur": 0, - "subtitleShadowEnabled": false, - "subtitleShadowLayers": [], - "subtitlePosition": { - "x": 49.53703703703704, - "y": 74.20138888888889 - }, - "subtitleRotation": 0, - "subtitleDirection": "horizontal", - "subtitleCharSpacing": -23, - "subtitleLineSpacing": 72, - "subtitleMaxCharsPerLine": 15, - "subtitleBackgroundEnabled": true, - "subtitleBackgroundColor": "#599dd9", - "subtitleBackgroundOpacity": 25, - "subtitleBackgroundShape": "rectangle", - "subtitleBackgroundSize": { - "width": 161.0185185185185, - "height": 30.48611111111111 - }, - "subtitleBackgroundPosition": { - "x": 50.23148148148148, - "y": 67.11805555555556 - }, - "subtitleBackgroundPoints": [], - "subtitleBackgroundRadius": 10, - "subtitleBackgroundRotation": 0, - "maskEnabled": false, - "maskImagePath": null, - "maskSize": 100, - "maskPosition": { - "x": 50, - "y": 50 - }, - "maskColor": null, - "maskOpacity": 100, - "maskShape": "rectangle" - } - }, - { - "id": "485183be-6eed-4eae-b74a-8591f08b69fa", - "name": "黄白实描", - "description": "系统模板 - 黄白实描", - "is_system": 1, - "config": { - "backgroundEnabled": false, - "backgroundImagePath": null, - "backgroundBlurEnabled": true, - "backgroundBlurIntensity": 30, - "backgroundSize": 100, - "backgroundPosition": { - "x": 50, - "y": 50 - }, - "personImagePath": null, - "personSize": 70.27777777777777, - "personPosition": { - "x": 35.87962962962963, - "y": 64.75694444444444 - }, - "personRotation": 0, - "personBorderEnabled": true, - "personBorderStyle": "solid", - "personBorderColor": "#FFFFFF", - "personBorderWidth": 32, - "personBorderDashLength": null, - "personBorderGapLength": null, - "autoSplitText": true, - "titleMaxLength": 4, - "subtitleMaxLength": 6, - "titleText": "置顶96", - "titleFontFamily": "1.程荣光刻楷", - "titleFontSize": 300, - "titleFontWeight": 1000, - "titleColor": "#ffde05", - "titleStrokeColor": "#000000", - "titleStrokeWidth": 0, - "titleShadowColor": "#000000", - "titleShadowOffsetX": 0, - "titleShadowOffsetY": 0, - "titleShadowBlur": 0, - "titleShadowEnabled": false, - "titleShadowLayers": [ - { - "id": 1765435502861.9124, - "offsetX": -2, - "offsetY": -2, - "blur": 12, - "color": "#000000", - "opacity": 100, - "enabled": true - }, - { - "id": 1765435502861.0488, - "offsetX": 2, - "offsetY": 2, - "blur": 16, - "color": "#000000", - "opacity": 100, - "enabled": true - }, - { - "id": 1765435502861.4207, - "offsetX": 0, - "offsetY": 0, - "blur": 14, - "color": "#000000", - "opacity": 100, - "enabled": true - } - ], - "titlePosition": { - "x": 91.89814814814812, - "y": 66.45833333333334 - }, - "titleRotation": 0, - "titleDirection": "vertical", - "titleCharSpacing": -20, - "titleLineSpacing": 118, - "titleMaxCharsPerLine": 10, - "titleBackgroundEnabled": false, - "titleBackgroundColor": "#000000", - "titleBackgroundOpacity": 70, - "titleBackgroundShape": "rectangle", - "titleBackgroundSize": { - "width": 30, - "height": 10 - }, - "titleBackgroundPosition": { - "x": 50, - "y": 30 - }, - "titleBackgroundPoints": [], - "titleBackgroundRadius": 10, - "titleBackgroundRotation": 0, - "subtitleText": "4高丹草新品", - "subtitleFontFamily": "USMCCyuanjiantecu", - "subtitleFontSize": 117, - "subtitleFontWeight": 500, - "subtitleColor": "#FFFFFF", - "subtitleStrokeColor": "#000000", - "subtitleStrokeWidth": 0, - "subtitleShadowColor": "#000000", - "subtitleShadowOffsetX": 0, - "subtitleShadowOffsetY": 0, - "subtitleShadowBlur": 0, - "subtitleShadowEnabled": false, - "subtitleShadowLayers": [ - { - "id": 1765435591571.2886, - "offsetX": -2, - "offsetY": -2, - "blur": 2, - "color": "#FFFFFF", - "opacity": 60, - "enabled": true - }, - { - "id": 1765435591571.856, - "offsetX": 2, - "offsetY": 2, - "blur": 0, - "color": "#000000", - "opacity": 65, - "enabled": true - }, - { - "id": 1765435591571.3809, - "offsetX": 0, - "offsetY": 0, - "blur": 4, - "color": "#000000", - "opacity": 50, - "enabled": true - } - ], - "subtitlePosition": { - "x": 47.45370370370371, - "y": 12.743055555555557 - }, - "subtitleRotation": 0, - "subtitleDirection": "horizontal", - "subtitleCharSpacing": 12, - "subtitleLineSpacing": 72, - "subtitleMaxCharsPerLine": 15, - "subtitleBackgroundEnabled": false, - "subtitleBackgroundColor": "#000000", - "subtitleBackgroundOpacity": 70, - "subtitleBackgroundShape": "rectangle", - "subtitleBackgroundSize": { - "width": 30, - "height": 10 - }, - "subtitleBackgroundPosition": { - "x": 50, - "y": 60 - }, - "subtitleBackgroundPoints": [], - "subtitleBackgroundRadius": 10, - "subtitleBackgroundRotation": 0, - "maskEnabled": false, - "maskImagePath": null, - "maskSize": 100, - "maskPosition": { - "x": 50, - "y": 50 - }, - "maskColor": null, - "maskOpacity": 100, - "maskShape": "rectangle" - } - }, - { - "id": "v08ezr6v3x-mkdite6i", - "name": "人像居中", - "description": "系统模板 - 人像居中", - "is_system": 1, - "config": { - "backgroundEnabled": false, - "backgroundImagePath": null, - "backgroundBlurEnabled": true, - "backgroundBlurIntensity": 30, - "backgroundSize": 100, - "backgroundPosition": { - "x": 50, - "y": 50 - }, - "personImagePath": null, - "personSize": 54.99999999999999, - "personPosition": { - "x": 53.935185185185205, - "y": 34.375 - }, - "personRotation": 0, - "personBorderEnabled": true, - "personBorderStyle": "solid", - "personBorderColor": "#FFFFFF", - "personBorderWidth": 8, - "personBorderDashLength": null, - "personBorderGapLength": null, - "autoSplitText": true, - "titleMaxLength": 6, - "subtitleMaxLength": 12, - "titleText": "托德揭秘芒格", - "titleFontFamily": "墨趣古风体", - "titleFontSize": 110, - "titleFontWeight": 100, - "titleColor": "#ffffff", - "titleStrokeColor": "#000000", - "titleStrokeWidth": 0, - "titleShadowColor": "#000000", - "titleShadowOffsetX": 0, - "titleShadowOffsetY": 0, - "titleShadowBlur": 0, - "titleShadowEnabled": false, - "titleShadowLayers": [ - { - "id": 1765435502861.9124, - "offsetX": -2, - "offsetY": -2, - "blur": 12, - "color": "#000000", - "opacity": 100, - "enabled": true - }, - { - "id": 1765435502861.0488, - "offsetX": 2, - "offsetY": 2, - "blur": 16, - "color": "#000000", - "opacity": 100, - "enabled": true - }, - { - "id": 1765435502861.4207, - "offsetX": 0, - "offsetY": 0, - "blur": 14, - "color": "#000000", - "opacity": 100, - "enabled": true - } - ], - "titlePosition": { - "x": 39.814814814814795, - "y": 69.40972222222223 - }, - "titleRotation": 0, - "titleDirection": "horizontal", - "titleCharSpacing": 12, - "titleLineSpacing": 118, - "titleMaxCharsPerLine": 10, - "titleBackgroundEnabled": false, - "titleBackgroundColor": "#000000", - "titleBackgroundOpacity": 70, - "titleBackgroundShape": "rectangle", - "titleBackgroundSize": { - "width": 30, - "height": 10 - }, - "titleBackgroundPosition": { - "x": 50, - "y": 30 - }, - "titleBackgroundPoints": [], - "titleBackgroundRadius": 10, - "titleBackgroundRotation": 0, - "subtitleText": "投资稳的原因", - "subtitleFontFamily": "庞门正道标题体免费版", - "subtitleFontSize": 117, - "subtitleFontWeight": 500, - "subtitleColor": "#eaf273", - "subtitleStrokeColor": "#000000", - "subtitleStrokeWidth": 0, - "subtitleShadowColor": "#000000", - "subtitleShadowOffsetX": 0, - "subtitleShadowOffsetY": 0, - "subtitleShadowBlur": 0, - "subtitleShadowEnabled": false, - "subtitleShadowLayers": [ - { - "id": 1765435591571.2886, - "offsetX": -2, - "offsetY": -2, - "blur": 2, - "color": "#FFFFFF", - "opacity": 60, - "enabled": true - }, - { - "id": 1765435591571.856, - "offsetX": 2, - "offsetY": 2, - "blur": 0, - "color": "#000000", - "opacity": 65, - "enabled": true - }, - { - "id": 1765435591571.3809, - "offsetX": 0, - "offsetY": 0, - "blur": 4, - "color": "#000000", - "opacity": 50, - "enabled": true - } - ], - "subtitlePosition": { - "x": 58.796296296296305, - "y": 77.84722222222221 - }, - "subtitleRotation": 0, - "subtitleDirection": "horizontal", - "subtitleCharSpacing": 12, - "subtitleLineSpacing": 72, - "subtitleMaxCharsPerLine": 15, - "subtitleBackgroundEnabled": false, - "subtitleBackgroundColor": "#000000", - "subtitleBackgroundOpacity": 70, - "subtitleBackgroundShape": "rectangle", - "subtitleBackgroundSize": { - "width": 30, - "height": 10 - }, - "subtitleBackgroundPosition": { - "x": 50, - "y": 60 - }, - "subtitleBackgroundPoints": [], - "subtitleBackgroundRadius": 10, - "subtitleBackgroundRotation": 0, - "maskEnabled": false, - "maskImagePath": null, - "maskSize": 100, - "maskPosition": { - "x": 50, - "y": 50 - }, - "maskColor": null, - "maskOpacity": 100, - "maskShape": "rectangle" - } - }, - { - "id": "1xwrrcvf7a5-mkdite6i", - "name": "青蓝虚描", - "description": "系统模板 - 青蓝虚描", - "is_system": 1, - "config": { - "backgroundEnabled": false, - "backgroundImagePath": null, - "backgroundBlurEnabled": true, - "backgroundBlurIntensity": 100, - "backgroundSize": 100, - "backgroundPosition": { - "x": 50, - "y": 50 - }, - "personImagePath": null, - "personSize": 56.73611111111111, - "personPosition": { - "x": 35.87962962962963, - "y": 71.52777777777777 - }, - "personRotation": 0, - "personBorderEnabled": true, - "personBorderStyle": "dashed", - "personBorderColor": "#149fc2", - "personBorderWidth": 14, - "personBorderDashLength": null, - "personBorderGapLength": null, - "autoSplitText": true, - "titleMaxLength": 4, - "subtitleMaxLength": 11, - "titleText": "托德揭秘", - "titleFontFamily": "泼墨体", - "titleFontSize": 115, - "titleFontWeight": 350, - "titleColor": "#149fc2", - "titleStrokeColor": "#000000", - "titleStrokeWidth": 7, - "titleShadowColor": "#000000", - "titleShadowOffsetX": 0, - "titleShadowOffsetY": 0, - "titleShadowBlur": 0, - "titleShadowEnabled": false, - "titleShadowLayers": [ - { - "id": 1765435502861.9124, - "offsetX": -2, - "offsetY": -2, - "blur": 12, - "color": "#000000", - "opacity": 100, - "enabled": true - }, - { - "id": 1765435502861.0488, - "offsetX": 2, - "offsetY": 2, - "blur": 16, - "color": "#000000", - "opacity": 100, - "enabled": true - }, - { - "id": 1765435502861.4207, - "offsetX": 0, - "offsetY": 0, - "blur": 14, - "color": "#000000", - "opacity": 100, - "enabled": true - } - ], - "titlePosition": { - "x": 90.9722222222222, - "y": 34.16666666666667 - }, - "titleRotation": 0, - "titleDirection": "vertical", - "titleCharSpacing": 50, - "titleLineSpacing": 118, - "titleMaxCharsPerLine": 10, - "titleBackgroundEnabled": false, - "titleBackgroundColor": "#000000", - "titleBackgroundOpacity": 70, - "titleBackgroundShape": "rectangle", - "titleBackgroundSize": { - "width": 30, - "height": 10 - }, - "titleBackgroundPosition": { - "x": 50, - "y": 30 - }, - "titleBackgroundPoints": [], - "titleBackgroundRadius": 10, - "titleBackgroundRotation": 0, - "subtitleText": "芒格投资稳的原因", - "subtitleFontFamily": "杨任东竹石体", - "subtitleFontSize": 87, - "subtitleFontWeight": 500, - "subtitleColor": "#149fc2", - "subtitleStrokeColor": "#000000", - "subtitleStrokeWidth": 0, - "subtitleShadowColor": "#000000", - "subtitleShadowOffsetX": 0, - "subtitleShadowOffsetY": 0, - "subtitleShadowBlur": 0, - "subtitleShadowEnabled": false, - "subtitleShadowLayers": [ - { - "id": 1768540523070.3923, - "offsetX": 0, - "offsetY": 0, - "blur": 2, - "color": "#000000", - "opacity": 100, - "enabled": true - }, - { - "id": 1768540523070.0796, - "offsetX": 0, - "offsetY": 0, - "blur": 2, - "color": "#000000", - "opacity": 100, - "enabled": true - } - ], - "subtitlePosition": { - "x": 76.85185185185186, - "y": 58.40277777777778 - }, - "subtitleRotation": 0, - "subtitleDirection": "vertical", - "subtitleCharSpacing": 12, - "subtitleLineSpacing": 72, - "subtitleMaxCharsPerLine": 15, - "subtitleBackgroundEnabled": false, - "subtitleBackgroundColor": "#000000", - "subtitleBackgroundOpacity": 70, - "subtitleBackgroundShape": "rectangle", - "subtitleBackgroundSize": { - "width": 30, - "height": 10 - }, - "subtitleBackgroundPosition": { - "x": 50, - "y": 60 - }, - "subtitleBackgroundPoints": [], - "subtitleBackgroundRadius": 10, - "subtitleBackgroundRotation": 0, - "maskEnabled": false, - "maskImagePath": null, - "maskSize": 100, - "maskPosition": { - "x": 50, - "y": 50 - }, - "maskColor": null, - "maskOpacity": 100, - "maskShape": "rectangle" - } - }, - { - "id": "43t1uykj8zg-mkdite6i", - "name": "粉红虚白", - "description": "系统模板 - 粉红虚白", - "is_system": 1, - "config": { - "backgroundEnabled": false, - "backgroundImagePath": null, - "backgroundBlurEnabled": true, - "backgroundBlurIntensity": 50, - "backgroundSize": 100, - "backgroundPosition": { - "x": 50, - "y": 50 - }, - "personImagePath": null, - "personSize": 81.7361111111111, - "personPosition": { - "x": 49.768518518518526, - "y": 60.41666666666666 - }, - "personRotation": 0, - "personBorderEnabled": true, - "personBorderStyle": "dashed", - "personBorderColor": "#ffffff", - "personBorderWidth": 8, - "personBorderDashLength": null, - "personBorderGapLength": null, - "autoSplitText": true, - "titleMaxLength": 4, - "subtitleMaxLength": 11, - "titleText": "长期持有", - "titleFontFamily": "庞门正道标题体免费版", - "titleFontSize": 165, - "titleFontWeight": 100, - "titleColor": "#e8c4df", - "titleStrokeColor": "#e147c0", - "titleStrokeWidth": 6, - "titleShadowColor": "#000000", - "titleShadowOffsetX": 0, - "titleShadowOffsetY": 0, - "titleShadowBlur": 0, - "titleShadowEnabled": false, - "titleShadowLayers": [], - "titlePosition": { - "x": 36.80555555555553, - "y": 11.944444444444452 - }, - "titleRotation": 0, - "titleDirection": "horizontal", - "titleCharSpacing": 11, - "titleLineSpacing": 118, - "titleMaxCharsPerLine": 10, - "titleBackgroundEnabled": false, - "titleBackgroundColor": "#000000", - "titleBackgroundOpacity": 70, - "titleBackgroundShape": "rectangle", - "titleBackgroundSize": { - "width": 30, - "height": 10 - }, - "titleBackgroundPosition": { - "x": 50, - "y": 30 - }, - "titleBackgroundPoints": [], - "titleBackgroundRadius": 10, - "titleBackgroundRotation": 0, - "subtitleText": "才是真省心又赚钱", - "subtitleFontFamily": "方正粗黑宋简体", - "subtitleFontSize": 117, - "subtitleFontWeight": 500, - "subtitleColor": "#FFFFFF", - "subtitleStrokeColor": "#ef62e3", - "subtitleStrokeWidth": 5, - "subtitleShadowColor": "#000000", - "subtitleShadowOffsetX": 0, - "subtitleShadowOffsetY": 0, - "subtitleShadowBlur": 0, - "subtitleShadowEnabled": false, - "subtitleShadowLayers": [ - { - "id": 1765435591571.2886, - "offsetX": -2, - "offsetY": -2, - "blur": 2, - "color": "#FFFFFF", - "opacity": 60, - "enabled": true - }, - { - "id": 1765435591571.856, - "offsetX": 2, - "offsetY": 2, - "blur": 0, - "color": "#000000", - "opacity": 65, - "enabled": true - }, - { - "id": 1765435591571.3809, - "offsetX": 0, - "offsetY": 0, - "blur": 4, - "color": "#000000", - "opacity": 50, - "enabled": true - } - ], - "subtitlePosition": { - "x": 51.3888888888889, - "y": 23.333333333333304 - }, - "subtitleRotation": 0, - "subtitleDirection": "horizontal", - "subtitleCharSpacing": 12, - "subtitleLineSpacing": 72, - "subtitleMaxCharsPerLine": 15, - "subtitleBackgroundEnabled": false, - "subtitleBackgroundColor": "#000000", - "subtitleBackgroundOpacity": 70, - "subtitleBackgroundShape": "rectangle", - "subtitleBackgroundSize": { - "width": 30, - "height": 10 - }, - "subtitleBackgroundPosition": { - "x": 50, - "y": 60 - }, - "subtitleBackgroundPoints": [], - "subtitleBackgroundRadius": 10, - "subtitleBackgroundRotation": 0, - "maskEnabled": false, - "maskImagePath": null, - "maskSize": 100, - "maskPosition": { - "x": 50, - "y": 50 - }, - "maskColor": null, - "maskOpacity": 100, - "maskShape": "rectangle" - } - }, - { - "id": "sb8mm7l4bjf-mkdite6i", - "name": "红黄虚描", - "description": "系统模板 - 红黄虚描", - "is_system": 1, - "config": { - "backgroundEnabled": false, - "backgroundImagePath": null, - "backgroundBlurEnabled": true, - "backgroundBlurIntensity": 60, - "backgroundSize": 100, - "backgroundPosition": { - "x": 50, - "y": 50 - }, - "personImagePath": null, - "personSize": 65.06944444444444, - "personPosition": { - "x": 62.73148148148148, - "y": 67.0138888888889 - }, - "personRotation": 0, - "personBorderEnabled": true, - "personBorderStyle": "dashed", - "personBorderColor": "#FFFFFF", - "personBorderWidth": 12, - "personBorderDashLength": null, - "personBorderGapLength": null, - "autoSplitText": true, - "titleMaxLength": 4, - "subtitleMaxLength": 10, - "titleText": "托德揭秘", - "titleFontFamily": "泼墨体", - "titleFontSize": 165, - "titleFontWeight": 100, - "titleColor": "#d4ec74", - "titleStrokeColor": "#000000", - "titleStrokeWidth": 0, - "titleShadowColor": "#000000", - "titleShadowOffsetX": 0, - "titleShadowOffsetY": 0, - "titleShadowBlur": 0, - "titleShadowEnabled": false, - "titleShadowLayers": [ - { - "id": 1765435502861.9124, - "offsetX": -2, - "offsetY": -2, - "blur": 12, - "color": "#000000", - "opacity": 100, - "enabled": true - }, - { - "id": 1765435502861.0488, - "offsetX": 2, - "offsetY": 2, - "blur": 16, - "color": "#000000", - "opacity": 100, - "enabled": true - }, - { - "id": 1765435502861.4207, - "offsetX": 0, - "offsetY": 0, - "blur": 14, - "color": "#000000", - "opacity": 100, - "enabled": true - } - ], - "titlePosition": { - "x": 55.09259259259257, - "y": 15.59027777777779 - }, - "titleRotation": 0, - "titleDirection": "horizontal", - "titleCharSpacing": 19, - "titleLineSpacing": 118, - "titleMaxCharsPerLine": 9, - "titleBackgroundEnabled": false, - "titleBackgroundColor": "#000000", - "titleBackgroundOpacity": 70, - "titleBackgroundShape": "rectangle", - "titleBackgroundSize": { - "width": 30, - "height": 10 - }, - "titleBackgroundPosition": { - "x": 50, - "y": 30 - }, - "titleBackgroundPoints": [], - "titleBackgroundRadius": 10, - "titleBackgroundRotation": 0, - "subtitleText": "芒格投资稳的原因", - "subtitleFontFamily": "MaokenAssortedSans-Lite", - "subtitleFontSize": 117, - "subtitleFontWeight": 500, - "subtitleColor": "#7e1010", - "subtitleStrokeColor": "#ffffff", - "subtitleStrokeWidth": 6, - "subtitleShadowColor": "#000000", - "subtitleShadowOffsetX": 0, - "subtitleShadowOffsetY": 0, - "subtitleShadowBlur": 0, - "subtitleShadowEnabled": false, - "subtitleShadowLayers": [ - { - "id": 1765435591571.2886, - "offsetX": -2, - "offsetY": -2, - "blur": 2, - "color": "#FFFFFF", - "opacity": 60, - "enabled": true - }, - { - "id": 1765435591571.856, - "offsetX": 2, - "offsetY": 2, - "blur": 0, - "color": "#000000", - "opacity": 65, - "enabled": true - }, - { - "id": 1765435591571.3809, - "offsetX": 0, - "offsetY": 0, - "blur": 4, - "color": "#000000", - "opacity": 50, - "enabled": true - } - ], - "subtitlePosition": { - "x": 18.98148148148148, - "y": 64.47916666666667 - }, - "subtitleRotation": 0, - "subtitleDirection": "vertical", - "subtitleCharSpacing": 12, - "subtitleLineSpacing": 72, - "subtitleMaxCharsPerLine": 15, - "subtitleBackgroundEnabled": false, - "subtitleBackgroundColor": "#000000", - "subtitleBackgroundOpacity": 70, - "subtitleBackgroundShape": "rectangle", - "subtitleBackgroundSize": { - "width": 30, - "height": 10 - }, - "subtitleBackgroundPosition": { - "x": 50, - "y": 60 - }, - "subtitleBackgroundPoints": [], - "subtitleBackgroundRadius": 10, - "subtitleBackgroundRotation": 0, - "maskEnabled": false, - "maskImagePath": null, - "maskSize": 100, - "maskPosition": { - "x": 50, - "y": 50 - }, - "maskColor": null, - "maskOpacity": 100, - "maskShape": "rectangle" - } - } - ], - "timestamp": "2026-04-23T13:22:37.457Z" -} diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index f7bf305..0047054 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1145,7 +1145,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" dependencies = [ - "libloading 0.7.4", + "libloading 0.8.9", ] [[package]] @@ -1548,6 +1548,16 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "filetime" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" +dependencies = [ + "cfg-if", + "libc", +] + [[package]] name = "find-msvc-tools" version = "0.1.9" @@ -5030,6 +5040,17 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "tar" +version = "0.4.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6221d9a6003c78398e3b239969f352578258df48c8eb051caadae0015bc840" +dependencies = [ + "filetime", + "libc", + "xattr", +] + [[package]] name = "target-lexicon" version = "0.12.16" @@ -5091,7 +5112,7 @@ dependencies = [ [[package]] name = "tauri-app" -version = "0.1.3" +version = "0.1.8" dependencies = [ "aes-gcm", "async-trait", @@ -5102,6 +5123,7 @@ dependencies = [ "eframe", "egui", "env_logger", + "flate2", "futures-util", "hex", "hmac", @@ -5118,6 +5140,7 @@ dependencies = [ "serde", "serde_json", "sha1", + "tar", "tauri", "tauri-build", "tauri-plugin-dialog", @@ -7254,6 +7277,16 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" +[[package]] +name = "xattr" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" +dependencies = [ + "libc", + "rustix 1.1.4", +] + [[package]] name = "xcursor" version = "0.3.10" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 3f1ca02..69eba1d 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tauri-app" -version = "0.1.3" +version = "0.1.8" description = "A Tauri App" authors = ["you"] edition = "2021" @@ -99,3 +99,5 @@ windows = { version = "0.58", features = [ ] } eframe = { version = "0.31", default-features = false, features = ["default_fonts", "glow"] } egui = "0.31" +flate2 = "1" +tar = "0.4" diff --git a/src-tauri/build.rs b/src-tauri/build.rs index 8c5d7ae..20962c9 100644 --- a/src-tauri/build.rs +++ b/src-tauri/build.rs @@ -55,6 +55,8 @@ const APP_COMMANDS: &[&str] = &[ ]; fn main() { + // 勿再用 winres:tauri-build 已写入 VERSION 资源,重复会导致 LNK1123 / CVT1100。 + // 本地版本比对优先读同目录 aiclient.version(见 zip-portable.cjs、updater engine)。 tauri_build::try_build( tauri_build::Attributes::new() .app_manifest(tauri_build::AppManifest::new().commands(APP_COMMANDS)), diff --git a/src-tauri/frontend-stub/index.html b/src-tauri/frontend-stub/index.html new file mode 100644 index 0000000..fb81940 --- /dev/null +++ b/src-tauri/frontend-stub/index.html @@ -0,0 +1,10 @@ + + + + + aiclient + + + + + diff --git a/src-tauri/scripts/bump-version.cjs b/src-tauri/scripts/bump-version.cjs index cd5eb17..9f01699 100644 --- a/src-tauri/scripts/bump-version.cjs +++ b/src-tauri/scripts/bump-version.cjs @@ -1,15 +1,20 @@ /** - * 构建前将版本号 patch 段 +1,并同步写入 tauri.conf.json / Cargo.toml / package.json。 + * 构建前将版本号 patch 段 +1,并同步写入 tauri.conf.json / Cargo.toml / aiclient_ui / npmrelease。 */ const fs = require("node:fs"); const path = require("node:path"); const tauriDir = path.join(__dirname, ".."); -const rootDir = path.join(tauriDir, ".."); - const tauriConfPath = path.join(tauriDir, "tauri.conf.json"); const cargoTomlPath = path.join(tauriDir, "Cargo.toml"); -const packageJsonPath = path.join(rootDir, "package.json"); +const uiPackageJsonPath = path.join(tauriDir, "..", "aiclient_ui", "package.json"); +const npmReleasePackageJsonPath = path.join( + tauriDir, + "..", + "..", + "npmrelease", + "package.json", +); function bumpPatch(version) { const parts = String(version) @@ -50,7 +55,14 @@ const conf = JSON.parse(fs.readFileSync(tauriConfPath, "utf8")); const newVersion = bumpPatch(conf.version); updateJsonVersion(tauriConfPath, newVersion); -updateJsonVersion(packageJsonPath, newVersion); +if (fs.existsSync(uiPackageJsonPath)) { + updateJsonVersion(uiPackageJsonPath, newVersion); +} +if (fs.existsSync(npmReleasePackageJsonPath)) { + updateJsonVersion(npmReleasePackageJsonPath, newVersion); +} else { + console.warn(`未找到 npmrelease/package.json: ${npmReleasePackageJsonPath}`); +} updateCargoVersion(cargoTomlPath, newVersion); console.log(`版本号已更新: ${conf.version} -> ${newVersion}`); diff --git a/src-tauri/scripts/zip-portable.cjs b/src-tauri/scripts/zip-portable.cjs index 9bdb1c3..c05067c 100644 --- a/src-tauri/scripts/zip-portable.cjs +++ b/src-tauri/scripts/zip-portable.cjs @@ -32,6 +32,7 @@ async function notifyReleaseVersion(version) { } const tauriDir = path.join(__dirname, ".."); +const npmReleaseDir = path.join(tauriDir, "..", "..", "npmrelease"); const conf = JSON.parse( fs.readFileSync(path.join(tauriDir, "tauri.conf.json"), "utf8"), ); @@ -70,6 +71,25 @@ const stagedExe = process.platform === "win32" ? `${productName}.exe` : productName; fs.copyFileSync(exePath, path.join(stageDir, stagedExe)); +function writeVersionSidecar(dir, baseName, ver) { + const file = path.join(dir, `${baseName}.version`); + fs.writeFileSync(file, `${ver}\n`, "utf8"); + return file; +} + +writeVersionSidecar(stageDir, productName, version); + +// 复制主程序到 npmrelease,供 npm publish 打包 +if (process.platform === "win32") { + fs.mkdirSync(npmReleaseDir, { recursive: true }); + const npmReleaseExe = path.join(npmReleaseDir, stagedExe); + fs.copyFileSync(exePath, npmReleaseExe); + writeVersionSidecar(npmReleaseDir, productName, version); + console.log(`已复制主程序到 npmrelease: ${npmReleaseExe}`); +} else { + console.warn("非 Windows 平台,跳过复制到 npmrelease"); +} + const updaterPath = path.join(releaseDir, "updater.exe"); if (process.platform === "win32" && fs.existsSync(updaterPath)) { fs.copyFileSync(updaterPath, path.join(stageDir, "updater.exe")); diff --git a/src-tauri/src/bin/updater/engine.rs b/src-tauri/src/bin/updater/engine.rs index eaaded0..745ddf0 100644 --- a/src-tauri/src/bin/updater/engine.rs +++ b/src-tauri/src/bin/updater/engine.rs @@ -9,12 +9,24 @@ use serde_json::Value; pub const ENV_FROM_UPDATER: &str = "AICLIENT_FROM_UPDATER"; pub const MAIN_EXE: &str = "aiclient.exe"; -pub const CHECK_UPDATE_URL: &str = "http://81.71.163.140:8001/api/checkupdate"; -pub const DOWNLOAD_URL: &str = "http://81.71.163.140:80/images/mainfile/main.exe"; +/// npm 包名(发布到 npmmirror 的桌面端包) +pub const NPM_PACKAGE_NAME: &str = "yaoyanaiclient"; +const NPM_REGISTRY_BASE: &str = "https://registry.npmmirror.com"; +const NPM_CDN_BASE: &str = "https://cdn.npmmirror.com/packages"; +const NPM_FETCH_RETRIES: u32 = 3; #[derive(Clone, Debug)] pub enum UpdaterMessage { Status(String), + /// 本地/远程版本(调试用) + VersionInfo { + local_display: String, + remote_display: String, + local_normalized: String, + remote_normalized: String, + needs_update: bool, + note: String, + }, /// 0.0 ~ 1.0;无总大小时为 None(界面显示不确定进度) DownloadProgress { fraction: Option, detail: String }, Launching, @@ -48,6 +60,25 @@ impl ProgressSink { pub fn launching(&self) { self.send(UpdaterMessage::Launching); } + + pub fn version_info( + &self, + local_display: impl Into, + remote_display: impl Into, + local_normalized: impl Into, + remote_normalized: impl Into, + needs_update: bool, + note: impl Into, + ) { + self.send(UpdaterMessage::VersionInfo { + local_display: local_display.into(), + remote_display: remote_display.into(), + local_normalized: local_normalized.into(), + remote_normalized: remote_normalized.into(), + needs_update, + note: note.into(), + }); + } } fn exe_dir() -> Result { @@ -62,9 +93,18 @@ fn exe_dir() -> Result { fn normalize_version(raw: &str) -> String { let trimmed = raw.trim().trim_start_matches(['v', 'V']); - let mut parts: Vec = trimmed - .split('.') - .filter_map(|p| p.parse().ok()) + // Windows 资源里常见 "0, 1, 3, 0" 或 "0.1.3.0" + let unified = trimmed.replace(',', "."); + let mut parts: Vec = unified + .split(|c| c == '.' || c == '-' || c == '_') + .filter_map(|p| { + let p = p.trim(); + if p.is_empty() { + None + } else { + p.parse().ok() + } + }) .collect(); if parts.is_empty() { return trimmed.to_string(); @@ -79,65 +119,228 @@ fn normalize_version(raw: &str) -> String { .join(".") } -fn versions_match(local: &str, remote: &str) -> bool { - normalize_version(local) == normalize_version(remote) +fn npm_registry_url() -> String { + format!("{NPM_REGISTRY_BASE}/{NPM_PACKAGE_NAME}") } -fn parse_remote_version(body: &str) -> Result { - let trimmed = body.trim(); - if trimmed.is_empty() { - return Err("更新接口返回空内容".to_string()); +fn npm_tgz_download_url(version: &str) -> String { + format!( + "{NPM_CDN_BASE}/{NPM_PACKAGE_NAME}/{version}/{NPM_PACKAGE_NAME}-{version}.tgz" + ) +} + +fn parse_npm_latest_version(body: &str) -> Result { + let value: Value = serde_json::from_str(body) + .map_err(|e| format!("解析 npm 元数据 JSON 失败: {e}"))?; + + if let Some(latest) = value + .get("dist-tags") + .and_then(|t| t.get("latest")) + .and_then(|v| v.as_str()) + { + let latest = latest.trim(); + if !latest.is_empty() { + return Ok(latest.to_string()); + } } - if let Ok(value) = serde_json::from_str::(trimmed) { - if value.get("ok").and_then(|v| v.as_bool()) == Some(false) { - let msg = value - .get("message") - .and_then(|v| v.as_str()) - .unwrap_or("检查更新失败"); - return Err(msg.to_string()); - } - for key in ["version", "latest_version", "latestVersion", "app_version"] { - if let Some(v) = value.get(key).and_then(|x| x.as_str()) { - if !v.trim().is_empty() { - return Ok(v.trim().to_string()); - } - } - } - if let Some(data) = value.get("data") { - for key in ["version", "latest_version", "latestVersion", "app_version"] { - if let Some(v) = data.get(key).and_then(|x| x.as_str()) { - if !v.trim().is_empty() { - return Ok(v.trim().to_string()); - } - } + // 兼容仅返回 dist-tags 片段或正则兜底 + if let Ok(re) = regex::Regex::new(r#""latest"\s*:\s*"([^"]+)""#) { + if let Some(caps) = re.captures(body) { + if let Some(m) = caps.get(1) { + return Ok(m.as_str().to_string()); } } } - if trimmed.chars().all(|c| c.is_ascii_alphanumeric() || c == '.' || c == '-') { - return Ok(trimmed.to_string()); - } - - Err(format!("无法解析更新接口返回的版本号: {trimmed}")) + Err(format!( + "无法从 npm 元数据提取 latest 版本(包名: {NPM_PACKAGE_NAME})" + )) } -async fn fetch_latest_version(client: &reqwest::Client) -> Result { +async fn fetch_npm_registry_once( + client: &reqwest::Client, + registry_url: &str, +) -> Result { let response = client - .get(CHECK_UPDATE_URL) + .get(registry_url) .send() .await - .map_err(|e| format!("请求更新接口失败: {e}"))?; + .map_err(|e| format!("请求 npm 仓库失败: {e}"))?; if !response.status().is_success() { - return Err(format!("更新接口 HTTP {}", response.status())); + return Err(format!("npm 仓库 HTTP {}", response.status())); } let body = response .text() .await - .map_err(|e| format!("读取更新接口响应失败: {e}"))?; - parse_remote_version(&body) + .map_err(|e| format!("读取 npm 元数据失败: {e}"))?; + parse_npm_latest_version(&body) +} + +async fn fetch_latest_version(client: &reqwest::Client) -> Result { + let registry_url = npm_registry_url(); + let mut last_error = String::from("获取 npm 版本信息失败"); + + for attempt in 1..=NPM_FETCH_RETRIES { + match fetch_npm_registry_once(client, ®istry_url).await { + Ok(version) => return Ok(version), + Err(e) => { + last_error = e; + if attempt < NPM_FETCH_RETRIES { + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + } + } + } + } + + Err(last_error) +} + +/// 与 exe 同目录的 `aiclient.version`(构建时由 zip-portable 写入) +fn read_version_sidecar(exe_path: &Path) -> Option { + let mut sidecar = exe_path.to_path_buf(); + sidecar.set_extension("version"); + if !sidecar.is_file() { + return None; + } + let text = std::fs::read_to_string(&sidecar).ok()?; + let v = text.trim(); + if v.is_empty() { + None + } else { + Some(v.to_string()) + } +} + +fn write_version_sidecar(exe_path: &Path, version: &str) -> Result<(), String> { + let mut sidecar = exe_path.to_path_buf(); + sidecar.set_extension("version"); + std::fs::write(&sidecar, format!("{version}\n")) + .map_err(|e| format!("写入 {} 失败: {e}", sidecar.display()))?; + Ok(()) +} + +fn version_from_fixed_file_info(buffer: &[u8]) -> Option { + use std::ffi::c_void; + + use windows::core::PCWSTR; + use windows::Win32::Storage::FileSystem::{VerQueryValueW, VS_FIXEDFILEINFO}; + + let root: Vec = "\\".encode_utf16().chain(std::iter::once(0)).collect(); + let mut ptr: *mut c_void = std::ptr::null_mut(); + let mut len: u32 = 0; + + let ok = unsafe { + VerQueryValueW( + buffer.as_ptr() as *const c_void, + PCWSTR(root.as_ptr()), + &mut ptr, + &mut len, + ) + }; + if !ok.as_bool() || ptr.is_null() || len < std::mem::size_of::() as u32 { + return None; + } + + let info = unsafe { &*(ptr as *const VS_FIXEDFILEINFO) }; + let major = (info.dwProductVersionMS >> 16) as u16; + let minor = (info.dwProductVersionMS & 0xFFFF) as u16; + let build = (info.dwProductVersionLS >> 16) as u16; + let patch = (info.dwProductVersionLS & 0xFFFF) as u16; + + if major == 0 && minor == 0 && build == 0 && patch == 0 { + return None; + } + + if patch == 0 { + Some(format!("{major}.{minor}.{build}")) + } else { + Some(format!("{major}.{minor}.{build}.{patch}")) + } +} + +fn version_from_string_table(buffer: &[u8]) -> Option { + use std::ffi::c_void; + + use windows::core::PCWSTR; + use windows::Win32::Storage::FileSystem::VerQueryValueW; + + let sub_block: Vec = "\\" + .encode_utf16() + .chain(std::iter::once(0)) + .collect(); + + let mut value_ptr: *mut c_void = std::ptr::null_mut(); + let mut value_len: u32 = 0; + + if !unsafe { + VerQueryValueW( + buffer.as_ptr() as *const c_void, + PCWSTR(sub_block.as_ptr()), + &mut value_ptr, + &mut value_len, + ) + } + .as_bool() + { + return None; + } + + if value_ptr.is_null() || value_len < 4 { + return None; + } + + let translate = unsafe { + std::slice::from_raw_parts(value_ptr as *const u16, (value_len / 2) as usize) + }; + + for i in (0..translate.len()).step_by(2) { + let Some((lang_id, code_page)) = translate.get(i).zip(translate.get(i + 1)) else { + break; + }; + let lang = format!("{lang_id:04x}{code_page:04x}"); + + for key in ["ProductVersion", "FileVersion"] { + let query: Vec = format!("\\StringFileInfo\\{lang}\\{key}") + .encode_utf16() + .chain(std::iter::once(0)) + .collect(); + value_ptr = std::ptr::null_mut(); + value_len = 0; + let ok = unsafe { + VerQueryValueW( + buffer.as_ptr() as *const c_void, + PCWSTR(query.as_ptr()), + &mut value_ptr, + &mut value_len, + ) + }; + if ok.as_bool() && !value_ptr.is_null() && value_len >= 2 { + let slice = unsafe { + std::slice::from_raw_parts(value_ptr as *const u16, value_len as usize) + }; + let end = slice.iter().position(|&c| c == 0).unwrap_or(slice.len()); + let version = String::from_utf16_lossy(&slice[..end]); + if !version.trim().is_empty() { + return Some(version.trim().to_string()); + } + } + } + } + + None +} + +/// 读取本地版本:优先 `aiclient.version`,其次 PE 资源。 +fn read_local_version(exe_path: &Path) -> Result<(String, String), String> { + if let Some(v) = read_version_sidecar(exe_path) { + return Ok((v, "aiclient.version".to_string())); + } + + let pe = read_exe_version(exe_path)?; + Ok((pe, "PE 资源".to_string())) } #[cfg(windows)] @@ -146,9 +349,7 @@ fn read_exe_version(path: &Path) -> Result { use std::os::windows::ffi::OsStrExt; use windows::core::PCWSTR; - use windows::Win32::Storage::FileSystem::{ - GetFileVersionInfoSizeW, GetFileVersionInfoW, VerQueryValueW, - }; + use windows::Win32::Storage::FileSystem::{GetFileVersionInfoSizeW, GetFileVersionInfoW}; let wide: Vec = path .as_os_str() @@ -158,7 +359,7 @@ fn read_exe_version(path: &Path) -> Result { let size = unsafe { GetFileVersionInfoSizeW(PCWSTR(wide.as_ptr()), None) }; if size == 0 { - return Err(format!("无法读取版本信息: {}", path.display())); + return Err(format!("exe 无版本资源块: {}", path.display())); } let mut buffer = vec![0u8; size as usize]; @@ -172,63 +373,17 @@ fn read_exe_version(path: &Path) -> Result { .map_err(|e| format!("GetFileVersionInfoW 失败: {e}"))?; } - let mut value_ptr: *mut c_void = std::ptr::null_mut(); - let mut value_len: u32 = 0; - let sub_block: Vec = "\\" - .encode_utf16() - .chain(std::iter::once(0)) - .collect(); - - unsafe { - if !VerQueryValueW( - buffer.as_ptr() as *const c_void, - PCWSTR(sub_block.as_ptr()), - &mut value_ptr, - &mut value_len, - ) - .as_bool() - { - return Err("VerQueryValueW 失败".to_string()); - } + if let Some(v) = version_from_string_table(&buffer) { + return Ok(v); + } + if let Some(v) = version_from_fixed_file_info(&buffer) { + return Ok(v); } - if value_ptr.is_null() || value_len < 2 { - return Err("版本信息为空".to_string()); - } - - let translate = unsafe { - std::slice::from_raw_parts(value_ptr as *const u16, (value_len / 2) as usize) - }; - let lang = format!("{:04x}{:04x}", translate[0], translate[1]); - - for key in ["ProductVersion", "FileVersion"] { - let query: Vec = format!("\\StringFileInfo\\{lang}\\{key}") - .encode_utf16() - .chain(std::iter::once(0)) - .collect(); - value_ptr = std::ptr::null_mut(); - value_len = 0; - let ok = unsafe { - VerQueryValueW( - buffer.as_ptr() as *const c_void, - PCWSTR(query.as_ptr()), - &mut value_ptr, - &mut value_len, - ) - }; - if ok.as_bool() && !value_ptr.is_null() && value_len >= 2 { - let slice = unsafe { - std::slice::from_raw_parts(value_ptr as *const u16, value_len as usize) - }; - let end = slice.iter().position(|&c| c == 0).unwrap_or(slice.len()); - let version = String::from_utf16_lossy(&slice[..end]); - if !version.trim().is_empty() { - return Ok(version.trim().to_string()); - } - } - } - - Err(format!("未在 {} 中找到版本字符串", path.display())) + Err(format!( + "未在 {} 中找到版本信息(无 StringFileInfo / VS_FIXEDFILEINFO)", + path.display() + )) } #[cfg(not(windows))] @@ -249,25 +404,69 @@ fn format_bytes(n: u64) -> String { } } +#[cfg(windows)] +fn extract_package_from_tgz(tgz_path: &Path, dest_exe: &Path) -> Result<(), String> { + use std::fs::File; + use std::io::copy; + + use flate2::read::GzDecoder; + use tar::Archive; + + let file = File::open(tgz_path).map_err(|e| format!("打开 tgz 失败: {e}"))?; + let decoder = GzDecoder::new(file); + let mut archive = Archive::new(decoder); + + let entries = archive + .entries() + .map_err(|e| format!("读取 tgz 条目失败: {e}"))?; + + let exe_name = MAIN_EXE; + for entry in entries { + let mut entry = entry.map_err(|e| format!("读取 tgz 条目失败: {e}"))?; + let path = entry.path().map_err(|e| format!("解析 tgz 路径失败: {e}"))?; + let path_str = path.to_string_lossy().replace('\\', "/"); + if path_str.ends_with(exe_name) { + let parent = dest_exe + .parent() + .ok_or_else(|| "无法获取目标目录".to_string())?; + std::fs::create_dir_all(parent).map_err(|e| format!("创建目录失败: {e}"))?; + let mut outfile = + File::create(dest_exe).map_err(|e| format!("创建 exe 失败: {e}"))?; + copy(&mut entry, &mut outfile).map_err(|e| format!("写入 exe 失败: {e}"))?; + return Ok(()); + } + } + + Err(format!("npm 包 tgz 中未找到 {exe_name}")) +} + async fn download_and_replace( client: &reqwest::Client, main_path: &Path, + remote_version: &str, sink: &ProgressSink, ) -> Result<(), String> { + let download_url = npm_tgz_download_url(remote_version); let response = client - .get(DOWNLOAD_URL) + .get(&download_url) .send() .await - .map_err(|e| format!("下载主程序失败: {e}"))?; + .map_err(|e| format!("下载 npm 包失败: {e}"))?; if !response.status().is_success() { - return Err(format!("下载主程序 HTTP {}", response.status())); + return Err(format!( + "下载 npm 包 HTTP {}({})", + response.status(), + download_url + )); } let total = response.content_length(); - let temp_path = main_path.with_extension("exe.download"); - let mut file = std::fs::File::create(&temp_path) - .map_err(|e| format!("创建临时文件失败: {e}"))?; + let tgz_path = main_path.with_extension("tgz.download"); + let temp_exe = main_path.with_extension("exe.download"); + + let mut file = std::fs::File::create(&tgz_path) + .map_err(|e| format!("创建临时 tgz 失败: {e}"))?; let mut downloaded: u64 = 0; let mut stream = response.bytes_stream(); @@ -276,24 +475,20 @@ async fn download_and_replace( let chunk = chunk.map_err(|e| format!("下载数据失败: {e}"))?; use std::io::Write; file.write_all(&chunk) - .map_err(|e| format!("写入临时文件失败: {e}"))?; + .map_err(|e| format!("写入临时 tgz 失败: {e}"))?; downloaded += chunk.len() as u64; - let fraction = total.map(|t| { - if t == 0 { - None - } else { - Some((downloaded as f32 / t as f32).clamp(0.0, 1.0)) - } - }).flatten(); + let fraction = total + .filter(|&t| t > 0) + .map(|t| (downloaded as f32 / t as f32).clamp(0.0, 1.0)); let detail = match total { Some(t) => format!( - "{} / {}", + "{} / {} (npm)", format_bytes(downloaded), format_bytes(t) ), - None => format_bytes(downloaded), + None => format!("{} (npm)", format_bytes(downloaded)), }; sink.download_progress(fraction, detail); } @@ -301,21 +496,42 @@ async fn download_and_replace( drop(file); if downloaded == 0 { - let _ = std::fs::remove_file(&temp_path); - return Err("下载的主程序为空".to_string()); + let _ = std::fs::remove_file(&tgz_path); + return Err("下载的 npm 包为空".to_string()); } + sink.download_progress(Some(1.0), "正在解压主程序…".to_string()); + + #[cfg(windows)] + { + extract_package_from_tgz(&tgz_path, &temp_exe)?; + } + #[cfg(not(windows))] + { + let _ = (tgz_path, temp_exe); + return Err("当前平台不支持从 npm tgz 解压".to_string()); + } + + let _ = std::fs::remove_file(&tgz_path); + sink.download_progress(Some(1.0), "正在替换主程序…".to_string()); if main_path.exists() { std::fs::remove_file(main_path).map_err(|e| format!("删除旧主程序失败: {e}"))?; } - std::fs::rename(&temp_path, main_path).map_err(|e| { - let _ = std::fs::remove_file(&temp_path); + std::fs::rename(&temp_exe, main_path).map_err(|e| { + let _ = std::fs::remove_file(&temp_exe); format!("替换主程序失败: {e}") })?; + // 与远端版本对齐,确保下次启动 updater 能正确比对 + write_version_sidecar(main_path, remote_version)?; + sink.download_progress( + Some(1.0), + format!("已更新 {remote_version} → aiclient.version"), + ); + Ok(()) } @@ -333,7 +549,7 @@ fn launch_main_app(main_path: &Path, dir: &Path) -> Result<(), String> { } pub async fn run_updater(sink: ProgressSink) -> Result<(), String> { - sink.status("检查更新中…"); + sink.status("正在从 npm 检查更新…"); let dir = exe_dir()?; let main_path = dir.join(MAIN_EXE); @@ -344,19 +560,60 @@ pub async fn run_updater(sink: ProgressSink) -> Result<(), String> { .map_err(|e| format!("创建 HTTP 客户端失败: {e}"))?; let remote_version = fetch_latest_version(&client).await?; - let needs_update = if main_path.is_file() { - match read_exe_version(&main_path) { - Ok(local_version) => !versions_match(&local_version, &remote_version), - Err(_) => true, + let remote_norm = normalize_version(&remote_version); + let npm_note = format!("npm 包 {NPM_PACKAGE_NAME} @ {NPM_REGISTRY_BASE}"); + + let (local_display, local_norm, needs_update, note) = if main_path.is_file() { + match read_local_version(&main_path) { + Ok((local_version, source)) => { + let local_norm = normalize_version(&local_version); + let matched = local_norm == remote_norm; + let note = if matched { + format!("版本一致(来源: {source}),跳过下载。{npm_note}") + } else { + format!( + "版本不一致(本地 {} vs npm {},来源: {source})。{npm_note}", + local_norm, remote_norm + ) + }; + (format!("{local_version} [{source}]"), local_norm, !matched, note) + } + Err(e) => { + let note = format!("读取本地版本失败: {e},将尝试下载。{npm_note}"); + ( + format!("(读取失败: {e})"), + String::new(), + true, + note, + ) + } } } else { - true + ( + "(文件不存在)".to_string(), + String::new(), + true, + format!("未找到 {}。{npm_note}", main_path.display()), + ) }; + sink.version_info( + &local_display, + &remote_version, + if local_norm.is_empty() { + "—" + } else { + &local_norm + }, + &remote_norm, + needs_update, + ¬e, + ); + if needs_update { sink.status("下载中…"); sink.download_progress(None, "准备下载…".to_string()); - download_and_replace(&client, &main_path, &sink).await?; + download_and_replace(&client, &main_path, &remote_version, &sink).await?; } else { sink.status("当前已是最新版本"); } diff --git a/src-tauri/src/bin/updater/ui.rs b/src-tauri/src/bin/updater/ui.rs index eca4eb4..0bc93bc 100644 --- a/src-tauri/src/bin/updater/ui.rs +++ b/src-tauri/src/bin/updater/ui.rs @@ -7,8 +7,8 @@ use eframe::egui; use crate::engine::{ProgressSink, UpdaterMessage}; -const WINDOW_WIDTH: f32 = 420.0; -const WINDOW_HEIGHT: f32 = 160.0; +const WINDOW_WIDTH: f32 = 440.0; +const WINDOW_HEIGHT: f32 = 260.0; pub fn run() -> ! { let options = eframe::NativeOptions { @@ -41,6 +41,12 @@ struct UpdaterApp { detail: String, progress: Option, show_bar: bool, + local_version: String, + remote_version: String, + local_normalized: String, + remote_normalized: String, + needs_update: Option, + version_note: String, error: Option, done: bool, should_close: bool, @@ -76,6 +82,12 @@ impl UpdaterApp { detail: String::new(), progress: None, show_bar: false, + local_version: "—".to_string(), + remote_version: "—".to_string(), + local_normalized: "—".to_string(), + remote_normalized: "—".to_string(), + needs_update: None, + version_note: String::new(), error: None, done: false, should_close: false, @@ -91,6 +103,21 @@ impl UpdaterApp { self.detail.clear(); } } + UpdaterMessage::VersionInfo { + local_display, + remote_display, + local_normalized, + remote_normalized, + needs_update, + note, + } => { + self.local_version = local_display; + self.remote_version = remote_display; + self.local_normalized = local_normalized; + self.remote_normalized = remote_normalized; + self.needs_update = Some(needs_update); + self.version_note = note; + } UpdaterMessage::DownloadProgress { fraction, detail } => { self.show_bar = true; self.status = "下载中…".to_string(); @@ -129,12 +156,59 @@ impl eframe::App for UpdaterApp { } egui::CentralPanel::default().show(ctx, |ui| { - ui.add_space(12.0); + ui.add_space(8.0); ui.vertical_centered(|ui| { ui.heading(&self.status); }); - ui.add_space(16.0); + ui.add_space(10.0); + egui::Frame::group(ui.style()) + .inner_margin(egui::Margin::symmetric(12, 8)) + .show(ui, |ui| { + ui.label(egui::RichText::new("版本信息(调试)").strong().size(13.0)); + ui.add_space(4.0); + ui.horizontal(|ui| { + ui.label("本地版本:"); + ui.monospace(&self.local_version); + }); + ui.horizontal(|ui| { + ui.label("远程版本:"); + ui.monospace(&self.remote_version); + }); + ui.horizontal(|ui| { + ui.label("npm 包:"); + ui.monospace(crate::engine::NPM_PACKAGE_NAME); + }); + ui.horizontal(|ui| { + ui.label("归一化本地:"); + ui.monospace(&self.local_normalized); + }); + ui.horizontal(|ui| { + ui.label("归一化远程:"); + ui.monospace(&self.remote_normalized); + }); + if let Some(needs) = self.needs_update { + let (text, color) = if needs { + ("需要下载", egui::Color32::from_rgb(230, 160, 60)) + } else { + ("无需下载", egui::Color32::from_rgb(80, 180, 120)) + }; + ui.horizontal(|ui| { + ui.label("比对结果:"); + ui.colored_label(color, text); + }); + } + if !self.version_note.is_empty() { + ui.add_space(4.0); + ui.label( + egui::RichText::new(&self.version_note) + .size(12.0) + .color(ui.visuals().weak_text_color()), + ); + } + }); + + ui.add_space(10.0); if self.show_bar { let mut bar = egui::ProgressBar::new(self.progress.unwrap_or(0.0)) diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 33fd0f4..86a6442 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -32,6 +32,20 @@ pub mod publish_store; use tauri::{Manager, WebviewUrl, WebviewWindowBuilder}; + +/// 开发:本地 Vite;发布:服务器静态资源(与 aiclient_ui `build:deploy` 输出目录一致) +const DEV_WEB_URL: &str = "http://localhost:1420/"; +const PROD_WEB_URL: &str = "http://81.71.163.140/images/newyaoyan/index.html"; + +fn webview_url() -> WebviewUrl { + let url = if cfg!(debug_assertions) { + DEV_WEB_URL + } else { + PROD_WEB_URL + }; + WebviewUrl::External(url.parse().expect("webview url")) +} + #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { let _ = env_logger::try_init(); @@ -81,25 +95,8 @@ pub fn run() { .map_err(|e| -> Box { e.into() })?; api_client::spawn_heartbeat_loop(heartbeat_handle); - let url = if cfg!(debug_assertions) { - WebviewUrl::External( - "http://localhost:1420/" - .parse() - .unwrap() - ) - } else { - WebviewUrl::External( - "http://81.71.163.140/images/newyaoyan/index.html" - .parse() - .unwrap() - ) - }; - WebviewWindowBuilder::new( - app, - "main", - url, - ) + WebviewWindowBuilder::new(app, "main", webview_url()) .title("MyApp") .build()?; diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index a139b59..0d0fd96 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,13 +1,12 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "aiclient", - "version": "0.1.3", + "version": "0.1.8", "identifier": "com.aiclient.desktop", "build": { - "beforeDevCommand": "npm run dev", + "beforeDevCommand": "npm run dev --prefix ../aiclient_ui", "devUrl": "http://localhost:1420", - "beforeBuildCommand": "npm run build", - "frontendDist": "../dist" + "frontendDist": "frontend-stub" }, "app": { "withGlobalTauri": true, diff --git a/src/App.vue b/src/App.vue deleted file mode 100644 index ebc0f09..0000000 --- a/src/App.vue +++ /dev/null @@ -1,12 +0,0 @@ - - - diff --git a/src/api/adminAppBranding.js b/src/api/adminAppBranding.js deleted file mode 100644 index 41b0b1f..0000000 --- a/src/api/adminAppBranding.js +++ /dev/null @@ -1,113 +0,0 @@ -import { apiRequest } from "./client.js"; - -/** 品牌静态资源基址(与 pythonbackend 根目录 images 挂载的 /images 一致) */ -const MEDIA_BASE = - import.meta.env.VITE_MEDIA_BASE_URL || "http://127.0.0.1:8001"; - -/** - * @param {string} token - * @param {RequestInit} [options] - */ -function adminRequest(token, path, options = {}) { - return apiRequest(path, { - ...options, - headers: { - Authorization: `Bearer ${token}`, - ...options.headers, - }, - }); -} - -function emptyBrandingForm() { - return { - softwareName: "", - logo: "", - contactWechat: "", - contactQq: "", - wechatQr: "", - qqQr: "", - }; -} - -/** - * 库内路径 images/xxx → 可访问 URL(预览用) - * @param {string | null | undefined} path - */ -export function brandingImageUrl(path) { - if (!path?.trim()) return ""; - const value = path.trim(); - if (value.startsWith("data:image/") || value.startsWith("http")) return value; - const normalized = value.replace(/\\/g, "/").replace(/^\//, ""); - if (normalized.startsWith("images/")) { - return `${MEDIA_BASE}/${normalized}`; - } - return `${MEDIA_BASE}/images/${normalized}`; -} - -/** 提交前:新上传保留 data URL;已有文件只提交 images/ 相对路径 */ -function toStoredImageValue(value) { - if (!value?.trim()) return null; - const v = value.trim(); - if (v.startsWith("data:image/")) return v; - const match = v.match(/\/images\/(.+?)(?:\?.*)?$/); - if (match) return `images/${match[1]}`; - if (v.startsWith("images/")) return v; - return v; -} - -/** API 载荷 → 表单 */ -function toForm(data) { - if (!data) return emptyBrandingForm(); - return { - softwareName: data.software_name ?? "", - logo: brandingImageUrl(data.logo_path), - contactWechat: data.wechat ?? "", - contactQq: data.qq ?? "", - wechatQr: brandingImageUrl(data.wechat_qrcode), - qqQr: brandingImageUrl(data.qq_qrcode), - }; -} - -/** 表单 → API 载荷 */ -function toPayload(form) { - return { - software_name: String(form.softwareName ?? "").trim(), - logo_path: toStoredImageValue(form.logo), - wechat: form.contactWechat?.trim() || null, - qq: form.contactQq?.trim() || null, - wechat_qrcode: toStoredImageValue(form.wechatQr), - qq_qrcode: toStoredImageValue(form.qqQr), - }; -} - -/** - * 加载默认 OEM(id=1)软件配置 - * @param {string} token - */ -export async function loadAdminAppBrandingApi(token) { - const res = await adminRequest(token, "/admin/oem-branding"); - if (!res.ok) { - return { ok: false, message: res.message || "加载软件配置失败" }; - } - return { ok: true, data: { form: toForm(res.data), oemId: res.data?.id ?? 1 } }; -} - -/** - * 保存默认 OEM(id=1)软件配置 - * @param {string} token - * @param {ReturnType} form - */ -export async function saveAdminAppBrandingApi(token, form) { - const res = await adminRequest(token, "/admin/oem-branding", { - method: "PATCH", - body: JSON.stringify(toPayload(form)), - }); - if (!res.ok) { - return { ok: false, message: res.message || "保存软件配置失败" }; - } - return { - ok: true, - message: res.message || "软件配置已保存", - data: { form: toForm(res.data), oemId: res.data?.id ?? 1 }, - }; -} diff --git a/src/api/adminCardKeys.js b/src/api/adminCardKeys.js deleted file mode 100644 index b81628c..0000000 --- a/src/api/adminCardKeys.js +++ /dev/null @@ -1,72 +0,0 @@ -import { apiRequest } from "./client.js"; - -/** - * @param {string} token - * @param {RequestInit} [options] - */ -function adminRequest(token, path, options = {}) { - return apiRequest(path, { - ...options, - headers: { - Authorization: `Bearer ${token}`, - ...options.headers, - }, - }); -} - -/** - * @param {string} token - * @param {{ - * page?: number, - * pageSize?: number, - * status?: string, - * username?: string, - * oemId?: number | null, - * agentId?: number | null, - * }} [params] - */ -export function listAdminCardKeysApi( - token, - { page = 1, pageSize = 20, status = "all", username, oemId, agentId } = {}, -) { - const query = new URLSearchParams({ - page: String(page), - page_size: String(pageSize), - status, - }); - const trimmed = username?.trim(); - if (trimmed) query.set("username", trimmed); - if (oemId != null) query.set("oem_id", String(oemId)); - if (agentId != null) query.set("agent_id", String(agentId)); - return adminRequest(token, `/admin/card-keys?${query}`); -} - -/** - * @param {string} token - * @param {object} payload - */ -export function createAdminCardKeysApi(token, payload) { - return adminRequest(token, "/admin/card-keys", { - method: "POST", - body: JSON.stringify(payload), - }); -} - -/** - * @param {string} token - * @param {number} cardId - * @param {object} payload - */ -export function updateAdminCardKeyApi(token, cardId, payload) { - return adminRequest(token, `/admin/card-keys/${cardId}`, { - method: "PATCH", - body: JSON.stringify(payload), - }); -} - -/** @param {string} token @param {number} cardId */ -export function deleteAdminCardKeyApi(token, cardId) { - return adminRequest(token, `/admin/card-keys/${cardId}`, { - method: "DELETE", - }); -} diff --git a/src/api/adminDesktopConfigs.js b/src/api/adminDesktopConfigs.js deleted file mode 100644 index 9a11f02..0000000 --- a/src/api/adminDesktopConfigs.js +++ /dev/null @@ -1,62 +0,0 @@ -import { apiRequest } from "./client.js"; - -/** - * @param {string} token - * @param {RequestInit} [options] - */ -function adminRequest(token, path, options = {}) { - return apiRequest(path, { - ...options, - headers: { - Authorization: `Bearer ${token}`, - ...options.headers, - }, - }); -} - -/** - * @param {string} token - * @param {{ page?: number, pageSize?: number, keyword?: string }} [params] - */ -export function listAdminDesktopConfigsApi( - token, - { page = 1, pageSize = 20, keyword = "" } = {}, -) { - const query = new URLSearchParams({ - page: String(page), - page_size: String(pageSize), - }); - const kw = keyword?.trim(); - if (kw) query.set("keyword", kw); - return adminRequest(token, `/admin/desktop-configs?${query}`); -} - -/** - * @param {string} token - * @param {object} payload - */ -export function createAdminDesktopConfigApi(token, payload) { - return adminRequest(token, "/admin/desktop-configs", { - method: "POST", - body: JSON.stringify(payload), - }); -} - -/** - * @param {string} token - * @param {number} configId - * @param {object} payload - */ -export function updateAdminDesktopConfigApi(token, configId, payload) { - return adminRequest(token, `/admin/desktop-configs/${configId}`, { - method: "PATCH", - body: JSON.stringify(payload), - }); -} - -/** @param {string} token @param {number} configId */ -export function deleteAdminDesktopConfigApi(token, configId) { - return adminRequest(token, `/admin/desktop-configs/${configId}`, { - method: "DELETE", - }); -} diff --git a/src/api/adminUsers.js b/src/api/adminUsers.js deleted file mode 100644 index d607d4d..0000000 --- a/src/api/adminUsers.js +++ /dev/null @@ -1,82 +0,0 @@ -import { apiRequest } from "./client.js"; - -/** - * @param {string} token - * @param {RequestInit} [options] - */ -function adminRequest(token, path, options = {}) { - return apiRequest(path, { - ...options, - headers: { - Authorization: `Bearer ${token}`, - ...options.headers, - }, - }); -} - -/** - * @param {string} token - * @param {{ - * page?: number, - * pageSize?: number, - * username?: string, - * deviceSerial?: string, - * oemId?: number | null, - * agentId?: number | null, - * roleId?: number | null, - * }} [params] - */ -export function listAdminUsersApi( - token, - { page = 1, pageSize = 20, username, deviceSerial, oemId, agentId, roleId } = {}, -) { - const query = new URLSearchParams({ - page: String(page), - page_size: String(pageSize), - }); - const trimmed = username?.trim(); - if (trimmed) query.set("username", trimmed); - const serial = deviceSerial?.trim(); - if (serial) query.set("device_serial", serial); - if (oemId != null) query.set("oem_id", String(oemId)); - if (agentId != null) query.set("agent_id", String(agentId)); - if (roleId != null) query.set("role_id", String(roleId)); - return adminRequest(token, `/admin/users?${query}`); -} - -/** - * @param {string} token - * @param {object} payload - */ -export function createAdminUserApi(token, payload) { - return adminRequest(token, "/admin/users", { - method: "POST", - body: JSON.stringify(payload), - }); -} - -/** - * @param {string} token - * @param {number} userId - * @param {object} payload - */ -export function updateAdminUserApi(token, userId, payload) { - return adminRequest(token, `/admin/users/${userId}`, { - method: "PATCH", - body: JSON.stringify(payload), - }); -} - -/** @param {string} token @param {number} userId */ -export function deleteAdminUserApi(token, userId) { - return adminRequest(token, `/admin/users/${userId}`, { - method: "DELETE", - }); -} - -/** 管理员解绑用户设备(清空 device_serial) */ -export function clearAdminUserDeviceSerialApi(token, userId) { - return adminRequest(token, `/admin/users/${userId}/clear-device-serial`, { - method: "POST", - }); -} diff --git a/src/api/agentCardKeys.js b/src/api/agentCardKeys.js deleted file mode 100644 index ce23db4..0000000 --- a/src/api/agentCardKeys.js +++ /dev/null @@ -1,50 +0,0 @@ -import { apiRequest } from "./client.js"; - -/** - * @param {string} token - * @param {RequestInit} [options] - */ -function agentRequest(token, path, options = {}) { - return apiRequest(path, { - ...options, - headers: { - Authorization: `Bearer ${token}`, - ...options.headers, - }, - }); -} - -/** - * @param {string} token - * @param {{ - * page?: number, - * pageSize?: number, - * status?: string, - * username?: string, - * }} [params] - */ -export function listAgentCardKeysApi( - token, - { page = 1, pageSize = 20, status = "all", username } = {}, -) { - const query = new URLSearchParams({ - page: String(page), - page_size: String(pageSize), - status, - }); - const trimmed = username?.trim(); - if (trimmed) query.set("username", trimmed); - return agentRequest(token, `/agent/card-keys?${query}`); -} - -/** - * @param {string} token - * @param {number} cardId - * @param {{ agent_remark?: string | null }} payload - */ -export function updateAgentCardKeyApi(token, cardId, payload) { - return agentRequest(token, `/agent/card-keys/${cardId}`, { - method: "PATCH", - body: JSON.stringify(payload), - }); -} diff --git a/src/api/agentUsers.js b/src/api/agentUsers.js deleted file mode 100644 index b9c318f..0000000 --- a/src/api/agentUsers.js +++ /dev/null @@ -1,38 +0,0 @@ -import { apiRequest } from "./client.js"; - -/** - * @param {string} token - * @param {RequestInit} [options] - */ -function agentRequest(token, path, options = {}) { - return apiRequest(path, { - ...options, - headers: { - Authorization: `Bearer ${token}`, - ...options.headers, - }, - }); -} - -/** - * @param {string} token - * @param {{ - * page?: number, - * pageSize?: number, - * username?: string, - * roleId?: number | null, - * }} [params] - */ -export function listAgentUsersApi( - token, - { page = 1, pageSize = 20, username, roleId } = {}, -) { - const query = new URLSearchParams({ - page: String(page), - page_size: String(pageSize), - }); - const trimmed = username?.trim(); - if (trimmed) query.set("username", trimmed); - if (roleId != null) query.set("role_id", String(roleId)); - return agentRequest(token, `/agent/users?${query}`); -} diff --git a/src/api/auth.js b/src/api/auth.js deleted file mode 100644 index b0b358f..0000000 --- a/src/api/auth.js +++ /dev/null @@ -1,47 +0,0 @@ -import { apiRequest } from "./client.js"; - -/** - * @param {{ username: string, password: string, confirmPassword: string }} payload - */ -export function registerApi(payload) { - return apiRequest("/auth/register", { - method: "POST", - body: JSON.stringify({ - username: payload.username, - password: payload.password, - confirmPassword: payload.confirmPassword, - }), - }); -} - -/** - * @param {{ username: string, password: string }} payload - */ -export function loginApi(payload) { - return apiRequest("/auth/login", { - method: "POST", - body: JSON.stringify({ - username: payload.username, - password: payload.password, - }), - }); -} - -/** @param {string} token */ -export function fetchMeApi(token) { - return apiRequest("/auth/me", { - headers: { - Authorization: `Bearer ${token}`, - }, - }); -} - -/** @param {string} token */ -export function logoutApi(token) { - return apiRequest("/auth/logout", { - method: "POST", - headers: { - Authorization: `Bearer ${token}`, - }, - }); -} diff --git a/src/api/cardKeys.js b/src/api/cardKeys.js deleted file mode 100644 index 2215dfe..0000000 --- a/src/api/cardKeys.js +++ /dev/null @@ -1,14 +0,0 @@ -import { apiRequest } from "./client.js"; - -/** - * @param {{ username: string, serialNumber: string }} payload - */ -export function activateCardKeyApi({ username, serialNumber }) { - return apiRequest("/card-keys/activate", { - method: "POST", - body: JSON.stringify({ - username: username.trim(), - serial_number: serialNumber.trim().toUpperCase(), - }), - }); -} diff --git a/src/api/client.js b/src/api/client.js deleted file mode 100644 index 5485169..0000000 --- a/src/api/client.js +++ /dev/null @@ -1,59 +0,0 @@ -import { invoke } from "@tauri-apps/api/core"; - -/** API 路径前缀(实际 HTTP 由 Rust `api_request` 发出) */ -const API_BASE = import.meta.env.VITE_API_BASE_URL || "/api/v1"; - -function isTauri() { - return typeof window !== "undefined" && "__TAURI_INTERNALS__" in window; -} - -/** - * @param {string} path - 相对 `/api/v1` 的路径,如 `/auth/login` - * @param {RequestInit} options - * @returns {Promise<{ ok: boolean, message: string, data?: unknown }>} - */ -export async function apiRequest(path, options = {}) { - if (!isTauri()) { - return { - ok: false, - message: "API 请求需在 Tauri 桌面端运行(由 Rust 代理并加解密)", - }; - } - - const method = (options.method || "GET").toUpperCase(); - let body; - if (options.body != null && options.body !== "") { - body = typeof options.body === "string" ? options.body : JSON.stringify(options.body); - } - - const headers = {}; - if (options.headers) { - const h = options.headers; - if (h instanceof Headers) { - h.forEach((value, key) => { - headers[key] = value; - }); - } else { - Object.assign(headers, h); - } - } - - const relPath = path.startsWith("/") ? path : `/${path}`; - - try { - const result = await invoke("api_request", { - path: relPath, - method, - body: body ?? null, - headers: Object.keys(headers).length ? headers : null, - }); - if (result && typeof result === "object" && "ok" in result) { - return result; - } - return { ok: false, message: "服务器返回格式异常" }; - } catch (err) { - return { ok: false, message: String(err) }; - } -} - -export { API_BASE }; diff --git a/src/api/oemAppBranding.js b/src/api/oemAppBranding.js deleted file mode 100644 index 587702a..0000000 --- a/src/api/oemAppBranding.js +++ /dev/null @@ -1,113 +0,0 @@ -import { apiRequest } from "./client.js"; - -/** 品牌静态资源基址(与 pythonbackend 根目录 images 挂载的 /images 一致) */ -const MEDIA_BASE = - import.meta.env.VITE_MEDIA_BASE_URL || "http://127.0.0.1:8001"; - -/** - * @param {string} token - * @param {RequestInit} [options] - */ -function oemRequest(token, path, options = {}) { - return apiRequest(path, { - ...options, - headers: { - Authorization: `Bearer ${token}`, - ...options.headers, - }, - }); -} - -function emptyBrandingForm() { - return { - softwareName: "", - logo: "", - contactWechat: "", - contactQq: "", - wechatQr: "", - qqQr: "", - }; -} - -/** - * 库内路径 images/xxx → 可访问 URL(预览用) - * @param {string | null | undefined} path - */ -export function brandingImageUrl(path) { - if (!path?.trim()) return ""; - const value = path.trim(); - if (value.startsWith("data:image/") || value.startsWith("http")) return value; - const normalized = value.replace(/\\/g, "/").replace(/^\//, ""); - if (normalized.startsWith("images/")) { - return `${MEDIA_BASE}/${normalized}`; - } - return `${MEDIA_BASE}/images/${normalized}`; -} - -/** 提交前:新上传保留 data URL;已有文件只提交 images/ 相对路径 */ -function toStoredImageValue(value) { - if (!value?.trim()) return null; - const v = value.trim(); - if (v.startsWith("data:image/")) return v; - const match = v.match(/\/images\/(.+?)(?:\?.*)?$/); - if (match) return `images/${match[1]}`; - if (v.startsWith("images/")) return v; - return v; -} - -/** API 载荷 → 表单 */ -function toForm(data) { - if (!data) return emptyBrandingForm(); - return { - softwareName: data.software_name ?? "", - logo: brandingImageUrl(data.logo_path), - contactWechat: data.wechat ?? "", - contactQq: data.qq ?? "", - wechatQr: brandingImageUrl(data.wechat_qrcode), - qqQr: brandingImageUrl(data.qq_qrcode), - }; -} - -/** 表单 → API 载荷 */ -function toPayload(form) { - return { - software_name: String(form.softwareName ?? "").trim(), - logo_path: toStoredImageValue(form.logo), - wechat: form.contactWechat?.trim() || null, - qq: form.contactQq?.trim() || null, - wechat_qrcode: toStoredImageValue(form.wechatQr), - qq_qrcode: toStoredImageValue(form.qqQr), - }; -} - -/** - * 加载默认 OEM(id=1)软件配置 - * @param {string} token - */ -export async function loadOemAppBrandingApi(token) { - const res = await oemRequest(token, "/oem/oem-branding"); - if (!res.ok) { - return { ok: false, message: res.message || "加载软件配置失败" }; - } - return { ok: true, data: { form: toForm(res.data), oemId: res.data?.id ?? 1 } }; -} - -/** - * 保存默认 OEM(id=1)软件配置 - * @param {string} token - * @param {ReturnType} form - */ -export async function saveOemAppBrandingApi(token, form) { - const res = await oemRequest(token, "/oem/oem-branding", { - method: "PATCH", - body: JSON.stringify(toPayload(form)), - }); - if (!res.ok) { - return { ok: false, message: res.message || "保存软件配置失败" }; - } - return { - ok: true, - message: res.message || "软件配置已保存", - data: { form: toForm(res.data), oemId: res.data?.id ?? 1 }, - }; -} diff --git a/src/api/oemCardKeys.js b/src/api/oemCardKeys.js deleted file mode 100644 index 9861295..0000000 --- a/src/api/oemCardKeys.js +++ /dev/null @@ -1,63 +0,0 @@ -import { apiRequest } from "./client.js"; - -/** - * @param {string} token - * @param {RequestInit} [options] - */ -function oemRequest(token, path, options = {}) { - return apiRequest(path, { - ...options, - headers: { - Authorization: `Bearer ${token}`, - ...options.headers, - }, - }); -} - -/** - * @param {string} token - * @param {{ - * page?: number, - * pageSize?: number, - * status?: string, - * username?: string, - * agentId?: number | null, - * }} [params] - */ -export function listOemCardKeysApi( - token, - { page = 1, pageSize = 20, status = "all", username, agentId } = {}, -) { - const query = new URLSearchParams({ - page: String(page), - page_size: String(pageSize), - status, - }); - const trimmed = username?.trim(); - if (trimmed) query.set("username", trimmed); - if (agentId != null) query.set("agent_id", String(agentId)); - return oemRequest(token, `/oem/card-keys?${query}`); -} - -/** - * @param {string} token - * @param {number} cardId - * @param {{ oem_remark?: string | null }} payload - */ -export function updateOemCardKeyApi(token, cardId, payload) { - return oemRequest(token, `/oem/card-keys/${cardId}`, { - method: "PATCH", - body: JSON.stringify(payload), - }); -} - -/** - * @param {string} token - * @param {{ card_ids: number[], agent_id: number }} payload - */ -export function assignOemCardKeysToAgentApi(token, payload) { - return oemRequest(token, "/oem/card-keys/assign-agent", { - method: "POST", - body: JSON.stringify(payload), - }); -} diff --git a/src/api/oemDesktopConfigs.js b/src/api/oemDesktopConfigs.js deleted file mode 100644 index f032462..0000000 --- a/src/api/oemDesktopConfigs.js +++ /dev/null @@ -1,62 +0,0 @@ -import { apiRequest } from "./client.js"; - -/** - * @param {string} token - * @param {RequestInit} [options] - */ -function oemRequest(token, path, options = {}) { - return apiRequest(path, { - ...options, - headers: { - Authorization: `Bearer ${token}`, - ...options.headers, - }, - }); -} - -/** - * @param {string} token - * @param {{ page?: number, pageSize?: number, keyword?: string }} [params] - */ -export function listOemDesktopConfigsApi( - token, - { page = 1, pageSize = 20, keyword = "" } = {}, -) { - const query = new URLSearchParams({ - page: String(page), - page_size: String(pageSize), - }); - const kw = keyword?.trim(); - if (kw) query.set("keyword", kw); - return oemRequest(token, `/oem/desktop-configs?${query}`); -} - -/** - * @param {string} token - * @param {object} payload - */ -export function createOemDesktopConfigApi(token, payload) { - return oemRequest(token, "/oem/desktop-configs", { - method: "POST", - body: JSON.stringify(payload), - }); -} - -/** - * @param {string} token - * @param {number} configId - * @param {object} payload - */ -export function updateOemDesktopConfigApi(token, configId, payload) { - return oemRequest(token, `/oem/desktop-configs/${configId}`, { - method: "PATCH", - body: JSON.stringify(payload), - }); -} - -/** @param {string} token @param {number} configId */ -export function deleteOemDesktopConfigApi(token, configId) { - return oemRequest(token, `/oem/desktop-configs/${configId}`, { - method: "DELETE", - }); -} diff --git a/src/api/oemSoftwareInfo.js b/src/api/oemSoftwareInfo.js deleted file mode 100644 index b36a861..0000000 --- a/src/api/oemSoftwareInfo.js +++ /dev/null @@ -1,35 +0,0 @@ -import { invoke } from "@tauri-apps/api/core"; - -/** - * @returns {Promise<{ - * oemId: number, - * softwareName: string, - * logoUrl: string | null, - * wechat: string | null, - * wechatQrcode: string | null, - * }>} - */ -export async function fetchSoftwareInfo() { - const empty = { - oemId: 1, - softwareName: "", - logoUrl: null, - wechat: null, - wechatQrcode: null, - }; - try { - const data = await invoke("get_software_info"); - if (!data || typeof data !== "object") { - return empty; - } - return { - oemId: data.oemId ?? 1, - softwareName: data.softwareName ?? "", - logoUrl: data.logoUrl || null, - wechat: data.wechat || null, - wechatQrcode: data.wechatQrcodeUrl || null, - }; - } catch { - return empty; - } -} diff --git a/src/api/oemUsers.js b/src/api/oemUsers.js deleted file mode 100644 index 4b48330..0000000 --- a/src/api/oemUsers.js +++ /dev/null @@ -1,72 +0,0 @@ -import { apiRequest } from "./client.js"; - -/** - * @param {string} token - * @param {RequestInit} [options] - */ -function oemRequest(token, path, options = {}) { - return apiRequest(path, { - ...options, - headers: { - Authorization: `Bearer ${token}`, - ...options.headers, - }, - }); -} - -/** - * @param {string} token - * @param {{ - * page?: number, - * pageSize?: number, - * username?: string, - * oemId?: number | null, - * agentId?: number | null, - * roleId?: number | null, - * }} [params] - */ -export function listOemUsersApi( - token, - { page = 1, pageSize = 20, username, oemId, agentId, roleId } = {}, -) { - const query = new URLSearchParams({ - page: String(page), - page_size: String(pageSize), - }); - const trimmed = username?.trim(); - if (trimmed) query.set("username", trimmed); - if (oemId != null) query.set("oem_id", String(oemId)); - if (agentId != null) query.set("agent_id", String(agentId)); - if (roleId != null) query.set("role_id", String(roleId)); - return oemRequest(token, `/oem/users?${query}`); -} - -/** - * @param {string} token - * @param {object} payload - */ -export function createOemUserApi(token, payload) { - return oemRequest(token, "/oem/users", { - method: "POST", - body: JSON.stringify(payload), - }); -} - -/** - * @param {string} token - * @param {number} userId - * @param {object} payload - */ -export function updateOemUserApi(token, userId, payload) { - return oemRequest(token, `/oem/users/${userId}`, { - method: "PATCH", - body: JSON.stringify(payload), - }); -} - -/** @param {string} token @param {number} userId */ -export function deleteOemUserApi(token, userId) { - return oemRequest(token, `/oem/users/${userId}`, { - method: "DELETE", - }); -} diff --git a/src/assets/tauri.svg b/src/assets/tauri.svg deleted file mode 100644 index 31b62c9..0000000 --- a/src/assets/tauri.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/src/assets/vite.svg b/src/assets/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/src/assets/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/components/AppSidebar.vue b/src/components/AppSidebar.vue deleted file mode 100644 index 64d1ccf..0000000 --- a/src/components/AppSidebar.vue +++ /dev/null @@ -1,122 +0,0 @@ - - - diff --git a/src/components/AppTitlebar.vue b/src/components/AppTitlebar.vue deleted file mode 100644 index fdb71d7..0000000 --- a/src/components/AppTitlebar.vue +++ /dev/null @@ -1,256 +0,0 @@ - - - diff --git a/src/components/AuthLayout.vue b/src/components/AuthLayout.vue deleted file mode 100644 index d9fa629..0000000 --- a/src/components/AuthLayout.vue +++ /dev/null @@ -1,24 +0,0 @@ - - - diff --git a/src/components/admin/AdminImageUpload.vue b/src/components/admin/AdminImageUpload.vue deleted file mode 100644 index 7339f74..0000000 --- a/src/components/admin/AdminImageUpload.vue +++ /dev/null @@ -1,101 +0,0 @@ - - - diff --git a/src/components/admin/AdminSubNav.vue b/src/components/admin/AdminSubNav.vue deleted file mode 100644 index 75f91ee..0000000 --- a/src/components/admin/AdminSubNav.vue +++ /dev/null @@ -1,31 +0,0 @@ - - - diff --git a/src/components/agent/AgentImageUpload.vue b/src/components/agent/AgentImageUpload.vue deleted file mode 100644 index 7339f74..0000000 --- a/src/components/agent/AgentImageUpload.vue +++ /dev/null @@ -1,101 +0,0 @@ - - - diff --git a/src/components/agent/AgentSubNav.vue b/src/components/agent/AgentSubNav.vue deleted file mode 100644 index 1e936e6..0000000 --- a/src/components/agent/AgentSubNav.vue +++ /dev/null @@ -1,30 +0,0 @@ - - - diff --git a/src/components/avatar/AvatarEditDialog.vue b/src/components/avatar/AvatarEditDialog.vue deleted file mode 100644 index 3611242..0000000 --- a/src/components/avatar/AvatarEditDialog.vue +++ /dev/null @@ -1,151 +0,0 @@ - - - \ No newline at end of file diff --git a/src/components/dashboard/DashboardCard.vue b/src/components/dashboard/DashboardCard.vue deleted file mode 100644 index b998b8e..0000000 --- a/src/components/dashboard/DashboardCard.vue +++ /dev/null @@ -1,48 +0,0 @@ - - - diff --git a/src/components/dashboard/StepBadge.vue b/src/components/dashboard/StepBadge.vue deleted file mode 100644 index 4fca5ad..0000000 --- a/src/components/dashboard/StepBadge.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/src/components/oem/OemImageUpload.vue b/src/components/oem/OemImageUpload.vue deleted file mode 100644 index 7339f74..0000000 --- a/src/components/oem/OemImageUpload.vue +++ /dev/null @@ -1,101 +0,0 @@ - - - diff --git a/src/components/oem/OemSubNav.vue b/src/components/oem/OemSubNav.vue deleted file mode 100644 index f0b6f78..0000000 --- a/src/components/oem/OemSubNav.vue +++ /dev/null @@ -1,31 +0,0 @@ - - - diff --git a/src/components/subtitle/KeywordEffectsSettings.vue b/src/components/subtitle/KeywordEffectsSettings.vue deleted file mode 100644 index 75fa5cb..0000000 --- a/src/components/subtitle/KeywordEffectsSettings.vue +++ /dev/null @@ -1,394 +0,0 @@ - - - diff --git a/src/components/subtitle/SubtitlePreviewCard.vue b/src/components/subtitle/SubtitlePreviewCard.vue deleted file mode 100644 index b05cf5c..0000000 --- a/src/components/subtitle/SubtitlePreviewCard.vue +++ /dev/null @@ -1,464 +0,0 @@ - - - - - diff --git a/src/components/subtitle/SubtitleStyleSelector.vue b/src/components/subtitle/SubtitleStyleSelector.vue deleted file mode 100644 index 93ded31..0000000 --- a/src/components/subtitle/SubtitleStyleSelector.vue +++ /dev/null @@ -1,264 +0,0 @@ - - - diff --git a/src/components/subtitle/SubtitleTemplateDialog.vue b/src/components/subtitle/SubtitleTemplateDialog.vue deleted file mode 100644 index f9a0b49..0000000 --- a/src/components/subtitle/SubtitleTemplateDialog.vue +++ /dev/null @@ -1,349 +0,0 @@ - - -