using Furion.DataEncryption;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Myshipping.Core.Entity;
using Mapster;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MiniExcelLibs;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Yitter.IdGenerator;
using Furion;
using NPOI.HSSF.UserModel;
using Myshipping.Core.Helper;
using System.Web;
using System.Text;
using Furion.EventBus;
using Microsoft.AspNetCore.Authorization;
using Myshipping.Core.Const;
namespace Myshipping.Core.Service;
///
/// 用户服务
///
[ApiDescriptionSettings(Name = "User", Order = 150)]
public class SysUserService : ISysUserService, IDynamicApiController, ITransient
{
private readonly SqlSugarRepository _sysUserRep; // 用户表仓储
private readonly ISysCacheService _sysCacheService;
private readonly ISysConfigService _sysConfigService;
private readonly ISysEmpService _sysEmpService;
private readonly ISysUserDataScopeService _sysUserDataScopeService;
private readonly ISysUserRoleService _sysUserRoleService;
private readonly ISysEmpPosService _sysEmpPosService;
private readonly IEventPublisher _publisher;
private readonly ISysDataUserMenu _sysDataUserMenu;
private readonly ISysRoleService _sysRoleService;
public SysUserService(SqlSugarRepository sysUserRep,
ISysCacheService sysCacheService,
ISysEmpService sysEmpService,
ISysUserDataScopeService sysUserDataScopeService,
ISysUserRoleService sysUserRoleService,
ISysConfigService sysConfigService,
ISysEmpPosService sysEmpPosService,
IEventPublisher publisher,
ISysDataUserMenu sysDataUserMenu,
ISysRoleService sysRoleService)
{
_sysUserRep = sysUserRep;
_sysCacheService = sysCacheService;
_sysEmpService = sysEmpService;
_sysUserDataScopeService = sysUserDataScopeService;
_sysUserRoleService = sysUserRoleService;
_sysConfigService = sysConfigService;
_sysEmpPosService = sysEmpPosService;
_publisher = publisher;
_sysDataUserMenu = sysDataUserMenu;
_sysRoleService = sysRoleService;
}
///
/// 分页查询用户
///
///
///
[HttpGet("/sysUser/page")]
public async Task QueryUserPageList([FromQuery] UserInput input)
{
var superAdmin = UserManager.IsSuperAdmin;
var searchValue = input.SearchValue;
var pid = input.SysEmpParam.OrgId;
var users = await _sysUserRep.AsQueryable().InnerJoin((u, e) => u.Id == e.Id)
.InnerJoin((u, e, o) => e.OrgId == o.Id)
.InnerJoin((u, e, o, t) => u.TenantId == t.Id)
.WhereIF(!string.IsNullOrWhiteSpace(searchValue), (u, e, o) => u.Account.Contains(input.SearchValue.Trim()) ||
u.Name.Contains(input.SearchValue.Trim()) ||
u.Phone.Contains(input.SearchValue.Trim()))
.WhereIF(!string.IsNullOrWhiteSpace(pid), (u, e, o) => e.OrgId == long.Parse(pid) ||
o.Pids.Contains(pid.Trim()))
.WhereIF(Enum.IsDefined(typeof(CommonStatus), input.SearchStatus), (u, e, o) => u.Status == input.SearchStatus)
.Where((u, e, o) => u.AdminType == AdminType.None)
.Select("u.*,t.Name As TenantName,o.name as orgName ").ToDataFilter("u", "Id", FilterType.User)
.OrderBy(PageInputOrder.OrderBuilder(input.SortField, input.DescSort)).
ToPagedListAsync(input.PageNo, input.PageSize);
var empInfos = await _sysEmpService.GetEmpInfo(users.Items.Select(m => long.Parse(m.Id)).ToList());
foreach (var user in users.Items)
{
user.SysEmpInfo = empInfos.FirstOrDefault(m => m.Id == long.Parse(user.Id));
}
return users.XnPagedResult();
}
///
/// 增加用户
///
///
///
[HttpPost("/sysUser/add")]
public async Task AddUser(AddUserInput input)
{
// 数据范围检查
CheckDataScope(input.SysEmpParam == null || string.IsNullOrEmpty(input.SysEmpParam.OrgId) ? 0 : long.Parse(input.SysEmpParam.OrgId));
var isExist = await _sysUserRep.AsQueryable().Filter(null, true).AnyAsync(u => u.Account == input.Account && u.IsDeleted == false);
if (isExist) throw Oops.Oh(ErrorCode.D1003);
var keyDES = App.GetOptions().DES;
var user = input.Adapt();
user.AdminType = AdminType.None;
user.Password = DESCEncryption.Encrypt(input.Password, keyDES);
if (string.IsNullOrEmpty(user.Name))
user.Name = user.Account;
if (string.IsNullOrEmpty(user.NickName))
user.NickName = user.Account;
try
{
_sysUserRep.CurrentBeginTran();
var newUser = await _sysUserRep.InsertReturnEntityAsync(user);
input.SysEmpParam.Id = newUser.Id.ToString();
// 增加员工信息
await _sysEmpService.AddOrUpdate(input.SysEmpParam);
// 如果当前运行模式为和川,则进行一些初始化操作
if (App.Configuration["RunType"] == CommonConst.RUN_TYPE_HECHUAN)
{
// 绑定角色:普通员工
long? roleId = await _sysRoleService.GetRoleIdByRoleCode(CommonConst.ROLE_COMMON_EMPLOYEE);
if (roleId != null)
{
await _sysUserRoleService.GrantRole(new UpdateUserInput()
{
Id = newUser.Id,
GrantRoleIdList = new List() { (long)roleId }
});
}
// 授权"订舱台账"菜单的数据范围
var userMenuDto = new User.Dto.SysDataUserMenuDto()
{
UserId = newUser.Id,
childrens = new List() {
new(MenuConst.MenuBookingOrder, DataScopeType.DEPT_WITH_CHILD, true)
}
};
await _sysDataUserMenu.GrantData(userMenuDto);
}
_sysUserRep.CurrentCommitTran();
await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_USERSDATASCOPE);
}
catch (Exception)
{
_sysUserRep.CurrentRollbackTran();
throw;
}
}
///
/// 删除用户
///
///
///
[HttpPost("/sysUser/delete")]
public async Task DeleteUser(DeleteUserInput input)
{
var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Id == input.Id);
if (user.AdminType != AdminType.None)
throw Oops.Oh(ErrorCode.D1014);
if (user.Account == UserManager.Account)
{
throw Oops.Oh(ErrorCode.D1001);
}
// 数据范围检查
CheckDataScopeByUserId(input.Id);
try
{
_sysUserRep.CurrentBeginTran();
// 直接删除用户
await _sysUserRep.AsUpdateable(new SysUser { IsDeleted = true }).UpdateColumns(user.FalseDeleteColumn()).Where(wh => wh.Id == user.Id).ExecuteCommandAsync();
// 删除员工及附属机构职位信息
await _sysEmpService.DeleteEmpInfoByUserId(user.Id);
//删除该用户对应的用户-角色表关联信息
await _sysUserRoleService.DeleteUserRoleListByUserId(user.Id);
//删除该用户对应的用户-数据范围表关联信息
await _sysUserDataScopeService.DeleteUserDataScopeListByUserId(user.Id);
_sysUserRep.CurrentCommitTran();
await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_USERSDATASCOPE);
}
catch (Exception)
{
_sysUserRep.CurrentRollbackTran();
throw;
}
}
///
/// 更新用户
///
///
///
[HttpPost("/sysUser/edit")]
public async Task UpdateUser(UpdateUserInput input)
{
// 数据范围检查
CheckDataScopeByUserId(input.Id);
// 排除自己并且判断与其他是否相同
var isExist = await _sysUserRep.AnyAsync(u => u.Account == input.Account && u.Id != input.Id);
if (isExist) throw Oops.Oh(ErrorCode.D1003);
var user = input.Adapt();
try
{
_sysUserRep.CurrentBeginTran();
await _sysUserRep.AsUpdateable(user).IgnoreColumns(it => new { it.Password, it.Status, it.AdminType, it.TenantId }).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
input.SysEmpParam.Id = user.Id.ToString();
// 更新员工及附属机构职位信息
await _sysEmpService.AddOrUpdate(input.SysEmpParam);
_sysUserRep.CurrentCommitTran();
await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_USERSDATASCOPE);
}
catch (Exception)
{
_sysUserRep.CurrentRollbackTran();
throw;
}
}
///
/// 查看用户
///
///
///
[HttpGet("/sysUser/detail")]
public async Task GetUser([FromQuery] QueryUserInput input)
{
var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Id == input.Id);
var userDto = user.Adapt();
if (userDto != null)
{
userDto.SysEmpInfo = await _sysEmpService.GetEmpInfo(user.Id);
}
return userDto;
}
///
/// 修改用户状态
///
///
///
[HttpPost("/sysUser/changeStatus")]
public async Task ChangeUserStatus(UpdateUserInput input)
{
var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Id == input.Id);
if (user.AdminType == AdminType.SuperAdmin)
throw Oops.Oh(ErrorCode.D1015);
if (!Enum.IsDefined(typeof(CommonStatus), input.Status))
throw Oops.Oh(ErrorCode.D3005);
user.Status = input.Status;
await _sysUserRep.AsUpdateable(user).ExecuteCommandAsync();
}
///
/// 授权用户角色
///
///
///
[HttpPost("/sysUser/grantRole")]
public async Task GrantUserRole(UpdateUserInput input)
{
// 数据范围检查
CheckDataScopeByUserId(input.Id);
await _sysUserRoleService.GrantRole(input);
}
///
/// 授权用户数据范围
///
///
///
[HttpPost("/sysUser/grantData")]
public async Task GrantUserData(UpdateUserInput input)
{
// 清除缓存
await _sysCacheService.DelAsync(CommonConst.CACHE_KEY_DATASCOPE + $"{input.Id}");
await _sysCacheService.DelAsync(CommonConst.CACHE_KEY_USERSDATASCOPE + $"{input.Id}");
// 数据范围检查
CheckDataScopeByUserId(input.Id);
await _sysUserDataScopeService.GrantData(input);
await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_USERSDATASCOPE);
await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_DATASCOPE);
}
///
/// 更新用户信息
///
///
///
[HttpPost("/sysUser/updateInfo")]
public async Task UpdateUserInfo(UpdateUserInput input)
{
var user = input.Adapt();
await _sysUserRep.AsUpdateable(user)
.IgnoreColumns(it => new { it.AdminType, it.LastLoginTime, it.TenantId, it.CreatedUserId, it.DjyUserId, it.Account, it.Password, it.Status, it.IsDeleted, it.Name })
.ExecuteCommandAsync();
await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_USERSDATASCOPE);
}
///
/// 修改用户密码
///
///
///
[HttpPost("/sysUser/updatePwd")]
public async Task UpdateUserPwd(ChangePasswordUserInput input)
{
var keyDES = App.GetOptions().DES;
var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Id == input.Id);
if (DESCEncryption.Encrypt(input.Password, keyDES) != user.Password)
throw Oops.Oh(ErrorCode.D1004);
if (!PasswordCheckHelper.Check(input.NewPassword))
{
throw Oops.Oh("密码强度不符合要求:需要8位以上的字母+数字+特殊符号");
}
user.Password = DESCEncryption.Encrypt(input.NewPassword, keyDES);
user.LastModifyPassword = DateTime.Now;
await _sysUserRep.AsUpdateable(user).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
}
///
/// 获取用户拥有角色
///
///
///
[HttpGet("/sysUser/ownRole")]
public async Task GetUserOwnRole([FromQuery] QueryUserInput input)
{
return await _sysUserRoleService.GetUserRoleIdList(input.Id);
}
///
/// 获取用户拥有数据
///
///
///
[HttpGet("/sysUser/ownData")]
public async Task GetUserOwnData([FromQuery] QueryUserInput input)
{
return await _sysUserDataScopeService.GetUserDataScopeIdList(input.Id);
}
///
/// 重置用户密码
///
///
///
[HttpPost("/sysUser/resetPwd")]
public async Task ResetUserPwd(ResetPasswordUserInput input)
{
var keyDES = App.GetOptions().DES;
var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Id == input.Id);
user.Password = DESCEncryption.Encrypt(input.NewPassword, keyDES);
user.LastLoginTime = DateTime.Today.AddYears(-1); //让密码过期,需要用户登录时重新修改密码
await _sysUserRep.AsUpdateable(user).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
}
///
/// 修改用户头像
///
///
///
[HttpPost("/sysUser/updateAvatar")]
public async Task UpdateAvatar(UploadAvatarInput input)
{
var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Id == input.Id);
user.Avatar = input.Avatar.ToString();
await _sysUserRep.AsUpdateable(user).IgnoreColumns(it => new { it.AdminType }).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
}
///
/// 获取用户选择器
///
///
///
[HttpGet("/sysUser/selector")]
public async Task GetUserSelector([FromQuery] UserInput input)
{
return await _sysUserRep.AsQueryable()
.WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => (u.Name.Contains(input.Name.Trim())))
.Where(u => u.Status != CommonStatus.DELETED)
.Where(u => u.AdminType != AdminType.SuperAdmin)
.Select(u => new
{
u.Id,
u.Name
}).ToListAsync();
}
///
/// 用户导出
///
///
[HttpGet("/sysUser/export")]
public async Task ExportUser()
{
var excelwork = new HSSFWorkbook();
var sheet = excelwork.CreateSheet();
var fileName = string.Empty;
//创建第一行表头
var srow = NpoiExcelExportHelper._.CreateRow(sheet, 0);
srow.CreateCell(0).SetCellValue("账号");
srow.CreateCell(1).SetCellValue("姓名");
srow.CreateCell(2).SetCellValue("性别");
srow.CreateCell(3).SetCellValue("手机");
srow.CreateCell(4).SetCellValue("状态");
srow.CreateCell(5).SetCellValue("邮件");
var users = await _sysUserRep.AsQueryable().Filter(null, true).Where(x => x.TenantId == UserManager.TENANT_ID && x.IsDeleted == false).ToListAsync();
int i = 1;
foreach (var item in users)
{
var row = NpoiExcelExportHelper._.CreateRow(sheet, i);
row.CreateCell(0).SetCellValue(item.Account);
row.CreateCell(1).SetCellValue(item.Name);
row.CreateCell(2).SetCellValue(item.Sex == Gender.MALE ? "男" : item.Sex == Gender.FEMALE ? "女" : "未知");
row.CreateCell(3).SetCellValue(item.Phone);
row.CreateCell(4).SetCellValue(item.Status == CommonStatus.ENABLE ? "正常" : item.Status == CommonStatus.DISABLE ? "停用" : "删除");
row.CreateCell(5).SetCellValue(item.Email);
i++;
}
var fileFullPath = Path.Combine(App.WebHostEnvironment.WebRootPath, App.GetOptions().Path);//服务器路径
if (!Directory.Exists(fileFullPath))
{
Directory.CreateDirectory(fileFullPath);
}
fileName = $"{UserManager.TENANT_NAME}_{DateTime.Now.Ticks}" + ".xls";//名称
var filestream = new FileStream(Path.Combine(fileFullPath, fileName), FileMode.OpenOrCreate, FileAccess.ReadWrite);
excelwork.Write(filestream);
filestream.Close();
filestream.Dispose();
var result = new FileStreamResult(new FileStream(Path.Combine(fileFullPath, fileName), FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };
return result;
}
/// 用户导入
///
///
///
[HttpPost("/sysUser/import")]
public async Task ImportUser(IFormFile file)
{
var path = Path.Combine(Path.GetTempPath(), $"{YitIdHelper.NextId()}.xlsx");
using (var stream = File.Create(path))
{
await file.CopyToAsync(stream);
}
throw Oops.Oh("请自行完善入库操作");
//var rows = MiniExcel.Query(path); // 解析
//foreach (var row in rows)
//{
// var a = row.A;
// var b = row.B;
// // 入库等操作
//}
}
///
/// 根据用户Id获取用户
///
///
///
[NonAction]
public async Task GetUserById(long userId)
{
return await _sysUserRep.FirstOrDefaultAsync(u => u.Id == userId);
}
///
/// 将OAuth账号转换成账号
///
///
///
///
[NonAction]
public async Task SaveAuthUserToUser(AuthUserInput authUser, UserInput sysUser)
{
var user = sysUser.Adapt();
user.AdminType = AdminType.None; // 非管理员
// oauth账号与系统账号判断
var isExist = await _sysUserRep.AnyAsync(u => u.Account == authUser.Username);
user.Account = isExist ? authUser.Username + DateTime.Now.Ticks : authUser.Username;
user.Name = user.NickName = authUser.Nickname;
user.Email = authUser.Email;
user.Sex = authUser.Gender;
await _sysUserRep.InsertAsync(user);
}
///
/// 获取用户数据范围(机构Id集合)并缓存
///
///
///
[NonAction]
public async Task> GetUserDataScopeIdList(long userId = 0)
{
userId = userId <= 0 ? UserManager.UserId : userId;
var dataScopes = await _sysCacheService.GetDataScope(userId); // 先从缓存里面读取
if (dataScopes == null || dataScopes.Count < 1)
{
if (!UserManager.IsSuperAdmin && !UserManager.IsTenantAdmin)
{
var orgId = await _sysEmpService.GetEmpOrgId(userId);
// 获取该用户对应的数据范围集合
var userDataScopeIdListForUser = await _sysUserDataScopeService.GetUserDataScopeIdList(userId);
// 获取该用户的角色对应的数据范围集合
var userDataScopeIdListForRole = await _sysUserRoleService.GetUserRoleDataScopeIdList(userId, orgId);
dataScopes = userDataScopeIdListForUser.Concat(userDataScopeIdListForRole).Distinct().ToList(); // 并集
}
else
{
dataScopes = await _sysUserRep.Change().AsQueryable().Select(u => u.Id).ToListAsync();
}
await _sysCacheService.SetDataScope(userId, dataScopes); // 缓存结果
}
return dataScopes;
}
///
/// 检查普通用户数据范围
///
///
///
[NonAction]
public async void CheckDataScope(long orgId)
{
// 如果当前用户不是超级管理员,则进行数据范围校验
if (!UserManager.IsSuperAdmin)
{
var dataScopes = await GetUserDataScopeIdList(UserManager.UserId);
if (dataScopes == null || orgId <= 0 || !dataScopes.Contains(orgId))
throw Oops.Oh(ErrorCode.D1013);
}
}
///
/// 获取用户数据范围(用户Id集合)
///
///
[NonAction]
public async Task> GetDataScopeIdUserList(long userId = 0)
{
userId = userId <= 0 ? UserManager.UserId : userId;
var list = await _sysCacheService.GetUsersDataScope(userId); // 先从缓存里面读取
if (list == null || list.Count < 1)
{
var dataScopes = await GetUserDataScopeIdList(userId);
list = (await _sysEmpService.HasOrgEmp(dataScopes)).Select(a => a.Id).ToList();
list.Add(userId);
list = list.Distinct().ToList();
await _sysCacheService.SetUsersDataScope(userId, list); // 缓存结果
}
return list;
}
///
/// 检查普通用户数据范围
///
///
///
[NonAction]
public async void CheckDataScopeByUserId(long userId)
{
// 如果当前用户不是超级管理员,则进行数据范围校验
if (!UserManager.IsSuperAdmin)
{
var dataScopes = await GetDataScopeIdUserList(UserManager.UserId);
if (dataScopes == null || userId <= 0 || !dataScopes.Contains(userId))
throw Oops.Oh(ErrorCode.D1013);
}
}
///
/// 获取租户下的用户
///
/// 用户的代码、英文名或中文名
/// 默认0 获取当前用户,可不传 传租户id获取当前租户
///
[HttpGet("/sysUser/GetTenantUser")]
public async Task> GetTenantUser(string name, long? tenantId = 0)
{
return await _sysUserRep.AsQueryable().Filter(null, true)
.WhereIF(!string.IsNullOrWhiteSpace(name), x => x.UserCode.Contains(name) || x.EnName.Contains(name) || x.Name.Contains(name))
.WhereIF(tenantId == 0, x => x.TenantId == Convert.ToInt64(UserManager.TENANT_ID) && x.Status == CommonStatus.ENABLE && x.IsDeleted == false)
.WhereIF(tenantId != 0, x => x.TenantId == tenantId)
.OrderBy(x => x.Name).ToListAsync();
}
[HttpGet("/sysUser/DecryptPassword")]
public async Task DecryptPassword(long id)
{
if (UserManager.IsSuperAdmin)
{
var user = await _sysUserRep.AsQueryable().Filter(null, false).FirstAsync(u => u.Id == id);
var keyDES = App.GetOptions().DES;
var pwdDecrypt = DESCEncryption.Decrypt(user.Password, keyDES);
return pwdDecrypt;
}
throw Oops.Bah("没有权限");
}
///
/// 通过职位获取用户信息
///
///
/// 职位代码 PCDD-调度
/// 返回用户详情
[HttpGet("/sysUser/QueryUserByPos")]
public async Task> QueryUserByPos([FromQuery] string name, [FromQuery] string pos)
{
if (string.IsNullOrWhiteSpace(pos))
Oops.Oh("没有权限");
var allList = await _sysEmpPosService.GetAllEmpByPos(new List { pos });
if (allList.Count > 0 && !string.IsNullOrWhiteSpace(name))
{
allList = allList.Where(a => a.SysEmpName.Contains(name.Trim())).ToList();
}
return allList;
}
///
/// 公司用户信息同步
///
///
[HttpPost("/sysUser/CompanyUserSync"), AllowAnonymous, ApiUser(ApiCode = "CompanyUserSync")]
public async Task CompanyUserSync(MyshippingCompanyUserSyncDto dto)
{
if (dto.Type != "CompanyUserSync")
{
throw Oops.Bah($"类型有误:{dto.Type}");
}
if (string.IsNullOrEmpty(dto.Company.CompId)
|| string.IsNullOrEmpty(dto.Company.CompName)
|| string.IsNullOrEmpty(dto.Company.AdminUser)
|| string.IsNullOrEmpty(dto.Company.AdminShowName)
|| string.IsNullOrEmpty(dto.Company.AdminUserEmail)
|| string.IsNullOrEmpty(dto.Company.AdminUserMobile)
|| string.IsNullOrEmpty(dto.Company.CompId))
{
throw Oops.Bah($"公司信息不全。公司ID、名称、管理员ID、名称、手机、邮箱都不能为空");
}
var cc = dto.Users.Where(x => string.IsNullOrEmpty(x.GID)
|| string.IsNullOrEmpty(x.CODENAME)
|| string.IsNullOrEmpty(x.SHOWNAME)
|| string.IsNullOrEmpty(x.EMAIL1)
|| string.IsNullOrEmpty(x.MOBILE))
.Count();
if (cc > 0)
{
throw Oops.Bah($"用户信息不全。用户ID、姓名、登录名、密码、手机、邮箱都不能为空");
}
await _publisher.PublishAsync(new ChannelEventSource("CompanyUserSync:CompanyUser", dto.ToJsonString()));
}
///
/// 用户离职信息同步
///
///
[HttpPost("/sysUser/UserLeave"), AllowAnonymous, ApiUser(ApiCode = "CompanyUserSync")]
public async Task UserLeave(MyshippingUserLeaveSyncDto dto)
{
if (dto.Type != "UserLeave")
{
throw Oops.Bah($"类型有误:{dto.Type}");
}
if (string.IsNullOrEmpty(dto.CompId)
|| string.IsNullOrEmpty(dto.UserId))
{
throw Oops.Bah($"信息不全。公司ID、用户ID都不能为空");
}
await _publisher.PublishAsync(new ChannelEventSource("CompanyUserSync:UserLeave", dto.ToJsonString()));
}
}