diff --git a/.gitignore b/.gitignore
index 2332f2f..29f6946 100644
--- a/.gitignore
+++ b/.gitignore
@@ -370,3 +370,5 @@ FodyWeavers.xsd
/src/Hua.Todo.Host/Hua.Todo.db-wal
/.artifacts/buildcheck
/.trae
+/.artifacts
+/.android-sdk
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index d4c67b0..64e9f20 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -20,6 +20,8 @@
"args": [
"publish",
"${workspaceFolder}/src/Hua.Todo.Host/Hua.Todo.Host.csproj",
+ "-c",
+ "Release",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary;ForceNoAlign"
],
diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 0000000..fd5e191
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,23 @@
+
+
+
+ 1.2.8
+ $(Version)
+ 1
+
+
+ ShaoHua
+ Hua.Todo
+ Hua.Todo
+ Copyright © 2024 ShaoHua
+ A simple cross-platform Todo application.
+
+
+ true
+
+
+
+
+
+
+
diff --git a/Directory.Build.targets b/Directory.Build.targets
index 705c3e5..851d05f 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -1,8 +1,8 @@
-
- false
- true
+
+ false
+ true
false
diff --git a/README.md b/README.md
index b287629..55e9c82 100644
--- a/README.md
+++ b/README.md
@@ -58,8 +58,8 @@ npm run dev
### Windows 交付产物(安装包)
-- 运行 `publish-windows.ps1` 生成 Inno Setup 安装包:`src/Hua.Todo.Maui/Output/Hua.Todo_Setup_vX.Y.Z.exe`(版本号来自 `Hua.Todo.Maui.csproj` 的 ``;根目录 `Directory.Build.targets` 会对 `Hua.Todo.Maui` 按 TargetFramework 条件配置 `UseMonoRuntime`:仅 Android 启用,其它目标关闭;同时会复制到 `artifacts/windows//installer/`)
-- 运行 `publish.ps1` 默认会同时发布 Windows + Linux(仅发布 Windows:`publish.ps1 -Windows`)
+- 运行 `publish-windows.ps1` 默认使用 `Release` 配置生成 Inno Setup 安装包:`src/Hua.Todo.Maui/Output/Hua.Todo_Setup_vX.Y.Z.exe`(版本号来自 `Hua.Todo.Maui.csproj` 的 ``;根目录 `Directory.Build.targets` 会对 `Hua.Todo.Maui` 按 TargetFramework 条件配置 `UseMonoRuntime`:仅 Android 启用,其它目标关闭;同时会复制到 `artifacts/windows//installer/`)
+- 运行 `publish.ps1` 默认会同时发布 Windows + Linux(仅发布 Windows:`publish.ps1 -Windows`),且均默认使用 `Release` 配置。
- 安装后主程序为:`Hua.Todo.Maui.exe`(快捷方式/安装后启动均指向该文件)
- 发布产物默认使用静态资源:`src/Hua.Todo.Maui/appsettings.json` 中 `WebServer.IsUsingStatic=true`
- 前端构建产物会输出到 `src/Hua.Todo.Maui/wwwroot`,并随 Windows 发布复制到发布目录(嵌入式服务器从 `AppContext.BaseDirectory/wwwroot` 提供静态文件)
diff --git a/docs/manual/技术设计文档.md b/docs/manual/技术设计文档.md
index dd5ab89..45d60a2 100644
--- a/docs/manual/技术设计文档.md
+++ b/docs/manual/技术设计文档.md
@@ -8,7 +8,7 @@
### 2.1 后端技术栈
- **开发语言**: C# 10
- **框架**: .NET 10
-- **UI 框架**: MAUI (Multi-platform App UI)
+- **UI 框架**: MAUI (Multi-platform App UI) + Avalonia (Linux 支持)
- **Web 服务器**: Kestrel (ASP.NET Core 内置)
- **API 框架**: ASP.NET Core Web API
- **数据访问**: Entity Framework Core
@@ -34,7 +34,8 @@ Hua.Todo/
│ │ ├── 技术栈与模块.md
│ │ ├── 版本记录.md
│ │ ├── 技术设计文档.md(本文件)
-│ │ └── 代码规范文档.md
+│ │ ├── 代码规范文档.md
+│ │ └── 部署文档.md
│ └── project/ # 项目进度/需求文档
│ ├── 产品需求文档.md
│ └── ...
@@ -73,7 +74,30 @@ Hua.Todo/
│ │ ├── MauiProgram.cs # MAUI 程序配置
│ │ └── Hua.Todo.Maui.csproj # MAUI 项目文件
│ │
-│ ├── Hua.Todo.Api/ # 后端 API 项目
+│ ├── Hua.Todo.Avalonia/ # Avalonia 项目(Linux 支持)
+│ │ ├── Assets/ # 资源文件
+│ │ │ └── icon.ico # 应用图标
+│ │ ├── Services/ # 服务层
+│ │ │ ├── EmbeddedWebServerServiceFactory.cs
+│ │ │ ├── GlobalHotKeyServiceFactory.cs
+│ │ │ ├── NoopEmbeddedWebServerService.cs
+│ │ │ └── Platforms/ # 平台特定服务
+│ │ │ ├── AndroidGlobalHotKeyService.cs
+│ │ │ └── LinuxGlobalHotKeyService.cs
+│ │ ├── Views/ # 视图
+│ │ │ ├── MainView.axaml
+│ │ │ ├── MainView.axaml.cs
+│ │ │ ├── MainWindow.axaml
+│ │ │ └── MainWindow.axaml.cs
+│ │ ├── App.axaml # Avalonia 应用入口
+│ │ ├── App.axaml.cs
+│ │ ├── Program.cs # Avalonia 程序配置
+│ │ ├── appsettings.json # 配置文件
+│ │ ├── setup.iss # 安装脚本
+│ │ ├── wwwroot/ # 前端静态资源
+│ │ └── Hua.Todo.Avalonia.csproj # Avalonia 项目文件
+│ │
+│ ├── Hua.Todo.Host/ # 后端 API 项目
│ │ ├── Controllers/ # API 控制器
│ │ │ ├── TasksController.cs
│ │ │ ├── SettingsController.cs
@@ -89,6 +113,8 @@ Hua.Todo/
│ │ │ └── SyncService.cs
│ │ ├── Data/ # 数据访问层
│ │ │ ├── TodoDbContext.cs
+│ │ │ ├── Converters/ # 类型转换器
+│ │ │ │ └── LenientUtcDateTimeStringConverter.cs
│ │ │ ├── Repositories/
│ │ │ │ ├── ITaskRepository.cs
│ │ │ │ └── TaskRepository.cs
@@ -99,7 +125,14 @@ Hua.Todo/
│ │ │ └── ServiceCollectionExtensions.cs
│ │ ├── Program.cs # API 入口
│ │ ├── appsettings.json # 配置文件
-│ │ └── Hua.Todo.Api.csproj # API 项目文件
+│ │ └── Hua.Todo.Host.csproj # Host 项目文件
+│ │
+│ ├── Hua.Todo.Application/ # 应用层
+│ │ ├── Data/ # 数据访问
+│ │ │ ├── TodoDbContext.cs
+│ │ │ └── Converters/ # 类型转换器
+│ │ │ └── LenientUtcDateTimeStringConverter.cs
+│ │ └── Hua.Todo.Application.csproj # Application 项目文件
│ │
│ ├── Hua.Todo.Core/ # 核心业务逻辑层
│ │ ├── Entities/ # 实体类
@@ -116,7 +149,7 @@ Hua.Todo/
│ │
│ ├── Hua.Todo.Web/ # 前端 Web 项目 (Vue.js)
│ │ ├── public/ # 静态资源
-│ │ │ └── index.html
+│ │ │ └── favicon.svg # 网站图标
│ │ ├── src/ # 源代码
│ │ │ ├── api/ # API 调用
│ │ │ │ ├── client.ts # HTTP 客户端配置
@@ -182,7 +215,23 @@ Hua.Todo/
- `WebViewContainer`: 封装 WebView 控件
- 平台特定服务: 快捷键、通知等
-### 4.2 后端 API 项目 (Hua.Todo.Host)
+### 4.2 Avalonia 项目 (Hua.Todo.Avalonia)
+**职责**:
+- Linux 平台支持
+- 桌面交互功能(托盘菜单、全局热键等)
+- WebView 容器管理
+- 本地 HTTP 服务器启动
+
+**关键组件**:
+- `Program.cs`: 配置 Avalonia 应用和依赖注入
+- `App.axaml.cs`: 应用程序主入口
+- `MainWindow.axaml.cs`: 主窗口管理
+- `MainView.axaml.cs`: 主视图管理
+- `GlobalHotKeyServiceFactory`: 全局热键服务工厂
+- `EmbeddedWebServerServiceFactory`: 内嵌 Web 服务器服务工厂
+- 平台特定服务: Linux 全局热键等
+
+### 4.3 后端 API 项目 (Hua.Todo.Host)
**职责**:
- 提供 RESTful API 接口
- 业务逻辑处理
@@ -198,7 +247,7 @@ Hua.Todo/
- `Data`: 数据访问层和数据库上下文
- `Program.cs`: API 服务器配置和启动
-### 4.3 核心业务层 (Hua.Todo.Core)
+### 4.4 核心业务层 (Hua.Todo.Core)
**职责**:
- 定义领域模型和业务规则
- 提供核心业务接口
@@ -210,7 +259,7 @@ Hua.Todo/
- `ValueObjects`: 值对象
- `Specifications`: 业务规范
-### 4.4 前端 Web 项目 (Hua.Todo.Web)
+### 4.5 前端 Web 项目 (Hua.Todo.Web)
**职责**:
- 用户界面展示
- 用户交互处理
diff --git a/docs/manual/版本记录.md b/docs/manual/版本记录.md
index 82720c2..89ecab3 100644
--- a/docs/manual/版本记录.md
+++ b/docs/manual/版本记录.md
@@ -11,10 +11,13 @@
### v1.2.0(开发中,2026-04-07)
+- **Linux 官方支持**:新增 `Hua.Todo.Avalonia` 项目,正式适配 Linux 平台,同时支持 Windows 和 macOS。
+- **Avalonia 桌面交互**:增加托盘菜单(显示/退出)、关闭隐藏到托盘、Windows 全局热键唤起主窗口、热键配置本地持久化;并对齐 Avalonia 的 appsettings 默认值。
- **关键词检索**:主界面增加搜索框,按任务标题实时过滤;采用“命中即显示(含上下文)”策略;支持 Esc 清空;英文大小写不敏感。
- **云同步(基础可用)**:新增“云同步设置”弹窗,支持手动配置服务端地址(格式校验 + 保存时可达性/风险提示);登录成功后拉取云端任务并刷新主界面(v1.2.0 为只读展示);401/403 时会自动清会话并弹出登录入口。
- **MAUI(Windows)内嵌 API 文档**:Debug 模式下,内嵌 WebServer 默认提供 Swagger UI(`{HostUrl}/swagger`)与 OpenAPI JSON(`{HostUrl}/swagger/v1/swagger.json`),便于本地接口调试。
- **Swagger 输出补齐 Dynamic API**:任务管理等 Dynamic API 端点会出现在 `swagger.json` 中,避免“接口缺失”导致联调困难。
+- **SQLite DateTime 兼容修复**:新增 `LenientUtcDateTimeStringConverter`,本地数据库中若存在历史遗留的 DateTime “ticks/时间戳字符串”脏数据,读取时将被兼容解析,避免 `/api/task` 等查询因单条坏数据整体失败。
- **SPA 路由回落行为修复**:当 Release/非 Debug 未启用 Swagger 时,`/swagger` 不再被当作“后端专用路径”排除,访问会按 SPA 路由规则回落到 `/index.html`,避免直接 404。
- **MAUI 多平台构建开关**:在 Windows 开发机上默认仅构建 Android + Windows 目标,避免 iOS/MacCatalyst 目标在非 macOS 环境触发运行时包缺失(NETSDK1082);在 macOS 上仍会包含 iOS/MacCatalyst 目标。
- **发布脚本整理**:拆分/对齐各平台发布入口,新增 `publish.ps1` 作为统一入口(默认发布 Windows + Linux),Windows 发布脚本支持开关打包与版本自增,发布产物会落盘到 `artifacts/`。
@@ -22,9 +25,10 @@
- **Windows WebView2 数据目录调整**:MAUI(Unpackaged)默认会在安装目录生成 `Hua.Todo.Maui.exe.WebView2`;现改为写入 `%LocalAppData%\Hua.Todo\WebView2`,避免污染安装目录。
- **Windows WebView2 Runtime 误判修复**:当系统已安装 WebView2 Runtime 但发布产物缺少/裁剪 WebView2 托管程序集时,旧检测逻辑会误判为“未安装”;现改为优先从常见安装目录探测 Evergreen 版本,避免阻断主界面加载。
- **Windows 三件套开发体验**:新增 `start-host.ps1` / `start-dev.ps1`,并在 MAUI 中约定 `IsUsingStatic=false` 时不启动内置 WebServer,避免注入覆盖 Vite 的 `/api -> 5173` 代理配置。
-- **Avalonia 桌面交互对齐 MAUI**:增加托盘菜单(显示/退出)、关闭隐藏到托盘、Windows 全局热键唤起主窗口、热键配置本地持久化;并对齐 Avalonia 的 appsettings 默认值。
-
-### v1.1.1 (2026-04-06)
+- **文档与部署指南**:新增 `docs/manual/部署文档.md`,详细说明开发环境搭建、多平台发布流程(Windows/Linux/Docker)以及关键配置项;并在技术设计文档中建立链接。
+- **用户文档完善**:新增 `docs/manual/新手指南.md` 和 `docs/manual/用户指南.md`,提供详细的使用说明和操作指南。
+27→
+28→### v1.1.1 (2026-04-06)
- **文档规范增强**:新增文档同步规则,强制代码变更与文档更新保持同步。
- **项目结构说明校准**:修正 README.md 和技术文档中对 `Hua.Todo.Host`、`Hua.Todo.Application` 等模块的路径与职责描述。
diff --git a/docs/manual/部署文档.md b/docs/manual/部署文档.md
new file mode 100644
index 0000000..df918e3
--- /dev/null
+++ b/docs/manual/部署文档.md
@@ -0,0 +1,128 @@
+# Hua.Todo 构建与部署手册
+
+本文档提供 Hua.Todo 项目的版本构建指南与多平台部署流程,侧重于如何产出可分发的版本并将其安装或部署到目标机器。
+
+## 1. 🏗️ 版本构建流程 (Release Build)
+
+在进行任何部署之前,必须先通过自动化脚本构建出 Release 版本的产物。
+
+### 1.1 前提要求
+
+- **环境检查**:已安装 .NET 10 SDK、Node.js 18+ 以及 Inno Setup 6(仅 Windows 打包需要)。
+- **脚本入口**:位于根目录的 `publish.ps1` 系列脚本。
+
+### 1.2 执行构建
+
+根据目标平台执行对应的构建命令:
+
+- **全平台一键构建**:
+ ```powershell
+ .\publish.ps1 -Windows -Linux
+ ```
+- **Windows 版本构建**:
+ ```powershell
+ .\publish-windows.ps1
+ ```
+- **Linux 版本构建**:
+ ```powershell
+ .\publish-linux.ps1 -RuntimeIdentifier linux-x64 -SelfContained
+ ```
+
+### 1.3 产物输出位置
+
+所有构建产物将按平台归类在根目录的 `artifacts/` 文件夹下:
+
+- **Windows**: `artifacts\windows\win-x64\installer\` (安装包) 与 `publish\` (解压即用版)
+- **Linux**: `artifacts\linux\linux-x64\` (`.tar.gz` 压缩包)
+
+***
+
+## 2. 🪟 Windows 客户端部署
+
+### 2.1 安装包分发 (Recommended)
+
+1. **分发文件**:将 `hua.todo-{version}-win-x64-setup.exe` 提供给终端用户。
+2. **安装流程**:用户运行安装程序,程序将自动:
+ - 安装到 `%ProgramFiles%\Hua.Todo`(或用户自定义路径)。
+ - 创建桌面与开始菜单快捷方式。
+ - 写入注册表以支持卸载。
+3. **静默安装**:支持 Inno Setup 标准静默参数 `/VERYSILENT /SUPPRESSMSGBOXES`。
+
+### 2.2 绿色版部署
+
+1. **分发文件**:将 `artifacts\windows\win-x64\publish\` 文件夹整体打包。
+2. **运行要求**:目标机器需安装 **WebView2 Runtime**。
+3. **启动程序**:运行 `Hua.Todo.Maui.exe`。
+
+***
+
+## 3. 🐧 Linux 客户端部署
+
+目前提供基于 Avalonia 的 Linux 交付版本,采用 `.tar.gz` 压缩包形式。
+
+### 3.1 解压部署
+
+1. **解压**:
+ ```bash
+ tar -xzf hua.todo-{version}-linux-x64.tar.gz -C /opt/hua-todo
+ ```
+2. **运行环境**:
+ - 确保系统安装了 `libwebkit2gtk-4.0-37`。
+ - 如果构建时未开启 `-SelfContained`,则需安装 .NET 10 Runtime。
+3. **权限设置**:
+ ```bash
+ chmod +x /opt/hua-todo/Hua.Todo.Avalonia
+ ```
+4. **启动**:直接运行 `/opt/hua-todo/Hua.Todo.Avalonia`。
+
+***
+
+## 4. ☁️ 云同步服务端部署 (Server)
+
+`Hua.Todo.Host` 可作为中心服务端部署,用于任务的云端同步。
+
+### 4.1 Docker 部署 (Recommended)
+
+1. **上传代码**或将 `src/Hua.Todo.Host/Dockerfile` 复制到服务器。
+2. **构建与启动**:
+ ```bash
+ docker build -t hua-todo-server -f src/Hua.Todo.Host/Dockerfile .
+ docker run -d \
+ --name hua-todo-server \
+ -p 5173:5173 \
+ -v /data/hua-todo/db:/app/data \
+ -e ASPNETCORE_ENVIRONMENT=Production \
+ hua-todo-server
+ ```
+
+### 4.2 直接部署 (Binary)
+
+1. **构建 Host**:`dotnet publish src/Hua.Todo.Host -c Release -o ./dist`。
+2. **同步产物**:将 `./dist` 内容同步到服务器。
+3. **配置 Systemd 服务**(可选):
+ 创建一个 `hua-todo.service` 文件,指向可执行程序并设置工作目录。
+
+***
+
+## 5. ⚙️ 关键配置校准
+
+### 5.1 数据持久化
+
+- **SQLite 路径**:客户端数据默认存储在用户目录下的 `Hua.Todo/todo.db`;服务端数据存储在容器挂载卷或指定 `appsettings.json` 的连接字符串中。
+- **备份建议**:定期备份 `todo.db` 文件。
+
+### 5.2 端口与访问
+
+- **客户端本地端口**:默认 `5057`。如果被占用,可在 `appsettings.json` 中修改 `WebServer.HostUrl`。
+- **服务端访问**:确保服务端防火墙已开放对应的 API 端口(默认 5173)。
+
+***
+
+## 6. 🛠️ 常见问题排查
+
+- **客户端无法加载 UI**:检查目标机器是否安装了 WebView2 Runtime(Windows)或 WebKitGTK(Linux)。
+- **同步连接失败**:
+ 1. 确认服务端 API 是否可达(访问 `/swagger` 验证)。
+ 2. 确认客户端配置的服务端地址格式(需包含 `http://` 或 `https://`)。
+- **权限问题**:在 Linux 下运行前,务必执行 `chmod +x` 给主程序执行权限。
+
diff --git a/docs/project/v1.2.0-tasks/02.1-版本统一与打包方案.md b/docs/project/v1.2.0-tasks/02.1-版本统一与打包方案.md
new file mode 100644
index 0000000..1418117
--- /dev/null
+++ b/docs/project/v1.2.0-tasks/02.1-版本统一与打包方案.md
@@ -0,0 +1,36 @@
+# 解决方案:统一版本与打包分发
+
+## 现状分析
+- **版本不一致**:`Hua.Todo.Maui` 的版本号为 `1.2.3`,而 `Hua.Todo.Avalonia` 和 `Hua.Todo.Host` 默认使用 `1.0.0`。
+- **打包脚本缺失**:目前仅 `Hua.Todo.Maui` 拥有 `setup.iss` (Inno Setup) 打包脚本,版本号硬编码为 `1.2.2`。
+- **配置冗余**:版本信息分散在各个 `.csproj` 和 `.iss` 文件中,维护困难。
+
+## 目标
+- 统一所有项目的版本号为 `1.2.3`。
+- 采用 `Directory.Build.props` 集中管理全局属性。
+- 为 `Hua.Todo.Avalonia` 提供与 `Hua.Todo.Maui` 一致的 Windows 安装程序打包能力。
+
+## 实施方案
+
+### 1. 统一 .NET 项目版本号
+- 在项目根目录创建 `Directory.Build.props` 文件。
+- 定义全局版本号 `1.2.3`。
+- 定义全局公司、版权、产品名称等元数据。
+- 移除各 `.csproj` 中冲突的版本定义。
+
+### 2. 统一 Inno Setup 打包脚本
+- **更新 `src/Hua.Todo.Maui/setup.iss`**:
+ - 将版本号更新为 `1.2.3`。
+ - 确保安装路径与应用名称一致。
+- **为 `src/Hua.Todo.Avalonia` 创建 `setup.iss`**:
+ - 参考 Maui 的脚本,调整 `Source` 路径为 Avalonia 的发布路径:`bin\Release\net10.0\win-x64\publish\*`。
+ - 调整可执行文件名称为 `Hua.Todo.Avalonia.exe`。
+ - 调整 AppId 以避免与 Maui 版本冲突。
+
+### 3. 发布流程标准化
+- 以后发布时,只需修改根目录下的 `Directory.Build.props` 即可同步所有项目的版本。
+- 执行 `dotnet publish -c Release -r win-x64` 后,手动或通过脚本运行 `ISCC setup.iss` 生成安装包。
+
+## 预期效果
+- 所有程序集(DLL/EXE)的版本号均显示为 `1.2.3`。
+- 提供 `Hua.Todo_Avalonia_Setup_v1.2.3.exe` 和 `Hua.Todo_Maui_Setup_v1.2.3.exe` 两个安装包。
diff --git a/publish-linux.ps1 b/publish-linux.ps1
index f538bf0..4afe144 100644
--- a/publish-linux.ps1
+++ b/publish-linux.ps1
@@ -14,14 +14,24 @@ param(
[ValidateSet("linux-x64", "linux-arm64")]
[string]$RuntimeIdentifier = "linux-x64",
+ [string]$TargetFramework = "net10.0",
+
[switch]$SelfContained,
- [string]$Configuration = "Release"
+ [switch]$SkipProcessStop,
+
+ [switch]$SkipRestore,
+
+ [ValidateSet("Release", "Debug")]
+ [string]$Configuration = "Release",
+
+ [string]$BaseIntermediateOutputPath
)
$ErrorActionPreference = "Stop"
$ScriptPath = $PSScriptRoot
+$DirectoryBuildProps = Join-Path $ScriptPath "Directory.Build.props"
function Get-FirstExistingFilePath {
param(
@@ -41,10 +51,23 @@ function Get-FirstExistingFilePath {
function Read-ProjectVersion {
param(
[Parameter(Mandatory = $true)]
- [string]$ProjectFile
+ [string]$ProjectFile,
+
+ [string]$DirectoryBuildProps
)
$currentVersion = "0.0.0"
+
+ # 1. Try Directory.Build.props first
+ if ($null -ne $DirectoryBuildProps -and (Test-Path $DirectoryBuildProps)) {
+ [xml]$props = Get-Content $DirectoryBuildProps -Raw
+ $versionNode = $props.SelectSingleNode("//Version")
+ if ($null -ne $versionNode -and -not [string]::IsNullOrWhiteSpace($versionNode.InnerText)) {
+ return $versionNode.InnerText.Trim()
+ }
+ }
+
+ # 2. Try .csproj
[xml]$csproj = Get-Content $ProjectFile -Raw
$versionNode = $csproj.SelectSingleNode("//Version")
@@ -60,6 +83,38 @@ function Read-ProjectVersion {
return $currentVersion
}
+function Stop-ProjectProcesses {
+ Write-Host "Shutting down dotnet build servers..." -ForegroundColor Yellow
+ dotnet build-server shutdown | Out-Null
+
+ Write-Host "Checking for running processes to prevent file locks..." -ForegroundColor Yellow
+
+ # Aggressively look for anything related to the project or MSBuild/dotnet background tasks
+ $processesToKill = Get-Process | Where-Object {
+ $_.ProcessName -like "*Hua.Todo*" -or
+ $_.ProcessName -eq "MSBuild" -or
+ ($_.ProcessName -eq "dotnet" -and ($_.CommandLine -like "*Hua.Todo*" -or $_.CommandLine -like "*msbuild*"))
+ }
+
+ if ($processesToKill) {
+ Write-Host "Stopping $($processesToKill.Count) running processes..." -ForegroundColor Yellow
+ foreach ($p in $processesToKill) {
+ try {
+ Stop-Process -Id $p.Id -Force -ErrorAction SilentlyContinue
+ } catch {
+ Write-Warning "Failed to stop process $($p.ProcessName) (ID: $($p.Id))"
+ }
+ }
+ Start-Sleep -Seconds 2 # Give OS more time to release file handles
+ } else {
+ Write-Host "No conflicting processes found." -ForegroundColor Green
+ }
+}
+
+if (!$SkipProcessStop.IsPresent) {
+ Stop-ProjectProcesses
+}
+
$candidateProjects = @(
(Join-Path $ScriptPath "src\Hua.Todo.Avalonia\Hua.Todo.Avalonia.csproj"),
(Join-Path $ScriptPath "src\Hua.Todo.Desktop.Avalonia\Hua.Todo.Desktop.Avalonia.csproj")
@@ -77,7 +132,8 @@ $candidatesText
exit 1
}
-$version = Read-ProjectVersion -ProjectFile $ProjectFile
+$version = Read-ProjectVersion -ProjectFile $ProjectFile -DirectoryBuildProps $DirectoryBuildProps
+$ProjectBaseName = [System.IO.Path]::GetFileNameWithoutExtension($ProjectFile)
$artifactRoot = Join-Path $ScriptPath "artifacts\linux\$RuntimeIdentifier"
$publishDir = Join-Path $artifactRoot "publish"
@@ -88,16 +144,57 @@ New-Item -ItemType Directory -Path $publishDir | Out-Null
$selfContainedValue = if ($SelfContained.IsPresent) { "true" } else { "false" }
-Write-Host "Publishing (RID=$RuntimeIdentifier, SelfContained=$selfContainedValue)..." -ForegroundColor Cyan
+if ($Configuration -ne "Release") {
+ Write-Host "⚠️ WARNING: You are publishing in $Configuration configuration!" -ForegroundColor Yellow
+ Write-Host " Typically, production artifacts MUST be in Release configuration." -ForegroundColor Yellow
+ Write-Host ""
+}
-dotnet publish $ProjectFile `
- -c $Configuration `
- -r $RuntimeIdentifier `
- --self-contained $selfContainedValue `
- -o $publishDir
+if (!$SkipRestore.IsPresent) {
+ Write-Host "Restoring $ProjectBaseName for $RuntimeIdentifier ($TargetFramework)..." -ForegroundColor Yellow
+ $restoreArgs = @("restore", $ProjectFile, "-r", $RuntimeIdentifier, "-p:IsDesktopBuild=true", "-p:SkipWebBuild=true", "--verbosity", "minimal")
+ if (![string]::IsNullOrWhiteSpace($BaseIntermediateOutputPath)) {
+ # Ensure trailing slash and avoid backslash escaping the quote in CLI
+ $path = $BaseIntermediateOutputPath.TrimEnd('\') + '\'
+ $restoreArgs += "-p:BaseIntermediateOutputPath=$path"
+ }
+ & dotnet @restoreArgs
-if ($LASTEXITCODE -ne 0) {
- Write-Error "dotnet publish failed"
+ Write-Host "Cleaning $ProjectBaseName ($TargetFramework)..." -ForegroundColor Yellow
+ $cleanArgs = @("clean", $ProjectFile, "-c", $Configuration, "-r", $RuntimeIdentifier, "-p:IsDesktopBuild=true", "-p:SkipWebBuild=true", "--verbosity", "minimal")
+ if (![string]::IsNullOrWhiteSpace($BaseIntermediateOutputPath)) {
+ $path = $BaseIntermediateOutputPath.TrimEnd('\') + '\'
+ $cleanArgs += "-p:BaseIntermediateOutputPath=$path"
+ }
+ & dotnet @cleanArgs
+}
+
+$maxAttempts = 3
+$publishSuccess = $false
+for ($attempt = 1; $attempt -le $maxAttempts; $attempt++) {
+ Write-Host "Publishing (RID=$RuntimeIdentifier, TFM=$TargetFramework, SelfContained=$selfContainedValue, Config=$Configuration, Attempt $attempt/$maxAttempts)..." -ForegroundColor Cyan
+ $publishArgs = @("publish", $ProjectFile, "-c", $Configuration, "-r", $RuntimeIdentifier, "--framework", $TargetFramework, "--self-contained", $selfContainedValue, "-p:IsDesktopBuild=true", "-p:SkipWebBuild=true", "-o", $publishDir)
+ if (![string]::IsNullOrWhiteSpace($BaseIntermediateOutputPath)) {
+ $path = $BaseIntermediateOutputPath.TrimEnd('\') + '\'
+ $publishArgs += "-p:BaseIntermediateOutputPath=$path"
+ }
+ $publishOutput = (& dotnet @publishArgs 2>&1 | Out-String)
+ $exitCode = $LASTEXITCODE
+
+ if ($exitCode -eq 0) {
+ $publishSuccess = $true
+ break
+ }
+
+ Write-Host $publishOutput
+ if ($attempt -lt $maxAttempts -and ($publishOutput -match 'Access to the path .* is denied|being used by another process|Sharing violation')) {
+ Write-Host "⚠️ Build failed due to file lock. Retrying in 3 seconds..." -ForegroundColor Yellow
+ Start-Sleep -Seconds 3
+ Stop-ProjectProcesses # Try killing processes again before retry
+ continue
+ }
+
+ Write-Error "dotnet publish failed after $attempt attempts."
exit 1
}
diff --git a/publish-windows.ps1 b/publish-windows.ps1
index c9c17d2..22492d3 100644
--- a/publish-windows.ps1
+++ b/publish-windows.ps1
@@ -1,32 +1,64 @@
param(
+ [ValidateSet("Maui", "Avalonia")]
+ [string]$AppType = "Maui",
+
[string]$TargetFramework = "net10.0-windows10.0.19041.0",
[string]$RuntimeIdentifier = "win-x64",
+ [ValidateSet("Release", "Debug")]
[string]$Configuration = "Release",
[switch]$SkipInnoSetup,
[switch]$SkipVersionBump,
- [string]$ArtifactsRoot = (Join-Path $PSScriptRoot ("artifacts\windows\{0}" -f $RuntimeIdentifier))
+ [switch]$SkipProcessStop,
+
+ [switch]$SkipRestore,
+
+ [string]$ArtifactsRoot = (Join-Path $PSScriptRoot ("artifacts\windows\{0}" -f $RuntimeIdentifier)),
+
+ [string]$BaseIntermediateOutputPath
)
$ErrorActionPreference = "Stop"
$ScriptPath = $PSScriptRoot
-$ProjectDir = Join-Path $ScriptPath "src\Hua.Todo.Maui"
-$ProjectFile = Join-Path $ProjectDir "Hua.Todo.Maui.csproj"
+
+if ($AppType -eq "Avalonia") {
+ $ProjectDir = Join-Path $ScriptPath "src\Hua.Todo.Avalonia"
+ $TargetFramework = "net10.0"
+} else {
+ $ProjectDir = Join-Path $ScriptPath "src\Hua.Todo.Maui"
+}
+
+$ProjectFile = Get-ChildItem -Path $ProjectDir -Filter "*.csproj" | Select-Object -First 1 -ExpandProperty FullName
$SetupScript = Join-Path $ProjectDir "setup.iss"
$ProjectBaseName = [System.IO.Path]::GetFileNameWithoutExtension($ProjectFile)
+$DirectoryBuildProps = Join-Path $ScriptPath "Directory.Build.props"
+
function Read-ProjectVersion {
param(
[Parameter(Mandatory = $true)]
- [string]$ProjectFile
+ [string]$ProjectFile,
+
+ [string]$DirectoryBuildProps
)
$currentVersion = "0.0.0"
+
+ # 1. Try Directory.Build.props first
+ if ($null -ne $DirectoryBuildProps -and (Test-Path $DirectoryBuildProps)) {
+ [xml]$props = Get-Content $DirectoryBuildProps -Raw
+ $versionNode = $props.SelectSingleNode("//Version")
+ if ($null -ne $versionNode -and -not [string]::IsNullOrWhiteSpace($versionNode.InnerText)) {
+ return $versionNode.InnerText.Trim()
+ }
+ }
+
+ # 2. Try .csproj
[xml]$csproj = Get-Content $ProjectFile -Raw
$versionNode = $csproj.SelectSingleNode("//Version")
@@ -153,14 +185,93 @@ function Copy-Directory {
Copy-Item -Path (Join-Path $Source "*") -Destination $Destination -Recurse -Force
}
-$currentVersion = Read-ProjectVersion -ProjectFile $ProjectFile
+function Stop-ProjectProcesses {
+ Write-Host "Shutting down dotnet build servers..." -ForegroundColor Yellow
+ dotnet build-server shutdown | Out-Null
+
+ Write-Host "Checking for running processes to prevent file locks..." -ForegroundColor Yellow
+
+ # Aggressively look for anything related to the project or MSBuild/dotnet background tasks
+ $processesToKill = Get-Process | Where-Object {
+ $_.ProcessName -like "*Hua.Todo*" -or
+ $_.ProcessName -eq "MSBuild" -or
+ ($_.ProcessName -eq "dotnet" -and ($_.CommandLine -like "*Hua.Todo*" -or $_.CommandLine -like "*msbuild*"))
+ }
+
+ if ($processesToKill) {
+ Write-Host "Stopping $($processesToKill.Count) running processes..." -ForegroundColor Yellow
+ foreach ($p in $processesToKill) {
+ try {
+ Stop-Process -Id $p.Id -Force -ErrorAction SilentlyContinue
+ } catch {
+ Write-Warning "Failed to stop process $($p.ProcessName) (ID: $($p.Id))"
+ }
+ }
+ Start-Sleep -Seconds 2 # Give OS more time to release file handles
+ } else {
+ Write-Host "No conflicting processes found." -ForegroundColor Green
+ }
+}
+
+if (!$SkipProcessStop.IsPresent) {
+ Stop-ProjectProcesses
+}
+
+$currentVersion = Read-ProjectVersion -ProjectFile $ProjectFile -DirectoryBuildProps $DirectoryBuildProps
Update-InnoSetupVersion -SetupScript $SetupScript -Version $currentVersion
-Write-Host "Publishing Hua.Todo.Maui (TFM=$TargetFramework, RID=$RuntimeIdentifier, Config=$Configuration)..." -ForegroundColor Cyan
+if ($Configuration -ne "Release") {
+ Write-Host "⚠️ WARNING: You are publishing in $Configuration configuration!" -ForegroundColor Yellow
+ Write-Host " Typically, production artifacts MUST be in Release configuration." -ForegroundColor Yellow
+ Write-Host ""
+}
+
+if (!$SkipRestore.IsPresent) {
+ Write-Host "Restoring $ProjectBaseName for $RuntimeIdentifier ($TargetFramework)..." -ForegroundColor Yellow
+ $restoreArgs = @("restore", $ProjectFile, "-r", $RuntimeIdentifier, "-p:IsDesktopBuild=true", "-p:SkipWebBuild=true", "--verbosity", "minimal")
+ if (![string]::IsNullOrWhiteSpace($BaseIntermediateOutputPath)) {
+ # Ensure trailing slash and avoid backslash escaping the quote in CLI
+ $path = $BaseIntermediateOutputPath.TrimEnd('\') + '\'
+ $restoreArgs += "-p:BaseIntermediateOutputPath=$path"
+ }
+ & dotnet @restoreArgs
+
+ Write-Host "Cleaning $ProjectBaseName ($TargetFramework)..." -ForegroundColor Yellow
+ $cleanArgs = @("clean", $ProjectFile, "-c", $Configuration, "-r", $RuntimeIdentifier, "-p:IsDesktopBuild=true", "-p:SkipWebBuild=true", "--verbosity", "minimal")
+ if (![string]::IsNullOrWhiteSpace($BaseIntermediateOutputPath)) {
+ $path = $BaseIntermediateOutputPath.TrimEnd('\') + '\'
+ $cleanArgs += "-p:BaseIntermediateOutputPath=$path"
+ }
+ & dotnet @cleanArgs
+}
+
# UseMonoRuntime 在 csproj 内按 TargetFramework 做了条件配置:仅 Android 启用,其它目标关闭。
-dotnet publish $ProjectFile -f $TargetFramework -c $Configuration -r $RuntimeIdentifier --self-contained false
-if ($LASTEXITCODE -ne 0) {
- Write-Error "MAUI build failed"
+$maxAttempts = 3
+$publishSuccess = $false
+for ($attempt = 1; $attempt -le $maxAttempts; $attempt++) {
+ Write-Host "Publishing $ProjectBaseName (Attempt $attempt/$maxAttempts)..." -ForegroundColor Cyan
+ $publishArgs = @("publish", $ProjectFile, "--framework", $TargetFramework, "-c", $Configuration, "-r", $RuntimeIdentifier, "--self-contained", "false", "-p:IsDesktopBuild=true", "-p:SkipWebBuild=true")
+ if (![string]::IsNullOrWhiteSpace($BaseIntermediateOutputPath)) {
+ $path = $BaseIntermediateOutputPath.TrimEnd('\') + '\'
+ $publishArgs += "-p:BaseIntermediateOutputPath=$path"
+ }
+ $publishOutput = (& dotnet @publishArgs 2>&1 | Out-String)
+ $exitCode = $LASTEXITCODE
+
+ if ($exitCode -eq 0) {
+ $publishSuccess = $true
+ break
+ }
+
+ Write-Host $publishOutput
+ if ($attempt -lt $maxAttempts -and ($publishOutput -match 'Access to the path .* is denied|being used by another process|Sharing violation')) {
+ Write-Host "⚠️ Build failed due to file lock. Retrying in 3 seconds..." -ForegroundColor Yellow
+ Start-Sleep -Seconds 3
+ Stop-ProjectProcesses # Try killing processes again before retry
+ continue
+ }
+
+ Write-Error "MAUI build failed after $attempt attempts."
exit 1
}
@@ -192,6 +303,7 @@ if (!(Test-Path $desiredExePath)) {
$candidateExe = $null
$preferredCandidateNames = @(
"Hua.Todo.Maui.exe",
+ "Hua.Todo.Avalonia.exe",
"Hua.Todo.exe"
)
foreach ($name in $preferredCandidateNames) {
@@ -217,19 +329,21 @@ if (!(Test-Path $desiredExePath)) {
exit 1
}
-$mauiWwwrootDir = Join-Path $ProjectDir "wwwroot"
-$mauiIndexPath = Join-Path $mauiWwwrootDir "index.html"
-if (!(Test-Path $mauiIndexPath)) {
- Write-Error "MAUI wwwroot not found: $mauiIndexPath"
- exit 1
-}
+if ($AppType -eq "Maui") {
+ $mauiWwwrootDir = Join-Path $ProjectDir "wwwroot"
+ $mauiIndexPath = Join-Path $mauiWwwrootDir "index.html"
+ if (!(Test-Path $mauiIndexPath)) {
+ Write-Error "MAUI wwwroot not found: $mauiIndexPath"
+ exit 1
+ }
-$publishWwwroot = Join-Path $publishDir "wwwroot"
-if (Test-Path $publishWwwroot) {
- Remove-Item -Recurse -Force $publishWwwroot
+ $publishWwwroot = Join-Path $publishDir "wwwroot"
+ if (Test-Path $publishWwwroot) {
+ Remove-Item -Recurse -Force $publishWwwroot
+ }
+ New-Item -ItemType Directory -Path $publishWwwroot | Out-Null
+ Copy-Item -Path (Join-Path $mauiWwwrootDir "*") -Destination $publishWwwroot -Recurse -Force
}
-New-Item -ItemType Directory -Path $publishWwwroot | Out-Null
-Copy-Item -Path (Join-Path $mauiWwwrootDir "*") -Destination $publishWwwroot -Recurse -Force
$installerPath = $null
if (!$SkipInnoSetup.IsPresent) {
@@ -255,6 +369,7 @@ if (!$SkipInnoSetup.IsPresent) {
# ISCC sometimes fails with a transient file sharing violation (e.g. antivirus/indexer holding the script/output briefly).
$maxAttempts = 3
for ($attempt = 1; $attempt -le $maxAttempts; $attempt++) {
+ Write-Host "Compiling installer (Attempt $attempt/$maxAttempts)..." -ForegroundColor Cyan
$isccOutput = (& $ISCC $SetupScript 2>&1 | Out-String)
$exitCode = $LASTEXITCODE
if ($exitCode -eq 0) {
@@ -286,8 +401,7 @@ if (!$SkipInnoSetup.IsPresent) {
Write-Host ("Output: {0}" -f $installerPath) -ForegroundColor Green
}
} else {
- Write-Error "Inno Setup compiler not found"
- exit 1
+ Write-Warning "Inno Setup compiler not found. Skipping installer creation."
}
}
@@ -302,7 +416,8 @@ if (![string]::IsNullOrWhiteSpace($ArtifactsRoot)) {
}
New-Item -ItemType Directory -Path $installerArtifactDir | Out-Null
- $installerName = "hua.todo-$currentVersion-$RuntimeIdentifier-setup.exe"
+ $installerPrefix = if ($AppType -eq "Avalonia") { "hua.todo-avalonia" } else { "hua.todo-maui" }
+ $installerName = "$installerPrefix-$currentVersion-$RuntimeIdentifier-setup.exe"
Copy-Item -Path $installerPath -Destination (Join-Path $installerArtifactDir $installerName) -Force
}
}
@@ -312,12 +427,22 @@ if (!$SkipVersionBump.IsPresent) {
if ($versionMatch.Success) {
$newVersion = "{0}.{1}.{2}" -f $versionMatch.Groups["major"].Value, $versionMatch.Groups["minor"].Value, ([int]$versionMatch.Groups["patch"].Value + 1)
- $content = Get-Content $ProjectFile -Raw
- if ($content -match "[^<]*") {
- $content = $content -replace "[^<]*", "$newVersion"
- Set-Content $ProjectFile -Value $content -Encoding UTF8
- } else {
- Write-Host "Skip version bump: node not found in csproj." -ForegroundColor Yellow
+ # 1. Update Directory.Build.props if exists
+ if (Test-Path $DirectoryBuildProps) {
+ $propsContent = Get-Content $DirectoryBuildProps -Raw
+ if ($propsContent -match "[^<]*") {
+ $propsContent = $propsContent -replace "[^<]*", "$newVersion"
+ Set-Content $DirectoryBuildProps -Value $propsContent -Encoding UTF8
+ Write-Host "Updated version in Directory.Build.props to $newVersion" -ForegroundColor Green
+ }
+ }
+
+ # 2. Update .csproj if it still has Version
+ $csprojContent = Get-Content $ProjectFile -Raw
+ if ($csprojContent -match "[^<]*") {
+ $csprojContent = $csprojContent -replace "[^<]*", "$newVersion"
+ Set-Content $ProjectFile -Value $csprojContent -Encoding UTF8
+ Write-Host "Updated version in $ProjectBaseName.csproj to $newVersion" -ForegroundColor Green
}
} else {
Write-Host "Skip version bump: version is not MAJOR.MINOR.PATCH -> $currentVersion" -ForegroundColor Yellow
diff --git a/publish.ps1 b/publish.ps1
index 9bc0148..eef69ec 100644
--- a/publish.ps1
+++ b/publish.ps1
@@ -7,6 +7,7 @@ param(
[switch]$LinuxSelfContained,
+ [ValidateSet("Release", "Debug")]
[string]$Configuration = "Release",
[switch]$SkipWindowsInnoSetup,
@@ -17,9 +18,92 @@ param(
$ErrorActionPreference = "Stop"
$ScriptPath = $PSScriptRoot
-
+$WebDir = Join-Path $ScriptPath "src\Hua.Todo.Web"
$publishWindowsScript = Join-Path $ScriptPath "publish-windows.ps1"
$publishLinuxScript = Join-Path $ScriptPath "publish-linux.ps1"
+$DirectoryBuildProps = Join-Path $ScriptPath "Directory.Build.props"
+
+function Stop-ProjectProcesses {
+ Write-Host "Shutting down dotnet build servers..." -ForegroundColor Yellow
+ dotnet build-server shutdown | Out-Null
+
+ Write-Host "Checking for running processes to prevent file locks..." -ForegroundColor Yellow
+
+ $processesToKill = Get-Process | Where-Object {
+ $_.ProcessName -like "*Hua.Todo*" -or
+ $_.ProcessName -eq "MSBuild" -or
+ ($_.ProcessName -eq "dotnet" -and ($_.CommandLine -like "*Hua.Todo*" -or $_.CommandLine -like "*msbuild*"))
+ }
+
+ if ($processesToKill) {
+ Write-Host "Stopping $($processesToKill.Count) running processes..." -ForegroundColor Yellow
+ foreach ($p in $processesToKill) {
+ try {
+ Stop-Process -Id $p.Id -Force -ErrorAction SilentlyContinue
+ } catch {
+ Write-Warning "Failed to stop process $($p.ProcessName) (ID: $($p.Id))"
+ }
+ }
+ Start-Sleep -Seconds 2
+ } else {
+ Write-Host "No conflicting processes found." -ForegroundColor Green
+ }
+}
+
+function Build-Web {
+ Write-Host "Building Web artifacts..." -ForegroundColor Cyan
+ if (!(Test-Path $WebDir)) {
+ Write-Error "Web directory not found: $WebDir"
+ exit 1
+ }
+
+ if (!(Test-Path (Join-Path $WebDir "node_modules"))) {
+ Write-Host "Installing npm dependencies..." -ForegroundColor Yellow
+ Push-Location $WebDir
+ npm install
+ Pop-Location
+ }
+
+ Write-Host "Running Web builds in parallel..." -ForegroundColor Yellow
+ $webJobs = @()
+ $webJobs += Start-Job -ScriptBlock {
+ param($dir)
+ Set-Location $dir
+ npm run build
+ } -ArgumentList $WebDir
+
+ $webJobs += Start-Job -ScriptBlock {
+ param($dir)
+ Set-Location $dir
+ npm run build -- --mode maui
+ } -ArgumentList $WebDir
+
+ $webJobs | Wait-Job | Receive-Job
+}
+
+function Bump-Version {
+ if (Test-Path $DirectoryBuildProps) {
+ [xml]$props = Get-Content $DirectoryBuildProps -Raw
+ $versionNode = $props.SelectSingleNode("//Version")
+ if ($null -ne $versionNode -and -not [string]::IsNullOrWhiteSpace($versionNode.InnerText)) {
+ $currentVersion = $versionNode.InnerText.Trim()
+ $versionMatch = [regex]::Match($currentVersion, '^(?\d+)\.(?\d+)\.(?\d+)$')
+ if ($versionMatch.Success) {
+ $newVersion = "{0}.{1}.{2}" -f $versionMatch.Groups["major"].Value, $versionMatch.Groups["minor"].Value, ([int]$versionMatch.Groups["patch"].Value + 1)
+ $propsContent = Get-Content $DirectoryBuildProps -Raw
+ $propsContent = $propsContent -replace "[^<]*", "$newVersion"
+ Set-Content $DirectoryBuildProps -Value $propsContent -Encoding UTF8
+ Write-Host "Bumped version in Directory.Build.props: $currentVersion -> $newVersion" -ForegroundColor Green
+ }
+ }
+ }
+}
+
+if ($Configuration -ne "Release") {
+ Write-Host "⚠️ WARNING: You are publishing in $Configuration configuration!" -ForegroundColor Yellow
+ Write-Host " Typically, production artifacts MUST be in Release configuration." -ForegroundColor Yellow
+ Write-Host ""
+}
$shouldPublishWindows = $Windows.IsPresent
$shouldPublishLinux = $Linux.IsPresent
@@ -28,36 +112,36 @@ if (!$shouldPublishWindows -and !$shouldPublishLinux) {
$shouldPublishLinux = $true
}
+# 1. Cleanup
+Stop-ProjectProcesses
+
+# 2. Build Web
+Build-Web
+
+# 3. App Publishing
+# NOTE: To avoid file locks in 'obj' and 'bin' folders, we publish the .NET apps sequentially.
+# However, we can parallelize the Inno Setup packaging later if needed.
+Write-Host "Starting app publishing..." -ForegroundColor Cyan
+
if ($shouldPublishWindows) {
- if (!(Test-Path $publishWindowsScript)) {
- Write-Error "publish-windows.ps1 not found: $publishWindowsScript"
- exit 1
- }
-
- & $publishWindowsScript `
- -Configuration $Configuration `
- -SkipInnoSetup:$SkipWindowsInnoSetup `
- -SkipVersionBump:$SkipWindowsVersionBump
-
- if ($LASTEXITCODE -ne 0) {
- exit $LASTEXITCODE
- }
+ Write-Host "Publishing Windows Apps..." -ForegroundColor Cyan
+ # Maui Windows (Skip ISS here, we'll do it later if parallel is needed, or just let it run)
+ & $publishWindowsScript -AppType Maui -Configuration $Configuration -SkipInnoSetup:$SkipWindowsInnoSetup -SkipVersionBump -SkipProcessStop
+
+ # Avalonia Windows
+ & $publishWindowsScript -AppType Avalonia -Configuration $Configuration -SkipInnoSetup:$SkipWindowsInnoSetup -SkipVersionBump -SkipProcessStop
}
if ($shouldPublishLinux) {
- if (!(Test-Path $publishLinuxScript)) {
- Write-Error "publish-linux.ps1 not found: $publishLinuxScript"
- exit 1
- }
-
+ Write-Host "Publishing Linux Apps..." -ForegroundColor Cyan
foreach ($rid in $LinuxRuntimes) {
- & $publishLinuxScript `
- -RuntimeIdentifier $rid `
- -SelfContained:$LinuxSelfContained `
- -Configuration $Configuration
-
- if ($LASTEXITCODE -ne 0) {
- exit $LASTEXITCODE
- }
+ & $publishLinuxScript -RuntimeIdentifier $rid -SelfContained:$LinuxSelfContained -Configuration $Configuration -SkipProcessStop
}
}
+
+# 4. Finalizing
+if (!$SkipWindowsVersionBump.IsPresent) {
+ Bump-Version
+}
+
+Write-Host "All publishing tasks completed!" -ForegroundColor Green
diff --git a/src/Hua.Todo.Application/Data/Converters/LenientUtcDateTimeStringConverter.cs b/src/Hua.Todo.Application/Data/Converters/LenientUtcDateTimeStringConverter.cs
new file mode 100644
index 0000000..037851f
--- /dev/null
+++ b/src/Hua.Todo.Application/Data/Converters/LenientUtcDateTimeStringConverter.cs
@@ -0,0 +1,70 @@
+using System.Globalization;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+namespace Hua.Todo.Application.Data.Converters;
+
+///
+/// 将 以 UTC 的 ISO 8601(Round-trip)字符串形式持久化到 SQLite,
+/// 并在读取时兼容历史遗留的 “ticks/Unix 时间戳” 数字字符串,避免因脏数据导致查询失败。
+///
+public sealed class LenientUtcDateTimeStringConverter : ValueConverter
+{
+ ///
+ /// 创建 UTC DateTime 与 SQLite TEXT 之间的转换器。
+ ///
+ public LenientUtcDateTimeStringConverter()
+ : base(
+ model => ConvertModelToProvider(model),
+ provider => ConvertProviderToModel(provider))
+ {
+ }
+
+ private static string ConvertModelToProvider(DateTime value)
+ {
+ var utc = value.Kind switch
+ {
+ DateTimeKind.Utc => value,
+ DateTimeKind.Local => value.ToUniversalTime(),
+ _ => DateTime.SpecifyKind(value, DateTimeKind.Utc)
+ };
+
+ return utc.ToString("O", CultureInfo.InvariantCulture);
+ }
+
+ private static DateTime ConvertProviderToModel(string value)
+ {
+ if (string.IsNullOrWhiteSpace(value))
+ {
+ return DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
+ }
+
+ if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var numeric))
+ {
+ if (numeric >= DateTime.MinValue.Ticks && numeric <= DateTime.MaxValue.Ticks && numeric >= 10_000_000_000_000)
+ {
+ return new DateTime(numeric, DateTimeKind.Utc);
+ }
+
+ if (numeric >= 0 && numeric <= 253_402_300_799_999)
+ {
+ return DateTimeOffset.FromUnixTimeMilliseconds(numeric).UtcDateTime;
+ }
+
+ if (numeric >= 0 && numeric <= 253_402_300_799)
+ {
+ return DateTimeOffset.FromUnixTimeSeconds(numeric).UtcDateTime;
+ }
+ }
+
+ if (DateTime.TryParse(
+ value,
+ CultureInfo.InvariantCulture,
+ DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal,
+ out var parsed))
+ {
+ return parsed.Kind == DateTimeKind.Utc ? parsed : DateTime.SpecifyKind(parsed, DateTimeKind.Utc);
+ }
+
+ return DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
+ }
+}
diff --git a/src/Hua.Todo.Application/Data/TodoDbContext.cs b/src/Hua.Todo.Application/Data/TodoDbContext.cs
index 54a6c78..1b5abd3 100644
--- a/src/Hua.Todo.Application/Data/TodoDbContext.cs
+++ b/src/Hua.Todo.Application/Data/TodoDbContext.cs
@@ -1,5 +1,6 @@
using Microsoft.EntityFrameworkCore;
using Hua.Todo.Core.Entities;
+using Hua.Todo.Application.Data.Converters;
namespace Hua.Todo.Application.Data;
@@ -44,6 +45,8 @@ public class TodoDbContext : DbContext
{
base.OnModelCreating(modelBuilder);
+ var utcDateTimeConverter = new LenientUtcDateTimeStringConverter();
+
modelBuilder.Entity(entity =>
{
entity.ToTable("Tasks");
@@ -52,8 +55,8 @@ public class TodoDbContext : DbContext
entity.Property(e => e.Title).IsRequired().HasMaxLength(200);
entity.Property(e => e.Priority).HasDefaultValue(TaskPriority.Medium);
entity.Property(e => e.IsCompleted).HasDefaultValue(false);
- entity.Property(e => e.CreatedAt).HasDefaultValueSql("datetime('now')");
- entity.Property(e => e.UpdatedAt).HasDefaultValueSql("datetime('now')");
+ entity.Property(e => e.CreatedAt).HasConversion(utcDateTimeConverter).HasDefaultValueSql("datetime('now')");
+ entity.Property(e => e.UpdatedAt).HasConversion(utcDateTimeConverter).HasDefaultValueSql("datetime('now')");
entity.HasOne(e => e.User)
.WithMany(u => u.Tasks)
@@ -80,8 +83,9 @@ public class TodoDbContext : DbContext
{
entity.ToTable("UserSessions");
entity.HasKey(e => e.Id);
- entity.Property(e => e.CreatedAtUtc).IsRequired();
- entity.Property(e => e.ExpiresAtUtc).IsRequired();
+ entity.Property(e => e.CreatedAtUtc).IsRequired().HasConversion(utcDateTimeConverter);
+ entity.Property(e => e.ExpiresAtUtc).IsRequired().HasConversion(utcDateTimeConverter);
+ entity.Property(e => e.StepUpExpiresAtUtc).HasConversion(utcDateTimeConverter);
entity.HasIndex(e => e.UserId);
entity.HasOne(e => e.User)
.WithMany()
diff --git a/src/Hua.Todo.Application/Hua.Todo.Application.csproj b/src/Hua.Todo.Application/Hua.Todo.Application.csproj
index 793e518..c696ada 100644
--- a/src/Hua.Todo.Application/Hua.Todo.Application.csproj
+++ b/src/Hua.Todo.Application/Hua.Todo.Application.csproj
@@ -1,7 +1,10 @@
- net10.0;net10.0-android;net10.0-ios;net10.0-maccatalyst
+
+ true
+ net10.0
+ net10.0;net10.0-android;net10.0-ios;net10.0-maccatalyst
enable
enable
Library
diff --git a/src/Hua.Todo.Avalonia/App.axaml b/src/Hua.Todo.Avalonia/App.axaml
index 09bcd01..1e920c1 100644
--- a/src/Hua.Todo.Avalonia/App.axaml
+++ b/src/Hua.Todo.Avalonia/App.axaml
@@ -2,27 +2,9 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Hua.Todo.Avalonia.App"
xmlns:local="using:Hua.Todo.Avalonia"
- xmlns:vm="using:Hua.Todo.Avalonia.ViewModels"
- x:DataType="vm:AppTrayViewModel"
RequestedThemeVariant="Default">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Hua.Todo.Avalonia/App.axaml.cs b/src/Hua.Todo.Avalonia/App.axaml.cs
index f0e3603..5b845d1 100644
--- a/src/Hua.Todo.Avalonia/App.axaml.cs
+++ b/src/Hua.Todo.Avalonia/App.axaml.cs
@@ -1,8 +1,8 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
-using Avalonia.Data.Core.Plugins;
using Avalonia.Markup.Xaml;
+using Avalonia.Platform;
using Avalonia.Threading;
using AvaloniaWebView;
using Hua.Todo.Avalonia.Models;
@@ -13,7 +13,6 @@ using Hua.Todo.Avalonia.Views;
using System;
using System.ComponentModel;
using System.IO;
-using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
@@ -98,9 +97,7 @@ public partial class App : global::Avalonia.Application
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
- DisableAvaloniaDataAnnotationValidation();
-
- _webServer = new EmbeddedWebServerService(_appSettings!);
+ _webServer = EmbeddedWebServerServiceFactory.Create(_appSettings!);
_ = Task.Run(async () =>
{
try
@@ -132,10 +129,16 @@ public partial class App : global::Avalonia.Application
};
}
- DataContext = new AppTrayViewModel(
- AppMetadata.GetTrayTooltipText(),
- ShowMainWindow,
- () => ExitApplication(desktop));
+ // 只在支持的平台上初始化系统托盘
+ if (OperatingSystem.IsWindows() || OperatingSystem.IsLinux())
+ {
+ var trayViewModel = new AppTrayViewModel(
+ AppMetadata.GetTrayTooltipText(),
+ ShowMainWindow,
+ () => ExitApplication(desktop));
+
+ InitializeTrayIcon(trayViewModel);
+ }
_mainWindow = new MainWindow(_appSettings!, _webServer)
{
@@ -185,6 +188,12 @@ public partial class App : global::Avalonia.Application
}
};
}
+ else if (ApplicationLifetime is ISingleViewApplicationLifetime singleView)
+ {
+ _webServer = EmbeddedWebServerServiceFactory.Create(_appSettings!);
+
+ singleView.MainView = new MainView(_appSettings!, _webServer);
+ }
base.OnFrameworkInitializationCompleted();
}
@@ -257,14 +266,43 @@ public partial class App : global::Avalonia.Application
}
}
- private void DisableAvaloniaDataAnnotationValidation()
+ private void InitializeTrayIcon(AppTrayViewModel trayViewModel)
{
- var dataValidationPluginsToRemove =
- BindingPlugins.DataValidators.OfType().ToArray();
-
- foreach (var plugin in dataValidationPluginsToRemove)
+ try
{
- BindingPlugins.DataValidators.Remove(plugin);
+ var trayIcons = new TrayIcons();
+
+ var iconUri = new Uri("avares://Hua.Todo.Avalonia/Assets/avalonia-logo.ico");
+ var icon = new WindowIcon(AssetLoader.Open(iconUri));
+
+ var trayIcon = new TrayIcon
+ {
+ Icon = icon,
+ ToolTipText = trayViewModel.TrayTooltipText,
+ Command = trayViewModel.ShowMainWindowCommand
+ };
+
+ var menu = new NativeMenu();
+ menu.Items.Add(new NativeMenuItem
+ {
+ Header = "显示主窗口",
+ Command = trayViewModel.ShowMainWindowCommand
+ });
+ menu.Items.Add(new NativeMenuItemSeparator());
+ menu.Items.Add(new NativeMenuItem
+ {
+ Header = "退出",
+ Command = trayViewModel.ExitApplicationCommand
+ });
+
+ trayIcon.Menu = menu;
+ trayIcons.Add(trayIcon);
+
+ TrayIcon.SetIcons(this, trayIcons);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"[App] Tray icon initialization failed: {ex}");
}
}
}
diff --git a/src/Hua.Todo.Avalonia/Assets/avalonia-logo.ico b/src/Hua.Todo.Avalonia/Assets/avalonia-logo.ico
deleted file mode 100644
index f7da8bb..0000000
Binary files a/src/Hua.Todo.Avalonia/Assets/avalonia-logo.ico and /dev/null differ
diff --git a/src/Hua.Todo.Avalonia/Assets/icon.ico b/src/Hua.Todo.Avalonia/Assets/icon.ico
new file mode 100644
index 0000000..8720501
Binary files /dev/null and b/src/Hua.Todo.Avalonia/Assets/icon.ico differ
diff --git a/src/Hua.Todo.Avalonia/Hua.Todo.Avalonia.csproj b/src/Hua.Todo.Avalonia/Hua.Todo.Avalonia.csproj
index 799f4a2..c24066c 100644
--- a/src/Hua.Todo.Avalonia/Hua.Todo.Avalonia.csproj
+++ b/src/Hua.Todo.Avalonia/Hua.Todo.Avalonia.csproj
@@ -1,7 +1,10 @@
WinExe
- net10.0
+ net10.0
+ net10.0-windows10.0.19041.0
+ net10.0
+ net10.0
enable
app.manifest
true
@@ -17,14 +20,14 @@
-
-
-
-
+
+
+
+
-
+
None
All
@@ -35,6 +38,10 @@
PreserveNewest
+
+ PreserveNewest
+ PreserveNewest
+
diff --git a/src/Hua.Todo.Avalonia/Output/Hua.Todo.Avalonia_Setup_v1.2.7.exe b/src/Hua.Todo.Avalonia/Output/Hua.Todo.Avalonia_Setup_v1.2.7.exe
new file mode 100644
index 0000000..6ed8756
Binary files /dev/null and b/src/Hua.Todo.Avalonia/Output/Hua.Todo.Avalonia_Setup_v1.2.7.exe differ
diff --git a/src/Hua.Todo.Avalonia/Program.cs b/src/Hua.Todo.Avalonia/Program.cs
index c2d7bd8..7ab08b0 100644
--- a/src/Hua.Todo.Avalonia/Program.cs
+++ b/src/Hua.Todo.Avalonia/Program.cs
@@ -1,5 +1,7 @@
using Avalonia;
using Avalonia.WebView.Desktop;
+using Hua.Todo.Avalonia.Services;
+using Hua.Todo.Avalonia.Models;
using System;
namespace Hua.Todo.Avalonia;
@@ -10,8 +12,14 @@ sealed class Program
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
- public static void Main(string[] args) => BuildAvaloniaApp()
- .StartWithClassicDesktopLifetime(args);
+ public static void Main(string[] args)
+ {
+ // 设置嵌入式 Web 服务器工厂
+ EmbeddedWebServerServiceFactory.SetFactory(appSettings => new EmbeddedWebServerService(appSettings));
+
+ BuildAvaloniaApp()
+ .StartWithClassicDesktopLifetime(args);
+ }
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
diff --git a/src/Hua.Todo.Avalonia/Services/EmbeddedWebServerServiceFactory.cs b/src/Hua.Todo.Avalonia/Services/EmbeddedWebServerServiceFactory.cs
new file mode 100644
index 0000000..b2cb292
--- /dev/null
+++ b/src/Hua.Todo.Avalonia/Services/EmbeddedWebServerServiceFactory.cs
@@ -0,0 +1,42 @@
+using System;
+using Hua.Todo.Avalonia.Models;
+
+namespace Hua.Todo.Avalonia.Services;
+
+///
+/// 嵌入式 WebServer 的平台工厂。
+/// 由平台入口项目在启动时注入实际实现(例如 Desktop 使用 Kestrel,Android 可使用 Noop 或移动端实现),
+/// 以避免共享项目直接依赖某个平台不可用的运行时组件。
+///
+public static class EmbeddedWebServerServiceFactory
+{
+ private static Func? _factory;
+
+ ///
+ /// 设置 WebServer 创建工厂。
+ /// 平台入口应尽早调用(在 生命周期开始前完成),以确保应用启动过程可用。
+ ///
+ /// 根据应用配置创建 WebServer 的工厂方法。
+ /// 当 为 null。
+ public static void SetFactory(Func factory)
+ {
+ _factory = factory ?? throw new ArgumentNullException(nameof(factory));
+ }
+
+ ///
+ /// 创建 WebServer 实例。
+ /// 若平台未注入工厂,则回退为 (不启动本地服务,仅用于维持调用链)。
+ ///
+ /// 应用配置。
+ /// 嵌入式 WebServer 实例。
+ public static IEmbeddedWebServerService Create(AppSettings appSettings)
+ {
+ if (_factory != null)
+ {
+ return _factory(appSettings);
+ }
+
+ return new NoopEmbeddedWebServerService(appSettings.WebServer.HostUrl);
+ }
+}
+
diff --git a/src/Hua.Todo.Avalonia/Services/GlobalHotKeyServiceFactory.cs b/src/Hua.Todo.Avalonia/Services/GlobalHotKeyServiceFactory.cs
index a61cc9b..22851d8 100644
--- a/src/Hua.Todo.Avalonia/Services/GlobalHotKeyServiceFactory.cs
+++ b/src/Hua.Todo.Avalonia/Services/GlobalHotKeyServiceFactory.cs
@@ -18,6 +18,14 @@ public static class GlobalHotKeyServiceFactory
{
return new WindowsGlobalHotKeyService();
}
+ else if (OperatingSystem.IsLinux())
+ {
+ return new LinuxGlobalHotKeyService();
+ }
+ else if (OperatingSystem.IsAndroid())
+ {
+ return new AndroidGlobalHotKeyService();
+ }
return new NoopGlobalHotKeyService();
}
diff --git a/src/Hua.Todo.Avalonia/Services/NoopEmbeddedWebServerService.cs b/src/Hua.Todo.Avalonia/Services/NoopEmbeddedWebServerService.cs
new file mode 100644
index 0000000..7e81b04
--- /dev/null
+++ b/src/Hua.Todo.Avalonia/Services/NoopEmbeddedWebServerService.cs
@@ -0,0 +1,34 @@
+using System.Threading.Tasks;
+
+namespace Hua.Todo.Avalonia.Services;
+
+///
+/// 不启动任何本地 WebServer 的占位实现。
+/// 适用于移动端/受限平台:仍可复用 UI 与前端契约注入逻辑,但 WebView 需要指向外部可访问的前端地址。
+///
+public sealed class NoopEmbeddedWebServerService : IEmbeddedWebServerService
+{
+ ///
+ /// 创建 。
+ ///
+ ///
+ /// 逻辑上的基础 URL。该实现不会实际监听端口,但会把该值暴露给调用方用于日志/显示或兼容逻辑。
+ ///
+ public NoopEmbeddedWebServerService(string baseUrl)
+ {
+ BaseUrl = baseUrl;
+ }
+
+ ///
+ public bool IsRunning => false;
+
+ ///
+ public string BaseUrl { get; }
+
+ ///
+ public Task StartAsync() => Task.CompletedTask;
+
+ ///
+ public Task StopAsync() => Task.CompletedTask;
+}
+
diff --git a/src/Hua.Todo.Avalonia/Services/Platforms/AndroidGlobalHotKeyService.cs b/src/Hua.Todo.Avalonia/Services/Platforms/AndroidGlobalHotKeyService.cs
new file mode 100644
index 0000000..db5cdbf
--- /dev/null
+++ b/src/Hua.Todo.Avalonia/Services/Platforms/AndroidGlobalHotKeyService.cs
@@ -0,0 +1,50 @@
+using System;
+
+namespace Hua.Todo.Avalonia.Services.Platforms;
+
+///
+/// Android 平台全局热键服务实现类
+/// 由于 Android 限制全局热键,使用通知快捷方式作为替代方案
+///
+public class AndroidGlobalHotKeyService : IGlobalHotKeyService
+{
+ private Action? _callback;
+
+ ///
+ /// Android 平台不支持全局热键
+ ///
+ public bool IsSupported => false;
+
+ ///
+ /// 注册通知快捷方式作为热键替代方案
+ ///
+ /// 修饰键(如 Alt、Control;多个键用逗号分隔)。
+ /// 主键(如 X、C)。
+ /// 热键触发时回调(不得阻塞,应自行切回 UI 线程)。
+ public void RegisterHotKey(string modifiers, string key, Action callback)
+ {
+ _callback = callback;
+ Console.WriteLine($"[AndroidGlobalHotKeyService] Registering notification shortcut as hotkey alternative");
+ }
+
+ ///
+ /// 注销快捷方式(空实现)
+ ///
+ public void UnregisterHotKey()
+ {
+ Console.WriteLine("[AndroidGlobalHotKeyService] Unregistering hotkey");
+ }
+
+ ///
+ /// 更新快捷方式配置
+ ///
+ /// 新的修饰键。
+ /// 新的主键。
+ public void UpdateHotKey(string modifiers, string key)
+ {
+ if (_callback != null)
+ {
+ RegisterHotKey(modifiers, key, _callback);
+ }
+ }
+}
diff --git a/src/Hua.Todo.Avalonia/Services/Platforms/LinuxGlobalHotKeyService.cs b/src/Hua.Todo.Avalonia/Services/Platforms/LinuxGlobalHotKeyService.cs
new file mode 100644
index 0000000..2594099
--- /dev/null
+++ b/src/Hua.Todo.Avalonia/Services/Platforms/LinuxGlobalHotKeyService.cs
@@ -0,0 +1,81 @@
+using System;
+
+namespace Hua.Todo.Avalonia.Services.Platforms;
+
+///
+/// Linux 平台全局热键服务实现类
+/// 提供基于 Linux 平台的全局热键支持
+///
+public class LinuxGlobalHotKeyService : IGlobalHotKeyService
+{
+ private Action? _callback;
+ private string? _modifiers;
+ private string? _key;
+
+ ///
+ /// Linux 平台支持全局热键
+ ///
+ public bool IsSupported => true;
+
+ ///
+ /// 注册全局热键
+ ///
+ /// 修饰键(如 Alt、Control;多个键用逗号分隔)。
+ /// 主键(如 X、C)。
+ /// 热键触发时回调(不得阻塞,应自行切回 UI 线程)。
+ public void RegisterHotKey(string modifiers, string key, Action callback)
+ {
+ try
+ {
+ _callback = callback;
+ _modifiers = modifiers;
+ _key = key;
+
+ // Linux 平台热键注册逻辑
+ // 这里可以使用如 libX11 或其他 Linux 热键库
+ // 由于 Avalonia 本身对 Linux 热键支持有限,这里提供基本实现
+ Console.WriteLine($"[LinuxGlobalHotKeyService] Registered hotkey: {modifiers}+{key}");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"[LinuxGlobalHotKeyService] Failed to register hotkey: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 注销已注册的热键
+ ///
+ public void UnregisterHotKey()
+ {
+ try
+ {
+ // Linux 平台热键注销逻辑
+ Console.WriteLine("[LinuxGlobalHotKeyService] Unregistered hotkey");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"[LinuxGlobalHotKeyService] Failed to unregister hotkey: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 更新热键配置
+ ///
+ /// 新的修饰键。
+ /// 新的主键。
+ public void UpdateHotKey(string modifiers, string key)
+ {
+ try
+ {
+ UnregisterHotKey();
+ if (_callback != null)
+ {
+ RegisterHotKey(modifiers, key, _callback);
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"[LinuxGlobalHotKeyService] Failed to update hotkey: {ex.Message}");
+ }
+ }
+}
diff --git a/src/Hua.Todo.Avalonia/Views/MainView.axaml b/src/Hua.Todo.Avalonia/Views/MainView.axaml
new file mode 100644
index 0000000..ed9cb58
--- /dev/null
+++ b/src/Hua.Todo.Avalonia/Views/MainView.axaml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Hua.Todo.Avalonia/Views/MainView.axaml.cs b/src/Hua.Todo.Avalonia/Views/MainView.axaml.cs
new file mode 100644
index 0000000..ffdf4ff
--- /dev/null
+++ b/src/Hua.Todo.Avalonia/Views/MainView.axaml.cs
@@ -0,0 +1,113 @@
+using Avalonia.Controls;
+using Avalonia.Layout;
+using Avalonia.Media;
+using Hua.Todo.Avalonia.Models;
+using Hua.Todo.Avalonia.Services;
+using System;
+
+namespace Hua.Todo.Avalonia.Views;
+
+///
+/// 应用主视图。
+/// 负责承载 WebView(前端 UI)并在导航完成后注入前端契约字段。
+///
+public partial class MainView : UserControl
+{
+ private readonly AppSettings _appSettings;
+ private readonly IEmbeddedWebServerService _webServer;
+
+ ///
+ /// 创建用于设计器预览的主视图实例。
+ ///
+ public MainView()
+ {
+ InitializeComponent();
+ _appSettings = new AppSettings();
+ _webServer = new NoopEmbeddedWebServerService(_appSettings.WebServer.HostUrl);
+ }
+
+ ///
+ /// 创建运行时主视图实例。
+ ///
+ /// 应用配置。
+ /// 嵌入式 WebServer。
+ public MainView(AppSettings appSettings, IEmbeddedWebServerService webServer)
+ {
+ InitializeComponent();
+ _appSettings = appSettings;
+ _webServer = webServer;
+
+ SetupWebView();
+ }
+
+ private void SetupWebView()
+ {
+ try
+ {
+ var webUrl = ResolveWebUrl();
+ MainWebView.Url = webUrl;
+
+ MainWebView.NavigationCompleted += async (_, _) =>
+ {
+ try
+ {
+ if (_webServer is not NoopEmbeddedWebServerService)
+ {
+ var apiBase = $"{_appSettings.WebServer.HostUrl.TrimEnd('/')}/api";
+ await MainWebView.ExecuteScriptAsync($"window.__API_BASE_URL__ = '{apiBase}';");
+ }
+
+ await MainWebView.ExecuteScriptAsync(@"
+ window.mauiInterop = {
+ onHotKeyConfigUpdated: null,
+ openHotKeySettings: function(config) {
+ const event = new CustomEvent('openHotKeySettings', { detail: config });
+ window.dispatchEvent(event);
+ },
+ updateHotKeyConfig: function(modifiers, key, isEnabled) {
+ const event = new CustomEvent('updateHotKeyConfig', {
+ detail: { modifiers, key, isEnabled }
+ });
+ window.dispatchEvent(event);
+ }
+ };
+
+ window.addEventListener('hotKeyConfigChanged', function(e) {
+ if (window.mauiInterop.onHotKeyConfigUpdated) {
+ window.mauiInterop.onHotKeyConfigUpdated(e.detail);
+ }
+ });
+ ");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"[MainView] WebView script injection failed: {ex.Message}");
+ }
+ };
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"[MainView] WebView initialization failed: {ex}");
+ Content = new TextBlock
+ {
+ Text = "WebView 初始化失败。请检查运行环境依赖(Windows 需要 WebView2 Runtime;Linux 需要 WebKitGTK)。",
+ HorizontalAlignment = HorizontalAlignment.Center,
+ VerticalAlignment = VerticalAlignment.Center,
+ TextWrapping = TextWrapping.Wrap
+ };
+ }
+ }
+
+ private Uri ResolveWebUrl()
+ {
+ if (OperatingSystem.IsAndroid())
+ {
+ return new Uri(_appSettings.WebServer.ForEndUrl);
+ }
+
+ return _appSettings.WebServer.IsUsingStatic
+ ? new Uri(_appSettings.WebServer.HostUrl)
+ : new Uri(_appSettings.WebServer.ForEndUrl);
+ }
+}
+
diff --git a/src/Hua.Todo.Avalonia/Views/MainWindow.axaml b/src/Hua.Todo.Avalonia/Views/MainWindow.axaml
index 57a9cab..af43ef9 100644
--- a/src/Hua.Todo.Avalonia/Views/MainWindow.axaml
+++ b/src/Hua.Todo.Avalonia/Views/MainWindow.axaml
@@ -6,7 +6,7 @@
mc:Ignorable="d" d:DesignWidth="450" d:DesignHeight="640"
x:Class="Hua.Todo.Avalonia.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
- Icon="/Assets/avalonia-logo.ico"
+ Icon="/Assets/icon.ico"
Width="450"
Height="640"
Title="待办事项"
@@ -15,7 +15,11 @@
-
-
+
+
+
+
diff --git a/src/Hua.Todo.Avalonia/Views/MainWindow.axaml.cs b/src/Hua.Todo.Avalonia/Views/MainWindow.axaml.cs
index 6ac4573..61612e9 100644
--- a/src/Hua.Todo.Avalonia/Views/MainWindow.axaml.cs
+++ b/src/Hua.Todo.Avalonia/Views/MainWindow.axaml.cs
@@ -1,15 +1,12 @@
using Avalonia.Controls;
-using Avalonia.Layout;
-using Avalonia.Media;
using Hua.Todo.Avalonia.Models;
using Hua.Todo.Avalonia.Services;
-using System;
namespace Hua.Todo.Avalonia.Views;
///
/// 应用主窗口。
-/// 负责承载 WebView(前端 UI)并在导航完成后注入前端契约字段。
+/// 负责承载 (前端 UI)。
///
public partial class MainWindow : Window
{
@@ -23,7 +20,8 @@ public partial class MainWindow : Window
{
InitializeComponent();
_appSettings = new AppSettings();
- _webServer = new EmbeddedWebServerService(_appSettings);
+ _webServer = new NoopEmbeddedWebServerService(_appSettings.WebServer.HostUrl);
+ Content = new MainView(_appSettings, _webServer);
}
///
@@ -36,67 +34,6 @@ public partial class MainWindow : Window
InitializeComponent();
_appSettings = appSettings;
_webServer = webServer;
-
- SetupWebView();
- }
-
- private void SetupWebView()
- {
- try
- {
- MainWebView.Url =
- _appSettings.WebServer.IsUsingStatic
- ? new Uri(_appSettings.WebServer.HostUrl)
- : new Uri(_appSettings.WebServer.ForEndUrl);
-
- MainWebView.NavigationCompleted += async (s, e) =>
- {
- try
- {
- if (_webServer.IsRunning)
- {
- var apiBase = $"{_webServer.BaseUrl.TrimEnd('/')}/api";
- await MainWebView.ExecuteScriptAsync($"window.__API_BASE_URL__ = '{apiBase}';");
- }
-
- await MainWebView.ExecuteScriptAsync(@"
- window.mauiInterop = {
- onHotKeyConfigUpdated: null,
- openHotKeySettings: function(config) {
- const event = new CustomEvent('openHotKeySettings', { detail: config });
- window.dispatchEvent(event);
- },
- updateHotKeyConfig: function(modifiers, key, isEnabled) {
- const event = new CustomEvent('updateHotKeyConfig', {
- detail: { modifiers, key, isEnabled }
- });
- window.dispatchEvent(event);
- }
- };
-
- window.addEventListener('hotKeyConfigChanged', function(e) {
- if (window.mauiInterop.onHotKeyConfigUpdated) {
- window.mauiInterop.onHotKeyConfigUpdated(e.detail);
- }
- });
- ");
- }
- catch (Exception ex)
- {
- Console.WriteLine($"[MainWindow] WebView script injection failed: {ex.Message}");
- }
- };
- }
- catch (Exception ex)
- {
- Console.WriteLine($"[MainWindow] WebView initialization failed: {ex}");
- Content = new TextBlock
- {
- Text = "WebView 初始化失败。请检查运行环境依赖(Windows 需要 WebView2 Runtime;Linux 需要 WebKitGTK)。",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- TextWrapping = TextWrapping.Wrap
- };
- }
+ Content = new MainView(_appSettings, _webServer);
}
}
diff --git a/src/Hua.Todo.Avalonia/appsettings.json b/src/Hua.Todo.Avalonia/appsettings.json
index c4333de..12d9bdc 100644
--- a/src/Hua.Todo.Avalonia/appsettings.json
+++ b/src/Hua.Todo.Avalonia/appsettings.json
@@ -1,10 +1,10 @@
{
"WebServer": {
"Port": 5057,
- "IsUsingStatic": false,
+ "IsUsingStatic": true,
"ConnectionString": "",
"HostUrl": "http://localhost:5057",
- "ForEndUrl": "http://localhost:5174"
+ "ForEndUrl": "http://localhost:5057"
},
"HotKey": {
"DefaultModifiers": "Alt",
diff --git a/src/Hua.Todo.Avalonia/setup.iss b/src/Hua.Todo.Avalonia/setup.iss
new file mode 100644
index 0000000..d7c6007
--- /dev/null
+++ b/src/Hua.Todo.Avalonia/setup.iss
@@ -0,0 +1,44 @@
+#define MyAppName "Hua.Todo.Avalonia"
+#define MyAppVersion "1.2.7"
+#define MyAppPublisher "ShaoHua"
+#define MyAppURL "https://git.we965.cn/Tools/Hua.Todo"
+#define MyAppExeName "Hua.Todo.Avalonia.exe"
+
+[Setup]
+; 1. 改用更快压缩(优先速度)
+Compression=zip/1
+
+; 注意: AppId 的值唯一标识此应用程序。不要在其他应用程序的安装程序中使用相同的 AppId 值。
+; (若要生成新的 GUID,请在 IDE 中单击“工具”|“生成 GUID”。)
+AppId={{A1B2C3D4-E5F6-4321-8765-FEDCBA987654}}
+AppName={#MyAppName}
+AppVersion={#MyAppVersion}
+AppPublisher={#MyAppPublisher}
+AppPublisherURL={#MyAppURL}
+AppSupportURL={#MyAppURL}
+AppUpdatesURL={#MyAppURL}
+DefaultDirName={autopf}\{#MyAppName}
+DisableProgramGroupPage=yes
+PrivilegesRequired=lowest
+OutputDir=Output
+OutputBaseFilename={#MyAppName}_Setup_v{#MyAppVersion}
+SetupIconFile=Assets\avalonia-logo.ico
+UninstallDisplayIcon={app}\avalonia-logo.ico
+SolidCompression=no
+WizardStyle=modern
+
+[Languages]
+Name: "chinesesimplified"; MessagesFile: "compiler:Languages\ChineseSimplified.isl"
+
+[Tasks]
+Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
+
+[Files]
+Source: "bin\Release\net10.0\win-x64\publish\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
+
+[Icons]
+Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\avalonia-logo.ico"
+Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon; IconFilename: "{app}\avalonia-logo.ico"
+
+[Run]
+Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
diff --git a/src/Hua.Todo.Avalonia/wwwroot/assets/index-C1b07_cD.js b/src/Hua.Todo.Avalonia/wwwroot/assets/index-C1b07_cD.js
new file mode 100644
index 0000000..e101ad8
--- /dev/null
+++ b/src/Hua.Todo.Avalonia/wwwroot/assets/index-C1b07_cD.js
@@ -0,0 +1,9 @@
+var e=Object.defineProperty,t=(t,n)=>{let r={};for(var i in t)e(r,i,{get:t[i],enumerable:!0});return n||e(r,Symbol.toStringTag,{value:`Module`}),r};(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();function n(e){let t=Object.create(null);for(let n of e.split(`,`))t[n]=1;return e=>e in t}var r={},i=[],a=()=>{},o=()=>!1,s=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),c=e=>e.startsWith(`onUpdate:`),l=Object.assign,u=(e,t)=>{let n=e.indexOf(t);n>-1&&e.splice(n,1)},d=Object.prototype.hasOwnProperty,f=(e,t)=>d.call(e,t),p=Array.isArray,m=e=>C(e)===`[object Map]`,h=e=>C(e)===`[object Set]`,g=e=>C(e)===`[object Date]`,_=e=>typeof e==`function`,v=e=>typeof e==`string`,y=e=>typeof e==`symbol`,b=e=>typeof e==`object`&&!!e,x=e=>(b(e)||_(e))&&_(e.then)&&_(e.catch),S=Object.prototype.toString,C=e=>S.call(e),w=e=>C(e).slice(8,-1),T=e=>C(e)===`[object Object]`,ee=e=>v(e)&&e!==`NaN`&&e[0]!==`-`&&``+parseInt(e,10)===e,te=n(`,key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted`),E=e=>{let t=Object.create(null);return(n=>t[n]||(t[n]=e(n)))},ne=/-\w/g,D=E(e=>e.replace(ne,e=>e.slice(1).toUpperCase())),re=/\B([A-Z])/g,ie=E(e=>e.replace(re,`-$1`).toLowerCase()),ae=E(e=>e.charAt(0).toUpperCase()+e.slice(1)),oe=E(e=>e?`on${ae(e)}`:``),O=(e,t)=>!Object.is(e,t),se=(e,...t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:r,value:n})},le=e=>{let t=parseFloat(e);return isNaN(t)?e:t},ue=e=>{let t=v(e)?Number(e):NaN;return isNaN(t)?e:t},de,fe=()=>de||=typeof globalThis<`u`?globalThis:typeof self<`u`?self:typeof window<`u`?window:typeof global<`u`?global:{};function pe(e){if(p(e)){let t={};for(let n=0;n{if(e){let n=e.split(he);n.length>1&&(t[n[0].trim()]=n[1].trim())}}),t}function ve(e){let t=``;if(v(e))t=e;else if(p(e))for(let n=0;nCe(e,t))}var Te=e=>!!(e&&e.__v_isRef===!0),k=e=>v(e)?e:e==null?``:p(e)||b(e)&&(e.toString===S||!_(e.toString))?Te(e)?k(e.value):JSON.stringify(e,Ee,2):String(e),Ee=(e,t)=>Te(t)?Ee(e,t.value):m(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((e,[t,n],r)=>(e[De(t,r)+` =>`]=n,e),{})}:h(t)?{[`Set(${t.size})`]:[...t.values()].map(e=>De(e))}:y(t)?De(t):b(t)&&!p(t)&&!T(t)?String(t):t,De=(e,t=``)=>y(e)?`Symbol(${e.description??t})`:e,Oe,ke=class{constructor(e=!1){this.detached=e,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this.__v_skip=!0,this.parent=Oe,!e&&Oe&&(this.index=(Oe.scopes||=[]).push(this)-1)}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let e,t;if(this.scopes)for(e=0,t=this.scopes.length;e0&&--this._on===0&&(Oe=this.prevScope,this.prevScope=void 0)}stop(e){if(this._active){this._active=!1;let t,n;for(t=0,n=this.effects.length;t0)return;if(Fe){let e=Fe;for(Fe=void 0;e;){let t=e.next;e.next=void 0,e.flags&=-9,e=t}}let e;for(;Pe;){let t=Pe;for(Pe=void 0;t;){let n=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(t){e||=t}t=n}}if(e)throw e}function ze(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function Be(e){let t,n=e.depsTail,r=n;for(;r;){let e=r.prevDep;r.version===-1?(r===n&&(n=e),Ue(r),We(r)):t=r,r.dep.activeLink=r.prevActiveLink,r.prevActiveLink=void 0,r=e}e.deps=t,e.depsTail=n}function Ve(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(He(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function He(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===Xe)||(e.globalVersion=Xe,!e.isSSR&&e.flags&128&&(!e.deps&&!e._dirty||!Ve(e))))return;e.flags|=2;let t=e.dep,n=A,r=Ge;A=e,Ge=!0;try{ze(e);let n=e.fn(e._value);(t.version===0||O(n,e._value))&&(e.flags|=128,e._value=n,t.version++)}catch(e){throw t.version++,e}finally{A=n,Ge=r,Be(e),e.flags&=-3}}function Ue(e,t=!1){let{dep:n,prevSub:r,nextSub:i}=e;if(r&&(r.nextSub=i,e.prevSub=void 0),i&&(i.prevSub=r,e.nextSub=void 0),n.subs===e&&(n.subs=r,!r&&n.computed)){n.computed.flags&=-5;for(let e=n.computed.deps;e;e=e.nextDep)Ue(e,!0)}!t&&!--n.sc&&n.map&&n.map.delete(n.key)}function We(e){let{prevDep:t,nextDep:n}=e;t&&(t.nextDep=n,e.prevDep=void 0),n&&(n.prevDep=t,e.nextDep=void 0)}var Ge=!0,Ke=[];function qe(){Ke.push(Ge),Ge=!1}function Je(){let e=Ke.pop();Ge=e===void 0?!0:e}function Ye(e){let{cleanup:t}=e;if(e.cleanup=void 0,t){let e=A;A=void 0;try{t()}finally{A=e}}}var Xe=0,Ze=class{constructor(e,t){this.sub=e,this.dep=t,this.version=t.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}},Qe=class{constructor(e){this.computed=e,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(e){if(!A||!Ge||A===this.computed)return;let t=this.activeLink;if(t===void 0||t.sub!==A)t=this.activeLink=new Ze(A,this),A.deps?(t.prevDep=A.depsTail,A.depsTail.nextDep=t,A.depsTail=t):A.deps=A.depsTail=t,$e(t);else if(t.version===-1&&(t.version=this.version,t.nextDep)){let e=t.nextDep;e.prevDep=t.prevDep,t.prevDep&&(t.prevDep.nextDep=e),t.prevDep=A.depsTail,t.nextDep=void 0,A.depsTail.nextDep=t,A.depsTail=t,A.deps===t&&(A.deps=e)}return t}trigger(e){this.version++,Xe++,this.notify(e)}notify(e){Le();try{for(let e=this.subs;e;e=e.prevSub)e.sub.notify()&&e.sub.dep.notify()}finally{Re()}}};function $e(e){if(e.dep.sc++,e.sub.flags&4){let t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let e=t.deps;e;e=e.nextDep)$e(e)}let n=e.dep.subs;n!==e&&(e.prevSub=n,n&&(n.nextSub=e)),e.dep.subs=e}}var et=new WeakMap,tt=Symbol(``),nt=Symbol(``),rt=Symbol(``);function j(e,t,n){if(Ge&&A){let t=et.get(e);t||et.set(e,t=new Map);let r=t.get(n);r||(t.set(n,r=new Qe),r.map=t,r.key=n),r.track()}}function it(e,t,n,r,i,a){let o=et.get(e);if(!o){Xe++;return}let s=e=>{e&&e.trigger()};if(Le(),t===`clear`)o.forEach(s);else{let i=p(e),a=i&&ee(n);if(i&&n===`length`){let e=Number(r);o.forEach((t,n)=>{(n===`length`||n===rt||!y(n)&&n>=e)&&s(t)})}else switch((n!==void 0||o.has(void 0))&&s(o.get(n)),a&&s(o.get(rt)),t){case`add`:i?a&&s(o.get(`length`)):(s(o.get(tt)),m(e)&&s(o.get(nt)));break;case`delete`:i||(s(o.get(tt)),m(e)&&s(o.get(nt)));break;case`set`:m(e)&&s(o.get(tt));break}}Re()}function at(e){let t=M(e);return t===e?t:(j(t,`iterate`,rt),Gt(e)?t:t.map(Jt))}function ot(e){return j(e=M(e),`iterate`,rt),e}function st(e,t){return Wt(e)?Ut(e)?Yt(Jt(t)):Yt(t):Jt(t)}var ct={__proto__:null,[Symbol.iterator](){return lt(this,Symbol.iterator,e=>st(this,e))},concat(...e){return at(this).concat(...e.map(e=>p(e)?at(e):e))},entries(){return lt(this,`entries`,e=>(e[1]=st(this,e[1]),e))},every(e,t){return dt(this,`every`,e,t,void 0,arguments)},filter(e,t){return dt(this,`filter`,e,t,e=>e.map(e=>st(this,e)),arguments)},find(e,t){return dt(this,`find`,e,t,e=>st(this,e),arguments)},findIndex(e,t){return dt(this,`findIndex`,e,t,void 0,arguments)},findLast(e,t){return dt(this,`findLast`,e,t,e=>st(this,e),arguments)},findLastIndex(e,t){return dt(this,`findLastIndex`,e,t,void 0,arguments)},forEach(e,t){return dt(this,`forEach`,e,t,void 0,arguments)},includes(...e){return pt(this,`includes`,e)},indexOf(...e){return pt(this,`indexOf`,e)},join(e){return at(this).join(e)},lastIndexOf(...e){return pt(this,`lastIndexOf`,e)},map(e,t){return dt(this,`map`,e,t,void 0,arguments)},pop(){return mt(this,`pop`)},push(...e){return mt(this,`push`,e)},reduce(e,...t){return ft(this,`reduce`,e,t)},reduceRight(e,...t){return ft(this,`reduceRight`,e,t)},shift(){return mt(this,`shift`)},some(e,t){return dt(this,`some`,e,t,void 0,arguments)},splice(...e){return mt(this,`splice`,e)},toReversed(){return at(this).toReversed()},toSorted(e){return at(this).toSorted(e)},toSpliced(...e){return at(this).toSpliced(...e)},unshift(...e){return mt(this,`unshift`,e)},values(){return lt(this,`values`,e=>st(this,e))}};function lt(e,t,n){let r=ot(e),i=r[t]();return r!==e&&!Gt(e)&&(i._next=i.next,i.next=()=>{let e=i._next();return e.done||(e.value=n(e.value)),e}),i}var ut=Array.prototype;function dt(e,t,n,r,i,a){let o=ot(e),s=o!==e&&!Gt(e),c=o[t];if(c!==ut[t]){let t=c.apply(e,a);return s?Jt(t):t}let l=n;o!==e&&(s?l=function(t,r){return n.call(this,st(e,t),r,e)}:n.length>2&&(l=function(t,r){return n.call(this,t,r,e)}));let u=c.call(o,l,r);return s&&i?i(u):u}function ft(e,t,n,r){let i=ot(e),a=i!==e&&!Gt(e),o=n,s=!1;i!==e&&(a?(s=r.length===0,o=function(t,r,i){return s&&(s=!1,t=st(e,t)),n.call(this,t,st(e,r),i,e)}):n.length>3&&(o=function(t,r,i){return n.call(this,t,r,i,e)}));let c=i[t](o,...r);return s?st(e,c):c}function pt(e,t,n){let r=M(e);j(r,`iterate`,rt);let i=r[t](...n);return(i===-1||i===!1)&&Kt(n[0])?(n[0]=M(n[0]),r[t](...n)):i}function mt(e,t,n=[]){qe(),Le();let r=M(e)[t].apply(e,n);return Re(),Je(),r}var ht=n(`__proto__,__v_isRef,__isVue`),gt=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!==`arguments`&&e!==`caller`).map(e=>Symbol[e]).filter(y));function _t(e){y(e)||(e=String(e));let t=M(this);return j(t,`has`,e),t.hasOwnProperty(e)}var vt=class{constructor(e=!1,t=!1){this._isReadonly=e,this._isShallow=t}get(e,t,n){if(t===`__v_skip`)return e.__v_skip;let r=this._isReadonly,i=this._isShallow;if(t===`__v_isReactive`)return!r;if(t===`__v_isReadonly`)return r;if(t===`__v_isShallow`)return i;if(t===`__v_raw`)return n===(r?i?It:Ft:i?Pt:Nt).get(e)||Object.getPrototypeOf(e)===Object.getPrototypeOf(n)?e:void 0;let a=p(e);if(!r){let e;if(a&&(e=ct[t]))return e;if(t===`hasOwnProperty`)return _t}let o=Reflect.get(e,t,N(e)?e:n);if((y(t)?gt.has(t):ht(t))||(r||j(e,`get`,t),i))return o;if(N(o)){let e=a&&ee(t)?o:o.value;return r&&b(e)?Vt(e):e}return b(o)?r?Vt(o):zt(o):o}},yt=class extends vt{constructor(e=!1){super(!1,e)}set(e,t,n,r){let i=e[t],a=p(e)&&ee(t);if(!this._isShallow){let e=Wt(i);if(!Gt(n)&&!Wt(n)&&(i=M(i),n=M(n)),!a&&N(i)&&!N(n))return e||(i.value=n),!0}let o=a?Number(t)e,Tt=e=>Reflect.getPrototypeOf(e);function Et(e,t,n){return function(...r){let i=this.__v_raw,a=M(i),o=m(a),s=e===`entries`||e===Symbol.iterator&&o,c=e===`keys`&&o,u=i[e](...r),d=n?wt:t?Yt:Jt;return!t&&j(a,`iterate`,c?nt:tt),l(Object.create(u),{next(){let{value:e,done:t}=u.next();return t?{value:e,done:t}:{value:s?[d(e[0]),d(e[1])]:d(e),done:t}}})}}function Dt(e){return function(...t){return e===`delete`?!1:e===`clear`?void 0:this}}function Ot(e,t){let n={get(n){let r=this.__v_raw,i=M(r),a=M(n);e||(O(n,a)&&j(i,`get`,n),j(i,`get`,a));let{has:o}=Tt(i),s=t?wt:e?Yt:Jt;if(o.call(i,n))return s(r.get(n));if(o.call(i,a))return s(r.get(a));r!==i&&r.get(n)},get size(){let t=this.__v_raw;return!e&&j(M(t),`iterate`,tt),t.size},has(t){let n=this.__v_raw,r=M(n),i=M(t);return e||(O(t,i)&&j(r,`has`,t),j(r,`has`,i)),t===i?n.has(t):n.has(t)||n.has(i)},forEach(n,r){let i=this,a=i.__v_raw,o=M(a),s=t?wt:e?Yt:Jt;return!e&&j(o,`iterate`,tt),a.forEach((e,t)=>n.call(r,s(e),s(t),i))}};return l(n,e?{add:Dt(`add`),set:Dt(`set`),delete:Dt(`delete`),clear:Dt(`clear`)}:{add(e){let n=M(this),r=Tt(n),i=M(e),a=!t&&!Gt(e)&&!Wt(e)?i:e;return r.has.call(n,a)||O(e,a)&&r.has.call(n,e)||O(i,a)&&r.has.call(n,i)||(n.add(a),it(n,`add`,a,a)),this},set(e,n){!t&&!Gt(n)&&!Wt(n)&&(n=M(n));let r=M(this),{has:i,get:a}=Tt(r),o=i.call(r,e);o||=(e=M(e),i.call(r,e));let s=a.call(r,e);return r.set(e,n),o?O(n,s)&&it(r,`set`,e,n,s):it(r,`add`,e,n),this},delete(e){let t=M(this),{has:n,get:r}=Tt(t),i=n.call(t,e);i||=(e=M(e),n.call(t,e));let a=r?r.call(t,e):void 0,o=t.delete(e);return i&&it(t,`delete`,e,void 0,a),o},clear(){let e=M(this),t=e.size!==0,n=e.clear();return t&&it(e,`clear`,void 0,void 0,void 0),n}}),[`keys`,`values`,`entries`,Symbol.iterator].forEach(r=>{n[r]=Et(r,e,t)}),n}function kt(e,t){let n=Ot(e,t);return(t,r,i)=>r===`__v_isReactive`?!e:r===`__v_isReadonly`?e:r===`__v_raw`?t:Reflect.get(f(n,r)&&r in t?n:t,r,i)}var At={get:kt(!1,!1)},jt={get:kt(!1,!0)},Mt={get:kt(!0,!1)},Nt=new WeakMap,Pt=new WeakMap,Ft=new WeakMap,It=new WeakMap;function Lt(e){switch(e){case`Object`:case`Array`:return 1;case`Map`:case`Set`:case`WeakMap`:case`WeakSet`:return 2;default:return 0}}function Rt(e){return e.__v_skip||!Object.isExtensible(e)?0:Lt(w(e))}function zt(e){return Wt(e)?e:Ht(e,!1,xt,At,Nt)}function Bt(e){return Ht(e,!1,Ct,jt,Pt)}function Vt(e){return Ht(e,!0,St,Mt,Ft)}function Ht(e,t,n,r,i){if(!b(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;let a=Rt(e);if(a===0)return e;let o=i.get(e);if(o)return o;let s=new Proxy(e,a===2?r:n);return i.set(e,s),s}function Ut(e){return Wt(e)?Ut(e.__v_raw):!!(e&&e.__v_isReactive)}function Wt(e){return!!(e&&e.__v_isReadonly)}function Gt(e){return!!(e&&e.__v_isShallow)}function Kt(e){return e?!!e.__v_raw:!1}function M(e){let t=e&&e.__v_raw;return t?M(t):e}function qt(e){return!f(e,`__v_skip`)&&Object.isExtensible(e)&&ce(e,`__v_skip`,!0),e}var Jt=e=>b(e)?zt(e):e,Yt=e=>b(e)?Vt(e):e;function N(e){return e?e.__v_isRef===!0:!1}function P(e){return Xt(e,!1)}function Xt(e,t){return N(e)?e:new Zt(e,t)}var Zt=class{constructor(e,t){this.dep=new Qe,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=t?e:M(e),this._value=t?e:Jt(e),this.__v_isShallow=t}get value(){return this.dep.track(),this._value}set value(e){let t=this._rawValue,n=this.__v_isShallow||Gt(e)||Wt(e);e=n?e:M(e),O(e,t)&&(this._rawValue=e,this._value=n?e:Jt(e),this.dep.trigger())}};function Qt(e){return N(e)?e.value:e}var $t={get:(e,t,n)=>t===`__v_raw`?e:Qt(Reflect.get(e,t,n)),set:(e,t,n,r)=>{let i=e[t];return N(i)&&!N(n)?(i.value=n,!0):Reflect.set(e,t,n,r)}};function en(e){return Ut(e)?e:new Proxy(e,$t)}var tn=class{constructor(e,t,n){this.fn=e,this.setter=t,this._value=void 0,this.dep=new Qe(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=Xe-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!t,this.isSSR=n}notify(){if(this.flags|=16,!(this.flags&8)&&A!==this)return Ie(this,!0),!0}get value(){let e=this.dep.track();return He(this),e&&(e.version=this.dep.version),this._value}set value(e){this.setter&&this.setter(e)}};function nn(e,t,n=!1){let r,i;return _(e)?r=e:(r=e.get,i=e.set),new tn(r,i,n)}var rn={},an=new WeakMap,on=void 0;function sn(e,t=!1,n=on){if(n){let t=an.get(n);t||an.set(n,t=[]),t.push(e)}}function cn(e,t,n=r){let{immediate:i,deep:o,once:s,scheduler:c,augmentJob:l,call:d}=n,f=e=>o?e:Gt(e)||o===!1||o===0?ln(e,1):ln(e),m,h,g,v,y=!1,b=!1;if(N(e)?(h=()=>e.value,y=Gt(e)):Ut(e)?(h=()=>f(e),y=!0):p(e)?(b=!0,y=e.some(e=>Ut(e)||Gt(e)),h=()=>e.map(e=>{if(N(e))return e.value;if(Ut(e))return f(e);if(_(e))return d?d(e,2):e()})):h=_(e)?t?d?()=>d(e,2):e:()=>{if(g){qe();try{g()}finally{Je()}}let t=on;on=m;try{return d?d(e,3,[v]):e(v)}finally{on=t}}:a,t&&o){let e=h,t=o===!0?1/0:o;h=()=>ln(e(),t)}let x=Ae(),S=()=>{m.stop(),x&&x.active&&u(x.effects,m)};if(s&&t){let e=t;t=(...t)=>{e(...t),S()}}let C=b?Array(e.length).fill(rn):rn,w=e=>{if(!(!(m.flags&1)||!m.dirty&&!e))if(t){let e=m.run();if(o||y||(b?e.some((e,t)=>O(e,C[t])):O(e,C))){g&&g();let n=on;on=m;try{let n=[e,C===rn?void 0:b&&C[0]===rn?[]:C,v];C=e,d?d(t,3,n):t(...n)}finally{on=n}}}else m.run()};return l&&l(w),m=new Me(h),m.scheduler=c?()=>c(w,!1):w,v=e=>sn(e,!1,m),g=m.onStop=()=>{let e=an.get(m);if(e){if(d)d(e,4);else for(let t of e)t();an.delete(m)}},t?i?w(!0):C=m.run():c?c(w.bind(null,!0),!0):m.run(),S.pause=m.pause.bind(m),S.resume=m.resume.bind(m),S.stop=S,S}function ln(e,t=1/0,n){if(t<=0||!b(e)||e.__v_skip||(n||=new Map,(n.get(e)||0)>=t))return e;if(n.set(e,t),t--,N(e))ln(e.value,t,n);else if(p(e))for(let r=0;r{ln(e,t,n)});else if(T(e)){for(let r in e)ln(e[r],t,n);for(let r of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,r)&&ln(e[r],t,n)}return e}function un(e,t,n,r){try{return r?e(...r):e()}catch(e){fn(e,t,n)}}function dn(e,t,n,r){if(_(e)){let i=un(e,t,n,r);return i&&x(i)&&i.catch(e=>{fn(e,t,n)}),i}if(p(e)){let i=[];for(let a=0;a>>1,i=F[r],a=Dn(i);a=Dn(n)?F.push(e):F.splice(xn(t),0,e),e.flags|=1,Cn()}}function Cn(){yn||=vn.then(On)}function wn(e){p(e)?hn.push(...e):gn&&e.id===-1?gn.splice(_n+1,0,e):e.flags&1||(hn.push(e),e.flags|=1),Cn()}function Tn(e,t,n=mn+1){for(;nDn(e)-Dn(t));if(hn.length=0,gn){gn.push(...e);return}for(gn=e,_n=0;_ne.id==null?e.flags&2?-1:1/0:e.id;function On(e){try{for(mn=0;mn{r._d&&$i(-1);let i=jn(t),a;try{a=e(...n)}finally{jn(i),r._d&&$i(1)}return a};return r._n=!0,r._c=!0,r._d=!0,r}function I(e,t){if(kn===null)return e;let n=Pa(kn),i=e.dirs||=[];for(let e=0;e1)return n&&_(t)?t.call(r&&r.proxy):t}}var In=Symbol.for(`v-scx`),Ln=()=>Fn(In);function Rn(e,t,n){return zn(e,t,n)}function zn(e,t,n=r){let{immediate:i,deep:o,flush:s,once:c}=n,u=l({},n),d=t&&i||!t&&s!==`post`,f;if(Ta){if(s===`sync`){let e=Ln();f=e.__watcherHandles||=[]}else if(!d){let e=()=>{};return e.stop=a,e.resume=a,e.pause=a,e}}let p=G;u.call=(e,t,n)=>dn(e,p,t,n);let m=!1;s===`post`?u.scheduler=e=>{R(e,p&&p.suspense)}:s!==`sync`&&(m=!0,u.scheduler=(e,t)=>{t?e():Sn(e)}),u.augmentJob=e=>{t&&(e.flags|=4),m&&(e.flags|=2,p&&(e.id=p.uid,e.i=p))};let h=cn(e,t,u);return Ta&&(f?f.push(h):d&&h()),h}function Bn(e,t,n){let r=this.proxy,i=v(e)?e.includes(`.`)?Vn(r,e):()=>r[e]:e.bind(r,r),a;_(t)?a=t:(a=t.handler,n=t);let o=Sa(this),s=zn(i,a.bind(r),n);return o(),s}function Vn(e,t){let n=t.split(`.`);return()=>{let t=e;for(let e=0;ee.__isTeleport,Wn=Symbol(`_leaveCb`),Gn=Symbol(`_enterCb`);function Kn(){let e={isMounted:!1,isLeaving:!1,isUnmounting:!1,leavingVNodes:new Map};return br(()=>{e.isMounted=!0}),Cr(()=>{e.isUnmounting=!0}),e}var qn=[Function,Array],Jn={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:qn,onEnter:qn,onAfterEnter:qn,onEnterCancelled:qn,onBeforeLeave:qn,onLeave:qn,onAfterLeave:qn,onLeaveCancelled:qn,onBeforeAppear:qn,onAppear:qn,onAfterAppear:qn,onAppearCancelled:qn},Yn=e=>{let t=e.subTree;return t.component?Yn(t.component):t},Xn={name:`BaseTransition`,props:Jn,setup(e,{slots:t}){let n=ya(),r=Kn();return()=>{let i=t.default&&ir(t.default(),!0);if(!i||!i.length)return;let a=Zn(i),o=M(e),{mode:s}=o;if(r.isLeaving)return tr(a);let c=nr(a);if(!c)return tr(a);let l=er(c,o,r,n,e=>l=e);c.type!==z&&rr(c,l);let u=n.subTree&&nr(n.subTree);if(u&&u.type!==z&&!ra(u,c)&&Yn(n).type!==z){let e=er(u,o,r,n);if(rr(u,e),s===`out-in`&&c.type!==z)return r.isLeaving=!0,e.afterLeave=()=>{r.isLeaving=!1,n.job.flags&8||n.update(),delete e.afterLeave,u=void 0},tr(a);s===`in-out`&&c.type!==z?e.delayLeave=(e,t,n)=>{let i=$n(r,u);i[String(u.key)]=u,e[Wn]=()=>{t(),e[Wn]=void 0,delete l.delayedLeave,u=void 0},l.delayedLeave=()=>{n(),delete l.delayedLeave,u=void 0}}:u=void 0}else u&&=void 0;return a}}};function Zn(e){let t=e[0];if(e.length>1){for(let n of e)if(n.type!==z){t=n;break}}return t}var Qn=Xn;function $n(e,t){let{leavingVNodes:n}=e,r=n.get(t.type);return r||(r=Object.create(null),n.set(t.type,r)),r}function er(e,t,n,r,i){let{appear:a,mode:o,persisted:s=!1,onBeforeEnter:c,onEnter:l,onAfterEnter:u,onEnterCancelled:d,onBeforeLeave:f,onLeave:m,onAfterLeave:h,onLeaveCancelled:g,onBeforeAppear:_,onAppear:v,onAfterAppear:y,onAppearCancelled:b}=t,x=String(e.key),S=$n(n,e),C=(e,t)=>{e&&dn(e,r,9,t)},w=(e,t)=>{let n=t[1];C(e,t),p(e)?e.every(e=>e.length<=1)&&n():e.length<=1&&n()},T={mode:o,persisted:s,beforeEnter(t){let r=c;if(!n.isMounted)if(a)r=_||c;else return;t[Wn]&&t[Wn](!0);let i=S[x];i&&ra(e,i)&&i.el[Wn]&&i.el[Wn](),C(r,[t])},enter(t){if(S[x]===e)return;let r=l,i=u,o=d;if(!n.isMounted)if(a)r=v||l,i=y||u,o=b||d;else return;let s=!1;t[Gn]=e=>{s||(s=!0,C(e?o:i,[t]),T.delayedLeave&&T.delayedLeave(),t[Gn]=void 0)};let c=t[Gn].bind(null,!1);r?w(r,[t,c]):c()},leave(t,r){let i=String(e.key);if(t[Gn]&&t[Gn](!0),n.isUnmounting)return r();C(f,[t]);let a=!1;t[Wn]=n=>{a||(a=!0,r(),C(n?g:h,[t]),t[Wn]=void 0,S[i]===e&&delete S[i])};let o=t[Wn].bind(null,!1);S[i]=e,m?w(m,[t,o]):o()},clone(e){let a=er(e,t,n,r,i);return i&&i(a),a}};return T}function tr(e){if(fr(e))return e=ca(e),e.children=null,e}function nr(e){if(!fr(e))return Un(e.type)&&e.children?Zn(e.children):e;if(e.component)return e.component.subTree;let{shapeFlag:t,children:n}=e;if(n){if(t&16)return n[0];if(t&32&&_(n.default))return n.default()}}function rr(e,t){e.shapeFlag&6&&e.component?(e.transition=t,rr(e.component.subTree,t)):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function ir(e,t=!1,n){let r=[],i=0;for(let a=0;a1)for(let e=0;elr(e,t&&(p(t)?t[r]:t),n,i,a));return}if(dr(i)&&!a){i.shapeFlag&512&&i.type.__asyncResolved&&i.component.subTree.component&&lr(e,t,n,i.component.subTree);return}let s=i.shapeFlag&4?Pa(i.component):i.el,c=a?null:s,{i:l,r:d}=e,m=t&&t.r,h=l.refs===r?l.refs={}:l.refs,g=l.setupState,y=M(g),b=g===r?o:e=>sr(h,e)?!1:f(y,e),x=(e,t)=>!(t&&sr(h,t));if(m!=null&&m!==d){if(ur(t),v(m))h[m]=null,b(m)&&(g[m]=null);else if(N(m)){let e=t;x(m,e.k)&&(m.value=null),e.k&&(h[e.k]=null)}}if(_(d))un(d,l,12,[c,h]);else{let t=v(d),r=N(d);if(t||r){let i=()=>{if(e.f){let n=t?b(d)?g[d]:h[d]:x(d)||!e.k?d.value:h[e.k];if(a)p(n)&&u(n,s);else if(p(n))n.includes(s)||n.push(s);else if(t)h[d]=[s],b(d)&&(g[d]=h[d]);else{let t=[s];x(d,e.k)&&(d.value=t),e.k&&(h[e.k]=t)}}else t?(h[d]=c,b(d)&&(g[d]=c)):r&&(x(d,e.k)&&(d.value=c),e.k&&(h[e.k]=c))};if(c){let t=()=>{i(),cr.delete(e)};t.id=-1,cr.set(e,t),R(t,n)}else ur(e),i()}}}function ur(e){let t=cr.get(e);t&&(t.flags|=8,cr.delete(e))}fe().requestIdleCallback,fe().cancelIdleCallback;var dr=e=>!!e.type.__asyncLoader,fr=e=>e.type.__isKeepAlive;function pr(e,t){hr(e,`a`,t)}function mr(e,t){hr(e,`da`,t)}function hr(e,t,n=G){let r=e.__wdc||=()=>{let t=n;for(;t;){if(t.isDeactivated)return;t=t.parent}return e()};if(_r(t,r,n),n){let e=n.parent;for(;e&&e.parent;)fr(e.parent.vnode)&&gr(r,t,n,e),e=e.parent}}function gr(e,t,n,r){let i=_r(t,e,r,!0);wr(()=>{u(r[t],i)},n)}function _r(e,t,n=G,r=!1){if(n){let i=n[e]||(n[e]=[]),a=t.__weh||=(...r)=>{qe();let i=Sa(n),a=dn(t,n,e,r);return i(),Je(),a};return r?i.unshift(a):i.push(a),a}}var vr=e=>(t,n=G)=>{(!Ta||e===`sp`)&&_r(e,(...e)=>t(...e),n)},yr=vr(`bm`),br=vr(`m`),xr=vr(`bu`),Sr=vr(`u`),Cr=vr(`bum`),wr=vr(`um`),Tr=vr(`sp`),Er=vr(`rtg`),Dr=vr(`rtc`);function Or(e,t=G){_r(`ec`,e,t)}var kr=`components`;function Ar(e,t){return Mr(kr,e,!0,t)||e}var jr=Symbol.for(`v-ndc`);function Mr(e,t,n=!0,r=!1){let i=kn||G;if(i){let n=i.type;if(e===kr){let e=Fa(n,!1);if(e&&(e===t||e===D(t)||e===ae(D(t))))return n}let a=Nr(i[e]||n[e],t)||Nr(i.appContext[e],t);return!a&&r?n:a}}function Nr(e,t){return e&&(e[t]||e[D(t)]||e[ae(D(t))])}function Pr(e,t,n,r){let i,a=n&&n[r],o=p(e);if(o||v(e)){let n=o&&Ut(e),r=!1,s=!1;n&&(r=!Gt(e),s=Wt(e),e=ot(e)),i=Array(e.length);for(let n=0,o=e.length;nt(e,n,void 0,a&&a[n]));else{let n=Object.keys(e);i=Array(n.length);for(let r=0,o=n.length;re?wa(e)?Pa(e):Fr(e.parent):null,Ir=l(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Fr(e.parent),$root:e=>Fr(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>Gr(e),$forceUpdate:e=>e.f||=()=>{Sn(e.update)},$nextTick:e=>e.n||=bn.bind(e.proxy),$watch:e=>Bn.bind(e)}),Lr=(e,t)=>e!==r&&!e.__isScriptSetup&&f(e,t),Rr={get({_:e},t){if(t===`__v_skip`)return!0;let{ctx:n,setupState:i,data:a,props:o,accessCache:s,type:c,appContext:l}=e;if(t[0]!==`$`){let e=s[t];if(e!==void 0)switch(e){case 1:return i[t];case 2:return a[t];case 4:return n[t];case 3:return o[t]}else if(Lr(i,t))return s[t]=1,i[t];else if(a!==r&&f(a,t))return s[t]=2,a[t];else if(f(o,t))return s[t]=3,o[t];else if(n!==r&&f(n,t))return s[t]=4,n[t];else Br&&(s[t]=0)}let u=Ir[t],d,p;if(u)return t===`$attrs`&&j(e.attrs,`get`,``),u(e);if((d=c.__cssModules)&&(d=d[t]))return d;if(n!==r&&f(n,t))return s[t]=4,n[t];if(p=l.config.globalProperties,f(p,t))return p[t]},set({_:e},t,n){let{data:i,setupState:a,ctx:o}=e;return Lr(a,t)?(a[t]=n,!0):i!==r&&f(i,t)?(i[t]=n,!0):f(e.props,t)||t[0]===`$`&&t.slice(1)in e?!1:(o[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:i,appContext:a,props:o,type:s}},c){let l;return!!(n[c]||e!==r&&c[0]!==`$`&&f(e,c)||Lr(t,c)||f(o,c)||f(i,c)||f(Ir,c)||f(a.config.globalProperties,c)||(l=s.__cssModules)&&l[c])},defineProperty(e,t,n){return n.get==null?f(n,`value`)&&this.set(e,t,n.value,null):e._.accessCache[t]=0,Reflect.defineProperty(e,t,n)}};function zr(e){return p(e)?e.reduce((e,t)=>(e[t]=null,e),{}):e}var Br=!0;function Vr(e){let t=Gr(e),n=e.proxy,r=e.ctx;Br=!1,t.beforeCreate&&Ur(t.beforeCreate,e,`bc`);let{data:i,computed:o,methods:s,watch:c,provide:l,inject:u,created:d,beforeMount:f,mounted:m,beforeUpdate:h,updated:g,activated:v,deactivated:y,beforeDestroy:x,beforeUnmount:S,destroyed:C,unmounted:w,render:T,renderTracked:ee,renderTriggered:te,errorCaptured:E,serverPrefetch:ne,expose:D,inheritAttrs:re,components:ie,directives:ae,filters:oe}=t;if(u&&Hr(u,r,null),s)for(let e in s){let t=s[e];_(t)&&(r[e]=t.bind(n))}if(i){let t=i.call(n,n);b(t)&&(e.data=zt(t))}if(Br=!0,o)for(let e in o){let t=o[e],i=La({get:_(t)?t.bind(n,n):_(t.get)?t.get.bind(n,n):a,set:!_(t)&&_(t.set)?t.set.bind(n):a});Object.defineProperty(r,e,{enumerable:!0,configurable:!0,get:()=>i.value,set:e=>i.value=e})}if(c)for(let e in c)Wr(c[e],r,n,e);if(l){let e=_(l)?l.call(n):l;Reflect.ownKeys(e).forEach(t=>{Pn(t,e[t])})}d&&Ur(d,e,`c`);function O(e,t){p(t)?t.forEach(t=>e(t.bind(n))):t&&e(t.bind(n))}if(O(yr,f),O(br,m),O(xr,h),O(Sr,g),O(pr,v),O(mr,y),O(Or,E),O(Dr,ee),O(Er,te),O(Cr,S),O(wr,w),O(Tr,ne),p(D))if(D.length){let t=e.exposed||={};D.forEach(e=>{Object.defineProperty(t,e,{get:()=>n[e],set:t=>n[e]=t,enumerable:!0})})}else e.exposed||={};T&&e.render===a&&(e.render=T),re!=null&&(e.inheritAttrs=re),ie&&(e.components=ie),ae&&(e.directives=ae),ne&&or(e)}function Hr(e,t,n=a){p(e)&&(e=Xr(e));for(let n in e){let r=e[n],i;i=b(r)?`default`in r?Fn(r.from||n,r.default,!0):Fn(r.from||n):Fn(r),N(i)?Object.defineProperty(t,n,{enumerable:!0,configurable:!0,get:()=>i.value,set:e=>i.value=e}):t[n]=i}}function Ur(e,t,n){dn(p(e)?e.map(e=>e.bind(t.proxy)):e.bind(t.proxy),t,n)}function Wr(e,t,n,r){let i=r.includes(`.`)?Vn(n,r):()=>n[r];if(v(e)){let n=t[e];_(n)&&Rn(i,n)}else if(_(e))Rn(i,e.bind(n));else if(b(e))if(p(e))e.forEach(e=>Wr(e,t,n,r));else{let r=_(e.handler)?e.handler.bind(n):t[e.handler];_(r)&&Rn(i,r,e)}}function Gr(e){let t=e.type,{mixins:n,extends:r}=t,{mixins:i,optionsCache:a,config:{optionMergeStrategies:o}}=e.appContext,s=a.get(t),c;return s?c=s:!i.length&&!n&&!r?c=t:(c={},i.length&&i.forEach(e=>Kr(c,e,o,!0)),Kr(c,t,o)),b(t)&&a.set(t,c),c}function Kr(e,t,n,r=!1){let{mixins:i,extends:a}=t;a&&Kr(e,a,n,!0),i&&i.forEach(t=>Kr(e,t,n,!0));for(let i in t)if(!(r&&i===`expose`)){let r=qr[i]||n&&n[i];e[i]=r?r(e[i],t[i]):t[i]}return e}var qr={data:Jr,props:Qr,emits:Qr,methods:Zr,computed:Zr,beforeCreate:L,created:L,beforeMount:L,mounted:L,beforeUpdate:L,updated:L,beforeDestroy:L,beforeUnmount:L,destroyed:L,unmounted:L,activated:L,deactivated:L,errorCaptured:L,serverPrefetch:L,components:Zr,directives:Zr,watch:$r,provide:Jr,inject:Yr};function Jr(e,t){return t?e?function(){return l(_(e)?e.call(this,this):e,_(t)?t.call(this,this):t)}:t:e}function Yr(e,t){return Zr(Xr(e),Xr(t))}function Xr(e){if(p(e)){let t={};for(let n=0;nt===`modelValue`||t===`model-value`?e.modelModifiers:e[`${t}Modifiers`]||e[`${D(t)}Modifiers`]||e[`${ie(t)}Modifiers`];function ai(e,t,...n){if(e.isUnmounted)return;let i=e.vnode.props||r,a=n,o=t.startsWith(`update:`),s=o&&ii(i,t.slice(7));s&&(s.trim&&(a=n.map(e=>v(e)?e.trim():e)),s.number&&(a=n.map(le)));let c,l=i[c=oe(t)]||i[c=oe(D(t))];!l&&o&&(l=i[c=oe(ie(t))]),l&&dn(l,e,6,a);let u=i[c+`Once`];if(u){if(!e.emitted)e.emitted={};else if(e.emitted[c])return;e.emitted[c]=!0,dn(u,e,6,a)}}var oi=new WeakMap;function si(e,t,n=!1){let r=n?oi:t.emitsCache,i=r.get(e);if(i!==void 0)return i;let a=e.emits,o={},s=!1;if(!_(e)){let r=e=>{let n=si(e,t,!0);n&&(s=!0,l(o,n))};!n&&t.mixins.length&&t.mixins.forEach(r),e.extends&&r(e.extends),e.mixins&&e.mixins.forEach(r)}return!a&&!s?(b(e)&&r.set(e,null),null):(p(a)?a.forEach(e=>o[e]=null):l(o,a),b(e)&&r.set(e,o),o)}function ci(e,t){return!e||!s(t)?!1:(t=t.slice(2).replace(/Once$/,``),f(e,t[0].toLowerCase()+t.slice(1))||f(e,ie(t))||f(e,t))}function li(e){let{type:t,vnode:n,proxy:r,withProxy:i,propsOptions:[a],slots:o,attrs:s,emit:l,render:u,renderCache:d,props:f,data:p,setupState:m,ctx:h,inheritAttrs:g}=e,_=jn(e),v,y;try{if(n.shapeFlag&4){let e=i||r,t=e;v=da(u.call(t,e,d,f,m,p,h)),y=s}else{let e=t;v=da(e.length>1?e(f,{attrs:s,slots:o,emit:l}):e(f,null)),y=t.props?s:ui(s)}}catch(t){Yi.length=0,fn(t,e,1),v=U(z)}let b=v;if(y&&g!==!1){let e=Object.keys(y),{shapeFlag:t}=b;e.length&&t&7&&(a&&e.some(c)&&(y=di(y,a)),b=ca(b,y,!1,!0))}return n.dirs&&(b=ca(b,null,!1,!0),b.dirs=b.dirs?b.dirs.concat(n.dirs):n.dirs),n.transition&&rr(b,n.transition),v=b,jn(_),v}var ui=e=>{let t;for(let n in e)(n===`class`||n===`style`||s(n))&&((t||={})[n]=e[n]);return t},di=(e,t)=>{let n={};for(let r in e)(!c(r)||!(r.slice(9)in t))&&(n[r]=e[r]);return n};function fi(e,t,n){let{props:r,children:i,component:a}=e,{props:o,children:s,patchFlag:c}=t,l=a.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&c>=0){if(c&1024)return!0;if(c&16)return r?pi(r,o,l):!!o;if(c&8){let e=t.dynamicProps;for(let t=0;tObject.create(gi),vi=e=>Object.getPrototypeOf(e)===gi;function yi(e,t,n,r=!1){let i={},a=_i();e.propsDefaults=Object.create(null),xi(e,t,i,a);for(let t in e.propsOptions[0])t in i||(i[t]=void 0);n?e.props=r?i:Bt(i):e.type.props?e.props=i:e.props=a,e.attrs=a}function bi(e,t,n,r){let{props:i,attrs:a,vnode:{patchFlag:o}}=e,s=M(i),[c]=e.propsOptions,l=!1;if((r||o>0)&&!(o&16)){if(o&8){let n=e.vnode.dynamicProps;for(let r=0;r{d=!0;let[n,r]=wi(e,t,!0);l(c,n),r&&u.push(...r)};!n&&t.mixins.length&&t.mixins.forEach(r),e.extends&&r(e.extends),e.mixins&&e.mixins.forEach(r)}if(!s&&!d)return b(e)&&a.set(e,i),i;if(p(s))for(let e=0;ee===`_`||e===`_ctx`||e===`$stable`,Di=e=>p(e)?e.map(da):[da(e)],Oi=(e,t,n)=>{if(t._n)return t;let r=Mn((...e)=>Di(t(...e)),n);return r._c=!1,r},ki=(e,t,n)=>{let r=e._ctx;for(let n in e){if(Ei(n))continue;let i=e[n];if(_(i))t[n]=Oi(n,i,r);else if(i!=null){let e=Di(i);t[n]=()=>e}}},Ai=(e,t)=>{let n=Di(t);e.slots.default=()=>n},ji=(e,t,n)=>{for(let r in t)(n||!Ei(r))&&(e[r]=t[r])},Mi=(e,t,n)=>{let r=e.slots=_i();if(e.vnode.shapeFlag&32){let e=t._;e?(ji(r,t,n),n&&ce(r,`_`,e,!0)):ki(t,r)}else t&&Ai(e,t)},Ni=(e,t,n)=>{let{vnode:i,slots:a}=e,o=!0,s=r;if(i.shapeFlag&32){let e=t._;e?n&&e===1?o=!1:ji(a,t,n):(o=!t.$stable,ki(t,a)),s=t}else t&&(Ai(e,t),s={default:1});if(o)for(let e in a)!Ei(e)&&s[e]==null&&delete a[e]},R=Gi;function Pi(e){return Fi(e)}function Fi(e,t){let n=fe();n.__VUE__=!0;let{insert:o,remove:s,patchProp:c,createElement:l,createText:u,createComment:d,setText:f,setElementText:p,parentNode:m,nextSibling:h,setScopeId:g=a,insertStaticContent:_}=e,v=(e,t,n,r=null,i=null,a=null,o=void 0,s=null,c=!!t.dynamicChildren)=>{if(e===t)return;e&&!ra(e,t)&&(r=be(e),he(e,i,a,!0),e=null),t.patchFlag===-2&&(c=!1,t.dynamicChildren=null);let{type:l,ref:u,shapeFlag:d}=t;switch(l){case qi:y(e,t,n,r);break;case z:b(e,t,n,r);break;case Ji:e??x(t,n,r,o);break;case Ki:ie(e,t,n,r,i,a,o,s,c);break;default:d&1?w(e,t,n,r,i,a,o,s,c):d&6?ae(e,t,n,r,i,a,o,s,c):(d&64||d&128)&&l.process(e,t,n,r,i,a,o,s,c,Ce)}u!=null&&i?lr(u,e&&e.ref,a,t||e,!t):u==null&&e&&e.ref!=null&&lr(e.ref,null,a,e,!0)},y=(e,t,n,r)=>{if(e==null)o(t.el=u(t.children),n,r);else{let n=t.el=e.el;t.children!==e.children&&f(n,t.children)}},b=(e,t,n,r)=>{e==null?o(t.el=d(t.children||``),n,r):t.el=e.el},x=(e,t,n,r)=>{[e.el,e.anchor]=_(e.children,t,n,r,e.el,e.anchor)},S=({el:e,anchor:t},n,r)=>{let i;for(;e&&e!==t;)i=h(e),o(e,n,r),e=i;o(t,n,r)},C=({el:e,anchor:t})=>{let n;for(;e&&e!==t;)n=h(e),s(e),e=n;s(t)},w=(e,t,n,r,i,a,o,s,c)=>{if(t.type===`svg`?o=`svg`:t.type===`math`&&(o=`mathml`),e==null)T(t,n,r,i,a,o,s,c);else{let n=e.el&&e.el._isVueCE?e.el:null;try{n&&n._beginPatch(),ne(e,t,i,a,o,s,c)}finally{n&&n._endPatch()}}},T=(e,t,n,r,i,a,s,u)=>{let d,f,{props:m,shapeFlag:h,transition:g,dirs:_}=e;if(d=e.el=l(e.type,a,m&&m.is,m),h&8?p(d,e.children):h&16&&E(e.children,d,null,r,i,Ii(e,a),s,u),_&&Nn(e,null,r,`created`),ee(d,e,e.scopeId,s,r),m){for(let e in m)e!==`value`&&!te(e)&&c(d,e,null,m[e],a,r);`value`in m&&c(d,`value`,null,m.value,a),(f=m.onVnodeBeforeMount)&&ha(f,r,e)}_&&Nn(e,null,r,`beforeMount`);let v=Ri(i,g);v&&g.beforeEnter(d),o(d,t,n),((f=m&&m.onVnodeMounted)||v||_)&&R(()=>{f&&ha(f,r,e),v&&g.enter(d),_&&Nn(e,null,r,`mounted`)},i)},ee=(e,t,n,r,i)=>{if(n&&g(e,n),r)for(let t=0;t{for(let l=c;l{let l=t.el=e.el,{patchFlag:u,dynamicChildren:d,dirs:f}=t;u|=e.patchFlag&16;let m=e.props||r,h=t.props||r,g;if(n&&Li(n,!1),(g=h.onVnodeBeforeUpdate)&&ha(g,n,t,e),f&&Nn(t,e,n,`beforeUpdate`),n&&Li(n,!0),(m.innerHTML&&h.innerHTML==null||m.textContent&&h.textContent==null)&&p(l,``),d?D(e.dynamicChildren,d,l,n,i,Ii(t,a),o):s||ue(e,t,l,null,n,i,Ii(t,a),o,!1),u>0){if(u&16)re(l,m,h,n,a);else if(u&2&&m.class!==h.class&&c(l,`class`,null,h.class,a),u&4&&c(l,`style`,m.style,h.style,a),u&8){let e=t.dynamicProps;for(let t=0;t{g&&ha(g,n,t,e),f&&Nn(t,e,n,`updated`)},i)},D=(e,t,n,r,i,a,o)=>{for(let s=0;s{if(t!==n){if(t!==r)for(let r in t)!te(r)&&!(r in n)&&c(e,r,t[r],null,a,i);for(let r in n){if(te(r))continue;let o=n[r],s=t[r];o!==s&&r!==`value`&&c(e,r,s,o,a,i)}`value`in n&&c(e,`value`,t.value,n.value,a)}},ie=(e,t,n,r,i,a,s,c,l)=>{let d=t.el=e?e.el:u(``),f=t.anchor=e?e.anchor:u(``),{patchFlag:p,dynamicChildren:m,slotScopeIds:h}=t;h&&(c=c?c.concat(h):h),e==null?(o(d,n,r),o(f,n,r),E(t.children||[],n,f,i,a,s,c,l)):p>0&&p&64&&m&&e.dynamicChildren&&e.dynamicChildren.length===m.length?(D(e.dynamicChildren,m,n,i,a,s,c),(t.key!=null||i&&t===i.subTree)&&zi(e,t,!0)):ue(e,t,n,f,i,a,s,c,l)},ae=(e,t,n,r,i,a,o,s,c)=>{t.slotScopeIds=s,e==null?t.shapeFlag&512?i.ctx.activate(t,n,r,o,c):oe(t,n,r,i,a,o,c):O(e,t,c)},oe=(e,t,n,r,i,a,o)=>{let s=e.component=va(e,r,i);if(fr(e)&&(s.ctx.renderer=Ce),Ea(s,!1,o),s.asyncDep){if(i&&i.registerDep(s,ce,o),!e.el){let r=s.subTree=U(z);b(null,r,t,n),e.placeholder=r.el}}else ce(s,e,t,n,i,a,o)},O=(e,t,n)=>{let r=t.component=e.component;if(fi(e,t,n))if(r.asyncDep&&!r.asyncResolved){le(r,t,n);return}else r.next=t,r.update();else t.el=e.el,r.vnode=t},ce=(e,t,n,r,i,a,o)=>{let s=()=>{if(e.isMounted){let{next:t,bu:n,u:r,parent:s,vnode:c}=e;{let n=Vi(e);if(n){t&&(t.el=c.el,le(e,t,o)),n.asyncDep.then(()=>{R(()=>{e.isUnmounted||l()},i)});return}}let u=t,d;Li(e,!1),t?(t.el=c.el,le(e,t,o)):t=c,n&&se(n),(d=t.props&&t.props.onVnodeBeforeUpdate)&&ha(d,s,t,c),Li(e,!0);let f=li(e),p=e.subTree;e.subTree=f,v(p,f,m(p.el),be(p),e,i,a),t.el=f.el,u===null&&hi(e,f.el),r&&R(r,i),(d=t.props&&t.props.onVnodeUpdated)&&R(()=>ha(d,s,t,c),i)}else{let o,{el:s,props:c}=t,{bm:l,m:u,parent:d,root:f,type:p}=e,m=dr(t);if(Li(e,!1),l&&se(l),!m&&(o=c&&c.onVnodeBeforeMount)&&ha(o,d,t),Li(e,!0),s&&Te){let t=()=>{e.subTree=li(e),Te(s,e.subTree,e,i,null)};m&&p.__asyncHydrate?p.__asyncHydrate(s,e,t):t()}else{f.ce&&f.ce._hasShadowRoot()&&f.ce._injectChildStyle(p,e.parent?e.parent.type:void 0);let o=e.subTree=li(e);v(null,o,n,r,e,i,a),t.el=o.el}if(u&&R(u,i),!m&&(o=c&&c.onVnodeMounted)){let e=t;R(()=>ha(o,d,e),i)}(t.shapeFlag&256||d&&dr(d.vnode)&&d.vnode.shapeFlag&256)&&e.a&&R(e.a,i),e.isMounted=!0,t=n=r=null}};e.scope.on();let c=e.effect=new Me(s);e.scope.off();let l=e.update=c.run.bind(c),u=e.job=c.runIfDirty.bind(c);u.i=e,u.id=e.uid,c.scheduler=()=>Sn(u),Li(e,!0),l()},le=(e,t,n)=>{t.component=e;let r=e.vnode.props;e.vnode=t,e.next=null,bi(e,t.props,r,n),Ni(e,t.children,n),qe(),Tn(e),Je()},ue=(e,t,n,r,i,a,o,s,c=!1)=>{let l=e&&e.children,u=e?e.shapeFlag:0,d=t.children,{patchFlag:f,shapeFlag:m}=t;if(f>0){if(f&128){pe(l,d,n,r,i,a,o,s,c);return}else if(f&256){de(l,d,n,r,i,a,o,s,c);return}}m&8?(u&16&&ye(l,i,a),d!==l&&p(n,d)):u&16?m&16?pe(l,d,n,r,i,a,o,s,c):ye(l,i,a,!0):(u&8&&p(n,``),m&16&&E(d,n,r,i,a,o,s,c))},de=(e,t,n,r,a,o,s,c,l)=>{e||=i,t||=i;let u=e.length,d=t.length,f=Math.min(u,d),p;for(p=0;pd?ye(e,a,o,!0,!1,f):E(t,n,r,a,o,s,c,l,f)},pe=(e,t,n,r,a,o,s,c,l)=>{let u=0,d=t.length,f=e.length-1,p=d-1;for(;u<=f&&u<=p;){let r=e[u],i=t[u]=l?fa(t[u]):da(t[u]);if(ra(r,i))v(r,i,n,null,a,o,s,c,l);else break;u++}for(;u<=f&&u<=p;){let r=e[f],i=t[p]=l?fa(t[p]):da(t[p]);if(ra(r,i))v(r,i,n,null,a,o,s,c,l);else break;f--,p--}if(u>f){if(u<=p){let e=p+1,i=ep)for(;u<=f;)he(e[u],a,o,!0),u++;else{let m=u,h=u,g=new Map;for(u=h;u<=p;u++){let e=t[u]=l?fa(t[u]):da(t[u]);e.key!=null&&g.set(e.key,u)}let _,y=0,b=p-h+1,x=!1,S=0,C=Array(b);for(u=0;u=b){he(r,a,o,!0);continue}let i;if(r.key!=null)i=g.get(r.key);else for(_=h;_<=p;_++)if(C[_-h]===0&&ra(r,t[_])){i=_;break}i===void 0?he(r,a,o,!0):(C[i-h]=u+1,i>=S?S=i:x=!0,v(r,t[i],n,null,a,o,s,c,l),y++)}let w=x?Bi(C):i;for(_=w.length-1,u=b-1;u>=0;u--){let e=h+u,i=t[e],f=t[e+1],p=e+1{let{el:a,type:c,transition:l,children:u,shapeFlag:d}=e;if(d&6){me(e.component.subTree,t,n,r);return}if(d&128){e.suspense.move(t,n,r);return}if(d&64){c.move(e,t,n,Ce);return}if(c===Ki){o(a,t,n);for(let e=0;el.enter(a),i);else{let{leave:r,delayLeave:i,afterLeave:c}=l,u=()=>{e.ctx.isUnmounted?s(a):o(a,t,n)},d=()=>{a._isLeaving&&a[Wn](!0),r(a,()=>{u(),c&&c()})};i?i(a,u,d):d()}else o(a,t,n)},he=(e,t,n,r=!1,i=!1)=>{let{type:a,props:o,ref:s,children:c,dynamicChildren:l,shapeFlag:u,patchFlag:d,dirs:f,cacheIndex:p}=e;if(d===-2&&(i=!1),s!=null&&(qe(),lr(s,null,n,e,!0),Je()),p!=null&&(t.renderCache[p]=void 0),u&256){t.ctx.deactivate(e);return}let m=u&1&&f,h=!dr(e),g;if(h&&(g=o&&o.onVnodeBeforeUnmount)&&ha(g,t,e),u&6)ve(e.component,n,r);else{if(u&128){e.suspense.unmount(n,r);return}m&&Nn(e,null,t,`beforeUnmount`),u&64?e.type.remove(e,t,n,Ce,r):l&&!l.hasOnce&&(a!==Ki||d>0&&d&64)?ye(l,t,n,!1,!0):(a===Ki&&d&384||!i&&u&16)&&ye(c,t,n),r&&ge(e)}(h&&(g=o&&o.onVnodeUnmounted)||m)&&R(()=>{g&&ha(g,t,e),m&&Nn(e,null,t,`unmounted`)},n)},ge=e=>{let{type:t,el:n,anchor:r,transition:i}=e;if(t===Ki){_e(n,r);return}if(t===Ji){C(e);return}let a=()=>{s(n),i&&!i.persisted&&i.afterLeave&&i.afterLeave()};if(e.shapeFlag&1&&i&&!i.persisted){let{leave:t,delayLeave:r}=i,o=()=>t(n,a);r?r(e.el,a,o):o()}else a()},_e=(e,t)=>{let n;for(;e!==t;)n=h(e),s(e),e=n;s(t)},ve=(e,t,n)=>{let{bum:r,scope:i,job:a,subTree:o,um:s,m:c,a:l}=e;Hi(c),Hi(l),r&&se(r),i.stop(),a&&(a.flags|=8,he(o,e,t,n)),s&&R(s,t),R(()=>{e.isUnmounted=!0},t)},ye=(e,t,n,r=!1,i=!1,a=0)=>{for(let o=a;o{if(e.shapeFlag&6)return be(e.component.subTree);if(e.shapeFlag&128)return e.suspense.next();let t=h(e.anchor||e.el),n=t&&t[Hn];return n?h(n):t},xe=!1,Se=(e,t,n)=>{let r;e==null?t._vnode&&(he(t._vnode,null,null,!0),r=t._vnode.component):v(t._vnode||null,e,t,null,null,null,n),t._vnode=e,xe||=(xe=!0,Tn(r),En(),!1)},Ce={p:v,um:he,m:me,r:ge,mt:oe,mc:E,pc:ue,pbc:D,n:be,o:e},we,Te;return t&&([we,Te]=t(Ce)),{render:Se,hydrate:we,createApp:ni(Se,we)}}function Ii({type:e,props:t},n){return n===`svg`&&e===`foreignObject`||n===`mathml`&&e===`annotation-xml`&&t&&t.encoding&&t.encoding.includes(`html`)?void 0:n}function Li({effect:e,job:t},n){n?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function Ri(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function zi(e,t,n=!1){let r=e.children,i=t.children;if(p(r)&&p(i))for(let e=0;e>1,e[n[s]]0&&(t[r]=n[a-1]),n[a]=r)}}for(a=n.length,o=n[a-1];a-- >0;)n[a]=o,o=t[o];return n}function Vi(e){let t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:Vi(t)}function Hi(e){if(e)for(let t=0;te.__isSuspense;function Gi(e,t){t&&t.pendingBranch?p(e)?t.effects.push(...e):t.effects.push(e):wn(e)}var Ki=Symbol.for(`v-fgt`),qi=Symbol.for(`v-txt`),z=Symbol.for(`v-cmt`),Ji=Symbol.for(`v-stc`),Yi=[],Xi=null;function B(e=!1){Yi.push(Xi=e?null:[])}function Zi(){Yi.pop(),Xi=Yi[Yi.length-1]||null}var Qi=1;function $i(e,t=!1){Qi+=e,e<0&&Xi&&t&&(Xi.hasOnce=!0)}function ea(e){return e.dynamicChildren=Qi>0?Xi||i:null,Zi(),Qi>0&&Xi&&Xi.push(e),e}function V(e,t,n,r,i,a){return ea(H(e,t,n,r,i,a,!0))}function ta(e,t,n,r,i){return ea(U(e,t,n,r,i,!0))}function na(e){return e?e.__v_isVNode===!0:!1}function ra(e,t){return e.type===t.type&&e.key===t.key}var ia=({key:e})=>e??null,aa=({ref:e,ref_key:t,ref_for:n})=>(typeof e==`number`&&(e=``+e),e==null?null:v(e)||N(e)||_(e)?{i:kn,r:e,k:t,f:!!n}:e);function H(e,t=null,n=null,r=0,i=null,a=e===Ki?0:1,o=!1,s=!1){let c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&ia(t),ref:t&&aa(t),scopeId:An,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:a,patchFlag:r,dynamicProps:i,dynamicChildren:null,appContext:null,ctx:kn};return s?(pa(c,n),a&128&&e.normalize(c)):n&&(c.shapeFlag|=v(n)?8:16),Qi>0&&!o&&Xi&&(c.patchFlag>0||a&6)&&c.patchFlag!==32&&Xi.push(c),c}var U=oa;function oa(e,t=null,n=null,r=0,i=null,a=!1){if((!e||e===jr)&&(e=z),na(e)){let r=ca(e,t,!0);return n&&pa(r,n),Qi>0&&!a&&Xi&&(r.shapeFlag&6?Xi[Xi.indexOf(e)]=r:Xi.push(r)),r.patchFlag=-2,r}if(Ia(e)&&(e=e.__vccOpts),t){t=sa(t);let{class:e,style:n}=t;e&&!v(e)&&(t.class=ve(e)),b(n)&&(Kt(n)&&!p(n)&&(n=l({},n)),t.style=pe(n))}let o=v(e)?1:Wi(e)?128:Un(e)?64:b(e)?4:_(e)?2:0;return H(e,t,n,r,i,o,a,!0)}function sa(e){return e?Kt(e)||vi(e)?l({},e):e:null}function ca(e,t,n=!1,r=!1){let{props:i,ref:a,patchFlag:o,children:s,transition:c}=e,l=t?ma(i||{},t):i,u={__v_isVNode:!0,__v_skip:!0,type:e.type,props:l,key:l&&ia(l),ref:t&&t.ref?n&&a?p(a)?a.concat(aa(t)):[a,aa(t)]:aa(t):a,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:s,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==Ki?o===-1?16:o|16:o,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:c,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&ca(e.ssContent),ssFallback:e.ssFallback&&ca(e.ssFallback),placeholder:e.placeholder,el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return c&&r&&rr(u,c.clone(u)),u}function la(e=` `,t=0){return U(qi,null,e,t)}function ua(e,t){let n=U(Ji,null,e);return n.staticCount=t,n}function W(e=``,t=!1){return t?(B(),ta(z,null,e)):U(z,null,e)}function da(e){return e==null||typeof e==`boolean`?U(z):p(e)?U(Ki,null,e.slice()):na(e)?fa(e):U(qi,null,String(e))}function fa(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:ca(e)}function pa(e,t){let n=0,{shapeFlag:r}=e;if(t==null)t=null;else if(p(t))n=16;else if(typeof t==`object`)if(r&65){let n=t.default;n&&(n._c&&(n._d=!1),pa(e,n()),n._c&&(n._d=!0));return}else{n=32;let r=t._;!r&&!vi(t)?t._ctx=kn:r===3&&kn&&(kn.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else _(t)?(t={default:t,_ctx:kn},n=32):(t=String(t),r&64?(n=16,t=[la(t)]):n=8);e.children=t,e.shapeFlag|=n}function ma(...e){let t={};for(let n=0;nG||kn,ba,xa;{let e=fe(),t=(t,n)=>{let r;return(r=e[t])||(r=e[t]=[]),r.push(n),e=>{r.length>1?r.forEach(t=>t(e)):r[0](e)}};ba=t(`__VUE_INSTANCE_SETTERS__`,e=>G=e),xa=t(`__VUE_SSR_SETTERS__`,e=>Ta=e)}var Sa=e=>{let t=G;return ba(e),e.scope.on(),()=>{e.scope.off(),ba(t)}},Ca=()=>{G&&G.scope.off(),ba(null)};function wa(e){return e.vnode.shapeFlag&4}var Ta=!1;function Ea(e,t=!1,n=!1){t&&xa(t);let{props:r,children:i}=e.vnode,a=wa(e);yi(e,r,a,t),Mi(e,i,n||t);let o=a?Da(e,t):void 0;return t&&xa(!1),o}function Da(e,t){let n=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,Rr);let{setup:r}=n;if(r){qe();let n=e.setupContext=r.length>1?Na(e):null,i=Sa(e),a=un(r,e,0,[e.props,n]),o=x(a);if(Je(),i(),(o||e.sp)&&!dr(e)&&or(e),o){if(a.then(Ca,Ca),t)return a.then(n=>{Oa(e,n,t)}).catch(t=>{fn(t,e,0)});e.asyncDep=a}else Oa(e,a,t)}else ja(e,t)}function Oa(e,t,n){_(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:b(t)&&(e.setupState=en(t)),ja(e,n)}var ka,Aa;function ja(e,t,n){let r=e.type;if(!e.render){if(!t&&ka&&!r.render){let t=r.template||Gr(e).template;if(t){let{isCustomElement:n,compilerOptions:i}=e.appContext.config,{delimiters:a,compilerOptions:o}=r;r.render=ka(t,l(l({isCustomElement:n,delimiters:a},i),o))}}e.render=r.render||a,Aa&&Aa(e)}{let t=Sa(e);qe();try{Vr(e)}finally{Je(),t()}}}var Ma={get(e,t){return j(e,`get`,``),e[t]}};function Na(e){return{attrs:new Proxy(e.attrs,Ma),slots:e.slots,emit:e.emit,expose:t=>{e.exposed=t||{}}}}function Pa(e){return e.exposed?e.exposeProxy||=new Proxy(en(qt(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Ir)return Ir[n](e)},has(e,t){return t in e||t in Ir}}):e.proxy}function Fa(e,t=!0){return _(e)?e.displayName||e.name:e.name||t&&e.__name}function Ia(e){return _(e)&&`__vccOpts`in e}var La=(e,t)=>nn(e,t,Ta);function Ra(e,t,n){try{$i(-1);let r=arguments.length;return r===2?b(t)&&!p(t)?na(t)?U(e,null,[t]):U(e,t):U(e,null,t):(r>3?n=Array.prototype.slice.call(arguments,2):r===3&&na(n)&&(n=[n]),U(e,t,n))}finally{$i(1)}}var za=`3.5.30`,Ba=void 0,Va=typeof window<`u`&&window.trustedTypes;if(Va)try{Ba=Va.createPolicy(`vue`,{createHTML:e=>e})}catch{}var Ha=Ba?e=>Ba.createHTML(e):e=>e,Ua=`http://www.w3.org/2000/svg`,Wa=`http://www.w3.org/1998/Math/MathML`,Ga=typeof document<`u`?document:null,Ka=Ga&&Ga.createElement(`template`),qa={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{let t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{let i=t===`svg`?Ga.createElementNS(Ua,e):t===`mathml`?Ga.createElementNS(Wa,e):n?Ga.createElement(e,{is:n}):Ga.createElement(e);return e===`select`&&r&&r.multiple!=null&&i.setAttribute(`multiple`,r.multiple),i},createText:e=>Ga.createTextNode(e),createComment:e=>Ga.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Ga.querySelector(e),setScopeId(e,t){e.setAttribute(t,``)},insertStaticContent(e,t,n,r,i,a){let o=n?n.previousSibling:t.lastChild;if(i&&(i===a||i.nextSibling))for(;t.insertBefore(i.cloneNode(!0),n),!(i===a||!(i=i.nextSibling)););else{Ka.innerHTML=Ha(r===`svg`?``:r===`mathml`?``:e);let i=Ka.content;if(r===`svg`||r===`mathml`){let e=i.firstChild;for(;e.firstChild;)i.appendChild(e.firstChild);i.removeChild(e)}t.insertBefore(i,n)}return[o?o.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},Ja=`transition`,Ya=`animation`,Xa=Symbol(`_vtc`),Za={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},Qa=l({},Jn,Za),$a=(e=>(e.displayName=`Transition`,e.props=Qa,e))((e,{slots:t})=>Ra(Qn,no(e),t)),eo=(e,t=[])=>{p(e)?e.forEach(e=>e(...t)):e&&e(...t)},to=e=>e?p(e)?e.some(e=>e.length>1):e.length>1:!1;function no(e){let t={};for(let n in e)n in Za||(t[n]=e[n]);if(e.css===!1)return t;let{name:n=`v`,type:r,duration:i,enterFromClass:a=`${n}-enter-from`,enterActiveClass:o=`${n}-enter-active`,enterToClass:s=`${n}-enter-to`,appearFromClass:c=a,appearActiveClass:u=o,appearToClass:d=s,leaveFromClass:f=`${n}-leave-from`,leaveActiveClass:p=`${n}-leave-active`,leaveToClass:m=`${n}-leave-to`}=e,h=ro(i),g=h&&h[0],_=h&&h[1],{onBeforeEnter:v,onEnter:y,onEnterCancelled:b,onLeave:x,onLeaveCancelled:S,onBeforeAppear:C=v,onAppear:w=y,onAppearCancelled:T=b}=t,ee=(e,t,n,r)=>{e._enterCancelled=r,oo(e,t?d:s),oo(e,t?u:o),n&&n()},te=(e,t)=>{e._isLeaving=!1,oo(e,f),oo(e,m),oo(e,p),t&&t()},E=e=>(t,n)=>{let i=e?w:y,o=()=>ee(t,e,n);eo(i,[t,o]),so(()=>{oo(t,e?c:a),ao(t,e?d:s),to(i)||lo(t,r,g,o)})};return l(t,{onBeforeEnter(e){eo(v,[e]),ao(e,a),ao(e,o)},onBeforeAppear(e){eo(C,[e]),ao(e,c),ao(e,u)},onEnter:E(!1),onAppear:E(!0),onLeave(e,t){e._isLeaving=!0;let n=()=>te(e,t);ao(e,f),e._enterCancelled?(ao(e,p),mo(e)):(mo(e),ao(e,p)),so(()=>{e._isLeaving&&(oo(e,f),ao(e,m),to(x)||lo(e,r,_,n))}),eo(x,[e,n])},onEnterCancelled(e){ee(e,!1,void 0,!0),eo(b,[e])},onAppearCancelled(e){ee(e,!0,void 0,!0),eo(T,[e])},onLeaveCancelled(e){te(e),eo(S,[e])}})}function ro(e){if(e==null)return null;if(b(e))return[io(e.enter),io(e.leave)];{let t=io(e);return[t,t]}}function io(e){return ue(e)}function ao(e,t){t.split(/\s+/).forEach(t=>t&&e.classList.add(t)),(e[Xa]||(e[Xa]=new Set)).add(t)}function oo(e,t){t.split(/\s+/).forEach(t=>t&&e.classList.remove(t));let n=e[Xa];n&&(n.delete(t),n.size||(e[Xa]=void 0))}function so(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}var co=0;function lo(e,t,n,r){let i=e._endId=++co,a=()=>{i===e._endId&&r()};if(n!=null)return setTimeout(a,n);let{type:o,timeout:s,propCount:c}=uo(e,t);if(!o)return r();let l=o+`end`,u=0,d=()=>{e.removeEventListener(l,f),a()},f=t=>{t.target===e&&++u>=c&&d()};setTimeout(()=>{u(n[e]||``).split(`, `),i=r(`${Ja}Delay`),a=r(`${Ja}Duration`),o=fo(i,a),s=r(`${Ya}Delay`),c=r(`${Ya}Duration`),l=fo(s,c),u=null,d=0,f=0;t===Ja?o>0&&(u=Ja,d=o,f=a.length):t===Ya?l>0&&(u=Ya,d=l,f=c.length):(d=Math.max(o,l),u=d>0?o>l?Ja:Ya:null,f=u?u===Ja?a.length:c.length:0);let p=u===Ja&&/\b(?:transform|all)(?:,|$)/.test(r(`${Ja}Property`).toString());return{type:u,timeout:d,propCount:f,hasTransform:p}}function fo(e,t){for(;e.lengthpo(t)+po(e[n])))}function po(e){return e===`auto`?0:Number(e.slice(0,-1).replace(`,`,`.`))*1e3}function mo(e){return(e?e.ownerDocument:document).body.offsetHeight}function ho(e,t,n){let r=e[Xa];r&&(t=(t?[t,...r]:[...r]).join(` `)),t==null?e.removeAttribute(`class`):n?e.setAttribute(`class`,t):e.className=t}var go=Symbol(`_vod`),_o=Symbol(`_vsh`),vo=Symbol(``),yo=/(?:^|;)\s*display\s*:/;function bo(e,t,n){let r=e.style,i=v(n),a=!1;if(n&&!i){if(t)if(v(t))for(let e of t.split(`;`)){let t=e.slice(0,e.indexOf(`:`)).trim();n[t]??So(r,t,``)}else for(let e in t)n[e]??So(r,e,``);for(let e in n)e===`display`&&(a=!0),So(r,e,n[e])}else if(i){if(t!==n){let e=r[vo];e&&(n+=`;`+e),r.cssText=n,a=yo.test(n)}}else t&&e.removeAttribute(`style`);go in e&&(e[go]=a?r.display:``,e[_o]&&(r.display=`none`))}var xo=/\s*!important$/;function So(e,t,n){if(p(n))n.forEach(n=>So(e,t,n));else if(n??=``,t.startsWith(`--`))e.setProperty(t,n);else{let r=To(e,t);xo.test(n)?e.setProperty(ie(r),n.replace(xo,``),`important`):e[r]=n}}var Co=[`Webkit`,`Moz`,`ms`],wo={};function To(e,t){let n=wo[t];if(n)return n;let r=D(t);if(r!==`filter`&&r in e)return wo[t]=r;r=ae(r);for(let n=0;nFo||=(Io.then(()=>Fo=0),Date.now());function Ro(e,t){let n=e=>{if(!e._vts)e._vts=Date.now();else if(e._vts<=n.attached)return;dn(zo(e,n.value),t,5,[e])};return n.value=e,n.attached=Lo(),n}function zo(e,t){if(p(t)){let n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(e=>t=>!t._stopped&&e&&e(t))}else return t}var Bo=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,Vo=(e,t,n,r,i,a)=>{let o=i===`svg`;t===`class`?ho(e,r,o):t===`style`?bo(e,n,r):s(t)?c(t)||Mo(e,t,n,r,a):(t[0]===`.`?(t=t.slice(1),!0):t[0]===`^`?(t=t.slice(1),!1):Ho(e,t,r,o))?(Oo(e,t,r),!e.tagName.includes(`-`)&&(t===`value`||t===`checked`||t===`selected`)&&Do(e,t,r,o,a,t!==`value`)):e._isVueCE&&(Uo(e,t)||e._def.__asyncLoader&&(/[A-Z]/.test(t)||!v(r)))?Oo(e,D(t),r,a,t):(t===`true-value`?e._trueValue=r:t===`false-value`&&(e._falseValue=r),Do(e,t,r,o))};function Ho(e,t,n,r){if(r)return!!(t===`innerHTML`||t===`textContent`||t in e&&Bo(t)&&_(n));if(t===`spellcheck`||t===`draggable`||t===`translate`||t===`autocorrect`||t===`sandbox`&&e.tagName===`IFRAME`||t===`form`||t===`list`&&e.tagName===`INPUT`||t===`type`&&e.tagName===`TEXTAREA`)return!1;if(t===`width`||t===`height`){let t=e.tagName;if(t===`IMG`||t===`VIDEO`||t===`CANVAS`||t===`SOURCE`)return!1}return Bo(t)&&v(n)?!1:t in e}function Uo(e,t){let n=e._def.props;if(!n)return!1;let r=D(t);return Array.isArray(n)?n.some(e=>D(e)===r):Object.keys(n).some(e=>D(e)===r)}var Wo=e=>{let t=e.props[`onUpdate:modelValue`]||!1;return p(t)?e=>se(t,e):t};function Go(e){e.target.composing=!0}function Ko(e){let t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event(`input`)))}var qo=Symbol(`_assign`);function Jo(e,t,n){return t&&(e=e.trim()),n&&(e=le(e)),e}var Yo={created(e,{modifiers:{lazy:t,trim:n,number:r}},i){e[qo]=Wo(i);let a=r||i.props&&i.props.type===`number`;ko(e,t?`change`:`input`,t=>{t.target.composing||e[qo](Jo(e.value,n,a))}),(n||a)&&ko(e,`change`,()=>{e.value=Jo(e.value,n,a)}),t||(ko(e,`compositionstart`,Go),ko(e,`compositionend`,Ko),ko(e,`change`,Ko))},mounted(e,{value:t}){e.value=t??``},beforeUpdate(e,{value:t,oldValue:n,modifiers:{lazy:r,trim:i,number:a}},o){if(e[qo]=Wo(o),e.composing)return;let s=(a||e.type===`number`)&&!/^0\d/.test(e.value)?le(e.value):e.value,c=t??``;s!==c&&(document.activeElement===e&&e.type!==`range`&&(r&&t===n||i&&e.value.trim()===c)||(e.value=c))}},Xo={deep:!0,created(e,t,n){e[qo]=Wo(n),ko(e,`change`,()=>{let t=e._modelValue,n=es(e),r=e.checked,i=e[qo];if(p(t)){let e=we(t,n),a=e!==-1;if(r&&!a)i(t.concat(n));else if(!r&&a){let n=[...t];n.splice(e,1),i(n)}}else if(h(t)){let e=new Set(t);r?e.add(n):e.delete(n),i(e)}else i(ts(e,r))})},mounted:Zo,beforeUpdate(e,t,n){e[qo]=Wo(n),Zo(e,t,n)}};function Zo(e,{value:t,oldValue:n},r){e._modelValue=t;let i;if(p(t))i=we(t,r.props.value)>-1;else if(h(t))i=t.has(r.props.value);else{if(t===n)return;i=Ce(t,ts(e,!0))}e.checked!==i&&(e.checked=i)}var Qo={deep:!0,created(e,{value:t,modifiers:{number:n}},r){let i=h(t);ko(e,`change`,()=>{let t=Array.prototype.filter.call(e.options,e=>e.selected).map(e=>n?le(es(e)):es(e));e[qo](e.multiple?i?new Set(t):t:t[0]),e._assigning=!0,bn(()=>{e._assigning=!1})}),e[qo]=Wo(r)},mounted(e,{value:t}){$o(e,t)},beforeUpdate(e,t,n){e[qo]=Wo(n)},updated(e,{value:t}){e._assigning||$o(e,t)}};function $o(e,t){let n=e.multiple,r=p(t);if(!(n&&!r&&!h(t))){for(let i=0,a=e.options.length;iString(e)===String(o)):a.selected=we(t,o)>-1}else a.selected=t.has(o);else if(Ce(es(a),t)){e.selectedIndex!==i&&(e.selectedIndex=i);return}}!n&&e.selectedIndex!==-1&&(e.selectedIndex=-1)}}function es(e){return`_value`in e?e._value:e.value}function ts(e,t){let n=t?`_trueValue`:`_falseValue`;return n in e?e[n]:t}var ns=[`ctrl`,`shift`,`alt`,`meta`],rs={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>`button`in e&&e.button!==0,middle:e=>`button`in e&&e.button!==1,right:e=>`button`in e&&e.button!==2,exact:(e,t)=>ns.some(n=>e[`${n}Key`]&&!t.includes(n))},is=(e,t)=>{if(!e)return e;let n=e._withMods||={},r=t.join(`.`);return n[r]||(n[r]=((n,...r)=>{for(let e=0;e{let n=e._withKeys||={},r=t.join(`.`);return n[r]||(n[r]=(n=>{if(!(`key`in n))return;let r=ie(n.key);if(t.some(e=>e===r||as[e]===r))return e(n)}))},ss=l({patchProp:Vo},qa),cs;function ls(){return cs||=Pi(ss)}var us=((...e)=>{let t=ls().createApp(...e),{mount:n}=t;return t.mount=e=>{let r=fs(e);if(!r)return;let i=t._component;!_(i)&&!i.render&&!i.template&&(i.template=r.innerHTML),r.nodeType===1&&(r.textContent=``);let a=n(r,!1,ds(r));return r instanceof Element&&(r.removeAttribute(`v-cloak`),r.setAttribute(`data-v-app`,``)),a},t});function ds(e){if(e instanceof SVGElement)return`svg`;if(typeof MathMLElement==`function`&&e instanceof MathMLElement)return`mathml`}function fs(e){return v(e)?document.querySelector(e):e}function ps(e,t){return function(){return e.apply(t,arguments)}}var{toString:ms}=Object.prototype,{getPrototypeOf:hs}=Object,{iterator:gs,toStringTag:_s}=Symbol,vs=(e=>t=>{let n=ms.call(t);return e[n]||(e[n]=n.slice(8,-1).toLowerCase())})(Object.create(null)),ys=e=>(e=e.toLowerCase(),t=>vs(t)===e),bs=e=>t=>typeof t===e,{isArray:xs}=Array,Ss=bs(`undefined`);function Cs(e){return e!==null&&!Ss(e)&&e.constructor!==null&&!Ss(e.constructor)&&K(e.constructor.isBuffer)&&e.constructor.isBuffer(e)}var ws=ys(`ArrayBuffer`);function Ts(e){let t;return t=typeof ArrayBuffer<`u`&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&ws(e.buffer),t}var Es=bs(`string`),K=bs(`function`),Ds=bs(`number`),Os=e=>typeof e==`object`&&!!e,ks=e=>e===!0||e===!1,As=e=>{if(vs(e)!==`object`)return!1;let t=hs(e);return(t===null||t===Object.prototype||Object.getPrototypeOf(t)===null)&&!(_s in e)&&!(gs in e)},js=e=>{if(!Os(e)||Cs(e))return!1;try{return Object.keys(e).length===0&&Object.getPrototypeOf(e)===Object.prototype}catch{return!1}},Ms=ys(`Date`),Ns=ys(`File`),Ps=e=>!!(e&&e.uri!==void 0),Fs=e=>e&&e.getParts!==void 0,Is=ys(`Blob`),Ls=ys(`FileList`),Rs=e=>Os(e)&&K(e.pipe);function zs(){return typeof globalThis<`u`?globalThis:typeof self<`u`?self:typeof window<`u`?window:typeof global<`u`?global:{}}var Bs=zs(),Vs=Bs.FormData===void 0?void 0:Bs.FormData,Hs=e=>{let t;return e&&(Vs&&e instanceof Vs||K(e.append)&&((t=vs(e))===`formdata`||t===`object`&&K(e.toString)&&e.toString()===`[object FormData]`))},Us=ys(`URLSearchParams`),[Ws,Gs,Ks,qs]=[`ReadableStream`,`Request`,`Response`,`Headers`].map(ys),Js=e=>e.trim?e.trim():e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,``);function Ys(e,t,{allOwnKeys:n=!1}={}){if(e==null)return;let r,i;if(typeof e!=`object`&&(e=[e]),xs(e))for(r=0,i=e.length;r0;)if(i=n[r],t===i.toLowerCase())return i;return null}var Zs=typeof globalThis<`u`?globalThis:typeof self<`u`?self:typeof window<`u`?window:global,Qs=e=>!Ss(e)&&e!==Zs;function $s(){let{caseless:e,skipUndefined:t}=Qs(this)&&this||{},n={},r=(r,i)=>{if(i===`__proto__`||i===`constructor`||i===`prototype`)return;let a=e&&Xs(n,i)||i;As(n[a])&&As(r)?n[a]=$s(n[a],r):As(r)?n[a]=$s({},r):xs(r)?n[a]=r.slice():(!t||!Ss(r))&&(n[a]=r)};for(let e=0,t=arguments.length;e(Ys(t,(t,r)=>{n&&K(t)?Object.defineProperty(e,r,{value:ps(t,n),writable:!0,enumerable:!0,configurable:!0}):Object.defineProperty(e,r,{value:t,writable:!0,enumerable:!0,configurable:!0})},{allOwnKeys:r}),e),tc=e=>(e.charCodeAt(0)===65279&&(e=e.slice(1)),e),nc=(e,t,n,r)=>{e.prototype=Object.create(t.prototype,r),Object.defineProperty(e.prototype,`constructor`,{value:e,writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(e,`super`,{value:t.prototype}),n&&Object.assign(e.prototype,n)},rc=(e,t,n,r)=>{let i,a,o,s={};if(t||={},e==null)return t;do{for(i=Object.getOwnPropertyNames(e),a=i.length;a-- >0;)o=i[a],(!r||r(o,e,t))&&!s[o]&&(t[o]=e[o],s[o]=!0);e=n!==!1&&hs(e)}while(e&&(!n||n(e,t))&&e!==Object.prototype);return t},ic=(e,t,n)=>{e=String(e),(n===void 0||n>e.length)&&(n=e.length),n-=t.length;let r=e.indexOf(t,n);return r!==-1&&r===n},ac=e=>{if(!e)return null;if(xs(e))return e;let t=e.length;if(!Ds(t))return null;let n=Array(t);for(;t-- >0;)n[t]=e[t];return n},oc=(e=>t=>e&&t instanceof e)(typeof Uint8Array<`u`&&hs(Uint8Array)),sc=(e,t)=>{let n=(e&&e[gs]).call(e),r;for(;(r=n.next())&&!r.done;){let n=r.value;t.call(e,n[0],n[1])}},cc=(e,t)=>{let n,r=[];for(;(n=e.exec(t))!==null;)r.push(n);return r},lc=ys(`HTMLFormElement`),uc=e=>e.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,function(e,t,n){return t.toUpperCase()+n}),dc=(({hasOwnProperty:e})=>(t,n)=>e.call(t,n))(Object.prototype),fc=ys(`RegExp`),pc=(e,t)=>{let n=Object.getOwnPropertyDescriptors(e),r={};Ys(n,(n,i)=>{let a;(a=t(n,i,e))!==!1&&(r[i]=a||n)}),Object.defineProperties(e,r)},mc=e=>{pc(e,(t,n)=>{if(K(e)&&[`arguments`,`caller`,`callee`].indexOf(n)!==-1)return!1;let r=e[n];if(K(r)){if(t.enumerable=!1,`writable`in t){t.writable=!1;return}t.set||=()=>{throw Error(`Can not rewrite read-only method '`+n+`'`)}}})},hc=(e,t)=>{let n={},r=e=>{e.forEach(e=>{n[e]=!0})};return xs(e)?r(e):r(String(e).split(t)),n},gc=()=>{},_c=(e,t)=>e!=null&&Number.isFinite(e=+e)?e:t;function vc(e){return!!(e&&K(e.append)&&e[_s]===`FormData`&&e[gs])}var yc=e=>{let t=Array(10),n=(e,r)=>{if(Os(e)){if(t.indexOf(e)>=0)return;if(Cs(e))return e;if(!(`toJSON`in e)){t[r]=e;let i=xs(e)?[]:{};return Ys(e,(e,t)=>{let a=n(e,r+1);!Ss(a)&&(i[t]=a)}),t[r]=void 0,i}}return e};return n(e,0)},bc=ys(`AsyncFunction`),xc=e=>e&&(Os(e)||K(e))&&K(e.then)&&K(e.catch),Sc=((e,t)=>e?setImmediate:t?((e,t)=>(Zs.addEventListener(`message`,({source:n,data:r})=>{n===Zs&&r===e&&t.length&&t.shift()()},!1),n=>{t.push(n),Zs.postMessage(e,`*`)}))(`axios@${Math.random()}`,[]):e=>setTimeout(e))(typeof setImmediate==`function`,K(Zs.postMessage)),q={isArray:xs,isArrayBuffer:ws,isBuffer:Cs,isFormData:Hs,isArrayBufferView:Ts,isString:Es,isNumber:Ds,isBoolean:ks,isObject:Os,isPlainObject:As,isEmptyObject:js,isReadableStream:Ws,isRequest:Gs,isResponse:Ks,isHeaders:qs,isUndefined:Ss,isDate:Ms,isFile:Ns,isReactNativeBlob:Ps,isReactNative:Fs,isBlob:Is,isRegExp:fc,isFunction:K,isStream:Rs,isURLSearchParams:Us,isTypedArray:oc,isFileList:Ls,forEach:Ys,merge:$s,extend:ec,trim:Js,stripBOM:tc,inherits:nc,toFlatObject:rc,kindOf:vs,kindOfTest:ys,endsWith:ic,toArray:ac,forEachEntry:sc,matchAll:cc,isHTMLForm:lc,hasOwnProperty:dc,hasOwnProp:dc,reduceDescriptors:pc,freezeMethods:mc,toObjectSet:hc,toCamelCase:uc,noop:gc,toFiniteNumber:_c,findKey:Xs,global:Zs,isContextDefined:Qs,isSpecCompliantForm:vc,toJSONObject:yc,isAsyncFn:bc,isThenable:xc,setImmediate:Sc,asap:typeof queueMicrotask<`u`?queueMicrotask.bind(Zs):typeof process<`u`&&process.nextTick||Sc,isIterable:e=>e!=null&&K(e[gs])},J=class e extends Error{static from(t,n,r,i,a,o){let s=new e(t.message,n||t.code,r,i,a);return s.cause=t,s.name=t.name,t.status!=null&&s.status==null&&(s.status=t.status),o&&Object.assign(s,o),s}constructor(e,t,n,r,i){super(e),Object.defineProperty(this,`message`,{value:e,enumerable:!0,writable:!0,configurable:!0}),this.name=`AxiosError`,this.isAxiosError=!0,t&&(this.code=t),n&&(this.config=n),r&&(this.request=r),i&&(this.response=i,this.status=i.status)}toJSON(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:q.toJSONObject(this.config),code:this.code,status:this.status}}};J.ERR_BAD_OPTION_VALUE=`ERR_BAD_OPTION_VALUE`,J.ERR_BAD_OPTION=`ERR_BAD_OPTION`,J.ECONNABORTED=`ECONNABORTED`,J.ETIMEDOUT=`ETIMEDOUT`,J.ERR_NETWORK=`ERR_NETWORK`,J.ERR_FR_TOO_MANY_REDIRECTS=`ERR_FR_TOO_MANY_REDIRECTS`,J.ERR_DEPRECATED=`ERR_DEPRECATED`,J.ERR_BAD_RESPONSE=`ERR_BAD_RESPONSE`,J.ERR_BAD_REQUEST=`ERR_BAD_REQUEST`,J.ERR_CANCELED=`ERR_CANCELED`,J.ERR_NOT_SUPPORT=`ERR_NOT_SUPPORT`,J.ERR_INVALID_URL=`ERR_INVALID_URL`;function Cc(e){return q.isPlainObject(e)||q.isArray(e)}function wc(e){return q.endsWith(e,`[]`)?e.slice(0,-2):e}function Tc(e,t,n){return e?e.concat(t).map(function(e,t){return e=wc(e),!n&&t?`[`+e+`]`:e}).join(n?`.`:``):t}function Ec(e){return q.isArray(e)&&!e.some(Cc)}var Dc=q.toFlatObject(q,{},null,function(e){return/^is[A-Z]/.test(e)});function Oc(e,t,n){if(!q.isObject(e))throw TypeError(`target must be an object`);t||=new FormData,n=q.toFlatObject(n,{metaTokens:!0,dots:!1,indexes:!1},!1,function(e,t){return!q.isUndefined(t[e])});let r=n.metaTokens,i=n.visitor||l,a=n.dots,o=n.indexes,s=(n.Blob||typeof Blob<`u`&&Blob)&&q.isSpecCompliantForm(t);if(!q.isFunction(i))throw TypeError(`visitor must be a function`);function c(e){if(e===null)return``;if(q.isDate(e))return e.toISOString();if(q.isBoolean(e))return e.toString();if(!s&&q.isBlob(e))throw new J(`Blob is not supported. Use a Buffer instead.`);return q.isArrayBuffer(e)||q.isTypedArray(e)?s&&typeof Blob==`function`?new Blob([e]):Buffer.from(e):e}function l(e,n,i){let s=e;if(q.isReactNative(t)&&q.isReactNativeBlob(e))return t.append(Tc(i,n,a),c(e)),!1;if(e&&!i&&typeof e==`object`){if(q.endsWith(n,`{}`))n=r?n:n.slice(0,-2),e=JSON.stringify(e);else if(q.isArray(e)&&Ec(e)||(q.isFileList(e)||q.endsWith(n,`[]`))&&(s=q.toArray(e)))return n=wc(n),s.forEach(function(e,r){!(q.isUndefined(e)||e===null)&&t.append(o===!0?Tc([n],r,a):o===null?n:n+`[]`,c(e))}),!1}return Cc(e)?!0:(t.append(Tc(i,n,a),c(e)),!1)}let u=[],d=Object.assign(Dc,{defaultVisitor:l,convertValue:c,isVisitable:Cc});function f(e,n){if(!q.isUndefined(e)){if(u.indexOf(e)!==-1)throw Error(`Circular reference detected in `+n.join(`.`));u.push(e),q.forEach(e,function(e,r){(!(q.isUndefined(e)||e===null)&&i.call(t,e,q.isString(r)?r.trim():r,n,d))===!0&&f(e,n?n.concat(r):[r])}),u.pop()}}if(!q.isObject(e))throw TypeError(`data must be an object`);return f(e),t}function kc(e){let t={"!":`%21`,"'":`%27`,"(":`%28`,")":`%29`,"~":`%7E`,"%20":`+`,"%00":`\0`};return encodeURIComponent(e).replace(/[!'()~]|%20|%00/g,function(e){return t[e]})}function Ac(e,t){this._pairs=[],e&&Oc(e,this,t)}var jc=Ac.prototype;jc.append=function(e,t){this._pairs.push([e,t])},jc.toString=function(e){let t=e?function(t){return e.call(this,t,kc)}:kc;return this._pairs.map(function(e){return t(e[0])+`=`+t(e[1])},``).join(`&`)};function Mc(e){return encodeURIComponent(e).replace(/%3A/gi,`:`).replace(/%24/g,`$`).replace(/%2C/gi,`,`).replace(/%20/g,`+`)}function Nc(e,t,n){if(!t)return e;let r=n&&n.encode||Mc,i=q.isFunction(n)?{serialize:n}:n,a=i&&i.serialize,o;if(o=a?a(t,i):q.isURLSearchParams(t)?t.toString():new Ac(t,i).toString(r),o){let t=e.indexOf(`#`);t!==-1&&(e=e.slice(0,t)),e+=(e.indexOf(`?`)===-1?`?`:`&`)+o}return e}var Pc=class{constructor(){this.handlers=[]}use(e,t,n){return this.handlers.push({fulfilled:e,rejected:t,synchronous:n?n.synchronous:!1,runWhen:n?n.runWhen:null}),this.handlers.length-1}eject(e){this.handlers[e]&&(this.handlers[e]=null)}clear(){this.handlers&&=[]}forEach(e){q.forEach(this.handlers,function(t){t!==null&&e(t)})}},Fc={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1,legacyInterceptorReqResOrdering:!0},Ic={isBrowser:!0,classes:{URLSearchParams:typeof URLSearchParams<`u`?URLSearchParams:Ac,FormData:typeof FormData<`u`?FormData:null,Blob:typeof Blob<`u`?Blob:null},protocols:[`http`,`https`,`file`,`blob`,`url`,`data`]},Lc=t({hasBrowserEnv:()=>Rc,hasStandardBrowserEnv:()=>Bc,hasStandardBrowserWebWorkerEnv:()=>Vc,navigator:()=>zc,origin:()=>Hc}),Rc=typeof window<`u`&&typeof document<`u`,zc=typeof navigator==`object`&&navigator||void 0,Bc=Rc&&(!zc||[`ReactNative`,`NativeScript`,`NS`].indexOf(zc.product)<0),Vc=typeof WorkerGlobalScope<`u`&&self instanceof WorkerGlobalScope&&typeof self.importScripts==`function`,Hc=Rc&&window.location.href||`http://localhost`,Y={...Lc,...Ic};function Uc(e,t){return Oc(e,new Y.classes.URLSearchParams,{visitor:function(e,t,n,r){return Y.isNode&&q.isBuffer(e)?(this.append(t,e.toString(`base64`)),!1):r.defaultVisitor.apply(this,arguments)},...t})}function Wc(e){return q.matchAll(/\w+|\[(\w*)]/g,e).map(e=>e[0]===`[]`?``:e[1]||e[0])}function Gc(e){let t={},n=Object.keys(e),r,i=n.length,a;for(r=0;r=e.length;return a=!a&&q.isArray(r)?r.length:a,s?(q.hasOwnProp(r,a)?r[a]=[r[a],n]:r[a]=n,!o):((!r[a]||!q.isObject(r[a]))&&(r[a]=[]),t(e,n,r[a],i)&&q.isArray(r[a])&&(r[a]=Gc(r[a])),!o)}if(q.isFormData(e)&&q.isFunction(e.entries)){let n={};return q.forEachEntry(e,(e,r)=>{t(Wc(e),r,n,0)}),n}return null}function qc(e,t,n){if(q.isString(e))try{return(t||JSON.parse)(e),q.trim(e)}catch(e){if(e.name!==`SyntaxError`)throw e}return(n||JSON.stringify)(e)}var Jc={transitional:Fc,adapter:[`xhr`,`http`,`fetch`],transformRequest:[function(e,t){let n=t.getContentType()||``,r=n.indexOf(`application/json`)>-1,i=q.isObject(e);if(i&&q.isHTMLForm(e)&&(e=new FormData(e)),q.isFormData(e))return r?JSON.stringify(Kc(e)):e;if(q.isArrayBuffer(e)||q.isBuffer(e)||q.isStream(e)||q.isFile(e)||q.isBlob(e)||q.isReadableStream(e))return e;if(q.isArrayBufferView(e))return e.buffer;if(q.isURLSearchParams(e))return t.setContentType(`application/x-www-form-urlencoded;charset=utf-8`,!1),e.toString();let a;if(i){if(n.indexOf(`application/x-www-form-urlencoded`)>-1)return Uc(e,this.formSerializer).toString();if((a=q.isFileList(e))||n.indexOf(`multipart/form-data`)>-1){let t=this.env&&this.env.FormData;return Oc(a?{"files[]":e}:e,t&&new t,this.formSerializer)}}return i||r?(t.setContentType(`application/json`,!1),qc(e)):e}],transformResponse:[function(e){let t=this.transitional||Jc.transitional,n=t&&t.forcedJSONParsing,r=this.responseType===`json`;if(q.isResponse(e)||q.isReadableStream(e))return e;if(e&&q.isString(e)&&(n&&!this.responseType||r)){let n=!(t&&t.silentJSONParsing)&&r;try{return JSON.parse(e,this.parseReviver)}catch(e){if(n)throw e.name===`SyntaxError`?J.from(e,J.ERR_BAD_RESPONSE,this,null,this.response):e}}return e}],timeout:0,xsrfCookieName:`XSRF-TOKEN`,xsrfHeaderName:`X-XSRF-TOKEN`,maxContentLength:-1,maxBodyLength:-1,env:{FormData:Y.classes.FormData,Blob:Y.classes.Blob},validateStatus:function(e){return e>=200&&e<300},headers:{common:{Accept:`application/json, text/plain, */*`,"Content-Type":void 0}}};q.forEach([`delete`,`get`,`head`,`post`,`put`,`patch`],e=>{Jc.headers[e]={}});var Yc=q.toObjectSet([`age`,`authorization`,`content-length`,`content-type`,`etag`,`expires`,`from`,`host`,`if-modified-since`,`if-unmodified-since`,`last-modified`,`location`,`max-forwards`,`proxy-authorization`,`referer`,`retry-after`,`user-agent`]),Xc=e=>{let t={},n,r,i;return e&&e.split(`
+`).forEach(function(e){i=e.indexOf(`:`),n=e.substring(0,i).trim().toLowerCase(),r=e.substring(i+1).trim(),!(!n||t[n]&&Yc[n])&&(n===`set-cookie`?t[n]?t[n].push(r):t[n]=[r]:t[n]=t[n]?t[n]+`, `+r:r)}),t},Zc=Symbol(`internals`);function Qc(e){return e&&String(e).trim().toLowerCase()}function $c(e){return e===!1||e==null?e:q.isArray(e)?e.map($c):String(e)}function el(e){let t=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g,r;for(;r=n.exec(e);)t[r[1]]=r[2];return t}var tl=e=>/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(e.trim());function nl(e,t,n,r,i){if(q.isFunction(r))return r.call(this,t,n);if(i&&(t=n),q.isString(t)){if(q.isString(r))return t.indexOf(r)!==-1;if(q.isRegExp(r))return r.test(t)}}function rl(e){return e.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(e,t,n)=>t.toUpperCase()+n)}function il(e,t){let n=q.toCamelCase(` `+t);[`get`,`set`,`has`].forEach(r=>{Object.defineProperty(e,r+n,{value:function(e,n,i){return this[r].call(this,t,e,n,i)},configurable:!0})})}var X=class{constructor(e){e&&this.set(e)}set(e,t,n){let r=this;function i(e,t,n){let i=Qc(t);if(!i)throw Error(`header name must be a non-empty string`);let a=q.findKey(r,i);(!a||r[a]===void 0||n===!0||n===void 0&&r[a]!==!1)&&(r[a||t]=$c(e))}let a=(e,t)=>q.forEach(e,(e,n)=>i(e,n,t));if(q.isPlainObject(e)||e instanceof this.constructor)a(e,t);else if(q.isString(e)&&(e=e.trim())&&!tl(e))a(Xc(e),t);else if(q.isObject(e)&&q.isIterable(e)){let n={},r,i;for(let t of e){if(!q.isArray(t))throw TypeError(`Object iterator must return a key-value pair`);n[i=t[0]]=(r=n[i])?q.isArray(r)?[...r,t[1]]:[r,t[1]]:t[1]}a(n,t)}else e!=null&&i(t,e,n);return this}get(e,t){if(e=Qc(e),e){let n=q.findKey(this,e);if(n){let e=this[n];if(!t)return e;if(t===!0)return el(e);if(q.isFunction(t))return t.call(this,e,n);if(q.isRegExp(t))return t.exec(e);throw TypeError(`parser must be boolean|regexp|function`)}}}has(e,t){if(e=Qc(e),e){let n=q.findKey(this,e);return!!(n&&this[n]!==void 0&&(!t||nl(this,this[n],n,t)))}return!1}delete(e,t){let n=this,r=!1;function i(e){if(e=Qc(e),e){let i=q.findKey(n,e);i&&(!t||nl(n,n[i],i,t))&&(delete n[i],r=!0)}}return q.isArray(e)?e.forEach(i):i(e),r}clear(e){let t=Object.keys(this),n=t.length,r=!1;for(;n--;){let i=t[n];(!e||nl(this,this[i],i,e,!0))&&(delete this[i],r=!0)}return r}normalize(e){let t=this,n={};return q.forEach(this,(r,i)=>{let a=q.findKey(n,i);if(a){t[a]=$c(r),delete t[i];return}let o=e?rl(i):String(i).trim();o!==i&&delete t[i],t[o]=$c(r),n[o]=!0}),this}concat(...e){return this.constructor.concat(this,...e)}toJSON(e){let t=Object.create(null);return q.forEach(this,(n,r)=>{n!=null&&n!==!1&&(t[r]=e&&q.isArray(n)?n.join(`, `):n)}),t}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map(([e,t])=>e+`: `+t).join(`
+`)}getSetCookie(){return this.get(`set-cookie`)||[]}get[Symbol.toStringTag](){return`AxiosHeaders`}static from(e){return e instanceof this?e:new this(e)}static concat(e,...t){let n=new this(e);return t.forEach(e=>n.set(e)),n}static accessor(e){let t=(this[Zc]=this[Zc]={accessors:{}}).accessors,n=this.prototype;function r(e){let r=Qc(e);t[r]||(il(n,e),t[r]=!0)}return q.isArray(e)?e.forEach(r):r(e),this}};X.accessor([`Content-Type`,`Content-Length`,`Accept`,`Accept-Encoding`,`User-Agent`,`Authorization`]),q.reduceDescriptors(X.prototype,({value:e},t)=>{let n=t[0].toUpperCase()+t.slice(1);return{get:()=>e,set(e){this[n]=e}}}),q.freezeMethods(X);function al(e,t){let n=this||Jc,r=t||n,i=X.from(r.headers),a=r.data;return q.forEach(e,function(e){a=e.call(n,a,i.normalize(),t?t.status:void 0)}),i.normalize(),a}function ol(e){return!!(e&&e.__CANCEL__)}var sl=class extends J{constructor(e,t,n){super(e??`canceled`,J.ERR_CANCELED,t,n),this.name=`CanceledError`,this.__CANCEL__=!0}};function cl(e,t,n){let r=n.config.validateStatus;!n.status||!r||r(n.status)?e(n):t(new J(`Request failed with status code `+n.status,[J.ERR_BAD_REQUEST,J.ERR_BAD_RESPONSE][Math.floor(n.status/100)-4],n.config,n.request,n))}function ll(e){let t=/^([-+\w]{1,25})(:?\/\/|:)/.exec(e);return t&&t[1]||``}function ul(e,t){e||=10;let n=Array(e),r=Array(e),i=0,a=0,o;return t=t===void 0?1e3:t,function(s){let c=Date.now(),l=r[a];o||=c,n[i]=s,r[i]=c;let u=a,d=0;for(;u!==i;)d+=n[u++],u%=e;if(i=(i+1)%e,i===a&&(a=(a+1)%e),c-o{n=r,i=null,a&&=(clearTimeout(a),null),e(...t)};return[(...e)=>{let t=Date.now(),s=t-n;s>=r?o(e,t):(i=e,a||=setTimeout(()=>{a=null,o(i)},r-s))},()=>i&&o(i)]}var fl=(e,t,n=3)=>{let r=0,i=ul(50,250);return dl(n=>{let a=n.loaded,o=n.lengthComputable?n.total:void 0,s=a-r,c=i(s),l=a<=o;r=a,e({loaded:a,total:o,progress:o?a/o:void 0,bytes:s,rate:c||void 0,estimated:c&&o&&l?(o-a)/c:void 0,event:n,lengthComputable:o!=null,[t?`download`:`upload`]:!0})},n)},pl=(e,t)=>{let n=e!=null;return[r=>t[0]({lengthComputable:n,total:e,loaded:r}),t[1]]},ml=e=>(...t)=>q.asap(()=>e(...t)),hl=Y.hasStandardBrowserEnv?((e,t)=>n=>(n=new URL(n,Y.origin),e.protocol===n.protocol&&e.host===n.host&&(t||e.port===n.port)))(new URL(Y.origin),Y.navigator&&/(msie|trident)/i.test(Y.navigator.userAgent)):()=>!0,gl=Y.hasStandardBrowserEnv?{write(e,t,n,r,i,a,o){if(typeof document>`u`)return;let s=[`${e}=${encodeURIComponent(t)}`];q.isNumber(n)&&s.push(`expires=${new Date(n).toUTCString()}`),q.isString(r)&&s.push(`path=${r}`),q.isString(i)&&s.push(`domain=${i}`),a===!0&&s.push(`secure`),q.isString(o)&&s.push(`SameSite=${o}`),document.cookie=s.join(`; `)},read(e){if(typeof document>`u`)return null;let t=document.cookie.match(RegExp(`(?:^|; )`+e+`=([^;]*)`));return t?decodeURIComponent(t[1]):null},remove(e){this.write(e,``,Date.now()-864e5,`/`)}}:{write(){},read(){return null},remove(){}};function _l(e){return typeof e==`string`?/^([a-z][a-z\d+\-.]*:)?\/\//i.test(e):!1}function vl(e,t){return t?e.replace(/\/?\/$/,``)+`/`+t.replace(/^\/+/,``):e}function yl(e,t,n){let r=!_l(t);return e&&(r||n==0)?vl(e,t):t}var bl=e=>e instanceof X?{...e}:e;function xl(e,t){t||={};let n={};function r(e,t,n,r){return q.isPlainObject(e)&&q.isPlainObject(t)?q.merge.call({caseless:r},e,t):q.isPlainObject(t)?q.merge({},t):q.isArray(t)?t.slice():t}function i(e,t,n,i){if(!q.isUndefined(t))return r(e,t,n,i);if(!q.isUndefined(e))return r(void 0,e,n,i)}function a(e,t){if(!q.isUndefined(t))return r(void 0,t)}function o(e,t){if(!q.isUndefined(t))return r(void 0,t);if(!q.isUndefined(e))return r(void 0,e)}function s(n,i,a){if(a in t)return r(n,i);if(a in e)return r(void 0,n)}let c={url:a,method:a,data:a,baseURL:o,transformRequest:o,transformResponse:o,paramsSerializer:o,timeout:o,timeoutMessage:o,withCredentials:o,withXSRFToken:o,adapter:o,responseType:o,xsrfCookieName:o,xsrfHeaderName:o,onUploadProgress:o,onDownloadProgress:o,decompress:o,maxContentLength:o,maxBodyLength:o,beforeRedirect:o,transport:o,httpAgent:o,httpsAgent:o,cancelToken:o,socketPath:o,responseEncoding:o,validateStatus:s,headers:(e,t,n)=>i(bl(e),bl(t),n,!0)};return q.forEach(Object.keys({...e,...t}),function(r){if(r===`__proto__`||r===`constructor`||r===`prototype`)return;let a=q.hasOwnProp(c,r)?c[r]:i,o=a(e[r],t[r],r);q.isUndefined(o)&&a!==s||(n[r]=o)}),n}var Sl=e=>{let t=xl({},e),{data:n,withXSRFToken:r,xsrfHeaderName:i,xsrfCookieName:a,headers:o,auth:s}=t;if(t.headers=o=X.from(o),t.url=Nc(yl(t.baseURL,t.url,t.allowAbsoluteUrls),e.params,e.paramsSerializer),s&&o.set(`Authorization`,`Basic `+btoa((s.username||``)+`:`+(s.password?unescape(encodeURIComponent(s.password)):``))),q.isFormData(n)){if(Y.hasStandardBrowserEnv||Y.hasStandardBrowserWebWorkerEnv)o.setContentType(void 0);else if(q.isFunction(n.getHeaders)){let e=n.getHeaders(),t=[`content-type`,`content-length`];Object.entries(e).forEach(([e,n])=>{t.includes(e.toLowerCase())&&o.set(e,n)})}}if(Y.hasStandardBrowserEnv&&(r&&q.isFunction(r)&&(r=r(t)),r||r!==!1&&hl(t.url))){let e=i&&a&&gl.read(a);e&&o.set(i,e)}return t},Cl=typeof XMLHttpRequest<`u`&&function(e){return new Promise(function(t,n){let r=Sl(e),i=r.data,a=X.from(r.headers).normalize(),{responseType:o,onUploadProgress:s,onDownloadProgress:c}=r,l,u,d,f,p;function m(){f&&f(),p&&p(),r.cancelToken&&r.cancelToken.unsubscribe(l),r.signal&&r.signal.removeEventListener(`abort`,l)}let h=new XMLHttpRequest;h.open(r.method.toUpperCase(),r.url,!0),h.timeout=r.timeout;function g(){if(!h)return;let r=X.from(`getAllResponseHeaders`in h&&h.getAllResponseHeaders());cl(function(e){t(e),m()},function(e){n(e),m()},{data:!o||o===`text`||o===`json`?h.responseText:h.response,status:h.status,statusText:h.statusText,headers:r,config:e,request:h}),h=null}`onloadend`in h?h.onloadend=g:h.onreadystatechange=function(){!h||h.readyState!==4||h.status===0&&!(h.responseURL&&h.responseURL.indexOf(`file:`)===0)||setTimeout(g)},h.onabort=function(){h&&=(n(new J(`Request aborted`,J.ECONNABORTED,e,h)),null)},h.onerror=function(t){let r=new J(t&&t.message?t.message:`Network Error`,J.ERR_NETWORK,e,h);r.event=t||null,n(r),h=null},h.ontimeout=function(){let t=r.timeout?`timeout of `+r.timeout+`ms exceeded`:`timeout exceeded`,i=r.transitional||Fc;r.timeoutErrorMessage&&(t=r.timeoutErrorMessage),n(new J(t,i.clarifyTimeoutError?J.ETIMEDOUT:J.ECONNABORTED,e,h)),h=null},i===void 0&&a.setContentType(null),`setRequestHeader`in h&&q.forEach(a.toJSON(),function(e,t){h.setRequestHeader(t,e)}),q.isUndefined(r.withCredentials)||(h.withCredentials=!!r.withCredentials),o&&o!==`json`&&(h.responseType=r.responseType),c&&([d,p]=fl(c,!0),h.addEventListener(`progress`,d)),s&&h.upload&&([u,f]=fl(s),h.upload.addEventListener(`progress`,u),h.upload.addEventListener(`loadend`,f)),(r.cancelToken||r.signal)&&(l=t=>{h&&=(n(!t||t.type?new sl(null,e,h):t),h.abort(),null)},r.cancelToken&&r.cancelToken.subscribe(l),r.signal&&(r.signal.aborted?l():r.signal.addEventListener(`abort`,l)));let _=ll(r.url);if(_&&Y.protocols.indexOf(_)===-1){n(new J(`Unsupported protocol `+_+`:`,J.ERR_BAD_REQUEST,e));return}h.send(i||null)})},wl=(e,t)=>{let{length:n}=e=e?e.filter(Boolean):[];if(t||n){let n=new AbortController,r,i=function(e){if(!r){r=!0,o();let t=e instanceof Error?e:this.reason;n.abort(t instanceof J?t:new sl(t instanceof Error?t.message:t))}},a=t&&setTimeout(()=>{a=null,i(new J(`timeout of ${t}ms exceeded`,J.ETIMEDOUT))},t),o=()=>{e&&=(a&&clearTimeout(a),a=null,e.forEach(e=>{e.unsubscribe?e.unsubscribe(i):e.removeEventListener(`abort`,i)}),null)};e.forEach(e=>e.addEventListener(`abort`,i));let{signal:s}=n;return s.unsubscribe=()=>q.asap(o),s}},Tl=function*(e,t){let n=e.byteLength;if(!t||n{let i=El(e,t),a=0,o,s=e=>{o||(o=!0,r&&r(e))};return new ReadableStream({async pull(e){try{let{done:t,value:r}=await i.next();if(t){s(),e.close();return}let o=r.byteLength;n&&n(a+=o),e.enqueue(new Uint8Array(r))}catch(e){throw s(e),e}},cancel(e){return s(e),i.return()}},{highWaterMark:2})},kl=64*1024,{isFunction:Al}=q,jl=(({Request:e,Response:t})=>({Request:e,Response:t}))(q.global),{ReadableStream:Ml,TextEncoder:Nl}=q.global,Pl=(e,...t)=>{try{return!!e(...t)}catch{return!1}},Fl=e=>{e=q.merge.call({skipUndefined:!0},jl,e);let{fetch:t,Request:n,Response:r}=e,i=t?Al(t):typeof fetch==`function`,a=Al(n),o=Al(r);if(!i)return!1;let s=i&&Al(Ml),c=i&&(typeof Nl==`function`?(e=>t=>e.encode(t))(new Nl):async e=>new Uint8Array(await new n(e).arrayBuffer())),l=a&&s&&Pl(()=>{let e=!1,t=new n(Y.origin,{body:new Ml,method:`POST`,get duplex(){return e=!0,`half`}}).headers.has(`Content-Type`);return e&&!t}),u=o&&s&&Pl(()=>q.isReadableStream(new r(``).body)),d={stream:u&&(e=>e.body)};i&&[`text`,`arrayBuffer`,`blob`,`formData`,`stream`].forEach(e=>{!d[e]&&(d[e]=(t,n)=>{let r=t&&t[e];if(r)return r.call(t);throw new J(`Response type '${e}' is not supported`,J.ERR_NOT_SUPPORT,n)})});let f=async e=>{if(e==null)return 0;if(q.isBlob(e))return e.size;if(q.isSpecCompliantForm(e))return(await new n(Y.origin,{method:`POST`,body:e}).arrayBuffer()).byteLength;if(q.isArrayBufferView(e)||q.isArrayBuffer(e))return e.byteLength;if(q.isURLSearchParams(e)&&(e+=``),q.isString(e))return(await c(e)).byteLength},p=async(e,t)=>q.toFiniteNumber(e.getContentLength())??f(t);return async e=>{let{url:i,method:o,data:s,signal:c,cancelToken:f,timeout:m,onDownloadProgress:h,onUploadProgress:g,responseType:_,headers:v,withCredentials:y=`same-origin`,fetchOptions:b}=Sl(e),x=t||fetch;_=_?(_+``).toLowerCase():`text`;let S=wl([c,f&&f.toAbortSignal()],m),C=null,w=S&&S.unsubscribe&&(()=>{S.unsubscribe()}),T;try{if(g&&l&&o!==`get`&&o!==`head`&&(T=await p(v,s))!==0){let e=new n(i,{method:`POST`,body:s,duplex:`half`}),t;if(q.isFormData(s)&&(t=e.headers.get(`content-type`))&&v.setContentType(t),e.body){let[t,n]=pl(T,fl(ml(g)));s=Ol(e.body,kl,t,n)}}q.isString(y)||(y=y?`include`:`omit`);let t=a&&`credentials`in n.prototype,c={...b,signal:S,method:o.toUpperCase(),headers:v.normalize().toJSON(),body:s,duplex:`half`,credentials:t?y:void 0};C=a&&new n(i,c);let f=await(a?x(C,b):x(i,c)),m=u&&(_===`stream`||_===`response`);if(u&&(h||m&&w)){let e={};[`status`,`statusText`,`headers`].forEach(t=>{e[t]=f[t]});let t=q.toFiniteNumber(f.headers.get(`content-length`)),[n,i]=h&&pl(t,fl(ml(h),!0))||[];f=new r(Ol(f.body,kl,n,()=>{i&&i(),w&&w()}),e)}_||=`text`;let ee=await d[q.findKey(d,_)||`text`](f,e);return!m&&w&&w(),await new Promise((t,n)=>{cl(t,n,{data:ee,headers:X.from(f.headers),status:f.status,statusText:f.statusText,config:e,request:C})})}catch(t){throw w&&w(),t&&t.name===`TypeError`&&/Load failed|fetch/i.test(t.message)?Object.assign(new J(`Network Error`,J.ERR_NETWORK,e,C,t&&t.response),{cause:t.cause||t}):J.from(t,t&&t.code,e,C,t&&t.response)}}},Il=new Map,Ll=e=>{let t=e&&e.env||{},{fetch:n,Request:r,Response:i}=t,a=[r,i,n],o=a.length,s,c,l=Il;for(;o--;)s=a[o],c=l.get(s),c===void 0&&l.set(s,c=o?new Map:Fl(t)),l=c;return c};Ll();var Rl={http:null,xhr:Cl,fetch:{get:Ll}};q.forEach(Rl,(e,t)=>{if(e){try{Object.defineProperty(e,`name`,{value:t})}catch{}Object.defineProperty(e,`adapterName`,{value:t})}});var zl=e=>`- ${e}`,Bl=e=>q.isFunction(e)||e===null||e===!1;function Vl(e,t){e=q.isArray(e)?e:[e];let{length:n}=e,r,i,a={};for(let o=0;o`adapter ${e} `+(t===!1?`is not supported by the environment`:`is not available in the build`));throw new J(`There is no suitable adapter to dispatch the request `+(n?e.length>1?`since :
+`+e.map(zl).join(`
+`):` `+zl(e[0]):`as no adapter specified`),`ERR_NOT_SUPPORT`)}return i}var Hl={getAdapter:Vl,adapters:Rl};function Ul(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw new sl(null,e)}function Wl(e){return Ul(e),e.headers=X.from(e.headers),e.data=al.call(e,e.transformRequest),[`post`,`put`,`patch`].indexOf(e.method)!==-1&&e.headers.setContentType(`application/x-www-form-urlencoded`,!1),Hl.getAdapter(e.adapter||Jc.adapter,e)(e).then(function(t){return Ul(e),t.data=al.call(e,e.transformResponse,t),t.headers=X.from(t.headers),t},function(t){return ol(t)||(Ul(e),t&&t.response&&(t.response.data=al.call(e,e.transformResponse,t.response),t.response.headers=X.from(t.response.headers))),Promise.reject(t)})}var Gl=`1.13.6`,Kl={};[`object`,`boolean`,`number`,`function`,`string`,`symbol`].forEach((e,t)=>{Kl[e]=function(n){return typeof n===e||`a`+(t<1?`n `:` `)+e}});var ql={};Kl.transitional=function(e,t,n){function r(e,t){return`[Axios v`+Gl+`] Transitional option '`+e+`'`+t+(n?`. `+n:``)}return(n,i,a)=>{if(e===!1)throw new J(r(i,` has been removed`+(t?` in `+t:``)),J.ERR_DEPRECATED);return t&&!ql[i]&&(ql[i]=!0,console.warn(r(i,` has been deprecated since v`+t+` and will be removed in the near future`))),e?e(n,i,a):!0}},Kl.spelling=function(e){return(t,n)=>(console.warn(`${n} is likely a misspelling of ${e}`),!0)};function Jl(e,t,n){if(typeof e!=`object`)throw new J(`options must be an object`,J.ERR_BAD_OPTION_VALUE);let r=Object.keys(e),i=r.length;for(;i-- >0;){let a=r[i],o=t[a];if(o){let t=e[a],n=t===void 0||o(t,a,e);if(n!==!0)throw new J(`option `+a+` must be `+n,J.ERR_BAD_OPTION_VALUE);continue}if(n!==!0)throw new J(`Unknown option `+a,J.ERR_BAD_OPTION)}}var Yl={assertOptions:Jl,validators:Kl},Xl=Yl.validators,Zl=class{constructor(e){this.defaults=e||{},this.interceptors={request:new Pc,response:new Pc}}async request(e,t){try{return await this._request(e,t)}catch(e){if(e instanceof Error){let t={};Error.captureStackTrace?Error.captureStackTrace(t):t=Error();let n=t.stack?t.stack.replace(/^.+\n/,``):``;try{e.stack?n&&!String(e.stack).endsWith(n.replace(/^.+\n.+\n/,``))&&(e.stack+=`
+`+n):e.stack=n}catch{}}throw e}}_request(e,t){typeof e==`string`?(t||={},t.url=e):t=e||{},t=xl(this.defaults,t);let{transitional:n,paramsSerializer:r,headers:i}=t;n!==void 0&&Yl.assertOptions(n,{silentJSONParsing:Xl.transitional(Xl.boolean),forcedJSONParsing:Xl.transitional(Xl.boolean),clarifyTimeoutError:Xl.transitional(Xl.boolean),legacyInterceptorReqResOrdering:Xl.transitional(Xl.boolean)},!1),r!=null&&(q.isFunction(r)?t.paramsSerializer={serialize:r}:Yl.assertOptions(r,{encode:Xl.function,serialize:Xl.function},!0)),t.allowAbsoluteUrls!==void 0||(this.defaults.allowAbsoluteUrls===void 0?t.allowAbsoluteUrls=!0:t.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls),Yl.assertOptions(t,{baseUrl:Xl.spelling(`baseURL`),withXsrfToken:Xl.spelling(`withXSRFToken`)},!0),t.method=(t.method||this.defaults.method||`get`).toLowerCase();let a=i&&q.merge(i.common,i[t.method]);i&&q.forEach([`delete`,`get`,`head`,`post`,`put`,`patch`,`common`],e=>{delete i[e]}),t.headers=X.concat(a,i);let o=[],s=!0;this.interceptors.request.forEach(function(e){if(typeof e.runWhen==`function`&&e.runWhen(t)===!1)return;s&&=e.synchronous;let n=t.transitional||Fc;n&&n.legacyInterceptorReqResOrdering?o.unshift(e.fulfilled,e.rejected):o.push(e.fulfilled,e.rejected)});let c=[];this.interceptors.response.forEach(function(e){c.push(e.fulfilled,e.rejected)});let l,u=0,d;if(!s){let e=[Wl.bind(this),void 0];for(e.unshift(...o),e.push(...c),d=e.length,l=Promise.resolve(t);u{if(!n._listeners)return;let t=n._listeners.length;for(;t-- >0;)n._listeners[t](e);n._listeners=null}),this.promise.then=e=>{let t,r=new Promise(e=>{n.subscribe(e),t=e}).then(e);return r.cancel=function(){n.unsubscribe(t)},r},e(function(e,r,i){n.reason||(n.reason=new sl(e,r,i),t(n.reason))})}throwIfRequested(){if(this.reason)throw this.reason}subscribe(e){if(this.reason){e(this.reason);return}this._listeners?this._listeners.push(e):this._listeners=[e]}unsubscribe(e){if(!this._listeners)return;let t=this._listeners.indexOf(e);t!==-1&&this._listeners.splice(t,1)}toAbortSignal(){let e=new AbortController,t=t=>{e.abort(t)};return this.subscribe(t),e.signal.unsubscribe=()=>this.unsubscribe(t),e.signal}static source(){let t;return{token:new e(function(e){t=e}),cancel:t}}};function $l(e){return function(t){return e.apply(null,t)}}function eu(e){return q.isObject(e)&&e.isAxiosError===!0}var tu={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511,WebServerIsDown:521,ConnectionTimedOut:522,OriginIsUnreachable:523,TimeoutOccurred:524,SslHandshakeFailed:525,InvalidSslCertificate:526};Object.entries(tu).forEach(([e,t])=>{tu[t]=e});function nu(e){let t=new Zl(e),n=ps(Zl.prototype.request,t);return q.extend(n,Zl.prototype,t,{allOwnKeys:!0}),q.extend(n,t,null,{allOwnKeys:!0}),n.create=function(t){return nu(xl(e,t))},n}var Z=nu(Jc);Z.Axios=Zl,Z.CanceledError=sl,Z.CancelToken=Ql,Z.isCancel=ol,Z.VERSION=Gl,Z.toFormData=Oc,Z.AxiosError=J,Z.Cancel=Z.CanceledError,Z.all=function(e){return Promise.all(e)},Z.spread=$l,Z.isAxiosError=eu,Z.mergeConfig=xl,Z.AxiosHeaders=X,Z.formToJSON=e=>Kc(q.isHTMLForm(e)?new FormData(e):e),Z.getAdapter=Hl.getAdapter,Z.HttpStatusCode=tu,Z.default=Z;var ru=Z.create({baseURL:`/api`,timeout:1e4,headers:{"Content-Type":`application/json`}}),iu=(e,t=`error`)=>{window.showToast?window.showToast(e,t):window.alert(e)};ru.interceptors.response.use(e=>{let t=e.data;if(console.log(`API Response:`,e.config.url,t),t&&typeof t==`object`&&(t.success===!1||t.Success===!1)){let e=t.errors||t.Errors,n=t.message||t.Message,r=e&&Array.isArray(e)&&e.length>0?e.join(`
+`):n||`操作失败`;return console.error(`Business Error:`,r),iu(r,`error`),Promise.reject(Error(r))}return e},e=>{console.error(`API Error:`,e);let t=`网络错误,请稍后再试`,n=e?.response?.status;if(n===502||n===503||n===504)return t=`后端服务不可达:请确认 Hua.Todo.Host 已启动(http://localhost:5173)`,iu(t,`error`),Promise.reject(e);if(e.response&&e.response.data){let n=e.response.data,r=n.errors||n.Errors,i=n.message||n.Message;r&&Array.isArray(r)&&r.length>0?t=r.join(`
+`):i&&(t=i)}else e.message&&(t=e.message);return iu(t,`error`),Promise.reject(e)});var au=e=>{if(e===0||e===1||e===2)return e;if(typeof e==`number`&&Number.isFinite(e))return e<=0?0:e===1?1:2;if(typeof e==`string`){let t=e.trim();if(t===`0`||t===`1`||t===`2`)return Number(t);let n=t.toLowerCase();if(n===`low`)return 0;if(n===`medium`||n===`mid`)return 1;if(n===`high`)return 2}return 1},ou=e=>typeof e==`string`&&e.trim()?e:e instanceof Date&&Number.isFinite(e.getTime())?e.toISOString():typeof e==`number`&&Number.isFinite(e)?new Date(e).toISOString():new Date().toISOString(),su=e=>{let t={...e??{}};return typeof t.id==`string`&&/^\d+$/.test(t.id)&&(t.id=Number(t.id)),t.title=typeof t.title==`string`?t.title:String(t.title??``),t.priority=au(t.priority),t.isCompleted=typeof t.isCompleted==`boolean`?t.isCompleted:!!t.isCompleted,t.createdAt=ou(t.createdAt),t.updatedAt=ou(t.updatedAt),t.parentTaskId===null?t.parentTaskId=void 0:typeof t.parentTaskId==`string`&&/^\d+$/.test(t.parentTaskId)&&(t.parentTaskId=Number(t.parentTaskId)),Array.isArray(t.subTasks)?t.subTasks=t.subTasks.map(su):t.subTasks=[],t},cu=e=>Array.isArray(e)?e.map(su):[],lu=`Hua.Todo_tasks`,uu=`Hua.Todo_sync_status`,Q=class{static saveTasks(e){try{localStorage.setItem(lu,JSON.stringify(cu(e)))}catch(e){console.error(`Failed to save tasks to localStorage:`,e)}}static loadTasks(){try{let e=localStorage.getItem(lu);return e?cu(JSON.parse(e)):[]}catch(e){return console.error(`Failed to load tasks from localStorage:`,e),[]}}static clearTasks(){try{localStorage.removeItem(lu)}catch(e){console.error(`Failed to clear tasks from localStorage:`,e)}}static saveSyncStatus(e){try{localStorage.setItem(uu,JSON.stringify(e))}catch(e){console.error(`Failed to save sync status:`,e)}}static loadSyncStatus(){try{let e=localStorage.getItem(uu);return e?JSON.parse(e):{lastSyncTime:0,isOnline:!0,pendingChanges:0}}catch(e){return console.error(`Failed to load sync status:`,e),{lastSyncTime:0,isOnline:!0,pendingChanges:0}}}static isOnline(){return navigator.onLine}},du={async getTasks(e){if(!Q.isOnline()){let t=Q.loadTasks();return{success:!0,data:e===void 0?t:t.filter(t=>t.isCompleted===e),message:`从本地加载任务`}}let t=e===!0?`/task/completed`:e===!1?`/task/active`:`/task`,n=await ru.get(t),r;if(r=Array.isArray(n.data)?{success:!0,data:n.data,message:`获取任务成功`}:n.data,r.success&&r.data){r.data=cu(r.data),Q.saveTasks(r.data);let e=Q.loadSyncStatus();e.lastSyncTime=Date.now(),e.isOnline=!0,e.pendingChanges=0,Q.saveSyncStatus(e)}return r},async getTask(e){if(!Q.isOnline()){let t=Q.loadTasks().find(t=>t.id===e);return{success:!0,data:t||null,message:t?`从本地加载任务`:`任务不存在`}}let t=await ru.get(`/task/${e}`),n;return n=t.data&&`id`in t.data?{success:!0,data:t.data,message:`获取任务成功`}:t.data,n.success&&n.data&&(n.data=su(n.data)),n},async createTask(e){let t={id:Date.now(),title:e.title,priority:e.priority,isCompleted:!1,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString(),parentTaskId:e.parentTaskId,subTasks:[]};if(!Q.isOnline()){let e=Q.loadTasks();e.unshift(t),Q.saveTasks(e);let n=Q.loadSyncStatus();return n.pendingChanges++,Q.saveSyncStatus(n),{success:!0,data:t,message:`离线创建任务成功`}}let n=await ru.post(`/task`,e),r;if(r=n.data&&`id`in n.data?{success:!0,data:n.data,message:`创建任务成功`}:n.data,r.success&&r.data){r.data=su(r.data);let e=Q.loadTasks(),n=e.findIndex(e=>e.id===t.id);n===-1?e.unshift(r.data):e[n]=r.data,Q.saveTasks(e)}return r},async updateTask(e,t){let n=t;if(!Q.isOnline()){let n=Q.loadTasks(),r=n.findIndex(t=>t.id===e);if(r!==-1){t.title&&(n[r].title=t.title),t.priority!==void 0&&(n[r].priority=t.priority),n[r].updatedAt=new Date().toISOString(),Q.saveTasks(n);let e=Q.loadSyncStatus();return e.pendingChanges++,Q.saveSyncStatus(e),{success:!0,data:n[r],message:`离线更新任务成功`}}return{success:!1,message:`任务不存在`}}let r=await ru.put(`/task`,n),i;if(i=r.data&&`id`in r.data?{success:!0,data:r.data,message:`更新任务成功`}:r.data,i.success&&i.data){i.data=su(i.data);let t=Q.loadTasks(),n=t.findIndex(t=>t.id===e);n!==-1&&(t[n]=i.data,Q.saveTasks(t))}return i},async toggleComplete(e){if(!Q.isOnline()){let t=Q.loadTasks(),n=t.findIndex(t=>t.id===e);if(n!==-1){t[n].isCompleted=!t[n].isCompleted,t[n].updatedAt=new Date().toISOString(),Q.saveTasks(t);let e=Q.loadSyncStatus();return e.pendingChanges++,Q.saveSyncStatus(e),{success:!0,data:t[n],message:`离线切换任务状态成功`}}return{success:!1,message:`任务不存在`}}let t=await ru.patch(`/task/${e}/toggle`),n;if(n=t.data&&`id`in t.data?{success:!0,data:t.data,message:`切换任务状态成功`}:t.data,n.success&&n.data){n.data=su(n.data);let t=Q.loadTasks(),r=t.findIndex(t=>t.id===e);r!==-1&&(t[r]=n.data,Q.saveTasks(t))}return n},async deleteTask(e){if(!Q.isOnline()){let t=Q.loadTasks(),n=t.findIndex(t=>t.id===e);if(n!==-1){t.splice(n,1),Q.saveTasks(t);let e=Q.loadSyncStatus();return e.pendingChanges++,Q.saveSyncStatus(e),{success:!0,message:`离线删除任务成功`}}return{success:!1,message:`任务不存在`}}let t=await ru.delete(`/task/${e}`),n;if(n=t.data&&typeof t.data==`object`&&`success`in t.data?t.data:{success:!0,message:`删除任务成功`},n.success){let t=Q.loadTasks(),n=t.findIndex(t=>t.id===e);n!==-1&&(t.splice(n,1),Q.saveTasks(t))}return n},async syncToServer(){if(!Q.isOnline())return{success:!1,message:`当前离线,无法同步`};let e=Q.loadTasks(),t=Q.loadSyncStatus();if(t.pendingChanges===0)return{success:!0,data:e,message:`没有待同步的更改`};try{let e=await ru.get(`/task`),n;return n=Array.isArray(e.data)?{success:!0,data:e.data,message:`获取任务成功`}:e.data,n.success&&n.data?(n.data=cu(n.data),Q.saveTasks(n.data),t.lastSyncTime=Date.now(),t.isOnline=!0,t.pendingChanges=0,Q.saveSyncStatus(t),{success:!0,data:n.data,message:`同步成功`}):{success:!1,message:`同步失败`}}catch(e){return console.error(`Sync failed:`,e),{success:!1,message:`同步失败`}}}},fu=`Hua.Todo_cloud_sync_settings`,pu=`Hua.Todo_cloud_sync_session`,$=class{static loadSettings(){try{let e=localStorage.getItem(fu);if(!e)return{serverUrl:``,enabled:!1};let t=JSON.parse(e);return{serverUrl:typeof t.serverUrl==`string`?t.serverUrl:``,enabled:typeof t.enabled==`boolean`?t.enabled:!1}}catch{return{serverUrl:``,enabled:!1}}}static saveSettings(e){localStorage.setItem(fu,JSON.stringify(e))}static clearSettings(){localStorage.removeItem(fu)}static loadSession(){try{let e=sessionStorage.getItem(pu);if(!e)return null;let t=JSON.parse(e);return!t.accessToken||typeof t.accessToken!=`string`?null:{accessToken:t.accessToken,expiresAtUtc:typeof t.expiresAtUtc==`string`?t.expiresAtUtc:``,userId:typeof t.userId==`string`?t.userId:``,role:typeof t.role==`string`?t.role:``,permissions:Array.isArray(t.permissions)?t.permissions.filter(e=>typeof e==`string`):[]}}catch{return null}}static saveSession(e){sessionStorage.setItem(pu,JSON.stringify(e))}static clearSession(){sessionStorage.removeItem(pu)}},mu=(e,t=`error`)=>{window.showToast?window.showToast(e,t):window.alert(e)},hu=0,gu=()=>{let e=Date.now();e-hu<1500||(hu=e,window.dispatchEvent(new CustomEvent(`openCloudSyncSettings`)))},_u=Z.create({timeout:1e4,headers:{"Content-Type":`application/json`}});_u.interceptors.request.use(e=>{let{serverUrl:t}=$.loadSettings();t&&(e.baseURL=t);let n=$.loadSession();return n?.accessToken&&(e.headers=e.headers??{},e.headers.Authorization=`Bearer ${n.accessToken}`),e}),_u.interceptors.response.use(e=>e,e=>{let t=`网络错误,请稍后再试`,n=e?.response?.status;if(n===401||n===403)return $.clearSession(),gu(),t=n===401?`云同步会话已过期,请重新登录`:`云同步权限不足,请重新登录或联系管理员`,mu(t,`error`),Promise.reject(e);if(e?.response?.data){let n=e.response.data;if(typeof n==`string`&&n.trim())t=n;else if(n&&typeof n==`object`){let e=n.message??n.Message,r=n.errors??n.Errors;Array.isArray(r)&&r.length>0?t=r.join(`
+`):typeof e==`string`&&e.trim()&&(t=e)}}else typeof e?.message==`string`&&e.message.trim()&&(t=e.message);return mu(t,`error`),Promise.reject(e)});var vu=e=>{let t=new Map;for(let n of e)t.set(n.id,{id:n.id,title:n.title??``,priority:n.priority??1,isCompleted:!!n.isCompleted,createdAt:n.createdAtUtc,updatedAt:n.updatedAtUtc,parentTaskId:n.parentTaskId??void 0,subTasks:[]});let n=[];for(let e of t.values()){let r=e.parentTaskId;typeof r==`number`&&t.has(r)?t.get(r).subTasks.push(e):n.push(e)}return n},yu={async login(e){let t=(await _u.post(`/auth/login`,e)).data;return $.saveSession({accessToken:t.accessToken,expiresAtUtc:t.expiresAtUtc,userId:t.userId,role:t.role,permissions:Array.isArray(t.permissions)?t.permissions:[]}),t},logout(){$.clearSession()},async getTasks(){let e=await _u.get(`/tasks/`);return vu(Array.isArray(e.data)?e.data:[])}},bu={class:`dialog-content`},xu={class:`dialog-body`},Su={class:`form-group`},Cu={class:`form-group`},wu=ar({__name:`TaskEditDialog`,props:{visible:{type:Boolean},task:{}},emits:[`update:visible`,`saved`],setup(e,{emit:t}){let n=e,r=t,i=P(``),a=P(1);Rn(()=>n.task,e=>{e&&(i.value=e.title,a.value=e.priority)},{immediate:!0});let o=async()=>{if(!n.task||!i.value.trim()){alert(`请输入任务标题`);return}try{let e=await du.updateTask(n.task.id,{id:n.task.id,title:i.value.trim(),priority:a.value});e.success&&e.data&&(r(`saved`,e.data),r(`update:visible`,!1))}catch(e){console.error(`Failed to update task:`,e),alert(`更新任务失败`)}},s=()=>{r(`update:visible`,!1)};return(t,n)=>e.visible?(B(),V(`div`,{key:0,class:`dialog-overlay`,onClick:is(s,[`self`])},[H(`div`,bu,[H(`div`,{class:`dialog-header`},[n[2]||=H(`h2`,{class:`dialog-title`},`编辑任务`,-1),H(`button`,{onClick:s,class:`btn-close`},`×`)]),H(`div`,xu,[H(`div`,Su,[n[3]||=H(`label`,{class:`form-label`},`任务标题`,-1),I(H(`input`,{"onUpdate:modelValue":n[0]||=e=>i.value=e,type:`text`,placeholder:`输入任务标题...`,class:`form-input`,onKeyup:os(o,[`enter`])},null,544),[[Yo,i.value]])]),H(`div`,Cu,[n[5]||=H(`label`,{class:`form-label`},`优先级`,-1),I(H(`select`,{"onUpdate:modelValue":n[1]||=e=>a.value=e,class:`form-select`},[...n[4]||=[H(`option`,{value:``,disabled:``},`请选择优先级`,-1),H(`option`,{value:0},`低`,-1),H(`option`,{value:1},`中`,-1),H(`option`,{value:2},`高`,-1)]],512),[[Qo,a.value]])])]),H(`div`,{class:`dialog-footer`},[H(`button`,{onClick:s,class:`btn-cancel`},`取消`),H(`button`,{onClick:o,class:`btn-save`},`保存`)])])])):W(``,!0)}}),Tu=(e,t)=>{let n=e.__vccOpts||e;for(let[e,r]of t)n[e]=r;return n},Eu=Tu(wu,[[`__scopeId`,`data-v-fc0893aa`]]),Du=[`checked`,`disabled`],Ou=[`title`],ku={class:`expand-icon`},Au={class:`task-info`},ju={class:`task-title`},Mu={class:`task-meta`},Nu={class:`task-id task-id--compact`},Pu={class:`task-priority task-priority--compact`},Fu={class:`task-created`},Iu={class:`task-actions`},Lu={key:0,class:`add-subtask-form`},Ru={key:1,class:`subtasks`},zu=Tu(ar({__name:`TaskItem`,props:{task:{},readOnly:{type:Boolean}},emits:[`updated`,`deleted`,`subtask-created`],setup(e,{emit:t}){let n=e,r=La(()=>n.readOnly===!0),i=t,a=P(!1),o=P(!1),s=P(!1),c=P(``),l=P(1),u=P(null),d=async()=>{if(r.value){w();return}o.value=!0,await bn(),u.value&&u.value.focus()},f=La(()=>{switch(n.task.priority){case 0:return`低`;case 2:return`高`;default:return`中`}}),p=La(()=>f.value),m=e=>{let t=new Date(e);if(!Number.isFinite(t.getTime()))return``;let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:${n(t.getMinutes())}:${n(t.getSeconds())}`},h=La(()=>m(n.task.createdAt)),g=()=>{a.value=!a.value},_=async()=>{if(r.value){w();return}try{let e=await du.toggleComplete(n.task.id);e.success&&e.data&&i(`updated`,e.data)}catch(e){console.error(`Failed to toggle task:`,e)}},v=async()=>{if(r.value){w();return}try{(await du.deleteTask(n.task.id)).success&&i(`deleted`,n.task.id)}catch(e){console.error(`Failed to delete task:`,e)}},y=async()=>{if(r.value){w();return}if(!c.value.trim()){alert(`请输入子任务标题`);return}try{let e=await du.createTask({title:c.value.trim(),priority:l.value,parentTaskId:n.task.id});e.success&&e.data&&(i(`subtask-created`,e.data),o.value=!1,c.value=``,l.value=1)}catch(e){console.error(`Failed to create subtask:`,e)}},b=e=>{if(n.task.subTasks){let t=n.task.subTasks.findIndex(t=>t.id===e.id);t!==-1&&(n.task.subTasks[t]=e,i(`updated`,n.task))}},x=e=>{n.task.subTasks&&(n.task.subTasks=n.task.subTasks.filter(t=>t.id!==e),i(`updated`,n.task))},S=()=>{if(r.value){w();return}s.value=!0},C=e=>{i(`updated`,e)},w=()=>{window.showToast?window.showToast(`云同步模式为只读展示,编辑/新增将在后续版本补齐`,`error`):window.alert(`云同步模式为只读展示,编辑/新增将在后续版本补齐`)};return(t,n)=>{let i=Ar(`TaskItem`,!0);return B(),V(`div`,{class:ve([`task-item`,{completed:e.task.isCompleted,"priority-low":e.task.priority===0,"priority-medium":e.task.priority===1,"priority-high":e.task.priority===2}])},[H(`div`,{class:`task-content`,onDblclick:S},[H(`input`,{type:`checkbox`,checked:e.task.isCompleted,disabled:r.value,onChange:_,class:`task-checkbox`},null,40,Du),e.task.subTasks&&e.task.subTasks.length>0?(B(),V(`button`,{key:0,class:`task-expand`,onClick:is(g,[`stop`]),title:a.value?`收起`:`展开`},[H(`span`,ku,k(a.value?`▼`:`▶`),1)],8,Ou)):W(``,!0),r.value?W(``,!0):(B(),V(`button`,{key:1,onClick:d,class:`btn-add-subtask-icon`,title:`添加子任务`},[...n[5]||=[H(`svg`,{width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.5`},[H(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,d:`M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m3.75 9v6m3-3H9m1.5-12H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z`})],-1)]])),H(`div`,Au,[H(`span`,ju,k(e.task.title),1),H(`div`,Mu,[H(`span`,Nu,`#`+k(e.task.id),1),H(`span`,Pu,k(p.value),1),H(`span`,Fu,`创建`+k(h.value),1)])]),H(`div`,Iu,[r.value?W(``,!0):(B(),V(`button`,{key:0,onClick:S,class:`btn-edit-icon`,title:`编辑`},[...n[6]||=[H(`svg`,{width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`},[H(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,d:`M12 20h9`}),H(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,d:`M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5Z`})],-1)]])),r.value?W(``,!0):(B(),V(`button`,{key:1,onClick:v,class:`btn-delete-icon`,title:`删除`},[...n[7]||=[H(`svg`,{width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`},[H(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,d:`M6 18L18 6M6 6l12 12`})],-1)]]))])],32),o.value?(B(),V(`div`,Lu,[I(H(`input`,{ref_key:`subTaskInput`,ref:u,"onUpdate:modelValue":n[0]||=e=>c.value=e,type:`text`,placeholder:`输入子任务标题...`,onKeyup:os(y,[`enter`]),class:`subtask-input`},null,544),[[Yo,c.value]]),I(H(`select`,{"onUpdate:modelValue":n[1]||=e=>l.value=e,class:`subtask-select`},[...n[8]||=[H(`option`,{value:0},`低`,-1),H(`option`,{value:1},`中`,-1),H(`option`,{value:2},`高`,-1)]],512),[[Qo,l.value]]),H(`button`,{onClick:y,class:`btn-create-subtask`,title:`创建子任务`},[...n[9]||=[H(`svg`,{width:`14`,height:`14`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`},[H(`line`,{x1:`12`,y1:`5`,x2:`12`,y2:`19`}),H(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`})],-1)]]),H(`button`,{onClick:n[2]||=e=>o.value=!1,class:`btn-cancel`,title:`取消`},[...n[10]||=[H(`svg`,{width:`14`,height:`14`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`},[H(`path`,{d:`M18 6L6 18M6 6l12 12`})],-1)]])])):W(``,!0),a.value&&e.task.subTasks&&e.task.subTasks.length>0?(B(),V(`div`,Ru,[(B(!0),V(Ki,null,Pr(e.task.subTasks,e=>(B(),ta(i,{key:e.id,task:e,readOnly:r.value,onUpdated:b,onDeleted:x,onSubtaskCreated:n[3]||=e=>t.$emit(`subtask-created`,e)},null,8,[`task`,`readOnly`]))),128))])):W(``,!0),U(Eu,{visible:s.value,"onUpdate:visible":n[4]||=e=>s.value=e,task:e.task,onSaved:C},null,8,[`visible`,`task`])],2)}}}),[[`__scopeId`,`data-v-96951dc0`]]),Bu={class:`task-list`},Vu={class:`page-header`},Hu={class:`header-controls`},Uu={class:`sort-group`},Wu=[`title`],Gu={key:0,class:`sort-order-icon`,viewBox:`0 0 24 24`,fill:`currentColor`},Ku={key:1,class:`sort-order-icon`,viewBox:`0 0 24 24`,fill:`currentColor`},qu={class:`search-box`},Ju={class:`checkbox-wrapper`},Yu={class:`task-info`},Xu={class:`info-item`},Zu={key:0,class:`info-item`},Qu={key:1,class:`info-item`},$u={key:0,class:`task-form`},ed={key:1,class:`cloud-readonly-banner`},td={key:2,class:`empty`},nd={key:3,class:`tasks-shell`},rd={class:`tasks-scroll`},id=Tu(ar({__name:`TaskList`,setup(e){let t=P(``),n=P(1),r=P([]),i=P(!1),a=P(`createdAt`),o=P(`desc`),s=P(Q.isOnline()),c=P(0),l=P(0),u=P(``),d=P(null),f=P(!1),p=P(!1),m=()=>{o.value=o.value===`asc`?`desc`:`asc`},h=()=>{s.value=Q.isOnline()},g=e=>{let t=new Date(e),n=new Date().getTime()-t.getTime(),r=Math.floor(n/6e4);return r<1?`刚刚`:r<60?`${r}分钟前`:r<1440?`${Math.floor(r/60)}小时前`:`${Math.floor(r/1440)}天前`},_=()=>{u.value=``,d.value?.focus()},v=e=>{if(e.key===`Escape`){u.value.trim().length>0&&(e.preventDefault(),_());return}e.key===`Enter`&&e.target?.blur?.()},y=e=>e.trim().toLocaleLowerCase(),b=(e,t)=>e.map(e=>{let n=(e.title??``).toLocaleLowerCase().includes(t),r=e.subTasks&&e.subTasks.length>0?b(e.subTasks,t):[];return!n&&r.length===0?null:{...e,subTasks:n?e.subTasks:r}}).filter(e=>e!==null),x=La(()=>{let e=r.value.filter(e=>!e.parentTaskId),t=i.value?e:T(e,!1),n=y(u.value);return w(n.length>0?b(t,n):t)}),S=La(()=>f.value&&p.value),C=La(()=>f.value?$.loadSettings().serverUrl?p.value?`云同步:已登录`:`云同步:未登录`:`云同步:未配置`:``),w=e=>{let t={2:3,1:2,0:1};return[...e].sort((e,n)=>{let r=0;switch(a.value){case`priority`:r=t[n.priority]-t[e.priority],r===0&&(r=new Date(n.createdAt).getTime()-new Date(e.createdAt).getTime());break;case`completedAt`:{let t=e.isCompleted?new Date(e.updatedAt).getTime():0;r=(n.isCompleted?new Date(n.updatedAt).getTime():0)-t,r===0&&(r=new Date(n.createdAt).getTime()-new Date(e.createdAt).getTime());break}default:r=new Date(n.createdAt).getTime()-new Date(e.createdAt).getTime();break}return o.value===`asc`?-r:r}).map(e=>e.subTasks&&e.subTasks.length>0?{...e,subTasks:w(e.subTasks)}:e)},T=(e,t)=>e.map(e=>({...e})).filter(e=>{if(e.isCompleted===t)return e.subTasks&&e.subTasks.length>0&&(e.subTasks=T(e.subTasks,t)),!0;if(e.subTasks&&e.subTasks.length>0){let n=T(e.subTasks,t);if(n.length>0)return e.subTasks=n,!0}return!1}),ee=async()=>{try{if(S.value){r.value=await yu.getTasks(),c.value=Date.now();let e=Q.loadSyncStatus();e.lastSyncTime=c.value,Q.saveSyncStatus(e),l.value=e.pendingChanges;return}let e=await du.getTasks();if(e.success&&e.data){r.value=e.data;let t=Q.loadSyncStatus();c.value=t.lastSyncTime,l.value=t.pendingChanges}}catch(e){console.error(`Failed to load tasks:`,e),alert(`加载任务失败`)}},te=async()=>{if(!t.value.trim()){alert(`请输入任务标题`);return}try{let e=await du.createTask({title:t.value.trim(),priority:n.value});e.success&&e.data&&(r.value.unshift(e.data),t.value=``,n.value=1)}catch(e){console.error(`Failed to create task:`,e),alert(`创建任务失败`)}},E=e=>{ne(r.value,e)},ne=(e,t)=>{for(let n=0;n0&&ne(e[n].subTasks,t))return!0}return!1},D=e=>{re(r.value,e)},re=(e,t)=>{for(let n=0;n0&&re(e[n].subTasks,t))return!0}return!1},ie=e=>{ae(r.value,e)},ae=(e,t)=>{for(let n=0;n0&&ae(e[n].subTasks,t))return!0}return!1},oe=()=>{let e=new CustomEvent(`openHotKeySettings`,{detail:{modifiers:`Alt`,key:`X`,isEnabled:!0}});window.dispatchEvent(e)},O=()=>{window.dispatchEvent(new CustomEvent(`openCloudSyncSettings`))},se=()=>{let e=$.loadSettings(),t=$.loadSession();f.value=e.enabled,p.value=!!t?.accessToken},ce=()=>{se(),ee()},le=()=>{se(),ee()};return br(()=>{se(),ee(),h(),window.addEventListener(`online`,h),window.addEventListener(`offline`,h),window.addEventListener(`cloudSyncStateChanged`,ce),window.addEventListener(`cloudSyncPullTasksRequested`,le)}),wr(()=>{window.removeEventListener(`online`,h),window.removeEventListener(`offline`,h),window.removeEventListener(`cloudSyncStateChanged`,ce),window.removeEventListener(`cloudSyncPullTasksRequested`,le)}),(e,r)=>(B(),V(`div`,Bu,[H(`div`,Vu,[H(`div`,Hu,[H(`div`,Uu,[I(H(`select`,{"onUpdate:modelValue":r[0]||=e=>a.value=e,class:`sort-select`},[...r[5]||=[H(`option`,{value:`createdAt`},`创建时间`,-1),H(`option`,{value:`completedAt`},`完成时间`,-1),H(`option`,{value:`priority`},`优先级`,-1)]],512),[[Qo,a.value]]),H(`button`,{type:`button`,class:`sort-select sort-order-btn`,onClick:m,title:o.value===`desc`?`切换为升序`:`切换为降序`},[o.value===`desc`?(B(),V(`svg`,Gu,[...r[6]||=[H(`path`,{d:`M11 4h2v11h3l-4 4-4-4h3V4z`},null,-1)]])):(B(),V(`svg`,Ku,[...r[7]||=[H(`path`,{d:`M11 20h2V9h3l-4-4-4 4h3v11z`},null,-1)]]))],8,Wu),H(`div`,qu,[I(H(`input`,{ref_key:`searchInputRef`,ref:d,"onUpdate:modelValue":r[1]||=e=>u.value=e,type:`text`,class:`search-input`,placeholder:`搜索任务...`,autocomplete:`off`,onKeydown:v},null,544),[[Yo,u.value]]),u.value.trim().length>0?(B(),V(`button`,{key:0,type:`button`,class:`search-clear-btn`,title:`清空搜索`,onClick:_},[...r[8]||=[H(`svg`,{width:`12`,height:`12`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`},[H(`line`,{x1:`18`,y1:`6`,x2:`6`,y2:`18`}),H(`line`,{x1:`6`,y1:`6`,x2:`18`,y2:`18`})],-1)]])):W(``,!0)]),H(`label`,Ju,[I(H(`input`,{type:`checkbox`,"onUpdate:modelValue":r[2]||=e=>i.value=e,class:`checkbox-input`},null,512),[[Xo,i.value]]),r[9]||=H(`span`,{class:`checkbox-label`},`已完成`,-1)]),H(`button`,{class:`hotkey-settings-btn`,onClick:oe,title:`设置快捷键`},[...r[10]||=[H(`svg`,{width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`},[H(`path`,{d:`M18 3a3 3 0 0 0-3 3v12a3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3H6a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3V6a3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3h12a3 3 0 0 0 3-3 3 3 0 0 0-3-3z`})],-1),H(`span`,null,`快捷键`,-1)]]),H(`button`,{class:`cloud-sync-btn`,onClick:O,title:`云同步设置`},[...r[11]||=[H(`svg`,{width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`},[H(`path`,{"stroke-linecap":`round`,"stroke-linejoin":`round`,d:`M7 18a4 4 0 1 1 1.1-7.85A6 6 0 0 1 20 12.5 3.5 3.5 0 0 1 18.5 19H7z`})],-1),H(`span`,null,`云同步`,-1)]])])]),H(`div`,Yu,[H(`span`,Xu,`计数:`+k(x.value.length),1),c.value>0?(B(),V(`span`,Zu,[H(`span`,null,`更新:`+k(g(c.value)),1)])):W(``,!0),C.value?(B(),V(`span`,Qu,[H(`span`,null,k(C.value),1)])):W(``,!0)])]),S.value?(B(),V(`div`,ed,` 云同步模式:只读展示(v1.2.0)。编辑/新增将在后续版本补齐。 `)):(B(),V(`div`,$u,[I(H(`input`,{"onUpdate:modelValue":r[3]||=e=>t.value=e,type:`text`,placeholder:`输入新任务...`,onKeyup:os(te,[`enter`]),class:`task-input`},null,544),[[Yo,t.value]]),I(H(`select`,{"onUpdate:modelValue":r[4]||=e=>n.value=e,class:`task-select`},[...r[12]||=[H(`option`,{value:0},`低`,-1),H(`option`,{value:1},`中`,-1),H(`option`,{value:2},`高`,-1)]],512),[[Qo,n.value]]),H(`button`,{onClick:te,class:`btn-add`},[...r[13]||=[H(`svg`,{width:`14`,height:`14`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`},[H(`line`,{x1:`12`,y1:`5`,x2:`12`,y2:`19`}),H(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`})],-1)]])])),x.value.length===0?(B(),V(`div`,td,k(u.value.trim().length>0?`无匹配任务`:`暂无任务`),1)):(B(),V(`div`,nd,[H(`div`,rd,[(B(!0),V(Ki,null,Pr(x.value,e=>(B(),ta(zu,{key:e.id,task:e,readOnly:S.value,onUpdated:E,onDeleted:D,onSubtaskCreated:ie},null,8,[`task`,`readOnly`]))),128))])]))]))}}),[[`__scopeId`,`data-v-dc6ee178`]]),ad={class:`hotkey-settings-dialog`},od={class:`dialog-body`},sd={class:`form-group`},cd={class:`form-group`},ld=[`value`],ud={class:`form-group`},dd={class:`checkbox-label`},fd={class:`preview`},pd={class:`hotkey-preview`},md=Tu(ar({__name:`HotKeySettingsDialog`,setup(e){let t=P(!1),n=zt({modifiers:`Alt`,key:`X`,isEnabled:!0}),r=`ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`.split(``);br(()=>{window.addEventListener(`openHotKeySettings`,i)});function i(e){let r=e.detail;n.modifiers=r.modifiers,n.key=r.key,n.isEnabled=r.isEnabled,t.value=!0}function a(){t.value=!1}function o(){return n.isEnabled?`${n.modifiers.split(`,`).map(e=>e.trim()).join(` + `)} + ${n.key}`:`未启用`}function s(){let e=new CustomEvent(`hotKeyConfigChanged`,{detail:{modifiers:n.modifiers,key:n.key,isEnabled:n.isEnabled}});window.dispatchEvent(e)}function c(){n.modifiers=`Alt`,n.key=`X`,n.isEnabled=!0,s()}function l(){let e={modifiers:n.modifiers,key:n.key,isEnabled:n.isEnabled};window.chrome?.webview?.postMessage&&window.chrome.webview.postMessage(`HOTKEY_CONFIG:${JSON.stringify(e)}`),a()}return(e,i)=>t.value?(B(),V(`div`,{key:0,class:`hotkey-settings-overlay`,onClick:is(a,[`self`])},[H(`div`,ad,[H(`div`,{class:`dialog-header`},[i[3]||=H(`h2`,null,`⌨️ 设置快捷键`,-1),H(`button`,{class:`close-button`,onClick:a},`×`)]),H(`div`,od,[H(`div`,sd,[i[5]||=H(`label`,null,`修饰键:`,-1),I(H(`select`,{"onUpdate:modelValue":i[0]||=e=>n.modifiers=e,onChange:s},[...i[4]||=[ua(``,6)]],544),[[Qo,n.modifiers]])]),H(`div`,cd,[i[6]||=H(`label`,null,`主键:`,-1),I(H(`select`,{"onUpdate:modelValue":i[1]||=e=>n.key=e,onChange:s},[(B(),V(Ki,null,Pr(r,e=>H(`option`,{key:e,value:e},k(e),9,ld)),64))],544),[[Qo,n.key]])]),H(`div`,ud,[H(`label`,dd,[I(H(`input`,{type:`checkbox`,"onUpdate:modelValue":i[2]||=e=>n.isEnabled=e,onChange:s},null,544),[[Xo,n.isEnabled]]),i[7]||=H(`span`,null,`启用快捷键`,-1)])]),H(`div`,fd,[i[8]||=H(`strong`,null,`当前快捷键:`,-1),H(`span`,pd,k(o()),1)])]),H(`div`,{class:`dialog-footer`},[H(`button`,{class:`btn btn-secondary`,onClick:c},`重置默认`),H(`button`,{class:`btn btn-primary`,onClick:l},`保存`)])])])):W(``,!0)}}),[[`__scopeId`,`data-v-ae88d5d6`]]),hd={class:`dialog`},gd={class:`dialog-body`},_d={class:`section`},vd={class:`checkbox-row`},yd={class:`section`},bd={class:`form-row`},xd=[`disabled`],Sd={key:0,class:`hint`},Cd={class:`mono`},wd={class:`probe-title`},Td={class:`probe-desc`},Ed={class:`section`},Dd={key:0,class:`logged-in`},Od={class:`hint`},kd={class:`mono`},Ad={class:`button-row`},jd=[`disabled`],Md={key:1,class:`login-form`},Nd={class:`form-row`},Pd=[`disabled`],Fd=Tu(ar({__name:`CloudSyncSettingsDialog`,setup(e){let t=P(!1),n=P(!1),r=P(``),i=P(``),a=P(!1),o=P(null),s=P(``),c=P(``),l=P(!1),u=()=>{let e=$.loadSettings();n.value=e.enabled,i.value=e.serverUrl,r.value=e.serverUrl},d=La(()=>!!$.loadSession()?.accessToken),f=La(()=>{let e=$.loadSession();if(!e)return``;let t=e.userId?e.userId.slice(0,8):``;return`${e.role||`User`}@${t}`}),p=La(()=>!n.value||!i.value||!s.value.trim()||!c.value?!1:!l.value),m=(e,t=`error`)=>{window.showToast?window.showToast(e,t):window.alert(e)},h=e=>{let t=e.trim();if(!t)return{ok:!1,message:`请输入服务端地址`};let n;try{n=new URL(t)}catch{return{ok:!1,message:`地址格式不正确,请包含协议(http:// 或 https://)`}}if(n.protocol!==`http:`&&n.protocol!==`https:`)return{ok:!1,message:`仅支持 http:// 或 https:// 地址`};if(!n.hostname)return{ok:!1,message:`地址缺少主机名(host)`};let r=n.origin,i=n.pathname&&n.pathname!==`/`?`已忽略地址中的路径部分,仅保留 origin。`:void 0;return{ok:!0,normalized:r.replace(/\/+$/,``),warn:i}},g=async e=>{let t=new URL(e).protocol===`https:`,n=`${e}/auth/login`,r=new AbortController,i=window.setTimeout(()=>r.abort(),4e3);try{let e=await fetch(n,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({userName:`__probe__`,password:`__probe__`}),signal:r.signal});return t?{type:`success`,title:`可达`,desc:`已探测到服务端响应(HTTP ${e.status})。可继续登录。`}:{type:`warn`,title:`可达(存在风险)`,desc:`服务端可访问,但当前为 HTTP(非加密)。建议使用 HTTPS。`}}catch{return t?{type:`warn`,title:`存在风险`,desc:`探测失败(可能是网络不可达 / 证书异常 / 跨域被阻止)。仍可保存地址并稍后重试登录。`}:{type:`warn`,title:`存在风险`,desc:`当前为 HTTP 且探测失败。请检查地址是否可达,或改用 HTTPS。`}}finally{window.clearTimeout(i)}},_=()=>{let e=$.loadSettings(),t=$.loadSession(),n=new CustomEvent(`cloudSyncStateChanged`,{detail:{enabled:e.enabled,serverUrl:e.serverUrl,isLoggedIn:!!t?.accessToken}});window.dispatchEvent(n)},v=()=>{if(n.value&&!i.value){n.value=!1,m(`启用云同步前请先配置并保存服务端地址`,`error`);return}$.saveSettings({serverUrl:i.value,enabled:n.value}),_()},y=async()=>{let e=h(r.value);if(!e.ok||!e.normalized){m(e.message||`地址不合法`,`error`);return}i.value=e.normalized,$.saveSettings({serverUrl:i.value,enabled:n.value}),e.warn?m(e.warn,`success`):m(`地址已保存`,`success`),a.value=!0;try{o.value=await g(i.value)}finally{a.value=!1}_()},b=async()=>{if(p.value){l.value=!0;try{await yu.login({userName:s.value.trim(),password:c.value}),m(`登录成功`,`success`),_(),await S()}finally{l.value=!1}}},x=()=>{yu.logout(),m(`已登出`,`success`),_()},S=async()=>{let e=new CustomEvent(`cloudSyncPullTasksRequested`);window.dispatchEvent(e)};function C(){u(),o.value=null,t.value=!0}function w(){t.value=!1}return br(()=>{window.addEventListener(`openCloudSyncSettings`,C)}),(e,u)=>t.value?(B(),V(`div`,{key:0,class:`overlay`,onClick:is(w,[`self`])},[H(`div`,hd,[H(`div`,{class:`dialog-header`},[u[4]||=H(`h2`,null,`☁️ 云同步设置`,-1),H(`button`,{class:`close-button`,onClick:w},`×`)]),H(`div`,gd,[H(`div`,_d,[u[6]||=H(`div`,{class:`section-title`},`同步开关`,-1),H(`label`,vd,[I(H(`input`,{type:`checkbox`,"onUpdate:modelValue":u[0]||=e=>n.value=e,onChange:v},null,544),[[Xo,n.value]]),u[5]||=H(`span`,null,`启用云同步(v1.2.0:仅支持登录后拉取任务)`,-1)]),u[7]||=H(`div`,{class:`hint`},` 启用后,主界面将以云端任务为准并进入只读展示;本地编辑/新增将在后续版本补齐。 `,-1)]),H(`div`,yd,[u[9]||=H(`div`,{class:`section-title`},`服务端地址`,-1),H(`div`,bd,[I(H(`input`,{"onUpdate:modelValue":u[1]||=e=>r.value=e,class:`text-input`,type:`text`,placeholder:`例如:https://example.com`,autocomplete:`off`},null,512),[[Yo,r.value]]),H(`button`,{class:`btn btn-secondary`,disabled:a.value,onClick:y},k(a.value?`探测中...`:`保存并探测`),9,xd)]),i.value?(B(),V(`div`,Sd,[u[8]||=la(` 已保存:`,-1),H(`span`,Cd,k(i.value),1)])):W(``,!0),o.value?(B(),V(`div`,{key:1,class:ve([`probe`,o.value.type])},[H(`div`,wd,k(o.value.title),1),H(`div`,Td,k(o.value.desc),1)],2)):W(``,!0)]),H(`div`,Ed,[u[12]||=H(`div`,{class:`section-title`},`登录`,-1),d.value?(B(),V(`div`,Dd,[H(`div`,Od,[u[10]||=la(` 已登录:`,-1),H(`span`,kd,k(f.value),1)]),H(`div`,Ad,[H(`button`,{class:`btn btn-secondary`,onClick:x},`登出`),H(`button`,{class:`btn btn-primary`,disabled:!n.value,onClick:S},` 拉取任务 `,8,jd)])])):(B(),V(`div`,Md,[H(`div`,Nd,[I(H(`input`,{"onUpdate:modelValue":u[2]||=e=>s.value=e,class:`text-input`,type:`text`,placeholder:`用户名`,autocomplete:`username`},null,512),[[Yo,s.value]]),I(H(`input`,{"onUpdate:modelValue":u[3]||=e=>c.value=e,class:`text-input`,type:`password`,placeholder:`密码`,autocomplete:`current-password`},null,512),[[Yo,c.value]]),H(`button`,{class:`btn btn-primary`,disabled:!p.value,onClick:b},k(l.value?`登录中...`:`登录`),9,Pd)]),u[11]||=H(`div`,{class:`hint`},` 说明:服务端使用 Bearer 会话(AccessToken=SessionId)。会话默认仅保存在本次运行(sessionStorage)。 `,-1)]))])]),H(`div`,{class:`dialog-footer`},[H(`button`,{class:`btn btn-secondary`,onClick:w},`关闭`)])])])):W(``,!0)}}),[[`__scopeId`,`data-v-c8c2626c`]]),Id={class:`app`},Ld={class:`toast-content`},Rd={class:`toast-icon`},zd={class:`toast-message`};us(ar({__name:`App`,setup(e){let t=P(``),n=P(`error`),r=P(!1),i=(e,i=`error`)=>{t.value=e,n.value=i,r.value=!0,setTimeout(()=>{r.value=!1},5e3)};return br(()=>{window.showToast=i}),(e,i)=>(B(),V(`div`,Id,[U(id),U(md),U(Fd),U($a,{name:`toast`},{default:Mn(()=>[r.value?(B(),V(`div`,{key:0,class:ve([`toast`,n.value])},[H(`div`,Ld,[H(`span`,Rd,k(n.value===`error`?`❌`:`✅`),1),H(`span`,zd,k(t.value),1)]),H(`button`,{onClick:i[0]||=e=>r.value=!1,class:`toast-close`},`×`)],2)):W(``,!0)]),_:1})]))}})).mount(`#app`);
\ No newline at end of file
diff --git a/src/Hua.Todo.Avalonia/wwwroot/assets/index-DxoB2Se3.css b/src/Hua.Todo.Avalonia/wwwroot/assets/index-DxoB2Se3.css
new file mode 100644
index 0000000..faef468
--- /dev/null
+++ b/src/Hua.Todo.Avalonia/wwwroot/assets/index-DxoB2Se3.css
@@ -0,0 +1 @@
+:root{--text:#6b6375;--text-h:#08060d;--bg:#fff;--border:#e5e4e7;--code-bg:#f4f3ec;--accent:#aa3bff;--accent-bg:#aa3bff1a;--accent-border:#aa3bff80;--social-bg:#f4f3ec80;--shadow:#0000001a 0 10px 15px -3px, #0000000d 0 4px 6px -2px;--sans:system-ui, "Segoe UI", Roboto, sans-serif;--heading:system-ui, "Segoe UI", Roboto, sans-serif;--mono:ui-monospace, Consolas, monospace;font:18px/145% var(--sans);letter-spacing:.18px;--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark;color:var(--text);background:var(--bg);font-synthesis:none;text-rendering:optimizelegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial}}@media (width<=1024px){:root{font-size:16px}}@media (prefers-color-scheme:dark){:root{--text:#9ca3af;--text-h:#f3f4f6;--bg:#16171d;--border:#2e303a;--code-bg:#1f2028;--accent:#c084fc;--accent-bg:#c084fc26;--accent-border:#c084fc80;--social-bg:#2f303a80;--shadow:#0006 0 10px 15px -3px, #00000040 0 4px 6px -2px}#social .button-icon{filter:invert()brightness(2)}}body{margin:0}h1,h2{font-family:var(--heading);color:var(--text-h);font-weight:500}h1{letter-spacing:-1.68px;margin:32px 0;font-size:56px}@media (width<=1024px){h1{margin:20px 0;font-size:36px}}h2{letter-spacing:-.24px;margin:0 0 8px;font-size:24px;line-height:118%}@media (width<=1024px){h2{font-size:20px}}p{margin:0}code,.counter{font-family:var(--mono);color:var(--text-h);border-radius:4px;display:inline-flex}code{background:var(--code-bg);padding:4px 8px;font-size:15px;line-height:135%}.counter{color:var(--accent);background:var(--accent-bg);border:2px solid #0000;border-radius:5px;margin-bottom:24px;padding:5px 10px;font-size:16px;transition:border-color .3s}.counter:hover{border-color:var(--accent-border)}.counter:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.hero{position:relative}.hero .base,.hero .framework,.hero .vite{margin:0 auto;inset-inline:0}.hero .base{z-index:0;width:170px;position:relative}.hero .framework,.hero .vite{position:absolute}.hero .framework{z-index:1;height:28px;top:34px;transform:perspective(2000px)rotate(300deg)rotateX(44deg)rotateY(39deg)scale(1.4)}.hero .vite{z-index:0;width:auto;height:26px;top:107px;transform:perspective(2000px)rotate(300deg)rotateX(40deg)rotateY(39deg)scale(.8)}#app{box-sizing:border-box;flex-direction:column;width:100%;max-width:none;min-height:100svh;margin:0;display:flex}#center{flex-direction:column;flex-grow:1;place-content:center;place-items:center;gap:25px;display:flex}@media (width<=1024px){#center{gap:18px;padding:32px 20px 24px}}#next-steps{border-top:1px solid var(--border);text-align:left;display:flex}#next-steps>div{flex:1 1 0;padding:32px}@media (width<=1024px){#next-steps>div{padding:24px 20px}}#next-steps .icon{width:22px;height:22px;margin-bottom:16px}@media (width<=1024px){#next-steps{text-align:center;flex-direction:column}}#docs{border-right:1px solid var(--border)}@media (width<=1024px){#docs{border-right:none;border-bottom:1px solid var(--border)}}#next-steps ul{gap:8px;margin:32px 0 0;padding:0;list-style:none;display:flex}#next-steps ul .logo{height:18px}#next-steps ul a{color:var(--text-h);background:var(--social-bg);border-radius:6px;align-items:center;gap:8px;padding:6px 12px;font-size:16px;text-decoration:none;transition:box-shadow .3s;display:flex}#next-steps ul a:hover{box-shadow:var(--shadow)}#next-steps ul a .button-icon{width:18px;height:18px}@media (width<=1024px){#next-steps ul{flex-wrap:wrap;justify-content:center;margin-top:20px}#next-steps ul li{flex:calc(50% - 8px)}#next-steps ul a{box-sizing:border-box;justify-content:center;width:100%}}#spacer{border-top:1px solid var(--border);height:88px}@media (width<=1024px){#spacer{height:48px}}.ticks{width:100%;position:relative}.ticks:before,.ticks:after{content:"";border:5px solid #0000;position:absolute;top:-4.5px}.ticks:before{border-left-color:var(--border);left:0}.ticks:after{border-right-color:var(--border);right:0}.dialog-overlay[data-v-fc0893aa]{z-index:1000;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background:#00000080;justify-content:center;align-items:center;padding:20px 16px;display:flex;position:fixed;inset:0}.dialog-content[data-v-fc0893aa]{background:#fff;border:1px solid #6366f11f;border-radius:20px;width:min(100%,420px);animation:.22s dialogSlideIn-fc0893aa;overflow:hidden;box-shadow:0 20px 60px #0000004d}@keyframes dialogSlideIn-fc0893aa{0%{opacity:0;transform:translateY(-20px)scale(.95)}to{opacity:1;transform:translateY(0)scale(1)}}.dialog-header[data-v-fc0893aa]{border-bottom:1px solid #e5e7eb;justify-content:space-between;align-items:center;padding:12px 14px;display:flex}.dialog-title[data-v-fc0893aa]{color:#1e293b;margin:0;font-size:16px;font-weight:700;line-height:1.3}.btn-close[data-v-fc0893aa]{color:#64748b;cursor:pointer;background:0 0;border:none;border-radius:8px;justify-content:center;align-items:center;width:28px;height:28px;font-size:20px;line-height:1;transition:all .2s;display:flex}.btn-close[data-v-fc0893aa]:hover{color:#334155;background:#f1f5f9}.dialog-body[data-v-fc0893aa]{gap:14px;padding:14px;display:grid}.form-group[data-v-fc0893aa]{margin-bottom:0}.form-label[data-v-fc0893aa]{color:#334155;margin-bottom:6px;font-size:13px;font-weight:600;display:block}.form-input[data-v-fc0893aa]{color:#1e293b;box-sizing:border-box;background:0 0;border:none;border-bottom:2px solid #e2e8f0;border-radius:0;width:100%;min-height:40px;padding:8px;font-size:14px;transition:all .2s}.form-input[data-v-fc0893aa]:focus{box-shadow:none;background:0 0;border-bottom-color:#6366f1;outline:none}.form-select[data-v-fc0893aa]{cursor:pointer;color:#1e293b;box-sizing:border-box;appearance:none;background:#f8fafc url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%2364748b'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E") right 10px center/18px no-repeat;border:2px solid #e2e8f0;border-radius:14px;width:100%;min-height:40px;padding:10px 40px 10px 14px;font-size:14px;transition:all .3s}.form-select[data-v-fc0893aa]:hover{background-color:#f8fafc;border-color:#cbd5e1}.form-select[data-v-fc0893aa]:focus{background:#fff;border-color:#6366f1;outline:none;box-shadow:0 0 0 4px #6366f11a}.form-select option[data-v-fc0893aa]{color:#1e293b;background:#fff}.form-select option[value="0"][data-v-fc0893aa]{color:#22c55e}.form-select option[value="1"][data-v-fc0893aa]{color:#f59e0b}.form-select option[value="2"][data-v-fc0893aa]{color:#ef4444}.dialog-footer[data-v-fc0893aa]{background:#f8fafc;border-top:1px solid #e5e7eb;justify-content:flex-end;gap:8px;padding:12px 16px 16px;display:flex}.btn-cancel[data-v-fc0893aa]{color:#374151;cursor:pointer;background:#e5e7eb;border:none;border-radius:14px;min-width:76px;padding:8px 18px;font-size:14px;font-weight:600;transition:background .2s}.btn-cancel[data-v-fc0893aa]:hover{background:#d1d5db}.btn-save[data-v-fc0893aa]{color:#fff;cursor:pointer;background:linear-gradient(135deg,#2563eb 0%,#1d4ed8 100%);border:none;border-radius:14px;min-width:76px;padding:8px 18px;font-size:14px;font-weight:600;transition:all .3s;box-shadow:0 4px 12px -2px #2563eb66}.btn-save[data-v-fc0893aa]:hover{transform:translateY(-2px);box-shadow:0 8px 16px -2px #2563eb80}.btn-save[data-v-fc0893aa]:active{transform:translateY(0)}@media (width<=768px){.dialog-content[data-v-fc0893aa]{border-radius:20px;width:100%}.dialog-header[data-v-fc0893aa]{padding:12px 14px}.dialog-title[data-v-fc0893aa]{font-size:16px}.dialog-body[data-v-fc0893aa]{gap:12px;padding:14px}.dialog-footer[data-v-fc0893aa]{padding:10px 14px 14px}.btn-cancel[data-v-fc0893aa],.btn-save[data-v-fc0893aa]{padding:8px 16px;font-size:14px}}.task-item[data-v-96951dc0]{-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;text-align:left;background:#fff;border:1px solid #e2e8f0e6;border-left-width:8px;border-radius:12px;flex-direction:column;margin-bottom:0;padding:10px 12px;transition:background .2s,box-shadow .2s,transform .2s,border-color .2s;display:flex}.task-item.priority-low[data-v-96951dc0]{background:#d1fae5a6;border-color:#a7f3d0bf #a7f3d0bf #a7f3d0bf #22c55ee6}.task-item.priority-medium[data-v-96951dc0]{background:#fef3c7b3;border-color:#fde68acc #fde68acc #fde68acc #f59e0be6}.task-item.priority-high[data-v-96951dc0]{background:#fee2e2b3;border-color:#fecacad9 #fecacad9 #fecacad9 #ef4444e6}.task-item.priority-low[data-v-96951dc0]:hover{background:#d1fae5d9}.task-item.priority-medium[data-v-96951dc0]:hover{background:#fef3c7d9}.task-item.priority-high[data-v-96951dc0]:hover{background:#fee2e2d9}.task-item[data-v-96951dc0]:hover{box-shadow:0 10px 20px -12px #0f172a40}.task-item.completed[data-v-96951dc0]{opacity:.6}.task-item.completed .task-title[data-v-96951dc0]{text-decoration:line-through}.task-content[data-v-96951dc0]{cursor:pointer;-webkit-user-select:none;user-select:none;flex:1;align-items:center;gap:6px;display:flex}.task-content[data-v-96951dc0]:hover{background:0 0}.task-expand[data-v-96951dc0]{cursor:pointer;background:0 0;border:none;justify-content:center;align-items:center;width:18px;height:18px;padding:0;display:flex}.expand-icon[data-v-96951dc0]{color:#6b7280;font-size:12px;transition:transform .2s}.task-checkbox[data-v-96951dc0]{cursor:pointer;appearance:none;background:#ffffffeb;border:1.5px solid #64748b99;border-radius:4px;place-content:center;width:18px;height:18px;transition:background-color .2s,border-color .2s,box-shadow .2s;display:grid}.task-checkbox[data-v-96951dc0]:after{content:"";opacity:0;border-bottom:2px solid #fff;border-right:2px solid #fff;width:6px;height:10px;transition:opacity .2s;transform:translateY(-1px)rotate(45deg)}.task-checkbox[data-v-96951dc0]:checked{background:#6366f1;border-color:#6366f1}.task-checkbox[data-v-96951dc0]:checked:after{opacity:1}.task-checkbox[data-v-96951dc0]:focus-visible{outline-offset:2px;outline:2px solid #6366f18c}@media (prefers-color-scheme:dark){.task-checkbox[data-v-96951dc0]{background:#0f172a59;border-color:#94a3b8bf}}.task-info[data-v-96951dc0]{flex-direction:column;flex:1;align-items:flex-start;gap:4px;min-width:0;display:flex}.task-title[data-v-96951dc0]{color:#374151;white-space:nowrap;text-overflow:ellipsis;width:100%;font-size:15px;overflow:hidden}.task-meta[data-v-96951dc0]{align-items:center;gap:8px;width:100%;min-width:0;display:flex}.task-created[data-v-96951dc0]{color:#475569d9;white-space:nowrap;text-overflow:ellipsis;flex:1;font-size:12px;line-height:1.2;overflow:hidden}.task-id[data-v-96951dc0]{color:#475569e6;font-variant-numeric:tabular-nums;background:#94a3b824;border-radius:999px;flex-shrink:0;padding:2px 8px;font-size:12px;font-weight:600;line-height:1.2}.task-id--compact[data-v-96951dc0]{padding:1px 6px;font-size:11px}.task-priority[data-v-96951dc0]{color:#475569e6;background:#94a3b82e;border-radius:999px;flex-shrink:0;padding:2px 8px;font-size:12px;font-weight:600;line-height:1.2}.task-priority--compact[data-v-96951dc0]{padding:1px 6px;font-size:11px}.task-item.priority-low .task-priority[data-v-96951dc0]{color:#15803df2;background:#22c55e24}.task-item.priority-medium .task-priority[data-v-96951dc0]{color:#b45309f2;background:#f59e0b29}.task-item.priority-high .task-priority[data-v-96951dc0]{color:#b91c1cf2;background:#ef444424}.task-actions[data-v-96951dc0]{flex-shrink:0;align-items:center;gap:6px;display:flex}.btn-edit-icon[data-v-96951dc0]{color:#2563eb;cursor:pointer;background:0 0;border:none;border-radius:4px;flex-shrink:0;justify-content:center;align-items:center;width:24px;height:24px;padding:0;transition:all .2s;display:flex}.btn-edit-icon[data-v-96951dc0]:hover{color:#1d4ed8;background:#dbeafe}.btn-edit-icon svg[data-v-96951dc0]{flex-shrink:0}.btn-add-subtask[data-v-96951dc0]{color:#1e40af;cursor:pointer;background:#dbeafe;border:none;border-radius:3px;align-items:center;gap:4px;padding:4px 10px;font-size:11px;transition:background .2s;display:flex}.btn-add-subtask svg[data-v-96951dc0]{flex-shrink:0}.btn-add-subtask-icon[data-v-96951dc0]{color:#6b7280;cursor:pointer;background:0 0;border:none;border-radius:4px;flex-shrink:0;justify-content:center;align-items:center;width:24px;height:24px;padding:0;transition:all .2s;display:flex}.btn-add-subtask-icon[data-v-96951dc0]:hover{color:#1e40af;background:#dbeafe}.btn-add-subtask-icon svg[data-v-96951dc0]{flex-shrink:0}.btn-add-subtask[data-v-96951dc0]:hover{background:#bfdbfe}.btn-delete-icon[data-v-96951dc0]{color:#dc2626;cursor:pointer;background:0 0;border:none;border-radius:4px;flex-shrink:0;justify-content:center;align-items:center;width:24px;height:24px;padding:0;transition:all .2s;display:flex}.btn-delete-icon[data-v-96951dc0]:hover{color:#991b1b;background:#fee2e2}.btn-delete-icon svg[data-v-96951dc0]{flex-shrink:0}.add-subtask-form[data-v-96951dc0]{background:#ffffff8c;border:1px solid #0000000d;border-radius:12px;flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:8px;margin-top:10px;padding:8px 12px;animation:.3s ease-out slideDown-96951dc0;display:flex}@keyframes slideDown-96951dc0{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.subtask-input[data-v-96951dc0]{color:#1e293b;background:0 0;border:none;border-bottom:1.5px solid #00000014;border-radius:0;width:100%;padding:8px;font-size:14px;transition:all .3s}.subtask-input[data-v-96951dc0]::placeholder{color:#94a3b8}.subtask-input[data-v-96951dc0]:focus{box-shadow:none;background:0 0;border-bottom-color:#6366f1;outline:none}.subtask-select[data-v-96951dc0]{cursor:pointer;color:#1e293b;background:#fff9;border:1.5px solid #00000014;border-radius:8px;min-width:60px;padding:4px 8px;font-size:13px;transition:all .3s}.subtask-select[data-v-96951dc0]:focus{background:#fff;border-color:#6366f1;outline:none;box-shadow:0 0 0 4px #6366f11a}.subtask-select option[data-v-96951dc0]{color:#1e293b;background:#fff}.subtask-select option[value="0"][data-v-96951dc0]{color:#22c55e}.subtask-select option[value="1"][data-v-96951dc0]{color:#f59e0b}.subtask-select option[value="2"][data-v-96951dc0]{color:#ef4444}.btn-create-subtask[data-v-96951dc0]{color:#fff;cursor:pointer;background:linear-gradient(135deg,#2563eb 0%,#1d4ed8 100%);border:none;border-radius:8px;justify-content:center;align-items:center;padding:4px 12px;font-size:14px;font-weight:600;transition:all .3s;display:flex;box-shadow:0 4px 12px -2px #2563eb4d}.btn-create-subtask[data-v-96951dc0]:hover{transform:translateY(-2px);box-shadow:0 8px 16px -2px #2563eb66}.btn-create-subtask[data-v-96951dc0]:active{transform:translateY(0)}.btn-cancel[data-v-96951dc0]{color:#dc2626;cursor:pointer;background:0 0;border:none;border-radius:4px;flex-shrink:0;justify-content:center;align-items:center;width:24px;height:24px;padding:0;transition:all .2s;display:flex}.btn-cancel[data-v-96951dc0]:hover{color:#475569;background:#e2e8f0}.add-subtask-form[data-v-96951dc0]>*{box-sizing:border-box}@media (width<=600px){.add-subtask-form[data-v-96951dc0]{border-radius:16px;flex-wrap:wrap}.subtask-input[data-v-96951dc0]{flex:100%;margin-bottom:4px}}.subtasks[data-v-96951dc0]{background:0 0;border:none;border-radius:0;flex-direction:column;gap:8px;margin-top:10px;margin-left:14px;padding:0;display:flex}.subtasks[data-v-96951dc0] .task-item{box-shadow:none;border-left-width:5px;padding:10px 12px}.subtasks[data-v-96951dc0] .task-item:hover{box-shadow:none}.subtasks[data-v-96951dc0] .task-item{border-top-width:0;border-bottom-width:0;border-right-width:0}.subtasks[data-v-96951dc0] .task-item.priority-low,.subtasks[data-v-96951dc0] .task-item.priority-medium,.subtasks[data-v-96951dc0] .task-item.priority-high{border-top-color:#0000;border-bottom-color:#0000;border-right-color:#0000}.task-item[data-v-96951dc0] ::selection{background:0 0}.task-list[data-v-dc6ee178]{background:0 0;flex-direction:column;width:100%;max-width:none;height:100dvh;min-height:100vh;margin:0;padding:0;display:flex}.page-header[data-v-dc6ee178]{--header-chip-height:24px;--header-chip-font-size:10px;--header-chip-pad-x:8px;background:#fff;border-radius:16px;justify-content:space-between;align-items:center;gap:8px;margin-bottom:12px;padding:4px 6px;display:flex;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.header-controls[data-v-dc6ee178]{flex:1;min-width:0}.task-form[data-v-dc6ee178]{background:#fff;border:1px solid #6366f11a;border-radius:20px;gap:8px;margin-bottom:8px;padding:8px;display:flex;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.task-input[data-v-dc6ee178]{color:#1e293b;background:0 0;border:none;border-bottom:2px solid #e2e8f0;border-radius:0;flex:1;padding:8px;font-size:14px;transition:all .3s}.task-input[data-v-dc6ee178]:focus{box-shadow:none;background:0 0;border-bottom-color:#6366f1;outline:none}.task-select[data-v-dc6ee178]{cursor:pointer;color:#1e293b;background:#f8fafc;border:2px solid #e2e8f0;border-radius:14px;min-width:150px;padding:10px 14px;font-size:14px;transition:all .3s}.task-select[data-v-dc6ee178]:focus{background:#fff;border-color:#6366f1;outline:none;box-shadow:0 0 0 4px #6366f11a}.task-select option[data-v-dc6ee178]{color:#1e293b;background:#fff}.task-select option[value="0"][data-v-dc6ee178]{color:#22c55e}.task-select option[value="1"][data-v-dc6ee178]{color:#f59e0b}.task-select option[value="2"][data-v-dc6ee178]{color:#ef4444}.btn-add[data-v-dc6ee178]{color:#fff;cursor:pointer;background:linear-gradient(135deg,#2563eb 0%,#1d4ed8 100%);border:none;border-radius:14px;justify-content:center;align-items:center;padding:8px 16px;font-size:14px;font-weight:600;transition:all .3s;display:flex;box-shadow:0 4px 12px -2px #2563eb66}.btn-add[data-v-dc6ee178]:hover{transform:translateY(-2px);box-shadow:0 8px 16px -2px #2563eb80}.btn-add[data-v-dc6ee178]:active{transform:translateY(0)}.checkbox-wrapper[data-v-dc6ee178]{cursor:pointer;-webkit-user-select:none;user-select:none;height:var(--header-chip-height);padding:0 var(--header-chip-pad-x);background:linear-gradient(135deg,#f8fafc 0%,#f1f5f9 100%);border:1px solid #e2e8f0;border-radius:8px;align-items:center;gap:4px;transition:all .3s;display:flex}.checkbox-wrapper[data-v-dc6ee178]:hover{background:#fff;border-color:#6366f1}.checkbox-input[data-v-dc6ee178]{cursor:pointer;appearance:none;background:#ffffffeb;border:1.5px solid #64748b99;border-radius:4px;place-content:center;width:14px;height:14px;transition:background-color .2s,border-color .2s,box-shadow .2s;display:grid}.checkbox-input[data-v-dc6ee178]:after{content:"";opacity:0;border-bottom:2px solid #fff;border-right:2px solid #fff;width:5px;height:8px;transition:opacity .2s;transform:translateY(-1px)rotate(45deg)}.checkbox-input[data-v-dc6ee178]:checked{background:#6366f1;border-color:#6366f1}.checkbox-input[data-v-dc6ee178]:checked:after{opacity:1}.checkbox-input[data-v-dc6ee178]:focus-visible{outline-offset:2px;outline:2px solid #6366f18c}@media (prefers-color-scheme:dark){.checkbox-input[data-v-dc6ee178]{background:#0f172a59;border-color:#94a3b8bf}}.checkbox-label[data-v-dc6ee178]{font-size:var(--header-chip-font-size);color:#475569;cursor:pointer;font-weight:400;transition:all .3s}.checkbox-wrapper:hover .checkbox-label[data-v-dc6ee178]{color:#6366f1}.task-info[data-v-dc6ee178]{flex-shrink:0;align-items:center;gap:8px;display:flex}.info-item[data-v-dc6ee178]{cursor:default;-webkit-user-select:none;user-select:none;height:var(--header-chip-height);padding:0 var(--header-chip-pad-x);font-size:var(--header-chip-font-size);color:#475569;background:linear-gradient(135deg,#f8fafc 0%,#f1f5f9 100%);border:1px solid #e2e8f0;border-radius:8px;align-items:center;gap:4px;font-weight:500;transition:all .3s;display:flex}.info-item svg[data-v-dc6ee178]{flex-shrink:0}.sort-group[data-v-dc6ee178]{flex-wrap:wrap;align-items:center;gap:4px;display:flex}.search-box[data-v-dc6ee178]{height:var(--header-chip-height);background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;align-items:center;transition:all .3s;display:inline-flex;overflow:hidden}.search-box[data-v-dc6ee178]:focus-within{background:#fff;border-color:#6366f1}.search-input[data-v-dc6ee178]{height:100%;padding:0 var(--header-chip-pad-x);font-size:var(--header-chip-font-size);color:#475569;background:0 0;border:none;outline:none;width:160px;min-width:120px}.search-input[data-v-dc6ee178]::placeholder{color:#94a3b8}.search-clear-btn[data-v-dc6ee178]{height:100%;width:var(--header-chip-height);color:#64748b;cursor:pointer;background:0 0;border:none;justify-content:center;align-items:center;padding:0;transition:all .2s;display:inline-flex}.search-clear-btn[data-v-dc6ee178]:hover{color:#6366f1;background:#6366f114}.search-clear-btn[data-v-dc6ee178]:active{transform:translateY(.5px)}.sort-select[data-v-dc6ee178]{height:var(--header-chip-height);padding:0 calc(var(--header-chip-pad-x) + 14px) 0 var(--header-chip-pad-x);cursor:pointer;font-size:var(--header-chip-font-size);color:#475569;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;transition:all .3s}.sort-select[data-v-dc6ee178]:focus{background:#fff;border-color:#6366f1;outline:none}.sort-select[data-v-dc6ee178]:hover{border-color:#6366f1}.sort-select.sort-order-btn[data-v-dc6ee178]{height:var(--header-chip-height);width:var(--header-chip-height);box-sizing:border-box;-webkit-user-select:none;user-select:none;border-radius:8px;justify-content:center;align-items:center;min-width:0;padding:0;font-size:0;line-height:0;display:inline-flex}.sort-order-icon[data-v-dc6ee178]{flex-shrink:0;width:14px;height:14px;display:block}.sort-order-btn[data-v-dc6ee178]:active{transform:translateY(.5px)}.hotkey-settings-btn[data-v-dc6ee178]{height:var(--header-chip-height);padding:0 var(--header-chip-pad-x);color:#fff;cursor:pointer;font-size:var(--header-chip-font-size);background:linear-gradient(135deg,#6366f1 0%,#8b5cf6 100%);border:none;border-radius:8px;align-items:center;gap:4px;font-weight:500;transition:all .3s;display:flex;box-shadow:0 2px 8px -2px #6366f166}.hotkey-settings-btn[data-v-dc6ee178]:hover{transform:translateY(-1px);box-shadow:0 4px 12px -2px #6366f180}.hotkey-settings-btn[data-v-dc6ee178]:active{transform:translateY(0)}.hotkey-settings-btn svg[data-v-dc6ee178]{flex-shrink:0;width:14px;height:14px}.hotkey-settings-btn span[data-v-dc6ee178]{font-size:inherit}.cloud-sync-btn[data-v-dc6ee178]{height:var(--header-chip-height);padding:0 var(--header-chip-pad-x);color:#fff;cursor:pointer;font-size:var(--header-chip-font-size);background:linear-gradient(135deg,#0ea5e9 0%,#2563eb 100%);border:none;border-radius:8px;align-items:center;gap:4px;font-weight:500;transition:all .3s;display:flex;box-shadow:0 2px 8px -2px #2563eb59}.cloud-sync-btn[data-v-dc6ee178]:hover{transform:translateY(-1px);box-shadow:0 4px 12px -2px #2563eb73}.cloud-sync-btn[data-v-dc6ee178]:active{transform:translateY(0)}.cloud-sync-btn svg[data-v-dc6ee178]{flex-shrink:0;width:14px;height:14px}.cloud-sync-btn span[data-v-dc6ee178]{font-size:inherit}.cloud-readonly-banner[data-v-dc6ee178]{color:#1e40afeb;background:#0ea5e914;border:1px solid #2563eb2e;border-radius:14px;margin-bottom:8px;padding:10px 12px;font-size:13px;font-weight:550}.empty[data-v-dc6ee178]{text-align:center;color:#94a3b8;background:#fff;border:2px dashed #e2e8f0;border-radius:20px;padding:40px 20px;font-size:16px;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.tasks-shell[data-v-dc6ee178]{background:#ffffffd9;border:1px solid #e2e8f0;border-radius:18px;flex:1;min-height:0;padding:10px;display:flex}.tasks-scroll[data-v-dc6ee178]{scrollbar-gutter:stable;flex-direction:column;flex:1;gap:10px;min-height:0;display:flex;overflow-y:auto}@media (width<=768px){.task-list[data-v-dc6ee178]{max-width:100%}.page-header[data-v-dc6ee178]{border-radius:14px;flex-flow:wrap;align-items:center;gap:6px;margin-bottom:8px;padding:4px 6px}.task-form[data-v-dc6ee178]{border-radius:16px;gap:6px;margin-bottom:8px;padding:8px}.task-input[data-v-dc6ee178]{border-radius:12px;padding:8px 10px;font-size:14px}.task-select[data-v-dc6ee178]{border-radius:12px;min-width:84px;padding:8px 10px;font-size:14px}.btn-add[data-v-dc6ee178]{border-radius:12px;padding:8px 14px;font-size:14px}.task-filters[data-v-dc6ee178]{border-radius:16px;flex-direction:row;align-items:center;gap:6px;margin-bottom:8px;padding:8px 10px}.checkbox-wrapper[data-v-dc6ee178]{height:var(--header-chip-height);padding:0 var(--header-chip-pad-x)}.checkbox-input[data-v-dc6ee178]{width:14px;height:14px}.checkbox-label[data-v-dc6ee178]{font-size:var(--header-chip-font-size)}.sort-group[data-v-dc6ee178]{justify-content:flex-start;width:auto}.search-input[data-v-dc6ee178]{width:130px;min-width:110px}.sort-select[data-v-dc6ee178]{height:var(--header-chip-height);padding:0 calc(var(--header-chip-pad-x) + 14px) 0 var(--header-chip-pad-x);font-size:var(--header-chip-font-size);flex:none}.hotkey-settings-btn[data-v-dc6ee178]{height:var(--header-chip-height);padding:0 var(--header-chip-pad-x);font-size:var(--header-chip-font-size);border-radius:8px}.hotkey-settings-btn svg[data-v-dc6ee178]{width:14px;height:14px}.task-info[data-v-dc6ee178]{justify-content:flex-start;width:auto}.info-item[data-v-dc6ee178]{height:var(--header-chip-height);padding:0 var(--header-chip-pad-x);font-size:var(--header-chip-font-size)}.empty[data-v-dc6ee178]{border-radius:16px;padding:30px 16px;font-size:16px}.tasks[data-v-dc6ee178]{gap:6px}}@media (width<=480px){.task-list[data-v-dc6ee178]{padding:0}.page-header[data-v-dc6ee178]{border-radius:14px;margin-bottom:6px;padding:4px 6px}.page-title[data-v-dc6ee178]{font-size:20px}.title-icon[data-v-dc6ee178]{width:22px;height:22px;padding:3px}.task-form[data-v-dc6ee178]{border-radius:14px;gap:6px;margin-bottom:6px;padding:6px}.task-input[data-v-dc6ee178]{border-radius:10px;padding:6px 8px;font-size:14px}.task-select[data-v-dc6ee178]{border-radius:10px;min-width:72px;padding:6px 8px;font-size:14px}.btn-add[data-v-dc6ee178]{border-radius:10px;padding:6px 12px;font-size:14px}.btn-add svg[data-v-dc6ee178]{width:14px;height:14px}.task-filters[data-v-dc6ee178]{border-radius:14px;flex-direction:row;align-items:center;gap:6px;margin-bottom:6px;padding:6px 8px}.checkbox-wrapper[data-v-dc6ee178]{height:var(--header-chip-height);padding:0 var(--header-chip-pad-x)}.checkbox-input[data-v-dc6ee178]{width:16px;height:16px}.checkbox-label[data-v-dc6ee178]{font-size:var(--header-chip-font-size)}.sort-group[data-v-dc6ee178]{justify-content:flex-start;width:auto}.search-input[data-v-dc6ee178]{width:120px;min-width:100px}.sort-select[data-v-dc6ee178]{height:var(--header-chip-height);padding:0 calc(var(--header-chip-pad-x) + 14px) 0 var(--header-chip-pad-x);font-size:var(--header-chip-font-size);flex:none}.hotkey-settings-btn[data-v-dc6ee178]{height:var(--header-chip-height);padding:0 var(--header-chip-pad-x);font-size:var(--header-chip-font-size);border-radius:8px}.hotkey-settings-btn svg[data-v-dc6ee178]{width:12px;height:12px}.hotkey-settings-btn span[data-v-dc6ee178]{display:none}.task-info[data-v-dc6ee178]{justify-content:flex-start;width:auto}.info-item[data-v-dc6ee178]{height:var(--header-chip-height);padding:0 var(--header-chip-pad-x);font-size:var(--header-chip-font-size)}.info-item svg[data-v-dc6ee178]{width:10px;height:10px}.empty[data-v-dc6ee178]{border-radius:14px;padding:25px 12px;font-size:16px}.tasks[data-v-dc6ee178]{gap:6px}}.hotkey-settings-overlay[data-v-ae88d5d6]{z-index:1000;background:#00000080;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.hotkey-settings-dialog[data-v-ae88d5d6]{background:#fff;border-radius:12px;width:90%;max-width:450px;overflow:hidden;box-shadow:0 20px 60px #0000004d}.dialog-header[data-v-ae88d5d6]{border-bottom:1px solid #e5e7eb;justify-content:space-between;align-items:center;padding:20px 24px;display:flex}.dialog-header h2[data-v-ae88d5d6]{color:#111827;margin:0;font-size:20px;font-weight:600}.close-button[data-v-ae88d5d6]{color:#6b7280;cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;width:32px;height:32px;padding:0;font-size:28px;transition:background .2s;display:flex}.close-button[data-v-ae88d5d6]:hover{color:#111827;background:#f3f4f6}.dialog-body[data-v-ae88d5d6]{padding:24px}.form-group[data-v-ae88d5d6]{margin-bottom:20px}.form-group label[data-v-ae88d5d6]{color:#374151;margin-bottom:8px;font-size:14px;font-weight:500;display:block}.form-group select[data-v-ae88d5d6]{cursor:pointer;background:#fff;border:1px solid #d1d5db;border-radius:6px;width:100%;padding:10px 12px;font-size:14px;transition:border-color .2s}.form-group select[data-v-ae88d5d6]:focus{border-color:#3b82f6;outline:none;box-shadow:0 0 0 3px #3b82f61a}.checkbox-label[data-v-ae88d5d6]{cursor:pointer;-webkit-user-select:none;user-select:none;align-items:center;display:flex}.checkbox-label input[type=checkbox][data-v-ae88d5d6]{cursor:pointer;accent-color:#3b82f6;width:18px;height:18px;margin-right:10px}.checkbox-label span[data-v-ae88d5d6]{font-weight:400}.preview[data-v-ae88d5d6]{background:#f9fafb;border:1px solid #e5e7eb;border-radius:8px;margin-top:24px;padding:16px}.preview strong[data-v-ae88d5d6]{color:#6b7280;text-transform:uppercase;letter-spacing:.5px;margin-bottom:8px;font-size:13px;display:block}.hotkey-preview[data-v-ae88d5d6]{color:#3b82f6;font-family:Consolas,Monaco,monospace;font-size:16px;font-weight:600}.dialog-footer[data-v-ae88d5d6]{background:#f9fafb;border-top:1px solid #e5e7eb;gap:12px;padding:20px 24px;display:flex}.btn[data-v-ae88d5d6]{cursor:pointer;border:none;border-radius:8px;flex:1;padding:12px 20px;font-size:14px;font-weight:500;transition:all .2s}.btn-primary[data-v-ae88d5d6]{color:#fff;background:#3b82f6}.btn-primary[data-v-ae88d5d6]:hover{background:#2563eb}.btn-secondary[data-v-ae88d5d6]{color:#374151;background:#fff;border:1px solid #d1d5db}.btn-secondary[data-v-ae88d5d6]:hover{background:#f3f4f6;border-color:#9ca3af}.overlay[data-v-c8c2626c]{z-index:1000;background:#00000080;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.dialog[data-v-c8c2626c]{background:#fff;border-radius:12px;width:92%;max-width:720px;overflow:hidden;box-shadow:0 20px 60px #0000004d}.dialog-header[data-v-c8c2626c]{border-bottom:1px solid #e5e7eb;justify-content:space-between;align-items:center;padding:16px 20px;display:flex}.dialog-header h2[data-v-c8c2626c]{color:#111827;margin:0;font-size:18px;font-weight:650}.close-button[data-v-c8c2626c]{color:#6b7280;cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;width:32px;height:32px;padding:0;font-size:28px;transition:background .2s;display:flex}.close-button[data-v-c8c2626c]:hover{color:#111827;background:#f3f4f6}.dialog-body[data-v-c8c2626c]{flex-direction:column;gap:16px;padding:18px 20px;display:flex}.section[data-v-c8c2626c]{background:#fff;border:1px solid #e5e7eb;border-radius:10px;padding:14px}.section-title[data-v-c8c2626c]{letter-spacing:.06em;color:#6b7280;text-transform:uppercase;margin-bottom:10px;font-size:12px;font-weight:700}.checkbox-row[data-v-c8c2626c]{-webkit-user-select:none;user-select:none;align-items:center;gap:10px;display:flex}.checkbox-row input[type=checkbox][data-v-c8c2626c]{cursor:pointer;accent-color:#3b82f6;width:18px;height:18px}.hint[data-v-c8c2626c]{color:#6b7280;margin-top:8px;font-size:12px;line-height:1.5}.mono[data-v-c8c2626c]{font-family:Consolas,Monaco,monospace;font-size:12px}.form-row[data-v-c8c2626c]{flex-wrap:wrap;align-items:center;gap:10px;display:flex}.text-input[data-v-c8c2626c]{background:#fff;border:1px solid #d1d5db;border-radius:8px;flex:1;min-width:240px;padding:10px 12px;font-size:14px;transition:border-color .2s,box-shadow .2s}.text-input[data-v-c8c2626c]:focus{border-color:#3b82f6;outline:none;box-shadow:0 0 0 3px #3b82f61a}.probe[data-v-c8c2626c]{background:#f9fafb;border:1px solid #e5e7eb;border-radius:10px;margin-top:10px;padding:10px 12px}.probe.success[data-v-c8c2626c]{background:#22c55e14;border-color:#22c55e40}.probe.warn[data-v-c8c2626c]{background:#f59e0b14;border-color:#f59e0b40}.probe.error[data-v-c8c2626c]{background:#ef444414;border-color:#ef444440}.probe-title[data-v-c8c2626c]{color:#111827;font-size:13px;font-weight:650}.probe-desc[data-v-c8c2626c]{color:#374151;margin-top:4px;font-size:12px;line-height:1.4}.button-row[data-v-c8c2626c]{flex-wrap:wrap;gap:10px;margin-top:10px;display:flex}.dialog-footer[data-v-c8c2626c]{background:#f9fafb;border-top:1px solid #e5e7eb;justify-content:flex-end;gap:12px;padding:14px 20px;display:flex}.btn[data-v-c8c2626c]{cursor:pointer;border:none;border-radius:10px;padding:10px 14px;font-size:13px;font-weight:600;transition:all .2s}.btn[data-v-c8c2626c]:disabled{opacity:.6;cursor:not-allowed}.btn-primary[data-v-c8c2626c]{color:#fff;background:#3b82f6}.btn-primary[data-v-c8c2626c]:hover:enabled{background:#2563eb}.btn-secondary[data-v-c8c2626c]{color:#374151;background:#fff;border:1px solid #d1d5db}.btn-secondary[data-v-c8c2626c]:hover:enabled{background:#f3f4f6;border-color:#9ca3af}*{box-sizing:border-box;margin:0;padding:0}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.app{background:linear-gradient(#f8fafc 0%,#f1f5f9 100%);width:100%;min-height:100vh}h1{text-align:center;color:#1f2937;margin-bottom:32px;font-size:32px;font-weight:700}.toast{z-index:9999;background:#fff;border-left:4px solid #ef4444;border-radius:12px;align-items:center;gap:12px;min-width:300px;max-width:90%;padding:12px 20px;display:flex;position:fixed;top:20px;left:50%;transform:translate(-50%);box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d}.toast.success{border-left-color:#22c55e}.toast.error{border-left-color:#ef4444}.toast-content{flex:1;align-items:center;gap:8px;display:flex}.toast-message{color:#1f2937;white-space:pre-line;font-size:14px;font-weight:500}.toast-close{color:#9ca3af;cursor:pointer;background:0 0;border:none;padding:0 4px;font-size:20px}.toast-close:hover{color:#4b5563}.toast-enter-active,.toast-leave-active{transition:all .3s cubic-bezier(.4,0,.2,1)}.toast-enter-from,.toast-leave-to{opacity:0;transform:translate(-50%,-20px)}
diff --git a/src/Hua.Todo.Avalonia/wwwroot/favicon.svg b/src/Hua.Todo.Avalonia/wwwroot/favicon.svg
new file mode 100644
index 0000000..6893eb1
--- /dev/null
+++ b/src/Hua.Todo.Avalonia/wwwroot/favicon.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/Hua.Todo.Avalonia/wwwroot/icons.svg b/src/Hua.Todo.Avalonia/wwwroot/icons.svg
new file mode 100644
index 0000000..e952219
--- /dev/null
+++ b/src/Hua.Todo.Avalonia/wwwroot/icons.svg
@@ -0,0 +1,24 @@
+
diff --git a/src/Hua.Todo.Avalonia/wwwroot/index.html b/src/Hua.Todo.Avalonia/wwwroot/index.html
new file mode 100644
index 0000000..aa97359
--- /dev/null
+++ b/src/Hua.Todo.Avalonia/wwwroot/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ Hua.Todo-web
+
+
+
+
+
+
+
diff --git a/src/Hua.Todo.Core/Hua.Todo.Core.csproj b/src/Hua.Todo.Core/Hua.Todo.Core.csproj
index 206c6e5..9ed914b 100644
--- a/src/Hua.Todo.Core/Hua.Todo.Core.csproj
+++ b/src/Hua.Todo.Core/Hua.Todo.Core.csproj
@@ -4,8 +4,6 @@
net10.0
enable
enable
- false
- false
diff --git a/src/Hua.Todo.Maui/Hua.Todo.Maui.csproj b/src/Hua.Todo.Maui/Hua.Todo.Maui.csproj
index 22607e8..4641e24 100644
--- a/src/Hua.Todo.Maui/Hua.Todo.Maui.csproj
+++ b/src/Hua.Todo.Maui/Hua.Todo.Maui.csproj
@@ -30,15 +30,10 @@
com.companyname.Hua.Todo.maui
- 1.2.1
- $(Version)
- 1
+
- 待办
- 待办
- Hua.Todo
- Copyright 2024
+
None
@@ -137,7 +132,7 @@
-
+
@@ -212,3 +207,5 @@
+
+
diff --git a/src/Hua.Todo.Maui/Platforms/Windows/MainPage.Windows.cs b/src/Hua.Todo.Maui/Platforms/Windows/MainPage.Windows.cs
index 7646af5..693613e 100644
--- a/src/Hua.Todo.Maui/Platforms/Windows/MainPage.Windows.cs
+++ b/src/Hua.Todo.Maui/Platforms/Windows/MainPage.Windows.cs
@@ -1,5 +1,6 @@
using Microsoft.Maui.Controls;
using Microsoft.Maui.ApplicationModel;
+using Microsoft.Maui.Handlers;
namespace Hua.Todo.Maui.Views
{
@@ -32,6 +33,20 @@ namespace Hua.Todo.Maui.Views
windowService.MinimizeWindow(window);
}
+ ///
+ /// 配置 WebView 滚动条行为。
+ ///
+ partial void ConfigureWebViewScrollBars()
+ {
+ // 使用 JavaScript 注入的方式禁用滚动条
+ MainWebView.EvaluateJavaScriptAsync(@"
+ // 禁用页面垂直滚动条
+ document.body.style.overflowY = 'hidden';
+ // 禁用整个文档的滚动
+ document.documentElement.style.overflowY = 'hidden';
+ ");
+ }
+
partial void PlatformPrepareWebViewContainer()
{
if (Platforms.Windows.WebView2RuntimeDetector.IsRuntimeInstalled(out _))
diff --git a/src/Hua.Todo.Maui/Views/MainPage.xaml.cs b/src/Hua.Todo.Maui/Views/MainPage.xaml.cs
index 484912c..490b5fb 100644
--- a/src/Hua.Todo.Maui/Views/MainPage.xaml.cs
+++ b/src/Hua.Todo.Maui/Views/MainPage.xaml.cs
@@ -119,9 +119,17 @@ namespace Hua.Todo.Maui.Views
}
});
");
+
+ // 配置 WebView 滚动条行为(平台特定实现)
+ ConfigureWebViewScrollBars();
};
}
+ ///
+ /// 配置 WebView 滚动条行为(平台特定实现)。
+ ///
+ partial void ConfigureWebViewScrollBars();
+
///
/// 规格化 URL(针对 Android 模拟器处理 localhost)。
/// Android 模拟器中 localhost 指向模拟器自身,需要替换为 10.0.2.2 才能访问宿主机服务。
diff --git a/src/Hua.Todo.Maui/setup.iss b/src/Hua.Todo.Maui/setup.iss
index b7005b1..7feb2e8 100644
--- a/src/Hua.Todo.Maui/setup.iss
+++ b/src/Hua.Todo.Maui/setup.iss
@@ -1,5 +1,5 @@
#define MyAppName "Hua.Todo"
-#define MyAppVersion "1.2.0"
+#define MyAppVersion "1.2.7"
#define MyAppPublisher "ShaoHua"
#define MyAppURL "https://git.we965.cn/Tools/Hua.Todo"
#define MyAppExeName "Hua.Todo.Maui.exe"
diff --git a/src/Hua.Todo.Web/package-lock.json b/src/Hua.Todo.Web/package-lock.json
index 27eca56..df30731 100644
--- a/src/Hua.Todo.Web/package-lock.json
+++ b/src/Hua.Todo.Web/package-lock.json
@@ -1,12 +1,13 @@
{
- "name": "Hua.Todo-web",
+ "name": "Hua.Todo-Web",
"version": "0.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
- "name": "Hua.Todo-web",
+ "name": "Hua.Todo-Web",
"version": "0.0.0",
+ "license": "AGPL-3.0",
"dependencies": {
"axios": "^1.13.6",
"pinia": "^3.0.4",
diff --git a/src/Hua.Todo.Web/public/favicon.svg b/src/Hua.Todo.Web/public/favicon.svg
index 6893eb1..9d63b65 100644
--- a/src/Hua.Todo.Web/public/favicon.svg
+++ b/src/Hua.Todo.Web/public/favicon.svg
@@ -1 +1,4 @@
-
\ No newline at end of file
+
+
\ No newline at end of file