diff --git a/backend/CollabApp.sln b/backend/CollabApp.sln
new file mode 100644
index 0000000000000000000000000000000000000000..36d092da6c82a8575da8cb349e8de167948c0e56
--- /dev/null
+++ b/backend/CollabApp.sln
@@ -0,0 +1,131 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CollabApp.API", "src\CollabApp.API\CollabApp.API.csproj", "{5665D919-F5F1-41A6-AD0E-4DFAA9A7AC6F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CollabApp.Domain", "src\CollabApp.Domain\CollabApp.Domain.csproj", "{170263DD-CBBB-4106-9D78-A38A001F1F3B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CollabApp.Application", "src\CollabApp.Application\CollabApp.Application.csproj", "{2505E022-6542-40FF-9725-1DA669A36A20}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CollabApp.Infrastructure", "src\CollabApp.Infrastructure\CollabApp.Infrastructure.csproj", "{78700058-9673-47E0-9993-2274A7BCD49C}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0AB3BF05-4346-4AA6-1389-037BE0695223}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CollabApp.Tests", "tests\CollabApp.Tests\CollabApp.Tests.csproj", "{59589A24-0675-42A4-B373-48410E57AC47}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CollabApp.Application.Tests", "tests\CollabApp.Application.Tests\CollabApp.Application.Tests.csproj", "{1E791B3C-5FF9-42C6-9F32-F71944C7F092}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CollabApp.Domain.Tests", "tests\CollabApp.Domain.Tests\CollabApp.Domain.Tests.csproj", "{5014B908-8BFF-484B-B9F8-9CB7FA87E16D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {5665D919-F5F1-41A6-AD0E-4DFAA9A7AC6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5665D919-F5F1-41A6-AD0E-4DFAA9A7AC6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5665D919-F5F1-41A6-AD0E-4DFAA9A7AC6F}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {5665D919-F5F1-41A6-AD0E-4DFAA9A7AC6F}.Debug|x64.Build.0 = Debug|Any CPU
+ {5665D919-F5F1-41A6-AD0E-4DFAA9A7AC6F}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {5665D919-F5F1-41A6-AD0E-4DFAA9A7AC6F}.Debug|x86.Build.0 = Debug|Any CPU
+ {5665D919-F5F1-41A6-AD0E-4DFAA9A7AC6F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5665D919-F5F1-41A6-AD0E-4DFAA9A7AC6F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5665D919-F5F1-41A6-AD0E-4DFAA9A7AC6F}.Release|x64.ActiveCfg = Release|Any CPU
+ {5665D919-F5F1-41A6-AD0E-4DFAA9A7AC6F}.Release|x64.Build.0 = Release|Any CPU
+ {5665D919-F5F1-41A6-AD0E-4DFAA9A7AC6F}.Release|x86.ActiveCfg = Release|Any CPU
+ {5665D919-F5F1-41A6-AD0E-4DFAA9A7AC6F}.Release|x86.Build.0 = Release|Any CPU
+ {170263DD-CBBB-4106-9D78-A38A001F1F3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {170263DD-CBBB-4106-9D78-A38A001F1F3B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {170263DD-CBBB-4106-9D78-A38A001F1F3B}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {170263DD-CBBB-4106-9D78-A38A001F1F3B}.Debug|x64.Build.0 = Debug|Any CPU
+ {170263DD-CBBB-4106-9D78-A38A001F1F3B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {170263DD-CBBB-4106-9D78-A38A001F1F3B}.Debug|x86.Build.0 = Debug|Any CPU
+ {170263DD-CBBB-4106-9D78-A38A001F1F3B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {170263DD-CBBB-4106-9D78-A38A001F1F3B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {170263DD-CBBB-4106-9D78-A38A001F1F3B}.Release|x64.ActiveCfg = Release|Any CPU
+ {170263DD-CBBB-4106-9D78-A38A001F1F3B}.Release|x64.Build.0 = Release|Any CPU
+ {170263DD-CBBB-4106-9D78-A38A001F1F3B}.Release|x86.ActiveCfg = Release|Any CPU
+ {170263DD-CBBB-4106-9D78-A38A001F1F3B}.Release|x86.Build.0 = Release|Any CPU
+ {2505E022-6542-40FF-9725-1DA669A36A20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2505E022-6542-40FF-9725-1DA669A36A20}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2505E022-6542-40FF-9725-1DA669A36A20}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {2505E022-6542-40FF-9725-1DA669A36A20}.Debug|x64.Build.0 = Debug|Any CPU
+ {2505E022-6542-40FF-9725-1DA669A36A20}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {2505E022-6542-40FF-9725-1DA669A36A20}.Debug|x86.Build.0 = Debug|Any CPU
+ {2505E022-6542-40FF-9725-1DA669A36A20}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2505E022-6542-40FF-9725-1DA669A36A20}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2505E022-6542-40FF-9725-1DA669A36A20}.Release|x64.ActiveCfg = Release|Any CPU
+ {2505E022-6542-40FF-9725-1DA669A36A20}.Release|x64.Build.0 = Release|Any CPU
+ {2505E022-6542-40FF-9725-1DA669A36A20}.Release|x86.ActiveCfg = Release|Any CPU
+ {2505E022-6542-40FF-9725-1DA669A36A20}.Release|x86.Build.0 = Release|Any CPU
+ {78700058-9673-47E0-9993-2274A7BCD49C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {78700058-9673-47E0-9993-2274A7BCD49C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {78700058-9673-47E0-9993-2274A7BCD49C}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {78700058-9673-47E0-9993-2274A7BCD49C}.Debug|x64.Build.0 = Debug|Any CPU
+ {78700058-9673-47E0-9993-2274A7BCD49C}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {78700058-9673-47E0-9993-2274A7BCD49C}.Debug|x86.Build.0 = Debug|Any CPU
+ {78700058-9673-47E0-9993-2274A7BCD49C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {78700058-9673-47E0-9993-2274A7BCD49C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {78700058-9673-47E0-9993-2274A7BCD49C}.Release|x64.ActiveCfg = Release|Any CPU
+ {78700058-9673-47E0-9993-2274A7BCD49C}.Release|x64.Build.0 = Release|Any CPU
+ {78700058-9673-47E0-9993-2274A7BCD49C}.Release|x86.ActiveCfg = Release|Any CPU
+ {78700058-9673-47E0-9993-2274A7BCD49C}.Release|x86.Build.0 = Release|Any CPU
+ {59589A24-0675-42A4-B373-48410E57AC47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {59589A24-0675-42A4-B373-48410E57AC47}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {59589A24-0675-42A4-B373-48410E57AC47}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {59589A24-0675-42A4-B373-48410E57AC47}.Debug|x64.Build.0 = Debug|Any CPU
+ {59589A24-0675-42A4-B373-48410E57AC47}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {59589A24-0675-42A4-B373-48410E57AC47}.Debug|x86.Build.0 = Debug|Any CPU
+ {59589A24-0675-42A4-B373-48410E57AC47}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {59589A24-0675-42A4-B373-48410E57AC47}.Release|Any CPU.Build.0 = Release|Any CPU
+ {59589A24-0675-42A4-B373-48410E57AC47}.Release|x64.ActiveCfg = Release|Any CPU
+ {59589A24-0675-42A4-B373-48410E57AC47}.Release|x64.Build.0 = Release|Any CPU
+ {59589A24-0675-42A4-B373-48410E57AC47}.Release|x86.ActiveCfg = Release|Any CPU
+ {59589A24-0675-42A4-B373-48410E57AC47}.Release|x86.Build.0 = Release|Any CPU
+ {1E791B3C-5FF9-42C6-9F32-F71944C7F092}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1E791B3C-5FF9-42C6-9F32-F71944C7F092}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1E791B3C-5FF9-42C6-9F32-F71944C7F092}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1E791B3C-5FF9-42C6-9F32-F71944C7F092}.Debug|x64.Build.0 = Debug|Any CPU
+ {1E791B3C-5FF9-42C6-9F32-F71944C7F092}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {1E791B3C-5FF9-42C6-9F32-F71944C7F092}.Debug|x86.Build.0 = Debug|Any CPU
+ {1E791B3C-5FF9-42C6-9F32-F71944C7F092}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1E791B3C-5FF9-42C6-9F32-F71944C7F092}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1E791B3C-5FF9-42C6-9F32-F71944C7F092}.Release|x64.ActiveCfg = Release|Any CPU
+ {1E791B3C-5FF9-42C6-9F32-F71944C7F092}.Release|x64.Build.0 = Release|Any CPU
+ {1E791B3C-5FF9-42C6-9F32-F71944C7F092}.Release|x86.ActiveCfg = Release|Any CPU
+ {1E791B3C-5FF9-42C6-9F32-F71944C7F092}.Release|x86.Build.0 = Release|Any CPU
+ {5014B908-8BFF-484B-B9F8-9CB7FA87E16D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5014B908-8BFF-484B-B9F8-9CB7FA87E16D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5014B908-8BFF-484B-B9F8-9CB7FA87E16D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {5014B908-8BFF-484B-B9F8-9CB7FA87E16D}.Debug|x64.Build.0 = Debug|Any CPU
+ {5014B908-8BFF-484B-B9F8-9CB7FA87E16D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {5014B908-8BFF-484B-B9F8-9CB7FA87E16D}.Debug|x86.Build.0 = Debug|Any CPU
+ {5014B908-8BFF-484B-B9F8-9CB7FA87E16D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5014B908-8BFF-484B-B9F8-9CB7FA87E16D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5014B908-8BFF-484B-B9F8-9CB7FA87E16D}.Release|x64.ActiveCfg = Release|Any CPU
+ {5014B908-8BFF-484B-B9F8-9CB7FA87E16D}.Release|x64.Build.0 = Release|Any CPU
+ {5014B908-8BFF-484B-B9F8-9CB7FA87E16D}.Release|x86.ActiveCfg = Release|Any CPU
+ {5014B908-8BFF-484B-B9F8-9CB7FA87E16D}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {5665D919-F5F1-41A6-AD0E-4DFAA9A7AC6F} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
+ {170263DD-CBBB-4106-9D78-A38A001F1F3B} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
+ {2505E022-6542-40FF-9725-1DA669A36A20} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
+ {78700058-9673-47E0-9993-2274A7BCD49C} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
+ {59589A24-0675-42A4-B373-48410E57AC47} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
+ {1E791B3C-5FF9-42C6-9F32-F71944C7F092} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
+ {5014B908-8BFF-484B-B9F8-9CB7FA87E16D} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
+ EndGlobalSection
+EndGlobal
diff --git a/backend/src/CollabApp.API/CollabApp.API.csproj b/backend/src/CollabApp.API/CollabApp.API.csproj
new file mode 100644
index 0000000000000000000000000000000000000000..716c3fbc785f4e7b8bae5a1f84b47fe2532c3ab0
--- /dev/null
+++ b/backend/src/CollabApp.API/CollabApp.API.csproj
@@ -0,0 +1,27 @@
+
+
+
+ net9.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
+
+
diff --git a/backend/src/CollabApp.API/Common/ApiResponse.cs b/backend/src/CollabApp.API/Common/ApiResponse.cs
new file mode 100644
index 0000000000000000000000000000000000000000..42f0ebdfaa47a24a5308d45e1d3b2e9076035ccc
--- /dev/null
+++ b/backend/src/CollabApp.API/Common/ApiResponse.cs
@@ -0,0 +1,192 @@
+using System.Net;
+
+namespace CollabApp.API.Common;
+
+///
+/// 统一API响应格式
+///
+/// 响应数据类型
+public class ApiResponse
+{
+ ///
+ /// 是否成功
+ ///
+ public bool Success { get; set; }
+
+ ///
+ /// 响应消息
+ ///
+ public string Message { get; set; } = string.Empty;
+
+ ///
+ /// 响应数据
+ ///
+ public T? Data { get; set; }
+
+ ///
+ /// 错误列表
+ ///
+ public List? Errors { get; set; }
+
+ ///
+ /// 时间戳
+ ///
+ public DateTime Timestamp { get; set; } = DateTime.UtcNow;
+
+ ///
+ /// HTTP状态码
+ ///
+ public int StatusCode { get; set; } = (int)HttpStatusCode.OK;
+
+ ///
+ /// 创建成功响应
+ ///
+ /// 响应数据
+ /// 响应消息
+ /// 成功响应
+ public static ApiResponse CreateSuccess(T? data = default, string message = "操作成功")
+ {
+ return new ApiResponse
+ {
+ Success = true,
+ Message = message,
+ Data = data,
+ StatusCode = (int)HttpStatusCode.OK
+ };
+ }
+
+ ///
+ /// 创建成功响应(带消息列表)
+ ///
+ /// 响应数据
+ /// 消息列表
+ /// 成功响应
+ public static ApiResponse CreateSuccess(T? data, List messages)
+ {
+ return new ApiResponse
+ {
+ Success = true,
+ Message = messages.FirstOrDefault() ?? "操作成功",
+ Data = data,
+ StatusCode = (int)HttpStatusCode.OK
+ };
+ }
+
+ ///
+ /// 创建失败响应
+ ///
+ /// 错误消息
+ /// 错误列表
+ /// HTTP状态码
+ /// 失败响应
+ public static ApiResponse CreateFailure(string message, List? errors = null, int statusCode = (int)HttpStatusCode.BadRequest)
+ {
+ return new ApiResponse
+ {
+ Success = false,
+ Message = message,
+ Data = default,
+ Errors = errors,
+ StatusCode = statusCode
+ };
+ }
+
+ ///
+ /// 创建失败响应(单个错误)
+ ///
+ /// 错误消息
+ /// 错误信息
+ /// HTTP状态码
+ /// 失败响应
+ public static ApiResponse CreateFailure(string message, string error, int statusCode = (int)HttpStatusCode.BadRequest)
+ {
+ return CreateFailure(message, new List { error }, statusCode);
+ }
+
+ ///
+ /// 创建错误响应
+ ///
+ /// 错误消息
+ /// 错误列表
+ /// HTTP状态码
+ /// 错误响应
+ public static ApiResponse CreateError(string message, List? errors = null, int statusCode = (int)HttpStatusCode.InternalServerError)
+ {
+ return new ApiResponse
+ {
+ Success = false,
+ Message = message,
+ Data = default,
+ Errors = errors,
+ StatusCode = statusCode
+ };
+ }
+
+ ///
+ /// 创建验证失败响应
+ ///
+ /// 验证错误列表
+ /// 验证失败响应
+ public static ApiResponse CreateValidationError(Dictionary> errors)
+ {
+ var errorList = errors.SelectMany(kvp =>
+ kvp.Value.Select(v => $"{kvp.Key}: {v}")).ToList();
+
+ return new ApiResponse
+ {
+ Success = false,
+ Message = "验证失败",
+ Data = default,
+ Errors = errorList,
+ StatusCode = (int)HttpStatusCode.BadRequest
+ };
+ }
+
+ ///
+ /// 创建未找到响应
+ ///
+ /// 消息
+ /// 未找到响应
+ public static ApiResponse CreateNotFound(string message = "未找到资源")
+ {
+ return new ApiResponse
+ {
+ Success = false,
+ Message = message,
+ Data = default,
+ StatusCode = (int)HttpStatusCode.NotFound
+ };
+ }
+
+ ///
+ /// 创建未授权响应
+ ///
+ /// 消息
+ /// 未授权响应
+ public static ApiResponse CreateUnauthorized(string message = "未授权访问")
+ {
+ return new ApiResponse
+ {
+ Success = false,
+ Message = message,
+ Data = default,
+ StatusCode = (int)HttpStatusCode.Unauthorized
+ };
+ }
+
+ ///
+ /// 创建禁止访问响应
+ ///
+ /// 消息
+ /// 禁止访问响应
+ public static ApiResponse CreateForbidden(string message = "禁止访问")
+ {
+ return new ApiResponse
+ {
+ Success = false,
+ Message = message,
+ Data = default,
+ StatusCode = (int)HttpStatusCode.Forbidden
+ };
+ }
+}
\ No newline at end of file
diff --git a/backend/src/CollabApp.API/Controllers/AuthController.cs b/backend/src/CollabApp.API/Controllers/AuthController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..68563999e0e5634b40a6b683fe42fa6332647126
--- /dev/null
+++ b/backend/src/CollabApp.API/Controllers/AuthController.cs
@@ -0,0 +1,107 @@
+using Microsoft.AspNetCore.Mvc;
+using System.Threading.Tasks;
+using CollabApp.Domain.Services.Auth;
+
+namespace CollabApp.API.Controllers;
+ public class RegisterDto
+ {
+ public string Username { get; set; } = string.Empty;
+ public string Password { get; set; } = string.Empty;
+ public string ConfirmPassword { get; set; } = string.Empty;
+ public string Avatar { get; set; } = string.Empty;
+ }
+
+ public class LoginDto
+ {
+ public string Username { get; set; } = string.Empty;
+ public string Password { get; set; } = string.Empty;
+ public bool RememberMe { get; set; } = false;
+ }
+
+ public class ForgotPasswordDto
+ {
+ public string Username { get; set; } = string.Empty;
+ public string NewPassword { get; set; } = string.Empty;
+ }
+
+ public class RefreshTokenDto
+ {
+ public string RefreshToken { get; set; } = string.Empty;
+ }
+
+ [ApiController]
+ [Route("api/[controller]")]
+ public class AuthController : ControllerBase
+ {
+ private readonly IAuthService _authService;
+ public AuthController(IAuthService authService)
+ {
+ _authService = authService;
+ }
+
+ [HttpPost("register")]
+ public async Task Register([FromBody] RegisterDto dto)
+ {
+ var result = await _authService.RegisterAsync(dto.Username, dto.Password, dto.ConfirmPassword, dto.Avatar);
+ return Ok(result);
+ }
+
+ [HttpPost("login")]
+ public async Task Login([FromBody] LoginDto dto)
+ {
+ var result = await _authService.LoginAsync(dto.Username, dto.Password, dto.RememberMe);
+ return Ok(result);
+ }
+
+ [HttpPost("forgot-password")]
+ public async Task ForgotPassword([FromBody] ForgotPasswordDto dto)
+ {
+ var result = await _authService.ForgotPasswordAsync(dto.Username, dto.NewPassword);
+ return Ok(result);
+ }
+
+ [HttpPost("refresh-token")]
+ public async Task RefreshToken([FromBody] RefreshTokenDto dto)
+ {
+ var result = await _authService.RefreshTokenAsync(dto.RefreshToken);
+ return Ok(result);
+ }
+
+ [HttpGet("verify")]
+ public IActionResult Verify()
+ {
+ try
+ {
+ // 获取用户身份信息
+ var userIdClaim = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier);
+ if (userIdClaim == null || !Guid.TryParse(userIdClaim.Value, out var userId))
+ {
+ return Unauthorized(new { code = 4001, message = "用户身份无效" });
+ }
+
+ var usernameClaim = User.FindFirst("unique_name");
+ var username = usernameClaim?.Value ?? "Unknown";
+
+ // 返回真实的用户信息
+ var response = new
+ {
+ code = 1000,
+ message = "验证成功",
+ data = new
+ {
+ id = userId.ToString(),
+ username = username,
+ nickname = username, // 可以后续从数据库获取
+ avatarUrl = "",
+ status = "online",
+ createdAt = DateTime.UtcNow
+ }
+ };
+ return Ok(response);
+ }
+ catch
+ {
+ return StatusCode(500, new { code = 5000, message = "服务器内部错误" });
+ }
+ }
+ }
\ No newline at end of file
diff --git a/backend/src/CollabApp.API/Controllers/LineDrawingGameController.cs b/backend/src/CollabApp.API/Controllers/LineDrawingGameController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..586e1d356d5c85b682cf9b4e89398042f6ebf8f1
--- /dev/null
+++ b/backend/src/CollabApp.API/Controllers/LineDrawingGameController.cs
@@ -0,0 +1,435 @@
+using CollabApp.Application.Interfaces;
+using CollabApp.Application.DTOs.Game;
+using CollabApp.Domain.ValueObjects;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Authorization;
+using System.Security.Claims;
+using CollabApp.API.Common;
+using Microsoft.AspNetCore.SignalR;
+using CollabApp.API.Hubs;
+
+namespace CollabApp.API.Controllers
+{
+ ///
+ /// 画线圈地游戏控制器
+ /// 处理游戏的创建、加入、开始等HTTP请求
+ ///
+ [ApiController]
+ [Route("api/[controller]")]
+ [Authorize]
+ public class LineDrawingGameController : ControllerBase
+ {
+ private readonly ILineDrawingGameService _gameService;
+ private readonly IHubContext _hubContext;
+ private readonly ILogger _logger;
+
+ public LineDrawingGameController(
+ ILineDrawingGameService gameService,
+ IHubContext hubContext,
+ ILogger logger)
+ {
+ _gameService = gameService;
+ _hubContext = hubContext;
+ _logger = logger;
+ }
+
+ ///
+ /// 创建游戏
+ ///
+ /// 创建游戏请求
+ /// 创建结果
+ [HttpPost("create")]
+ public async Task CreateGame([FromBody] CreateGameRequest request)
+ {
+ try
+ {
+ var userId = GetCurrentUserId();
+ var userName = GetCurrentUserName();
+
+ var settings = new GameSettings
+ {
+ Duration = request.GameTimeMinutes * 60,
+ MapWidth = 1000,
+ MapHeight = 1000,
+ MaxPlayers = request.MaxPlayers,
+ EnablePowerUps = true,
+ EnableSpecialEvents = true,
+ GameMode = "classic"
+ };
+
+ var result = await _gameService.CreateGameAsync(request.RoomId.ToString(), settings, userId, userName);
+
+ if (result.Success)
+ {
+ _logger.LogInformation("游戏创建成功: GameId={GameId}, Host={HostName}", result.GameId, userName);
+
+ return Ok(ApiResponse