版本260406

This commit is contained in:
2026-04-06 22:04:05 +08:00
parent 7dc5e73af7
commit 0b150470be
216 changed files with 98993 additions and 33 deletions

View File

@@ -0,0 +1,198 @@
using OrpaonVision.Core.Results;
using OrpaonVision.Model.Security;
using OrpaonVision.Model.Configuration;
namespace OrpaonVision.Core.Security;
/// <summary>
/// 机种权限服务接口。
/// </summary>
public interface IProductPermissionService
{
/// <summary>
/// 检查用户是否具有指定机种的权限。
/// </summary>
/// <param name="userId">用户ID。</param>
/// <param name="productTypeId">机种ID。</param>
/// <param name="permissionType">权限类型。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>权限检查结果。</returns>
Task<Result<bool>> CheckPermissionAsync(Guid userId, Guid productTypeId, ProductPermissionType permissionType, CancellationToken cancellationToken = default);
/// <summary>
/// 检查用户是否具有指定机种编码的权限。
/// </summary>
/// <param name="userId">用户ID。</param>
/// <param name="productTypeCode">机种编码。</param>
/// <param name="permissionType">权限类型。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>权限检查结果。</returns>
Task<Result<bool>> CheckPermissionByCodeAsync(Guid userId, string productTypeCode, ProductPermissionType permissionType, CancellationToken cancellationToken = default);
/// <summary>
/// 获取用户在指定机种的权限列表。
/// </summary>
/// <param name="userId">用户ID。</param>
/// <param name="productTypeId">机种ID。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>权限列表。</returns>
Task<Result<IReadOnlyList<ProductPermissionModel>>> GetUserPermissionsAsync(Guid userId, Guid productTypeId, CancellationToken cancellationToken = default);
/// <summary>
/// 授予用户机种权限。
/// </summary>
/// <param name="userId">用户ID。</param>
/// <param name="productTypeId">机种ID。</param>
/// <param name="permissionType">权限类型。</param>
/// <param name="expiresAtUtc">过期时间(可选)。</param>
/// <param name="remark">备注。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>授权结果。</returns>
Task<Result<ProductPermissionModel>> GrantPermissionAsync(Guid userId, Guid productTypeId, ProductPermissionType permissionType, DateTime? expiresAtUtc = null, string? remark = null, CancellationToken cancellationToken = default);
/// <summary>
/// 撤销用户机种权限。
/// </summary>
/// <param name="permissionId">权限ID。</param>
/// <param name="reason">撤销原因。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>撤销结果。</returns>
Task<Result> RevokePermissionAsync(Guid permissionId, string reason, CancellationToken cancellationToken = default);
/// <summary>
/// 检查机种是否被锁定。
/// </summary>
/// <param name="productTypeId">机种ID。</param>
/// <param name="lockType">锁定类型。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>锁定检查结果。</returns>
Task<Result<bool>> IsProductLockedAsync(Guid productTypeId, ProductLockType lockType, CancellationToken cancellationToken = default);
/// <summary>
/// 锁定机种。
/// </summary>
/// <param name="productTypeId">机种ID。</param>
/// <param name="lockType">锁定类型。</param>
/// <param name="lockReason">锁定原因。</param>
/// <param name="expectedUnlockAtUtc">预计解锁时间(可选)。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>锁定结果。</returns>
Task<Result<ProductLockRecordModel>> LockProductAsync(Guid productTypeId, ProductLockType lockType, string lockReason, DateTime? expectedUnlockAtUtc = null, CancellationToken cancellationToken = default);
/// <summary>
/// 解锁机种。
/// </summary>
/// <param name="lockRecordId">锁定记录ID。</param>
/// <param name="unlockReason">解锁原因。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>解锁结果。</returns>
Task<Result> UnlockProductAsync(Guid lockRecordId, string unlockReason, CancellationToken cancellationToken = default);
/// <summary>
/// 验证机种切换权限。
/// </summary>
/// <param name="userId">用户ID。</param>
/// <param name="sourceProductTypeId">源机种ID。</param>
/// <param name="targetProductTypeId">目标机种ID。</param>
/// <param name="isForced">是否强制切换。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>验证结果。</returns>
Task<Result<ProductSwitchValidationResult>> ValidateSwitchPermissionAsync(Guid userId, Guid? sourceProductTypeId, Guid targetProductTypeId, bool isForced = false, CancellationToken cancellationToken = default);
/// <summary>
/// 记录机种切换。
/// </summary>
/// <param name="userId">用户ID。</param>
/// <param name="userName">用户姓名。</param>
/// <param name="userRole">用户角色。</param>
/// <param name="sourceProductTypeId">源机种ID。</param>
/// <param name="targetProductTypeId">目标机种ID。</param>
/// <param name="switchType">切换类型。</param>
/// <param name="switchReason">切换原因。</param>
/// <param name="isForced">是否强制切换。</param>
/// <param name="forcedReason">强制切换原因。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>记录结果。</returns>
Task<Result<ProductSwitchRecordModel>> RecordSwitchAsync(Guid userId, string userName, string userRole, Guid? sourceProductTypeId, Guid targetProductTypeId, ProductSwitchType switchType, string switchReason, bool isForced = false, string? forcedReason = null, CancellationToken cancellationToken = default);
/// <summary>
/// 获取机种切换历史记录。
/// </summary>
/// <param name="productTypeId">机种ID可选。</param>
/// <param name="userId">用户ID可选。</param>
/// <param name="startTime">开始时间。</param>
/// <param name="endTime">结束时间。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>切换记录列表。</returns>
Task<Result<IReadOnlyList<ProductSwitchRecordModel>>> GetSwitchHistoryAsync(Guid? productTypeId = null, Guid? userId = null, DateTime? startTime = null, DateTime? endTime = null, CancellationToken cancellationToken = default);
/// <summary>
/// 获取机种锁定记录。
/// </summary>
/// <param name="productTypeId">机种ID。</param>
/// <param name="includeUnlocked">是否包含已解锁的记录。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>锁定记录列表。</returns>
Task<Result<IReadOnlyList<ProductLockRecordModel>>> GetLockRecordsAsync(Guid productTypeId, bool includeUnlocked = false, CancellationToken cancellationToken = default);
}
/// <summary>
/// 机种切换验证结果。
/// </summary>
public sealed class ProductSwitchValidationResult
{
/// <summary>
/// 是否允许切换。
/// </summary>
public bool CanSwitch { get; init; }
/// <summary>
/// 验证消息。
/// </summary>
public string Message { get; init; } = string.Empty;
/// <summary>
/// 警告信息。
/// </summary>
public List<string> Warnings { get; init; } = new();
/// <summary>
/// 错误信息。
/// </summary>
public List<string> Errors { get; init; } = new();
/// <summary>
/// 需要审批。
/// </summary>
public bool RequiresApproval { get; init; }
/// <summary>
/// 审批人列表。
/// </summary>
public List<string> Approvers { get; init; } = new();
/// <summary>
/// 源机种信息。
/// </summary>
public ProductTypeModel? SourceProduct { get; init; }
/// <summary>
/// 目标机种信息。
/// </summary>
public ProductTypeModel? TargetProduct { get; init; }
/// <summary>
/// 当前用户权限。
/// </summary>
public List<ProductPermissionType> CurrentPermissions { get; init; } = new();
/// <summary>
/// 所需权限。
/// </summary>
public List<ProductPermissionType> RequiredPermissions { get; init; } = new();
/// <summary>
/// 验证时间UTC
/// </summary>
public DateTime ValidatedAtUtc { get; init; } = DateTime.UtcNow;
}