From 1412ce26957f0c4fc9172f005982e3a7936971c0 Mon Sep 17 00:00:00 2001
From: ShaoHua <345265198@qqcom>
Date: Sat, 4 Apr 2026 22:11:18 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E9=87=8D=E6=9E=84=20TodoList=20?=
=?UTF-8?q?=E6=9E=B6=E6=9E=84=EF=BC=8C=E6=96=B0=E5=A2=9E=E5=8A=A8=E6=80=81?=
=?UTF-8?q?=20API=20=E4=B8=8E=20MAUI=20=E5=86=85=E5=B5=8C=20Web=20?=
=?UTF-8?q?=E6=9C=8D=E5=8A=A1=20feat:=E4=BC=98=E5=8C=96=E4=BA=A4=E4=BA=92?=
=?UTF-8?q?=E9=80=BB=E8=BE=91,=E4=BC=98=E5=8C=96=E5=8F=91=E5=B8=83?=
=?UTF-8?q?=E6=B5=81=E7=A8=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 3 +
.vscode/launch.json | 35 +
.vscode/tasks.json | 41 ++
Publish.ps1 | 62 ++
README.md | 2 +-
SCRIPTS_README.md | 388 ----------
TodoList.slnx | 3 +-
TodoList/App.xaml.cs | 44 +-
TodoList/TodoList.csproj | 1 +
TodoList/ViewModels/MainViewModel.cs | 2 -
TodoList/Views/MainWindow.xaml | 2 +-
TodoList/Views/MainWindow.xaml.cs | 2 +-
docs/实现对比文档.md | 2 +-
restart-service.ps1 | 92 ---
restart-web.ps1 | 101 +++
.../Controllers/TasksController.cs | 291 --------
src/TodoList.Api/Models/TaskModels.cs | 117 ---
.../Repositories/TaskRepository.cs | 122 ----
src/TodoList.Api/Services/TaskService.cs | 185 -----
src/TodoList.Api/TodoList.Api.http | 6 -
.../Data/TodoDbContext.cs | 25 +-
.../DynamicApi/DynamicApiExtensions.cs | 11 +
.../DynamicApi/DynamicApiMiddleware.cs | 637 ++++++++++++++++
.../DynamicApi/HttpAttributes.cs | 76 ++
.../DynamicApi/ParameterBindingAttributes.cs | 11 +
.../DynamicApi/RemoteServiceAttribute.cs | 8 +
.../Interfaces/IDynamicApiService.cs | 5 +
.../Interfaces/ITaskService.cs | 17 +
.../20260313044926_InitialCreate.Designer.cs | 8 +-
.../20260313044926_InitialCreate.cs | 4 +-
...20260313092658_AddParentTaskId.Designer.cs | 14 +-
.../20260313092658_AddParentTaskId.cs | 4 +-
.../Migrations/TodoDbContextModelSnapshot.cs | 14 +-
src/TodoList.Application/Models/TaskModels.cs | 47 ++
.../Properties/launchSettings.json | 12 +
.../Repositories/TaskRepository.cs | 79 ++
.../ServiceCollectionExtensions.cs | 23 +
.../Services/TaskService.cs | 127 ++++
.../TodoList.Application.csproj | 22 +
src/TodoList.Core/Class1.cs | 6 -
.../Entities/{Task.cs => TaskEntity.cs} | 6 +-
.../Interfaces/ITaskRepository.cs | 20 +-
src/TodoList.Core/Interfaces/ITaskService.cs | 73 --
src/TodoList.Core/TodoList.Core.csproj | 4 +-
.../Program.cs | 30 +-
.../Properties/launchSettings.json | 6 +-
.../TodoList.Host.csproj} | 6 +-
.../appsettings.Development.json | 0
.../appsettings.json | 0
.../todolist.db | Bin 32768 -> 32768 bytes
src/TodoList.Maui/App.xaml.cs | 230 +++++-
src/TodoList.Maui/AppShell.xaml | 2 -
src/TodoList.Maui/BuildSetup.ps1 | 55 --
src/TodoList.Maui/MauiProgram.cs | 83 ++-
src/TodoList.Maui/Models/AppSettings.cs | 44 ++
.../Platforms/Windows/WindowsWindowService.cs | 42 +-
src/TodoList.Maui/README.md | 2 +-
.../Resources/Images/app_titlebar_icon.svg | 8 +
.../Resources/Images/titlebar_icon.png | Bin 0 -> 106636 bytes
src/TodoList.Maui/Services/AppMetadata.cs | 60 ++
.../Services/EmbeddedWebServerService.cs | 138 ++++
.../Services/HotKeySettingsService.cs | 48 +-
.../Services/IEmbeddedWebServerService.cs | 9 +
.../Platforms/WindowsGlobalHotKeyService.cs | 104 ++-
.../Platforms/WindowsSystemTrayService.cs | 17 +-
src/TodoList.Maui/TodoList.Maui.csproj | 82 ++-
.../TodoList.Maui.csproj.DotSettings | 2 +
.../ViewModels/QuickEntryViewModel.cs | 53 --
src/TodoList.Maui/Views/MainPage.xaml | 30 +-
src/TodoList.Maui/Views/MainPage.xaml.cs | 63 +-
src/TodoList.Maui/Views/QuickEntryPage.xaml | 46 --
.../Views/QuickEntryPage.xaml.cs | 22 -
src/TodoList.Maui/appsettings.json | 16 +
src/TodoList.Maui/icon.jpg | Bin 0 -> 50666 bytes
src/TodoList.Maui/setup.iss | 35 +-
src/TodoList.Web/src/App.vue | 103 ++-
src/TodoList.Web/src/api/client.ts | 55 +-
src/TodoList.Web/src/api/tasks.ts | 137 +++-
.../src/components/HotKeySettingsDialog.vue | 4 +-
.../src/components/TaskEditDialog.vue | 147 ++--
src/TodoList.Web/src/components/TaskItem.vue | 486 ++++++++++---
src/TodoList.Web/src/components/TaskList.vue | 677 ++++++++++--------
.../src/services/localStorageService.ts | 5 +-
.../src/services/taskNormalizer.ts | 68 ++
src/TodoList.Web/src/style.css | 8 +-
src/TodoList.Web/src/types/task.ts | 3 +-
src/TodoList.Web/vite.config.ts | 19 +-
start-forend.ps1 | 81 +++
start-maui.ps1 | 96 +++
start-service.ps1 | 128 ----
stop-service.ps1 | 97 ---
91 files changed, 3612 insertions(+), 2489 deletions(-)
create mode 100644 .vscode/launch.json
create mode 100644 .vscode/tasks.json
create mode 100644 Publish.ps1
delete mode 100644 SCRIPTS_README.md
delete mode 100644 restart-service.ps1
create mode 100644 restart-web.ps1
delete mode 100644 src/TodoList.Api/Controllers/TasksController.cs
delete mode 100644 src/TodoList.Api/Models/TaskModels.cs
delete mode 100644 src/TodoList.Api/Repositories/TaskRepository.cs
delete mode 100644 src/TodoList.Api/Services/TaskService.cs
delete mode 100644 src/TodoList.Api/TodoList.Api.http
rename src/{TodoList.Api => TodoList.Application}/Data/TodoDbContext.cs (54%)
create mode 100644 src/TodoList.Application/DynamicApi/DynamicApiExtensions.cs
create mode 100644 src/TodoList.Application/DynamicApi/DynamicApiMiddleware.cs
create mode 100644 src/TodoList.Application/DynamicApi/HttpAttributes.cs
create mode 100644 src/TodoList.Application/DynamicApi/ParameterBindingAttributes.cs
create mode 100644 src/TodoList.Application/DynamicApi/RemoteServiceAttribute.cs
create mode 100644 src/TodoList.Application/Interfaces/IDynamicApiService.cs
create mode 100644 src/TodoList.Application/Interfaces/ITaskService.cs
rename src/{TodoList.Api => TodoList.Application}/Migrations/20260313044926_InitialCreate.Designer.cs (91%)
rename src/{TodoList.Api => TodoList.Application}/Migrations/20260313044926_InitialCreate.cs (96%)
rename src/{TodoList.Api => TodoList.Application}/Migrations/20260313092658_AddParentTaskId.Designer.cs (85%)
rename src/{TodoList.Api => TodoList.Application}/Migrations/20260313092658_AddParentTaskId.cs (93%)
rename src/{TodoList.Api => TodoList.Application}/Migrations/TodoDbContextModelSnapshot.cs (85%)
create mode 100644 src/TodoList.Application/Models/TaskModels.cs
create mode 100644 src/TodoList.Application/Properties/launchSettings.json
create mode 100644 src/TodoList.Application/Repositories/TaskRepository.cs
create mode 100644 src/TodoList.Application/ServiceCollectionExtensions.cs
create mode 100644 src/TodoList.Application/Services/TaskService.cs
create mode 100644 src/TodoList.Application/TodoList.Application.csproj
delete mode 100644 src/TodoList.Core/Class1.cs
rename src/TodoList.Core/Entities/{Task.cs => TaskEntity.cs} (89%)
delete mode 100644 src/TodoList.Core/Interfaces/ITaskService.cs
rename src/{TodoList.Api => TodoList.Host}/Program.cs (52%)
rename src/{TodoList.Api => TodoList.Host}/Properties/launchSettings.json (90%)
rename src/{TodoList.Api/TodoList.Api.csproj => TodoList.Host/TodoList.Host.csproj} (69%)
rename src/{TodoList.Api => TodoList.Host}/appsettings.Development.json (100%)
rename src/{TodoList.Api => TodoList.Host}/appsettings.json (100%)
rename src/{TodoList.Api => TodoList.Host}/todolist.db (97%)
delete mode 100644 src/TodoList.Maui/BuildSetup.ps1
create mode 100644 src/TodoList.Maui/Models/AppSettings.cs
create mode 100644 src/TodoList.Maui/Resources/Images/app_titlebar_icon.svg
create mode 100644 src/TodoList.Maui/Resources/Images/titlebar_icon.png
create mode 100644 src/TodoList.Maui/Services/AppMetadata.cs
create mode 100644 src/TodoList.Maui/Services/EmbeddedWebServerService.cs
create mode 100644 src/TodoList.Maui/Services/IEmbeddedWebServerService.cs
create mode 100644 src/TodoList.Maui/TodoList.Maui.csproj.DotSettings
delete mode 100644 src/TodoList.Maui/ViewModels/QuickEntryViewModel.cs
delete mode 100644 src/TodoList.Maui/Views/QuickEntryPage.xaml
delete mode 100644 src/TodoList.Maui/Views/QuickEntryPage.xaml.cs
create mode 100644 src/TodoList.Maui/appsettings.json
create mode 100644 src/TodoList.Maui/icon.jpg
create mode 100644 src/TodoList.Web/src/services/taskNormalizer.ts
create mode 100644 start-forend.ps1
create mode 100644 start-maui.ps1
delete mode 100644 start-service.ps1
delete mode 100644 stop-service.ps1
diff --git a/.gitignore b/.gitignore
index 16c6ee3..321a810 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,6 +37,7 @@ bld/
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
+src/TodoList.Maui/wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
@@ -363,3 +364,5 @@ MigrationBackup/
FodyWeavers.xsd
/Setup/Output
/TodoList/Output
+/src/TodoList.Maui/Output
+/src/TodoList.Host/todolist.db
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..0532146
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,35 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ // 使用 IntelliSense 找出 C# 调试存在哪些属性
+ // 将悬停用于现有属性的说明
+ // 有关详细信息,请访问 https://github.com/dotnet/vscode-csharp/blob/main/debugger-launchjson.md。
+ "name": ".NET Core Launch (web)",
+ "type": "coreclr",
+ "request": "launch",
+ "preLaunchTask": "build",
+ // 如果已更改目标框架,请确保更新程序路径。
+ "program": "${workspaceFolder}/src/TodoList.Host/bin/Debug/net10.0/TodoList.Host.dll",
+ "args": [],
+ "cwd": "${workspaceFolder}/src/TodoList.Host",
+ "stopAtEntry": false,
+ // 启用在启动 ASP.NET Core 时启动 Web 浏览器。有关详细信息: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
+ "serverReadyAction": {
+ "action": "openExternally",
+ "pattern": "\\bNow listening on:\\s+(https?://\\S+)"
+ },
+ "env": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "sourceFileMap": {
+ "/Views": "${workspaceFolder}/Views"
+ }
+ },
+ {
+ "name": ".NET Core Attach",
+ "type": "coreclr",
+ "request": "attach"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..bcea2f5
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,41 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "build",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "build",
+ "${workspaceFolder}/src/TodoList.Host/TodoList.Host.csproj",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary;ForceNoAlign"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "publish",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "publish",
+ "${workspaceFolder}/src/TodoList.Host/TodoList.Host.csproj",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary;ForceNoAlign"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "watch",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "watch",
+ "run",
+ "--project",
+ "${workspaceFolder}/src/TodoList.Host/TodoList.Host.csproj"
+ ],
+ "problemMatcher": "$msCompile"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Publish.ps1 b/Publish.ps1
new file mode 100644
index 0000000..fe52246
--- /dev/null
+++ b/Publish.ps1
@@ -0,0 +1,62 @@
+$ErrorActionPreference = "Stop"
+
+$ScriptPath = $PSScriptRoot
+$ProjectDir = Join-Path $ScriptPath "src\TodoList.Maui"
+$ProjectFile = Join-Path $ProjectDir "TodoList.Maui.csproj"
+$SetupScript = Join-Path $ProjectDir "setup.iss"
+
+# Read version from project file
+$currentVersion = "1.0.0"
+[xml]$csproj = Get-Content $ProjectFile -Raw
+$versionNode = $csproj.SelectSingleNode("//Version")
+if ($null -ne $versionNode) {
+ $currentVersion = $versionNode.InnerText
+} else {
+ $versionNode = $csproj.SelectSingleNode("//ApplicationDisplayVersion")
+ if ($null -ne $versionNode) {
+ $currentVersion = $versionNode.InnerText
+ }
+}
+
+# Update setup script version with current version before build
+if (Test-Path $SetupScript) {
+ $issContent = Get-Content $SetupScript
+ $versionFound = $false
+ for ($i = 0; $i -lt $issContent.Count; $i++) {
+ if ($issContent[$i] -like '#define MyAppVersion *') {
+ $issContent[$i] = '#define MyAppVersion "' + $currentVersion + '"'
+ $versionFound = $true
+ break
+ }
+ }
+ if ($versionFound) {
+ Set-Content $SetupScript -Value $issContent
+ }
+}
+
+Write-Host "Building TodoList.Maui (Release)..." -ForegroundColor Cyan
+dotnet publish $ProjectFile -f net10.0-windows10.0.19041.0 -c Release --self-contained false
+if ($LASTEXITCODE -ne 0) {
+ Write-Error "MAUI build failed"
+ exit 1
+}
+
+$ISCC = "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe"
+if (Test-Path $ISCC) {
+ & $ISCC $SetupScript
+ if ($LASTEXITCODE -eq 0) {
+ Write-Host "Setup package created successfully!" -ForegroundColor Green
+ } else {
+ Write-Error "Packaging failed"
+ }
+} else {
+ Write-Error "Inno Setup compiler not found"
+}
+
+$versionParts = $currentVersion.Split(".")
+$patch = [int]$versionParts[2] + 1
+$newVersion = $versionParts[0] + "." + $versionParts[1] + "." + $patch
+
+$content = Get-Content $ProjectFile -Raw
+$content = $content -replace ".*", "$newVersion"
+Set-Content $ProjectFile -Value $content
diff --git a/README.md b/README.md
index cb18958..22738db 100644
--- a/README.md
+++ b/README.md
@@ -64,7 +64,7 @@ dotnet restore
dotnet ef database update
dotnet run
```
-API 将在 `http://localhost:5057` 启动
+API 将在 `http://localhost:5173` 启动
#### 3. 启动前端 Web
```bash
diff --git a/SCRIPTS_README.md b/SCRIPTS_README.md
deleted file mode 100644
index c78d47e..0000000
--- a/SCRIPTS_README.md
+++ /dev/null
@@ -1,388 +0,0 @@
-# TodoList 服务管理脚本
-
-本目录包含用于管理 TodoList 服务的 PowerShell 脚本。
-
-## 脚本列表
-
-### 1. `start-service.ps1` - 启动服务
-启动 TodoList.Api 服务和 TodoList.Maui 应用。
-
-#### 使用方法
-```powershell
-# 启动 API 服务和 MAUI 应用(默认)
-.\start-service.ps1
-
-# 只启动 API 服务
-.\start-service.ps1 -StartMaui:$false
-```
-
-#### 功能
-- 检查 TodoList.Api 服务是否已在运行
-- 如果未运行,启动 TodoList.Api 服务
-- 默认启动 TodoList.Maui 应用(可通过 `-StartMaui:$false` 禁用)
-- 显示服务访问地址和 Swagger 文档链接
-
-#### 输出示例
-```
-====================================
- TodoList 服务启动脚本
-====================================
-
-[1/2] 检查 TodoList.Api 服务...
-✓ TodoList.Api 服务未运行
-
-[2/2] 启动 TodoList.Api 服务...
-📂 工作目录: D:\Proj\TodoList\src\TodoList.Api
-🚀 启动服务...
-✅ TodoList.Api 服务已启动
- 进程 ID: 65992
- 访问地址: http://localhost:5057
- Swagger 文档: http://localhost:5057/swagger
-
-[3/3] 启动 TodoList.Maui 应用...
-🚀 启动 TodoList.Maui...
-✅ TodoList.Maui 已启动
-
-====================================
- 启动完成
-====================================
-
-💡 提示:
- - 按 Ctrl+C 可以停止服务
- - 运行 stop-service.ps1 可以关闭服务
- - 运行 restart-service.ps1 可以重启服务
-```
-
----
-
-### 2. `stop-service.ps1` - 关闭服务
-停止所有正在运行的 TodoList.Api 服务和 TodoList.Maui 应用。
-
-#### 使用方法
-```powershell
-# 正常关闭
-.\stop-service.ps1
-
-# 强制关闭
-.\stop-service.ps1 -Force
-```
-
-#### 功能
-- 查找并停止所有 TodoList.Api 进程
-- 查找并停止所有 TodoList.Maui 进程
-- 显示停止的进程数量和状态
-
-#### 输出示例
-```
-====================================
- TodoList 服务关闭脚本
-====================================
-
-[1/2] 查找 TodoList.Api 服务...
-🔍 找到 1 个 TodoList.Api 进程
- 正在停止进程 ID: 65992...
- ✅ 进程 65992 已停止
-
-[2/2] 查找 TodoList.Maui 应用...
-✓ TodoList.Maui 应用未运行
-
-====================================
- 关闭完成
- 已停止 1 个进程
-====================================
-
-💡 提示:
- - 运行 start-service.ps1 可以启动服务
- - 运行 restart-service.ps1 可以重启服务
-```
-
----
-
-### 3. `restart-service.ps1` - 重启服务
-停止现有服务并重新启动。
-
-#### 使用方法
-```powershell
-# 重启 API 服务
-.\restart-service.ps1
-
-# 重启 API 和 MAUI 应用
-.\restart-service.ps1 -StartMaui
-
-# 强制重启
-.\restart-service.ps1 -Force
-```
-
-#### 功能
-- 调用 stop-service.ps1 停止现有服务
-- 等待进程完全关闭(最多 10 秒)
-- 调用 start-service.ps1 启动服务
-- 显示重启进度和状态
-
-#### 输出示例
-```
-====================================
- TodoList 服务重启脚本
-====================================
-
-[1/3] 停止现有服务...
-✅ 服务已停止
-
-[2/3] 等待进程完全关闭...
-✅ 所有进程已关闭
-
-[3/3] 启动服务...
-✅ 服务已启动
-
-====================================
- 重启完成
-====================================
-
-💡 提示:
- - 按 Ctrl+C 可以停止服务
- - 运行 stop-service.ps1 可以关闭服务
- - 运行 restart-service.ps1 可以重启服务
-```
-
----
-
-### 4. `BuildSetup.ps1` - 构建安装包
-构建 TodoList.Maui 项目的 Release 版本并创建 Inno Setup 安装包。
-
-#### 使用方法
-```powershell
-# 在 TodoList 目录下运行
-.\TodoList\BuildSetup.ps1
-```
-
-#### 功能
-- 自动读取项目版本号
-- 自动递增补丁版本号(例如 1.0.0 → 1.0.1)
-- 更新 .csproj 文件中的版本号
-- 更新 setup.iss 文件中的版本号
-- 构建 Release 版本(win-x64)
-- 使用 Inno Setup 编译器创建安装包
-
-#### 输出示例
-```
-Setup package created successfully!
-```
-
-#### 依赖项
-- .NET SDK
-- Inno Setup 6(默认路径:`C:\Program Files (x86)\Inno Setup 6\ISCC.exe`)
-
----
-
-## 参数说明
-
-### `start-service.ps1`
-| 参数 | 类型 | 默认值 | 说明 |
-|------|------|----------|------|
-| `-StartMaui` | Switch | `$true` | 是否启动 TodoList.Maui 应用(默认启用) |
-| `-ServicePath` | String | `"src\TodoList.Api"` | API 服务相对路径 |
-| `-MauiPath` | String | `"src\TodoList.Maui"` | MAUI 应用相对路径 |
-
-### `stop-service.ps1`
-| 参数 | 类型 | 默认值 | 说明 |
-|------|------|----------|------|
-| `-Force` | Switch | `$false` | 是否强制关闭进程 |
-
-### `restart-service.ps1`
-| 参数 | 类型 | 默认值 | 说明 |
-|------|------|----------|------|
-| `-StartMaui` | Switch | `$false` | 是否同时启动 TodoList.Maui 应用 |
-| `-Force` | Switch | `$false` | 是否强制关闭进程 |
-
-### `BuildSetup.ps1`
-| 参数 | 类型 | 默认值 | 说明 |
-|------|------|----------|------|
-| 无 | - | - | 脚本自动检测项目文件并处理 |
-
----
-
-## 使用场景
-
-### 场景 1: 首次启动
-```powershell
-# 启动 API 服务和 MAUI 应用(默认)
-.\start-service.ps1
-
-# 访问 http://localhost:5057 查看服务
-# 访问 http://localhost:5057/swagger 查看 API 文档
-```
-
-### 场景 2: 只启动 API 服务
-```powershell
-# 只启动 API 服务,不启动 MAUI 应用
-.\start-service.ps1 -StartMaui:$false
-```
-
-### 场景 3: 开发调试
-```powershell
-# 启动 API 和 MAUI 应用(默认行为)
-.\start-service.ps1
-
-# 使用 Alt+X 快捷键唤醒 MAUI 应用
-# 在 MAUI 应用中测试快捷键功能
-```
-
-### 场景 4: 代码修改后重启
-```powershell
-# 快速重启服务
-.\restart-service.ps1
-
-# 重启服务并启动 MAUI 应用
-.\restart-service.ps1 -StartMaui
-
-# 或者强制重启(如果进程卡住)
-.\restart-service.ps1 -Force
-```
-
-### 场景 5: 完全关闭
-```powershell
-# 关闭所有服务
-.\stop-service.ps1
-
-# 或者强制关闭
-.\stop-service.ps1 -Force
-```
-
-### 场景 6: 构建安装包
-```powershell
-# 在 TodoList 目录下构建安装包
-.\TodoList\BuildSetup.ps1
-
-# 脚本会自动:
-# 1. 递增版本号
-# 2. 构建 Release 版本
-# 3. 创建 Inno Setup 安装包
-```
-
----
-
-## 注意事项
-
-1. **PowerShell 执行策略**
- - 如果遇到执行策略错误,运行:`Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser`
- - 或者临时绕过:`powershell -ExecutionPolicy Bypass -File .\start-service.ps1`
-
-2. **进程检测**
- - 脚本通过进程名称和窗口标题检测 TodoList.Api 服务
- - 脚本通过进程名称检测 TodoList.Maui 应用
-
-3. **端口占用**
- - 如果端口 5057 被占用,启动会失败
- - 使用 `netstat -ano | findstr :5057` 检查端口占用情况
-
-4. **MAUI 应用构建**
- - 如果 MAUI 应用不存在,需要先构建:`dotnet build src\TodoList.Maui\TodoList.Maui.csproj`
- - 默认路径:`src\TodoList.Maui\bin\Debug\net10.0-windows10.0.19041.0\win-x64\TodoList.Maui.exe`
-
-5. **快捷键功能**
- - MAUI 应用启动后,默认快捷键为 `Alt + X`
- - 可以在应用设置中自定义快捷键
-
----
-
-## 故障排除
-
-### 问题 1: 无法启动服务
-**症状**: 运行 `start-service.ps1` 后服务未启动
-
-**解决方案**:
-1. 检查 .NET SDK 是否安装:`dotnet --version`
-2. 检查项目路径是否正确
-3. 查看错误信息:`dotnet run src\TodoList.Api\TodoList.Api.csproj`
-
-### 问题 2: 无法停止服务
-**症状**: 运行 `stop-service.ps1` 后进程仍在运行
-
-**解决方案**:
-1. 使用强制关闭:`.\stop-service.ps1 -Force`
-2. 手动结束进程:`taskkill /F /IM dotnet.exe`
-3. 检查是否有其他 dotnet 进程占用
-
-### 问题 3: MAUI 应用无法启动
-**症状**: 运行 `start-service.ps1` 后 MAUI 应用未启动
-
-**解决方案**:
-1. 先构建 MAUI 项目:`dotnet build src\TodoList.Maui\TodoList.Maui.csproj`
-2. 检查可执行文件是否存在
-3. 查看构建错误信息
-
-### 问题 4: BuildSetup.ps1 无法构建安装包
-**症状**: 运行 `.\TodoList\BuildSetup.ps1` 后构建失败
-
-**解决方案**:
-1. 检查 Inno Setup 是否已安装:`Test-Path "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe"`
-2. 如果未安装,请从 https://jrsoftware.org/isdl.php 下载安装
-3. 检查 .NET SDK 是否安装:`dotnet --version`
-4. 检查项目文件是否存在:`Test-Path .\TodoList\TodoList.csproj`
-5. 检查 setup.iss 文件是否存在:`Test-Path .\TodoList\setup.iss`
-
-### 问题 5: 版本号未正确递增
-**症状**: 运行 BuildSetup.ps1 后版本号未变化
-
-**解决方案**:
-1. 检查 .csproj 文件中是否有 `` 标签
-2. 确保版本号格式为 `X.Y.Z`(三个数字用点分隔)
-3. 手动检查并修复版本号格式
-
----
-
-## 快捷命令
-
-```powershell
-# 启动服务(API + MAUI,默认)
-.\start-service.ps1
-
-# 只启动 API 服务
-.\start-service.ps1 -StartMaui:$false
-
-# 关闭服务
-.\stop-service.ps1
-
-# 重启服务
-.\restart-service.ps1
-
-# 重启服务并启动 MAUI 应用
-.\restart-service.ps1 -StartMaui
-
-# 强制关闭
-.\stop-service.ps1 -Force
-
-# 强制重启
-.\restart-service.ps1 -Force
-
-# 构建安装包
-.\TodoList\BuildSetup.ps1
-```
-
----
-
-## 技术细节
-
-- **脚本语言**: PowerShell 5.1+
-- **目标平台**: Windows
-- **依赖**: .NET SDK, dotnet CLI
-- **错误处理**: 支持错误捕获和友好提示
-- **日志输出**: 彩色输出,易于阅读
-
----
-
-## 更新日志
-
-### v1.1.0 (2026-03-18)
-- 新增 `BuildSetup.ps1` 脚本,支持自动构建安装包
-- 更新 `start-service.ps1`,默认启动 MAUI 应用(`-StartMaui` 默认值为 `$true`)
-- 优化所有脚本的输出格式,添加提示信息
-- 更新文档,修正参数默认值说明
-- 添加 BuildSetup.ps1 相关故障排除指南
-
-### v1.0.0 (2026-03-13)
-- 初始版本
-- 实现启动、关闭、重启服务功能
-- 支持 TodoList.Api 和 TodoList.Maui 应用管理
-- 添加参数支持和错误处理
-- 彩色输出和友好提示
\ No newline at end of file
diff --git a/TodoList.slnx b/TodoList.slnx
index e12c6c2..e6f9e0e 100644
--- a/TodoList.slnx
+++ b/TodoList.slnx
@@ -6,7 +6,8 @@
-
+
+
\ No newline at end of file
diff --git a/TodoList/App.xaml.cs b/TodoList/App.xaml.cs
index df48065..033b4e6 100644
--- a/TodoList/App.xaml.cs
+++ b/TodoList/App.xaml.cs
@@ -7,17 +7,19 @@ using TodoList.Services;
using TodoList.ViewModels;
using TodoList.Views;
using System.Linq;
+using System.Reflection;
namespace TodoList
{
public partial class App : System.Windows.Application
{
+ private const string MainWindowTitle = "待办事项";
private IDataService _dataService;
private GlobalShortcutService _shortcutService;
private MainWindow _mainWindow;
private QuickEntryWindow? _quickEntryWindow;
private SettingsService _settingsService;
- private System.Windows.Forms.NotifyIcon _notifyIcon;
+ private NotifyIcon _notifyIcon;
private Mutex _mutex;
private EventWaitHandle _eventWaitHandle;
private const string UniqueEventName = "Global\\TodoListApp_Event_v1";
@@ -60,7 +62,7 @@ namespace TodoList
catch
{
// Fallback to old method if event open fails
- var hWnd = FindWindow(null, "待办事项");
+ var hWnd = FindWindow(null, MainWindowTitle);
if (hWnd != IntPtr.Zero)
{
ShowWindow(hWnd, 9); // SW_RESTORE
@@ -108,6 +110,7 @@ namespace TodoList
var mainViewModel = new MainViewModel(_dataService, _settingsService);
_mainWindow = new MainWindow(mainViewModel);
+ _mainWindow.Title = MainWindowTitle;
_mainWindow.Loaded += MainWindow_Loaded;
// Initialize Tray Icon
@@ -132,7 +135,7 @@ namespace TodoList
{
try
{
- var exePath = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
+ var exePath = System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName;
string cmd = $"\"{exePath}\" --silent";
// If running as dotnet tool, try to find the shim or stable entry point
@@ -168,7 +171,7 @@ namespace TodoList
private void InitializeTrayIcon()
{
- _notifyIcon = new System.Windows.Forms.NotifyIcon();
+ _notifyIcon = new NotifyIcon();
// Try load icon from resource or file
try
@@ -195,15 +198,43 @@ namespace TodoList
}
_notifyIcon.Visible = true;
- _notifyIcon.Text = "TodoList";
+ _notifyIcon.Text = GetNotifyIconText();
_notifyIcon.DoubleClick += (s, e) => ShowMainWindow();
- var contextMenu = new System.Windows.Forms.ContextMenuStrip();
+ var contextMenu = new ContextMenuStrip();
contextMenu.Items.Add("打开主界面", null, (s, e) => ShowMainWindow());
contextMenu.Items.Add("退出", null, (s, e) => ExitApplication());
_notifyIcon.ContextMenuStrip = contextMenu;
}
+ private static string GetNotifyIconText()
+ {
+ var version = GetDisplayVersion();
+ var text = string.IsNullOrWhiteSpace(version) ? MainWindowTitle : $"{MainWindowTitle} v{version}";
+
+ return text.Length > 63 ? text[..63] : text;
+ }
+
+ private static string? GetDisplayVersion()
+ {
+ var asm = Assembly.GetExecutingAssembly();
+
+ var info = asm.GetCustomAttribute()?.InformationalVersion?.Trim();
+ if (!string.IsNullOrWhiteSpace(info))
+ {
+ var plus = info.IndexOf('+');
+ return plus >= 0 ? info[..plus] : info;
+ }
+
+ var file = asm.GetCustomAttribute()?.Version?.Trim();
+ if (!string.IsNullOrWhiteSpace(file))
+ {
+ return file;
+ }
+
+ return asm.GetName().Version?.ToString();
+ }
+
private void ShowMainWindow()
{
Log("ShowMainWindow called");
@@ -298,6 +329,7 @@ namespace TodoList
if (_quickEntryWindow == null)
{
_quickEntryWindow = new QuickEntryWindow(_dataService);
+ _quickEntryWindow.Title = "新建待办";
}
if (_quickEntryWindow.WindowState == WindowState.Minimized)
diff --git a/TodoList/TodoList.csproj b/TodoList/TodoList.csproj
index ceb6fe5..f8328a4 100644
--- a/TodoList/TodoList.csproj
+++ b/TodoList/TodoList.csproj
@@ -5,6 +5,7 @@
net8.0-windows
enable
enable
+ 65001
true
true
icon.ico
diff --git a/TodoList/ViewModels/MainViewModel.cs b/TodoList/ViewModels/MainViewModel.cs
index c0afc50..83c7454 100644
--- a/TodoList/ViewModels/MainViewModel.cs
+++ b/TodoList/ViewModels/MainViewModel.cs
@@ -55,8 +55,6 @@ namespace TodoList.ViewModels
[ObservableProperty]
private Models.SortOrder sortOrder = Models.SortOrder.Descending;
- public string AppVersion => System.Reflection.Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "1.0.0";
-
public string FullShortcut
{
get
diff --git a/TodoList/Views/MainWindow.xaml b/TodoList/Views/MainWindow.xaml
index 58a45d6..1fd19d8 100644
--- a/TodoList/Views/MainWindow.xaml
+++ b/TodoList/Views/MainWindow.xaml
@@ -114,7 +114,7 @@
-
diff --git a/TodoList/Views/MainWindow.xaml.cs b/TodoList/Views/MainWindow.xaml.cs
index 90ad15c..adef138 100644
--- a/TodoList/Views/MainWindow.xaml.cs
+++ b/TodoList/Views/MainWindow.xaml.cs
@@ -28,7 +28,7 @@ namespace TodoList.Views
// If settings are open, close settings?
// But user requirement is "Equals pressing X button", which usually means Close/Hide window.
// However, if we want better UX:
- if (DataContext is MainViewModel vm && vm.IsSettingsOpen)
+ if (DataContext is MainViewModel { IsSettingsOpen: true } vm)
{
vm.IsSettingsOpen = false;
e.Handled = true;
diff --git a/docs/实现对比文档.md b/docs/实现对比文档.md
index 9992e8b..9d7cd78 100644
--- a/docs/实现对比文档.md
+++ b/docs/实现对比文档.md
@@ -182,7 +182,7 @@
## 当前运行状态
### 服务状态
-- ✅ **TodoList.Api**: 运行中 (http://localhost:5057)
+- ✅ **TodoList.Api**: 运行中 (http://localhost:5173)
- ✅ **TodoList.Web**: 运行中 (http://localhost:5173)
- ✅ **TodoList.Maui**: 运行中 (Windows 桌面应用)
diff --git a/restart-service.ps1 b/restart-service.ps1
deleted file mode 100644
index 7b03cc9..0000000
--- a/restart-service.ps1
+++ /dev/null
@@ -1,92 +0,0 @@
-param(
- [switch]$StartMaui = $false,
- [switch]$Force = $false
-)
-
-$ErrorActionPreference = "Stop"
-
-Write-Host "====================================" -ForegroundColor Cyan
-Write-Host " TodoList 服务重启脚本" -ForegroundColor Cyan
-Write-Host "====================================" -ForegroundColor Cyan
-Write-Host ""
-
-Write-Host "[1/3] 停止现有服务..." -ForegroundColor Yellow
-
-$stopScriptPath = Join-Path $PSScriptRoot "stop-service.ps1"
-
-if (!(Test-Path $stopScriptPath)) {
- Write-Host "❌ 停止脚本不存在: $stopScriptPath" -ForegroundColor Red
- exit 1
-}
-
-try {
- if ($Force) {
- & $stopScriptPath -Force
- } else {
- & $stopScriptPath
- }
- Write-Host "✅ 服务已停止" -ForegroundColor Green
-} catch {
- Write-Host "❌ 停止服务失败: $_" -ForegroundColor Red
- exit 1
-}
-
-Write-Host ""
-Write-Host "[2/3] 等待进程完全关闭..." -ForegroundColor Yellow
-
-$timeout = 10
-$elapsed = 0
-
-while ($elapsed -lt $timeout) {
- $apiRunning = Get-Process -Name "dotnet" -ErrorAction SilentlyContinue | Where-Object { $_.MainWindowTitle -like "*TodoList.Api*" }
- $mauiRunning = Get-Process -Name "TodoList.Maui" -ErrorAction SilentlyContinue
-
- if (-not $apiRunning -and -not $mauiRunning) {
- Write-Host "✅ 所有进程已关闭" -ForegroundColor Green
- break
- }
-
- Start-Sleep -Seconds 1
- $elapsed++
-
- if ($elapsed -lt $timeout) {
- Write-Host " 等待中... ($elapsed/$timeout 秒)" -ForegroundColor Gray
- }
-}
-
-if ($elapsed -ge $timeout) {
- Write-Host "⚠️ 等待超时,继续启动..." -ForegroundColor Yellow
-}
-
-Write-Host ""
-Write-Host "[3/3] 启动服务..." -ForegroundColor Yellow
-
-$startScriptPath = Join-Path $PSScriptRoot "start-service.ps1"
-
-if (!(Test-Path $startScriptPath)) {
- Write-Host "❌ 启动脚本不存在: $startScriptPath" -ForegroundColor Red
- exit 1
-}
-
-try {
- if ($StartMaui) {
- & $startScriptPath -StartMaui
- } else {
- & $startScriptPath
- }
- Write-Host "✅ 服务已启动" -ForegroundColor Green
-} catch {
- Write-Host "❌ 启动服务失败: $_" -ForegroundColor Red
- exit 1
-}
-
-Write-Host ""
-Write-Host "====================================" -ForegroundColor Cyan
-Write-Host " 重启完成" -ForegroundColor Green
-Write-Host "====================================" -ForegroundColor Cyan
-Write-Host ""
-Write-Host "💡 提示:" -ForegroundColor Yellow
-Write-Host " - 按 Ctrl+C 可以停止服务" -ForegroundColor Gray
-Write-Host " - 运行 stop-service.bat 可以关闭服务" -ForegroundColor Gray
-Write-Host " - 运行 restart-service.bat 可以重启服务" -ForegroundColor Gray
-Write-Host ""
\ No newline at end of file
diff --git a/restart-web.ps1 b/restart-web.ps1
new file mode 100644
index 0000000..93c7e3b
--- /dev/null
+++ b/restart-web.ps1
@@ -0,0 +1,101 @@
+param(
+ [switch]$Force = $false
+)
+
+$ErrorActionPreference = "Stop"
+
+Write-Host "====================================" -ForegroundColor Cyan
+Write-Host " TodoList.Web Restart Script" -ForegroundColor Cyan
+Write-Host "====================================" -ForegroundColor Cyan
+Write-Host ""
+
+$webProjectPath = Join-Path $PSScriptRoot "src\TodoList.Web"
+
+if (!(Test-Path $webProjectPath)) {
+ Write-Host "ERROR: Web project path not found: $webProjectPath" -ForegroundColor Red
+ exit 1
+}
+
+function Get-TodoListWebProcesses {
+ param(
+ [Parameter(Mandatory = $true)]
+ [string]$WebProjectPath
+ )
+
+ Get-CimInstance Win32_Process -Filter "Name='node.exe'" | Where-Object {
+ $_.CommandLine -and
+ $_.CommandLine -like "*vite*" -and
+ $_.CommandLine -like "*$WebProjectPath*"
+ }
+}
+
+Write-Host "[1/3] Stopping existing service..." -ForegroundColor Yellow
+
+$webProcesses = @(Get-TodoListWebProcesses -WebProjectPath $webProjectPath)
+
+if ($webProcesses.Count -eq 0) {
+ Write-Host "OK: TodoList.Web is not running" -ForegroundColor Green
+} else {
+ Write-Host "Found $($webProcesses.Count) process(es)" -ForegroundColor Yellow
+ foreach ($process in $webProcesses) {
+ $processId = $process.ProcessId
+ Write-Host "Stopping PID: $processId" -ForegroundColor Gray
+ try {
+ Stop-Process -Id $processId -Force:$Force -ErrorAction Stop
+ Write-Host "OK: Stopped PID: $processId" -ForegroundColor Green
+ } catch {
+ Write-Host "WARN: Failed to stop PID: $processId. $_" -ForegroundColor Yellow
+ }
+ }
+}
+
+Write-Host ""
+Write-Host "[2/3] Waiting for processes to exit..." -ForegroundColor Yellow
+
+$timeout = 10
+$elapsed = 0
+
+while ($elapsed -lt $timeout) {
+ $webRunning = @(Get-TodoListWebProcesses -WebProjectPath $webProjectPath)
+
+ if ($webRunning.Count -eq 0) {
+ Write-Host "OK: All processes exited" -ForegroundColor Green
+ break
+ }
+
+ Start-Sleep -Seconds 1
+ $elapsed++
+
+ if ($elapsed -lt $timeout) {
+ Write-Host "Waiting... ($elapsed/$timeout sec)" -ForegroundColor Gray
+ }
+}
+
+if ($elapsed -ge $timeout) {
+ Write-Host "WARN: Timeout reached, continuing to start..." -ForegroundColor Yellow
+}
+
+Write-Host ""
+Write-Host "[3/3] Starting service..." -ForegroundColor Yellow
+
+try {
+ Write-Host "Working directory: $webProjectPath" -ForegroundColor Gray
+ Write-Host "Running: npm run dev" -ForegroundColor Green
+
+ $webProcess = Start-Process -FilePath "npm.cmd" -ArgumentList @("run", "dev") -WorkingDirectory $webProjectPath -PassThru
+
+ Write-Host "OK: Started TodoList.Web" -ForegroundColor Green
+ Write-Host "PID: $($webProcess.Id)" -ForegroundColor Gray
+} catch {
+ Write-Host "ERROR: Failed to start service. $_" -ForegroundColor Red
+ exit 1
+}
+
+Write-Host ""
+Write-Host "====================================" -ForegroundColor Cyan
+Write-Host " Done" -ForegroundColor Green
+Write-Host "====================================" -ForegroundColor Cyan
+Write-Host ""
+Write-Host "Notes:" -ForegroundColor Yellow
+Write-Host " - Vite will choose an available port automatically (no explicit port required)" -ForegroundColor Gray
+Write-Host " - Check the npm/vite output for the Local URL" -ForegroundColor Gray
diff --git a/src/TodoList.Api/Controllers/TasksController.cs b/src/TodoList.Api/Controllers/TasksController.cs
deleted file mode 100644
index 3f09eea..0000000
--- a/src/TodoList.Api/Controllers/TasksController.cs
+++ /dev/null
@@ -1,291 +0,0 @@
-using Microsoft.AspNetCore.Mvc;
-using TodoList.Api.Models;
-using TodoTask = TodoList.Core.Entities.Task;
-using TodoList.Core.Entities;
-using TodoList.Core.Interfaces;
-
-namespace TodoList.Api.Controllers;
-
-///
-/// 任务控制器,提供任务的 RESTful API 接口
-///
-[ApiController]
-[Route("api/[controller]")]
-public class TasksController : ControllerBase
-{
- private readonly ITaskService _taskService;
-
- ///
- /// 构造函数,注入任务服务
- ///
- /// 任务服务接口
- public TasksController(ITaskService taskService)
- {
- _taskService = taskService;
- }
-
- ///
- /// 获取任务列表
- ///
- /// 可选参数,true 获取已完成任务,false 获取未完成任务,不传则获取所有任务
- /// 任务列表响应
- [HttpGet]
- public async Task>>> GetTasks([FromQuery] bool? completed = null)
- {
- try
- {
- List tasks;
-
- if (completed.HasValue)
- {
- tasks = completed.Value
- ? await _taskService.GetCompletedTasksAsync()
- : await _taskService.GetActiveTasksAsync();
- }
- else
- {
- tasks = await _taskService.GetAllTasksAsync();
- }
-
- var taskDtos = tasks.Select(MapToDto).ToList();
-
- return Ok(new ApiResponse>
- {
- Success = true,
- Data = taskDtos,
- Message = "获取任务列表成功"
- });
- }
- catch (Exception ex)
- {
- return StatusCode(500, new ApiResponse>
- {
- Success = false,
- Message = "获取任务列表失败",
- Errors = new List { ex.Message }
- });
- }
- }
-
- ///
- /// 根据ID获取指定任务
- ///
- /// 任务ID
- /// 任务详情响应
- [HttpGet("{id}")]
- public async Task>> GetTask(int id)
- {
- try
- {
- var task = await _taskService.GetTaskByIdAsync(id);
- if (task == null)
- {
- return NotFound(new ApiResponse
- {
- Success = false,
- Message = $"未找到ID为 {id} 的任务"
- });
- }
-
- return Ok(new ApiResponse
- {
- Success = true,
- Data = MapToDto(task),
- Message = "获取任务成功"
- });
- }
- catch (Exception ex)
- {
- return StatusCode(500, new ApiResponse
- {
- Success = false,
- Message = "获取任务失败",
- Errors = new List { ex.Message }
- });
- }
- }
-
- ///
- /// 创建新任务
- ///
- /// 创建任务的数据传输对象
- /// 创建的任务响应
- [HttpPost]
- public async Task>> CreateTask([FromBody] CreateTaskDto dto)
- {
- try
- {
- if (string.IsNullOrWhiteSpace(dto.Title))
- {
- return BadRequest(new ApiResponse
- {
- Success = false,
- Message = "任务标题不能为空",
- Errors = new List { "Title is required" }
- });
- }
-
- var task = await _taskService.CreateTaskAsync(dto.Title, dto.Priority, dto.ParentTaskId);
-
- return CreatedAtAction(nameof(GetTask), new { id = task.Id }, new ApiResponse
- {
- Success = true,
- Data = MapToDto(task),
- Message = "创建任务成功"
- });
- }
- catch (Exception ex)
- {
- return StatusCode(500, new ApiResponse
- {
- Success = false,
- Message = "创建任务失败",
- Errors = new List { ex.Message }
- });
- }
- }
-
- ///
- /// 更新任务
- ///
- /// 任务ID
- /// 更新任务的数据传输对象
- /// 更新后的任务响应
- [HttpPut("{id}")]
- public async Task>> UpdateTask(int id, [FromBody] UpdateTaskDto dto)
- {
- try
- {
- var task = await _taskService.UpdateTaskAsync(id, dto.Title, dto.Priority);
-
- return Ok(new ApiResponse
- {
- Success = true,
- Data = MapToDto(task),
- Message = "更新任务成功"
- });
- }
- catch (KeyNotFoundException)
- {
- return NotFound(new ApiResponse
- {
- Success = false,
- Message = $"未找到ID为 {id} 的任务"
- });
- }
- catch (Exception ex)
- {
- return StatusCode(500, new ApiResponse
- {
- Success = false,
- Message = "更新任务失败",
- Errors = new List { ex.Message }
- });
- }
- }
-
- ///
- /// 切换任务的完成状态
- ///
- /// 任务ID
- /// 更新后的任务响应
- [HttpPatch("{id}/complete")]
- public async Task>> ToggleComplete(int id)
- {
- try
- {
- var task = await _taskService.ToggleCompleteAsync(id);
-
- return Ok(new ApiResponse
- {
- Success = true,
- Data = MapToDto(task),
- Message = task.IsCompleted ? "任务已完成" : "任务已取消完成"
- });
- }
- catch (KeyNotFoundException)
- {
- return NotFound(new ApiResponse
- {
- Success = false,
- Message = $"未找到ID为 {id} 的任务"
- });
- }
- catch (Exception ex)
- {
- return StatusCode(500, new ApiResponse
- {
- Success = false,
- Message = "更新任务状态失败",
- Errors = new List { ex.Message }
- });
- }
- }
-
- ///
- /// 删除任务
- ///
- /// 任务ID
- /// 删除结果响应
- [HttpDelete("{id}")]
- public async Task>> DeleteTask(int id)
- {
- try
- {
- await _taskService.DeleteTaskAsync(id);
-
- return Ok(new ApiResponse