diff --git a/FlaskAPI/app.py b/FlaskAPI/app.py
new file mode 100644
index 0000000000000000000000000000000000000000..31acf958d687021a715d557488c96e8f715d52bc
--- /dev/null
+++ b/FlaskAPI/app.py
@@ -0,0 +1,67 @@
+import spacy
+import json
+from flask import Flask, jsonify, request, Response
+
+# 加载 SpaCy 中文模型
+nlp = spacy.load("zh_core_web_sm")
+
+app = Flask(__name__)
+
+def preprocess_text(text):
+ # 使用 SpaCy 进行命名实体识别
+ doc = nlp(text)
+
+ # 识别实体
+ entities = [{"Text": ent.text, "Label": ent.label_} for ent in doc.ents]
+
+ # 按句子拆分文本
+ sentences = [sent.text for sent in doc.sents]
+
+ # 返回预处理后的数据
+ result = {
+ "Entities": list(entities), # 确保将实体列表转换为标准列表
+ "Sentences": sentences
+ }
+
+ return result
+
+@app.route('/spacy', methods=['POST'])
+def preprocess():
+ data = request.get_json()
+ text = data.get("text", "")
+
+ # 进行预处理
+ processed_result = preprocess_text(text)
+ print(f"Entities: {processed_result.values()}")
+
+ # 返回预处理后的数据
+ res = Response(json.dumps(processed_result, ensure_ascii=False), content_type="application/json; charset=utf-8")
+
+ return res
+
+@app.route('/parse_input', methods=['POST'])
+def parse_text():
+ # 从请求中获取用户输入
+ content = request.json.get('content', '')
+
+ if not content:
+ return jsonify({"error": "Content is required"}), 400
+
+ # 使用 spaCy 进行文本处理
+ doc = nlp(content)
+
+ # 提取实体和关键词
+ entities = [{"text": ent.text, "label": ent.label_} for ent in doc.ents]
+ tokens = [token.text for token in doc if not token.is_stop] # 去除停用词
+
+ # 构造响应
+ response = {
+ "entities": entities,
+ "tokens": tokens,
+ "text": content
+ }
+
+ return jsonify(response)
+
+if __name__ == '__main__':
+ app.run(debug=True)
\ No newline at end of file
diff --git a/FlaskAPI/dockerfile b/FlaskAPI/dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..e8671ed86fb0539b529d195bf885d0ce23a5b89c
--- /dev/null
+++ b/FlaskAPI/dockerfile
@@ -0,0 +1,12 @@
+FROM python:3.11-slim
+
+WORKDIR /app
+
+COPY requirements.txt .
+RUN pip install --no-cache-dir -r requirements.txt \
+ && python -m spacy download zh_core_web_sm
+
+COPY . .
+
+EXPOSE 5000
+CMD ["gunicorn", "-b", "0.0.0.0:5000", "app:app"]
diff --git a/FlaskAPI/requirement.txt b/FlaskAPI/requirement.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9d80114edf69eaceedf82130d8378a9586d6c26a
--- /dev/null
+++ b/FlaskAPI/requirement.txt
@@ -0,0 +1,2 @@
+Flask
+spacy
\ No newline at end of file
diff --git a/backend/UniversalAdminSystem.sln b/backend/UniversalAdminSystem.sln
new file mode 100644
index 0000000000000000000000000000000000000000..c65262f760ac4e68d281100d9baae651d78b2719
--- /dev/null
+++ b/backend/UniversalAdminSystem.sln
@@ -0,0 +1,48 @@
+
+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", "{9032CBF4-BB53-4E64-9978-E90FEB71CC7C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniversalAdminSystem.Api", "src\UniversalAdminSystem.Api\UniversalAdminSystem.Api.csproj", "{2AD39004-1226-419A-946B-72964C31CFF2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniversalAdminSystem.Application", "src\UniversalAdminSystem.Application\UniversalAdminSystem.Application.csproj", "{1B84D865-ECF7-4F61-A45C-81641308405F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniversalAdminSystem.Domian", "src\UniversalAdminSystem.Domian\UniversalAdminSystem.Domian.csproj", "{6430BA75-BA96-4EED-9F4E-D7DB30C583A3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniversalAdminSystem.Infrastructure", "src\UniversalAdminSystem.Infrastructure\UniversalAdminSystem.Infrastructure.csproj", "{D497ABDA-6594-4364-9BE7-90AB35E2B194}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {2AD39004-1226-419A-946B-72964C31CFF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2AD39004-1226-419A-946B-72964C31CFF2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2AD39004-1226-419A-946B-72964C31CFF2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2AD39004-1226-419A-946B-72964C31CFF2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1B84D865-ECF7-4F61-A45C-81641308405F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1B84D865-ECF7-4F61-A45C-81641308405F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1B84D865-ECF7-4F61-A45C-81641308405F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1B84D865-ECF7-4F61-A45C-81641308405F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6430BA75-BA96-4EED-9F4E-D7DB30C583A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6430BA75-BA96-4EED-9F4E-D7DB30C583A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6430BA75-BA96-4EED-9F4E-D7DB30C583A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6430BA75-BA96-4EED-9F4E-D7DB30C583A3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D497ABDA-6594-4364-9BE7-90AB35E2B194}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D497ABDA-6594-4364-9BE7-90AB35E2B194}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D497ABDA-6594-4364-9BE7-90AB35E2B194}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D497ABDA-6594-4364-9BE7-90AB35E2B194}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {2AD39004-1226-419A-946B-72964C31CFF2} = {9032CBF4-BB53-4E64-9978-E90FEB71CC7C}
+ {1B84D865-ECF7-4F61-A45C-81641308405F} = {9032CBF4-BB53-4E64-9978-E90FEB71CC7C}
+ {6430BA75-BA96-4EED-9F4E-D7DB30C583A3} = {9032CBF4-BB53-4E64-9978-E90FEB71CC7C}
+ {D497ABDA-6594-4364-9BE7-90AB35E2B194} = {9032CBF4-BB53-4E64-9978-E90FEB71CC7C}
+ EndGlobalSection
+EndGlobal
diff --git a/backend/dockerfile b/backend/dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..1c63d6f8f1f6199266935248d965a3be3e8855eb
--- /dev/null
+++ b/backend/dockerfile
@@ -0,0 +1,15 @@
+FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
+WORKDIR /app
+EXPOSE 5101
+
+FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+WORKDIR /src
+COPY . .
+RUN dotnet restore
+
+RUN dotnet publish -c Release -o /app/publish
+
+FROM base AS final
+WORKDIR /app
+COPY --from=build /app/publish .
+ENTRYPOINT ["dotnet", "UniversalAdminSystem.dll"]
diff --git a/backend/src/UniversalAdminSystem.Api/AllowedFiles.json b/backend/src/UniversalAdminSystem.Api/AllowedFiles.json
new file mode 100644
index 0000000000000000000000000000000000000000..34cf87d0ed7d6d44fae59336dc503165ca20389b
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/AllowedFiles.json
@@ -0,0 +1,86 @@
+{
+ "AllowedFiles": {
+ "AllowedFiles": [
+ {
+ "Mime": "image/jpeg",
+ "Ext": "jpg",
+ "Signature": "FF D8"
+ },
+ {
+ "Mime": "image/png",
+ "Ext": "png",
+ "Signature": "89 50 4E 47 0D 0A 1A 0A"
+ },
+ {
+ "Mime": "image/gif",
+ "Ext": "gif",
+ "Signature": "47 49 46 38 37 61"
+ },
+ {
+ "Mime": "image/gif",
+ "Ext": "gif",
+ "Signature": "47 49 46 38 39 61"
+ },
+ {
+ "Mime": "image/bmp",
+ "Ext": "bmp",
+ "Signature": "42 4D"
+ },
+ {
+ "Mime": "image/webp",
+ "Ext": "webp",
+ "Signature": "52 49 46 46 ?? ?? ?? ?? 57 45 42 50"
+ },
+ {
+ "Mime": "application/pdf",
+ "Ext": "pdf",
+ "Signature": "25 50 44 46"
+ },
+ {
+ "Mime": "application/json",
+ "Ext": "json",
+ "Signature": ""
+ },
+ {
+ "Mime": "text/markdown",
+ "Ext": "md",
+ "Signature": ""
+ },
+ {
+ "Mime": "text/plain",
+ "Ext": "txt",
+ "Signature": ""
+ },
+ {
+ "Mime": "application/xml",
+ "Ext": "xml",
+ "Signature": ""
+ },
+ {
+ "Mime": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+ "Ext": "docx",
+ "Signature": "50 4B 03 04"
+ },
+ {
+ "Mime": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ "Ext": "xlsx",
+ "Signature": "50 4B 03 04"
+ },
+ {
+ "Mime": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
+ "Ext": "pptx",
+ "Signature": "50 4B 03 04"
+ },
+ {
+ "Mime": "application/vnd.ms-excel",
+ "Ext": "xls",
+ "Signature": "D0 CF 11 E0 A1 B1 1A E1"
+ },
+ {
+ "Mime": "application/msword",
+ "Ext": "doc",
+ "Signature": "D0 CF 11 E0 A1 B1 1A E1"
+ }
+ ]
+ }
+}
diff --git a/backend/src/UniversalAdminSystem.Api/Attributes/RequirePermissionAttribute.cs b/backend/src/UniversalAdminSystem.Api/Attributes/RequirePermissionAttribute.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5a563303a252b335819e1f574ee349f4f5c395ac
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/Attributes/RequirePermissionAttribute.cs
@@ -0,0 +1,61 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
+using System.Security.Claims;
+using UniversalAdminSystem.Application.PermissionManagement.Interfaces;
+
+namespace UniversalAdminSystem.Api.Attributes;
+
+///
+/// 权限验证特性
+/// 用于标记需要特定权限的API接口
+///
+[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] //指定该特性可用于 类(Controller) 或 方法(Action) 级别。
+public class RequirePermissionAttribute : Attribute, IAsyncAuthorizationFilter
+{
+ private readonly string _permissionCode;
+
+ public RequirePermissionAttribute(string permissionCode)
+ {
+ _permissionCode = permissionCode;
+ }
+
+ public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
+ {
+ try
+ {
+
+ // 获取用户ID
+ var userId = context.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
+ System.Console.WriteLine($"userId: {userId}" ?? "null");
+ if (string.IsNullOrEmpty(userId))
+ {
+ Console.WriteLine($"userId: {context.HttpContext.User.Identity?.Name}");
+ context.Result = new UnauthorizedResult();
+ return;
+ }
+
+ // 获取权限检查服务
+ var service = context.HttpContext.RequestServices.GetService();
+ if (service == null)
+ {
+ context.Result = new StatusCodeResult(500);
+ return;
+ }
+
+ // 检查用户是否有指定权限
+ var hasPermission = await service.CheckUserPermissionAsync(Guid.Parse(userId), _permissionCode);
+ System.Console.WriteLine($"hasPermission: {hasPermission}");
+ if (!hasPermission)
+ {
+ context.Result = new StatusCodeResult(401);
+ return;
+ }
+ }
+ catch (Exception ex)
+ {
+ // 记录错误并返回500
+ Console.WriteLine($"权限验证错误: {ex.Message}");
+ context.Result = new StatusCodeResult(500);
+ }
+ }
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Api/Attributes/RequireRoleAttribute.cs b/backend/src/UniversalAdminSystem.Api/Attributes/RequireRoleAttribute.cs
new file mode 100644
index 0000000000000000000000000000000000000000..66a24bd8d31e21b0de4fb7bf4b451f13b7d3996b
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/Attributes/RequireRoleAttribute.cs
@@ -0,0 +1,46 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
+using System.Security.Claims;
+
+namespace UniversalAdminSystem.Api.Attributes;
+
+///
+/// 角色验证特性
+/// 用于标记需要特定角色的API接口
+///
+[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
+public class RequireRoleAttribute : Attribute, IAsyncAuthorizationFilter
+{
+ private readonly string _roleName;
+
+ public RequireRoleAttribute(string roleName)
+ {
+ _roleName = roleName;
+ }
+
+ public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
+ {
+ try
+ {
+ // 获取用户角色
+ var userRole = context.HttpContext.User.FindFirst(ClaimTypes.Role)?.Value;
+ if (string.IsNullOrEmpty(userRole))
+ {
+ context.Result = new UnauthorizedResult();
+ return;
+ }
+
+ // 检查用户角色是否匹配
+ if (userRole != _roleName)
+ {
+ context.Result = new ForbidResult();
+ return;
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"角色验证错误: {ex.Message}");
+ context.Result = new StatusCodeResult(500);
+ }
+ }
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Api/Controllers/AIQuestionsController.cs b/backend/src/UniversalAdminSystem.Api/Controllers/AIQuestionsController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..3ba2d39fb87463451339a819af4bba4e094b483e
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/Controllers/AIQuestionsController.cs
@@ -0,0 +1,99 @@
+using Microsoft.AspNetCore.Mvc;
+using UniversalAdminSystem.Api.Attributes;
+using UniversalAdminSystem.Application.AIQuestions.DTOs;
+using UniversalAdminSystem.Application.AIQuestions.Interfaces;
+using UniversalAdminSystem.Application.Common.Results;
+
+namespace UniversalAdminSystem.Api.Controllers;
+
+[ApiController]
+[Route("api/[controller]")]
+public class AIQuestionsController : ControllerBase
+{
+ private readonly IAIQusetionsAppService _AIQusetionAppService;
+
+ public AIQuestionsController(IAIQusetionsAppService aIQusetionsAppService)
+ {
+ _AIQusetionAppService = aIQusetionsAppService;
+ }
+
+ [HttpPost("visitor")]
+ public Task VisitorAccess(ContentDto content)
+ {
+ throw new NotImplementedException();//尚未实现
+ }
+
+ [HttpPost("chat/{conversationsId}")]
+ [RequirePermission("document:Read")]
+ public async Task SendMessageAsync(Guid conversationsId, [FromBody] string userMessage)
+ {
+ try
+ {
+
+ var result = await _AIQusetionAppService.Chat(conversationsId, userMessage);
+ return Ok(Result.Success(result));
+ }
+ catch (System.Exception e)
+ {
+ return BadRequest(Result.Failure(e.Message));
+ }
+ }
+
+ [HttpPost("user")]
+ [RequirePermission("document:Read")]
+ public async Task CreateUserConversation(ConversationsDto conversationsDto)
+ {
+ try
+ {
+ var result = await _AIQusetionAppService.CreateConversation(conversationsDto);
+ return Ok(Result.Success(result));
+ }
+ catch (System.Exception e)
+ {
+ return BadRequest(Result.Failure(e.Message));
+ }
+ }
+
+ [HttpGet("user/{userid}")]
+ [RequirePermission("document:Read")]
+ public async Task GetUsersConversationsByUserId(Guid userid)
+ {
+ try
+ {
+ var list = await _AIQusetionAppService.GetUsersConversationsByUserId(userid);
+ return Ok(Result>.Success(list));
+ }
+ catch (System.Exception e)
+ {
+ return BadRequest(Result.Failure(e.Message));
+ }
+ }
+
+ [HttpDelete("user/{conversationsId}")]
+ public async Task DeleteUserConversations(Guid ConversationsId)
+ {
+ try
+ {
+ await _AIQusetionAppService.DeleteUserConversations(ConversationsId);
+ return Ok(Result.Success());
+ }
+ catch (System.Exception e)
+ {
+ return BadRequest(Result.Failure(e.Message));
+ }
+ }
+
+ [HttpGet("user/message/{ConversationsId}")]
+ public async Task GetAllConversationMessage(Guid ConversationsId)
+ {
+ try
+ {
+ var list = await _AIQusetionAppService.GetConversationMessage(ConversationsId);
+ return Ok(Result>.Success(list));
+ }
+ catch (System.Exception e)
+ {
+ return BadRequest(Result.Failure(e.Message));
+ }
+ }
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Api/Controllers/AuthenticationController.cs b/backend/src/UniversalAdminSystem.Api/Controllers/AuthenticationController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..dd1e8cd2cff4d46ea9b8ac5c9c629a4f6e578636
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/Controllers/AuthenticationController.cs
@@ -0,0 +1,97 @@
+using Microsoft.AspNetCore.Mvc;
+using UniversalAdminSystem.Application.Authentication.DTOs;
+using UniversalAdminSystem.Application.Authentication.Interfaces;
+using UniversalAdminSystem.Application.Common.Results;
+using UniversalAdminSystem.Domian.UserManagement.ValueObj;
+
+namespace UniversalAdminSystem.Api.Controllers;
+
+[ApiController]
+[Route("api/auth")]
+public class AuthenticationController : ControllerBase
+{
+ private readonly ILoginAppService _loginAppService;
+ private readonly IRegisterAppService _registerAppService;
+ private readonly IJwtTokenService _jwtTokenService;
+
+ public AuthenticationController(
+ ILoginAppService loginAppService,
+ IRegisterAppService registerAppService,
+ IJwtTokenService jwtTokenService)
+ {
+ _loginAppService = loginAppService;
+ _registerAppService = registerAppService;
+ _jwtTokenService = jwtTokenService;
+ }
+
+ [HttpPost("login")]
+ public async Task Login([FromBody] LoginDto loginDto)
+ {
+ try
+ {
+ if (string.IsNullOrEmpty(loginDto.Account) || string.IsNullOrEmpty(loginDto.Password))
+ {
+ return BadRequest(Result.Failure("账号和密码不能为空"));
+ }
+
+ var result = await _loginAppService.LoginAsync(loginDto);
+ return Ok(Result.Success(result));
+ }
+ catch (Exception ex)
+ {
+ return BadRequest(Result.Failure(ex.Message));
+ }
+ }
+
+ [HttpPost("register")]
+ public async Task Register([FromBody] RegisterDto registerDto)
+ {
+ try
+ {
+ if (string.IsNullOrEmpty(registerDto.Account) ||
+ string.IsNullOrEmpty(registerDto.Password) ||
+ string.IsNullOrEmpty(registerDto.Email))
+ {
+ return BadRequest(Result.Failure("账号、密码和邮箱不能为空"));
+ }
+
+ var result = await _registerAppService.RegisterAsync(registerDto);
+ return Ok(Result.Success(result));
+ }
+ catch (Exception ex)
+ {
+ return BadRequest(Result.Failure(ex.Message));
+ }
+ }
+
+ [HttpPost("refresh-token")]
+ public IActionResult RefreshToken([FromBody] RefreshTokenDto refreshTokenDto)
+ {
+ try
+ {
+ if (string.IsNullOrEmpty(refreshTokenDto.Token))
+ {
+ return BadRequest(Result.Failure("Token不能为空"));
+ }
+
+ var newToken = _jwtTokenService.RefreshToken(
+ refreshTokenDto.Token,
+ out string userId,
+ out string roleId,
+ out UserStatus status);
+
+ var result = new RefreshTokenResultDto(newToken, userId, roleId);
+ return Ok(Result.Success(result));
+ }
+ catch (Exception ex)
+ {
+ return BadRequest(Result.Failure(ex.Message));
+ }
+ }
+
+ [HttpPost("logout")]
+ public IActionResult Logout()
+ {
+ return Ok(Result.Success("登出成功"));
+ }
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Api/Controllers/FileController.cs b/backend/src/UniversalAdminSystem.Api/Controllers/FileController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..dc9c96e15c19593e6959765f349d900d1f82bb0b
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/Controllers/FileController.cs
@@ -0,0 +1,125 @@
+using Microsoft.AspNetCore.Mvc;
+using UniversalAdminSystem.Application.FileStorage.DTOs;
+using UniversalAdminSystem.Application.FileStorage.Interfaces;
+using UniversalAdminSystem.Api.Attributes;
+using UniversalAdminSystem.Domian.FileStorage.ValueObjects;
+using UniversalAdminSystem.Application.Common.Results;
+using UniversalAdminSystem.Application.Common.Interfaces;
+
+namespace UniversalAdminSystem.Api.Controllers;
+
+[ApiController]
+[Route("api/files")]
+public class FileController : ControllerBase
+{
+ private readonly IFileAppService _fileAppService;
+ private readonly IFileStorageService _fileStorageService;
+ private readonly IUnitOfWork _unitOfWork;
+
+ public FileController(IFileAppService fileAppService, IFileStorageService fileStorageService, IUnitOfWork unitOfWork)
+ {
+ _unitOfWork = unitOfWork;
+ _fileAppService = fileAppService;
+ _fileStorageService = fileStorageService;
+ }
+
+ [HttpPost("upload")]
+ [RequirePermission("file:Create")]
+ public async Task Upload(IFormFile file, Guid? parentId = null)
+ {
+ if (file == null || file.Length == 0) return BadRequest(Result.Failure("请选择要上传的文件"));
+ try
+ {
+ var res = await _fileAppService.UploadAsync(file);
+ return Ok(Result.Success(res));
+ }
+ catch (Exception ex)
+ {
+ return BadRequest(Result.Failure(ex.Message));
+ }
+ }
+
+ [HttpGet("test-permission")]
+ [RequirePermission("file:Create")]
+ public IActionResult TestPermission()
+ {
+ return Ok(Result.Success("权限检查通过"));
+ }
+
+ // [HttpGet("download/{fileId}")]
+ // [RequirePermission("file:download")]
+ // public async Task Download(Guid fileId)
+ // {
+ // var result = await _fileAppService.DownloadAsync((FileId)fileId);
+ // return result.IsSuccess ? Ok(result) : BadRequest(result);
+ // }
+
+ [HttpGet("list")]
+ [RequirePermission("file:Read")]
+ public async Task List()
+ {
+ var result = await _fileAppService.GetList();
+ return Ok(result);
+ }
+
+ // [HttpPost("folder")]
+ // [RequirePermission("file:create")]
+ // public async Task CreateFolder([FromBody] string name, [FromQuery] Guid? parentId)
+ // {
+ // var result = await _fileAppService.CreateFolderAsync(name, parentId.HasValue ? (FileId)parentId.Value : null);
+ // return result.IsSuccess ? Ok(result) : BadRequest(result);
+ // }
+
+ // [HttpDelete("{fileId}")]
+ // [RequirePermission("file:delete")]
+ // public async Task Delete(Guid fileId)
+ // {
+ // var result = await _fileAppService.DeleteAsync((FileId)fileId);
+ // return result.IsSuccess ? Ok(result) : BadRequest(result);
+ // }
+
+ // [HttpGet("{fileId}")]
+ // [RequirePermission("file:read")]
+ // public async Task GetFileById(Guid fileId)
+ // {
+ // var result = await _fileAppService.GetFileByIdAsync((FileId)fileId);
+ // return result.IsSuccess ? Ok(result) : BadRequest(result);
+ // }
+
+ [HttpGet("{id}")]
+ [RequirePermission("file:Read")]
+ public async Task Download(Guid id)
+ {
+ try
+ {
+
+ var entity = await _fileAppService.GetFileById(id);
+ var file = await _fileStorageService.DownloadAsync(entity.Name);
+ return new FileStreamResult(file, entity.Type);
+ }
+ catch (System.Exception)
+ {
+ return BadRequest(Result.Failure(""));
+ }
+ }
+
+ [HttpDelete("{id}")]
+ [RequirePermission("file:Delete")]
+ public async Task RemoveFile(Guid id)
+ {
+ try
+ {
+ await _unitOfWork.BeginTransactionAsync();
+ var entity = await _fileAppService.GetFileById(id);
+ await _fileStorageService.DeleteAsync(entity.Name);
+ await _fileAppService.RemoveFile(entity.Id);
+ await _unitOfWork.CommitAsync();
+ return Ok(Result.Success());
+ }
+ catch (System.Exception)
+ {
+ await _unitOfWork.RollbackAsync();
+ return BadRequest(Result.Failure("操作错误"));
+ }
+ }
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Api/Controllers/K2ModelController.cs b/backend/src/UniversalAdminSystem.Api/Controllers/K2ModelController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..0138549c4767c3026f86b95a78fe3835fdef3ba2
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/Controllers/K2ModelController.cs
@@ -0,0 +1,93 @@
+// using Microsoft.AspNetCore.Mvc;
+// using UniversalAdminSystem.Infrastructure.Services;
+
+// namespace UniversalAdminSystem.Api.Controllers;
+
+// [ApiController]
+// [Route("api/[controller]")]
+// public class K2ModelController : ControllerBase
+// {
+// private readonly K2ModelService _k2ModelService;
+// private readonly ILogger _logger;
+
+// public K2ModelController(K2ModelService k2ModelService, ILogger logger)
+// {
+// _k2ModelService = k2ModelService;
+// _logger = logger;
+// }
+
+// ///
+// /// 发送简单文本请求到K2模型
+// ///
+// /// 请求模型
+// /// 模型响应
+// [HttpPost("chat")]
+// public async Task SendChatRequest([FromBody] K2ChatRequest request)
+// {
+// try
+// {2
+// _logger.LogInformation("收到K2模型聊天请求: {Prompt}", request.Prompt);
+
+// var response = await _k2ModelService.SendSimpleRequestAsync(
+// request.Prompt,
+// request.Model ?? "qwen-turbo");
+
+// return Ok(new { response = response });
+// }
+// catch (Exception ex)
+// {
+// _logger.LogError(ex, "K2模型请求失败");
+// return StatusCode(500, new { error = "K2模型请求失败", message = ex.Message });
+// }
+// }
+
+// ///
+// /// 发送多轮对话请求到K2模型
+// ///
+// /// 多轮对话请求
+// /// 模型响应
+// [HttpPost("conversation")]
+// public async Task SendConversationRequest([FromBody] K2ConversationRequest request)
+// {
+// try
+// {
+// _logger.LogInformation("收到K2模型多轮对话请求,消息数量: {MessageCount}", request.Messages.Count);
+
+// var response = await _k2ModelService.SendChatRequestAsync(
+// request.Messages,
+// request.Model ?? "qwen-turbo",
+// request.Temperature ?? 0.7f,
+// request.MaxTokens ?? 1000);
+
+// return Ok(response);
+// }
+// catch (Exception ex)
+// {
+// _logger.LogError(ex, "K2模型多轮对话请求失败");
+// return StatusCode(500, new { error = "K2模型请求失败", message = ex.Message });
+// }
+// }
+
+// ///
+// /// 获取K2模型配置信息
+// ///
+// /// 配置信息
+// [HttpGet("config")]
+// public IActionResult GetConfig([FromServices] K2ConfigService configService)
+// {
+// try
+// {
+// var config = configService.GetK2Config();
+// return Ok(new
+// {
+// baseUrl = config.BaseUrl,
+// hasApiKey = !string.IsNullOrEmpty(config.ApiKey)
+// });
+// }
+// catch (Exception ex)
+// {
+// _logger.LogError(ex, "获取K2配置失败");
+// return StatusCode(500, new { error = "获取配置失败", message = ex.Message });
+// }
+// }
+// }
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Api/Controllers/LogController.cs b/backend/src/UniversalAdminSystem.Api/Controllers/LogController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..62ca15e9272e38f8530255aed9c32f0851a5ea5e
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/Controllers/LogController.cs
@@ -0,0 +1,71 @@
+using Microsoft.AspNetCore.Mvc;
+using UniversalAdminSystem.Application.LogManagement.DTOs;
+using UniversalAdminSystem.Application.LogManagement.Interfaces;
+using UniversalAdminSystem.Api.Attributes;
+using UniversalAdminSystem.Application.Common.Results;
+
+namespace UniversalAdminSystem.Api.Controllers;
+
+[ApiController]
+[Route("api/logs")]
+public class LogController : ControllerBase
+{
+ private readonly ILogManagementAppService _logService;
+ public LogController(ILogManagementAppService logService) => _logService = logService;
+
+ [HttpGet]
+ //[RequirePermission("log:read")]
+ public async Task GetAllLogsAsync()
+ {
+ var result = await _logService.GetAllLogsAsync();
+ return result.IsSuccess ? Ok(result) : BadRequest(result);
+ }
+
+ [HttpGet("{id}")]
+ //[RequirePermission("log:read")]
+ public async Task GetLogByIdAsync(Guid id)
+ {
+ var result = await _logService.GetLogByIdAsync(id);
+ return result.IsSuccess ? Ok(result) : BadRequest(result);
+ }
+
+ [HttpPost]
+ //[RequirePermission("log:create")]
+ public async Task CreateLogAsync([FromBody] LogCreateDto dto)
+ {
+ var result = await _logService.CreateLogAsync(dto);
+ return result.IsSuccess ? Ok(result) : BadRequest(result);
+ }
+
+ [HttpGet("level/{level}")]
+ //[RequirePermission("log:read")]
+ public async Task GetLogsByLevelAsync(string level)
+ {
+ var result = await _logService.GetLogsByLevelAsync(level);
+ return result.IsSuccess ? Ok(result) : BadRequest(result);
+ }
+
+ [HttpGet("user/{userId}")]
+ //[RequirePermission("log:read")]
+ public async Task GetLogsByUserAsync(Guid userId)
+ {
+ var result = await _logService.GetLogsByUserAsync(userId);
+ return result.IsSuccess ? Ok(result) : BadRequest(result);
+ }
+
+ [HttpGet("date")]
+ //[RequirePermission("log:read")]
+ public async Task GetLogsByDateRangeAsync([FromQuery] DateTime start, [FromQuery] DateTime end)
+ {
+ var result = await _logService.GetLogsByDateRangeAsync(start, end);
+ return result.IsSuccess ? Ok(result) : BadRequest(result);
+ }
+
+ [HttpGet("source/{source}")]
+ //[RequirePermission("log:read")]
+ public async Task GetLogsBySourceAsync(string source)
+ {
+ var result = await _logService.GetLogsBySourceAsync(source);
+ return result.IsSuccess ? Ok(result) : BadRequest(result);
+ }
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Api/Controllers/PermissionController.cs b/backend/src/UniversalAdminSystem.Api/Controllers/PermissionController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d4bea70c6a5d664c80c46cbfac17dc6342cea7b6
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/Controllers/PermissionController.cs
@@ -0,0 +1,163 @@
+using Microsoft.AspNetCore.Mvc;
+using UniversalAdminSystem.Application.PermissionManagement.DTOs;
+using UniversalAdminSystem.Application.PermissionManagement.Interfaces;
+using UniversalAdminSystem.Infrastructure.Services;
+using UniversalAdminSystem.Api.Attributes;
+using UniversalAdminSystem.Application.Common.Results;
+
+namespace UniversalAdminSystem.Api.Controllers;
+
+///
+/// 权限管理控制器
+///
+[ApiController]
+[Route("api/permissions")]
+public class PermissionController : ControllerBase
+{
+ private readonly IPermissionManagementAppService _permissionAppService;
+ private readonly PermissionRuleConfigService _permissionRuleConfigService;
+
+ public PermissionController(IPermissionManagementAppService permissionAppService, PermissionRuleConfigService permissionRuleConfigService)
+ {
+ _permissionAppService = permissionAppService;
+ _permissionRuleConfigService = permissionRuleConfigService;
+ }
+
+ ///
+ /// 获取所有权限列表
+ ///
+ [HttpGet]
+ [RequirePermission("permission:Read")]
+ public async Task GetAllPermissionsAsync()
+ {
+ try
+ {
+ var permissions = await _permissionAppService.GetAllPermissionAsync();
+ return Ok(Result>.Success(permissions));
+ }
+ catch (Exception ex)
+ {
+ return BadRequest(Result>.Failure(ex.Message));
+ }
+ }
+
+ ///
+ /// 创建新权限
+ ///
+ [HttpPost("create")]
+ [RequirePermission("permission:Create")]
+ public async Task CreatePermissionAsync([FromBody] PermissionCreateDto createDto)
+ {
+ try
+ {
+ var permission = await _permissionAppService.CreatePermissionAsync(createDto);
+ return Ok(Result.Success(permission));
+ }
+ catch (InvalidOperationException ex)
+ {
+ // 检查是否是重复权限错误
+ if (ex.Message.Contains("已存在"))
+ {
+ return Conflict(Result.Failure(ex.Message));
+ }
+ return BadRequest(Result.Failure(ex.Message));
+ }
+ catch (Exception ex)
+ {
+ return BadRequest(Result.Failure($"创建权限失败: {ex.Message}"));
+ }
+ }
+
+ ///
+ /// 删除权限
+ ///
+ [HttpDelete("{permissionId}")]
+ [RequirePermission("permission:Delete")]
+ public async Task DeletePermissionAsync(Guid permissionId)
+ {
+ try
+ {
+ await _permissionAppService.RemovePermissionAsync(permissionId);
+ return Ok(Result.Success("权限删除成功"));
+ }
+ catch (Exception ex)
+ {
+ return BadRequest(Result.Failure(ex.Message));
+ }
+ }
+
+
+ // 已废弃(请使用Role Controller的分配api)
+ // ///
+ // /// 为角色分配权限
+ // ///
+ // [HttpPost("assign")]
+ // [RequirePermission("permission:Update")]
+ // public async Task AssignPermissionToRoleAsync([FromBody] AssignPermissionDto assignDto)
+ // {
+ // try
+ // {
+ // await _permissionAppService.AssignPermissionToRoleAsync(assignDto);
+ // return Ok(Result.Success("权限分配成功"));
+ // }
+ // catch (Exception ex)
+ // {
+ // return BadRequest(Result.Failure(ex.Message));
+ // }
+ // }
+
+ ///
+ /// 获取权限规则配置
+ ///
+ [HttpGet("rules")]
+ [RequirePermission("permission:Read")]
+ public IActionResult GetPermissionRulesAsync()
+ {
+ try
+ {
+ var rules = _permissionRuleConfigService.GetCurrentConfig();
+ return Ok(Result>>.Success(rules));
+ }
+ catch (Exception ex)
+ {
+ return BadRequest(Result>>.Failure(ex.Message));
+ }
+ }
+
+ ///
+ /// 更新权限规则配置
+ ///
+ [HttpPut("rules")]
+ [RequirePermission("permission:Update")]
+ public IActionResult UpdatePermissionRulesAsync([FromBody] Dictionary> newRules)
+ {
+ try
+ {
+ // TODO: 这里应该校验当前用户是否为超级管理员
+ _permissionRuleConfigService.UpdateConfig(newRules);
+ return Ok(Result.Success("权限规则更新成功"));
+ }
+ catch (Exception ex)
+ {
+ return BadRequest(Result.Failure(ex.Message));
+ }
+ }
+
+ ///
+ /// 刷新权限规则配置
+ ///
+ [HttpPost("rules/refresh")]
+ [RequirePermission("permission:Update")]
+ public IActionResult RefreshPermissionRulesAsync()
+ {
+ try
+ {
+ _permissionRuleConfigService.RefreshConfig();
+ return Ok(Result.Success("权限规则刷新成功"));
+ }
+ catch (Exception ex)
+ {
+ return BadRequest(Result.Failure(ex.Message));
+ }
+ }
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Api/Controllers/RoleController.cs b/backend/src/UniversalAdminSystem.Api/Controllers/RoleController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b975d81b7f92b69bbe3c11a245ef288252ca578f
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/Controllers/RoleController.cs
@@ -0,0 +1,225 @@
+using Microsoft.AspNetCore.Mvc;
+using UniversalAdminSystem.Application.PermissionManagement.DTOs;
+using UniversalAdminSystem.Application.PermissionManagement.Interfaces;
+using UniversalAdminSystem.Api.Attributes;
+using UniversalAdminSystem.Application.Common.Results;
+
+namespace UniversalAdminSystem.Api.Controllers;
+
+///
+/// 角色管理控制器
+/// 提供角色的创建、查询、权限分配等操作
+///
+[ApiController]
+[Route("api/roles")]
+public class RoleController : ControllerBase
+{
+ private readonly IRoleManagementAppService _roleManagementAppService;
+ private readonly IPermissionManagementAppService _permissionAppService;
+
+ public RoleController(
+ IRoleManagementAppService roleManagementAppService,
+ IPermissionManagementAppService permissionAppService)
+ {
+ _roleManagementAppService = roleManagementAppService;
+ _permissionAppService = permissionAppService;
+ }
+
+ ///
+ /// 获取所有角色列表
+ ///
+ [HttpGet]
+ [RequirePermission("role:Read")]
+ public async Task GetAllRolesAsync()
+ {
+ try
+ {
+ var roles = await _roleManagementAppService.GetAllRolesAsync();
+ return Ok(Result>.Success(roles));
+ }
+ catch (Exception ex)
+ {
+ return BadRequest(Result>.Failure(ex.Message));
+ }
+ }
+
+ ///
+ /// 根据ID获取角色
+ ///
+ [HttpGet("{roleId}")]
+ [RequirePermission("role:Read")]
+ public async Task GetRoleByIdAsync(Guid roleId)
+ {
+ try
+ {
+ var role = await _roleManagementAppService.GetRoleByIdAsync(roleId);
+ if (role == null)
+ {
+ return NotFound(Result.Failure("角色不存在"));
+ }
+ return Ok(Result.Success(role));
+ }
+ catch (Exception ex)
+ {
+ return BadRequest(Result.Failure(ex.Message));
+ }
+ }
+
+ ///
+ /// 创建新角色
+ ///
+ [HttpPost]
+ [RequirePermission("role:Create")]
+ public async Task CreateRoleAsync([FromBody] RoleCreateDto createDto)
+ {
+ try
+ {
+ var role = await _roleManagementAppService.CreateRoleAsync(createDto);
+ return Ok(Result.Success(role));
+ }
+ catch (Exception ex)
+ {
+ return BadRequest(Result.Failure(ex.Message));
+ }
+ }
+
+ ///
+ /// 更新角色信息
+ ///
+ [HttpPut("{roleId}")]
+ [RequirePermission("role:Update")]
+ public async Task UpdateRoleAsync(Guid roleId, [FromBody] RoleUpdateDto updateDto)
+ {
+ try
+ {
+ var role = await _roleManagementAppService.UpdateRoleAsync(roleId, updateDto);
+ return Ok(Result.Success(role));
+ }
+ catch (KeyNotFoundException)
+ {
+ return NotFound(Result.Failure("角色不存在"));
+ }
+ catch (Exception ex)
+ {
+ return BadRequest(Result.Failure(ex.Message));
+ }
+ }
+
+ ///
+ /// 删除角色
+ ///
+ [HttpDelete("{roleId}")]
+ [RequirePermission("role:Delete")]
+ public async Task DeleteRoleAsync(Guid roleId)
+ {
+ try
+ {
+ await _roleManagementAppService.DeleteRoleAsync(roleId);
+ return Ok(Result.Success("角色删除成功"));
+ }
+ catch (KeyNotFoundException)
+ {
+ return NotFound(Result.Failure("角色不存在"));
+ }
+ catch (Exception ex)
+ {
+ return BadRequest(Result.Failure(ex.Message));
+ }
+ }
+
+ ///
+ /// 为角色分配权限
+ ///
+ [HttpPost("{roleId}/permissions")]
+ [RequirePermission("role:Update")]
+ public async Task AssignPermissionsToRoleAsync(
+ Guid roleId,
+ [FromBody] List permissionCodes)
+ {
+ try
+ {
+ // 将权限编码转换为权限ID(这里需要根据实际需求调整)
+
+ foreach (var permissionCode in permissionCodes)
+ {
+ var assignDto = new AssignPermissionDto(permissionCode, roleId);
+ await _permissionAppService.AssignPermissionToRoleAsync(assignDto);
+ }
+ return Ok(Result.Success("角色权限分配成功"));
+ }
+ catch (Exception ex)
+ {
+ return BadRequest(Result.Failure(ex.Message));
+ }
+ }
+
+ ///
+ /// 为角色分配权限(使用权限ID)
+ ///
+ [HttpPost("{roleId}/permissions/ids")]
+ [RequirePermission("role:Update")]
+ public async Task AssignPermissionsToRoleByIdsAsync(
+ Guid roleId,
+ [FromBody] List permissionIds)
+ {
+ try
+ {
+ await _roleManagementAppService.AssignPermissionsToRoleAsync(roleId, permissionIds);
+ return Ok(Result.Success("角色权限分配成功"));
+ }
+ catch (KeyNotFoundException)
+ {
+ return NotFound(Result.Failure("角色不存在"));
+ }
+ catch (Exception ex)
+ {
+ return BadRequest(Result.Failure(ex.Message));
+ }
+ }
+
+ ///
+ /// 移除角色的权限
+ ///
+ [HttpDelete("{roleId}/permissions")]
+ [RequirePermission("role:Update")]
+ public async Task RemovePermissionsFromRoleAsync(
+ Guid roleId,
+ [FromBody] List permissionIds)
+ {
+ try
+ {
+ await _roleManagementAppService.RemovePermissionsFromRoleAsync(roleId, permissionIds);
+ return Ok(Result.Success("角色权限移除成功"));
+ }
+ catch (KeyNotFoundException)
+ {
+ return NotFound(Result.Failure("角色不存在"));
+ }
+ catch (Exception ex)
+ {
+ return BadRequest(Result.Failure(ex.Message));
+ }
+ }
+
+ ///
+ /// 获取角色的所有权限
+ ///
+ [HttpGet("{roleId}/permissions")]
+ [RequirePermission("role:Read")]
+ public async Task GetRolePermissionsAsync(Guid roleId)
+ {
+ try
+ {
+ var permissions = await _roleManagementAppService.GetRolePermissionsAsync(roleId);
+ return Ok(Result>.Success(permissions));
+ }
+ catch (KeyNotFoundException)
+ {
+ return NotFound(Result>.Failure("角色不存在"));
+ }
+ catch (Exception ex)
+ {
+ return BadRequest(Result>.Failure(ex.Message));
+ }
+ }
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Api/Controllers/SystemSettingsController.cs b/backend/src/UniversalAdminSystem.Api/Controllers/SystemSettingsController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..57b42c9fbcdc7fe318410e7b8ce26907fbb33dde
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/Controllers/SystemSettingsController.cs
@@ -0,0 +1,63 @@
+using Microsoft.AspNetCore.Mvc;
+using UniversalAdminSystem.Application.SystemSettings.DTOs;
+using UniversalAdminSystem.Application.SystemSettings.Interfaces;
+using UniversalAdminSystem.Api.Attributes;
+using UniversalAdminSystem.Application.Common.Results;
+
+namespace UniversalAdminSystem.Api.Controllers;
+
+[ApiController]
+[Route("api/system-settings")]
+public class SystemSettingsController : ControllerBase
+{
+ private readonly ISystemSettingAppService _settingService;
+ public SystemSettingsController(ISystemSettingAppService settingService) => _settingService = settingService;
+
+ [HttpGet]
+ //[RequirePermission("systemsetting:read")]
+ public async Task GetAllSettingsAsync()
+ {
+ var result = await _settingService.GetAllSettingsAsync();
+ return result.IsSuccess ? Ok(result) : BadRequest(result);
+ }
+
+ [HttpGet("key/{key}")]
+ //[RequirePermission("systemsetting:read")]
+ public async Task GetSettingByKeyAsync(string key)
+ {
+ var result = await _settingService.GetSettingByKeyAsync(key);
+ return result.IsSuccess ? Ok(result) : BadRequest(result);
+ }
+
+ [HttpGet("group/{group}")]
+ //[RequirePermission("systemsetting:read")]
+ public async Task GetSettingsByGroupAsync(string group)
+ {
+ var result = await _settingService.GetSettingsByGroupAsync(group);
+ return result.IsSuccess ? Ok(result) : BadRequest(result);
+ }
+
+ [HttpPost]
+ //[RequirePermission("systemsetting:create")]
+ public async Task CreateSettingAsync([FromBody] SystemSettingCreateDto dto)
+ {
+ var result = await _settingService.CreateSettingAsync(dto);
+ return result.IsSuccess ? Ok(result) : BadRequest(result);
+ }
+
+ [HttpPut("{id}")]
+ //[RequirePermission("systemsetting:update")]
+ public async Task UpdateSetting(Guid id, [FromBody] SystemSettingUpdateDto updateDto)
+ {
+ var result = await _settingService.UpdateSettingAsync(id, updateDto);
+ return result.IsSuccess ? Ok(result) : BadRequest(result);
+ }
+
+ [HttpDelete("{id}")]
+ //[RequirePermission("systemsetting:delete")]
+ public async Task DeleteSettingAsync(Guid id)
+ {
+ var result = await _settingService.DeleteSettingAsync(id);
+ return result.IsSuccess ? Ok(result) : BadRequest(result);
+ }
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Api/Controllers/TestController.cs b/backend/src/UniversalAdminSystem.Api/Controllers/TestController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8d6789b8d5fb919f8601c891de00a8b547f3a74c
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/Controllers/TestController.cs
@@ -0,0 +1,53 @@
+using System.Text;
+using System.Text.Json;
+using Microsoft.AspNetCore.Mvc;
+using UniversalAdminSystem.Infrastructure.Services;
+
+namespace UniversalAdminSystem.Api.Controllers;
+
+[ApiController]
+[Route("api/[controller]")]
+public class TestController : ControllerBase
+{
+ private readonly ILogger _logger;
+ private readonly SpaCyService _spacy;
+ private readonly K2ModelService _k2;
+ private readonly EmbeddingService _embedding;
+
+ public TestController(ILogger logger, K2ModelService k2, SpaCyService spacy, EmbeddingService embedding)
+ {
+ _logger = logger;
+ _k2 = k2;
+ _spacy = spacy;
+ _embedding = embedding;
+ }
+
+ [HttpPost("spacy")]
+ public async Task Spacy([FromBody] SpaCyRequest text)
+ {
+ // 文本分片
+ _logger.LogInformation("开始分片文件: {Text}", text);
+ var preprocessResult = await _spacy.AnalyzeTextAsync(text.Text);
+ Console.WriteLine(preprocessResult.Entities);
+ Console.WriteLine(preprocessResult.Sentences);
+
+ var preprocessResultJson = JsonSerializer.Serialize(preprocessResult, new JsonSerializerOptions
+ {
+ PropertyNamingPolicy = JsonNamingPolicy.CamelCase
+ });
+ var chunks = await _k2.SendChunkingRequestAsync(preprocessResultJson);
+ _logger.LogInformation("分片完成,生成 {Count} 个 chunk", chunks.Count);
+
+ // Embedding
+ _logger.LogInformation("开始Embedding");
+ var embeddings = new List();
+ embeddings.AddRange(await _embedding.GetEmbeddingAsync(chunks));
+ _logger.LogInformation("Embedding 完成: {Count} 个向量", embeddings.Count);
+ return Ok(embeddings);
+ }
+}
+
+public class SpaCyRequest(string text)
+{
+ public string Text { get; set; } = text;
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Api/Controllers/UserManagementController.cs b/backend/src/UniversalAdminSystem.Api/Controllers/UserManagementController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b4b75f731a443fa648e912d538c3ad8bd5e7e9db
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/Controllers/UserManagementController.cs
@@ -0,0 +1,176 @@
+using Microsoft.AspNetCore.Mvc;
+using UniversalAdminSystem.Application.Common.Results;
+using UniversalAdminSystem.Application.UserManagement.Dtos;
+using UniversalAdminSystem.Application.UserManagement.Interface;
+using UniversalAdminSystem.Api.Attributes;
+
+namespace UniversalAdminSystem.Api.Controllers;
+
+///
+/// 用户管理控制器
+///
+[ApiController]
+[Route("api/user")]
+public class UserManagementController : ControllerBase
+{
+ private readonly IUserManagementAppService _userRepoService;
+
+ public UserManagementController(IUserManagementAppService userService)
+ {
+ _userRepoService = userService;
+ }
+
+ [HttpGet]
+ [RequirePermission("user:Read")]
+ public async Task GetUsersAsync()
+ {
+ var result = await _userRepoService.GetUsersAsync();
+
+ if (result.IsSuccess)
+ {
+ return Ok(result);
+ }
+ else
+ {
+ return BadRequest(result);
+ }
+ }
+
+ [HttpPost("create")]
+ [RequirePermission("user:Create")]
+ public async Task CreateUserAsync([FromBody] UserCreateDto userCreate)
+ {
+ var result = await _userRepoService.CreateUserAsync(userCreate);
+
+ if (result.IsSuccess)
+ {
+ return Ok(result);
+ }
+ else
+ {
+ return BadRequest(result);
+ }
+ }
+
+ [HttpDelete("{id}")]
+ [RequirePermission("user:Delete")]
+ public async Task DeleteUserAsync(Guid id)
+ {
+ var result = await _userRepoService.DeleteUserAsync(id);
+
+ if (result.IsSuccess)
+ {
+ return Ok(result);
+ }
+ else
+ {
+ return BadRequest(result);
+ }
+ }
+
+ [HttpGet("{id}")]
+ [RequirePermission("user:Read")]
+ public async Task GetUserByIdAsync(Guid id)
+ {
+ var result = await _userRepoService.GetUserByIdAsync(id);
+
+ if (result.IsSuccess)
+ {
+ return Ok(result);
+ }
+ else
+ {
+ return BadRequest(result);
+ }
+ }
+
+ [HttpPut("{id}")]
+ [RequirePermission("user:Update")]
+ public async Task UpdateUserAsync(Guid id, [FromBody] UserUpdateDto updateDto)
+ {
+ var result = await _userRepoService.UpdateUserAsync(id, updateDto);
+
+ if (result.IsSuccess)
+ {
+ return Ok(result);
+ }
+ else
+ {
+ return BadRequest(result);
+ }
+ }
+
+ // 已废弃(批量获取角色)
+ // [HttpPost("{id}/role")]
+ // [RequirePermission("user:Update")]
+ // public async Task AssignRoleAsync(Guid id, [FromBody] List roleIds)
+ // {
+ // var result = await _userRepoService.AssignRoleAsync(id, roleIds);
+
+ // if (result.IsSuccess)
+ // {
+ // return Ok(result);
+ // }
+ // else
+ // {
+ // return BadRequest(result);
+ // }
+ // }
+
+ ///
+ /// 移除用户角色
+ ///
+ [HttpDelete("{id}/roles/{roleId}")]
+ [RequirePermission("user:Update")]
+ public async Task RemoveRoleAsync(Guid id, Guid roleId)
+ {
+ var result = await _userRepoService.RemoveRoleAsync(id, roleId);
+
+ if (result.IsSuccess)
+ {
+ return Ok(result);
+ }
+ else
+ {
+ return BadRequest(result);
+ }
+ }
+
+ ///
+ /// 获取用户的所有权限
+ ///
+ [HttpGet("{id}/permissions")]
+ [RequirePermission("user:Read")]
+ public async Task GetUserPermissionsAsync(Guid id)
+ {
+ var result = await _userRepoService.GetUserPermissionsAsync(id);
+
+ if (result.IsSuccess)
+ {
+ return Ok(result);
+ }
+ else
+ {
+ return BadRequest(result);
+ }
+ }
+
+ ///
+ /// 检查用户是否有指定权限
+ ///
+ [HttpPost("{id}/permissions/check")]
+ [RequirePermission("user:Read")]
+ public async Task CheckUserPermissionAsync(Guid id, [FromBody] string permissionCode)
+ {
+ var result = await _userRepoService.CheckUserPermissionAsync(id, permissionCode);
+
+ if (result.IsSuccess)
+ {
+ return Ok(result);
+ }
+ else
+ {
+ return BadRequest(result);
+ }
+ }
+}
diff --git a/backend/src/UniversalAdminSystem.Api/Controllers/UserRoleController.cs b/backend/src/UniversalAdminSystem.Api/Controllers/UserRoleController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..935fd991b9e9e44f2a04a0d40a53a3600314c91b
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/Controllers/UserRoleController.cs
@@ -0,0 +1,122 @@
+using Microsoft.AspNetCore.Mvc;
+using UniversalAdminSystem.Application.Common.Results;
+using UniversalAdminSystem.Application.PermissionManagement.Interfaces;
+using UniversalAdminSystem.Api.Attributes;
+
+namespace UniversalAdminSystem.Api.Controllers;
+
+///
+/// 用户角色管理控制器
+/// 提供用户角色分配和管理功能
+///
+[ApiController]
+[Route("api/users")]
+public class UserRoleController : ControllerBase
+{
+ private readonly IPermissionCheckService _permissionCheckService;
+
+ public UserRoleController(IPermissionCheckService permissionCheckService)
+ {
+ _permissionCheckService = permissionCheckService;
+ }
+
+ ///
+ /// 获取用户的所有权限
+ ///
+ [HttpGet("{userId}/permissions")]
+ [RequirePermission("user:Read")]
+ public async Task GetUserPermissionsAsync(Guid userId)
+ {
+ try
+ {
+ var permissions = await _permissionCheckService.GetUserPermissionsAsync(userId);
+ var result = Result>.Success(permissions);
+ return Ok(result);
+ }
+ catch (Exception ex)
+ {
+ var result = Result>.Failure($"获取用户权限失败: {ex.Message}");
+ return BadRequest(result);
+ }
+ }
+
+ ///
+ /// 获取用户的所有角色
+ ///
+ [HttpGet("{userId}/roles")]
+ [RequirePermission("user:Read")]
+ public async Task GetUserRolesAsync(Guid userId)
+ {
+ try
+ {
+ var roles = await _permissionCheckService.GetUserRoleAsync(userId);
+ var result = Result>.Success(roles);
+ return Ok(result);
+ }
+ catch (Exception ex)
+ {
+ var result = Result>.Failure($"获取用户角色失败: {ex.Message}");
+ return BadRequest(result);
+ }
+ }
+
+ ///
+ /// 检查用户是否有指定权限
+ ///
+ [HttpPost("{userId}/permissions/check")]
+ [RequirePermission("user:Read")]
+ public async Task CheckUserPermissionAsync(Guid userId, [FromBody] string permissionCode)
+ {
+ try
+ {
+ var hasPermission = await _permissionCheckService.CheckUserPermissionAsync(userId, permissionCode);
+ var result = Result.Success(hasPermission);
+ return Ok(result);
+ }
+ catch (Exception ex)
+ {
+ var result = Result.Failure($"检查用户权限失败: {ex.Message}");
+ return BadRequest(result);
+ }
+ }
+
+ ///
+ /// 检查用户是否有任意一个指定权限
+ ///
+ [HttpPost("{userId}/permissions/check-any")]
+ [RequirePermission("user:Read")]
+ public async Task CheckUserAnyPermissionAsync(Guid userId, [FromBody] List permissionCodes)
+ {
+ try
+ {
+ var hasPermission = await _permissionCheckService.CheckUserAnyPermissionAsync(userId, permissionCodes);
+ var result = Result.Success(hasPermission);
+ return Ok(result);
+ }
+ catch (Exception ex)
+ {
+ var result = Result.Failure($"检查用户权限失败: {ex.Message}");
+ return BadRequest(result);
+ }
+ }
+
+ ///
+ /// 检查用户是否有所有指定权限
+ ///
+ [HttpPost("{userId}/permissions/check-all")]
+ [RequirePermission("user:Read")]
+ public async Task CheckUserAllPermissionsAsync(Guid userId, [FromBody] List permissionCodes)
+ {
+ try
+ {
+ var hasPermission = await _permissionCheckService.CheckUserAllPermissionsAsync(userId, permissionCodes);
+ var result = Result.Success(hasPermission);
+ return Ok(result);
+ }
+ catch (Exception ex)
+ {
+ var result = Result.Failure($"检查用户权限失败: {ex.Message}");
+ return BadRequest(result);
+ }
+ }
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Api/K2ModelTests.http b/backend/src/UniversalAdminSystem.Api/K2ModelTests.http
new file mode 100644
index 0000000000000000000000000000000000000000..ae1fd04ad9a8157616f3f7f656bb59c4492def38
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/K2ModelTests.http
@@ -0,0 +1,20 @@
+###
+POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions
+Content-Type: application/json
+Authorization: Bearer sk-a31163f6b59e44dcbdb87c668482ce96
+
+{
+ "model": "Moonshot-Kimi-K2-Instruct",
+ "messages": [
+ {
+ "role": "user",
+ "content": "你好,请介绍一下你自己"
+ }
+ ],
+ "temperature": 0.7,
+ "max_tokens": 1000,
+ "stream": true,
+ "stream_options": {
+ "include_usage": true
+ }
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Api/Middleware/JwtAuthenticationMiddleware.cs b/backend/src/UniversalAdminSystem.Api/Middleware/JwtAuthenticationMiddleware.cs
new file mode 100644
index 0000000000000000000000000000000000000000..c528bfa46d414d333ce26d0c85b4cc72cacc63c8
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/Middleware/JwtAuthenticationMiddleware.cs
@@ -0,0 +1,126 @@
+using System.Security.Claims;
+using UniversalAdminSystem.Application.Authentication.Interfaces;
+using UniversalAdminSystem.Domian.UserManagement.ValueObj;
+
+namespace UniversalAdminSystem.Api.Middleware;
+
+public class JwtAuthenticationMiddleware
+{
+ private readonly RequestDelegate _next;
+ private readonly IJwtTokenService _jwtService;
+ private readonly ILogger _logger;
+
+ public JwtAuthenticationMiddleware(
+ RequestDelegate next,
+ IJwtTokenService jwtService,
+ ILogger logger)
+ {
+ _next = next;
+ _jwtService = jwtService;
+ _logger = logger;
+ }
+
+ public async Task InvokeAsync(HttpContext context)
+ {
+ try
+ {
+ var token = ExtractTokenFromHeader(context);
+ Console.WriteLine($"提取到的Token: {(token != null ? "存在" : "不存在")}");
+ if (!string.IsNullOrEmpty(token))
+ {
+ Console.WriteLine($"Token内容: {token.Substring(0, Math.Min(50, token.Length))}...");
+ var userInfo = await AuthenticateTokenAsync(token);
+ if (userInfo.HasValue)
+ {
+ Console.WriteLine($"Token解析结果 - 用户ID: {userInfo.Value.UserId}, 角色ID: {userInfo.Value.RoleId}, 状态: {userInfo.Value.status}");
+ SetUserClaims(context, userInfo.Value);
+ _logger.LogInformation("用户 {UserId} 认证成功", userInfo.Value.UserId);
+ }
+ else
+ {
+ Console.WriteLine("Token解析失败");
+ }
+ }
+ else
+ {
+ Console.WriteLine("Token不存在");
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning("JWT认证中间件异常: {Message}", ex.Message);
+ }
+
+ await _next(context);
+ }
+
+ private string? ExtractTokenFromHeader(HttpContext context)
+ {
+ var authHeader = context.Request.Headers["Authorization"].FirstOrDefault();
+ Console.WriteLine($"Authorization头: {authHeader ?? "null"}");
+
+ if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
+ {
+ Console.WriteLine("Authorization头为空或不以Bearer开头");
+ return null;
+ }
+
+ var token = authHeader.Substring("Bearer ".Length).Trim();
+ Console.WriteLine($"提取的Token长度: {token.Length}");
+ Console.WriteLine($"Token前50个字符: {token.Substring(0, Math.Min(50, token.Length))}");
+
+ // 检查token格式
+ if (string.IsNullOrEmpty(token))
+ {
+ Console.WriteLine("Token为空");
+ return null;
+ }
+
+ // JWT应该包含两个点,格式为: header.payload.signature
+ var parts = token.Split('.');
+ if (parts.Length != 3)
+ {
+ Console.WriteLine($"Token格式错误,包含{parts.Length}个部分,应该是3个部分");
+ return null;
+ }
+
+ Console.WriteLine("Token格式检查通过");
+ return token;
+ }
+
+ private async Task<(string UserId, string RoleId, UserStatus status)?> AuthenticateTokenAsync(string token)
+ {
+ try
+ {
+ var (userId, roleId, status) = _jwtService.ParseToken(token);
+ Console.WriteLine($"Token解析结果 - 用户ID: {userId}, 角色ID: {roleId}, 状态: {status}");
+ return (userId, roleId, status);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning("Token解析失败: {Message}", ex.Message);
+ return null;
+ }
+ }
+
+ private void SetUserClaims(HttpContext context, (string UserId, string RoleId, UserStatus status) userInfo)
+ {
+ var claims = new List
+ {
+ new Claim(ClaimTypes.NameIdentifier, userInfo.UserId),
+ new Claim(ClaimTypes.Role, userInfo.RoleId),
+ new Claim(ClaimTypes.StateOrProvince, userInfo.status.ToString()),
+ };
+
+ var identity = new ClaimsIdentity(claims, "jwt");
+ context.User = new ClaimsPrincipal(identity);
+ }
+}
+
+public static class JwtAuthenticationMiddlewareExtensions
+{
+ public static IApplicationBuilder UseJwtAuthentication(this IApplicationBuilder builder)
+ {
+ return builder.UseMiddleware();
+ }
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Api/PermissionRules.json b/backend/src/UniversalAdminSystem.Api/PermissionRules.json
new file mode 100644
index 0000000000000000000000000000000000000000..2c8a6a266227f8916da510946f9e11f0468f95c2
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/PermissionRules.json
@@ -0,0 +1,13 @@
+{
+ "Read": ["data", "file", "user", "role", "permission", "config", "system", "report","document"],
+ "Create": ["data", "user", "file", "role", "permission"],
+ "Update": ["data", "user", "config", "role", "permission"],
+ "Delete": ["data", "user", "file", "role", "permission"],
+ "Manage": ["system", "user"],
+ "Execute": ["job", "script"],
+ "Import": ["data", "file"],
+ "Export": ["data", "file", "report"],
+ "Public": ["document"],
+ "Restricted": ["document"],
+ "Private": ["document"]
+}
diff --git a/backend/src/UniversalAdminSystem.Api/Program.cs b/backend/src/UniversalAdminSystem.Api/Program.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5fb4110917d7238c6096064ce66bb217d5743e52
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/Program.cs
@@ -0,0 +1,105 @@
+using UniversalAdminSystem.Infrastructure.DependencyInject;
+using UniversalAdminSystem.Infrastructure.Services;
+using UniversalAdminSystem.Api.Middleware;
+using Microsoft.OpenApi.Models;
+
+var builder = WebApplication.CreateBuilder(args);
+
+// 加载外部的允许文件配置,避免 appsettings.json 膨胀
+builder.Configuration.AddJsonFile("AllowedFiles.json", optional: false, reloadOnChange: true);
+
+builder.Services.AddHttpClient();
+// 添加CORS服务
+builder.Services.AddCors(options =>
+{
+ // 开发环境策略 - 允许所有来源
+ options.AddPolicy("AllowAll", policy =>
+ {
+ policy.AllowAnyOrigin()
+ .AllowAnyMethod()
+ .AllowAnyHeader();
+ });
+
+ // 生产环境策略 - 指定允许的来源
+ options.AddPolicy("AllowSpecific", policy =>
+ {
+ policy.WithOrigins(
+ "http://localhost:5173",
+ "http://localhost:3000", // React开发服务器
+ "http://localhost:8080", // Vue开发服务器
+ "http://localhost:4200", // Angular开发服务器
+ "https://mikuslittlenest.cn", // 生产域名
+ "http://www.mikuslittlenest.cn",
+ "http://localhost:8081",
+ "http://mikuslittlenest.cn"
+ )
+ .AllowAnyMethod()
+ .AllowAnyHeader()
+ .AllowCredentials();
+ });
+});
+
+// Add services to the container.
+builder.Services.AddEndpointsApiExplorer();
+builder.Services.AddSwaggerGen(c =>
+{
+ c.SwaggerDoc("v1", new OpenApiInfo { Title = "Universal Admin System API", Version = "v1" });
+
+ // 添加JWT认证配置
+ c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
+ {
+ Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
+ Name = "Authorization",
+ In = ParameterLocation.Header,
+ Type = SecuritySchemeType.ApiKey,
+ Scheme = "Bearer"
+ });
+
+ c.AddSecurityRequirement(new OpenApiSecurityRequirement
+ {
+ {
+ new OpenApiSecurityScheme
+ {
+ Reference = new OpenApiReference
+ {
+ Type = ReferenceType.SecurityScheme,
+ Id = "Bearer"
+ }
+ },
+ new string[] {}
+ }
+ });
+});
+
+// 在应用启动时初始化权限规则配置
+var configPath = Path.Combine(Directory.GetCurrentDirectory(), "PermissionRules.json");
+var permissionRuleConfigService = new PermissionRuleConfigService(configPath);
+permissionRuleConfigService.Initialize();
+
+builder.Services.AddSingleton(permissionRuleConfigService);
+
+// 显式注册 AllowedFilesConfig
+builder.Services.Configure(
+ builder.Configuration.GetSection("AllowedFiles"));
+
+builder.Services.AddAllService(builder.Configuration);
+builder.Services.AddControllers();
+
+var app = builder.Build();
+
+// Configure the HTTP request pipeline.
+if (app.Environment.IsDevelopment())
+{
+ app.UseSwagger();
+ app.UseSwaggerUI();
+}
+
+app.UseCors("AllowSpecific");
+
+// 添加JWT认证中间件
+Console.WriteLine("正在注册JWT认证中间件...");
+app.UseJwtAuthentication();
+Console.WriteLine("JWT认证中间件注册完成");
+
+app.MapControllers();
+app.Run();
diff --git a/backend/src/UniversalAdminSystem.Api/Properties/launchSettings.json b/backend/src/UniversalAdminSystem.Api/Properties/launchSettings.json
new file mode 100644
index 0000000000000000000000000000000000000000..db616011b26ea66a5e4440373d36404056175094
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/Properties/launchSettings.json
@@ -0,0 +1,41 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:56387",
+ "sslPort": 44340
+ }
+ },
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "applicationUrl": "http://localhost:5101",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "applicationUrl": "https://localhost:7242;http://localhost:5101",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/backend/src/UniversalAdminSystem.Api/SystemPermissions.json b/backend/src/UniversalAdminSystem.Api/SystemPermissions.json
new file mode 100644
index 0000000000000000000000000000000000000000..7aa7b88cdcfc5f1a9bfb34e096149736975e79b6
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/SystemPermissions.json
@@ -0,0 +1,89 @@
+{
+ "SystemPermissions": [
+ {
+ "Resource": "file",
+ "Action": "Create",
+ "Name": "文件上传"
+ },
+ {
+ "Resource": "file",
+ "Action": "Read",
+ "Name": "文件下载"
+ },
+ {
+ "Resource": "file",
+ "Action": "Delete",
+ "Name": "文件删除"
+ },
+ {
+ "Resource": "user",
+ "Action": "Create",
+ "Name": "创建用户"
+ },
+ {
+ "Resource": "user",
+ "Action": "Read",
+ "Name": "查看用户"
+ },
+ {
+ "Resource": "user",
+ "Action": "Update",
+ "Name": "更新用户"
+ },
+ {
+ "Resource": "user",
+ "Action": "Delete",
+ "Name": "删除用户"
+ },
+ {
+ "Resource": "role",
+ "Action": "Create",
+ "Name": "创建角色"
+ },
+ {
+ "Resource": "role",
+ "Action": "Read",
+ "Name": "查看角色"
+ },
+ {
+ "Resource": "role",
+ "Action": "Update",
+ "Name": "更新角色"
+ },
+ {
+ "Resource": "role",
+ "Action": "Delete",
+ "Name": "删除角色"
+ },
+ {
+ "Resource": "permission",
+ "Action": "Create",
+ "Name": "创建权限"
+ },
+ {
+ "Resource": "permission",
+ "Action": "Read",
+ "Name": "查看权限"
+ },
+ {
+ "Resource": "permission",
+ "Action": "Update",
+ "Name": "更新权限"
+ },
+ {
+ "Resource": "permission",
+ "Action": "Delete",
+ "Name": "删除权限"
+ },
+ {
+ "Resource": "config",
+ "Action": "Update",
+ "Name": "更新系统配置"
+ },
+ {
+ "Resource": "system",
+ "Action": "Manage",
+ "Name": "管理安全策略"
+ }
+ ]
+}
diff --git a/backend/src/UniversalAdminSystem.Api/UniversalAdminSystem.Api.csproj b/backend/src/UniversalAdminSystem.Api/UniversalAdminSystem.Api.csproj
new file mode 100644
index 0000000000000000000000000000000000000000..5e7a731a722430a09a19f0350d1d876d0aec3084
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/UniversalAdminSystem.Api.csproj
@@ -0,0 +1,23 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
+
diff --git a/backend/src/UniversalAdminSystem.Api/UniversalAdminSystem.Api.http b/backend/src/UniversalAdminSystem.Api/UniversalAdminSystem.Api.http
new file mode 100644
index 0000000000000000000000000000000000000000..1596c1b6f35b2a20307bc62e11cae2f3b6813cc5
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/UniversalAdminSystem.Api.http
@@ -0,0 +1,18 @@
+@url = http://localhost:5101
+
+### login
+POST {{url}}/api/auth/login
+Content-Type: application/json
+
+{
+ "account": "manager",
+ "password": "manager123"
+}
+
+### test spacy
+POST {{url}}/api/test/spacy
+Content-Type: application/json
+
+{
+ "text": "初音未来(日语:初音 ミク/はつねミク Hatsune Miku)是克理普敦未来媒体(简称Crypton Future Media)以雅马哈的VOCALOID语音合成引擎为基础开发的虚拟歌手。她的形象是一位留着青绿色双马尾、身穿未来感服装的16岁少女。自2007年发布以来,她在全球范围内获得了大量粉丝,演唱会甚至使用全息投影技术现场表演。她的粉丝遍布中国、日本、美国等地。Her popularity spread rapidly through platforms like YouTube, NicoNico Douga, and Bilibili.\n\nCrypton在2020年发布了基于全新M9引擎的初音未来NT版本,该版本改进了发音的自然度和表现力。初音未来不仅仅是一款软件,更是音乐创作文化的象征。许多音乐人,包括著名制作人ryo(supercell)、DECO*27,都为她创作了脍炙人口的作品,如《千本樱》《Tell Your World》。这些作品在全球播放量超过数亿次,并被翻唱成多种语言版本。\n以下是一个超长的无标点测试段落它包含了许多描述但是没有任何中文句号逗号或感叹号这种情况下我们的分片算法应该能够在达到最大token限制时自动切割同时保持尽可能的语义完整性而不是让分片在一个人名例如初音未来的中间被截断因为那样会影响RAG的召回效果\n此外,初音未来的成功还催生了大量衍生角色和跨界合作。例如,雪初音是她的冬季特别版本,已经连续多年成为札幌冰雪节的形象大使。她还与赛车、旅游、食品、服装等行业合作,形成了庞大的商业生态。In the future, AI voice synthesis technology may allow for even more natural and expressive performances, and Hatsune Miku could evolve into an interactive virtual idol capable of real-time conversations with fans."
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Api/appsettings.json b/backend/src/UniversalAdminSystem.Api/appsettings.json
new file mode 100644
index 0000000000000000000000000000000000000000..070b4fdfe3bf7dc8183251b8c216f0d051696bd2
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Api/appsettings.json
@@ -0,0 +1,37 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning",
+ "UniversalAdminSystem.Infrastructure.Services.SystemPermissionConfigLoader": "Debug"
+ }
+ },
+ "AllowedHosts": "*",
+ "ConnectionStrings": {
+ "pgSql": "Server=localhost;Port=5432;Username=admin;Password=031028@yue;Database=rag_vector_db",
+ "RabbitMq": "amqp://admin:admin@localhost:5672/"
+ },
+ "Jwt": {
+ "Key": "YourSuperSecretKey1232347509872093oiqewupori",
+ "Issuer": "UniversalAdminSystem",
+ "Audience": "api-web-admin",
+ "ExpireHours": 2
+ },
+ "K2": {
+ "ApiKey": "sk-a31163f6b59e44dcbdb87c668482ce96",
+ "BaseUrl": "https://dashscope.aliyuncs.com/compatible-mode/v1/"
+ },
+ "Tongyi": {
+ "ApiKey": "sk-a31163f6b59e44dcbdb87c668482ce96",
+ "BaseUrl": "https://dashscope.aliyuncs.com/"
+ },
+ "RabbitMq": {
+ "Host": "localhost",
+ "Port": 5672,
+ "Username": "guest",
+ "Password": "guest",
+ "Exchange": "file-processing",
+ "Queue": "file-processing-queue",
+ "RoutingKey": "file-processing"
+ }
+}
diff --git a/backend/src/UniversalAdminSystem.Application/AIQuestions/DTOs/ContentDto.cs b/backend/src/UniversalAdminSystem.Application/AIQuestions/DTOs/ContentDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..9bdf02857f872aafe0d952dd12925064e2f16874
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/AIQuestions/DTOs/ContentDto.cs
@@ -0,0 +1,3 @@
+namespace UniversalAdminSystem.Application.AIQuestions.DTOs;
+
+public record ContentDto(string Content);
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/AIQuestions/DTOs/ContentResultDto.cs b/backend/src/UniversalAdminSystem.Application/AIQuestions/DTOs/ContentResultDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..98786f9d68ac12a339056adf7e2758ec7b85433d
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/AIQuestions/DTOs/ContentResultDto.cs
@@ -0,0 +1,3 @@
+namespace UniversalAdminSystem.Application.AIQuestions.DTOs;
+
+public record ContentResultDto(string Role,string Content);
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/AIQuestions/DTOs/ConversationsDto.cs b/backend/src/UniversalAdminSystem.Application/AIQuestions/DTOs/ConversationsDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e28eaf9e585223b76569e81b7feb1800c7b9b88c
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/AIQuestions/DTOs/ConversationsDto.cs
@@ -0,0 +1,3 @@
+namespace UniversalAdminSystem.Application.AIQuestions.DTOs;
+
+public record ConversationsDto(Guid UserId,string Title);
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/AIQuestions/DTOs/ConversationsResultDto.cs b/backend/src/UniversalAdminSystem.Application/AIQuestions/DTOs/ConversationsResultDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1349ba6a7f445ab293128b6894b86db9f3d51069
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/AIQuestions/DTOs/ConversationsResultDto.cs
@@ -0,0 +1,3 @@
+namespace UniversalAdminSystem.Application.AIQuestions.DTOs;
+
+public record ConversationsResultDto(Guid ConversationId,string? Title);
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/AIQuestions/Interfaces/IAIQusetionsAppService.cs b/backend/src/UniversalAdminSystem.Application/AIQuestions/Interfaces/IAIQusetionsAppService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..c00924e7bfb4195f5fda679c14dcb45abefbacfa
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/AIQuestions/Interfaces/IAIQusetionsAppService.cs
@@ -0,0 +1,21 @@
+using UniversalAdminSystem.Application.AIQuestions.DTOs;
+
+namespace UniversalAdminSystem.Application.AIQuestions.Interfaces;
+
+public interface IAIQusetionsAppService
+{
+
+ Task> GetUsersConversationsByUserId(Guid userId);
+
+ Task DeleteUserConversations(Guid ConversationsId);
+
+ Task VisitorAccess(ContentDto content);
+
+ Task UserAccess(Guid id, ContentDto content);
+
+ Task> GetConversationMessage(Guid Id);
+
+ Task CreateConversation(ConversationsDto conversationsDto);
+
+ Task Chat(Guid conversationId, string userMessage);
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/AIQuestions/Interfaces/IAnswerService.cs b/backend/src/UniversalAdminSystem.Application/AIQuestions/Interfaces/IAnswerService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..4ae1201492acfbec96e882627e672760c6af1c32
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/AIQuestions/Interfaces/IAnswerService.cs
@@ -0,0 +1,8 @@
+using UniversalAdminSystem.Domian.UserConversations.Aggregates;
+
+namespace UniversalAdminSystem.Application.AIQuestions.Interfaces;
+
+public interface IAnswerService
+{
+ Task AnswerAsync(string userInput, IEnumerable? messages);
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/AIQuestions/Service/AIQusetionsAppService.cs b/backend/src/UniversalAdminSystem.Application/AIQuestions/Service/AIQusetionsAppService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..dbebcef9da932223db7c1d3b5ed1b92108cb6a50
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/AIQuestions/Service/AIQusetionsAppService.cs
@@ -0,0 +1,142 @@
+using UniversalAdminSystem.Application.AIQuestions.DTOs;
+using UniversalAdminSystem.Application.AIQuestions.Interfaces;
+using UniversalAdminSystem.Application.Common.Interfaces;
+using UniversalAdminSystem.Application.PermissionManagement.Interfaces;
+using UniversalAdminSystem.Domian.Core.ValueObjects;
+using UniversalAdminSystem.Domian.UserConversations.Aggregates;
+using UniversalAdminSystem.Domian.UserConversations.IRepository;
+using UniversalAdminSystem.Domian.UserManagement.IRepository;
+
+namespace UniversalAdminSystem.Application.AIQuestions.Service;
+
+public class AIQusetionsAppService : IAIQusetionsAppService
+{
+ private readonly IMessageRepository _messageRepo;
+
+ private readonly IConversationsRepository _conversationsRepo;
+
+ private readonly IPermissionCheckService _permissioncheck;
+
+ private readonly IUserRepository _userRepository;
+
+ private readonly IUnitOfWork _work;
+ private readonly IAnswerService _answerService;
+
+ public AIQusetionsAppService(IMessageRepository message,
+ IConversationsRepository conversations,
+ IPermissionCheckService permissioncheck,
+ IUnitOfWork work,
+ IUserRepository userRepository,
+ IAnswerService answerService)
+ {
+ _messageRepo = message;
+ _conversationsRepo = conversations;
+ _permissioncheck = permissioncheck;
+ _work = work;
+ _userRepository = userRepository;
+ _answerService = answerService;
+ }
+
+ public async Task CreateConversation(ConversationsDto conversationsDto)
+ {
+ try
+ {
+ var user = await _userRepository.GetByGuidAsync(conversationsDto.UserId) ?? throw new Exception("用户不存在");
+ await _work.BeginTransactionAsync();
+ var Conversation = Conversations.Create(conversationsDto.UserId, conversationsDto.Title);
+ var entity = await _conversationsRepo.AddAsync(Conversation);
+ await _work.CommitAsync();
+ return new ConversationsResultDto(entity.Id.Value, entity.Title);
+ }
+ catch (System.Exception e)
+ {
+ await _work.RollbackAsync();
+ throw new Exception($"用户会话创建失败:{e.Message}");
+ }
+ }
+
+ public async Task DeleteUserConversations(Guid ConversationsId)
+ {
+ try
+ {
+ await _work.BeginTransactionAsync();
+ await _messageRepo.RemoveByConversationIdAsync(ConversationsId);
+ await _conversationsRepo.RemoveConversation(ConversationsId);
+ await _work.CommitAsync();
+ }
+ catch (System.Exception)
+ {
+ await _work.RollbackAsync();
+ throw new Exception("删除异常");
+ }
+ }
+
+ public async Task> GetConversationMessage(Guid Id)
+ {
+ try
+ {
+ var list = await _messageRepo.GetByConversationIdAsync(Id);
+ return list.Select(m => new ContentResultDto(m.Role, m.Content));
+ }
+ catch (System.Exception)
+ {
+ throw new Exception("获取用户会话消息失败");
+ }
+ }
+
+ public async Task> GetUsersConversationsByUserId(Guid userId)
+ {
+ try
+ {
+ var user = await _userRepository.GetByGuidAsync(userId) ?? throw new Exception("用户不存在");
+ var list = await _conversationsRepo.GetByUserIdAsync(userId);
+ return list.Select(m => new ConversationsResultDto(m.Id.Value, m.Title));
+ }
+ catch (System.Exception e)
+ {
+ throw new Exception($"获取用户会话失败:{e.Message}");
+ }
+ }
+
+ public async Task Chat(Guid conversationId, string userInput)
+ {
+ try
+ {
+ // 开启事务
+ await _work.BeginTransactionAsync();
+
+ // 创建消息并持久化
+ var message = Message.Create(ConversationId.Create(conversationId), "user", userInput);
+ await _messageRepo.AddAsync(message);
+
+ await _work.CommitAsync();
+ // 回答
+ await _work.BeginTransactionAsync();
+ var messages = await _messageRepo.GetByConversationIdAsync(conversationId);
+ System.Console.WriteLine("消息列表:",messages);
+ var temp = await _answerService.AnswerAsync(userInput, messages);
+ System.Console.WriteLine(temp);
+ var Systemmessage = Message.Create(ConversationId.Create(conversationId), "system", temp);
+ await _messageRepo.AddAsync(Systemmessage);
+ await _work.CommitAsync();
+ return temp;
+ }
+ catch (System.Exception e)
+ {
+ await _work.RollbackAsync();
+ throw new Exception(e.Message);
+ }
+
+
+ }
+
+ public Task UserAccess(Guid id, ContentDto content)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task VisitorAccess(ContentDto content)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/Authentication/DTOs/CredentialDto.cs b/backend/src/UniversalAdminSystem.Application/Authentication/DTOs/CredentialDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..bd00463569e418a98f1008911948dad8eab28e5d
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/Authentication/DTOs/CredentialDto.cs
@@ -0,0 +1,3 @@
+namespace UniversalAdminSystem.Application.Authentication.DTOs;
+
+public record CredentialDto(string Message, string? Account = null, string? Token = null);
diff --git a/backend/src/UniversalAdminSystem.Application/Authentication/DTOs/LoginDto.cs b/backend/src/UniversalAdminSystem.Application/Authentication/DTOs/LoginDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..14bb597dc0e88473ec907bd0e58928820e843484
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/Authentication/DTOs/LoginDto.cs
@@ -0,0 +1,3 @@
+namespace UniversalAdminSystem.Application.Authentication.DTOs;
+
+public record LoginDto(string Account, string Password);
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/Authentication/DTOs/LoginResultDto.cs b/backend/src/UniversalAdminSystem.Application/Authentication/DTOs/LoginResultDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..742c9c124afd2c3c14b5d24e116b7a7a05bde8d6
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/Authentication/DTOs/LoginResultDto.cs
@@ -0,0 +1,5 @@
+using UniversalAdminSystem.Domian.UserManagement.Entities;
+
+namespace UniversalAdminSystem.Application.Authentication.DTOs;
+
+public record LoginResultDto(string Token, string UserId, string RoleId, string UserName,UserInfo UserInfo);
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/Authentication/DTOs/RegisterDto.cs b/backend/src/UniversalAdminSystem.Application/Authentication/DTOs/RegisterDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8006203034c7633dc9dc6516a3672ca4c8aad500
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/Authentication/DTOs/RegisterDto.cs
@@ -0,0 +1,3 @@
+namespace UniversalAdminSystem.Application.Authentication.DTOs;
+
+public record RegisterDto(string Account, string Password, string Email);
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/Authentication/DTOs/RegisterResultDto.cs b/backend/src/UniversalAdminSystem.Application/Authentication/DTOs/RegisterResultDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..00c7d44b1b6895cbd8fde95ff42cb88bbf6574eb
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/Authentication/DTOs/RegisterResultDto.cs
@@ -0,0 +1,3 @@
+namespace UniversalAdminSystem.Application.Authentication.DTOs;
+
+public record RegisterResultDto(string UserId, string Account, string Message);
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/Authentication/DTOs/TokenDto.cs b/backend/src/UniversalAdminSystem.Application/Authentication/DTOs/TokenDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e91dd4d16d383e05deebcb78a57740dab76d59cd
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/Authentication/DTOs/TokenDto.cs
@@ -0,0 +1,26 @@
+namespace UniversalAdminSystem.Application.Authentication.DTOs;
+
+///
+/// 刷新Token请求DTO
+///
+public record RefreshTokenDto(string Token);
+
+///
+/// 刷新Token结果DTO
+///
+public record RefreshTokenResultDto(string Token, string UserId, string RoleId);
+
+///
+/// 验证Token请求DTO
+///
+public record ValidateTokenDto(string Token);
+
+///
+/// Token验证结果DTO
+///
+public record TokenValidationResultDto(bool IsValid, string UserId, string RoleId);
+
+///
+/// 登出响应DTO
+///
+public record LogoutResultDto(string Message);
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/Authentication/Interfaces/IJwtTokenService.cs b/backend/src/UniversalAdminSystem.Application/Authentication/Interfaces/IJwtTokenService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b9413a3df28a446ab9708c82a9d9a1ccfb93fa39
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/Authentication/Interfaces/IJwtTokenService.cs
@@ -0,0 +1,10 @@
+using UniversalAdminSystem.Domian.UserManagement.ValueObj;
+
+namespace UniversalAdminSystem.Application.Authentication.Interfaces;
+
+public interface IJwtTokenService
+{
+ string GenerateToken(string userId, string roleId, UserStatus status);
+ (string userId, string roleId, UserStatus status) ParseToken(string token);
+ string RefreshToken(string oldToken, out string userId, out string roleId, out UserStatus status);
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/Authentication/Interfaces/ILoginAppService.cs b/backend/src/UniversalAdminSystem.Application/Authentication/Interfaces/ILoginAppService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..80adb82212c043cd90b77b03ed8d1665b45f3fed
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/Authentication/Interfaces/ILoginAppService.cs
@@ -0,0 +1,8 @@
+using UniversalAdminSystem.Application.Authentication.DTOs;
+
+namespace UniversalAdminSystem.Application.Authentication.Interfaces;
+
+public interface ILoginAppService
+{
+ Task LoginAsync(LoginDto dto);
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/Authentication/Interfaces/IRegisterAppService.cs b/backend/src/UniversalAdminSystem.Application/Authentication/Interfaces/IRegisterAppService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..7070f3a78f5afdf627cc73bb709e67fc13761a4c
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/Authentication/Interfaces/IRegisterAppService.cs
@@ -0,0 +1,8 @@
+using UniversalAdminSystem.Application.Authentication.DTOs;
+
+namespace UniversalAdminSystem.Application.Authentication.Interfaces;
+
+public interface IRegisterAppService
+{
+ Task RegisterAsync(RegisterDto dto);
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/Authentication/Service/LoginAppService.cs b/backend/src/UniversalAdminSystem.Application/Authentication/Service/LoginAppService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..70edb566165c26011b07e3da000a9b9f2455816f
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/Authentication/Service/LoginAppService.cs
@@ -0,0 +1,40 @@
+using UniversalAdminSystem.Application.Authentication.DTOs;
+using UniversalAdminSystem.Application.Authentication.Interfaces;
+using UniversalAdminSystem.Domian.UserManagement.IRepository;
+using UniversalAdminSystem.Application.UserManagement.Interface;
+using UniversalAdminSystem.Domian.UserManagement.ValueObj;
+
+namespace UniversalAdminSystem.Application.Authentication.Service;
+
+public class LoginAppService : ILoginAppService
+{
+ private readonly IUserRepository _userRepository;
+ private readonly IJwtTokenService _jwtService;
+ private readonly IPasswordHelper _passwordHelper;
+ private readonly IUserInfoRepository _userInfoRepository;
+
+ public LoginAppService(
+ IUserRepository userRepository,
+ IJwtTokenService jwtService,
+ IPasswordHelper passwordHelper,
+ IUserInfoRepository userInfoRepository)
+ {
+ _userRepository = userRepository;
+ _jwtService = jwtService;
+ _passwordHelper = passwordHelper;
+ _userInfoRepository = userInfoRepository;
+ }
+
+ public async Task LoginAsync(LoginDto dto)
+ {
+
+ var user = await _userRepository.GetUserByAccountAsync(dto.Account) ?? throw new Exception("账号不存在");
+ var userinfo = await _userInfoRepository.GetByGuidAsync(user.UserInfoId ?? throw new Exception("用户信息未绑定")) ?? throw new Exception("用户信息不存在");
+ // 使用密码验证服务进行安全比对
+ if (!_passwordHelper.VerifyPasswordWithSeparateSalt(dto.Password, user.Password, user.Salt)) throw new Exception("密码错误");
+ // 生成JWT令牌
+ var token = _jwtService.GenerateToken(user.UserId.Value.ToString(), user.RoleId?.Value.ToString() ?? "", user.Status);
+ // 返回登录结果
+ return new LoginResultDto(token, user.UserId.Value.ToString(), user.RoleId?.Value.ToString() ?? "", user.Account.Value.ToString(),userinfo);
+ }
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/Authentication/Service/RegisterAppService.cs b/backend/src/UniversalAdminSystem.Application/Authentication/Service/RegisterAppService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5577a52231a07311a7b1494891d20dddb6d5e664
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/Authentication/Service/RegisterAppService.cs
@@ -0,0 +1,91 @@
+using UniversalAdminSystem.Application.Authentication.DTOs;
+using UniversalAdminSystem.Application.Authentication.Interfaces;
+using UniversalAdminSystem.Domian.UserManagement.Aggregates;
+using UniversalAdminSystem.Domian.UserManagement.IRepository;
+using UniversalAdminSystem.Domian.UserManagement.ValueObj;
+using UniversalAdminSystem.Application.UserManagement.Interface;
+using UniversalAdminSystem.Domian.UserManagement.Entities;
+using UniversalAdminSystem.Application.Common.Interfaces;
+using UniversalAdminSystem.Domian.PermissionManagement.IRepository;
+
+namespace UniversalAdminSystem.Application.Authentication.Service;
+
+public class RegisterAppService : IRegisterAppService
+{
+ private readonly IUserRepository _userRepository;
+ private readonly IPasswordHelper _passwordHelper;
+ private readonly IUnitOfWork _unitOfWork;
+
+ private readonly IRoleRepository _RoleRepo;
+
+ public RegisterAppService(
+ IUserRepository userRepository,
+ IPasswordHelper passwordHelper,
+ IUnitOfWork unitOfWork,
+ IRoleRepository roleRepository)
+ {
+ _userRepository = userRepository;
+ _passwordHelper = passwordHelper;
+ _unitOfWork = unitOfWork;
+ _RoleRepo = roleRepository;
+ }
+
+ public async Task RegisterAsync(RegisterDto dto)
+ {
+ try
+ {
+ // 开始事务
+ await _unitOfWork.BeginTransactionAsync();
+
+ // 检查账号是否已存在
+ var existingUser = await _userRepository.GetUserByAccountAsync(dto.Account);
+ if (existingUser != null)
+ {
+ throw new Exception("账号已存在");
+ }
+
+ // 检查邮箱是否已存在
+ var existingUserByEmail = await _userRepository.GetUserByEmailAsync(dto.Email);
+ if (existingUserByEmail != null)
+ {
+ throw new Exception("邮箱已被注册");
+ }
+
+ // 密码加密
+ var (hashedPassword, salt) = _passwordHelper.HashPasswordWithSeparateSalt(dto.Password);
+
+ // 创建用户信息
+ var userInfo = UserInfo.CreateUserInfo();
+ await _userRepository.AddUserInfoAsync(userInfo);
+ var Role = await _RoleRepo.GetByNameAsync("普通用户") ?? throw new Exception("用户创建失败");
+ // 创建用户
+ var user = User.CreateUser(
+ userInfo.UserInfoId,
+ dto.Account,
+ hashedPassword,
+ dto.Email,
+ salt,
+ UserStatus.Normal,
+ Role.RoleId.Value
+
+ );
+
+ await _userRepository.AddAsync(user);
+
+ // 提交事务
+ await _unitOfWork.CommitAsync();
+
+ return new RegisterResultDto(
+ user.UserId.Value.ToString(),
+ user.Account.Value.ToString(),
+ "注册成功"
+ );
+ }
+ catch (Exception)
+ {
+ // 回滚事务
+ await _unitOfWork.RollbackAsync();
+ throw;
+ }
+ }
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/Common/Exceptions/BusinessException.cs b/backend/src/UniversalAdminSystem.Application/Common/Exceptions/BusinessException.cs
new file mode 100644
index 0000000000000000000000000000000000000000..ef09cbe4c38b034895e71acddf6677b7ddce5ed3
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/Common/Exceptions/BusinessException.cs
@@ -0,0 +1,43 @@
+namespace UniversalAdminSystem.Application.Common.Exceptions;
+
+///
+/// 业务异常基类
+///
+public class BusinessException : Exception
+{
+ public string ErrorCode { get; }
+
+ public BusinessException(string message, string errorCode = "BUSINESS_ERROR") : base(message)
+ {
+ ErrorCode = errorCode;
+ }
+
+ public BusinessException(string message, Exception innerException, string errorCode = "BUSINESS_ERROR") : base(message, innerException)
+ {
+ ErrorCode = errorCode;
+ }
+}
+
+///
+/// 菜单相关业务异常
+///
+public class MenuBusinessException : BusinessException
+{
+ public MenuBusinessException(string message, string errorCode = "MENU_ERROR") : base(message, errorCode) { }
+}
+
+///
+/// 未找到异常
+///
+public class NotFoundException : BusinessException
+{
+ public NotFoundException(string message) : base(message, "NOT_FOUND") { }
+}
+
+///
+/// 验证异常
+///
+public class ValidationException : BusinessException
+{
+ public ValidationException(string message) : base(message, "VALIDATION_ERROR") { }
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/Common/Results/Result.cs b/backend/src/UniversalAdminSystem.Application/Common/Results/Result.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b7251037e074bc227da196a8ba4158f990f853d9
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/Common/Results/Result.cs
@@ -0,0 +1,54 @@
+namespace UniversalAdminSystem.Application.Common.Results;
+
+///
+/// 统一响应结果基类
+///
+public class Result
+{
+ public bool IsSuccess { get; }
+ public string Message { get; }
+ public string[] Errors { get; }
+
+ protected Result(bool isSuccess, string message, string[]? errors = null)
+ {
+ IsSuccess = isSuccess;
+ Message = message;
+ Errors = errors ?? Array.Empty();
+ }
+
+ public static Result Success(string message = "操作成功")
+ {
+ return new Result(true, message);
+ }
+
+ public static Result Failure(string message, string[]? errors = null)
+ {
+ return new Result(false, message, errors);
+ }
+}
+
+///
+/// 带数据的响应结果
+///
+public class Result : Result
+{
+ public T? Data { get; }
+
+ protected Result(bool isSuccess, string message, T? data, string[]? errors = null)
+ : base(isSuccess, message, errors)
+ {
+ Data = data;
+ }
+
+ public static Result Success(T data, string message = "操作成功")
+ {
+ return new Result(true, message, data);
+ }
+
+ public static new Result Failure(string message, string[]? errors = null)
+ {
+ return new Result(false, message, default, errors);
+ }
+
+ public static implicit operator Result(T data) => Success(data);
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/Common/interfaces/IEventBus.cs b/backend/src/UniversalAdminSystem.Application/Common/interfaces/IEventBus.cs
new file mode 100644
index 0000000000000000000000000000000000000000..c8646a98b3260d796d23194de0671e8df1b3aaa7
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/Common/interfaces/IEventBus.cs
@@ -0,0 +1,6 @@
+namespace UniversalAdminSystem.Application.Common.Interfaces;
+
+public interface IEventBus
+{
+ Task PublishAsync(string exchange, string routingKey, string payload, string? messageId = null, CancellationToken ct = default);
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/Common/interfaces/IUnitOfWork.cs b/backend/src/UniversalAdminSystem.Application/Common/interfaces/IUnitOfWork.cs
new file mode 100644
index 0000000000000000000000000000000000000000..c4f6fab73471c00a0d8c3a4d98067992f6014e93
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/Common/interfaces/IUnitOfWork.cs
@@ -0,0 +1,9 @@
+namespace UniversalAdminSystem.Application.Common.Interfaces;
+
+public interface IUnitOfWork
+{
+ Task BeginTransactionAsync();
+ Task CommitAsync();
+ Task RollbackAsync();
+ Task SaveChangesAsync(CancellationToken cancellationToken = default);
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/FileStorage/DTOs/FileDto.cs b/backend/src/UniversalAdminSystem.Application/FileStorage/DTOs/FileDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d75714257f3df0e6eed479825c9cad0bf9f40829
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/FileStorage/DTOs/FileDto.cs
@@ -0,0 +1,38 @@
+namespace UniversalAdminSystem.Application.FileStorage.DTOs;
+
+public record FileDto(
+ Guid Id,
+ string Name,
+ string Path,
+ long Size,
+ string Type,
+ Guid OwnerId,
+ DateTime UploadTime,
+ bool IsFolder,
+ Guid? ParentId,
+ string AccessLevel
+);
+
+public record FileUploadDto(
+ string Name,
+ string Path,
+ long Size,
+ string Type,
+ Guid? ParentId = null
+);
+
+public record FileDownloadDto(
+ Guid Id,
+ string Name,
+ string Path,
+ string Type
+);
+
+public record FileUploadResultDto(
+ Guid? Id = null,
+ string? Name = null,
+ string? Path = null,
+ long? Size = null,
+ string? Type = null,
+ string? Message = null
+);
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/FileStorage/DTOs/FileProcessingJobDto.cs b/backend/src/UniversalAdminSystem.Application/FileStorage/DTOs/FileProcessingJobDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..17815855ccb7b65ef89e39329fa7412e8c8af38c
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/FileStorage/DTOs/FileProcessingJobDto.cs
@@ -0,0 +1,3 @@
+namespace UniversalAdminSystem.Application.FileStorage.DTOs;
+
+public record FileProcessingJobDto(Guid FileId, string FilePath, string ContentType, long Size);
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/FileStorage/Interfaces/IDocParser.cs b/backend/src/UniversalAdminSystem.Application/FileStorage/Interfaces/IDocParser.cs
new file mode 100644
index 0000000000000000000000000000000000000000..dc2f7ddd699bc3c116f93e3a7f11d5b22a94109f
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/FileStorage/Interfaces/IDocParser.cs
@@ -0,0 +1,7 @@
+namespace UniversalAdminSystem.Application.FileStorage.Interfaces;
+
+public interface IDocParser
+{
+ // bool CanParse();
+ Task ParseAsync(string path);
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/FileStorage/Interfaces/IFileAppService.cs b/backend/src/UniversalAdminSystem.Application/FileStorage/Interfaces/IFileAppService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..bb7ec7a70955bea8995410ad2f799c569ceb6ae2
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/FileStorage/Interfaces/IFileAppService.cs
@@ -0,0 +1,24 @@
+using UniversalAdminSystem.Domian.FileStorage.ValueObjects;
+using UniversalAdminSystem.Domian.UserManagement.ValueObj;
+using UniversalAdminSystem.Application.FileStorage.DTOs;
+using UniversalAdminSystem.Domian.Core.ValueObjects;
+using UniversalAdminSystem.Application.Common.Results;
+using Microsoft.AspNetCore.Http;
+
+namespace UniversalAdminSystem.Application.FileStorage.Interfaces;
+
+public interface IFileAppService
+{
+ Task UploadAsync(IFormFile file);
+
+ Task> GetList();
+ // Task> DownloadAsync(FileId fileId);
+ // Task>> ListAsync(FileId? parentId);
+ // Task> CreateFolderAsync(string name, FileId? parentId);
+ // Task DeleteAsync(FileId fileId);
+ // Task> GetFileByIdAsync(FileId fileId);
+
+ Task GetFileById(Guid id);
+
+ Task RemoveFile(Guid id);
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/FileStorage/Interfaces/IFileProcessingQueue.cs b/backend/src/UniversalAdminSystem.Application/FileStorage/Interfaces/IFileProcessingQueue.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1c0b5a6f1fe3fb92b23e5378c6f370e9c32ed8e8
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/FileStorage/Interfaces/IFileProcessingQueue.cs
@@ -0,0 +1,8 @@
+using UniversalAdminSystem.Application.FileStorage.DTOs;
+
+namespace UniversalAdminSystem.Application.FileStorage.Interfaces;
+
+public interface IFileProcessingQueue
+{
+ Task EnqueueAsync(FileProcessingJobDto jd, CancellationToken ct = default);
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/FileStorage/Interfaces/IFileStorageService.cs b/backend/src/UniversalAdminSystem.Application/FileStorage/Interfaces/IFileStorageService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5aa8613bae0e314d29badd670531574331820b4d
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/FileStorage/Interfaces/IFileStorageService.cs
@@ -0,0 +1,12 @@
+using Microsoft.AspNetCore.Http;
+using UniversalAdminSystem.Application.FileStorage.DTOs;
+
+namespace UniversalAdminSystem.Application.FileStorage.Interfaces;
+
+public interface IFileStorageService
+{
+ Task SaveAsync(IFormFile file);
+ Task DownloadAsync(string fileName);
+ Task DeleteAsync(string fileName);
+ Task> ListFilesAsync();
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/FileStorage/Interfaces/IFileValidationService.cs b/backend/src/UniversalAdminSystem.Application/FileStorage/Interfaces/IFileValidationService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a871dba3bedfbf64f8f9f0f9365c6e4cd75a4dae
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/FileStorage/Interfaces/IFileValidationService.cs
@@ -0,0 +1,6 @@
+namespace UniversalAdminSystem.Application.FileStorage.Interfaces;
+
+public interface IFileValidationService
+{
+ (bool isValid, string message, string? format) ValidateFile(string fileName, long fileSize, Stream stream);
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/FileStorage/Services/FileAppService.cs b/backend/src/UniversalAdminSystem.Application/FileStorage/Services/FileAppService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..84d144aad614dd0d18a1c2169b4d14ff4c476583
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/FileStorage/Services/FileAppService.cs
@@ -0,0 +1,122 @@
+using Microsoft.AspNetCore.Http;
+using UniversalAdminSystem.Application.Common.Interfaces;
+using UniversalAdminSystem.Application.FileStorage.DTOs;
+using UniversalAdminSystem.Application.FileStorage.Interfaces;
+using UniversalAdminSystem.Domian.Core.ValueObjects;
+using UniversalAdminSystem.Domian.FileStorage.IRepository;
+using UniversalAdminSystem.Domian.FileStorage.ValueObjects;
+using File = UniversalAdminSystem.Domian.FileStorage.Aggregates.File;
+
+namespace UniversalAdminSystem.Application.FileStorage.Services;
+
+public class FileAppService : IFileAppService
+{
+ private readonly IFileRepository _fileRepository;
+ private readonly IFileValidationService _fileValidator;
+ private readonly IFileStorageService _localfileStorage;
+ private readonly IUnitOfWork _unitOfWork;
+ private readonly IFileProcessingQueue _fileProcessingQueue;
+
+
+ public FileAppService(IFileRepository fileRepository, IFileValidationService fileValidator, IFileStorageService localfileStorage, IUnitOfWork unitOfWork, IFileProcessingQueue fileProcessingQueue)
+ {
+ _fileRepository = fileRepository;
+ _fileValidator = fileValidator;
+ _localfileStorage = localfileStorage;
+ _unitOfWork = unitOfWork;
+ _fileProcessingQueue = fileProcessingQueue;
+ }
+
+ public async Task UploadAsync(IFormFile file)
+ {
+ try
+ {
+ using var fileStream = file.OpenReadStream();
+ var (isValid, message, format) = _fileValidator.ValidateFile(file.FileName, file.Length, fileStream);
+ if (!isValid) throw new Exception($"校验结果: {message}");
+ var fileInfo = await _localfileStorage.SaveAsync(file);
+ Console.WriteLine("开启事务------------------");
+ await _unitOfWork.BeginTransactionAsync();
+ var fileEntity = File.Create
+ (
+ FileName.Create(fileInfo.Name),
+ FilePath.Create(fileInfo.FullName),
+ FileSize.Create(file.Length),
+ FileType.Create(file.ContentType),
+ (UserId)Guid.NewGuid(),
+ false,
+ null
+ );
+ Console.WriteLine($"文件信息打印---------------");
+ Console.WriteLine($"文件名:{fileEntity.Name}");
+ Console.WriteLine($"文件url:{fileEntity.Path}");
+ Console.WriteLine($"文件大小:{fileEntity.Size}");
+ Console.WriteLine($"文件类型:{fileEntity.Type}");
+ Console.WriteLine("---------------------------");
+ await _fileRepository.AddAsync(fileEntity);
+ Console.WriteLine("添加数据成功!");
+
+ // 文件处理任务入队
+ await _fileProcessingQueue.EnqueueAsync(new FileProcessingJobDto(
+ fileEntity.Id.Value,
+ fileInfo.FullName,
+ file.ContentType,
+ file.Length), CancellationToken.None);
+ Console.WriteLine("文件处理任务入队成功!提交事务!");
+ await _unitOfWork.CommitAsync();
+ Console.WriteLine("提交事务成功!");
+
+ return new FileUploadResultDto
+ (
+ fileEntity.Id.Value,
+ fileInfo.Name,
+ fileInfo.FullName,
+ file.Length,
+ file.ContentType,
+ message
+ );
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("添加数据到数据库失败!回滚事务!");
+ await _unitOfWork.RollbackAsync();
+ return new FileUploadResultDto(Message: ex.Message);
+ }
+ }
+
+ public async Task> GetList()
+ {
+ var files = await _fileRepository.GetAllAsync();
+ return files.Select(file => new FileUploadResultDto(
+ file.Id,
+ file.Name,
+ file.Path,
+ file.Size,
+ file.Type
+ ));
+ }
+
+ public async Task GetFileById(Guid id)
+ {
+ var file = await _fileRepository.GetByGuidAsync(id);
+ if (file == null)
+ {
+ throw new FileNotFoundException();
+ }
+ return new FileDownloadDto(file.Id, file.Name, file.Path, file.Type);
+ }
+
+ public async Task RemoveFile(Guid id)
+ {
+ try
+ {
+ await _fileRepository.RemoveAsync(id);
+ }
+ catch (System.Exception)
+ {
+
+ throw new Exception("删除异常");
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/LogManagement/DTOs/LogEntryDto.cs b/backend/src/UniversalAdminSystem.Application/LogManagement/DTOs/LogEntryDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..0883fcde3347213813b5e6c6d46d46ccb63f5b5f
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/LogManagement/DTOs/LogEntryDto.cs
@@ -0,0 +1,21 @@
+namespace UniversalAdminSystem.Application.LogManagement.DTOs;
+
+public record LogEntryDto(
+ Guid Id,
+ string Level,
+ string Message,
+ string Source,
+ Guid? UserId,
+ DateTime Timestamp,
+ string? Context,
+ string? Exception
+);
+
+public record LogCreateDto(
+ string Level,
+ string Message,
+ string Source,
+ Guid? UserId = null,
+ string? Context = null,
+ string? Exception = null
+);
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/LogManagement/Interfaces/ILogManagementAppService.cs b/backend/src/UniversalAdminSystem.Application/LogManagement/Interfaces/ILogManagementAppService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..61b7d96c6977504a2c1e3c8d119f2ba467439e37
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/LogManagement/Interfaces/ILogManagementAppService.cs
@@ -0,0 +1,52 @@
+using UniversalAdminSystem.Application.LogManagement.DTOs;
+using UniversalAdminSystem.Application.Common.Results;
+
+namespace UniversalAdminSystem.Application.LogManagement.Interfaces;
+
+public interface ILogManagementAppService
+{
+ ///
+ /// 获取所有日志
+ ///
+ Task>> GetAllLogsAsync();
+
+ ///
+ /// 根据ID获取日志
+ ///
+ Task> GetLogByIdAsync(Guid id);
+
+ ///
+ /// 创建日志
+ ///
+ Task> CreateLogAsync(LogCreateDto createDto);
+
+ ///
+ /// 根据级别获取日志
+ ///
+ Task>> GetLogsByLevelAsync(string level);
+
+ ///
+ /// 根据用户获取日志
+ ///
+ Task>> GetLogsByUserAsync(Guid userId);
+
+ ///
+ /// 根据日期范围获取日志
+ ///
+ Task>> GetLogsByDateRangeAsync(DateTime start, DateTime end);
+
+ ///
+ /// 根据来源获取日志
+ ///
+ Task>> GetLogsBySourceAsync(string source);
+
+ ///
+ /// 删除日志
+ ///
+ Task DeleteLogAsync(Guid id);
+
+ ///
+ /// 清空所有日志
+ ///
+ Task ClearLogsAsync();
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/LogManagement/Services/LogManagementAppService.cs b/backend/src/UniversalAdminSystem.Application/LogManagement/Services/LogManagementAppService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..0b812233c4a7aa3ef598f3e8360d97251cc612a8
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/LogManagement/Services/LogManagementAppService.cs
@@ -0,0 +1,182 @@
+using UniversalAdminSystem.Application.LogManagement.DTOs;
+using UniversalAdminSystem.Application.LogManagement.Interfaces;
+using UniversalAdminSystem.Domian.LogManagement.Aggregates;
+using UniversalAdminSystem.Domian.Core.Interfaces;
+using UniversalAdminSystem.Application.Common.Results;
+using UniversalAdminSystem.Domian.Core.ValueObjects;
+using UniversalAdminSystem.Application.Common.Interfaces;
+
+namespace UniversalAdminSystem.Application.LogManagement.Services;
+
+public class LogManagementAppService : ILogManagementAppService
+{
+ private readonly IRepository _logRepository;
+ private readonly IUnitOfWork _unitOfWork;
+
+ public LogManagementAppService(
+ IRepository logRepository,
+ IUnitOfWork unitOfWork)
+ {
+ _logRepository = logRepository;
+ _unitOfWork = unitOfWork;
+ }
+
+ public async Task>> GetAllLogsAsync()
+ {
+ try
+ {
+ var logs = await _logRepository.GetAllAsync();
+ var logDtos = logs.Select(MapToDto);
+ return Result>.Success(logDtos);
+ }
+ catch (Exception ex)
+ {
+ return Result>.Failure($"获取日志列表失败: {ex.Message}");
+ }
+ }
+
+ public async Task> GetLogByIdAsync(Guid id)
+ {
+ try
+ {
+ var log = await _logRepository.GetByGuidAsync(id);
+ if (log == null)
+ {
+ return Result.Success(null);
+ }
+
+ return Result.Success(MapToDto(log));
+ }
+ catch (Exception ex)
+ {
+ return Result.Failure($"获取日志详情失败: {ex.Message}");
+ }
+ }
+
+ public async Task> CreateLogAsync(LogCreateDto createDto)
+ {
+ try
+ {
+ var log = LogEntry.Create(
+ createDto.Level,
+ createDto.Message,
+ createDto.Source,
+ createDto.UserId.HasValue ? (UserId)createDto.UserId.Value : null,
+ createDto.Context,
+ createDto.Exception
+ );
+
+ await _logRepository.AddAsync(log);
+ await _unitOfWork.SaveChangesAsync();
+ return Result.Success(MapToDto(log));
+ }
+ catch (Exception ex)
+ {
+ return Result.Failure($"创建日志失败: {ex.Message}");
+ }
+ }
+
+ public async Task>> GetLogsByLevelAsync(string level)
+ {
+ try
+ {
+ var logs = await _logRepository.GetAllAsync();
+ var filteredLogs = logs.Where(l => l.Level == level).Select(MapToDto);
+ return Result>.Success(filteredLogs);
+ }
+ catch (Exception ex)
+ {
+ return Result>.Failure($"获取日志失败: {ex.Message}");
+ }
+ }
+
+ public async Task>> GetLogsByUserAsync(Guid userId)
+ {
+ try
+ {
+ var logs = await _logRepository.GetAllAsync();
+ var userLogs = logs.Where(l => l.UserId != null && l.UserId.Value == userId);
+
+ var logDtos = userLogs.Select(MapToDto);
+ return Result>.Success(logDtos);
+ }
+ catch (Exception ex)
+ {
+ return Result>.Failure($"获取用户日志失败: {ex.Message}");
+ }
+ }
+
+ public async Task>> GetLogsByDateRangeAsync(DateTime start, DateTime end)
+ {
+ try
+ {
+ var logs = await _logRepository.GetAllAsync();
+ var dateRangeLogs = logs.Where(l => l.Timestamp >= start && l.Timestamp <= end);
+
+ var logDtos = dateRangeLogs.Select(MapToDto);
+ return Result>.Success(logDtos);
+ }
+ catch (Exception ex)
+ {
+ return Result>.Failure($"获取日志失败: {ex.Message}");
+ }
+ }
+
+ public async Task>> GetLogsBySourceAsync(string source)
+ {
+ try
+ {
+ var logs = await _logRepository.GetAllAsync();
+ var sourceLogs = logs.Where(l => l.Source == source);
+
+ var logDtos = sourceLogs.Select(MapToDto);
+ return Result>.Success(logDtos);
+ }
+ catch (Exception ex)
+ {
+ return Result>.Failure($"获取日志失败: {ex.Message}");
+ }
+ }
+
+ public async Task DeleteLogAsync(Guid id)
+ {
+ try
+ {
+ var log = await _logRepository.GetByGuidAsync(id);
+ if (log == null)
+ {
+ return Result.Failure("日志不存在");
+ }
+
+ await _logRepository.RemoveAsync(id);
+ await _unitOfWork.SaveChangesAsync();
+ return Result.Success("日志删除成功");
+ }
+ catch (Exception ex)
+ {
+ return Result.Failure($"删除日志失败: {ex.Message}");
+ }
+ }
+
+ public async Task ClearLogsAsync()
+ {
+ try
+ {
+ var logs = await _logRepository.GetAllAsync();
+ foreach (var log in logs)
+ {
+ await _logRepository.RemoveAsync(log.Id);
+ }
+ await _unitOfWork.SaveChangesAsync();
+ return Result.Success("日志清空成功");
+ }
+ catch (Exception ex)
+ {
+ return Result.Failure($"清空日志失败: {ex.Message}");
+ }
+ }
+
+ private static LogEntryDto MapToDto(LogEntry l) => new(
+ l.Id, l.Level, l.Message, l.Source, l.UserId?.Value, l.Timestamp, l.Context, l.Exception
+ );
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/PermissionManagement/DTOs/AssignPermissionDto.cs b/backend/src/UniversalAdminSystem.Application/PermissionManagement/DTOs/AssignPermissionDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a87563835e77fe7bc57706bb6dfaccaa6a9d12b0
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/PermissionManagement/DTOs/AssignPermissionDto.cs
@@ -0,0 +1,11 @@
+namespace UniversalAdminSystem.Application.PermissionManagement.DTOs;
+
+///
+/// 权限分配数据传输对象
+///
+/// 权限编码
+/// 角色ID
+public record AssignPermissionDto(
+ string PermissionCode,
+ Guid RoleId
+);
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/PermissionManagement/DTOs/PermissionCreateDto.cs b/backend/src/UniversalAdminSystem.Application/PermissionManagement/DTOs/PermissionCreateDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..79124bac8dffbc3551c12f2941c5e3c95a70b74e
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/PermissionManagement/DTOs/PermissionCreateDto.cs
@@ -0,0 +1,15 @@
+namespace UniversalAdminSystem.Application.PermissionManagement.DTOs;
+
+///
+/// 权限创建数据传输对象
+///
+/// 权限名称
+/// 权限作用资源
+/// 权限操作类型值
+/// 权限描述
+public record PermissionCreateDto(
+ string Name,
+ string Resource,
+ int ActionValue,
+ string? Description = null
+);
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/PermissionManagement/DTOs/PermissionDto.cs b/backend/src/UniversalAdminSystem.Application/PermissionManagement/DTOs/PermissionDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..3c8cf10ab48d7355557ffbe921efe4a8887beb96
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/PermissionManagement/DTOs/PermissionDto.cs
@@ -0,0 +1,13 @@
+namespace UniversalAdminSystem.Application.PermissionManagement.DTOs;
+
+///
+/// 权限数据传输对象
+///
+/// 权限名称
+/// 权限编码
+/// 权限描述
+public record PermissionDto(
+ string Name,
+ string Code,
+ string Description
+);
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/PermissionManagement/DTOs/RoleDto.cs b/backend/src/UniversalAdminSystem.Application/PermissionManagement/DTOs/RoleDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a72356d6c5a214810477e519bbb41a8dd1abd819
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/PermissionManagement/DTOs/RoleDto.cs
@@ -0,0 +1,46 @@
+namespace UniversalAdminSystem.Application.PermissionManagement.DTOs;
+
+///
+/// 角色数据传输对象
+///
+/// 角色ID
+/// 角色名称
+/// 角色描述
+/// 是否为系统角色
+/// 是否为超级管理员
+/// 创建时间
+/// 更新时间
+/// 权限数量
+public record RoleDto(
+ Guid RoleId,
+ string Name,
+ string? Description,
+ bool IsSystem,
+ bool IsSupper,
+ DateTime CreateTime,
+ DateTime UpdateTime,
+ int PermissionCount = 0
+);
+
+///
+/// 角色创建数据传输对象
+///
+/// 角色名称
+/// 角色描述
+/// 是否为系统角色
+/// 是否为超级管理员
+public record RoleCreateDto(
+ string Name,
+ string? Description = null,
+ bool IsSupper = false
+);
+
+///
+/// 角色更新数据传输对象
+///
+/// 角色名称
+/// 角色描述
+public record RoleUpdateDto(
+ string Name,
+ string? Description = null
+);
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/PermissionManagement/Interfaces/IPermissionCheckService.cs b/backend/src/UniversalAdminSystem.Application/PermissionManagement/Interfaces/IPermissionCheckService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f355206c53746e1b688b828b748afcbabca8a972
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/PermissionManagement/Interfaces/IPermissionCheckService.cs
@@ -0,0 +1,46 @@
+namespace UniversalAdminSystem.Application.PermissionManagement.Interfaces;
+
+///
+/// 权限检查服务接口
+/// 提供用户权限验证功能
+///
+public interface IPermissionCheckService
+{
+ ///
+ /// 检查用户是否有指定权限
+ ///
+ /// 用户ID
+ /// 权限编码
+ /// 是否有权限
+ Task CheckUserPermissionAsync(Guid userId, string permissionCode);
+
+ ///
+ /// 检查用户是否有任意一个指定权限
+ ///
+ /// 用户ID
+ /// 权限编码列表
+ /// 是否有权限
+ Task CheckUserAnyPermissionAsync(Guid userId, IEnumerable permissionCodes);
+
+ ///
+ /// 检查用户是否有所有指定权限
+ ///
+ /// 用户ID
+ /// 权限编码列表
+ /// 是否有权限
+ Task CheckUserAllPermissionsAsync(Guid userId, IEnumerable permissionCodes);
+
+ ///
+ /// 获取用户的所有权限
+ ///
+ /// 用户ID
+ /// 权限编码列表
+ Task> GetUserPermissionsAsync(Guid userId);
+
+ ///
+ /// 获取用户的所有角色
+ ///
+ /// 用户ID
+ /// 角色名称列表
+ Task> GetUserRoleAsync(Guid userId);
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/PermissionManagement/Interfaces/IPermissionManagementAppService.cs b/backend/src/UniversalAdminSystem.Application/PermissionManagement/Interfaces/IPermissionManagementAppService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..9d3caa5d7c746771ffb9a91ac550da23a332ddab
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/PermissionManagement/Interfaces/IPermissionManagementAppService.cs
@@ -0,0 +1,37 @@
+using UniversalAdminSystem.Application.PermissionManagement.DTOs;
+
+namespace UniversalAdminSystem.Application.PermissionManagement.Interfaces;
+
+///
+/// 权限管理应用服务接口
+/// 提供权限的创建、查询、分配等业务操作
+///
+public interface IPermissionManagementAppService
+{
+ ///
+ /// 获取所有权限列表
+ ///
+ /// 权限列表
+ Task> GetAllPermissionAsync();
+
+ ///
+ /// 创建新权限
+ ///
+ /// 权限创建数据传输对象
+ /// 创建的权限信息
+ Task CreatePermissionAsync(PermissionCreateDto createDto);
+
+ ///
+ /// 删除权限
+ ///
+ /// 权限ID
+ /// 删除操作结果
+ Task RemovePermissionAsync(Guid permissionId);
+
+ ///
+ /// 为角色分配权限
+ ///
+ /// 权限分配数据传输对象
+ /// 分配操作结果
+ Task AssignPermissionToRoleAsync(AssignPermissionDto assignDto);
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/PermissionManagement/Interfaces/IRoleManagementAppService.cs b/backend/src/UniversalAdminSystem.Application/PermissionManagement/Interfaces/IRoleManagementAppService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..6667c1ea8941566d2a1da90921a46867459eafc7
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/PermissionManagement/Interfaces/IRoleManagementAppService.cs
@@ -0,0 +1,68 @@
+using UniversalAdminSystem.Application.PermissionManagement.DTOs;
+
+namespace UniversalAdminSystem.Application.PermissionManagement.Interfaces;
+
+///
+/// 角色管理应用服务接口
+/// 提供角色的创建、查询、更新、删除等业务操作
+///
+public interface IRoleManagementAppService
+{
+ ///
+ /// 获取所有角色列表
+ ///
+ /// 角色列表
+ Task> GetAllRolesAsync();
+
+ ///
+ /// 根据ID获取角色
+ ///
+ /// 角色ID
+ /// 角色信息
+ Task GetRoleByIdAsync(Guid roleId);
+
+ ///
+ /// 创建新角色
+ ///
+ /// 角色创建数据传输对象
+ /// 创建的角色信息
+ Task CreateRoleAsync(RoleCreateDto createDto);
+
+ ///
+ /// 更新角色信息
+ ///
+ /// 角色ID
+ /// 角色更新数据传输对象
+ /// 更新后的角色信息
+ Task UpdateRoleAsync(Guid roleId, RoleUpdateDto updateDto);
+
+ ///
+ /// 删除角色
+ ///
+ /// 角色ID
+ /// 删除操作结果
+ Task DeleteRoleAsync(Guid roleId);
+
+ ///
+ /// 为角色分配权限
+ ///
+ /// 角色ID
+ /// 权限ID列表
+ /// 分配操作结果
+ Task AssignPermissionsToRoleAsync(Guid roleId, IEnumerable permissionIds);
+
+ ///
+ /// 移除角色的权限
+ ///
+ /// 角色ID
+ /// 权限ID列表
+ /// 移除操作结果
+ Task RemovePermissionsFromRoleAsync(Guid roleId, IEnumerable permissionIds);
+
+ ///
+ /// 获取角色的所有权限
+ ///
+ /// 角色ID
+ /// 权限列表
+ Task> GetRolePermissionsAsync(Guid roleId);
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/PermissionManagement/Services/PermissionCheckService.cs b/backend/src/UniversalAdminSystem.Application/PermissionManagement/Services/PermissionCheckService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..022244fe3c712f5d0595abb0f8f9115284471078
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/PermissionManagement/Services/PermissionCheckService.cs
@@ -0,0 +1,349 @@
+using UniversalAdminSystem.Application.PermissionManagement.Interfaces;
+using UniversalAdminSystem.Domian.PermissionManagement.IRepository;
+using UniversalAdminSystem.Domian.UserManagement.IRepository;
+using UniversalAdminSystem.Domian.PermissionManagement.ValueObjects;
+
+namespace UniversalAdminSystem.Application.PermissionManagement.Services;
+
+///
+/// 权限检查服务实现
+/// 提供用户权限验证的具体逻辑
+///
+public class PermissionCheckService : IPermissionCheckService
+{
+ private readonly IUserRepository _userRepository;
+ private readonly IRoleRepository _roleRepository;
+ private readonly IPermissionRepository _permissionRepository;
+
+ public PermissionCheckService(
+ IUserRepository userRepository,
+ IRoleRepository roleRepository,
+ IPermissionRepository permissionRepository)
+ {
+ _userRepository = userRepository;
+ _roleRepository = roleRepository;
+ _permissionRepository = permissionRepository;
+ }
+
+ public async Task CheckUserPermissionAsync(Guid userId, string permissionCode)
+ {
+ try
+ {
+ var user = await _userRepository.GetByGuidAsync(userId);
+ if (user == null || user.RoleId == null) return false;
+ var role = await _roleRepository.GetByGuidAsync(user.RoleId.Value);
+ if (role == null) return false;
+ var permission = await _permissionRepository.GetByCodeAsync(PermissionCode.Create(permissionCode));
+ if (permission == null) return false;
+
+ Console.WriteLine($"检查权限: {permissionCode}");
+ Console.WriteLine($"角色权限数量: {role.Permissions.Count}");
+
+ // 打印角色拥有的所有权限
+ foreach (var perm in role.Permissions)
+ {
+ Console.WriteLine($"角色权限: {perm.Code} (类型: {perm.Code.GetType().Name})");
+ }
+
+ // 修复比较逻辑:使用值对象比较
+ var hasPermission = role.Permissions.Any(p => p.Code == PermissionCode.Create(permissionCode));
+ Console.WriteLine($"权限检查结果: {hasPermission}");
+
+ return hasPermission;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"权限检查错误: {ex.Message}");
+ return false;
+ }
+ }
+
+ ///
+ /// 检查用户是否有任意一个指定权限
+ ///
+ public async Task CheckUserAnyPermissionAsync(Guid userId, IEnumerable permissionCodes)
+ {
+ foreach (var permissionCode in permissionCodes)
+ {
+ if (await CheckUserPermissionAsync(userId, permissionCode)) return true;
+ }
+ return false;
+ }
+
+ ///
+ /// 检查用户是否有所有指定权限
+ ///
+ public async Task CheckUserAllPermissionsAsync(Guid userId, IEnumerable permissionCodes)
+ {
+ foreach (var permissionCode in permissionCodes)
+ {
+ if (!await CheckUserPermissionAsync(userId, permissionCode)) return false;
+ }
+ return true;
+ }
+
+ ///
+ /// 获取用户的所有权限编码
+ ///
+ public async Task> GetUserPermissionsAsync(Guid userId)
+ {
+ try
+ {
+ if (userId == Guid.Empty) throw new ArgumentException("用户ID为空", nameof(userId));
+ var user = await _userRepository.GetByGuidAsync(userId) ?? throw new InvalidOperationException("用户不存在");
+ if (user.RoleId == null) return Enumerable.Empty();
+ var role = await _roleRepository.GetByGuidAsync(user.RoleId.Value) ?? throw new InvalidDataException("用户角色不存在");
+ return role.Permissions.Select(p => p.Code.Value);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"获取用户权限错误: {ex.Message}");
+ return Enumerable.Empty();
+ }
+ }
+
+ ///
+ /// 获取用户的所有角色
+ ///
+ public async Task> GetUserRoleAsync(Guid userId)
+ {
+ try
+ {
+ var user = await _userRepository.GetByGuidAsync(userId);
+ if (user == null) return Enumerable.Empty();
+ if (user.RoleId == null) return Enumerable.Empty();
+ var role = await _roleRepository.GetByGuidAsync(user.RoleId.Value);
+ if (role == null) return Enumerable.Empty();
+ return new[] { role.Name.Value };
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"获取用户角色错误: {ex.Message}");
+ return Enumerable.Empty();
+ }
+ }
+
+ ///
+ /// 检查用户是否有菜单访问权限
+ ///
+ public async Task CheckMenuPermissionAsync(Guid userId, string? menuPermissionCode)
+ {
+ // 如果菜单没有设置权限要求,则所有用户都可以访问
+ if (string.IsNullOrEmpty(menuPermissionCode))
+ {
+ return true;
+ }
+
+ return await CheckUserPermissionAsync(userId, menuPermissionCode);
+ }
+
+ ///
+ /// 检查用户是否有文件访问权限
+ ///
+ public async Task CheckFilePermissionAsync(Guid userId, string fileAccessLevel, Guid? fileOwnerId = null)
+ {
+ try
+ {
+ // 超级管理员可以访问所有文件
+ if (await IsSuperAdminAsync(userId))
+ {
+ return true;
+ }
+
+ // 管理员可以访问除超级管理员文件外的所有文件
+ if (await IsAdminAsync(userId))
+ {
+ if (fileOwnerId.HasValue)
+ {
+ var fileOwner = await _userRepository.GetByGuidAsync(fileOwnerId.Value);
+ return fileOwner == null || !await IsSuperAdminAsync(fileOwnerId.Value);
+ }
+ return true;
+ }
+
+ // 普通用户只能访问自己的文件或公开文件
+ switch (fileAccessLevel.ToLower())
+ {
+ case "public":
+ return true;
+ case "private":
+ return fileOwnerId.HasValue && fileOwnerId.Value == userId;
+ case "restricted":
+ return false;
+ default:
+ return false;
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"文件权限检查错误: {ex.Message}");
+ return false;
+ }
+ }
+
+ ///
+ /// 检查用户是否有日志查看权限
+ ///
+ public async Task CheckLogPermissionAsync(Guid userId, string logLevel)
+ {
+ try
+ {
+ // 超级管理员可以查看所有日志
+ if (await IsSuperAdminAsync(userId))
+ {
+ return true;
+ }
+
+ // 管理员可以查看除系统级日志外的所有日志
+ if (await IsAdminAsync(userId))
+ {
+ return logLevel.ToLower() != "system";
+ }
+
+ // 普通用户只能查看基本日志
+ return logLevel.ToLower() == "basic" || logLevel.ToLower() == "info";
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"日志权限检查错误: {ex.Message}");
+ return false;
+ }
+ }
+
+ ///
+ /// 检查用户是否有系统设置管理权限
+ ///
+ public async Task CheckSystemSettingPermissionAsync(Guid userId, string settingKey)
+ {
+ try
+ {
+ // 超级管理员可以管理所有设置
+ if (await IsSuperAdminAsync(userId))
+ {
+ return true;
+ }
+
+ // 管理员可以管理除系统核心设置外的所有设置
+ if (await IsAdminAsync(userId))
+ {
+ var restrictedSettings = new[] { "system.core", "security", "database" };
+ return !restrictedSettings.Any(s => settingKey.StartsWith(s));
+ }
+
+ // 普通用户只能查看基本设置
+ var basicSettings = new[] { "ui", "theme", "language" };
+ return basicSettings.Any(s => settingKey.StartsWith(s));
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"系统设置权限检查错误: {ex.Message}");
+ return false;
+ }
+ }
+
+
+ ///
+ /// 检查用户是否为超级管理员
+ ///
+ public async Task IsSuperAdminAsync(Guid userId)
+ {
+ try
+ {
+ var permissions = await GetUserPermissionsAsync(userId);
+ return permissions.Any(p => p.Contains("super") || p.Contains("system"));
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"超级管理员检查错误: {ex.Message}");
+ return false;
+ }
+ }
+
+ ///
+ /// 检查用户是否为管理员
+ ///
+ public async Task IsAdminAsync(Guid userId)
+ {
+ try
+ {
+ var user = await _userRepository.GetByGuidAsync(userId);
+ if (user == null || user.RoleId == null) return false;
+ var role = await _roleRepository.GetByGuidAsync(user.RoleId.Value);
+ if (role == null) return false;
+ return role.IsSupper;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"管理员检查错误: {ex.Message}");
+ return false;
+ }
+ }
+
+ ///
+ /// 获取用户可访问的菜单权限列表
+ ///
+ public async Task> GetUserMenuPermissionsAsync(Guid userId)
+ {
+ try
+ {
+ var allPermissions = await GetUserPermissionsAsync(userId);
+ return allPermissions.Where(p => p.StartsWith("menu:"));
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"获取菜单权限错误: {ex.Message}");
+ return Enumerable.Empty();
+ }
+ }
+
+ ///
+ /// 获取用户可访问的文件权限列表
+ ///
+ public async Task> GetUserFilePermissionsAsync(Guid userId)
+ {
+ try
+ {
+ var allPermissions = await GetUserPermissionsAsync(userId);
+ return allPermissions.Where(p => p.StartsWith("file:"));
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"获取文件权限错误: {ex.Message}");
+ return Enumerable.Empty();
+ }
+ }
+
+ ///
+ /// 获取用户可访问的日志权限列表
+ ///
+ public async Task> GetUserLogPermissionsAsync(Guid userId)
+ {
+ try
+ {
+ var allPermissions = await GetUserPermissionsAsync(userId);
+ return allPermissions.Where(p => p.StartsWith("log:"));
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"获取日志权限错误: {ex.Message}");
+ return Enumerable.Empty();
+ }
+ }
+
+ ///
+ /// 获取用户可访问的系统设置权限列表
+ ///
+ public async Task> GetUserSystemSettingPermissionsAsync(Guid userId)
+ {
+ try
+ {
+ var allPermissions = await GetUserPermissionsAsync(userId);
+ return allPermissions.Where(p => p.StartsWith("setting:"));
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"获取系统设置权限错误: {ex.Message}");
+ return Enumerable.Empty();
+ }
+ }
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/PermissionManagement/Services/PermissionManagementAppService.cs b/backend/src/UniversalAdminSystem.Application/PermissionManagement/Services/PermissionManagementAppService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f6b7ee28573e34f8ebad4d7136d39fe4a8b82ff3
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/PermissionManagement/Services/PermissionManagementAppService.cs
@@ -0,0 +1,141 @@
+using UniversalAdminSystem.Application.Common.Interfaces;
+using UniversalAdminSystem.Application.PermissionManagement.DTOs;
+using UniversalAdminSystem.Application.PermissionManagement.Interfaces;
+using UniversalAdminSystem.Domian.PermissionManagement.Aggregate;
+using UniversalAdminSystem.Domian.PermissionManagement.Interfaces;
+using UniversalAdminSystem.Domian.PermissionManagement.IRepository;
+using UniversalAdminSystem.Domian.PermissionManagement.ValueObjects;
+
+namespace UniversalAdminSystem.Application.PermissionManagement.Services;
+
+///
+/// 权限管理应用服务实现
+/// 提供权限的创建、查询、分配等业务操作的具体实现
+///
+public class PermissionManagementAppService : IPermissionManagementAppService
+{
+ private readonly IUnitOfWork _unitOfWork;
+ private readonly IPermissionRepository _permissionRepository;
+ private readonly IRoleRepository _roleRepository;
+ private readonly IAssignPermissionDomainService _assignPermissionDomainService;
+
+ public PermissionManagementAppService(
+ IUnitOfWork unitOfWork,
+ IPermissionRepository permissionRepository,
+ IRoleRepository roleRepository,
+ IAssignPermissionDomainService assignPermissionDomainService
+ )
+ {
+ _unitOfWork = unitOfWork;
+ _permissionRepository = permissionRepository;
+ _roleRepository = roleRepository;
+ _assignPermissionDomainService = assignPermissionDomainService;
+ }
+
+ ///
+ /// 为角色分配权限
+ ///
+ public async Task AssignPermissionToRoleAsync(AssignPermissionDto assignDto)
+ {
+ try
+ {
+ await _unitOfWork.BeginTransactionAsync();
+ var permission = await _permissionRepository.GetByCodeAsync((PermissionCode)assignDto.PermissionCode)
+ ?? throw new KeyNotFoundException("未找到对应的权限");
+ var role = await _roleRepository.GetByGuidAsync(assignDto.RoleId)
+ ?? throw new KeyNotFoundException("未找到对应的角色");
+ var state = _assignPermissionDomainService.AssignPermission(permission, role);
+ if (state)
+ {
+ await _roleRepository.Update(role);
+
+ }
+ await _unitOfWork.CommitAsync();
+ }
+ catch (KeyNotFoundException)
+ {
+ await _unitOfWork.RollbackAsync();
+ throw;
+ }
+ }
+
+ ///
+ /// 创建新权限
+ ///
+ public async Task CreatePermissionAsync(PermissionCreateDto createDto)
+ {
+ try
+ {
+ if (!Enum.IsDefined(typeof(PermissionAction), createDto.ActionValue))
+ {
+ throw new InvalidOperationException($"无效的操作类型值: {createDto.ActionValue}");
+ }
+ PermissionAction enumValue = (PermissionAction)createDto.ActionValue;
+ // 检查权限代码是否已存在
+ var existingPermission = await _permissionRepository.GetByCodeAsync(PermissionCode.Create($"{createDto.Resource}:{enumValue}"));
+ if (existingPermission != null)
+ {
+ throw new InvalidOperationException($"权限代码 '{createDto.Resource}:{enumValue}' 已存在,无法创建重复权限");
+ }
+
+ // 开启事务
+ await _unitOfWork.BeginTransactionAsync();
+
+ // 创建权限并保存
+ var permission = Permission.CreateStandardPermission(
+ createDto.Name,
+ createDto.Resource,
+ createDto.ActionValue,
+ createDto.Description
+ );
+
+ try
+ {
+ var savedPermission = await _permissionRepository.AddAsync(permission);
+ await _unitOfWork.CommitAsync();
+ return new PermissionDto(
+ savedPermission.Name,
+ savedPermission.Code,
+ savedPermission.Description!
+ );
+ }
+ catch (System.Exception ex)
+ {
+ throw new InvalidOperationException(ex.Message);
+ }
+ }
+ catch (System.Exception ex)
+ {
+ await _unitOfWork.RollbackAsync();
+ throw new InvalidOperationException(ex.Message);
+ }
+ }
+
+ ///
+ /// 获取所有权限列表
+ ///
+ public async Task> GetAllPermissionAsync()
+ {
+ var permissions = await _permissionRepository.GetAllAsync();
+ var permissionList = permissions.Select(p => new PermissionDto(p.Name, p.Code, p.Description!));
+ return permissionList;
+ }
+
+ ///
+ /// 删除权限
+ ///
+ public async Task RemovePermissionAsync(Guid permissionId)
+ {
+ try
+ {
+ await _unitOfWork.BeginTransactionAsync();
+ await _permissionRepository.RemoveAsync(permissionId);
+ await _unitOfWork.CommitAsync();
+ }
+ catch (System.Exception ex)
+ {
+ await _unitOfWork.RollbackAsync();
+ throw new System.Exception(ex.Message);
+ }
+ }
+}
diff --git a/backend/src/UniversalAdminSystem.Application/PermissionManagement/Services/RoleManagementAppService.cs b/backend/src/UniversalAdminSystem.Application/PermissionManagement/Services/RoleManagementAppService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..2603384f7e9a1e9f70a2fa1a66cbc3fa7110161a
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/PermissionManagement/Services/RoleManagementAppService.cs
@@ -0,0 +1,301 @@
+using UniversalAdminSystem.Application.Common.Interfaces;
+using UniversalAdminSystem.Application.PermissionManagement.DTOs;
+using UniversalAdminSystem.Application.PermissionManagement.Interfaces;
+using UniversalAdminSystem.Domian.PermissionManagement.Aggregate;
+using UniversalAdminSystem.Domian.PermissionManagement.IRepository;
+using UniversalAdminSystem.Domian.PermissionManagement.ValueObjects;
+
+namespace UniversalAdminSystem.Application.PermissionManagement.Services;
+
+///
+/// 角色管理应用服务实现
+/// 提供角色的创建、查询、更新、删除等业务操作的具体实现
+///
+public class RoleManagementAppService : IRoleManagementAppService
+{
+ private readonly IUnitOfWork _unitOfWork;
+ private readonly IRoleRepository _roleRepository;
+ private readonly IPermissionRepository _permissionRepository;
+
+ public RoleManagementAppService(
+ IUnitOfWork unitOfWork,
+ IRoleRepository roleRepository,
+ IPermissionRepository permissionRepository)
+ {
+ _unitOfWork = unitOfWork;
+ _roleRepository = roleRepository;
+ _permissionRepository = permissionRepository;
+ }
+
+ ///
+ /// 获取所有角色列表
+ ///
+ public async Task> GetAllRolesAsync()
+ {
+ try
+ {
+ var roles = await _roleRepository.GetAllRolesWithPermissionsAsync();
+ return roles.Select(r => new RoleDto(
+ r.RoleId,
+ r.Name,
+ r.Description ?? string.Empty,
+ r.IsSystem,
+ r.IsSupper,
+ r.CreateTime,
+ r.UpdateTime,
+ r.PermissionCount
+ ));
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"获取角色列表失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据ID获取角色
+ ///
+ public async Task GetRoleByIdAsync(Guid roleId)
+ {
+ try
+ {
+ var role = await _roleRepository.GetRoleWithPermissionsAsync(roleId);
+ if (role == null) return null;
+
+ return new RoleDto(
+ role.RoleId,
+ role.Name,
+ role.Description ?? string.Empty,
+ role.IsSystem,
+ role.IsSupper,
+ role.CreateTime,
+ role.UpdateTime,
+ role.PermissionCount
+ );
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"获取角色失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 创建新角色
+ ///
+ public async Task CreateRoleAsync(RoleCreateDto createDto)
+ {
+ try
+ {
+ await _unitOfWork.BeginTransactionAsync();
+
+ // 检查角色名称是否已存在
+ if (await _roleRepository.ExistsAsync(createDto.Name))
+ {
+ throw new InvalidOperationException($"角色名称 '{createDto.Name}' 已存在");
+ }
+
+ // 创建角色
+ var role = Role.Create(
+ createDto.Name,
+ createDto.Description,
+ false,
+ createDto.IsSupper
+ );
+
+ var savedRole = await _roleRepository.AddAsync(role);
+ await _unitOfWork.CommitAsync();
+
+ return new RoleDto(
+ savedRole.RoleId,
+ savedRole.Name,
+ savedRole.Description,
+ savedRole.IsSystem,
+ savedRole.IsSupper,
+ savedRole.CreateTime,
+ savedRole.UpdateTime
+ );
+ }
+ catch (Exception ex)
+ {
+ await _unitOfWork.RollbackAsync();
+ throw new InvalidOperationException($"创建角色失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 更新角色信息
+ ///
+ public async Task UpdateRoleAsync(Guid roleId, RoleUpdateDto updateDto)
+ {
+ try
+ {
+ await _unitOfWork.BeginTransactionAsync();
+
+ var role = await _roleRepository.GetByGuidAsync(roleId);
+ if (role == null)
+ {
+ throw new KeyNotFoundException($"角色ID '{roleId}' 不存在");
+ }
+
+ // 检查是否为系统角色
+ if (role.IsSystem)
+ {
+ throw new InvalidOperationException("系统角色不允许修改");
+ }
+
+ // 检查角色名称是否已存在(排除当前角色)
+ var existingRole = await _roleRepository.GetByNameAsync(updateDto.Name);
+ if (existingRole != null && existingRole.RoleId != roleId)
+ {
+ throw new InvalidOperationException($"角色名称 '{updateDto.Name}' 已存在");
+ }
+
+ // 更新角色信息
+ role.SetName(updateDto.Name);
+ role.SetDescription(updateDto.Description);
+
+ await _roleRepository.Update(role);
+ await _unitOfWork.CommitAsync();
+
+ return new RoleDto(
+ role.RoleId,
+ role.Name,
+ role.Description,
+ role.IsSystem,
+ role.IsSupper,
+ role.CreateTime,
+ role.UpdateTime
+ );
+ }
+ catch (Exception ex)
+ {
+ await _unitOfWork.RollbackAsync();
+ throw new InvalidOperationException($"更新角色失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 删除角色
+ ///
+ public async Task DeleteRoleAsync(Guid roleId)
+ {
+ try
+ {
+ await _unitOfWork.BeginTransactionAsync();
+
+ var role = await _roleRepository.GetByGuidAsync(roleId);
+ if (role == null)
+ {
+ throw new KeyNotFoundException($"角色ID '{roleId}' 不存在");
+ }
+
+ // 检查是否为系统角色
+ if (role.IsSystem)
+ {
+ throw new InvalidOperationException("系统角色不允许删除");
+ }
+
+ // 检查是否为超级管理员角色
+ if (role.IsSupper)
+ {
+ throw new InvalidOperationException("超级管理员角色不允许删除");
+ }
+
+ await _roleRepository.RemoveAsync(roleId);
+ await _unitOfWork.CommitAsync();
+ }
+ catch (Exception ex)
+ {
+ await _unitOfWork.RollbackAsync();
+ throw new InvalidOperationException($"删除角色失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 为角色分配权限
+ ///
+ public async Task AssignPermissionsToRoleAsync(Guid roleId, IEnumerable permissionIds)
+ {
+ try
+ {
+ await _unitOfWork.BeginTransactionAsync();
+
+ var role = await _roleRepository.GetByGuidAsync(roleId);
+ if (role == null)
+ {
+ throw new KeyNotFoundException($"角色ID '{roleId}' 不存在");
+ }
+
+ // 验证权限是否存在
+ var permissions = await _permissionRepository.GetByIdsAsync(permissionIds);
+ var validPermissionIds = permissions.Select(p => p.PermissionId).ToHashSet();
+ var invalidPermissionIds = permissionIds.Except(validPermissionIds).ToList();
+
+ if (invalidPermissionIds.Any())
+ {
+ throw new InvalidOperationException($"以下权限ID不存在: {string.Join(", ", invalidPermissionIds)}");
+ }
+
+ // 为角色分配权限(使用Permission实体)
+ role.AddPermissions(permissions);
+
+ await _roleRepository.Update(role);
+ await _unitOfWork.CommitAsync();
+ }
+ catch (Exception ex)
+ {
+ await _unitOfWork.RollbackAsync();
+ throw new InvalidOperationException($"为角色分配权限失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 移除角色的权限
+ ///
+ public async Task RemovePermissionsFromRoleAsync(Guid roleId, IEnumerable permissionIds)
+ {
+ try
+ {
+ await _unitOfWork.BeginTransactionAsync();
+
+ var role = await _roleRepository.GetByGuidAsync(roleId);
+ if (role == null)
+ {
+ throw new KeyNotFoundException($"角色ID '{roleId}' 不存在");
+ }
+
+ // 获取要移除的权限实体
+ var permissionsToRemove = await _permissionRepository.GetByIdsAsync(permissionIds);
+
+ // 移除角色权限(使用Permission实体)
+ role.RemovePermissions(permissionsToRemove);
+
+ await _roleRepository.Update(role);
+ await _unitOfWork.CommitAsync();
+ }
+ catch (Exception ex)
+ {
+ await _unitOfWork.RollbackAsync();
+ throw new InvalidOperationException($"移除角色权限失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 获取角色的所有权限
+ ///
+ public async Task> GetRolePermissionsAsync(Guid roleId)
+ {
+ var role = await _roleRepository.GetByGuidAsync(roleId);
+ if (role == null)
+ {
+ throw new KeyNotFoundException($"角色ID '{roleId}' 不存在");
+ }
+
+ // 直接使用角色的权限导航属性
+ return role.Permissions.Select(p => new PermissionDto(
+ p.Name,
+ p.Code,
+ p.Description ?? string.Empty
+ ));
+ }
+}
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/SystemSettings/DTOs/SystemSettingDto.cs b/backend/src/UniversalAdminSystem.Application/SystemSettings/DTOs/SystemSettingDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..fc2982d346a9b46ad5055b1bef759bafc280eb82
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/SystemSettings/DTOs/SystemSettingDto.cs
@@ -0,0 +1,23 @@
+namespace UniversalAdminSystem.Application.SystemSettings.DTOs;
+
+public record SystemSettingDto(
+ Guid Id,
+ string Key,
+ string Value,
+ string? Description,
+ string? Group,
+ DateTime CreateTime,
+ DateTime UpdateTime
+);
+
+public record SystemSettingCreateDto(
+ string Key,
+ string Value,
+ string? Description = null,
+ string? Group = null
+);
+
+public record SystemSettingUpdateDto(
+ string Value,
+ string? Description = null
+);
\ No newline at end of file
diff --git a/backend/src/UniversalAdminSystem.Application/SystemSettings/Interfaces/ISystemSettingAppService.cs b/backend/src/UniversalAdminSystem.Application/SystemSettings/Interfaces/ISystemSettingAppService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1fa29350dfa65582b434129ae3d9e193feb4ce07
--- /dev/null
+++ b/backend/src/UniversalAdminSystem.Application/SystemSettings/Interfaces/ISystemSettingAppService.cs
@@ -0,0 +1,37 @@
+using UniversalAdminSystem.Application.SystemSettings.DTOs;
+using UniversalAdminSystem.Application.Common.Results;
+
+namespace UniversalAdminSystem.Application.SystemSettings.Interfaces;
+
+public interface ISystemSettingAppService
+{
+ ///
+ /// 获取所有系统设置
+ ///
+ Task>> GetAllSettingsAsync();
+
+ ///
+ /// 根据键获取系统设置
+ ///
+ Task> GetSettingByKeyAsync(string key);
+
+ ///
+ /// 根据组获取系统设置
+ ///
+ Task>> GetSettingsByGroupAsync(string group);
+
+ ///
+ /// 创建系统设置
+ ///
+ Task> CreateSettingAsync(SystemSettingCreateDto createDto);
+
+ ///