29 changed files with 1836 additions and 4 deletions
@ -0,0 +1,15 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Data; |
||||
|
|
||||
|
namespace PackageName.CompanyName.ProjectName.AIO.EntityFrameworkCore.DataSeeder |
||||
|
{ |
||||
|
public interface IProjectNameDataSeeder |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 初始化数据
|
||||
|
/// </summary>
|
||||
|
/// <param name="context">数据种子上下文</param>
|
||||
|
/// <returns>任务</returns>
|
||||
|
Task SeedAsync(DataSeedContext context); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,503 @@ |
|||||
|
using Microsoft.Extensions.Logging; |
||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
using Volo.Abp.Guids; |
||||
|
using Volo.Abp.Identity; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using Volo.Abp.Uow; |
||||
|
using IdentityRole = Volo.Abp.Identity.IdentityRole; |
||||
|
using IdentityUser = Volo.Abp.Identity.IdentityUser; |
||||
|
|
||||
|
namespace PackageName.CompanyName.ProjectName.AIO.EntityFrameworkCore.DataSeeder |
||||
|
{ |
||||
|
public class ProjectNameDataSeederDataSeeder : IProjectNameDataSeeder, ITransientDependency |
||||
|
{ |
||||
|
private readonly ICurrentTenant _currentTenant; |
||||
|
private readonly IGuidGenerator _guidGenerator; |
||||
|
private readonly ILogger<ProjectNameDataSeeder> _logger; |
||||
|
private readonly IRepository<Org, Guid> _orgRepository; |
||||
|
private readonly IRepository<WorkUnit, Guid> _workUnitRepository; |
||||
|
private readonly IRepository<User, Guid> _userRepository; |
||||
|
private readonly IdentityUserManager _identityUserManager; |
||||
|
private readonly IdentityRoleManager _identityRoleManager; |
||||
|
private readonly IUnitOfWorkManager _unitOfWorkManager; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 构造函数
|
||||
|
/// </summary>
|
||||
|
public ProjectNameDataSeeder( |
||||
|
ICurrentTenant currentTenant, |
||||
|
IGuidGenerator guidGenerator, |
||||
|
ILogger<ProjectNameDataSeeder> logger, |
||||
|
IRepository<Org, Guid> orgRepository, |
||||
|
IRepository<WorkUnit, Guid> workUnitRepository, |
||||
|
IRepository<User, Guid> userRepository, |
||||
|
IdentityUserManager identityUserManager, |
||||
|
IdentityRoleManager identityRoleManager, |
||||
|
IUnitOfWorkManager unitOfWorkManager) |
||||
|
{ |
||||
|
_currentTenant = currentTenant; |
||||
|
_guidGenerator = guidGenerator; |
||||
|
_logger = logger; |
||||
|
_orgRepository = orgRepository; |
||||
|
_workUnitRepository = workUnitRepository; |
||||
|
_userRepository = userRepository; |
||||
|
_identityUserManager = identityUserManager; |
||||
|
_identityRoleManager = identityRoleManager; |
||||
|
_unitOfWorkManager = unitOfWorkManager; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 初始化数据
|
||||
|
/// </summary>
|
||||
|
/// <param name="context">数据种子上下文</param>
|
||||
|
/// <returns>任务</returns>
|
||||
|
public async Task SeedAsync(DataSeedContext context) |
||||
|
{ |
||||
|
using (_currentTenant.Change(context.TenantId)) |
||||
|
{ |
||||
|
_logger.LogInformation("开始初始化巡检数据..."); |
||||
|
|
||||
|
// 初始化角色
|
||||
|
using (var uow = _unitOfWorkManager.Begin(requiresNew: true)) |
||||
|
{ |
||||
|
await SeedRolesAsync(); |
||||
|
await uow.CompleteAsync(); |
||||
|
} |
||||
|
|
||||
|
// 初始化单位数据
|
||||
|
using (var uow = _unitOfWorkManager.Begin(requiresNew: true)) |
||||
|
{ |
||||
|
await SeedWorkUnitsAsync(); |
||||
|
await uow.CompleteAsync(); |
||||
|
} |
||||
|
|
||||
|
// 初始化组织数据
|
||||
|
using (var uow = _unitOfWorkManager.Begin(requiresNew: true)) |
||||
|
{ |
||||
|
await SeedOrgsAsync(); |
||||
|
await uow.CompleteAsync(); |
||||
|
} |
||||
|
|
||||
|
// 初始化用户数据
|
||||
|
using (var uow = _unitOfWorkManager.Begin(requiresNew: true)) |
||||
|
{ |
||||
|
await SeedUsersAsync(); |
||||
|
await uow.CompleteAsync(); |
||||
|
} |
||||
|
|
||||
|
_logger.LogInformation("巡检数据初始化完成"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 初始化角色数据
|
||||
|
/// </summary>
|
||||
|
private async Task SeedRolesAsync() |
||||
|
{ |
||||
|
// 超级管理员
|
||||
|
await CreateRoleIfNotExistsAsync( |
||||
|
"超级管理员", |
||||
|
"系统超级管理员,拥有所有权限"); |
||||
|
|
||||
|
// 区委办公室-督查室管理员
|
||||
|
await CreateRoleIfNotExistsAsync( |
||||
|
"区委办公室-督查室管理员", |
||||
|
"区委办公室督查室管理员"); |
||||
|
|
||||
|
// 责任领导秘书
|
||||
|
await CreateRoleIfNotExistsAsync( |
||||
|
"责任领导秘书", |
||||
|
"负责协助责任领导进行工作"); |
||||
|
|
||||
|
// 责任单位管理员
|
||||
|
await CreateRoleIfNotExistsAsync( |
||||
|
"责任单位管理员", |
||||
|
"负责管理责任单位的信息"); |
||||
|
|
||||
|
// 责任单位落实人员
|
||||
|
await CreateRoleIfNotExistsAsync( |
||||
|
"责任单位落实人员", |
||||
|
"负责执行责任单位的任务"); |
||||
|
|
||||
|
// 责任单位分管领导
|
||||
|
await CreateRoleIfNotExistsAsync( |
||||
|
"责任单位分管领导", |
||||
|
"负责管理责任单位的部分工作"); |
||||
|
|
||||
|
// 责任单位党组书记
|
||||
|
await CreateRoleIfNotExistsAsync( |
||||
|
"责任单位党组书记", |
||||
|
"负责责任单位的党组工作"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 创建角色(如果不存在)
|
||||
|
/// </summary>
|
||||
|
private async Task CreateRoleIfNotExistsAsync(string roleName, string description) |
||||
|
{ |
||||
|
if (await _identityRoleManager.FindByNameAsync(roleName) == null) |
||||
|
{ |
||||
|
var role = new IdentityRole( |
||||
|
_guidGenerator.Create(), |
||||
|
roleName, |
||||
|
_currentTenant.Id) |
||||
|
{ |
||||
|
IsStatic = true, |
||||
|
IsPublic = true |
||||
|
}; |
||||
|
|
||||
|
await _identityRoleManager.CreateAsync(role); |
||||
|
|
||||
|
_logger.LogInformation($"创建角色:{roleName}"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 初始化单位数据
|
||||
|
/// </summary>
|
||||
|
private async Task SeedWorkUnitsAsync() |
||||
|
{ |
||||
|
// 创建永川区
|
||||
|
var yongchuanDistrict = await CreateWorkUnitIfNotExistsAsync( |
||||
|
"永川区", |
||||
|
"001", |
||||
|
"001", |
||||
|
"永川区"); |
||||
|
|
||||
|
// 创建区政府
|
||||
|
var districtGovernment = await CreateWorkUnitIfNotExistsAsync( |
||||
|
"区政府", |
||||
|
"002", |
||||
|
"001.002", |
||||
|
"永川区政府", |
||||
|
yongchuanDistrict.Id); |
||||
|
|
||||
|
// 创建区委办公室
|
||||
|
var districtCommitteeOffice = await CreateWorkUnitIfNotExistsAsync( |
||||
|
"区委办公室", |
||||
|
"003", |
||||
|
"001.003", |
||||
|
"永川区委办公室", |
||||
|
yongchuanDistrict.Id); |
||||
|
|
||||
|
// 创建督查室
|
||||
|
await CreateWorkUnitIfNotExistsAsync( |
||||
|
"督查室", |
||||
|
"004", |
||||
|
"001.003.004", |
||||
|
"区委办公室督查室", |
||||
|
districtCommitteeOffice.Id); |
||||
|
|
||||
|
// 创建区委扫黑办
|
||||
|
await CreateWorkUnitIfNotExistsAsync( |
||||
|
"区委扫黑办", |
||||
|
"005", |
||||
|
"001.005", |
||||
|
"永川区委扫黑办", |
||||
|
yongchuanDistrict.Id); |
||||
|
|
||||
|
// 创建区体育局
|
||||
|
await CreateWorkUnitIfNotExistsAsync( |
||||
|
"区体育局", |
||||
|
"006", |
||||
|
"001.006", |
||||
|
"永川区体育局", |
||||
|
yongchuanDistrict.Id); |
||||
|
|
||||
|
// 创建区统计局
|
||||
|
await CreateWorkUnitIfNotExistsAsync( |
||||
|
"区统计局", |
||||
|
"007", |
||||
|
"001.007", |
||||
|
"永川区统计局", |
||||
|
yongchuanDistrict.Id); |
||||
|
|
||||
|
// 创建区信访办
|
||||
|
await CreateWorkUnitIfNotExistsAsync( |
||||
|
"区信访办", |
||||
|
"008", |
||||
|
"001.008", |
||||
|
"永川区信访办", |
||||
|
yongchuanDistrict.Id); |
||||
|
|
||||
|
// 创建区医保局
|
||||
|
await CreateWorkUnitIfNotExistsAsync( |
||||
|
"区医保局", |
||||
|
"009", |
||||
|
"001.009", |
||||
|
"永川区医保局", |
||||
|
yongchuanDistrict.Id); |
||||
|
|
||||
|
// 创建区大数据发展局
|
||||
|
await CreateWorkUnitIfNotExistsAsync( |
||||
|
"区大数据发展局", |
||||
|
"010", |
||||
|
"001.010", |
||||
|
"永川区大数据发展局", |
||||
|
yongchuanDistrict.Id); |
||||
|
|
||||
|
// 创建区机关事务局
|
||||
|
await CreateWorkUnitIfNotExistsAsync( |
||||
|
"区机关事务局", |
||||
|
"011", |
||||
|
"001.011", |
||||
|
"永川区机关事务局", |
||||
|
yongchuanDistrict.Id); |
||||
|
|
||||
|
// 创建区广播电视局
|
||||
|
await CreateWorkUnitIfNotExistsAsync( |
||||
|
"区广播电视局", |
||||
|
"012", |
||||
|
"001.012", |
||||
|
"永川区广播电视局", |
||||
|
yongchuanDistrict.Id); |
||||
|
|
||||
|
// 创建区中新项目管理局
|
||||
|
await CreateWorkUnitIfNotExistsAsync( |
||||
|
"区中新项目管理局", |
||||
|
"013", |
||||
|
"001.013", |
||||
|
"永川区中新项目管理局", |
||||
|
yongchuanDistrict.Id); |
||||
|
|
||||
|
// 创建镇街
|
||||
|
await CreateWorkUnitIfNotExistsAsync( |
||||
|
"镇街", |
||||
|
"014", |
||||
|
"001.014", |
||||
|
"永川区镇街", |
||||
|
yongchuanDistrict.Id); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 创建单位(如果不存在)
|
||||
|
/// </summary>
|
||||
|
private async Task<WorkUnit> CreateWorkUnitIfNotExistsAsync( |
||||
|
string name, |
||||
|
string code, |
||||
|
string treeCode, |
||||
|
string description, |
||||
|
Guid? parentId = null) |
||||
|
{ |
||||
|
var workUnit = await _workUnitRepository.FindAsync(w => w.Name == name); |
||||
|
|
||||
|
if (workUnit == null) |
||||
|
{ |
||||
|
workUnit = new WorkUnit( |
||||
|
_guidGenerator.Create(), |
||||
|
code, |
||||
|
treeCode, |
||||
|
name, |
||||
|
description) |
||||
|
{ |
||||
|
ParentId = parentId |
||||
|
}; |
||||
|
|
||||
|
await _workUnitRepository.InsertAsync(workUnit); |
||||
|
|
||||
|
_logger.LogInformation($"创建单位:{name}"); |
||||
|
} |
||||
|
|
||||
|
return workUnit; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 初始化组织数据
|
||||
|
/// </summary>
|
||||
|
private async Task SeedOrgsAsync() |
||||
|
{ |
||||
|
// 创建区委办公室-督查室
|
||||
|
var supervisionOffice = await CreateOrgIfNotExistsAsync( |
||||
|
"区委办公室-督查室", |
||||
|
"001", |
||||
|
"001", |
||||
|
"区委办公室督查室"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 创建组织(如果不存在)
|
||||
|
/// </summary>
|
||||
|
private async Task<Org> CreateOrgIfNotExistsAsync( |
||||
|
string name, |
||||
|
string code, |
||||
|
string treeCode, |
||||
|
string description, |
||||
|
Guid? parentId = null) |
||||
|
{ |
||||
|
var org = await _orgRepository.FindAsync(o => o.Name == name); |
||||
|
|
||||
|
if (org == null) |
||||
|
{ |
||||
|
org = new Org( |
||||
|
_guidGenerator.Create(), |
||||
|
code, |
||||
|
treeCode, |
||||
|
name, |
||||
|
description) |
||||
|
{ |
||||
|
ParentId = parentId |
||||
|
}; |
||||
|
|
||||
|
await _orgRepository.InsertAsync(org); |
||||
|
|
||||
|
_logger.LogInformation($"创建组织:{name}"); |
||||
|
} |
||||
|
|
||||
|
return org; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 初始化用户数据
|
||||
|
/// </summary>
|
||||
|
private async Task SeedUsersAsync() |
||||
|
{ |
||||
|
// 获取所需单位
|
||||
|
var supervisionOffice = await _workUnitRepository.FindAsync(w => w.Name == "督查室"); |
||||
|
if (supervisionOffice == null) |
||||
|
{ |
||||
|
_logger.LogError("未找到督查室单位,无法创建用户"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// 获取所需组织
|
||||
|
var supervisionOrg = await _orgRepository.FindAsync(o => o.Name == "区委办公室-督查室"); |
||||
|
if (supervisionOrg == null) |
||||
|
{ |
||||
|
_logger.LogError("未找到区委办公室-督查室组织,无法创建用户"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// 查找超级管理员角色
|
||||
|
var superAdminRole = await _identityRoleManager.FindByNameAsync("超级管理员"); |
||||
|
if (superAdminRole == null) |
||||
|
{ |
||||
|
_logger.LogError("未找到超级管理员角色,无法为用户分配角色"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// 创建用户数据(使用固定用户名避免生成问题)
|
||||
|
await CreateUserIfNotExistsAsync("李达康", "lidk001", GenderType.Male, supervisionOffice.Id, supervisionOrg.Id, "超级管理员"); |
||||
|
await CreateUserIfNotExistsAsync("高育良", "gyl002", GenderType.Male, supervisionOffice.Id, supervisionOrg.Id, "超级管理员"); |
||||
|
await CreateUserIfNotExistsAsync("祁同伟", "qtw003", GenderType.Male, supervisionOffice.Id, supervisionOrg.Id, "超级管理员"); |
||||
|
await CreateUserIfNotExistsAsync("侯亮平", "hlp004", GenderType.Male, supervisionOffice.Id, supervisionOrg.Id, "超级管理员"); |
||||
|
await CreateUserIfNotExistsAsync("赵瑞龙", "zrl005", GenderType.Female, supervisionOffice.Id, supervisionOrg.Id, "超级管理员"); |
||||
|
await CreateUserIfNotExistsAsync("宋梦平", "smp006", GenderType.Male, supervisionOffice.Id, supervisionOrg.Id, "超级管理员, 部门领导"); |
||||
|
await CreateUserIfNotExistsAsync("李太亮", "ltl007", GenderType.Male, supervisionOffice.Id, supervisionOrg.Id, "超级管理员, 部门领导"); |
||||
|
await CreateUserIfNotExistsAsync("高峰", "gf008", GenderType.Male, supervisionOffice.Id, supervisionOrg.Id, "超级管理员, 部门领导"); |
||||
|
await CreateUserIfNotExistsAsync("朱丽平", "zlp009", GenderType.Female, supervisionOffice.Id, supervisionOrg.Id, "超级管理员, 部门领导"); |
||||
|
await CreateUserIfNotExistsAsync("安欣", "ax010", GenderType.Male, supervisionOffice.Id, supervisionOrg.Id, "超级管理员"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 创建用户(如果不存在)
|
||||
|
/// </summary>
|
||||
|
private async Task CreateUserIfNotExistsAsync( |
||||
|
string name, |
||||
|
string userName, |
||||
|
GenderType gender, |
||||
|
Guid workUnitId, |
||||
|
Guid orgId, |
||||
|
string roles) |
||||
|
{ |
||||
|
// 检查用户是否已存在
|
||||
|
var existingUser = await _userRepository.FindAsync(u => u.NickName == name); |
||||
|
if (existingUser != null) |
||||
|
{ |
||||
|
_logger.LogInformation($"用户[{name}]已存在,跳过创建"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var identityUser = await _identityUserManager.FindByNameAsync(userName); |
||||
|
if (identityUser == null) |
||||
|
{ |
||||
|
// 创建Identity用户
|
||||
|
identityUser = new IdentityUser( |
||||
|
_guidGenerator.Create(), |
||||
|
userName, |
||||
|
$"{userName}@example.com", |
||||
|
_currentTenant.Id) |
||||
|
{ |
||||
|
Name = name, |
||||
|
Surname = "" |
||||
|
}; |
||||
|
|
||||
|
// 设置默认密码 123456
|
||||
|
var identityResult = await _identityUserManager.CreateAsync(identityUser, "123456"); |
||||
|
if (!identityResult.Succeeded) |
||||
|
{ |
||||
|
_logger.LogError($"创建Identity用户[{name}]失败: {string.Join(", ", identityResult.Errors.Select(e => e.Description))}"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// 分配角色
|
||||
|
if (!string.IsNullOrWhiteSpace(roles)) |
||||
|
{ |
||||
|
var roleNames = roles.Split(',', StringSplitOptions.RemoveEmptyEntries); |
||||
|
foreach (var roleName in roleNames) |
||||
|
{ |
||||
|
var trimmedRoleName = roleName.Trim(); |
||||
|
var role = await _identityRoleManager.FindByNameAsync(trimmedRoleName); |
||||
|
if (role != null) |
||||
|
{ |
||||
|
var roleResult = await _identityUserManager.AddToRoleAsync(identityUser, trimmedRoleName); |
||||
|
if (!roleResult.Succeeded) |
||||
|
{ |
||||
|
_logger.LogWarning($"为用户[{name}]分配角色[{trimmedRoleName}]失败: {string.Join(", ", roleResult.Errors.Select(e => e.Description))}"); |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
_logger.LogWarning($"角色[{trimmedRoleName}]不存在,无法为用户[{name}]分配"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 创建系统用户
|
||||
|
var user = new User( |
||||
|
_guidGenerator.Create(), |
||||
|
name, |
||||
|
workUnitId, |
||||
|
identityUser.Id, |
||||
|
gender) |
||||
|
{ |
||||
|
OrgId = orgId |
||||
|
}; |
||||
|
|
||||
|
// 保存用户
|
||||
|
await _userRepository.InsertAsync(user); |
||||
|
|
||||
|
_logger.LogInformation($"创建用户:{name},用户名:{userName}"); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
_logger.LogInformation($"Identity用户[{userName}]已存在,检查是否需要创建业务用户"); |
||||
|
|
||||
|
// 检查是否需要创建业务用户
|
||||
|
var businessUser = await _userRepository.FindAsync(u => u.IdentityUserId == identityUser.Id); |
||||
|
if (businessUser == null) |
||||
|
{ |
||||
|
// 创建系统用户
|
||||
|
var user = new User( |
||||
|
_guidGenerator.Create(), |
||||
|
name, |
||||
|
workUnitId, |
||||
|
identityUser.Id, |
||||
|
gender) |
||||
|
{ |
||||
|
OrgId = orgId |
||||
|
}; |
||||
|
|
||||
|
// 保存用户
|
||||
|
await _userRepository.InsertAsync(user); |
||||
|
|
||||
|
_logger.LogInformation($"为已存在的Identity用户创建业务用户:{name}"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
using System; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
|
||||
|
namespace PackageName.CompanyName.ProjectName.Users.Dtos |
||||
|
{ |
||||
|
[Serializable] |
||||
|
public class CreateUpdateUserDto |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 用户名称
|
||||
|
/// </summary>
|
||||
|
[Required(ErrorMessage = "用户名称不能为空")] |
||||
|
[StringLength(50, ErrorMessage = "用户名称长度不能超过50个字符")] |
||||
|
public string NickName { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 密码
|
||||
|
/// </summary>
|
||||
|
[StringLength(20, MinimumLength = 6, ErrorMessage = "密码长度必须在6-20个字符之间")] |
||||
|
public string Password { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 联系方式
|
||||
|
/// </summary>
|
||||
|
public string ContactInfo { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 职位
|
||||
|
/// </summary>
|
||||
|
public string Position { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 是否启用
|
||||
|
/// </summary>
|
||||
|
public bool IsActive { get; set; } = true; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace PackageName.CompanyName.ProjectName.Users.Dtos |
||||
|
{ |
||||
|
[Serializable] |
||||
|
public class UserDto : FullAuditedEntityDto<Guid> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 用户名称
|
||||
|
/// </summary>
|
||||
|
public string NickName { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Identity用户Id
|
||||
|
/// </summary>
|
||||
|
public Guid IdentityUserId { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 用户状态
|
||||
|
/// </summary>
|
||||
|
public bool IsActive { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 联系方式
|
||||
|
/// </summary>
|
||||
|
public string ContactInfo { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 职位
|
||||
|
/// </summary>
|
||||
|
public string Position { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 角色名称
|
||||
|
/// </summary>
|
||||
|
public string RoleNames { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace PackageName.CompanyName.ProjectName.Users.Dtos |
||||
|
{ |
||||
|
[Serializable] |
||||
|
public class UserItemDto : FullAuditedEntityDto<Guid> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 用户名称
|
||||
|
/// </summary>
|
||||
|
public string NickName { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Identity用户Id
|
||||
|
/// </summary>
|
||||
|
public Guid IdentityUserId { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 用户状态
|
||||
|
/// </summary>
|
||||
|
public bool IsActive { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 联系方式
|
||||
|
/// </summary>
|
||||
|
public string ContactInfo { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 职位
|
||||
|
/// </summary>
|
||||
|
public string Position { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 角色名称
|
||||
|
/// </summary>
|
||||
|
public string RoleNames { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace PackageName.CompanyName.ProjectName.Users.Dtos |
||||
|
{ |
||||
|
[Serializable] |
||||
|
public class UserPagedAndSortedResultRequestDto : PagedAndSortedResultRequestDto |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 用户名称
|
||||
|
/// </summary>
|
||||
|
public string NickName { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,55 @@ |
|||||
|
using PackageName.CompanyName.ProjectName.Users.Dtos; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
|
||||
|
namespace PackageName.CompanyName.ProjectName.Users |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 用户应用服务接口
|
||||
|
/// </summary>
|
||||
|
public interface IUserAppService : |
||||
|
IApplicationService |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 创建用户
|
||||
|
/// </summary>
|
||||
|
Task<UserDto> CreateAsync(CreateUpdateUserDto input); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 更新用户
|
||||
|
/// </summary>
|
||||
|
Task<UserDto> UpdateAsync(Guid id, CreateUpdateUserDto input); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 删除用户
|
||||
|
/// </summary>
|
||||
|
Task DeleteAsync(Guid id); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 获取用户
|
||||
|
/// </summary>
|
||||
|
Task<UserDto> GetAsync(Guid id); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 获取用户列表
|
||||
|
/// </summary>
|
||||
|
Task<PagedResultDto<UserItemDto>> GetListAsync(UserPagedAndSortedResultRequestDto input); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 修改用户密码
|
||||
|
/// </summary>
|
||||
|
Task ChangePasswordAsync(Guid id, string currentPassword, string newPassword); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 重置用户密码(管理员操作)
|
||||
|
/// </summary>
|
||||
|
Task ResetPasswordAsync(Guid id, string newPassword); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 启用或禁用用户
|
||||
|
/// </summary>
|
||||
|
Task SetUserActiveStatusAsync(Guid id, bool isActive); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,198 @@ |
|||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using PackageName.CompanyName.ProjectName.Permissions; |
||||
|
using PackageName.CompanyName.ProjectName.Users.Dtos; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Linq.Dynamic.Core; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
using Volo.Abp.Identity; |
||||
|
|
||||
|
namespace PackageName.CompanyName.ProjectName.Users |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 用户
|
||||
|
/// </summary>
|
||||
|
public class UserAppService : ApplicationService, IUserAppService |
||||
|
{ |
||||
|
private readonly IUserRepository _userRepository; |
||||
|
private readonly IUserManager _userManager; |
||||
|
private readonly IdentityUserManager _identityUserManager; |
||||
|
|
||||
|
public UserAppService( |
||||
|
IUserRepository userRepository, |
||||
|
IUserManager userManager, |
||||
|
IdentityUserManager identityUserManager) |
||||
|
{ |
||||
|
_userRepository = userRepository; |
||||
|
_userManager = userManager; |
||||
|
_identityUserManager = identityUserManager; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 创建用户
|
||||
|
/// </summary>
|
||||
|
[Authorize(ProjectNamePermissions.User.Create)] |
||||
|
public async Task<UserDto> CreateAsync(CreateUpdateUserDto input) |
||||
|
{ |
||||
|
// 参数检查和验证逻辑可以在这里添加
|
||||
|
if (string.IsNullOrEmpty(input.NickName)) |
||||
|
{ |
||||
|
throw new UserFriendlyException("昵称不能为空"); |
||||
|
} |
||||
|
if (string.IsNullOrEmpty(input.Password)) |
||||
|
{ |
||||
|
throw new UserFriendlyException("密码不能为空"); |
||||
|
} |
||||
|
|
||||
|
// 使用UserManager创建用户
|
||||
|
var user = await _userManager.CreateAsync( |
||||
|
input.NickName, |
||||
|
input.Password, |
||||
|
input.ContactInfo, |
||||
|
input.Position, |
||||
|
input.IsActive); |
||||
|
|
||||
|
// 返回DTO对象
|
||||
|
return await MapToUserDtoAsync(user); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 更新用户
|
||||
|
/// </summary>
|
||||
|
[Authorize(ProjectNamePermissions.User.Update)] |
||||
|
public async Task<UserDto> UpdateAsync(Guid id, CreateUpdateUserDto input) |
||||
|
{ |
||||
|
// 使用UserManager更新用户基本信息
|
||||
|
var user = await _userManager.UpdateAsync( |
||||
|
id, |
||||
|
input.NickName, |
||||
|
input.Password, |
||||
|
input.ContactInfo, |
||||
|
input.Position, |
||||
|
input.IsActive); |
||||
|
|
||||
|
// 返回DTO对象
|
||||
|
return await MapToUserDtoAsync(user); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 删除用户
|
||||
|
/// </summary>
|
||||
|
[Authorize(ProjectNamePermissions.User.Delete)] |
||||
|
public Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
return _userManager.DeleteAsync(id); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 获取用户
|
||||
|
/// </summary>
|
||||
|
[Authorize(ProjectNamePermissions.User.Default)] |
||||
|
public async Task<UserDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
var user = await _userManager.GetAsync(id); |
||||
|
return await MapToUserDtoAsync(user); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 获取用户列表
|
||||
|
/// </summary>
|
||||
|
[Authorize(ProjectNamePermissions.User.Default)] |
||||
|
public async Task<PagedResultDto<UserItemDto>> GetListAsync(UserPagedAndSortedResultRequestDto input) |
||||
|
{ |
||||
|
// 创建查询
|
||||
|
var query = await CreateFilteredQueryAsync(input); |
||||
|
|
||||
|
// 获取总记录数
|
||||
|
var totalCount = await AsyncExecuter.CountAsync(query); |
||||
|
|
||||
|
// 获取已排序和分页的查询结果
|
||||
|
var users = await AsyncExecuter.ToListAsync( |
||||
|
query.OrderBy(input.Sorting ?? nameof(User.NickName)) |
||||
|
.Skip(input.SkipCount) |
||||
|
.Take(input.MaxResultCount)); |
||||
|
|
||||
|
// 转换为DTO并返回
|
||||
|
var userDtos = new List<UserItemDto>(); |
||||
|
foreach (var user in users) |
||||
|
{ |
||||
|
var userDto = ObjectMapper.Map<User, UserItemDto>(user); |
||||
|
|
||||
|
// 填充角色信息
|
||||
|
if (user.IdentityUser != null) |
||||
|
{ |
||||
|
var roles = await _identityUserManager.GetRolesAsync(user.IdentityUser); |
||||
|
userDto.RoleNames = string.Join("、", roles); |
||||
|
userDto.IsActive = user.IdentityUser.LockoutEnd == null || user.IdentityUser.LockoutEnd < DateTimeOffset.Now; |
||||
|
} |
||||
|
|
||||
|
userDtos.Add(userDto); |
||||
|
} |
||||
|
|
||||
|
return new PagedResultDto<UserItemDto>(totalCount, userDtos); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 修改用户密码
|
||||
|
/// </summary>
|
||||
|
[Authorize] |
||||
|
public async Task ChangePasswordAsync(Guid id, string currentPassword, string newPassword) |
||||
|
{ |
||||
|
await _userManager.ChangePasswordAsync(id, currentPassword, newPassword); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 重置用户密码(管理员操作)
|
||||
|
/// </summary>
|
||||
|
[Authorize(ProjectNamePermissions.User.Update)] |
||||
|
public async Task ResetPasswordAsync(Guid id, string newPassword) |
||||
|
{ |
||||
|
await _userManager.ResetPasswordAsync(id, newPassword); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 启用或禁用用户
|
||||
|
/// </summary>
|
||||
|
[Authorize(ProjectNamePermissions.User.Update)] |
||||
|
public async Task SetUserActiveStatusAsync(Guid id, bool isActive) |
||||
|
{ |
||||
|
await _userManager.SetUserActiveStatusAsync(id, isActive); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 创建基础查询,应用过滤条件
|
||||
|
/// </summary>
|
||||
|
protected async virtual Task<IQueryable<User>> CreateFilteredQueryAsync( |
||||
|
UserPagedAndSortedResultRequestDto input) |
||||
|
{ |
||||
|
// 获取基础查询,并加载相关实体
|
||||
|
var query = await _userRepository.WithDetailsAsync( |
||||
|
x => x.IdentityUser); |
||||
|
|
||||
|
// 应用过滤条件
|
||||
|
return query |
||||
|
.WhereIf(!string.IsNullOrWhiteSpace(input.NickName), |
||||
|
x => x.NickName.Contains(input.NickName)); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 将User实体映射为UserDto,并填充权限信息
|
||||
|
/// </summary>
|
||||
|
private Task<UserDto> MapToUserDtoAsync(User user) |
||||
|
{ |
||||
|
var userDto = ObjectMapper.Map<User, UserDto>(user); |
||||
|
|
||||
|
// 设置用户状态
|
||||
|
if (user.IdentityUser != null) |
||||
|
{ |
||||
|
userDto.IsActive = user.IdentityUser.LockoutEnd == null || user.IdentityUser.LockoutEnd < DateTimeOffset.Now; |
||||
|
} |
||||
|
|
||||
|
return Task.FromResult(userDto); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Auditing; |
||||
|
|
||||
|
namespace PackageName.CompanyName.ProjectName.TreeCodes |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 定义具有树形编码的实体接口
|
||||
|
/// </summary>
|
||||
|
public interface IHaveTreeCode : IHasCreationTime |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 树形编码
|
||||
|
/// </summary>
|
||||
|
string TreeCode { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 父级Id
|
||||
|
/// </summary>
|
||||
|
Guid? ParentId { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace PackageName.CompanyName.ProjectName.TreeCodes |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 树形编码生成器接口
|
||||
|
/// </summary>
|
||||
|
public interface ITreeCodeGenerator |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 生成树形编码
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TEntity">实体类型</typeparam>
|
||||
|
/// <param name="repository">仓储</param>
|
||||
|
/// <param name="parentId">父级Id</param>
|
||||
|
/// <returns>生成的树形编码</returns>
|
||||
|
Task<string> GenerateAsync<TEntity>( |
||||
|
IRepository<TEntity, Guid> repository, |
||||
|
Guid? parentId) |
||||
|
where TEntity : class, IEntity<Guid>, IHaveTreeCode; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 更新节点及其所有子节点的TreeCode
|
||||
|
/// </summary>
|
||||
|
Task UpdateTreeCodesAsync<TEntity>( |
||||
|
IRepository<TEntity, Guid> repository, |
||||
|
Guid entityId) |
||||
|
where TEntity : class, IEntity<Guid>, IHaveTreeCode; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,114 @@ |
|||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace PackageName.CompanyName.ProjectName.TreeCodes |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 树形编码生成器
|
||||
|
/// </summary>
|
||||
|
public class TreeCodeGenerator : ITreeCodeGenerator, ISingletonDependency |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 生成树形编码
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TEntity">实体类型</typeparam>
|
||||
|
/// <param name="repository">仓储</param>
|
||||
|
/// <param name="parentId">父级Id</param>
|
||||
|
/// <returns>生成的树形编码</returns>
|
||||
|
public async virtual Task<string> GenerateAsync<TEntity>( |
||||
|
IRepository<TEntity, Guid> repository, |
||||
|
Guid? parentId) |
||||
|
where TEntity : class, IEntity<Guid>, IHaveTreeCode |
||||
|
{ |
||||
|
if (!parentId.HasValue) |
||||
|
{ |
||||
|
// 生成根节点编码
|
||||
|
return await GenerateRootCodeAsync(repository); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
// 生成子节点编码
|
||||
|
return await GenerateChildCodeAsync(repository, parentId.Value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private async Task<string> GenerateRootCodeAsync<TEntity>( |
||||
|
IRepository<TEntity, Guid> repository) |
||||
|
where TEntity : class, IEntity<Guid>, IHaveTreeCode |
||||
|
{ |
||||
|
var query = await repository.GetQueryableAsync(); |
||||
|
query = query.Where(e => e.ParentId == null).OrderByDescending(e => e.CreationTime); |
||||
|
var maxCodeEntity = await repository.AsyncExecuter.FirstOrDefaultAsync(query); |
||||
|
|
||||
|
if (maxCodeEntity == null) |
||||
|
{ |
||||
|
return "0001"; |
||||
|
} |
||||
|
|
||||
|
int maxCode = int.Parse(maxCodeEntity.TreeCode.Split('.').LastOrDefault("0")); |
||||
|
return (maxCode + 1).ToString("D4"); |
||||
|
} |
||||
|
|
||||
|
private async Task<string> GenerateChildCodeAsync<TEntity>( |
||||
|
IRepository<TEntity, Guid> repository, |
||||
|
Guid parentId) |
||||
|
where TEntity : class, IEntity<Guid>, IHaveTreeCode |
||||
|
{ |
||||
|
var parent = await repository.GetAsync(parentId); |
||||
|
if (parent == null) |
||||
|
{ |
||||
|
throw new EntityNotFoundException(typeof(TEntity), parentId); |
||||
|
} |
||||
|
|
||||
|
var query = await repository.GetQueryableAsync(); |
||||
|
query = query.Where(e => e.ParentId == parentId).OrderByDescending(e => e.CreationTime); |
||||
|
var maxCodeEntity = await repository.AsyncExecuter.FirstOrDefaultAsync(query); |
||||
|
|
||||
|
string newCode; |
||||
|
if (maxCodeEntity == null) |
||||
|
{ |
||||
|
newCode = "0001"; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
int maxCode = int.Parse(maxCodeEntity.TreeCode.Split('.').Last()); |
||||
|
newCode = (maxCode + 1).ToString("D4"); |
||||
|
} |
||||
|
|
||||
|
// 构建完整的TreeCode: 父TreeCode.新编码
|
||||
|
return $"{parent.TreeCode}.{newCode}"; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 更新节点及其所有子节点的TreeCode
|
||||
|
/// </summary>
|
||||
|
public async virtual Task UpdateTreeCodesAsync<TEntity>( |
||||
|
IRepository<TEntity, Guid> repository, |
||||
|
Guid entityId) |
||||
|
where TEntity : class, IEntity<Guid>, IHaveTreeCode |
||||
|
{ |
||||
|
var entity = await repository.GetAsync(entityId); |
||||
|
var query = await repository.GetQueryableAsync(); |
||||
|
var children = await repository.AsyncExecuter.ToListAsync( |
||||
|
query.Where(e => e.ParentId == entityId)); |
||||
|
|
||||
|
foreach (var child in children) |
||||
|
{ |
||||
|
// 获取子节点编码(TreeCode最后一部分)或生成新编码
|
||||
|
string childCode = child.TreeCode.Contains('.') |
||||
|
? child.TreeCode.Split('.').Last() |
||||
|
: child.TreeCode; |
||||
|
|
||||
|
child.TreeCode = $"{entity.TreeCode}.{childCode}"; |
||||
|
await repository.UpdateAsync(child); |
||||
|
|
||||
|
// 递归更新子节点
|
||||
|
await UpdateTreeCodesAsync(repository, child.Id); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,69 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Services; |
||||
|
|
||||
|
namespace PackageName.CompanyName.ProjectName.Users |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 用户管理服务接口
|
||||
|
/// </summary>
|
||||
|
public interface IUserManager : IDomainService |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 创建新用户
|
||||
|
/// </summary>
|
||||
|
Task<User> CreateAsync( |
||||
|
string nickName, |
||||
|
string password, |
||||
|
string contactInfo = null, |
||||
|
string position = null, |
||||
|
bool isActive = true |
||||
|
); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 更新用户信息
|
||||
|
/// </summary>
|
||||
|
Task<User> UpdateAsync( |
||||
|
Guid id, |
||||
|
string nickName, |
||||
|
string password, |
||||
|
string contactInfo = null, |
||||
|
string position = null, |
||||
|
bool isActive = true); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 删除用户
|
||||
|
/// </summary>
|
||||
|
Task DeleteAsync(Guid id); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 修改用户密码
|
||||
|
/// </summary>
|
||||
|
Task ChangePasswordAsync(Guid id, string currentPassword, string newPassword); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 重置用户密码
|
||||
|
/// </summary>
|
||||
|
Task ResetPasswordAsync(Guid id, string newPassword); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 获取用户信息
|
||||
|
/// </summary>
|
||||
|
Task<User> GetAsync(Guid id); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 根据Identity用户ID获取用户
|
||||
|
/// </summary>
|
||||
|
Task<User> FindByIdentityUserIdAsync(Guid identityUserId); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 根据用户昵称查找用户
|
||||
|
/// </summary>
|
||||
|
Task<User> FindByNickNameAsync(string nickName); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 禁用或启用用户
|
||||
|
/// </summary>
|
||||
|
Task SetUserActiveStatusAsync(Guid id, bool isActive); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace PackageName.CompanyName.ProjectName.Users |
||||
|
{ |
||||
|
public interface IUserRepository : IRepository<User, Guid> |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,59 @@ |
|||||
|
using System; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using Volo.Abp.Domain.Entities.Auditing; |
||||
|
using Volo.Abp.Identity; |
||||
|
|
||||
|
namespace PackageName.CompanyName.ProjectName.Users |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 用户实体
|
||||
|
/// </summary>
|
||||
|
public class User : FullAuditedEntity<Guid> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 用户名称
|
||||
|
/// </summary>
|
||||
|
[MaxLength(50)] |
||||
|
public string NickName { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Identity用户Id
|
||||
|
/// </summary>
|
||||
|
public Guid IdentityUserId { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Identity用户
|
||||
|
/// </summary>
|
||||
|
public virtual IdentityUser IdentityUser { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 联系方式
|
||||
|
/// </summary>
|
||||
|
[MaxLength(50)] |
||||
|
public string ContactInfo { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 职位
|
||||
|
/// </summary>
|
||||
|
[MaxLength(50)] |
||||
|
public string Position { get; set; } |
||||
|
|
||||
|
protected User() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public User( |
||||
|
Guid id, |
||||
|
string nickName, |
||||
|
Guid identityUserId, |
||||
|
string contactInfo = null, |
||||
|
string position = null |
||||
|
) : base(id) |
||||
|
{ |
||||
|
NickName = nickName; |
||||
|
IdentityUserId = identityUserId; |
||||
|
ContactInfo = contactInfo; |
||||
|
Position = position; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,406 @@ |
|||||
|
using Microsoft.Extensions.Logging; |
||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Domain.Services; |
||||
|
using Volo.Abp.Identity; |
||||
|
|
||||
|
namespace PackageName.CompanyName.ProjectName.Users |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 用户管理服务,用于处理用户的CRUD操作
|
||||
|
/// </summary>
|
||||
|
public class UserManager : DomainService, IUserManager |
||||
|
{ |
||||
|
private readonly IUserRepository _userRepository; |
||||
|
private readonly IdentityUserManager _identityUserManager; |
||||
|
private readonly ILogger<UserManager> _logger; |
||||
|
|
||||
|
public UserManager( |
||||
|
IUserRepository userRepository, |
||||
|
IdentityUserManager identityUserManager, |
||||
|
ILogger<UserManager> logger) |
||||
|
{ |
||||
|
_userRepository = userRepository; |
||||
|
_identityUserManager = identityUserManager; |
||||
|
_logger = logger; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 创建新用户
|
||||
|
/// </summary>
|
||||
|
/// <param name="nickName">用户昵称</param>
|
||||
|
/// <param name="password">用户密码</param>
|
||||
|
/// <param name="contactInfo">联系方式</param>
|
||||
|
/// <param name="position">职位</param>
|
||||
|
/// <param name="isActive">是否启用</param>
|
||||
|
/// <returns>创建的用户实体</returns>
|
||||
|
public async Task<User> CreateAsync( |
||||
|
string nickName, |
||||
|
string password, |
||||
|
string contactInfo = null, |
||||
|
string position = null, |
||||
|
bool isActive = true) |
||||
|
{ |
||||
|
// 参数验证
|
||||
|
if (string.IsNullOrWhiteSpace(nickName)) |
||||
|
{ |
||||
|
throw new UserFriendlyException("用户名不能为空"); |
||||
|
} |
||||
|
|
||||
|
// 密码校验
|
||||
|
if (string.IsNullOrWhiteSpace(password) || password.Length < 6) |
||||
|
{ |
||||
|
throw new UserFriendlyException("密码不能为空且长度不能少于6位"); |
||||
|
} |
||||
|
|
||||
|
// 检查用户昵称是否已存在
|
||||
|
var existingUser = await _userRepository.FindAsync(u => u.NickName == nickName); |
||||
|
if (existingUser != null) |
||||
|
{ |
||||
|
throw new UserFriendlyException($"昵称为 '{nickName}' 的用户已存在"); |
||||
|
} |
||||
|
|
||||
|
// 创建Identity用户
|
||||
|
var identityUser = new IdentityUser(GuidGenerator.Create(), nickName, $"{nickName}@inspection.com"); |
||||
|
var identityResult = await _identityUserManager.CreateAsync(identityUser, password); |
||||
|
if (!identityResult.Succeeded) |
||||
|
{ |
||||
|
throw new UserFriendlyException("创建用户失败: " + |
||||
|
string.Join(", ", identityResult.Errors.Select(x => x.Description))); |
||||
|
} |
||||
|
|
||||
|
// 设置用户状态
|
||||
|
if (!isActive) |
||||
|
{ |
||||
|
var lockoutResult = await _identityUserManager.SetLockoutEndDateAsync(identityUser, DateTimeOffset.MaxValue); |
||||
|
if (!lockoutResult.Succeeded) |
||||
|
{ |
||||
|
throw new UserFriendlyException("设置用户状态失败: " + |
||||
|
string.Join(", ", lockoutResult.Errors.Select(e => e.Description))); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 创建业务用户
|
||||
|
var user = new User( |
||||
|
GuidGenerator.Create(), |
||||
|
nickName, |
||||
|
identityUser.Id, |
||||
|
contactInfo, |
||||
|
position |
||||
|
); |
||||
|
|
||||
|
// 保存用户
|
||||
|
await _userRepository.InsertAsync(user, true); |
||||
|
|
||||
|
_logger.LogInformation($"创建了新用户:{nickName},ID:{user.Id}"); |
||||
|
|
||||
|
return user; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 更新用户信息
|
||||
|
/// </summary>
|
||||
|
/// <param name="id">用户ID</param>
|
||||
|
/// <param name="nickName">用户昵称</param>
|
||||
|
/// <param name="password">用户密码(可选,如不修改则传入null)</param>
|
||||
|
/// <param name="contactInfo">联系方式</param>
|
||||
|
/// <param name="position">职位</param>
|
||||
|
/// <param name="isActive">是否启用</param>
|
||||
|
/// <returns>更新后的用户实体</returns>
|
||||
|
public async Task<User> UpdateAsync( |
||||
|
Guid id, |
||||
|
string nickName, |
||||
|
string password, |
||||
|
string contactInfo = null, |
||||
|
string position = null, |
||||
|
bool isActive = true) |
||||
|
{ |
||||
|
// 最大重试次数
|
||||
|
const int maxRetries = 3; |
||||
|
int retryCount = 0; |
||||
|
|
||||
|
while (true) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
// 每次尝试时重新获取最新的用户数据
|
||||
|
var user = await _userRepository.GetAsync(id, false); |
||||
|
if (user == null) |
||||
|
{ |
||||
|
throw new UserFriendlyException("用户不存在"); |
||||
|
} |
||||
|
|
||||
|
// 检查用户昵称是否已被其他用户使用
|
||||
|
var existingUser = await _userRepository.FindAsync(u => u.NickName == nickName && u.Id != id); |
||||
|
if (existingUser != null) |
||||
|
{ |
||||
|
throw new UserFriendlyException($"昵称为 '{nickName}' 的用户已存在"); |
||||
|
} |
||||
|
|
||||
|
// 更新Identity用户
|
||||
|
var identityUser = await _identityUserManager.FindByIdAsync(user.IdentityUserId.ToString()); |
||||
|
if (identityUser == null) |
||||
|
{ |
||||
|
throw new UserFriendlyException("Identity用户不存在"); |
||||
|
} |
||||
|
|
||||
|
// 更新用户名
|
||||
|
var usernameResult = await _identityUserManager.SetUserNameAsync(identityUser, nickName); |
||||
|
if (!usernameResult.Succeeded) |
||||
|
{ |
||||
|
throw new UserFriendlyException("更新用户名失败: " + |
||||
|
string.Join(", ", usernameResult.Errors.Select(e => e.Description))); |
||||
|
} |
||||
|
|
||||
|
// 更新电子邮件
|
||||
|
var emailResult = await _identityUserManager.SetEmailAsync(identityUser, $"{nickName}@inspection.com"); |
||||
|
if (!emailResult.Succeeded) |
||||
|
{ |
||||
|
throw new UserFriendlyException("更新电子邮件失败: " + |
||||
|
string.Join(", ", emailResult.Errors.Select(e => e.Description))); |
||||
|
} |
||||
|
|
||||
|
// 如果提供了新密码,则更新密码
|
||||
|
if (!string.IsNullOrEmpty(password)) |
||||
|
{ |
||||
|
// 移除当前密码
|
||||
|
await _identityUserManager.RemovePasswordAsync(identityUser); |
||||
|
// 设置新密码
|
||||
|
var passwordResult = await _identityUserManager.AddPasswordAsync(identityUser, password); |
||||
|
if (!passwordResult.Succeeded) |
||||
|
{ |
||||
|
throw new UserFriendlyException("更新密码失败: " + |
||||
|
string.Join(", ", passwordResult.Errors.Select(e => e.Description))); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 设置用户状态
|
||||
|
await SetUserActiveStatusAsync(id, isActive); |
||||
|
|
||||
|
// 更新用户信息
|
||||
|
user.NickName = nickName; |
||||
|
user.ContactInfo = contactInfo; |
||||
|
user.Position = position; |
||||
|
|
||||
|
// 保存更新
|
||||
|
await _userRepository.UpdateAsync(user, true); |
||||
|
|
||||
|
_logger.LogInformation($"更新了用户信息:{nickName},ID:{user.Id}"); |
||||
|
|
||||
|
return user; |
||||
|
} |
||||
|
catch (Volo.Abp.Data.AbpDbConcurrencyException ex) |
||||
|
{ |
||||
|
// 增加重试计数
|
||||
|
retryCount++; |
||||
|
|
||||
|
// 如果达到最大重试次数,则抛出用户友好的异常
|
||||
|
if (retryCount >= maxRetries) |
||||
|
{ |
||||
|
throw new UserFriendlyException( |
||||
|
"更新用户信息失败:数据已被其他用户修改。请刷新页面后重试。", |
||||
|
"409", ex.Message, |
||||
|
ex); |
||||
|
} |
||||
|
|
||||
|
// 短暂延迟后重试
|
||||
|
await Task.Delay(100 * retryCount); // 逐步增加延迟时间
|
||||
|
|
||||
|
// 记录重试信息
|
||||
|
_logger.LogWarning($"检测到用户[{id}]更新时发生并发冲突,正在进行第{retryCount}次重试..."); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 删除用户
|
||||
|
/// </summary>
|
||||
|
/// <param name="id">用户ID</param>
|
||||
|
/// <returns>操作任务</returns>
|
||||
|
public async Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
// 获取用户
|
||||
|
var user = await _userRepository.GetAsync(id); |
||||
|
if (user == null) |
||||
|
{ |
||||
|
throw new UserFriendlyException("用户不存在"); |
||||
|
} |
||||
|
|
||||
|
// 删除Identity用户
|
||||
|
var identityUser = await _identityUserManager.FindByIdAsync(user.IdentityUserId.ToString()); |
||||
|
if (identityUser != null) |
||||
|
{ |
||||
|
var result = await _identityUserManager.DeleteAsync(identityUser); |
||||
|
if (!result.Succeeded) |
||||
|
{ |
||||
|
throw new UserFriendlyException("删除Identity用户失败: " + |
||||
|
string.Join(", ", result.Errors.Select(e => e.Description))); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 删除用户
|
||||
|
await _userRepository.DeleteAsync(user); |
||||
|
|
||||
|
_logger.LogInformation($"删除了用户,ID:{id}"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 修改用户密码
|
||||
|
/// </summary>
|
||||
|
/// <param name="id">用户ID</param>
|
||||
|
/// <param name="currentPassword">当前密码</param>
|
||||
|
/// <param name="newPassword">新密码</param>
|
||||
|
/// <returns>操作结果</returns>
|
||||
|
public async Task ChangePasswordAsync(Guid id, string currentPassword, string newPassword) |
||||
|
{ |
||||
|
if (string.IsNullOrEmpty(newPassword) || newPassword.Length < 6) |
||||
|
{ |
||||
|
throw new UserFriendlyException("新密码不能为空且长度不能少于6位"); |
||||
|
} |
||||
|
|
||||
|
// 获取用户
|
||||
|
var user = await _userRepository.GetAsync(id); |
||||
|
if (user == null) |
||||
|
{ |
||||
|
throw new UserFriendlyException("用户不存在"); |
||||
|
} |
||||
|
|
||||
|
// 获取Identity用户
|
||||
|
var identityUser = await _identityUserManager.FindByIdAsync(user.IdentityUserId.ToString()); |
||||
|
if (identityUser == null) |
||||
|
{ |
||||
|
throw new UserFriendlyException("Identity用户不存在"); |
||||
|
} |
||||
|
|
||||
|
// 修改密码
|
||||
|
var result = await _identityUserManager.ChangePasswordAsync(identityUser, currentPassword, newPassword); |
||||
|
if (!result.Succeeded) |
||||
|
{ |
||||
|
throw new UserFriendlyException("修改密码失败: " + |
||||
|
string.Join(", ", result.Errors.Select(e => e.Description))); |
||||
|
} |
||||
|
|
||||
|
_logger.LogInformation($"用户[{user.NickName}]成功修改了密码"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 重置用户密码(管理员操作)
|
||||
|
/// </summary>
|
||||
|
/// <param name="id">用户ID</param>
|
||||
|
/// <param name="newPassword">新密码</param>
|
||||
|
/// <returns>操作结果</returns>
|
||||
|
public async Task ResetPasswordAsync(Guid id, string newPassword) |
||||
|
{ |
||||
|
if (string.IsNullOrEmpty(newPassword) || newPassword.Length < 6) |
||||
|
{ |
||||
|
throw new UserFriendlyException("新密码不能为空且长度不能少于6位"); |
||||
|
} |
||||
|
|
||||
|
// 获取用户
|
||||
|
var user = await _userRepository.GetAsync(id); |
||||
|
if (user == null) |
||||
|
{ |
||||
|
throw new UserFriendlyException("用户不存在"); |
||||
|
} |
||||
|
|
||||
|
// 获取Identity用户
|
||||
|
var identityUser = await _identityUserManager.FindByIdAsync(user.IdentityUserId.ToString()); |
||||
|
if (identityUser == null) |
||||
|
{ |
||||
|
throw new UserFriendlyException("Identity用户不存在"); |
||||
|
} |
||||
|
|
||||
|
// 生成重置令牌
|
||||
|
var token = await _identityUserManager.GeneratePasswordResetTokenAsync(identityUser); |
||||
|
|
||||
|
// 重置密码
|
||||
|
var result = await _identityUserManager.ResetPasswordAsync(identityUser, token, newPassword); |
||||
|
if (!result.Succeeded) |
||||
|
{ |
||||
|
throw new UserFriendlyException("重置密码失败: " + |
||||
|
string.Join(", ", result.Errors.Select(e => e.Description))); |
||||
|
} |
||||
|
|
||||
|
_logger.LogInformation($"管理员重置了用户[{user.NickName}]的密码"); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 获取用户信息
|
||||
|
/// </summary>
|
||||
|
/// <param name="id">用户ID</param>
|
||||
|
/// <returns>用户实体</returns>
|
||||
|
public async Task<User> GetAsync(Guid id) |
||||
|
{ |
||||
|
return await _userRepository.GetAsync(id); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 根据Identity用户ID获取用户
|
||||
|
/// </summary>
|
||||
|
/// <param name="identityUserId">Identity用户ID</param>
|
||||
|
/// <returns>用户实体,如果不存在则返回null</returns>
|
||||
|
public async Task<User> FindByIdentityUserIdAsync(Guid identityUserId) |
||||
|
{ |
||||
|
return await _userRepository.FindAsync(u => u.IdentityUserId == identityUserId); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 根据用户昵称查找用户
|
||||
|
/// </summary>
|
||||
|
/// <param name="nickName">用户昵称</param>
|
||||
|
/// <returns>用户实体,如果不存在则返回null</returns>
|
||||
|
public async Task<User> FindByNickNameAsync(string nickName) |
||||
|
{ |
||||
|
return await _userRepository.FindAsync(u => u.NickName == nickName); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 禁用或启用用户
|
||||
|
/// </summary>
|
||||
|
/// <param name="id">用户ID</param>
|
||||
|
/// <param name="isActive">是否启用</param>
|
||||
|
/// <returns>操作任务</returns>
|
||||
|
public async Task SetUserActiveStatusAsync(Guid id, bool isActive) |
||||
|
{ |
||||
|
// 获取用户
|
||||
|
var user = await _userRepository.GetAsync(id); |
||||
|
if (user == null) |
||||
|
{ |
||||
|
throw new UserFriendlyException("用户不存在"); |
||||
|
} |
||||
|
|
||||
|
// 获取Identity用户
|
||||
|
var identityUser = await _identityUserManager.FindByIdAsync(user.IdentityUserId.ToString()); |
||||
|
if (identityUser == null) |
||||
|
{ |
||||
|
throw new UserFriendlyException("Identity用户不存在"); |
||||
|
} |
||||
|
|
||||
|
// 设置用户状态
|
||||
|
if (isActive) |
||||
|
{ |
||||
|
// 启用用户
|
||||
|
var result = await _identityUserManager.SetLockoutEndDateAsync(identityUser, null); |
||||
|
if (!result.Succeeded) |
||||
|
{ |
||||
|
throw new UserFriendlyException($"启用用户失败: " + |
||||
|
string.Join(", ", result.Errors.Select(e => e.Description))); |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
// 禁用用户(设置永久锁定)
|
||||
|
var result = await _identityUserManager.SetLockoutEndDateAsync(identityUser, DateTimeOffset.MaxValue); |
||||
|
if (!result.Succeeded) |
||||
|
{ |
||||
|
throw new UserFriendlyException($"禁用用户失败: " + |
||||
|
string.Join(", ", result.Errors.Select(e => e.Description))); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
_logger.LogInformation($"已{(isActive ? "启用" : "禁用")}用户[{user.NickName}]"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using PackageName.CompanyName.ProjectName.EntityFrameworkCore; |
||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; |
||||
|
using Volo.Abp.EntityFrameworkCore; |
||||
|
|
||||
|
namespace PackageName.CompanyName.ProjectName.Users |
||||
|
{ |
||||
|
public class UserRepository : EfCoreRepository<ProjectNameDbContext, User, Guid>, IUserRepository |
||||
|
{ |
||||
|
public UserRepository(IDbContextProvider<ProjectNameDbContext> dbContextProvider) : base(dbContextProvider) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public override async Task<IQueryable<User>> WithDetailsAsync() |
||||
|
{ |
||||
|
return (await GetDbSetAsync()).Include(x => x.IdentityUser); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,134 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using PackageName.CompanyName.ProjectName.Users.Dtos; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace PackageName.CompanyName.ProjectName.Users |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 用户管理控制器
|
||||
|
/// </summary>
|
||||
|
[RemoteService] |
||||
|
[Route("api/app/user")] |
||||
|
public class UserController : ProjectNameControllerBase |
||||
|
{ |
||||
|
private readonly IUserAppService _userAppService; |
||||
|
|
||||
|
public UserController(IUserAppService userAppService) |
||||
|
{ |
||||
|
_userAppService = userAppService; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 创建用户
|
||||
|
/// </summary>
|
||||
|
[HttpPost] |
||||
|
public async Task<UserDto> CreateAsync(CreateUpdateUserDto input) |
||||
|
{ |
||||
|
return await _userAppService.CreateAsync(input); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 更新用户
|
||||
|
/// </summary>
|
||||
|
[HttpPut("{id}")] |
||||
|
public async Task<UserDto> UpdateAsync(Guid id, CreateUpdateUserDto input) |
||||
|
{ |
||||
|
return await _userAppService.UpdateAsync(id, input); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 删除用户
|
||||
|
/// </summary>
|
||||
|
[HttpDelete("{id}")] |
||||
|
public async Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
await _userAppService.DeleteAsync(id); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 获取用户
|
||||
|
/// </summary>
|
||||
|
[HttpGet("{id}")] |
||||
|
public async Task<UserDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
return await _userAppService.GetAsync(id); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 获取用户列表
|
||||
|
/// </summary>
|
||||
|
[HttpGet] |
||||
|
public async Task<PagedResultDto<UserItemDto>> GetListAsync(UserPagedAndSortedResultRequestDto input) |
||||
|
{ |
||||
|
return await _userAppService.GetListAsync(input); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 修改用户密码
|
||||
|
/// </summary>
|
||||
|
[HttpPost("{id}/change-password")] |
||||
|
public async Task ChangePasswordAsync(Guid id, [FromBody] ChangePasswordRequest request) |
||||
|
{ |
||||
|
await _userAppService.ChangePasswordAsync(id, request.CurrentPassword, request.NewPassword); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 重置用户密码(管理员操作)
|
||||
|
/// </summary>
|
||||
|
[HttpPost("{id}/reset-password")] |
||||
|
public async Task ResetPasswordAsync(Guid id, [FromBody] ResetPasswordRequest request) |
||||
|
{ |
||||
|
await _userAppService.ResetPasswordAsync(id, request.NewPassword); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 启用或禁用用户
|
||||
|
/// </summary>
|
||||
|
[HttpPost("{id}/set-active")] |
||||
|
public async Task SetUserActiveStatusAsync(Guid id, [FromBody] SetUserActiveRequest request) |
||||
|
{ |
||||
|
await _userAppService.SetUserActiveStatusAsync(id, request.IsActive); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 修改密码请求
|
||||
|
/// </summary>
|
||||
|
public class ChangePasswordRequest |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 当前密码
|
||||
|
/// </summary>
|
||||
|
public string CurrentPassword { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 新密码
|
||||
|
/// </summary>
|
||||
|
public string NewPassword { get; set; } |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 重置密码请求
|
||||
|
/// </summary>
|
||||
|
public class ResetPasswordRequest |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 新密码
|
||||
|
/// </summary>
|
||||
|
public string NewPassword { get; set; } |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 设置用户状态请求
|
||||
|
/// </summary>
|
||||
|
public class SetUserActiveRequest |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 是否启用
|
||||
|
/// </summary>
|
||||
|
public bool IsActive { get; set; } |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue