diff --git a/backend/src/BaseBackend.Api/API.md b/backend/src/BaseBackend.Api/API.md new file mode 100644 index 0000000000000000000000000000000000000000..7b377d63373c631270ec6f91649b89f0df79c569 --- /dev/null +++ b/backend/src/BaseBackend.Api/API.md @@ -0,0 +1,218 @@ +# 通用后台管理系统 API 调用文档 + +## 基础信息 + +- 基础URL:`http://localhost:5256` +- 所有接口均为RESTful风格,部分接口需在Header中携带`session`(登录后获取)。 + +--- + +## 目录 + +1. [认证相关](#认证相关) +2. [用户管理](#用户管理) +3. [角色管理](#角色管理) +4. [权限管理](#权限管理) +5. [健康检查](#健康检查) + +--- + +## 1. 认证相关 + +### 用户注册 + +- **接口**:`POST /api/auth/reg` +- **参数**(JSON): + - `Account`:账号(字符串) + - `Password`:密码(字符串) + - `Name`:姓名(字符串) +- **示例**: + +```json +POST /api/auth/reg +Content-Type: application/json + +{ + "Account": "testuser", + "Password": "123456", + "Name": "测试用户" +} +``` + +### 用户登录 + +- **接口**:`POST /api/auth/login` +- **参数**(JSON): + - `Account`:账号 + - `Password`:密码 +- **返回**:包含`session`的Token +- **示例**: + +```json +POST /api/auth/login +Content-Type: application/json + +{ + "Account": "testuser", + "Password": "123456" +} +``` + +--- + +## 2. 用户管理 + +> 需在Header中携带`session`字段 + +### 获取所有用户 + +- **接口**:`GET /api/user` +- **Header**:`session: ` +- **示例**: + +```http +GET /api/user +session: +``` + +### 根据ID获取用户 + +- **接口**:`GET /api/user/{userId}` +- **Header**:`session: ` +- **示例**: + +```http +GET /api/user/71a9a42b-81e8-4f54-b2a5-ff8a2634055d +session: +``` + +### 更新用户信息 + +- **接口**:`PUT /api/user` +- **Header**:`session: ` +- **参数**(JSON): + - `userId`:用户ID + - `Name`:姓名(可选) + - `Phone`:手机号(可选) +- **示例**: + +```json +PUT /api/user +session: +Content-Type: application/json + +{ + "userId": "71a9a42b-81e8-4f54-b2a5-ff8a2634055d", + "Name": "新用户名", + "Phone": 13800138000 +} +``` + +### 删除用户 + +- **接口**:`DELETE /api/user/{userId}` +- **Header**:`session: ` +- **示例**: + +```http +DELETE /api/user/71a9a42b-81e8-4f54-b2a5-ff8a2634055d +session: +``` + +--- + +## 3. 角色管理 + +> 需在Header中携带`session`字段 + +### 获取所有角色 + +- **接口**:`GET /api/role` +- **Header**:`session: ` + +### 根据用户ID获取角色 + +- **接口**:`GET /api/role/{userId}` +- **Header**:`session: ` + +### 添加新角色 + +- **接口**:`POST /api/role` +- **Header**:`session: ` +- **参数**(JSON):`name`(角色名) + +### 为用户分配角色 + +- **接口**:`PUT /api/role/{roleId}` +- **Header**:`session: ` +- **参数**(JSON):`Id`(用户ID) + +### 删除角色 + +- **接口**:`DELETE /api/role` +- **Header**:`session: ` +- **参数**(JSON):`Id`(角色ID) + +### 取消用户角色分配 + +- **接口**:`DELETE /api/role/{roleId}` +- **Header**:`session: ` +- **参数**(JSON):`Id`(用户ID) + +--- + +## 4. 权限管理 + +> 需在Header中携带`session`字段 + +### 获取所有权限 + +- **接口**:`GET /api/premission` +- **Header**:`session: ` + +### 根据角色ID获取权限 + +- **接口**:`GET /api/premission/{roleId}` +- **Header**:`session: ` + +### 添加新权限 + +- **接口**:`POST /api/premission` +- **Header**:`session: ` +- **参数**(JSON):`name`(权限名) + +### 为角色分配权限 + +- **接口**:`PUT /api/premission/{premissionId}` +- **Header**:`session: ` +- **参数**(JSON):`Id`(角色ID) + +### 删除权限 + +- **接口**:`DELETE /api/premission` +- **Header**:`session: ` +- **参数**(JSON):`Id`(权限ID) + +### 取消角色权限分配 + +- **接口**:`DELETE /api/premission/{premissionId}` +- **Header**:`session: ` +- **参数**(JSON):`Id`(角色ID) + +--- + +## 5. 健康检查 + +- **接口**:`GET /` +- **说明**:用于检测服务是否正常运行 + +--- + +## 变量说明 + +- `userId`、`roleId`、`premissionId`等可通过注册、添加等接口响应获取 +- `session`为登录后返回的Token,需在后续请求Header中携带 + +--- + +如需更详细的参数说明或返回格式,请参考`src/BaseBackend.Api/BaseBackend.Api.http`文件中的调用示例,或补充需求说明。 \ No newline at end of file diff --git a/backend/src/BaseBackend.Api/BaseBackend.Api.csproj b/backend/src/BaseBackend.Api/BaseBackend.Api.csproj index 3a64909d0ba9afe574fe489bf9c1ac9e6726e89d..e3aecb3bf316b3fd1e349129d30eb827bb3c91bc 100644 --- a/backend/src/BaseBackend.Api/BaseBackend.Api.csproj +++ b/backend/src/BaseBackend.Api/BaseBackend.Api.csproj @@ -18,6 +18,7 @@ + diff --git a/backend/src/BaseBackend.Api/BaseBackend.Api.csproj.user b/backend/src/BaseBackend.Api/BaseBackend.Api.csproj.user index 9ff5820a24514c8c51aea43655b97bad275de94e..031db340b26b4b069e73a306df846da0e8a93f8c 100644 --- a/backend/src/BaseBackend.Api/BaseBackend.Api.csproj.user +++ b/backend/src/BaseBackend.Api/BaseBackend.Api.csproj.user @@ -2,5 +2,7 @@ https + MvcControllerEmptyScaffolder + root/Common/MVC/Controller \ No newline at end of file diff --git a/backend/src/BaseBackend.Api/BaseBackend.Api.http b/backend/src/BaseBackend.Api/BaseBackend.Api.http index afb818bf6bdee7d721e302d9d2a6d41ec27d72bc..b6904996280463500fa2d301ffa6bd0f8aa94a2a 100644 --- a/backend/src/BaseBackend.Api/BaseBackend.Api.http +++ b/backend/src/BaseBackend.Api/BaseBackend.Api.http @@ -1,6 +1,241 @@ -@BaseBackend.Api_HostAddress = http://localhost:5256 +@url = http://localhost:5256 +@contentType = application/json +@userId = 71a9a42b-81e8-4f54-b2a5-ff8a2634055d +@roleId="943d60a2-0aaa-4582-89bc-1320eeb2ddbd" -GET {{BaseBackend.Api_HostAddress}}/weatherforecast/ -Accept: application/json +# ======================================== +# 认证相关测试 +# ======================================== -### +### 用户注册 +POST {{url}}/api/auth/reg +Content-Type: {{contentType}} + +{ + "Account": "testuser", + "Password": "123456", + "Name": "测试用户" +} + +### 用户登录 +POST {{url}}/api/auth/login +Content-Type: {{contentType}} + +{ + "Account": "testuser", + "Password": "123456" +} + +### 用户登录 - 错误密码 +POST {{url}}/api/auth/login +Content-Type: {{contentType}} + +{ + "Account": "testuser", + "Password": "wrongpassword" +} + +### 用户登录 - 不存在的用户 +POST {{url}}/api/auth/login +Content-Type: {{contentType}} + +{ + "Account": "nonexistent", + "Password": "123456" +} + +# ======================================== +# 用户管理测试 +# ======================================== + +### 获取所有用户 +GET {{url}}/api/user +Accept: {{contentType}} + +### 根据ID获取用户 +GET {{url}}/api/user/{{userId}} +Accept: {{contentType}} + +### 更新用户信息 +PUT {{url}}/api/user +Content-Type: {{contentType}} + +{ + "userId": "{{userId}}", + "Name": "更新后的用户名", + "Phone": 13800138000 +} + +### 更新用户信息 - 只更新姓名 +PUT {{url}}/api/user +Content-Type: {{contentType}} + +{ + "userId": "{{userId}}", + "Name": "新用户名1" +} + +### 更新用户信息 - 只更新手机号 +PUT {{url}}/api/user +Content-Type: {{contentType}} + +{ + "userId": "{{userId}}", + "Phone": 13900139000 +} + +### 更新用户信息 - 无效手机号 +PUT {{url}}/api/user +Content-Type: {{contentType}} + +{ + "userId": "{{userId}}", + "Phone": 123456789 +} + +### 更新用户信息 - 无效姓名(太短) +PUT {{url}}/api/user +Content-Type: {{contentType}} + +{ + "userId": "{{userId}}", + "Name": "abc" +} + +### 删除用户 +DELETE {{url}}/api/user/{{userId}} + +### 删除不存在的用户 +DELETE {{url}}/api/user/00000000-0000-0000-0000-000000000000 + +# ======================================== +# 角色管理测试 +# ======================================== + +### 获取所有角色 +GET {{url}}/api/role +Accept: {{contentType}} + +### 根据用户ID获取角色 +GET {{url}}/api/role/{{userId}} +Accept: {{contentType}} + +### 添加新角色 +POST {{url}}/api/role +Content-Type: {{contentType}} + +{ + "name": "管理员" +} + +### 添加另一个角色 +POST {{url}}/api/role +Content-Type: {{contentType}} + +{ + "name": "普通用户" +} + +### 为用户分配角色 +PUT {{url}}/api/role/69431276-2ca0-4d69-a7c6-8f18125c0203 +Content-Type: {{contentType}} + +{ + "Id": "71a9a42b-81e8-4f54-b2a5-ff8a2634055d" +} + +### 删除角色 +DELETE {{url}}/api/role +Content-Type: {{contentType}} + +{ + "Id": "943d60a2-0aaa-4582-89bc-1320eeb2ddbd" +} + +### 取消用户角色分配 +DELETE {{url}}/api/role/69431276-2ca0-4d69-a7c6-8f18125c0203 +Content-Type: {{contentType}} + +{ + "Id": "71a9a42b-81e8-4f54-b2a5-ff8a2634055d" +} + +# ======================================== +# 权限管理测试 +# ======================================== + +### 获取所有权限 +GET {{url}}/api/premission +Accept: {{contentType}} + +### 根据角色ID获取权限 +GET {{url}}/api/premission/69431276-2ca0-4d69-a7c6-8f18125c0203 +Accept: {{contentType}} + +### 添加新权限 +POST {{url}}/api/premission +Content-Type: {{contentType}} + +{ + "name": "user.manage" +} + +### 添加另一个权限 +POST {{url}}/api/premission +Content-Type: {{contentType}} + +{ + "name": "role.manage" +} + +### 为角色分配权限 +PUT {{url}}/api/premission/cda096b4-5a0f-424e-83cf-08f5185acc74 +Content-Type: {{contentType}} + +{ + "Id": "69431276-2ca0-4d69-a7c6-8f18125c0203" +} + +### 删除权限 +DELETE {{url}}/api/premission +Content-Type: {{contentType}} + +{ + "Id": "5510ef6a-7c9d-4e53-b2c5-6c77531c471f" +} + +### 取消角色权限分配 +DELETE {{url}}/api/premission/cda096b4-5a0f-424e-83cf-08f5185acc74 +Content-Type: {{contentType}} + +{ + "Id": "69431276-2ca0-4d69-a7c6-8f18125c0203" +} + +# ======================================== +# 基础健康检查 +# ======================================== + +### 健康检查 +GET {{url}}/ +Accept: {{contentType}} + +# ======================================== +# 变量设置(用于测试) +# ======================================== + +### 设置测试变量 - 用户ID +# 从注册或登录响应中获取用户ID +@userId = 00000000-0000-0000-0000-000000000000 + +### 设置测试变量 - 角色ID +# 从添加角色响应中获取角色ID +@roleId = 00000000-0000-0000-0000-000000000000 + +### 设置测试变量 - 权限ID +# 从添加权限响应中获取权限ID +@premissionId = 00000000-0000-0000-0000-000000000000 + +### 设置测试变量 - 会话Token +# 从登录响应中获取会话Token +@sessionToken = your-session-token-here diff --git a/backend/src/BaseBackend.Api/BaseBackend.Api.session.http b/backend/src/BaseBackend.Api/BaseBackend.Api.session.http new file mode 100644 index 0000000000000000000000000000000000000000..1672b99ca948abe3772b94360661c62728cc58e0 --- /dev/null +++ b/backend/src/BaseBackend.Api/BaseBackend.Api.session.http @@ -0,0 +1,179 @@ +@url = http://localhost:5256 +@contentType = application/json +@userId = 71a9a42b-81e8-4f54-b2a5-ff8a2634055d +@roleId = 943d60a2-0aaa-4582-89bc-1320eeb2ddbd +@premissionId = cda096b4-5a0f-424e-83cf-08f5185acc74 +@sessionToken = GHL4Ma3UYL9c4AHAvM2a5BegotYTrEJu + + +# ======================================== +# 认证相关测试 +# ======================================== + +### 用户注册 +POST {{url}}/api/auth/reg +Content-Type: {{contentType}} + +{ + "Account": "testuser", + "Password": "123456", + "Name": "测试用户" +} + +### 用户登录 +POST {{url}}/api/auth/login +Content-Type: {{contentType}} + +{ + "Account": "root", + "Password": "rootroot" +} + +# ======================================== +# 用户管理测试 +# ======================================== + +### 获取所有用户 +GET {{url}}/api/user +Accept: {{contentType}} +session: dFuxvWZ6KhxJyK7FZcMK5apRJlw1n8lJ + +### 根据ID获取用户 +GET {{url}}/api/user/3e804d80-0b1c-44bb-b42f-d1a77ac97f4f +Accept: {{contentType}} +session: 8DDhDMs3uGmLJGxXrGDzeZT4M5iFhw7z + +### 更新用户信息 +PUT {{url}}/api/user +Content-Type: {{contentType}} +session: {{sessionToken}} + +{ + "userId": "3e804d80-0b1c-44bb-b42f-d1a77ac97f4f", + "Name": "更新后的用户名", + "Phone": 13800138000 +} + +### 删除用户 +DELETE {{url}}/api/user/3e804d80-0b1c-44bb-b42f-d1a77ac97f4f +session: {{sessionToken}} + +# ======================================== +# 角色管理测试 +# ======================================== + +### 获取所有角色 +GET {{url}}/api/role +Accept: {{contentType}} +session: eoV5zsLtzsFl7t67rFqyaFGPGMMU6e83 + +### 根据用户ID获取角色 +GET {{url}}/api/role/{{userId}} +Accept: {{contentType}} +session: {{sessionToken}} + +### 添加新角色 +POST {{url}}/api/role +Content-Type: {{contentType}} +session: {{sessionToken}} + +{ + "name": "管理员" +} + +### 为用户分配角色 +PUT {{url}}/api/role/{{roleId}} +Content-Type: {{contentType}} +session: {{sessionToken}} + +{ + "Id": "{{userId}}" +} + +### 删除角色 +DELETE {{url}}/api/role +Content-Type: {{contentType}} +session: {{sessionToken}} + +{ + "Id": "{{roleId}}" +} + +### 取消用户角色分配 +DELETE {{url}}/api/role/{{roleId}} +Content-Type: {{contentType}} +session: {{sessionToken}} + +{ + "Id": "{{userId}}" +} + +# ======================================== +# 权限管理测试 +# ======================================== + +### 获取所有权限 +GET {{url}}/api/premission +Accept: {{contentType}} +session: {{sessionToken}} + +### 根据角色ID获取权限 +GET {{url}}/api/premission/{{roleId}} +Accept: {{contentType}} +session: {{sessionToken}} + +### 添加新权限 +POST {{url}}/api/premission +Content-Type: {{contentType}} +session: {{sessionToken}} + +{ + "name": "user.manage" +} + +### 为角色分配权限 +PUT {{url}}/api/premission/{{premissionId}} +Content-Type: {{contentType}} +session: {{sessionToken}} + +{ + "Id": "{{roleId}}" +} + +### 删除权限 +DELETE {{url}}/api/premission +Content-Type: {{contentType}} +session: {{sessionToken}} + +{ + "Id": "{{premissionId}}" +} + +### 取消角色权限分配 +DELETE {{url}}/api/premission/{{premissionId}} +Content-Type: {{contentType}} +session: {{sessionToken}} + +{ + "Id": "{{roleId}}" +} + +# ======================================== +# 变量设置(用于测试) +# ======================================== + +### 设置测试变量 - 用户ID +# 从注册或登录响应中获取用户ID +@userId = 00000000-0000-0000-0000-000000000000 + +### 设置测试变量 - 角色ID +# 从添加角色响应中获取角色ID +@roleId = 00000000-0000-0000-0000-000000000000 + +### 设置测试变量 - 权限ID +# 从添加权限响应中获取权限ID +@premissionId = 00000000-0000-0000-0000-000000000000 + +### 设置测试变量 - 会话Token +# 从登录响应中获取会话Token +# @sessionToken = your-session-token-here \ No newline at end of file diff --git a/backend/src/BaseBackend.Api/Controllers/AuthController.cs b/backend/src/BaseBackend.Api/Controllers/AuthController.cs index a16e951a39cc83ebc3d65e66a4253b0e37937eb6..c5245a4588a7e5f9a8030bb78a282a311a506c60 100644 --- a/backend/src/BaseBackend.Api/Controllers/AuthController.cs +++ b/backend/src/BaseBackend.Api/Controllers/AuthController.cs @@ -1,22 +1,25 @@ using BaseBackend.Api.Controllers.Base; using BaseBackend.Application.DTOs; +using BaseBackend.Application.Services; using Microsoft.AspNetCore.Mvc; namespace BaseBackend.Api.Controllers { [ApiController] - [Route("[controller]")] - public class AuthController : BaseAppController + [Route("api/[controller]")] + public class AuthController(LoginAuthService loginAuthService) : BaseAppController { + private readonly LoginAuthService _loginAuthService = loginAuthService; [HttpPost("login")] - public IActionResult Login() + public async Task Login(UserAuthDTO data) { - return CommonResult(); + return CommonResult(await _loginAuthService.Login(data.Account, data.Password)); } [HttpPost("reg")] - public IActionResult Reg() + public async Task RegAsync(UserAuthDTO data) { - return CommonResult(); + + return CommonResult(await _loginAuthService.Reg(data.Account, data.Password, data.Name)); } } } diff --git a/backend/src/BaseBackend.Api/Controllers/Base/BaseAppController.cs b/backend/src/BaseBackend.Api/Controllers/Base/BaseAppController.cs index 42b8a88472ac78888b60416ba54c36a19b6cf39d..564569e8615a12152de92c0dbd4fbec16b27e323 100644 --- a/backend/src/BaseBackend.Api/Controllers/Base/BaseAppController.cs +++ b/backend/src/BaseBackend.Api/Controllers/Base/BaseAppController.cs @@ -1,20 +1,25 @@ -using BaseBackend.Application.DTOs.Base; +using BaseBackend.Application.DTOs; +using BaseBackend.Application.DTOs.Base; using Microsoft.AspNetCore.Mvc; namespace BaseBackend.Api.Controllers.Base { - public class BaseAppController : ControllerBase + public class BaseAppController : ControllerBase { - protected IActionResult CommonResult(BaseResultDTO result) + protected IActionResult CommonResult(BaseResultDTO result) { if (result.IsSuccess) { - return Ok(result.Data); + return Ok(new HttpResultDTO(2000, result.Msg, result.Data)); } else { - return BadRequest(result.Msg); + return BadRequest(new HttpResultDTO(-1, result.Msg)); } } + protected IActionResult UnauthResult() + { + return Unauthorized(); + } } } diff --git a/backend/src/BaseBackend.Api/Controllers/PremissionController.cs b/backend/src/BaseBackend.Api/Controllers/PremissionController.cs new file mode 100644 index 0000000000000000000000000000000000000000..9ce5a9680ff606788ff0b9b55a4a4af1e818ac6e --- /dev/null +++ b/backend/src/BaseBackend.Api/Controllers/PremissionController.cs @@ -0,0 +1,77 @@ +using BaseBackend.Api.Controllers.Base; +using BaseBackend.Application.DTOs; +using BaseBackend.Application.Services; +using Microsoft.AspNetCore.Mvc; + +namespace BaseBackend.Api.Controllers +{ + [ApiController] + [Route("api/[controller]")] + public class PremissionController(PremissionService premissionService, CommonAuthService commonAuthService) : BaseAppController + { + private readonly PremissionService _premissionService = premissionService; + private readonly CommonAuthService _commonAuthService = commonAuthService; + + [HttpGet] + public async Task GetAll([FromHeader] string? session) + { + if (await _commonAuthService.CheckPermissionAsync(session, "premission.getAll")) + { + return CommonResult(await _premissionService.GetAll()); + } + return Unauthorized(); + + } + [HttpGet("{roleId}")] + public async Task GetByRoleId(Guid roleId, [FromHeader] string? session) + { + if (await _commonAuthService.CheckPermissionAsync(session, "premission.getByRoleId")) + { + return CommonResult(await _premissionService.GetByRoleId(roleId)); + } + return Unauthorized(); + + } + [HttpPost] + public async Task Add([FromBody] BaseCreateDTO premissionName, [FromHeader] string? session) + { + if (await _commonAuthService.CheckPermissionAsync(session, "premission.add")) + { + return CommonResult(await _premissionService.Add(premissionName.Name)); + } + return Unauthorized(); + + } + [HttpPut("{premissionId}")] + public async Task Assign(Guid premissionId, [FromBody] BaseAssignDTO roleId, [FromHeader] string? session) + { + if (await _commonAuthService.CheckPermissionAsync(session, "premission.assign")) + { + return CommonResult(await _premissionService.Assign(premissionId, roleId.Id)); + } + return Unauthorized(); + + } + [HttpDelete] + public async Task Delete([FromBody] BaseDeleteDTO premissionId, [FromHeader] string? session) + { + if (await _commonAuthService.CheckPermissionAsync(session, "premission.delete")) + { + return CommonResult(await _premissionService.Delete(premissionId.Id)); + } + return Unauthorized(); + + } + [HttpDelete("{premissionId}")] + public async Task Unassign(Guid premissionId, [FromBody] BaseAssignDTO roleId, [FromHeader] string? session) + { + if (await _commonAuthService.CheckPermissionAsync(session, "premission.unassign")) + { + return CommonResult(await _premissionService.Unassign(premissionId, roleId.Id)); + } + return Unauthorized(); + + } + + } +} diff --git a/backend/src/BaseBackend.Api/Controllers/RoleController.cs b/backend/src/BaseBackend.Api/Controllers/RoleController.cs new file mode 100644 index 0000000000000000000000000000000000000000..dcff45028d668b53e589ec839077955ce9509352 --- /dev/null +++ b/backend/src/BaseBackend.Api/Controllers/RoleController.cs @@ -0,0 +1,75 @@ +using BaseBackend.Api.Controllers.Base; +using BaseBackend.Application.DTOs; +using BaseBackend.Application.Services; +using Microsoft.AspNetCore.Mvc; + +namespace BaseBackend.Api.Controllers +{ + [ApiController] + [Route("api/[controller]")] + public class RoleController(RoleService roleService, CommonAuthService commonAuthService) : BaseAppController + { + private readonly RoleService _roleService = roleService; + private readonly CommonAuthService _commonAuthService = commonAuthService; + + [HttpGet] + public async Task GetAll([FromHeader] string? session) + { + if (await _commonAuthService.CheckPermissionAsync(session, "role.getAll")) + { + return CommonResult(await _roleService.GetAll()); + } + return Unauthorized(); + } + [HttpGet("{userId}")] + public async Task GetByUserId(Guid userId, [FromHeader] string? session) + { + if (await _commonAuthService.CheckPermissionAsync(session, "role.getByUserId")) + { + return CommonResult(await _roleService.GetByUserId(userId)); + } + return Unauthorized(); + + } + [HttpPost] + public async Task Add(BaseCreateDTO roleName, [FromHeader] string? session) + { + if (await _commonAuthService.CheckPermissionAsync(session, "role.add")) + { + return CommonResult(await _roleService.Add(roleName.Name)); + } + return Unauthorized(); + } + [HttpPut("{roleId}")] + public async Task Assign(Guid roleId, [FromBody] BaseAssignDTO userId, [FromHeader] string? session) + { + if (await _commonAuthService.CheckPermissionAsync(session, "role.assign")) + { + return CommonResult(await _roleService.Assign(roleId, userId.Id)); + } + return Unauthorized(); + + } + [HttpDelete] + public async Task Delete([FromBody] BaseDeleteDTO roleId, [FromHeader] string? session) + { + if (await _commonAuthService.CheckPermissionAsync(session, "role.delete")) + { + return CommonResult(await _roleService.Delete(roleId.Id)); + } + return Unauthorized(); + + } + [HttpDelete("{roleId}")] + public async Task Unassign(Guid roleId, [FromBody] BaseAssignDTO userId, [FromHeader] string? session) + { + if (await _commonAuthService.CheckPermissionAsync(session, "role.unassign")) + { + return CommonResult(await _roleService.Unassign(roleId, userId.Id)); + } + return Unauthorized(); + + } + + } +} diff --git a/backend/src/BaseBackend.Api/Controllers/UserController.cs b/backend/src/BaseBackend.Api/Controllers/UserController.cs new file mode 100644 index 0000000000000000000000000000000000000000..db104912282b20892aefecee1c200ff7af225ff8 --- /dev/null +++ b/backend/src/BaseBackend.Api/Controllers/UserController.cs @@ -0,0 +1,55 @@ +using BaseBackend.Api.Controllers.Base; +using BaseBackend.Application.DTOs; +using BaseBackend.Application.Services; +using Microsoft.AspNetCore.Mvc; + +namespace BaseBackend.Api.Controllers +{ + [ApiController] + [Route("api/[controller]")] + public class UserController(UserService userService, CommonAuthService commonAuthService) : BaseAppController + { + private readonly UserService _userService = userService; + private readonly CommonAuthService _commonAuthService = commonAuthService; + [HttpGet] + public async Task GetAll([FromHeader] string? session) + { + Console.WriteLine(session); + if (await _commonAuthService.CheckPermissionAsync(session, "user.getAll")) + { + return CommonResult(await _userService.GetAllUsers()); + } + return Unauthorized(); + + } + [HttpGet("{userId}")] + public async Task GetById(Guid userId, [FromHeader] string? session) + { + if (await _commonAuthService.CheckPermissionAsync(session, "user.getById")) + { + return CommonResult(await _userService.GetUserById(userId)); + } + return Unauthorized(); + + } + [HttpPut] + public async Task Update([FromBody] UserUpdateDTO update, [FromHeader] string? session) + { + if (await _commonAuthService.CheckPermissionAsync(session, "user.update", update.UserId)) + { + return CommonResult(await _userService.UpdateUser(update)); + } + return Unauthorized(); + + } + [HttpDelete("{userId}")] + public async Task Delete(Guid userId, [FromHeader] string? session) + { + if (await _commonAuthService.CheckPermissionAsync(session, "user.delete", userId)) + { + return CommonResult(await _userService.DeleteUser(userId)); + } + return Unauthorized(); + } + } +} diff --git a/backend/src/BaseBackend.Api/Program.cs b/backend/src/BaseBackend.Api/Program.cs index 0b062dfc1433c1e101bd374de5963e7a95dbb7ec..41896cf14320cf3f84297155bf5d9192524b122f 100644 --- a/backend/src/BaseBackend.Api/Program.cs +++ b/backend/src/BaseBackend.Api/Program.cs @@ -1,5 +1,6 @@ -using Microsoft.EntityFrameworkCore; +using BaseBackend.Application; using BaseBackend.Infrastructure; + var builder = WebApplication.CreateBuilder(args); builder.Services.AddOpenApi(); @@ -9,11 +10,10 @@ builder.Services.AddApplication(); //基础设施层 builder.Services.AddInfrastructure(builder.Configuration); -//重复 -// builder.Services.AddDbContext(options => -// options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"))); var app = builder.Build(); +//初始化数据库以及数据 +await app.Services.CheckDatabase(); app.UseHttpsRedirection(); diff --git a/backend/src/BaseBackend.Api/appsettings.json b/backend/src/BaseBackend.Api/appsettings.json index 38e0f1ce05ba2592b3fbb6a1dc347679dd1f9487..d34a52a721bec249c917309f188e1083ee43fda3 100644 --- a/backend/src/BaseBackend.Api/appsettings.json +++ b/backend/src/BaseBackend.Api/appsettings.json @@ -7,6 +7,6 @@ }, "AllowedHosts": "*", "ConnectionStrings": { - "DefaultConnection": "Host=localhost;Port=5432;Database=User;Username=users;Password=12345678" + "DefaultConnection": "server=localhost;database=user;uid=postgres;pwd=12345678" } } diff --git a/backend/src/BaseBackend.Application/BaseBackend.Application.csproj b/backend/src/BaseBackend.Application/BaseBackend.Application.csproj index 60d8a6fa805e8b0d0ba971a886765d16e29ea70a..c09415b312a59dce4bca830e4ca66ab745f11f3c 100644 --- a/backend/src/BaseBackend.Application/BaseBackend.Application.csproj +++ b/backend/src/BaseBackend.Application/BaseBackend.Application.csproj @@ -6,6 +6,10 @@ enable + + + + diff --git a/backend/src/BaseBackend.Application/DTOs/Base/BaseResultDTO.cs b/backend/src/BaseBackend.Application/DTOs/Base/BaseResultDTO.cs index 3023bceff0db38274a59b850bf8c282d3f4c26a5..9fb8d24c34762c72ca4fc351c9b1fc4dc1e0928d 100644 --- a/backend/src/BaseBackend.Application/DTOs/Base/BaseResultDTO.cs +++ b/backend/src/BaseBackend.Application/DTOs/Base/BaseResultDTO.cs @@ -1,21 +1,21 @@ namespace BaseBackend.Application.DTOs.Base { - public class BaseResultDTO + public class BaseResultDTO { public bool IsSuccess { get; protected set; } - public T? Data { get; private set; } - public string Msg { get; protected set; } + public Object? Data { get; private set; } + public string Msg { get; protected set; } = null!; - public static BaseResultDTO Success(T data, string msg = "成功") + public static BaseResultDTO Success(Object? data, string msg = "成功") { return new() { IsSuccess = true, Data = data, Msg = msg }; } - public static BaseResultDTO Fail(string msg = "失败") + public static BaseResultDTO Fail(string msg = "失败") { - return new() { IsSuccess = true, Msg = msg }; + return new() { IsSuccess = false, Msg = msg }; } } } diff --git a/backend/src/BaseBackend.Application/DTOs/BaseAssignDTO.cs b/backend/src/BaseBackend.Application/DTOs/BaseAssignDTO.cs new file mode 100644 index 0000000000000000000000000000000000000000..f377f9ab976e19941d7a4ba42295b33894fb1b58 --- /dev/null +++ b/backend/src/BaseBackend.Application/DTOs/BaseAssignDTO.cs @@ -0,0 +1,7 @@ +namespace BaseBackend.Application.DTOs +{ + public class BaseAssignDTO(Guid Id) + { + public Guid Id { get; set; } = Id; + } +} diff --git a/backend/src/BaseBackend.Application/DTOs/BaseCreateDTO.cs b/backend/src/BaseBackend.Application/DTOs/BaseCreateDTO.cs new file mode 100644 index 0000000000000000000000000000000000000000..cc939a3a20e5a86d50b5c6676924d90b21ceeac5 --- /dev/null +++ b/backend/src/BaseBackend.Application/DTOs/BaseCreateDTO.cs @@ -0,0 +1,5 @@ +namespace BaseBackend.Application.DTOs; +public class BaseCreateDTO(string Name) +{ + public string Name { get; set; } = Name; +} \ No newline at end of file diff --git a/backend/src/BaseBackend.Application/DTOs/BaseDeleteDTO.cs b/backend/src/BaseBackend.Application/DTOs/BaseDeleteDTO.cs new file mode 100644 index 0000000000000000000000000000000000000000..59fb0c2714912dc7bb0e726ab6e24616e0403c8b --- /dev/null +++ b/backend/src/BaseBackend.Application/DTOs/BaseDeleteDTO.cs @@ -0,0 +1,7 @@ +namespace BaseBackend.Application.DTOs +{ + public class BaseDeleteDTO(Guid Id) + { + public Guid Id { get; set; } = Id; + } +} diff --git a/backend/src/BaseBackend.Application/DTOs/HttpResultDTO.cs b/backend/src/BaseBackend.Application/DTOs/HttpResultDTO.cs new file mode 100644 index 0000000000000000000000000000000000000000..1270ee5d28b17691accb5d7cbd985848411f53de --- /dev/null +++ b/backend/src/BaseBackend.Application/DTOs/HttpResultDTO.cs @@ -0,0 +1,7 @@ +namespace BaseBackend.Application.DTOs +{ + public record class HttpResultDTO(int Code, string Msg, Object? Data) + { + public HttpResultDTO(int Code, string Msg) : this(Code, Msg, null) { } + } +} diff --git a/backend/src/BaseBackend.Application/DTOs/UserAuthDTO.cs b/backend/src/BaseBackend.Application/DTOs/UserAuthDTO.cs new file mode 100644 index 0000000000000000000000000000000000000000..60c9b882662dd4c6848b4387c5fc912ee7f45498 --- /dev/null +++ b/backend/src/BaseBackend.Application/DTOs/UserAuthDTO.cs @@ -0,0 +1,9 @@ +namespace BaseBackend.Application.DTOs +{ + public class UserAuthDTO(string account, string password, string? name = null) + { + public string Account { get; set; } = account; + public string Password { get; set; } = password; + public string? Name { get; set; } = name; + } +} diff --git a/backend/src/BaseBackend.Application/DTOs/UserAuthResultDTO.cs b/backend/src/BaseBackend.Application/DTOs/UserAuthResultDTO.cs index d0d6f0ef45978795efb34191cb079912a2ad4145..364e1aad802cc30f8fc72704a8fb112005635322 100644 --- a/backend/src/BaseBackend.Application/DTOs/UserAuthResultDTO.cs +++ b/backend/src/BaseBackend.Application/DTOs/UserAuthResultDTO.cs @@ -1,5 +1,5 @@  namespace BaseBackend.Application.DTOs { - public record class UserAuthResultDTO(); + public record class UserAuthResultDTO(string Session); } diff --git a/backend/src/BaseBackend.Application/DTOs/UserUpdateDTO.cs b/backend/src/BaseBackend.Application/DTOs/UserUpdateDTO.cs new file mode 100644 index 0000000000000000000000000000000000000000..0e9ea4dcce542c2e1b56fd5215aecd62718d4ede --- /dev/null +++ b/backend/src/BaseBackend.Application/DTOs/UserUpdateDTO.cs @@ -0,0 +1,9 @@ +namespace BaseBackend.Application.DTOs +{ + public class UserUpdateDTO(Guid userId, string? name, long? phone) + { + public Guid UserId { get; set; } = userId; + public string? Name { get; set; } = name; + public long? Phone { get; set; } = phone; + } +} diff --git a/backend/src/BaseBackend.Application/ServiceCollectionExtensions.cs b/backend/src/BaseBackend.Application/ServiceCollectionExtensions.cs new file mode 100644 index 0000000000000000000000000000000000000000..cb12f30a41164c3998c3bcf5a4f7152c85759f64 --- /dev/null +++ b/backend/src/BaseBackend.Application/ServiceCollectionExtensions.cs @@ -0,0 +1,20 @@ +using BaseBackend.Application.Services; +using Microsoft.Extensions.DependencyInjection; + +namespace BaseBackend.Application +{ + public static class ServiceCollectionExtensions + { + public static IServiceCollection AddApplication(this IServiceCollection services) + { + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + + return services; + } + } +} \ No newline at end of file diff --git a/backend/src/BaseBackend.Application/Services/AuthService.cs b/backend/src/BaseBackend.Application/Services/AuthService.cs deleted file mode 100644 index 76f0730f8d4d482f9adb1ee2fa20389a01b4c45a..0000000000000000000000000000000000000000 --- a/backend/src/BaseBackend.Application/Services/AuthService.cs +++ /dev/null @@ -1,26 +0,0 @@ -using BaseBackend.Application.Common.Interfaces; -using BaseBackend.Domain.Repositories; - -namespace BaseBackend.Application.Services -{ - public class AuthService(IPasswordHasher passwordHasher, IUserRepository userRepository) - { - private readonly IPasswordHasher _passwordHasher = passwordHasher; - private readonly IUserRepository _userRep = userRepository; - public async Task Login(string account, string password) - { - var user = await _userRep.GetByAccountAsync(account); - if (user != null) - { - if (_passwordHasher.VerifyPassword(user.HashedPassword, password, user.Salt)) - { - return user; - } - } - } - public void Reg() - { - - } - } -} diff --git a/backend/src/BaseBackend.Application/Services/CommonAuthService.cs b/backend/src/BaseBackend.Application/Services/CommonAuthService.cs new file mode 100644 index 0000000000000000000000000000000000000000..a848880831274378abf2fb1d0ee1cf7fe0fe59a1 --- /dev/null +++ b/backend/src/BaseBackend.Application/Services/CommonAuthService.cs @@ -0,0 +1,44 @@ +using BaseBackend.Domain.Repositories; + +namespace BaseBackend.Application.Services +{ + public class CommonAuthService(IUserRoleRepository userRoleRepository, IRolePremissionRepository rolePremissionRepository, IPremissionRepository premissionRepository, SessionService sessionService) + { + private readonly IUserRoleRepository _userRoleRep = userRoleRepository; + private readonly IRolePremissionRepository _rolePremissionRep = rolePremissionRepository; + private readonly IPremissionRepository _premissionRep = premissionRepository; + private readonly SessionService _sessionService = sessionService; + public async Task CheckPermissionAsync(Guid userId, string premissionName, Guid? operatUserId = null) + { + if (userId == operatUserId) + { + return true; + } + var premission = await _premissionRep.GetByNameAsync(premissionName); + if (premission != null) + { + var userHasRoleList = await _userRoleRep.GetRoleListByUserId(userId); + var premissionHasRoleList = await _rolePremissionRep.GetRoleListByPremissionId(premission.Id); + var sameRoleNum = userHasRoleList.Intersect(premissionHasRoleList).Count(); + if (sameRoleNum > 0) + { + return true; + } + } + return false; + } + public async Task CheckPermissionAsync(string? session, string premissionName, Guid? operatUserId = null) + { + if (session != null) + { + var userId = await _sessionService.GetUserIdBySession(session); + if (userId != null) + { + return await CheckPermissionAsync((Guid)userId, premissionName, operatUserId); + } + + } + return false; + } + } +} diff --git a/backend/src/BaseBackend.Application/Services/LoginAuthService.cs b/backend/src/BaseBackend.Application/Services/LoginAuthService.cs new file mode 100644 index 0000000000000000000000000000000000000000..ad3420d19329d185e04df057fbd0c07e5be78405 --- /dev/null +++ b/backend/src/BaseBackend.Application/Services/LoginAuthService.cs @@ -0,0 +1,63 @@ +using BaseBackend.Application.Common.Interfaces; +using BaseBackend.Application.DTOs; +using BaseBackend.Application.DTOs.Base; +using BaseBackend.Domain.Entities.App; +using BaseBackend.Domain.Repositories; +using System.Security.Cryptography; + +namespace BaseBackend.Application.Services +{ + public class LoginAuthService(IPasswordHasher passwordHasher, IUserRepository userRepository, ISessionRepository sessionRepository) + { + private readonly IPasswordHasher _passwordHasher = passwordHasher; + private readonly IUserRepository _userRep = userRepository; + private readonly ISessionRepository _sessionRep = sessionRepository; + + private string GenerateSession(int length) + { + const string validChars = "ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + char[] chars = new char[length]; + + using (var rng = RandomNumberGenerator.Create()) + { + byte[] randomBytes = new byte[length]; + rng.GetBytes(randomBytes); + + for (int i = 0; i < length; i++) + { + chars[i] = validChars[randomBytes[i] % validChars.Length]; + } + } + + return new string(chars); + } + + public async Task Login(string account, string password) + { + var user = await _userRep.GetByAccountAsync(account); + if (user != null) + { + if (_passwordHasher.VerifyPassword(user.HashedPassword, password, user.Salt)) + { + var session = GenerateSession(32); + await _sessionRep.AddAsync(UserSession.Create(user.Id, session)); + return BaseResultDTO.Success(new UserAuthResultDTO(session)); + } + } + return BaseResultDTO.Fail("密码错误或账号不存在"); + } + public async Task Reg(string account, string password, string name) + { + var hashedPassword = _passwordHasher.CreatePassword(password); + + var user = (await _userRep.AddAsync(AppUser.Create(account, name, hashedPassword.hashedPassword, hashedPassword.salt))); + if (user != null) + { + var session = GenerateSession(32); + await _sessionRep.AddAsync(UserSession.Create(user.Id, session)); + return BaseResultDTO.Success(new UserAuthResultDTO(session)); + } + return BaseResultDTO.Fail("注册错误"); + } + } +} diff --git a/backend/src/BaseBackend.Application/Services/PremissionService.cs b/backend/src/BaseBackend.Application/Services/PremissionService.cs new file mode 100644 index 0000000000000000000000000000000000000000..4c6639e851b495ab6a6103d60721a96c420531b1 --- /dev/null +++ b/backend/src/BaseBackend.Application/Services/PremissionService.cs @@ -0,0 +1,70 @@ +using BaseBackend.Application.DTOs.Base; +using BaseBackend.Domain.Entities.App; +using BaseBackend.Domain.Repositories; + +namespace BaseBackend.Application.Services +{ + public class PremissionService(IRepository roleRepository, IRolePremissionRepository rolePremissionRepository, IPremissionRepository premissionRepository) + { + private readonly IRepository _roleRep = roleRepository; + private readonly IRolePremissionRepository _rolePremissionRep = rolePremissionRepository; + private readonly IPremissionRepository _premissionRep = premissionRepository; + + public async Task GetAll() + { + return BaseResultDTO.Success(await _premissionRep.GetAllAsync()); + } + private async Task GetById(Guid premissionId) + { + return await _premissionRep.GetByIdAsync(premissionId); + } + public async Task GetByRoleId(Guid roleId) + { + var premissionList = await _rolePremissionRep.GetPremissionListByRoleId(roleId); + if (premissionList.Count > 0) + { + List result = []; + premissionList.ForEach(async premissionId => result.Add(await this.GetById(premissionId))); + return BaseResultDTO.Success(result); + } + return BaseResultDTO.Fail("角色不存在或未分配权限"); + } + public async Task Add(string name) + { + var premission = AppPremission.Create(name); + await _premissionRep.AddAsync(premission); + return BaseResultDTO.Success(premission); + } + public async Task Delete(Guid premissionId) + { + var premission = await _premissionRep.DeleteAsync(premissionId); + if(premission != null) + { + var rolePremissions = await _rolePremissionRep.DeleteByPremissionId(premissionId); + return BaseResultDTO.Success(premission); + } + return BaseResultDTO.Fail("权限不存在"); + } + public async Task Assign(Guid premissionId, Guid roleId) + { + var role = await _roleRep.GetByIdAsync(roleId); + var premission = await _premissionRep.GetByIdAsync(premissionId); + if (role != null && premission != null) + { + var result = await _rolePremissionRep.AddAsync(RolePremission.Create(roleId, premissionId)); + return BaseResultDTO.Success(result); + } + return BaseResultDTO.Fail("角色或权限不存在"); + } + public async Task Unassign(Guid premissionId, Guid roleId) + { + var rolePremission = await _rolePremissionRep.GetByPremissionIdAndRoleId(premissionId, roleId); + if (rolePremission != null) + { + await _rolePremissionRep.DeleteAsync(rolePremission); + return BaseResultDTO.Success(rolePremission); + } + return BaseResultDTO.Fail("权限分配不存在"); + } + } +} diff --git a/backend/src/BaseBackend.Application/Services/RoleService.cs b/backend/src/BaseBackend.Application/Services/RoleService.cs new file mode 100644 index 0000000000000000000000000000000000000000..4e1e551f7659e4a03614d3ccdccb58eea7b2ca2a --- /dev/null +++ b/backend/src/BaseBackend.Application/Services/RoleService.cs @@ -0,0 +1,72 @@ +using BaseBackend.Application.DTOs.Base; +using BaseBackend.Domain.Entities.App; +using BaseBackend.Domain.Repositories; + +namespace BaseBackend.Application.Services +{ + public class RoleService(IUserRepository userRepository, IRepository roleRepository, IUserRoleRepository userRoleRepository) + { + private readonly IUserRepository _userRep = userRepository; + private readonly IRepository _roleRep = roleRepository; + private readonly IUserRoleRepository _userRoleRep = userRoleRepository; + + public async Task GetAll() + { + return BaseResultDTO.Success(await _roleRep.GetAllAsync()); + } + private async Task GetById(Guid roleId) + { + return await _roleRep.GetByIdAsync(roleId); + } + public async Task GetByUserId(Guid userId) + { + var roleList = await _userRoleRep.GetRoleListByUserId(userId); + if (roleList.Count > 0) + { + List result = []; + roleList.ForEach(async roleId => result.Add(await this.GetById(roleId))); + return BaseResultDTO.Success(result); + } + return BaseResultDTO.Fail("用户不存在或未分配角色"); + } + public async Task Add(string name) + { + var role = AppRole.Create(name); + await _roleRep.AddAsync(role); + return BaseResultDTO.Success(role); + } + public async Task Delete(Guid roleId) + { + var role = await _roleRep.DeleteAsync(roleId); + if (role != null) + { + var userRoles = await _userRoleRep.DeleteByRoleId(roleId); + return BaseResultDTO.Success(role); + } + return BaseResultDTO.Fail("该角色不存在"); + } + public async Task Assign(Guid roleId, Guid userId) + { + Console.WriteLine(roleId); + Console.WriteLine(userId); + var user = await _userRep.GetByIdAsync(userId); + var role = await _roleRep.GetByIdAsync(roleId); + if (user != null && role != null) + { + var result = await _userRoleRep.AddAsync(UserRole.Create(userId, roleId)); + return BaseResultDTO.Success(result); + } + return BaseResultDTO.Fail("用户或角色不存在"); + } + public async Task Unassign(Guid roleId, Guid userId) + { + var userRole = await _userRoleRep.GetByRoleIdAndUserId(roleId, userId); + if (userRole != null) + { + await _userRoleRep.DeleteAsync(userRole); + return BaseResultDTO.Success(userRole); + } + return BaseResultDTO.Fail("角色分配不存在"); + } + } +} diff --git a/backend/src/BaseBackend.Application/Services/SessionService.cs b/backend/src/BaseBackend.Application/Services/SessionService.cs new file mode 100644 index 0000000000000000000000000000000000000000..426028c1311549bd88fe5272d8417aa8220f3ca3 --- /dev/null +++ b/backend/src/BaseBackend.Application/Services/SessionService.cs @@ -0,0 +1,21 @@ +using BaseBackend.Domain.Entities.App; +using BaseBackend.Domain.Repositories; + +namespace BaseBackend.Application.Services +{ + public class SessionService(ISessionRepository sessionRepository) + { + private readonly ISessionRepository _sessionRep = sessionRepository; + + public async Task GetUserIdBySession(string session) + { + var userSession = await _sessionRep.GetBySession(session); + if (userSession != null) + { + return userSession.UserId; + } + return null; + + } + } +} diff --git a/backend/src/BaseBackend.Application/Services/UserService.cs b/backend/src/BaseBackend.Application/Services/UserService.cs new file mode 100644 index 0000000000000000000000000000000000000000..12565c1c7618f4a9b69d8ec7faeb41d5e425c7fb --- /dev/null +++ b/backend/src/BaseBackend.Application/Services/UserService.cs @@ -0,0 +1,68 @@ +using BaseBackend.Application.DTOs; +using BaseBackend.Application.DTOs.Base; +using BaseBackend.Domain.Entities.App; +using BaseBackend.Domain.Repositories; + +namespace BaseBackend.Application.Services +{ + public class UserService(IUserRepository userRepository) + { + private readonly IUserRepository _userRep = userRepository; + + + public async Task GetUserById(Guid id) + { + return BaseResultDTO.Success(await _userRep.GetByIdAsync(id)); + + } + public async Task GetAllUsers() + { + return BaseResultDTO.Success(await _userRep.GetAllAsync()); + } + public async Task GetUserByAccount(string account) + { + return await _userRep.GetByAccountAsync(account); + } + public async Task UpdateUser(UserUpdateDTO update) + { + var user = await _userRep.GetByIdAsync(update.UserId); + if (user != null) + { + bool allClear = true; + if (update.Name != null) + { + if (!user.SetNewName(update.Name)) + { + allClear = false; + } + } + if (update.Phone.HasValue && update.Phone != 0) + { + if (!user.SetNewPhone(update.Phone)) + { + allClear = false; + } + } + if (allClear) + { + return BaseResultDTO.Success(await _userRep.UpdateAsync(user)); + } + else + { + return BaseResultDTO.Fail("修改的数据有误"); + } + } + return BaseResultDTO.Fail("用户不存在"); + + } + public async Task DeleteUser(Guid userId) + { + var result = await _userRep.DeleteAsync(userId); + if (result != null) + { + return BaseResultDTO.Success(result); + } + return BaseResultDTO.Fail("用户不存在"); + } + } +} diff --git a/backend/src/BaseBackend.Domain/Entities/App/AppPremission.cs b/backend/src/BaseBackend.Domain/Entities/App/AppPremission.cs new file mode 100644 index 0000000000000000000000000000000000000000..62b3cb0531ab0cd8d13fa32c9667efdd87367f0f --- /dev/null +++ b/backend/src/BaseBackend.Domain/Entities/App/AppPremission.cs @@ -0,0 +1,13 @@ +namespace BaseBackend.Domain.Entities.App +{ + public class AppPremission : BaseEntity + { + public string Name { get; private set; } = null!; + public bool IsEnabled { get; private set; } = true; + + public static AppPremission Create(string name) + { + return new() { Name = name }; + } + } +} diff --git a/backend/src/BaseBackend.Domain/Entities/App/AppRole.cs b/backend/src/BaseBackend.Domain/Entities/App/AppRole.cs new file mode 100644 index 0000000000000000000000000000000000000000..95cfb8ad54065097cb2f204cc5403700144206bd --- /dev/null +++ b/backend/src/BaseBackend.Domain/Entities/App/AppRole.cs @@ -0,0 +1,13 @@ +namespace BaseBackend.Domain.Entities.App +{ + public class AppRole() : BaseEntity + { + public string Name { get; private set; } = null!; + public bool IsEnabled { get; private set; } = true; + + public static AppRole Create(string name) + { + return new() { Name = name }; + } + } +} diff --git a/backend/src/BaseBackend.Domain/Entities/App/AppUser.cs b/backend/src/BaseBackend.Domain/Entities/App/AppUser.cs index 36243bccefddb4a5860f3535fb9ab5299c7cdb9e..fa79976805be7ea99fa343086a1617ff6e2a3247 100644 --- a/backend/src/BaseBackend.Domain/Entities/App/AppUser.cs +++ b/backend/src/BaseBackend.Domain/Entities/App/AppUser.cs @@ -6,15 +6,36 @@ namespace BaseBackend.Domain.Entities.App public string Name { get; private set; } = null!; public string HashedPassword { get; private set; } = null!; public string Salt { get; private set; } = null!; + public long Phone { get; private set; } + public static AppUser Create(string account, string name, string hashedPassword, string salt) { return new() { Account = account, Name = name, HashedPassword = hashedPassword, Salt = salt }; } - public void SetPassword(string hashedPassword, string salt) + public void SetNewPassword(string hashedPassword, string salt) { this.HashedPassword = hashedPassword; this.Salt = salt; } + public bool SetNewName(string name) + { + name = name.Trim(); + if (name != null && name != "" && name.Length > 3 && name.Length < 33) + { + this.Name = name; + return true; + } + return false; + } + public bool SetNewPhone(long? phone) + { + if (phone.HasValue && phone >= 13000000000 && 20000000000 > phone) + { + this.Phone = (long)phone; + return true; + } + return false; + } } } \ No newline at end of file diff --git a/backend/src/BaseBackend.Domain/Entities/App/RolePremission.cs b/backend/src/BaseBackend.Domain/Entities/App/RolePremission.cs new file mode 100644 index 0000000000000000000000000000000000000000..1a96af7815832ab932079941052d3b81007de689 --- /dev/null +++ b/backend/src/BaseBackend.Domain/Entities/App/RolePremission.cs @@ -0,0 +1,13 @@ +namespace BaseBackend.Domain.Entities.App +{ + public class RolePremission : BaseEntity + { + public Guid RoleId { get; private set; } + public Guid PremissionId { get; private set; } + + public static RolePremission Create(Guid RoleId, Guid PremissionId) + { + return new() { RoleId = RoleId, PremissionId = PremissionId }; + } + } +} \ No newline at end of file diff --git a/backend/src/BaseBackend.Domain/Entities/App/UserRole.cs b/backend/src/BaseBackend.Domain/Entities/App/UserRole.cs new file mode 100644 index 0000000000000000000000000000000000000000..aa80f8f010fe63811933201c2c98a3fa549e99b4 --- /dev/null +++ b/backend/src/BaseBackend.Domain/Entities/App/UserRole.cs @@ -0,0 +1,13 @@ +namespace BaseBackend.Domain.Entities.App +{ + public class UserRole : BaseEntity + { + public Guid UserId { get; private set; } + public Guid RoleId { get; private set; } + + public static UserRole Create(Guid userId, Guid roleId) + { + return new() { UserId = userId, RoleId = roleId }; + } + } +} diff --git a/backend/src/BaseBackend.Domain/Entities/App/UserSession.cs b/backend/src/BaseBackend.Domain/Entities/App/UserSession.cs new file mode 100644 index 0000000000000000000000000000000000000000..b49cf2dcefdf309f62bd8d78f4f42b0944583aa9 --- /dev/null +++ b/backend/src/BaseBackend.Domain/Entities/App/UserSession.cs @@ -0,0 +1,16 @@ + + +namespace BaseBackend.Domain.Entities.App +{ + public class UserSession() : BaseEntity + { + public Guid UserId { get; private set; } + public string Session { get; private set; } = null!; + public DateTime ExpirTime { get; private set; } = DateTime.UtcNow.AddDays(1); + + public static UserSession Create(Guid userId, string session) + { + return new UserSession { UserId = userId, Session = session }; + } + } +} diff --git a/backend/src/BaseBackend.Domain/Entities/BaseEntity.cs b/backend/src/BaseBackend.Domain/Entities/BaseEntity.cs index 1aebfed67f862f1ba33c77a0380596e7d1156b75..6144662dc6fb0415f4bf7346c9bc0949c8fa656b 100644 --- a/backend/src/BaseBackend.Domain/Entities/BaseEntity.cs +++ b/backend/src/BaseBackend.Domain/Entities/BaseEntity.cs @@ -3,12 +3,12 @@ public class BaseEntity { public Guid Id { get; private set; } = Guid.NewGuid(); - public DateTime CreateTime { get; private set; } = DateTime.Now; - public DateTime UpdateTime { get; private set; } = DateTime.Now; + public DateTime CreateTime { get; private set; } = DateTime.UtcNow; // 改为 UTC + public DateTime UpdateTime { get; private set; } = DateTime.UtcNow; // 改为 UTC public void SetUpdateTime() { - this.UpdateTime = DateTime.Now; + this.UpdateTime = DateTime.UtcNow; // 改为 UTC } } } diff --git a/backend/src/BaseBackend.Domain/Repositories/IPremissionRepository.cs b/backend/src/BaseBackend.Domain/Repositories/IPremissionRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..19f6e9ec250361f06e7d989887e5fe6cf706a259 --- /dev/null +++ b/backend/src/BaseBackend.Domain/Repositories/IPremissionRepository.cs @@ -0,0 +1,9 @@ +using BaseBackend.Domain.Entities.App; + +namespace BaseBackend.Domain.Repositories +{ + public interface IPremissionRepository:IRepository + { + public Task GetByNameAsync(string name); + } +} diff --git a/backend/src/BaseBackend.Domain/Repositories/IRepository.cs b/backend/src/BaseBackend.Domain/Repositories/IRepository.cs index cd7521f6821b0c952863bc85d0dd01c7c103942c..2610b6e294806870be192c3752d270a8a51dfcb6 100644 --- a/backend/src/BaseBackend.Domain/Repositories/IRepository.cs +++ b/backend/src/BaseBackend.Domain/Repositories/IRepository.cs @@ -9,5 +9,6 @@ namespace BaseBackend.Domain.Repositories public Task AddAsync(T entity); public Task UpdateAsync(T entity); public Task DeleteAsync(Guid id); + public Task DeleteAsync(T entity); } } diff --git a/backend/src/BaseBackend.Domain/Repositories/IRolePremissionRepository.cs b/backend/src/BaseBackend.Domain/Repositories/IRolePremissionRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..351747578f2105ccbc03887fc3a40502fda93a65 --- /dev/null +++ b/backend/src/BaseBackend.Domain/Repositories/IRolePremissionRepository.cs @@ -0,0 +1,13 @@ +using BaseBackend.Domain.Entities.App; + +namespace BaseBackend.Domain.Repositories +{ + public interface IRolePremissionRepository : IRepository + { + public Task> GetPremissionListByRoleId(Guid roleId); + public Task> GetRoleListByPremissionId(Guid premissionId); + public Task> DeleteByPremissionId(Guid premissionId); + + public Task GetByPremissionIdAndRoleId(Guid premissionId, Guid roleId); + } +} diff --git a/backend/src/BaseBackend.Domain/Repositories/ISessionRepository.cs b/backend/src/BaseBackend.Domain/Repositories/ISessionRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..adbe62fc507323794db8050244f4ac4d56c6d5c2 --- /dev/null +++ b/backend/src/BaseBackend.Domain/Repositories/ISessionRepository.cs @@ -0,0 +1,10 @@ + +using BaseBackend.Domain.Entities.App; + +namespace BaseBackend.Domain.Repositories +{ + public interface ISessionRepository : IRepository + { + public Task GetBySession(string session); + } +} diff --git a/backend/src/BaseBackend.Domain/Repositories/IUserRoleRepository.cs b/backend/src/BaseBackend.Domain/Repositories/IUserRoleRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..9831a68850f9295baf82926770369c19e20f7e6c --- /dev/null +++ b/backend/src/BaseBackend.Domain/Repositories/IUserRoleRepository.cs @@ -0,0 +1,12 @@ +using BaseBackend.Domain.Entities.App; + +namespace BaseBackend.Domain.Repositories +{ + public interface IUserRoleRepository : IRepository + { + public Task GetByRoleIdAndUserId(Guid roleId, Guid userId); + public Task> GetRoleListByUserId(Guid userId); + public Task> GetUserListByRoleId(Guid roleId); + public Task> DeleteByRoleId(Guid roleId); + } +} \ No newline at end of file diff --git a/backend/src/BaseBackend.Infrastructure/Common/PasswordHasher.cs b/backend/src/BaseBackend.Infrastructure/Common/PasswordHasher.cs index 3421f2640297d78ba804ac9d309cbc73ce62673a..fb9185f414ec33ec2cabd6392a30efb8f52455b9 100644 --- a/backend/src/BaseBackend.Infrastructure/Common/PasswordHasher.cs +++ b/backend/src/BaseBackend.Infrastructure/Common/PasswordHasher.cs @@ -6,12 +6,12 @@ namespace BaseBackend.Infrastructure.Common { internal class PasswordHasher : BasePasswordHasher { - private string? GeneratePassword(string password, string salt) + private string GeneratePassword(string password, string salt) { - var hashedPassword = SHA256.HashData(Encoding.UTF8.GetBytes(password + salt)); - return hashedPassword.ToString(); + var hashedBytes = SHA256.HashData(Encoding.UTF8.GetBytes(password + salt)); + return Convert.ToHexString(hashedBytes).ToLower(); } - public override (string? hashedPassword, string salt) CreatePassword(string password) + public override (string hashedPassword, string salt) CreatePassword(string password) { var salt = GetSalt(6); return (GeneratePassword(password, salt), salt); diff --git a/backend/src/BaseBackend.Infrastructure/Data/AppDbContext.cs b/backend/src/BaseBackend.Infrastructure/Data/AppDbContext.cs index 269b5a3453957d09732e040290fd390239b396c3..dbfa059e1e19b65e70e38900ab29825c7205f75a 100644 --- a/backend/src/BaseBackend.Infrastructure/Data/AppDbContext.cs +++ b/backend/src/BaseBackend.Infrastructure/Data/AppDbContext.cs @@ -6,6 +6,16 @@ namespace BaseBackend.Infrastructure.Data { public class AppDbContext(DbContextOptions options) : DbContext(options) { - public DbSet Users { get; set; } + public DbSet AppUsers { get; set; } + public DbSet UserSessions { get; set; } + public DbSet UserRoles { get; set; } + public DbSet AppRoles { get; set; } + public DbSet RolePremissions { get; set; } + public DbSet AppPremissions { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + + } } } \ No newline at end of file diff --git a/backend/src/BaseBackend.Infrastructure/Repositories/EfRepository.cs b/backend/src/BaseBackend.Infrastructure/Repositories/EfRepository.cs index b486c78475ee32845c1e5f2316bd9ac08b35c51d..e497b9a29910fd7adc441f55ff57c3b303451915 100644 --- a/backend/src/BaseBackend.Infrastructure/Repositories/EfRepository.cs +++ b/backend/src/BaseBackend.Infrastructure/Repositories/EfRepository.cs @@ -1,6 +1,4 @@ - - -using BaseBackend.Domain.Entities; +using BaseBackend.Domain.Entities; using BaseBackend.Domain.Repositories; using BaseBackend.Infrastructure.Data; using Microsoft.EntityFrameworkCore; @@ -46,6 +44,16 @@ namespace BaseBackend.Infrastructure.Repositories return entity; } + public async Task DeleteAsync(T entity) + { + if (entity != null) + { + _dbSet.Remove(entity); + await db.SaveChangesAsync(); + } + return entity; + } + } } diff --git a/backend/src/BaseBackend.Infrastructure/Repositories/PremissionRepository.cs b/backend/src/BaseBackend.Infrastructure/Repositories/PremissionRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..931243dba3d54d755d8a1e29656c787decddb957 --- /dev/null +++ b/backend/src/BaseBackend.Infrastructure/Repositories/PremissionRepository.cs @@ -0,0 +1,15 @@ +using BaseBackend.Domain.Entities.App; +using BaseBackend.Domain.Repositories; +using BaseBackend.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; + +namespace BaseBackend.Infrastructure.Repositories +{ + public class PremissionRepository(AppDbContext db) : EfRepository(db), IPremissionRepository + { + public async Task GetByNameAsync(string name) + { + return await _dbSet.FirstOrDefaultAsync(p => p.Name == name); + } + } +} diff --git a/backend/src/BaseBackend.Infrastructure/Repositories/RolePremissionRepository.cs b/backend/src/BaseBackend.Infrastructure/Repositories/RolePremissionRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..77b650621f6f7aa6b468ba87f6fa44fe5ddc8da3 --- /dev/null +++ b/backend/src/BaseBackend.Infrastructure/Repositories/RolePremissionRepository.cs @@ -0,0 +1,36 @@ +using BaseBackend.Domain.Entities.App; +using BaseBackend.Domain.Repositories; +using BaseBackend.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; + +namespace BaseBackend.Infrastructure.Repositories +{ + public class RolePremissionRepository(AppDbContext db) : EfRepository(db), IRolePremissionRepository + { + public async Task> DeleteByPremissionId(Guid premissionId) + { + var delData = _dbSet.Where(rp => rp.PremissionId == premissionId); + await delData.ExecuteDeleteAsync(); + return await delData.ToListAsync(); + } + + public async Task GetByPremissionIdAndRoleId(Guid premissionId, Guid roleId) + { + return await _dbSet.FirstOrDefaultAsync(rp => rp.PremissionId == premissionId && rp.RoleId == roleId); + } + + public async Task> GetPremissionListByRoleId(Guid roleId) + { + List result = []; + await _dbSet.Where(rp => rp.RoleId == roleId).ForEachAsync(rp => result.Add(rp.PremissionId)); + return result; + } + + public async Task> GetRoleListByPremissionId(Guid premissionId) + { + List result = []; + await _dbSet.Where(rp => rp.PremissionId == premissionId).ForEachAsync(rp => result.Add(rp.RoleId)); + return result; + } + } +} diff --git a/backend/src/BaseBackend.Infrastructure/Repositories/SessionRepository.cs b/backend/src/BaseBackend.Infrastructure/Repositories/SessionRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..cc05b65df6f7140467d1530c64401c13714e76b3 --- /dev/null +++ b/backend/src/BaseBackend.Infrastructure/Repositories/SessionRepository.cs @@ -0,0 +1,16 @@ + +using BaseBackend.Domain.Entities.App; +using BaseBackend.Domain.Repositories; +using BaseBackend.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; + +namespace BaseBackend.Infrastructure.Repositories +{ + internal class SessionRepository(AppDbContext db) : EfRepository(db), ISessionRepository + { + public async Task GetBySession(string session) + { + return await _dbSet.FirstOrDefaultAsync(s => s.Session == session); + } + } +} diff --git a/backend/src/BaseBackend.Infrastructure/Repositories/UserRoleRepository.cs b/backend/src/BaseBackend.Infrastructure/Repositories/UserRoleRepository.cs new file mode 100644 index 0000000000000000000000000000000000000000..61f2550d0f7447f93f1c9e7233fce99c1dce0665 --- /dev/null +++ b/backend/src/BaseBackend.Infrastructure/Repositories/UserRoleRepository.cs @@ -0,0 +1,37 @@ +using BaseBackend.Domain.Entities.App; +using BaseBackend.Domain.Repositories; +using BaseBackend.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; + +namespace BaseBackend.Infrastructure.Repositories +{ + public class UserRoleRepository(AppDbContext db) : EfRepository(db), IUserRoleRepository + { + + + public async Task> GetRoleListByUserId(Guid userId) + { + List result = []; + await _dbSet.Where(ur => ur.UserId == userId).ForEachAsync(ur => result.Add(ur.RoleId)); + return result; + } + + public async Task> GetUserListByRoleId(Guid roleId) + { + List result = []; + await _dbSet.Where(ur => ur.RoleId == roleId).ForEachAsync(ur => result.Add(ur.UserId)); + return result; + } + public async Task> DeleteByRoleId(Guid roleId) + { + var delData = _dbSet.Where(ur => ur.RoleId == roleId); + await delData.ExecuteDeleteAsync(); + return await delData.ToListAsync(); + } + + public async Task GetByRoleIdAndUserId(Guid roleId, Guid userId) + { + return await _dbSet.FirstOrDefaultAsync(ur => ur.RoleId == roleId && ur.UserId == userId); + } + } +} diff --git a/backend/src/BaseBackend.Infrastructure/ServiceCollectionExtensions.cs b/backend/src/BaseBackend.Infrastructure/ServiceCollectionExtensions.cs index 1934ad156d38f9bcf7b6545e31200c2cbab89430..b0430da98bdbf86b6987338f8cdb010f6fe22bdf 100644 --- a/backend/src/BaseBackend.Infrastructure/ServiceCollectionExtensions.cs +++ b/backend/src/BaseBackend.Infrastructure/ServiceCollectionExtensions.cs @@ -1,16 +1,34 @@ +using BaseBackend.Application.Common.Interfaces; +using BaseBackend.Domain.Repositories; +using BaseBackend.Infrastructure.Common; +using BaseBackend.Infrastructure.Data; +using BaseBackend.Infrastructure.Repositories; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -namespace BaseBackend.Infrastructure; +namespace BaseBackend.Infrastructure { public static class ServiceCollectionExtensions { - public static IServiceCollection AddInfrastructure(this IServiceCollection services,IConfiguration configuration) + public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration) { //数据库注册上下文到容器 services.AddDbContext(options => - options.UseSqlServer(configuration.GetConnectionString("DefaultConnection"))); + options.UseNpgsql(configuration.GetConnectionString("DefaultConnection"))); + + //仓储接口 + services.AddScoped(typeof(IRepository<>), typeof(EfRepository<>)); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + + + + //其余 + services.AddScoped(); return services; } } diff --git a/backend/src/BaseBackend.Infrastructure/ServiceProviderExtensions.cs b/backend/src/BaseBackend.Infrastructure/ServiceProviderExtensions.cs new file mode 100644 index 0000000000000000000000000000000000000000..a29a9ede163ee88033a4a37955bc95f03958197a --- /dev/null +++ b/backend/src/BaseBackend.Infrastructure/ServiceProviderExtensions.cs @@ -0,0 +1,139 @@ +using BaseBackend.Domain.Entities.App; +using BaseBackend.Infrastructure.Common; +using BaseBackend.Infrastructure.Data; +using Microsoft.Extensions.DependencyInjection; + +namespace BaseBackend.Infrastructure +{ + public static class ServiceProviderExtensions + { + public static async Task CheckDatabase(this IServiceProvider services) + { + // ====== 新增:数据库初始化和插入动态数据 ====== + using (var scope = services.CreateScope()) + { + var db = scope.ServiceProvider.GetRequiredService(); + // 如果数据库不存在则创建 + db.Database.EnsureCreated(); + + // 检查是否已有用户数据,没有则插入 + if (!db.AppUsers.Any() && !db.AppRoles.Any() && !db.AppPremissions.Any()) + { + // 添加权限初始数据 + var premission_getAll = AppPremission.Create("premission.getAll"); + var premission_getByRoleId = AppPremission.Create("premission.getByRoleId"); + var premission_add = AppPremission.Create("premission.add"); + var premission_assign = AppPremission.Create("premission.assign"); + var premission_delete = AppPremission.Create("premission.delete"); + var premission_unassign = AppPremission.Create("premission.unassign"); + var user_getAll = AppPremission.Create("user.getAll"); + var user_getById = AppPremission.Create("user.getById"); + var user_update = AppPremission.Create("user.update"); + var user_delete = AppPremission.Create("user.delete"); + var role_getAll = AppPremission.Create("role.getAll"); + var role_getByUserId = AppPremission.Create("role.getByUserId"); + var role_add = AppPremission.Create("role.add"); + var role_assign = AppPremission.Create("role.assign"); + var role_delete = AppPremission.Create("role.delete"); + var role_unassign = AppPremission.Create("role.unassign"); + + var premissions = new List { + premission_getAll, + premission_getByRoleId, + premission_add, + premission_assign, + premission_delete, + premission_unassign, + user_getAll, + user_getById, + user_update, + user_delete, + role_getAll, + role_getByUserId, + role_add, + role_assign, + role_delete, + role_unassign + }; + await db.AppPremissions.AddRangeAsync(premissions); + + // 添加角色初始数据 + var super_admin = AppRole.Create("超级管理员"); + var admin = AppRole.Create("管理员"); + var user = AppRole.Create("用户"); + + var roles = new List { super_admin, admin, user }; + await db.AppRoles.AddRangeAsync(roles); + + // 添加用户初始数据 + var password = new PasswordHasher().CreatePassword("rootroot"); + var root = AppUser.Create("root", "超级管理员", password.hashedPassword, password.salt); + await db.AppUsers.AddAsync(root); + + //添加角色权限关联数据 + var rolePremissions = new List { + //超级管理员 + RolePremission.Create(super_admin.Id, premission_getAll.Id), + RolePremission.Create(super_admin.Id, premission_getByRoleId.Id), + RolePremission.Create(super_admin.Id, premission_add.Id), + RolePremission.Create(super_admin.Id, premission_assign.Id), + RolePremission.Create(super_admin.Id, premission_delete.Id), + RolePremission.Create(super_admin.Id, premission_unassign.Id), + RolePremission.Create(super_admin.Id, user_getAll.Id), + RolePremission.Create(super_admin.Id, user_getById.Id), + RolePremission.Create(super_admin.Id, user_update.Id), + RolePremission.Create(super_admin.Id, user_delete.Id), + RolePremission.Create(super_admin.Id, role_getAll.Id), + RolePremission.Create(super_admin.Id, role_getByUserId.Id), + RolePremission.Create(super_admin.Id, role_add.Id), + RolePremission.Create(super_admin.Id, role_assign.Id), + RolePremission.Create(super_admin.Id, role_delete.Id), + RolePremission.Create(super_admin.Id, role_unassign.Id), + //管理员 + RolePremission.Create(admin.Id, premission_getAll.Id), + RolePremission.Create(admin.Id, premission_getByRoleId.Id), + RolePremission.Create(admin.Id, premission_add.Id), + RolePremission.Create(admin.Id, premission_assign.Id), + //RolePremission.Create(admin.Id, premission_delete.Id), + RolePremission.Create(admin.Id, premission_unassign.Id), + RolePremission.Create(admin.Id, user_getAll.Id), + RolePremission.Create(admin.Id, user_getById.Id), + RolePremission.Create(admin.Id, user_update.Id), + //RolePremission.Create(admin.Id, user_delete.Id), + RolePremission.Create(admin.Id, role_getAll.Id), + RolePremission.Create(admin.Id, role_getByUserId.Id), + RolePremission.Create(admin.Id, role_add.Id), + RolePremission.Create(admin.Id, role_assign.Id), + //RolePremission.Create(admin.Id, role_delete.Id), + RolePremission.Create(admin.Id, role_unassign.Id), + //用户 + RolePremission.Create(user.Id, premission_getAll.Id), + RolePremission.Create(user.Id, premission_getByRoleId.Id), + //RolePremission.Create(user.Id, premission_add.Id), + //RolePremission.Create(user.Id, premission_assign.Id), + //RolePremission.Create(user.Id, premission_delete.Id), + //RolePremission.Create(user.Id, premission_unassign.Id), + RolePremission.Create(user.Id, user_getAll.Id), + RolePremission.Create(user.Id, user_getById.Id), + RolePremission.Create(user.Id, user_update.Id), + //RolePremission.Create(user.Id, user_delete.Id), + RolePremission.Create(user.Id, role_getAll.Id), + RolePremission.Create(user.Id, role_getByUserId.Id) + //RolePremission.Create(user.Id, role_add.Id), + //RolePremission.Create(user.Id, role_assign.Id), + //RolePremission.Create(user.Id, role_delete.Id), + //RolePremission.Create(user.Id, role_unassign.Id) + }; + await db.RolePremissions.AddRangeAsync(rolePremissions); + + //添加用户角色关联数据 + await db.UserRoles.AddAsync(UserRole.Create(root.Id, super_admin.Id)); + + await db.SaveChangesAsync(); + } + } + // ====== 新增结束 ====== + return services; + } + } +} \ No newline at end of file diff --git a/frontend/UserManage/.editorconfig b/frontend/UserManage/.editorconfig new file mode 100644 index 0000000000000000000000000000000000000000..5a5809dbeff9763e5efeafee09134dcd5f1ce8c3 --- /dev/null +++ b/frontend/UserManage/.editorconfig @@ -0,0 +1,9 @@ +[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue,css,scss,sass,less,styl}] +charset = utf-8 +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +end_of_line = lf +max_line_length = 100 diff --git a/frontend/UserManage/.gitattributes b/frontend/UserManage/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..6313b56c57848efce05faa7aa7e901ccfc2886ea --- /dev/null +++ b/frontend/UserManage/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/frontend/UserManage/.gitignore b/frontend/UserManage/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..8ee54e8d343e466a213c8c30aa04be77126b170d --- /dev/null +++ b/frontend/UserManage/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/frontend/UserManage/.prettierrc.json b/frontend/UserManage/.prettierrc.json new file mode 100644 index 0000000000000000000000000000000000000000..29a2402ef050746efe041b9e3393bf33796407c3 --- /dev/null +++ b/frontend/UserManage/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "semi": false, + "singleQuote": true, + "printWidth": 100 +} diff --git a/frontend/UserManage/README.md b/frontend/UserManage/README.md new file mode 100644 index 0000000000000000000000000000000000000000..00833db31c106eb89db05870a0d9025187e6d115 --- /dev/null +++ b/frontend/UserManage/README.md @@ -0,0 +1,35 @@ +# UserManage + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur). + +## Customize configuration + +See [Vite Configuration Reference](https://vite.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Lint with [ESLint](https://eslint.org/) + +```sh +pnpm lint +``` diff --git a/frontend/UserManage/eslint.config.js b/frontend/UserManage/eslint.config.js new file mode 100644 index 0000000000000000000000000000000000000000..7807d8b33d25d86a60b25349e940aa9ae59c3d2e --- /dev/null +++ b/frontend/UserManage/eslint.config.js @@ -0,0 +1,26 @@ +import { defineConfig, globalIgnores } from 'eslint/config' +import globals from 'globals' +import js from '@eslint/js' +import pluginVue from 'eslint-plugin-vue' +import skipFormatting from '@vue/eslint-config-prettier/skip-formatting' + +export default defineConfig([ + { + name: 'app/files-to-lint', + files: ['**/*.{js,mjs,jsx,vue}'], + }, + + globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']), + + { + languageOptions: { + globals: { + ...globals.browser, + }, + }, + }, + + js.configs.recommended, + ...pluginVue.configs['flat/essential'], + skipFormatting, +]) diff --git a/frontend/UserManage/index.html b/frontend/UserManage/index.html new file mode 100644 index 0000000000000000000000000000000000000000..07cc89d13c4dbf229f2122c5a907793742b0bec9 --- /dev/null +++ b/frontend/UserManage/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/frontend/UserManage/jsconfig.json b/frontend/UserManage/jsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..5a1f2d222a302a174e710614c6d76531b7bda926 --- /dev/null +++ b/frontend/UserManage/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/frontend/UserManage/package.json b/frontend/UserManage/package.json new file mode 100644 index 0000000000000000000000000000000000000000..99316e426ad20c3a66d2d73c9600a4445ee56fcb --- /dev/null +++ b/frontend/UserManage/package.json @@ -0,0 +1,34 @@ +{ + "name": "usermanages", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "pnpm vite", + "build": "vite build", + "preview": "vite preview", + "lint": "eslint . --fix", + "format": "prettier --write src/" + }, + "dependencies": { + "@element-plus/icons-vue": "^2.3.1", + "axios": "^1.11.0", + "echarts": "^5.6.0", + "element-plus": "^2.10.4", + "pinia": "^3.0.3", + "vue": "^3.5.17", + "vue-echarts": "^7.0.3", + "vue-router": "^4.5.1" + }, + "devDependencies": { + "@eslint/js": "^9.29.0", + "@vitejs/plugin-vue": "^5.0.0", + "@vue/eslint-config-prettier": "^10.2.0", + "eslint": "^9.29.0", + "eslint-plugin-vue": "~10.2.0", + "globals": "^16.2.0", + "prettier": "3.5.3", + "vite": "^7.0.0", + "vite-plugin-vue-devtools": "^7.7.7" + } +} diff --git a/frontend/UserManage/pnpm-lock.yaml b/frontend/UserManage/pnpm-lock.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4f4b0d40c3c4b9ea69a3401736e7007246e125e6 --- /dev/null +++ b/frontend/UserManage/pnpm-lock.yaml @@ -0,0 +1,3029 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@element-plus/icons-vue': + specifier: ^2.3.1 + version: 2.3.1(vue@3.5.18) + axios: + specifier: ^1.11.0 + version: 1.11.0 + echarts: + specifier: ^5.6.0 + version: 5.6.0 + element-plus: + specifier: ^2.10.4 + version: 2.10.4(vue@3.5.18) + pinia: + specifier: ^3.0.3 + version: 3.0.3(vue@3.5.18) + vue: + specifier: ^3.5.17 + version: 3.5.18 + vue-echarts: + specifier: ^7.0.3 + version: 7.0.3(@vue/runtime-core@3.5.18)(echarts@5.6.0)(vue@3.5.18) + vue-router: + specifier: ^4.5.1 + version: 4.5.1(vue@3.5.18) + devDependencies: + '@eslint/js': + specifier: ^9.29.0 + version: 9.31.0 + '@vitejs/plugin-vue': + specifier: ^5.0.0 + version: 5.2.4(vite@7.0.6)(vue@3.5.18) + '@vue/eslint-config-prettier': + specifier: ^10.2.0 + version: 10.2.0(eslint@9.31.0)(prettier@3.5.3) + eslint: + specifier: ^9.29.0 + version: 9.31.0 + eslint-plugin-vue: + specifier: ~10.2.0 + version: 10.2.0(eslint@9.31.0)(vue-eslint-parser@10.2.0(eslint@9.31.0)) + globals: + specifier: ^16.2.0 + version: 16.3.0 + prettier: + specifier: 3.5.3 + version: 3.5.3 + vite: + specifier: ^7.0.0 + version: 7.0.6 + vite-plugin-vue-devtools: + specifier: ^7.7.7 + version: 7.7.7(rollup@4.45.1)(vite@7.0.6)(vue@3.5.18) + +packages: + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@antfu/utils@0.7.10': + resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==} + + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.28.0': + resolution: {integrity: sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.28.0': + resolution: {integrity: sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.28.0': + resolution: {integrity: sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.27.3': + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.27.2': + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.27.1': + resolution: {integrity: sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-member-expression-to-functions@7.27.1': + resolution: {integrity: sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.27.3': + resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.27.1': + resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.27.1': + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-replace-supers@7.27.1': + resolution: {integrity: sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.27.1': + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.28.2': + resolution: {integrity: sha512-/V9771t+EgXz62aCcyofnQhGM8DQACbRhvzKFsXKC9QM+5MadF8ZmIm0crDMaz3+o0h0zXfJnd4EhbYbxsrcFw==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.28.0': + resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-proposal-decorators@7.28.0': + resolution: {integrity: sha512-zOiZqvANjWDUaUS9xMxbMcK/Zccztbe/6ikvUXaG9nsPH3w6qh5UaPGAnirI/WhIbZ8m3OHU0ReyPrknG+ZKeg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-decorators@7.27.1': + resolution: {integrity: sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.27.1': + resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.27.1': + resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.27.1': + resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.28.0': + resolution: {integrity: sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.28.0': + resolution: {integrity: sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.28.2': + resolution: {integrity: sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==} + engines: {node: '>=6.9.0'} + + '@ctrl/tinycolor@3.6.1': + resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} + engines: {node: '>=10'} + + '@element-plus/icons-vue@2.3.1': + resolution: {integrity: sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==} + peerDependencies: + vue: ^3.2.0 + + '@esbuild/aix-ppc64@0.25.8': + resolution: {integrity: sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.8': + resolution: {integrity: sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.8': + resolution: {integrity: sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.8': + resolution: {integrity: sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.8': + resolution: {integrity: sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.8': + resolution: {integrity: sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.8': + resolution: {integrity: sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.8': + resolution: {integrity: sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.8': + resolution: {integrity: sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.8': + resolution: {integrity: sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.8': + resolution: {integrity: sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.8': + resolution: {integrity: sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.8': + resolution: {integrity: sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.8': + resolution: {integrity: sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.8': + resolution: {integrity: sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.8': + resolution: {integrity: sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.8': + resolution: {integrity: sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.8': + resolution: {integrity: sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.8': + resolution: {integrity: sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.8': + resolution: {integrity: sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.8': + resolution: {integrity: sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.25.8': + resolution: {integrity: sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.8': + resolution: {integrity: sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.8': + resolution: {integrity: sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.8': + resolution: {integrity: sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.8': + resolution: {integrity: sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.7.0': + resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.21.0': + resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.3.0': + resolution: {integrity: sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.15.1': + resolution: {integrity: sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.31.0': + resolution: {integrity: sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.3.4': + resolution: {integrity: sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@floating-ui/core@1.7.2': + resolution: {integrity: sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw==} + + '@floating-ui/dom@1.7.2': + resolution: {integrity: sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA==} + + '@floating-ui/utils@0.2.10': + resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@jridgewell/gen-mapping@0.3.12': + resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.4': + resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==} + + '@jridgewell/trace-mapping@0.3.29': + resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==} + + '@pkgr/core@0.2.9': + resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + + '@rollup/pluginutils@5.2.0': + resolution: {integrity: sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.45.1': + resolution: {integrity: sha512-NEySIFvMY0ZQO+utJkgoMiCAjMrGvnbDLHvcmlA33UXJpYBCvlBEbMMtV837uCkS+plG2umfhn0T5mMAxGrlRA==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.45.1': + resolution: {integrity: sha512-ujQ+sMXJkg4LRJaYreaVx7Z/VMgBBd89wGS4qMrdtfUFZ+TSY5Rs9asgjitLwzeIbhwdEhyj29zhst3L1lKsRQ==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.45.1': + resolution: {integrity: sha512-FSncqHvqTm3lC6Y13xncsdOYfxGSLnP+73k815EfNmpewPs+EyM49haPS105Rh4aF5mJKywk9X0ogzLXZzN9lA==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.45.1': + resolution: {integrity: sha512-2/vVn/husP5XI7Fsf/RlhDaQJ7x9zjvC81anIVbr4b/f0xtSmXQTFcGIQ/B1cXIYM6h2nAhJkdMHTnD7OtQ9Og==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.45.1': + resolution: {integrity: sha512-4g1kaDxQItZsrkVTdYQ0bxu4ZIQ32cotoQbmsAnW1jAE4XCMbcBPDirX5fyUzdhVCKgPcrwWuucI8yrVRBw2+g==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.45.1': + resolution: {integrity: sha512-L/6JsfiL74i3uK1Ti2ZFSNsp5NMiM4/kbbGEcOCps99aZx3g8SJMO1/9Y0n/qKlWZfn6sScf98lEOUe2mBvW9A==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.45.1': + resolution: {integrity: sha512-RkdOTu2jK7brlu+ZwjMIZfdV2sSYHK2qR08FUWcIoqJC2eywHbXr0L8T/pONFwkGukQqERDheaGTeedG+rra6Q==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.45.1': + resolution: {integrity: sha512-3kJ8pgfBt6CIIr1o+HQA7OZ9mp/zDk3ctekGl9qn/pRBgrRgfwiffaUmqioUGN9hv0OHv2gxmvdKOkARCtRb8Q==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.45.1': + resolution: {integrity: sha512-k3dOKCfIVixWjG7OXTCOmDfJj3vbdhN0QYEqB+OuGArOChek22hn7Uy5A/gTDNAcCy5v2YcXRJ/Qcnm4/ma1xw==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.45.1': + resolution: {integrity: sha512-PmI1vxQetnM58ZmDFl9/Uk2lpBBby6B6rF4muJc65uZbxCs0EA7hhKCk2PKlmZKuyVSHAyIw3+/SiuMLxKxWog==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loongarch64-gnu@4.45.1': + resolution: {integrity: sha512-9UmI0VzGmNJ28ibHW2GpE2nF0PBQqsyiS4kcJ5vK+wuwGnV5RlqdczVocDSUfGX/Na7/XINRVoUgJyFIgipoRg==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.45.1': + resolution: {integrity: sha512-7nR2KY8oEOUTD3pBAxIBBbZr0U7U+R9HDTPNy+5nVVHDXI4ikYniH1oxQz9VoB5PbBU1CZuDGHkLJkd3zLMWsg==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.45.1': + resolution: {integrity: sha512-nlcl3jgUultKROfZijKjRQLUu9Ma0PeNv/VFHkZiKbXTBQXhpytS8CIj5/NfBeECZtY2FJQubm6ltIxm/ftxpw==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.45.1': + resolution: {integrity: sha512-HJV65KLS51rW0VY6rvZkiieiBnurSzpzore1bMKAhunQiECPuxsROvyeaot/tcK3A3aGnI+qTHqisrpSgQrpgA==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.45.1': + resolution: {integrity: sha512-NITBOCv3Qqc6hhwFt7jLV78VEO/il4YcBzoMGGNxznLgRQf43VQDae0aAzKiBeEPIxnDrACiMgbqjuihx08OOw==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.45.1': + resolution: {integrity: sha512-+E/lYl6qu1zqgPEnTrs4WysQtvc/Sh4fC2nByfFExqgYrqkKWp1tWIbe+ELhixnenSpBbLXNi6vbEEJ8M7fiHw==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.45.1': + resolution: {integrity: sha512-a6WIAp89p3kpNoYStITT9RbTbTnqarU7D8N8F2CV+4Cl9fwCOZraLVuVFvlpsW0SbIiYtEnhCZBPLoNdRkjQFw==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.45.1': + resolution: {integrity: sha512-T5Bi/NS3fQiJeYdGvRpTAP5P02kqSOpqiopwhj0uaXB6nzs5JVi2XMJb18JUSKhCOX8+UE1UKQufyD6Or48dJg==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.45.1': + resolution: {integrity: sha512-lxV2Pako3ujjuUe9jiU3/s7KSrDfH6IgTSQOnDWr9aJ92YsFd7EurmClK0ly/t8dzMkDtd04g60WX6yl0sGfdw==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.45.1': + resolution: {integrity: sha512-M/fKi4sasCdM8i0aWJjCSFm2qEnYRR8AMLG2kxp6wD13+tMGA4Z1tVAuHkNRjud5SW2EM3naLuK35w9twvf6aA==} + cpu: [x64] + os: [win32] + + '@sec-ant/readable-stream@0.4.1': + resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + + '@sindresorhus/merge-streams@4.0.0': + resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} + engines: {node: '>=18'} + + '@sxzz/popperjs-es@2.11.7': + resolution: {integrity: sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/lodash-es@4.17.12': + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + + '@types/lodash@4.17.20': + resolution: {integrity: sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==} + + '@types/web-bluetooth@0.0.16': + resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==} + + '@vitejs/plugin-vue@5.2.4': + resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 + vue: ^3.2.25 + + '@vue/babel-helper-vue-transform-on@1.4.0': + resolution: {integrity: sha512-mCokbouEQ/ocRce/FpKCRItGo+013tHg7tixg3DUNS+6bmIchPt66012kBMm476vyEIJPafrvOf4E5OYj3shSw==} + + '@vue/babel-plugin-jsx@1.4.0': + resolution: {integrity: sha512-9zAHmwgMWlaN6qRKdrg1uKsBKHvnUU+Py+MOCTuYZBoZsopa90Di10QRjB+YPnVss0BZbG/H5XFwJY1fTxJWhA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + peerDependenciesMeta: + '@babel/core': + optional: true + + '@vue/babel-plugin-resolve-type@1.4.0': + resolution: {integrity: sha512-4xqDRRbQQEWHQyjlYSgZsWj44KfiF6D+ktCuXyZ8EnVDYV3pztmXJDf1HveAjUAXxAnR8daCQT51RneWWxtTyQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@vue/compiler-core@3.5.18': + resolution: {integrity: sha512-3slwjQrrV1TO8MoXgy3aynDQ7lslj5UqDxuHnrzHtpON5CBinhWjJETciPngpin/T3OuW3tXUf86tEurusnztw==} + + '@vue/compiler-dom@3.5.18': + resolution: {integrity: sha512-RMbU6NTU70++B1JyVJbNbeFkK+A+Q7y9XKE2EM4NLGm2WFR8x9MbAtWxPPLdm0wUkuZv9trpwfSlL6tjdIa1+A==} + + '@vue/compiler-sfc@3.5.18': + resolution: {integrity: sha512-5aBjvGqsWs+MoxswZPoTB9nSDb3dhd1x30xrrltKujlCxo48j8HGDNj3QPhF4VIS0VQDUrA1xUfp2hEa+FNyXA==} + + '@vue/compiler-ssr@3.5.18': + resolution: {integrity: sha512-xM16Ak7rSWHkM3m22NlmcdIM+K4BMyFARAfV9hYFl+SFuRzrZ3uGMNW05kA5pmeMa0X9X963Kgou7ufdbpOP9g==} + + '@vue/devtools-api@6.6.4': + resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==} + + '@vue/devtools-api@7.7.7': + resolution: {integrity: sha512-lwOnNBH2e7x1fIIbVT7yF5D+YWhqELm55/4ZKf45R9T8r9dE2AIOy8HKjfqzGsoTHFbWbr337O4E0A0QADnjBg==} + + '@vue/devtools-core@7.7.7': + resolution: {integrity: sha512-9z9TLbfC+AjAi1PQyWX+OErjIaJmdFlbDHcD+cAMYKY6Bh5VlsAtCeGyRMrXwIlMEQPukvnWt3gZBLwTAIMKzQ==} + peerDependencies: + vue: ^3.0.0 + + '@vue/devtools-kit@7.7.7': + resolution: {integrity: sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA==} + + '@vue/devtools-shared@7.7.7': + resolution: {integrity: sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw==} + + '@vue/eslint-config-prettier@10.2.0': + resolution: {integrity: sha512-GL3YBLwv/+b86yHcNNfPJxOTtVFJ4Mbc9UU3zR+KVoG7SwGTjPT+32fXamscNumElhcpXW3mT0DgzS9w32S7Bw==} + peerDependencies: + eslint: '>= 8.21.0' + prettier: '>= 3.0.0' + + '@vue/reactivity@3.5.18': + resolution: {integrity: sha512-x0vPO5Imw+3sChLM5Y+B6G1zPjwdOri9e8V21NnTnlEvkxatHEH5B5KEAJcjuzQ7BsjGrKtfzuQ5eQwXh8HXBg==} + + '@vue/runtime-core@3.5.18': + resolution: {integrity: sha512-DUpHa1HpeOQEt6+3nheUfqVXRog2kivkXHUhoqJiKR33SO4x+a5uNOMkV487WPerQkL0vUuRvq/7JhRgLW3S+w==} + + '@vue/runtime-dom@3.5.18': + resolution: {integrity: sha512-YwDj71iV05j4RnzZnZtGaXwPoUWeRsqinblgVJwR8XTXYZ9D5PbahHQgsbmzUvCWNF6x7siQ89HgnX5eWkr3mw==} + + '@vue/server-renderer@3.5.18': + resolution: {integrity: sha512-PvIHLUoWgSbDG7zLHqSqaCoZvHi6NNmfVFOqO+OnwvqMz/tqQr3FuGWS8ufluNddk7ZLBJYMrjcw1c6XzR12mA==} + peerDependencies: + vue: 3.5.18 + + '@vue/shared@3.5.18': + resolution: {integrity: sha512-cZy8Dq+uuIXbxCZpuLd2GJdeSO/lIzIspC2WtkqIpje5QyFbvLaI5wZtdUjLHjGZrlVX6GilejatWwVYYRc8tA==} + + '@vueuse/core@9.13.0': + resolution: {integrity: sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==} + + '@vueuse/metadata@9.13.0': + resolution: {integrity: sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==} + + '@vueuse/shared@9.13.0': + resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + async-validator@4.2.5: + resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + axios@1.11.0: + resolution: {integrity: sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + birpc@2.5.0: + resolution: {integrity: sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + + browserslist@4.25.1: + resolution: {integrity: sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + caniuse-lite@1.0.30001727: + resolution: {integrity: sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + copy-anything@3.0.5: + resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} + engines: {node: '>=12.13'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + default-browser-id@5.0.0: + resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} + engines: {node: '>=18'} + + default-browser@5.2.1: + resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} + engines: {node: '>=18'} + + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + echarts@5.6.0: + resolution: {integrity: sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==} + + electron-to-chromium@1.5.190: + resolution: {integrity: sha512-k4McmnB2091YIsdCgkS0fMVMPOJgxl93ltFzaryXqwip1AaxeDqKCGLxkXODDA5Ab/D+tV5EL5+aTx76RvLRxw==} + + element-plus@2.10.4: + resolution: {integrity: sha512-UD4elWHrCnp1xlPhbXmVcaKFLCRaRAY6WWRwemGfGW3ceIjXm9fSYc9RNH3AiOEA6Ds1p9ZvhCs76CR9J8Vd+A==} + peerDependencies: + vue: ^3.2.0 + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + error-stack-parser-es@0.1.5: + resolution: {integrity: sha512-xHku1X40RO+fO8yJ8Wh2f2rZWVjqyhb1zgq1yZ8aZRQkv6OOKhKWRUaht3eSCUbAOBaKIgM+ykwFLE+QUxgGeg==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + esbuild@0.25.8: + resolution: {integrity: sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-config-prettier@10.1.8: + resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-plugin-prettier@5.5.3: + resolution: {integrity: sha512-NAdMYww51ehKfDyDhv59/eIItUVzU0Io9H2E8nHNGKEeeqlnci+1gCvrHib6EmZdf6GxF+LCV5K7UC65Ezvw7w==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0' + prettier: '>=3.0.0' + peerDependenciesMeta: + '@types/eslint': + optional: true + eslint-config-prettier: + optional: true + + eslint-plugin-vue@10.2.0: + resolution: {integrity: sha512-tl9s+KN3z0hN2b8fV2xSs5ytGl7Esk1oSCxULLwFcdaElhZ8btYYZFrWxvh4En+czrSDtuLCeCOGa8HhEZuBdQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + vue-eslint-parser: ^10.0.0 + + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.31.0: + resolution: {integrity: sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + execa@9.6.0: + resolution: {integrity: sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw==} + engines: {node: ^18.19.0 || >=20.5.0} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fdir@6.4.6: + resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + figures@6.1.0: + resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} + engines: {node: '>=18'} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@4.0.4: + resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} + engines: {node: '>= 6'} + + fs-extra@11.3.0: + resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==} + engines: {node: '>=14.14'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stream@9.0.1: + resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} + engines: {node: '>=18'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@16.3.0: + resolution: {integrity: sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==} + engines: {node: '>=18'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hookable@5.5.3: + resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + + human-signals@8.0.1: + resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==} + engines: {node: '>=18.18.0'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-stream@4.0.1: + resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} + engines: {node: '>=18'} + + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + + is-what@4.1.16: + resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} + engines: {node: '>=12.13'} + + is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + + lodash-unified@1.0.3: + resolution: {integrity: sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==} + peerDependencies: + '@types/lodash-es': '*' + lodash: '*' + lodash-es: '*' + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + memoize-one@6.0.0: + resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanoid@5.1.5: + resolution: {integrity: sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==} + engines: {node: ^18 || >=20} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + + normalize-wheel-es@1.2.0: + resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==} + + npm-run-path@6.0.0: + resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==} + engines: {node: '>=18'} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + open@10.2.0: + resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==} + engines: {node: '>=18'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-ms@4.0.0: + resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} + engines: {node: '>=18'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + pinia@3.0.3: + resolution: {integrity: sha512-ttXO/InUULUXkMHpTdp9Fj4hLpD/2AoJdmAbAeW2yu1iy1k+pkFekQXw5VpC0/5p51IOR/jDaDRfRWRnMMsGOA==} + peerDependencies: + typescript: '>=4.4.4' + vue: ^2.7.0 || ^3.5.11 + peerDependenciesMeta: + typescript: + optional: true + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + + prettier@3.5.3: + resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} + engines: {node: '>=14'} + hasBin: true + + pretty-ms@9.2.0: + resolution: {integrity: sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==} + engines: {node: '>=18'} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + + rollup@4.45.1: + resolution: {integrity: sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-applescript@7.0.0: + resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} + engines: {node: '>=18'} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.2: + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + engines: {node: '>=10'} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + sirv@3.0.1: + resolution: {integrity: sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==} + engines: {node: '>=18'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + speakingurl@14.0.1: + resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} + engines: {node: '>=0.10.0'} + + strip-final-newline@4.0.0: + resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} + engines: {node: '>=18'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + superjson@2.2.2: + resolution: {integrity: sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==} + engines: {node: '>=16'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + synckit@0.11.11: + resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==} + engines: {node: ^14.18.0 || >=16.0.0} + + tinyglobby@0.2.14: + resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} + engines: {node: '>=12.0.0'} + + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + + tslib@2.3.0: + resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + unicorn-magic@0.3.0: + resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} + engines: {node: '>=18'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vite-hot-client@2.1.0: + resolution: {integrity: sha512-7SpgZmU7R+dDnSmvXE1mfDtnHLHQSisdySVR7lO8ceAXvM0otZeuQQ6C8LrS5d/aYyP/QZ0hI0L+dIPrm4YlFQ==} + peerDependencies: + vite: ^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 + + vite-plugin-inspect@0.8.9: + resolution: {integrity: sha512-22/8qn+LYonzibb1VeFZmISdVao5kC22jmEKm24vfFE8siEn47EpVcCLYMv6iKOYMJfjSvSJfueOwcFCkUnV3A==} + engines: {node: '>=14'} + peerDependencies: + '@nuxt/kit': '*' + vite: ^3.1.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.1 + peerDependenciesMeta: + '@nuxt/kit': + optional: true + + vite-plugin-vue-devtools@7.7.7: + resolution: {integrity: sha512-d0fIh3wRcgSlr4Vz7bAk4va1MkdqhQgj9ANE/rBhsAjOnRfTLs2ocjFMvSUOsv6SRRXU9G+VM7yMgqDb6yI4iQ==} + engines: {node: '>=v14.21.3'} + peerDependencies: + vite: ^3.1.0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 + + vite-plugin-vue-inspector@5.3.2: + resolution: {integrity: sha512-YvEKooQcSiBTAs0DoYLfefNja9bLgkFM7NI2b07bE2SruuvX0MEa9cMaxjKVMkeCp5Nz9FRIdcN1rOdFVBeL6Q==} + peerDependencies: + vite: ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 + + vite@7.0.6: + resolution: {integrity: sha512-MHFiOENNBd+Bd9uvc8GEsIzdkn1JxMmEeYX35tI3fv0sJBUTfW5tQsoaOwuY4KhBI09A3dUJ/DXf2yxPVPUceg==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vue-demi@0.13.11: + resolution: {integrity: sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==} + engines: {node: '>=12'} + hasBin: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + + vue-demi@0.14.10: + resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} + engines: {node: '>=12'} + hasBin: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + + vue-echarts@7.0.3: + resolution: {integrity: sha512-/jSxNwOsw5+dYAUcwSfkLwKPuzTQ0Cepz1LxCOpj2QcHrrmUa/Ql0eQqMmc1rTPQVrh2JQ29n2dhq75ZcHvRDw==} + peerDependencies: + '@vue/runtime-core': ^3.0.0 + echarts: ^5.5.1 + vue: ^2.7.0 || ^3.1.1 + peerDependenciesMeta: + '@vue/runtime-core': + optional: true + + vue-eslint-parser@10.2.0: + resolution: {integrity: sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + + vue-router@4.5.1: + resolution: {integrity: sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==} + peerDependencies: + vue: ^3.2.0 + + vue@3.5.18: + resolution: {integrity: sha512-7W4Y4ZbMiQ3SEo+m9lnoNpV9xG7QVMLa+/0RFwwiAVkeYoyGXqWE85jabU4pllJNUzqfLShJ5YLptewhCWUgNA==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wsl-utils@0.1.0: + resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==} + engines: {node: '>=18'} + + xml-name-validator@4.0.0: + resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} + engines: {node: '>=12'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yoctocolors@2.1.1: + resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==} + engines: {node: '>=18'} + + zrender@5.6.1: + resolution: {integrity: sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==} + +snapshots: + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + + '@antfu/utils@0.7.10': {} + + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.28.0': {} + + '@babel/core@7.28.0': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.0 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) + '@babel/helpers': 7.28.2 + '@babel/parser': 7.28.0 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.2 + convert-source-map: 2.0.0 + debug: 4.4.1 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.28.0': + dependencies: + '@babel/parser': 7.28.0 + '@babel/types': 7.28.2 + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.27.3': + dependencies: + '@babel/types': 7.28.2 + + '@babel/helper-compilation-targets@7.27.2': + dependencies: + '@babel/compat-data': 7.28.0 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.25.1 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-member-expression-to-functions': 7.27.1 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.0) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/traverse': 7.28.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-member-expression-to-functions@7.27.1': + dependencies: + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.2 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.27.1': + dependencies: + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.2 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.27.3(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.27.1': + dependencies: + '@babel/types': 7.28.2 + + '@babel/helper-plugin-utils@7.27.1': {} + + '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-member-expression-to-functions': 7.27.1 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + dependencies: + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.2 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.27.1': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helpers@7.28.2': + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.28.2 + + '@babel/parser@7.28.0': + dependencies: + '@babel/types': 7.28.2 + + '@babel/plugin-proposal-decorators@7.28.0(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-syntax-decorators': 7.27.1(@babel/core@7.28.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-syntax-decorators@7.27.1(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-typescript@7.28.0(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.0) + transitivePeerDependencies: + - supports-color + + '@babel/template@7.27.2': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.28.0 + '@babel/types': 7.28.2 + + '@babel/traverse@7.28.0': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.0 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.0 + '@babel/template': 7.27.2 + '@babel/types': 7.28.2 + debug: 4.4.1 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.28.2': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + + '@ctrl/tinycolor@3.6.1': {} + + '@element-plus/icons-vue@2.3.1(vue@3.5.18)': + dependencies: + vue: 3.5.18 + + '@esbuild/aix-ppc64@0.25.8': + optional: true + + '@esbuild/android-arm64@0.25.8': + optional: true + + '@esbuild/android-arm@0.25.8': + optional: true + + '@esbuild/android-x64@0.25.8': + optional: true + + '@esbuild/darwin-arm64@0.25.8': + optional: true + + '@esbuild/darwin-x64@0.25.8': + optional: true + + '@esbuild/freebsd-arm64@0.25.8': + optional: true + + '@esbuild/freebsd-x64@0.25.8': + optional: true + + '@esbuild/linux-arm64@0.25.8': + optional: true + + '@esbuild/linux-arm@0.25.8': + optional: true + + '@esbuild/linux-ia32@0.25.8': + optional: true + + '@esbuild/linux-loong64@0.25.8': + optional: true + + '@esbuild/linux-mips64el@0.25.8': + optional: true + + '@esbuild/linux-ppc64@0.25.8': + optional: true + + '@esbuild/linux-riscv64@0.25.8': + optional: true + + '@esbuild/linux-s390x@0.25.8': + optional: true + + '@esbuild/linux-x64@0.25.8': + optional: true + + '@esbuild/netbsd-arm64@0.25.8': + optional: true + + '@esbuild/netbsd-x64@0.25.8': + optional: true + + '@esbuild/openbsd-arm64@0.25.8': + optional: true + + '@esbuild/openbsd-x64@0.25.8': + optional: true + + '@esbuild/openharmony-arm64@0.25.8': + optional: true + + '@esbuild/sunos-x64@0.25.8': + optional: true + + '@esbuild/win32-arm64@0.25.8': + optional: true + + '@esbuild/win32-ia32@0.25.8': + optional: true + + '@esbuild/win32-x64@0.25.8': + optional: true + + '@eslint-community/eslint-utils@4.7.0(eslint@9.31.0)': + dependencies: + eslint: 9.31.0 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/config-array@0.21.0': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.1 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.3.0': {} + + '@eslint/core@0.15.1': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.1': + dependencies: + ajv: 6.12.6 + debug: 4.4.1 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.31.0': {} + + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.3.4': + dependencies: + '@eslint/core': 0.15.1 + levn: 0.4.1 + + '@floating-ui/core@1.7.2': + dependencies: + '@floating-ui/utils': 0.2.10 + + '@floating-ui/dom@1.7.2': + dependencies: + '@floating-ui/core': 1.7.2 + '@floating-ui/utils': 0.2.10 + + '@floating-ui/utils@0.2.10': {} + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.6': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.3.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@jridgewell/gen-mapping@0.3.12': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.4 + '@jridgewell/trace-mapping': 0.3.29 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.4': {} + + '@jridgewell/trace-mapping@0.3.29': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.4 + + '@pkgr/core@0.2.9': {} + + '@polka/url@1.0.0-next.29': {} + + '@rollup/pluginutils@5.2.0(rollup@4.45.1)': + dependencies: + '@types/estree': 1.0.8 + estree-walker: 2.0.2 + picomatch: 4.0.3 + optionalDependencies: + rollup: 4.45.1 + + '@rollup/rollup-android-arm-eabi@4.45.1': + optional: true + + '@rollup/rollup-android-arm64@4.45.1': + optional: true + + '@rollup/rollup-darwin-arm64@4.45.1': + optional: true + + '@rollup/rollup-darwin-x64@4.45.1': + optional: true + + '@rollup/rollup-freebsd-arm64@4.45.1': + optional: true + + '@rollup/rollup-freebsd-x64@4.45.1': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.45.1': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.45.1': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.45.1': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.45.1': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.45.1': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.45.1': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.45.1': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.45.1': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.45.1': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.45.1': + optional: true + + '@rollup/rollup-linux-x64-musl@4.45.1': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.45.1': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.45.1': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.45.1': + optional: true + + '@sec-ant/readable-stream@0.4.1': {} + + '@sindresorhus/merge-streams@4.0.0': {} + + '@sxzz/popperjs-es@2.11.7': {} + + '@types/estree@1.0.8': {} + + '@types/json-schema@7.0.15': {} + + '@types/lodash-es@4.17.12': + dependencies: + '@types/lodash': 4.17.20 + + '@types/lodash@4.17.20': {} + + '@types/web-bluetooth@0.0.16': {} + + '@vitejs/plugin-vue@5.2.4(vite@7.0.6)(vue@3.5.18)': + dependencies: + vite: 7.0.6 + vue: 3.5.18 + + '@vue/babel-helper-vue-transform-on@1.4.0': {} + + '@vue/babel-plugin-jsx@1.4.0(@babel/core@7.28.0)': + dependencies: + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0) + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.2 + '@vue/babel-helper-vue-transform-on': 1.4.0 + '@vue/babel-plugin-resolve-type': 1.4.0(@babel/core@7.28.0) + '@vue/shared': 3.5.18 + optionalDependencies: + '@babel/core': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@vue/babel-plugin-resolve-type@1.4.0(@babel/core@7.28.0)': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/core': 7.28.0 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/parser': 7.28.0 + '@vue/compiler-sfc': 3.5.18 + transitivePeerDependencies: + - supports-color + + '@vue/compiler-core@3.5.18': + dependencies: + '@babel/parser': 7.28.0 + '@vue/shared': 3.5.18 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.18': + dependencies: + '@vue/compiler-core': 3.5.18 + '@vue/shared': 3.5.18 + + '@vue/compiler-sfc@3.5.18': + dependencies: + '@babel/parser': 7.28.0 + '@vue/compiler-core': 3.5.18 + '@vue/compiler-dom': 3.5.18 + '@vue/compiler-ssr': 3.5.18 + '@vue/shared': 3.5.18 + estree-walker: 2.0.2 + magic-string: 0.30.17 + postcss: 8.5.6 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.18': + dependencies: + '@vue/compiler-dom': 3.5.18 + '@vue/shared': 3.5.18 + + '@vue/devtools-api@6.6.4': {} + + '@vue/devtools-api@7.7.7': + dependencies: + '@vue/devtools-kit': 7.7.7 + + '@vue/devtools-core@7.7.7(vite@7.0.6)(vue@3.5.18)': + dependencies: + '@vue/devtools-kit': 7.7.7 + '@vue/devtools-shared': 7.7.7 + mitt: 3.0.1 + nanoid: 5.1.5 + pathe: 2.0.3 + vite-hot-client: 2.1.0(vite@7.0.6) + vue: 3.5.18 + transitivePeerDependencies: + - vite + + '@vue/devtools-kit@7.7.7': + dependencies: + '@vue/devtools-shared': 7.7.7 + birpc: 2.5.0 + hookable: 5.5.3 + mitt: 3.0.1 + perfect-debounce: 1.0.0 + speakingurl: 14.0.1 + superjson: 2.2.2 + + '@vue/devtools-shared@7.7.7': + dependencies: + rfdc: 1.4.1 + + '@vue/eslint-config-prettier@10.2.0(eslint@9.31.0)(prettier@3.5.3)': + dependencies: + eslint: 9.31.0 + eslint-config-prettier: 10.1.8(eslint@9.31.0) + eslint-plugin-prettier: 5.5.3(eslint-config-prettier@10.1.8(eslint@9.31.0))(eslint@9.31.0)(prettier@3.5.3) + prettier: 3.5.3 + transitivePeerDependencies: + - '@types/eslint' + + '@vue/reactivity@3.5.18': + dependencies: + '@vue/shared': 3.5.18 + + '@vue/runtime-core@3.5.18': + dependencies: + '@vue/reactivity': 3.5.18 + '@vue/shared': 3.5.18 + + '@vue/runtime-dom@3.5.18': + dependencies: + '@vue/reactivity': 3.5.18 + '@vue/runtime-core': 3.5.18 + '@vue/shared': 3.5.18 + csstype: 3.1.3 + + '@vue/server-renderer@3.5.18(vue@3.5.18)': + dependencies: + '@vue/compiler-ssr': 3.5.18 + '@vue/shared': 3.5.18 + vue: 3.5.18 + + '@vue/shared@3.5.18': {} + + '@vueuse/core@9.13.0(vue@3.5.18)': + dependencies: + '@types/web-bluetooth': 0.0.16 + '@vueuse/metadata': 9.13.0 + '@vueuse/shared': 9.13.0(vue@3.5.18) + vue-demi: 0.14.10(vue@3.5.18) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@vueuse/metadata@9.13.0': {} + + '@vueuse/shared@9.13.0(vue@3.5.18)': + dependencies: + vue-demi: 0.14.10(vue@3.5.18) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + acorn-jsx@5.3.2(acorn@8.15.0): + dependencies: + acorn: 8.15.0 + + acorn@8.15.0: {} + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + argparse@2.0.1: {} + + async-validator@4.2.5: {} + + asynckit@0.4.0: {} + + axios@1.11.0: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.4 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + balanced-match@1.0.2: {} + + birpc@2.5.0: {} + + boolbase@1.0.0: {} + + brace-expansion@1.1.12: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + browserslist@4.25.1: + dependencies: + caniuse-lite: 1.0.30001727 + electron-to-chromium: 1.5.190 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.25.1) + + bundle-name@4.1.0: + dependencies: + run-applescript: 7.0.0 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + callsites@3.1.0: {} + + caniuse-lite@1.0.30001727: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + concat-map@0.0.1: {} + + convert-source-map@2.0.0: {} + + copy-anything@3.0.5: + dependencies: + is-what: 4.1.16 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + cssesc@3.0.0: {} + + csstype@3.1.3: {} + + dayjs@1.11.13: {} + + debug@4.4.1: + dependencies: + ms: 2.1.3 + + deep-is@0.1.4: {} + + default-browser-id@5.0.0: {} + + default-browser@5.2.1: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.0 + + define-lazy-prop@3.0.0: {} + + delayed-stream@1.0.0: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + echarts@5.6.0: + dependencies: + tslib: 2.3.0 + zrender: 5.6.1 + + electron-to-chromium@1.5.190: {} + + element-plus@2.10.4(vue@3.5.18): + dependencies: + '@ctrl/tinycolor': 3.6.1 + '@element-plus/icons-vue': 2.3.1(vue@3.5.18) + '@floating-ui/dom': 1.7.2 + '@popperjs/core': '@sxzz/popperjs-es@2.11.7' + '@types/lodash': 4.17.20 + '@types/lodash-es': 4.17.12 + '@vueuse/core': 9.13.0(vue@3.5.18) + async-validator: 4.2.5 + dayjs: 1.11.13 + escape-html: 1.0.3 + lodash: 4.17.21 + lodash-es: 4.17.21 + lodash-unified: 1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21) + memoize-one: 6.0.0 + normalize-wheel-es: 1.2.0 + vue: 3.5.18 + transitivePeerDependencies: + - '@vue/composition-api' + + entities@4.5.0: {} + + error-stack-parser-es@0.1.5: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + esbuild@0.25.8: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.8 + '@esbuild/android-arm': 0.25.8 + '@esbuild/android-arm64': 0.25.8 + '@esbuild/android-x64': 0.25.8 + '@esbuild/darwin-arm64': 0.25.8 + '@esbuild/darwin-x64': 0.25.8 + '@esbuild/freebsd-arm64': 0.25.8 + '@esbuild/freebsd-x64': 0.25.8 + '@esbuild/linux-arm': 0.25.8 + '@esbuild/linux-arm64': 0.25.8 + '@esbuild/linux-ia32': 0.25.8 + '@esbuild/linux-loong64': 0.25.8 + '@esbuild/linux-mips64el': 0.25.8 + '@esbuild/linux-ppc64': 0.25.8 + '@esbuild/linux-riscv64': 0.25.8 + '@esbuild/linux-s390x': 0.25.8 + '@esbuild/linux-x64': 0.25.8 + '@esbuild/netbsd-arm64': 0.25.8 + '@esbuild/netbsd-x64': 0.25.8 + '@esbuild/openbsd-arm64': 0.25.8 + '@esbuild/openbsd-x64': 0.25.8 + '@esbuild/openharmony-arm64': 0.25.8 + '@esbuild/sunos-x64': 0.25.8 + '@esbuild/win32-arm64': 0.25.8 + '@esbuild/win32-ia32': 0.25.8 + '@esbuild/win32-x64': 0.25.8 + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@4.0.0: {} + + eslint-config-prettier@10.1.8(eslint@9.31.0): + dependencies: + eslint: 9.31.0 + + eslint-plugin-prettier@5.5.3(eslint-config-prettier@10.1.8(eslint@9.31.0))(eslint@9.31.0)(prettier@3.5.3): + dependencies: + eslint: 9.31.0 + prettier: 3.5.3 + prettier-linter-helpers: 1.0.0 + synckit: 0.11.11 + optionalDependencies: + eslint-config-prettier: 10.1.8(eslint@9.31.0) + + eslint-plugin-vue@10.2.0(eslint@9.31.0)(vue-eslint-parser@10.2.0(eslint@9.31.0)): + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0) + eslint: 9.31.0 + natural-compare: 1.4.0 + nth-check: 2.1.1 + postcss-selector-parser: 6.1.2 + semver: 7.7.2 + vue-eslint-parser: 10.2.0(eslint@9.31.0) + xml-name-validator: 4.0.0 + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint@9.31.0: + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.21.0 + '@eslint/config-helpers': 0.3.0 + '@eslint/core': 0.15.1 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.31.0 + '@eslint/plugin-kit': 0.3.4 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.1 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + transitivePeerDependencies: + - supports-color + + espree@10.4.0: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + estree-walker@2.0.2: {} + + esutils@2.0.3: {} + + execa@9.6.0: + dependencies: + '@sindresorhus/merge-streams': 4.0.0 + cross-spawn: 7.0.6 + figures: 6.1.0 + get-stream: 9.0.1 + human-signals: 8.0.1 + is-plain-obj: 4.1.0 + is-stream: 4.0.1 + npm-run-path: 6.0.0 + pretty-ms: 9.2.0 + signal-exit: 4.1.0 + strip-final-newline: 4.0.0 + yoctocolors: 2.1.1 + + fast-deep-equal@3.1.3: {} + + fast-diff@1.3.0: {} + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fdir@6.4.6(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + figures@6.1.0: + dependencies: + is-unicode-supported: 2.1.0 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flatted@3.3.3: {} + + follow-redirects@1.15.9: {} + + form-data@4.0.4: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + fs-extra@11.3.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gensync@1.0.0-beta.2: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-stream@9.0.1: + dependencies: + '@sec-ant/readable-stream': 0.4.1 + is-stream: 4.0.1 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + globals@14.0.0: {} + + globals@16.3.0: {} + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + has-flag@4.0.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hookable@5.5.3: {} + + human-signals@8.0.1: {} + + ignore@5.3.2: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + is-docker@3.0.0: {} + + is-extglob@2.1.1: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-plain-obj@4.1.0: {} + + is-stream@4.0.1: {} + + is-unicode-supported@2.1.0: {} + + is-what@4.1.16: {} + + is-wsl@3.1.0: + dependencies: + is-inside-container: 1.0.0 + + isexe@2.0.0: {} + + js-tokens@4.0.0: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@2.2.3: {} + + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + kolorist@1.8.0: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash-es@4.17.21: {} + + lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21): + dependencies: + '@types/lodash-es': 4.17.12 + lodash: 4.17.21 + lodash-es: 4.17.21 + + lodash.merge@4.6.2: {} + + lodash@4.17.21: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.4 + + math-intrinsics@1.1.0: {} + + memoize-one@6.0.0: {} + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.12 + + mitt@3.0.1: {} + + mrmime@2.0.1: {} + + ms@2.1.3: {} + + nanoid@3.3.11: {} + + nanoid@5.1.5: {} + + natural-compare@1.4.0: {} + + node-releases@2.0.19: {} + + normalize-wheel-es@1.2.0: {} + + npm-run-path@6.0.0: + dependencies: + path-key: 4.0.0 + unicorn-magic: 0.3.0 + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + open@10.2.0: + dependencies: + default-browser: 5.2.1 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + wsl-utils: 0.1.0 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-ms@4.0.0: {} + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-key@4.0.0: {} + + pathe@2.0.3: {} + + perfect-debounce@1.0.0: {} + + picocolors@1.1.1: {} + + picomatch@4.0.3: {} + + pinia@3.0.3(vue@3.5.18): + dependencies: + '@vue/devtools-api': 7.7.7 + vue: 3.5.18 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prelude-ls@1.2.1: {} + + prettier-linter-helpers@1.0.0: + dependencies: + fast-diff: 1.3.0 + + prettier@3.5.3: {} + + pretty-ms@9.2.0: + dependencies: + parse-ms: 4.0.0 + + proxy-from-env@1.1.0: {} + + punycode@2.3.1: {} + + resolve-from@4.0.0: {} + + rfdc@1.4.1: {} + + rollup@4.45.1: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.45.1 + '@rollup/rollup-android-arm64': 4.45.1 + '@rollup/rollup-darwin-arm64': 4.45.1 + '@rollup/rollup-darwin-x64': 4.45.1 + '@rollup/rollup-freebsd-arm64': 4.45.1 + '@rollup/rollup-freebsd-x64': 4.45.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.45.1 + '@rollup/rollup-linux-arm-musleabihf': 4.45.1 + '@rollup/rollup-linux-arm64-gnu': 4.45.1 + '@rollup/rollup-linux-arm64-musl': 4.45.1 + '@rollup/rollup-linux-loongarch64-gnu': 4.45.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.45.1 + '@rollup/rollup-linux-riscv64-gnu': 4.45.1 + '@rollup/rollup-linux-riscv64-musl': 4.45.1 + '@rollup/rollup-linux-s390x-gnu': 4.45.1 + '@rollup/rollup-linux-x64-gnu': 4.45.1 + '@rollup/rollup-linux-x64-musl': 4.45.1 + '@rollup/rollup-win32-arm64-msvc': 4.45.1 + '@rollup/rollup-win32-ia32-msvc': 4.45.1 + '@rollup/rollup-win32-x64-msvc': 4.45.1 + fsevents: 2.3.3 + + run-applescript@7.0.0: {} + + semver@6.3.1: {} + + semver@7.7.2: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + signal-exit@4.1.0: {} + + sirv@3.0.1: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + + source-map-js@1.2.1: {} + + speakingurl@14.0.1: {} + + strip-final-newline@4.0.0: {} + + strip-json-comments@3.1.1: {} + + superjson@2.2.2: + dependencies: + copy-anything: 3.0.5 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + synckit@0.11.11: + dependencies: + '@pkgr/core': 0.2.9 + + tinyglobby@0.2.14: + dependencies: + fdir: 6.4.6(picomatch@4.0.3) + picomatch: 4.0.3 + + totalist@3.0.1: {} + + tslib@2.3.0: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + unicorn-magic@0.3.0: {} + + universalify@2.0.1: {} + + update-browserslist-db@1.1.3(browserslist@4.25.1): + dependencies: + browserslist: 4.25.1 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + util-deprecate@1.0.2: {} + + vite-hot-client@2.1.0(vite@7.0.6): + dependencies: + vite: 7.0.6 + + vite-plugin-inspect@0.8.9(rollup@4.45.1)(vite@7.0.6): + dependencies: + '@antfu/utils': 0.7.10 + '@rollup/pluginutils': 5.2.0(rollup@4.45.1) + debug: 4.4.1 + error-stack-parser-es: 0.1.5 + fs-extra: 11.3.0 + open: 10.2.0 + perfect-debounce: 1.0.0 + picocolors: 1.1.1 + sirv: 3.0.1 + vite: 7.0.6 + transitivePeerDependencies: + - rollup + - supports-color + + vite-plugin-vue-devtools@7.7.7(rollup@4.45.1)(vite@7.0.6)(vue@3.5.18): + dependencies: + '@vue/devtools-core': 7.7.7(vite@7.0.6)(vue@3.5.18) + '@vue/devtools-kit': 7.7.7 + '@vue/devtools-shared': 7.7.7 + execa: 9.6.0 + sirv: 3.0.1 + vite: 7.0.6 + vite-plugin-inspect: 0.8.9(rollup@4.45.1)(vite@7.0.6) + vite-plugin-vue-inspector: 5.3.2(vite@7.0.6) + transitivePeerDependencies: + - '@nuxt/kit' + - rollup + - supports-color + - vue + + vite-plugin-vue-inspector@5.3.2(vite@7.0.6): + dependencies: + '@babel/core': 7.28.0 + '@babel/plugin-proposal-decorators': 7.28.0(@babel/core@7.28.0) + '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.0) + '@babel/plugin-transform-typescript': 7.28.0(@babel/core@7.28.0) + '@vue/babel-plugin-jsx': 1.4.0(@babel/core@7.28.0) + '@vue/compiler-dom': 3.5.18 + kolorist: 1.8.0 + magic-string: 0.30.17 + vite: 7.0.6 + transitivePeerDependencies: + - supports-color + + vite@7.0.6: + dependencies: + esbuild: 0.25.8 + fdir: 6.4.6(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.45.1 + tinyglobby: 0.2.14 + optionalDependencies: + fsevents: 2.3.3 + + vue-demi@0.13.11(vue@3.5.18): + dependencies: + vue: 3.5.18 + + vue-demi@0.14.10(vue@3.5.18): + dependencies: + vue: 3.5.18 + + vue-echarts@7.0.3(@vue/runtime-core@3.5.18)(echarts@5.6.0)(vue@3.5.18): + dependencies: + echarts: 5.6.0 + vue: 3.5.18 + vue-demi: 0.13.11(vue@3.5.18) + optionalDependencies: + '@vue/runtime-core': 3.5.18 + transitivePeerDependencies: + - '@vue/composition-api' + + vue-eslint-parser@10.2.0(eslint@9.31.0): + dependencies: + debug: 4.4.1 + eslint: 9.31.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.6.0 + semver: 7.7.2 + transitivePeerDependencies: + - supports-color + + vue-router@4.5.1(vue@3.5.18): + dependencies: + '@vue/devtools-api': 6.6.4 + vue: 3.5.18 + + vue@3.5.18: + dependencies: + '@vue/compiler-dom': 3.5.18 + '@vue/compiler-sfc': 3.5.18 + '@vue/runtime-dom': 3.5.18 + '@vue/server-renderer': 3.5.18(vue@3.5.18) + '@vue/shared': 3.5.18 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + word-wrap@1.2.5: {} + + wsl-utils@0.1.0: + dependencies: + is-wsl: 3.1.0 + + xml-name-validator@4.0.0: {} + + yallist@3.1.1: {} + + yocto-queue@0.1.0: {} + + yoctocolors@2.1.1: {} + + zrender@5.6.1: + dependencies: + tslib: 2.3.0 diff --git a/frontend/UserManage/pnpm-workspace.yaml b/frontend/UserManage/pnpm-workspace.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c5739b7433373b954e38dba07a74be9b5d28c7f0 --- /dev/null +++ b/frontend/UserManage/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +ignoredBuiltDependencies: + - esbuild diff --git a/frontend/UserManage/public/favicon.ico b/frontend/UserManage/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 Binary files /dev/null and b/frontend/UserManage/public/favicon.ico differ diff --git a/frontend/UserManage/src/App.vue b/frontend/UserManage/src/App.vue new file mode 100644 index 0000000000000000000000000000000000000000..aeb2fd134a1c61c58e4e0565b01570dd21f0b33b --- /dev/null +++ b/frontend/UserManage/src/App.vue @@ -0,0 +1,73 @@ + + + + + diff --git a/frontend/UserManage/src/api/auth.js b/frontend/UserManage/src/api/auth.js new file mode 100644 index 0000000000000000000000000000000000000000..5e1a74d3e20f509bc4cfd7b199c7bc7df2501b45 --- /dev/null +++ b/frontend/UserManage/src/api/auth.js @@ -0,0 +1,33 @@ +// 认证相关API +export const authApi = { + // 登录 + async login(username, password) { + // 模拟API调用 + return new Promise((resolve, reject) => { + setTimeout(() => { + if (username && password) { + resolve({ + token: 'mock-token-' + Date.now(), + user: { username } + }); + } else { + reject(new Error('用户名或密码错误')); + } + }, 1000); + }); + }, + + // 注册 + async register(username, password, confirmPassword) { + // 模拟API调用 + return new Promise((resolve, reject) => { + setTimeout(() => { + if (username && password && password === confirmPassword) { + resolve({ message: '注册成功' }); + } else { + reject(new Error('注册失败,请检查输入信息')); + } + }, 1000); + }); + } +}; \ No newline at end of file diff --git a/frontend/UserManage/src/assets/Head.svg b/frontend/UserManage/src/assets/Head.svg new file mode 100644 index 0000000000000000000000000000000000000000..5f50ef838bb70568d49d8fe133bcf8d56eb401e8 --- /dev/null +++ b/frontend/UserManage/src/assets/Head.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/frontend/UserManage/src/assets/Mange.svg b/frontend/UserManage/src/assets/Mange.svg new file mode 100644 index 0000000000000000000000000000000000000000..4e9b2bd1c2f7c935b98605202f9b9ed053dccaf3 --- /dev/null +++ b/frontend/UserManage/src/assets/Mange.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/UserManage/src/assets/base.css b/frontend/UserManage/src/assets/base.css new file mode 100644 index 0000000000000000000000000000000000000000..8816868a41b651f318dee87c6784ebcd6e29eca1 --- /dev/null +++ b/frontend/UserManage/src/assets/base.css @@ -0,0 +1,86 @@ +/* color palette from */ +:root { + --vt-c-white: #ffffff; + --vt-c-white-soft: #f8f8f8; + --vt-c-white-mute: #f2f2f2; + + --vt-c-black: #181818; + --vt-c-black-soft: #222222; + --vt-c-black-mute: #282828; + + --vt-c-indigo: #2c3e50; + + --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); + --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); + --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); + --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); + + --vt-c-text-light-1: var(--vt-c-indigo); + --vt-c-text-light-2: rgba(60, 60, 60, 0.66); + --vt-c-text-dark-1: var(--vt-c-white); + --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); +} + +/* semantic color variables for this project */ +:root { + --color-background: var(--vt-c-white); + --color-background-soft: var(--vt-c-white-soft); + --color-background-mute: var(--vt-c-white-mute); + + --color-border: var(--vt-c-divider-light-2); + --color-border-hover: var(--vt-c-divider-light-1); + + --color-heading: var(--vt-c-text-light-1); + --color-text: var(--vt-c-text-light-1); + + --section-gap: 160px; +} + +@media (prefers-color-scheme: dark) { + :root { + --color-background: var(--vt-c-black); + --color-background-soft: var(--vt-c-black-soft); + --color-background-mute: var(--vt-c-black-mute); + + --color-border: var(--vt-c-divider-dark-2); + --color-border-hover: var(--vt-c-divider-dark-1); + + --color-heading: var(--vt-c-text-dark-1); + --color-text: var(--vt-c-text-dark-2); + } +} + +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + font-weight: normal; +} + +body { + min-height: 100vh; + color: var(--color-text); + background: var(--color-background); + transition: + color 0.5s, + background-color 0.5s; + line-height: 1.6; + font-family: + Inter, + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + Roboto, + Oxygen, + Ubuntu, + Cantarell, + 'Fira Sans', + 'Droid Sans', + 'Helvetica Neue', + sans-serif; + font-size: 15px; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} diff --git a/frontend/UserManage/src/assets/logo.svg b/frontend/UserManage/src/assets/logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..7565660356e5b3723c9c33d508b830c9cfbea29f --- /dev/null +++ b/frontend/UserManage/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/frontend/UserManage/src/assets/main.css b/frontend/UserManage/src/assets/main.css new file mode 100644 index 0000000000000000000000000000000000000000..2ae3af95665c069a9c5706b3dc6e454d4e05cbde --- /dev/null +++ b/frontend/UserManage/src/assets/main.css @@ -0,0 +1,37 @@ +@import './base.css'; + +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + font-weight: normal; +} + +a, +.green { + text-decoration: none; + color: hsla(160, 100%, 37%, 1); + transition: 0.4s; + padding: 3px; +} + +@media (hover: hover) { + a:hover { + background-color: hsla(160, 100%, 37%, 0.2); + } +} + +@media (min-width: 1024px) { + body { + display: flex; + place-items: center; + } + + #app { + width: 100vw; + min-height: 100vh; + margin: 0; + padding: 0; + box-sizing: border-box; + } +} diff --git a/frontend/UserManage/src/components/AppBreadcrumb.vue b/frontend/UserManage/src/components/AppBreadcrumb.vue new file mode 100644 index 0000000000000000000000000000000000000000..6c138e768fac35718f9ca4f5c06c93f378329851 --- /dev/null +++ b/frontend/UserManage/src/components/AppBreadcrumb.vue @@ -0,0 +1,18 @@ + + + diff --git a/frontend/UserManage/src/components/HeaderBar.vue b/frontend/UserManage/src/components/HeaderBar.vue new file mode 100644 index 0000000000000000000000000000000000000000..407aa3c20b35dd37e22fb2db2821d0b8c9d101bd --- /dev/null +++ b/frontend/UserManage/src/components/HeaderBar.vue @@ -0,0 +1,101 @@ + + + + + + + \ No newline at end of file diff --git a/frontend/UserManage/src/components/HelloWorld.vue b/frontend/UserManage/src/components/HelloWorld.vue new file mode 100644 index 0000000000000000000000000000000000000000..eff59f13c630e632c777d7bfc8ac3a10ba4f9263 --- /dev/null +++ b/frontend/UserManage/src/components/HelloWorld.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/frontend/UserManage/src/components/Sidebar.vue b/frontend/UserManage/src/components/Sidebar.vue new file mode 100644 index 0000000000000000000000000000000000000000..d1a0623896013510041a72164805452b9450cd2d --- /dev/null +++ b/frontend/UserManage/src/components/Sidebar.vue @@ -0,0 +1,87 @@ + + + + diff --git a/frontend/UserManage/src/components/TheWelcome.vue b/frontend/UserManage/src/components/TheWelcome.vue new file mode 100644 index 0000000000000000000000000000000000000000..fe48afc20626fd1457bcb3098456e8630dd4bbe7 --- /dev/null +++ b/frontend/UserManage/src/components/TheWelcome.vue @@ -0,0 +1,94 @@ + + + diff --git a/frontend/UserManage/src/components/WelcomeItem.vue b/frontend/UserManage/src/components/WelcomeItem.vue new file mode 100644 index 0000000000000000000000000000000000000000..ac366d0740bfa462d7e9f290137601a3f3139ecc --- /dev/null +++ b/frontend/UserManage/src/components/WelcomeItem.vue @@ -0,0 +1,86 @@ + + + diff --git a/frontend/UserManage/src/components/icons/IconCommunity.vue b/frontend/UserManage/src/components/icons/IconCommunity.vue new file mode 100644 index 0000000000000000000000000000000000000000..2dc8b055253af30fb797037e2fe260505f0cf711 --- /dev/null +++ b/frontend/UserManage/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/frontend/UserManage/src/components/icons/IconDocumentation.vue b/frontend/UserManage/src/components/icons/IconDocumentation.vue new file mode 100644 index 0000000000000000000000000000000000000000..6d4791cfbcf2782b3e5ffbabd042d4c47b2fbbed --- /dev/null +++ b/frontend/UserManage/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/frontend/UserManage/src/components/icons/IconEcosystem.vue b/frontend/UserManage/src/components/icons/IconEcosystem.vue new file mode 100644 index 0000000000000000000000000000000000000000..c3a4f078c0bd340a33c61ea9ecd8a755d03571ed --- /dev/null +++ b/frontend/UserManage/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/frontend/UserManage/src/components/icons/IconSupport.vue b/frontend/UserManage/src/components/icons/IconSupport.vue new file mode 100644 index 0000000000000000000000000000000000000000..7452834d3ef961ce24c3a072ddba2620b6158bae --- /dev/null +++ b/frontend/UserManage/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/frontend/UserManage/src/components/icons/IconTooling.vue b/frontend/UserManage/src/components/icons/IconTooling.vue new file mode 100644 index 0000000000000000000000000000000000000000..660598d7c76644ffe126a1a1feb1606650bfb937 --- /dev/null +++ b/frontend/UserManage/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/frontend/UserManage/src/components/icons/SearchUser.vue b/frontend/UserManage/src/components/icons/SearchUser.vue new file mode 100644 index 0000000000000000000000000000000000000000..8f14941ee2798e4e1b7d916a29e39faa680b0bc4 --- /dev/null +++ b/frontend/UserManage/src/components/icons/SearchUser.vue @@ -0,0 +1,3 @@ + diff --git a/frontend/UserManage/src/components/icons/UserHead.vue b/frontend/UserManage/src/components/icons/UserHead.vue new file mode 100644 index 0000000000000000000000000000000000000000..44120f1e3ade36c46137e0f76a4c2592f8522720 --- /dev/null +++ b/frontend/UserManage/src/components/icons/UserHead.vue @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/frontend/UserManage/src/components/icons/UserTou.vue b/frontend/UserManage/src/components/icons/UserTou.vue new file mode 100644 index 0000000000000000000000000000000000000000..b821a2ba2339698453f4f563086cf1a92bf924c4 --- /dev/null +++ b/frontend/UserManage/src/components/icons/UserTou.vue @@ -0,0 +1,4 @@ + + \ No newline at end of file diff --git a/frontend/UserManage/src/layout/LayoutMain.vue b/frontend/UserManage/src/layout/LayoutMain.vue new file mode 100644 index 0000000000000000000000000000000000000000..36ba333a6774eb86756707f3f74fee7770dc3c8d --- /dev/null +++ b/frontend/UserManage/src/layout/LayoutMain.vue @@ -0,0 +1,43 @@ + + + + diff --git a/frontend/UserManage/src/main.js b/frontend/UserManage/src/main.js new file mode 100644 index 0000000000000000000000000000000000000000..25f45aa689bdc5ec3150b08b9997d7fdee02e004 --- /dev/null +++ b/frontend/UserManage/src/main.js @@ -0,0 +1,33 @@ +import './assets/main.css' +import zhCn from 'element-plus/dist/locale/zh-cn.mjs' +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' +import ElementPlus from 'element-plus' +import 'element-plus/dist/index.css' +import ECharts from 'vue-echarts' +import { use } from 'echarts/core' +import { CanvasRenderer } from 'echarts/renderers' +import { BarChart } from 'echarts/charts' +import {createPinia} from 'pinia' +import { GridComponent, TooltipComponent } from 'echarts/components' +use([CanvasRenderer, BarChart, GridComponent, TooltipComponent]) + + +const app = createApp(App) + +const pinia = createPinia(); + + + + +app.component('el-chart', ECharts) + +app.use(router) +app.use(pinia) +// app.use(ElementPlus) +app.use(ElementPlus,{ + local:zhCn, +}) + +app.mount('#app') diff --git a/frontend/UserManage/src/router/index.js b/frontend/UserManage/src/router/index.js new file mode 100644 index 0000000000000000000000000000000000000000..a305939c236ea00da18f19901f80c37f99365368 --- /dev/null +++ b/frontend/UserManage/src/router/index.js @@ -0,0 +1,61 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' +//import Users from '../views/Users.vue' +import Files from '../views/FileManage.vue' +import Logs from '../views/Logs.vue' +import UserList from '../views/UserList.vue' +import PermissionManage from '@/views/PermissionManage.vue' +import RoleManage from '@/views/RoleManage.vue' +import LayoutMain from '@/layout/LayoutMain.vue' +const routes = [ + { + path:'/', + redirect:'/login' + }, + { + path: '/login', + name: 'Login', + component: () => import('@/views/Login.vue'), + meta: { requiresAuth: false, title: '登录' } + }, + { + path: '/', + component:LayoutMain, + children:[ + { path: ' /', redirect: '/home' }, + { path: '/home', component: HomeView }, + { path: '/users', component: UserList }, + { path: '/files', component: Files }, + { path: '/logs', component: Logs }, + {path: '/users/list', component: UserList }, + {path:'/users/permission-manage',component: PermissionManage}, + {path:'/users/role-manage',component:RoleManage} + ] + }, + { + path: '/:pathMatch(.*)*', + name: 'NotFound', + component: () => import('@/views/NotFound.vue'), + meta: { requiresAuth: false, title: '页面不存在' } + }, + +] + +const router = createRouter({ + history: createWebHistory(), + routes, +}) +// 路由守卫 +router.beforeEach((to, from, next) => { + // 设置页面标题 + document.title = to.meta.title ? `${to.meta.title} - 后台管理系统` : '后台管理系统'; + + // 简化路由守卫,只处理登录页面 + if (to.path === '/login') { + next(); + } else { + next(); + } +}); + +export default router diff --git a/frontend/UserManage/src/stores/user.js b/frontend/UserManage/src/stores/user.js new file mode 100644 index 0000000000000000000000000000000000000000..b97d156c18100fd18aa4fd8134d685f9fe8d80d1 --- /dev/null +++ b/frontend/UserManage/src/stores/user.js @@ -0,0 +1,77 @@ +import { defineStore } from 'pinia'; + +// 用户状态管理 +export const useUserStore = defineStore('user', { + state: () => ({ + // 用户信息 + userInfo: null, + // 认证令牌 + token: localStorage.getItem('token') || null, + // 加载状态 + loading: false, + // 错误信息 + error: null + }), + + getters: { + // 是否认证 + isAuthenticated: (state) => !!state.token, + + // 获取用户名 + username: (state) => state.userInfo?.username || '' + }, + + actions: { + // 登录 + async login(username, password) { + try { + this.loading = true; + this.error = null; + + // 模拟登录API调用 + await new Promise(resolve => setTimeout(resolve, 1000)); + + // 模拟登录成功 + this.token = 'mock-token-' + Date.now(); + localStorage.setItem('token', this.token); + + this.userInfo = { username }; + + return true; + } catch (error) { + this.error = error.message || '登录失败,请检查用户名和密码'; + return false; + } finally { + this.loading = false; + } + }, + + // 注册 + async register(username, password, confirmPassword) { + try { + this.loading = true; + this.error = null; + + // 模拟注册API调用 + await new Promise(resolve => setTimeout(resolve, 1000)); + + return true; + } catch (error) { + this.error = error.message || '注册失败,请检查输入信息'; + return false; + } finally { + this.loading = false; + } + }, + + // 登出 + logout() { + // 清除令牌 + this.token = null; + localStorage.removeItem('token'); + + // 清除用户信息 + this.userInfo = null; + } + } +}); \ No newline at end of file diff --git a/frontend/UserManage/src/views/AboutView.vue b/frontend/UserManage/src/views/AboutView.vue new file mode 100644 index 0000000000000000000000000000000000000000..756ad2a17909837834858538422308120cf09dab --- /dev/null +++ b/frontend/UserManage/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/frontend/UserManage/src/views/FileManage.vue b/frontend/UserManage/src/views/FileManage.vue new file mode 100644 index 0000000000000000000000000000000000000000..8ba0e692ad6b2ecbf6edd6218904716ebe905a7e --- /dev/null +++ b/frontend/UserManage/src/views/FileManage.vue @@ -0,0 +1,176 @@ + + + + + \ No newline at end of file diff --git a/frontend/UserManage/src/views/HomeView.vue b/frontend/UserManage/src/views/HomeView.vue new file mode 100644 index 0000000000000000000000000000000000000000..03fa118830b9b8cb8935a0fffd8240d06d328237 --- /dev/null +++ b/frontend/UserManage/src/views/HomeView.vue @@ -0,0 +1,184 @@ + + + + diff --git a/frontend/UserManage/src/views/Login.vue b/frontend/UserManage/src/views/Login.vue new file mode 100644 index 0000000000000000000000000000000000000000..f339211ffcde8c481679958bd435124f161f6db4 --- /dev/null +++ b/frontend/UserManage/src/views/Login.vue @@ -0,0 +1,432 @@ + + + + + + \ No newline at end of file diff --git a/frontend/UserManage/src/views/Logs.vue b/frontend/UserManage/src/views/Logs.vue new file mode 100644 index 0000000000000000000000000000000000000000..a2c6b9bd9985beae4e833399c640a3f1085c99f1 --- /dev/null +++ b/frontend/UserManage/src/views/Logs.vue @@ -0,0 +1,3 @@ + diff --git a/frontend/UserManage/src/views/NotFound.vue b/frontend/UserManage/src/views/NotFound.vue new file mode 100644 index 0000000000000000000000000000000000000000..efcd2bf790ccbc20a057d322d89ee1f471a154f3 --- /dev/null +++ b/frontend/UserManage/src/views/NotFound.vue @@ -0,0 +1,24 @@ + + + + + \ No newline at end of file diff --git a/frontend/UserManage/src/views/PermissionManage.vue b/frontend/UserManage/src/views/PermissionManage.vue new file mode 100644 index 0000000000000000000000000000000000000000..e35647b457eebf8a49415790730bc37f32840e57 --- /dev/null +++ b/frontend/UserManage/src/views/PermissionManage.vue @@ -0,0 +1,350 @@ + + + + + \ No newline at end of file diff --git a/frontend/UserManage/src/views/RoleManage.vue b/frontend/UserManage/src/views/RoleManage.vue new file mode 100644 index 0000000000000000000000000000000000000000..8be8deca4bc458286aee062696c1887dff2a2fef --- /dev/null +++ b/frontend/UserManage/src/views/RoleManage.vue @@ -0,0 +1,458 @@ + + + + + \ No newline at end of file diff --git a/frontend/UserManage/src/views/UserList.vue b/frontend/UserManage/src/views/UserList.vue new file mode 100644 index 0000000000000000000000000000000000000000..775cdec8b1b8b9af7d5b8d8e39ba9a0ababa93ed --- /dev/null +++ b/frontend/UserManage/src/views/UserList.vue @@ -0,0 +1,389 @@ + + + + + \ No newline at end of file diff --git a/frontend/UserManage/src/views/Users.vue b/frontend/UserManage/src/views/Users.vue new file mode 100644 index 0000000000000000000000000000000000000000..0d894aefd973602208b0ee823ff8b529e05cf2f8 --- /dev/null +++ b/frontend/UserManage/src/views/Users.vue @@ -0,0 +1,3 @@ + diff --git a/frontend/UserManage/vite.config.js b/frontend/UserManage/vite.config.js new file mode 100644 index 0000000000000000000000000000000000000000..4217010a3178372181948ce34c4d5045dfa18325 --- /dev/null +++ b/frontend/UserManage/vite.config.js @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueDevTools from 'vite-plugin-vue-devtools' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueDevTools(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + }, + }, +}) diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000000000000000000000000000000000000..b7c8597814333af261693cdd3d8fa63b21816641 --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "element-plus": "^2.10.4" + } +} diff --git "a/frontend/\345\211\215\347\253\257\351\241\271\347\233\256.test" "b/frontend/\345\211\215\347\253\257\351\241\271\347\233\256.test" deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000