添加项目文件。

This commit is contained in:
youngq 2024-06-26 17:47:25 +08:00
parent e86dc57b4a
commit fb83651055
55 changed files with 2477 additions and 0 deletions

31
WGShare.API.sln Normal file
View File

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34723.18
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WGShare.API", "WGShare.API\WGShare.API.csproj", "{A5611B2B-6FFE-48BE-9AB5-EA846A47E37D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WGShare.Domain", "WGShare.Domain\WGShare.Domain.csproj", "{93A88636-4DAE-4832-A2F7-CAEB193017A3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A5611B2B-6FFE-48BE-9AB5-EA846A47E37D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A5611B2B-6FFE-48BE-9AB5-EA846A47E37D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5611B2B-6FFE-48BE-9AB5-EA846A47E37D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5611B2B-6FFE-48BE-9AB5-EA846A47E37D}.Release|Any CPU.Build.0 = Release|Any CPU
{93A88636-4DAE-4832-A2F7-CAEB193017A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{93A88636-4DAE-4832-A2F7-CAEB193017A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{93A88636-4DAE-4832-A2F7-CAEB193017A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{93A88636-4DAE-4832-A2F7-CAEB193017A3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CCBE5CF2-07F8-444A-9664-FA34CBB56143}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,187 @@
using Masuit.Tools;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using System.Configuration;
using System.Security.Claims;
using WGShare.API.Controllers.Basic;
using WGShare.API.Helpers;
using WGShare.Domain.DTOs.Login;
using WGShare.Domain.Entities;
using WGShare.Domain.FriendlyException;
namespace WGShare.API.Controllers
{
[Route("auth")]
public class AuthController : BasicController
{
private readonly ISqlSugarClient _sqlSugar;
private readonly JwtHelper _jwtHelper;
public AuthController(ISqlSugarClient sqlSugar, JwtHelper jwtHelper)
{
_sqlSugar = sqlSugar;
_jwtHelper = jwtHelper;
}
/// <summary>
/// 检查用户名
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
[HttpGet("check-user"), AllowAnonymous]
public async Task<bool> CheckUser([FromQuery] string userName)
{
return await _sqlSugar.Queryable<User>().AnyAsync(x => x.IsDelete == false && x.UserName == userName);
}
/// <summary>
/// 正常账号登录
/// </summary>
/// <returns></returns>
[HttpPost("login"), AllowAnonymous]
public async Task<IActionResult> Login([FromBody] UserLoginDTO loginDTO)
{
var user = await _sqlSugar.Queryable<User>()
.FirstAsync(x => x.UserName == loginDTO.Account && x.IsDelete == false && x.Pwd == loginDTO.Pwd);
if (user == null)
{
throw Oops.Oh("用户名或密码不正确!");
}
var tenant = await _sqlSugar.Queryable<Tenant>().FirstAsync(x => x.Id == user.TenantId);
if (tenant == null || tenant.IsDelete == true)
{
throw Oops.Oh("该区域账号已停用,请联系管理员");
}
if (await _sqlSugar.Queryable<Role>().AnyAsync(x => x.IsDelete == true && x.Id == user.RoleId))
{
throw Oops.Oh("该角色账号已停用,请联系管理员");
}
var perms = await _sqlSugar.Queryable<Permission>()
.InnerJoin<RolePrem>((m, rm) => m.Id == rm.PermId)
.Where((m, rm) => rm.RoleId == user.RoleId)
.Distinct()
.ToListAsync();
var btnAutn = new List<Claim>();
btnAutn.Add(new Claim("perm", perms.Sum(x => x.PermValue).ToString()));
btnAutn.Add(new Claim("role", user.RoleId));
btnAutn.Add(new Claim("tenant", user.TenantId));
return Ok(new
{
perms = perms.Sum(x => x.PermValue),
token = _jwtHelper.CreateToken(user.Id, btnAutn),
roleId = user.RoleId,
userName = user.UserName,
tenantName = tenant.TenantName
});
}
/// <summary>
/// 匿名登录,直接进入会议室
/// </summary>
/// <returns></returns>
[HttpPost("anon-login")]
public async Task<IActionResult> Login([FromBody] AnonymousLoginDTO loginDTO)
{
var room = await _sqlSugar.Queryable<Room>().FirstAsync(x => x.Id == loginDTO.RoomId);
if (room == null)
{
throw Oops.Oh("会议号无效");
}
var anonRoleId = "2";
// 匿名登录使用普通用户身份
var perms = await _sqlSugar.Queryable<Permission>()
.InnerJoin<RolePrem>((m, rm) => m.Id == rm.PermId)
.Where((m, rm) => rm.RoleId == anonRoleId)
.Distinct()
.ToListAsync();
var tenant = await _sqlSugar.Queryable<Tenant>().FirstAsync(x => x.Id == room.TenantId);
if (tenant == null || tenant.IsDelete == true)
{
throw Oops.Oh("该区域账号已停用,请联系管理员");
}
var btnAutn = new List<Claim>();
btnAutn.Add(new Claim("perm", perms.Sum(x => x.PermValue).ToString()));
btnAutn.Add(new Claim("role", anonRoleId));
btnAutn.Add(new Claim("tenant", room.TenantId));
btnAutn.Add(new Claim("mac", loginDTO.Mac));
btnAutn.Add(new Claim("machine", loginDTO.MachineName));
btnAutn.Add(new Claim("nickName", loginDTO.NickName));
return Ok(new
{
perms = perms.Sum(x => x.PermValue),
token = _jwtHelper.CreateToken("0", btnAutn),
roleId = anonRoleId,
userName = loginDTO.NickName,
tenantName = tenant.TenantName
});
}
/// <summary>
/// 登出(暂未处理任何业务逻辑)
/// </summary>
/// <returns></returns>
[HttpPost("logout")]
public async Task<bool> Logout()
{
return true;
}
#region
/// <summary>
/// 管理员登录
/// </summary>
/// <returns></returns>
[HttpPost("admin/login"), AllowAnonymous]
public async Task<string> LoginForAdmin([FromBody] UserLoginDTO loginDTO)
{
var adminClient = _sqlSugar.AsTenant().GetConnection("usercenter");
var user = await adminClient.Queryable<Admin>()
.FirstAsync(x => x.Account == loginDTO.Account && x.Password == loginDTO.Pwd);
if (user == null)
{
throw Oops.Oh("用户名或密码不正确!");
}
return _jwtHelper.CreateToken(user.Id);
}
/// <summary>
/// 管理员信息
/// </summary>
/// <returns></returns>
[HttpGet("admin/info")]
public async Task<IActionResult> GetAdminInfo()
{
var adminClient = _sqlSugar.AsTenant().GetConnection("usercenter");
var user = await adminClient.Queryable<Admin>()
.FirstAsync(x => x.Id == UId);
if (user == null)
{
throw Oops.Oh("管理员不存在!");
}
return Ok(new
{
name = user.Name,
id = user.Id,
});
}
#endregion
}
}

View File

@ -0,0 +1,93 @@
using Mapster;
using Masuit.Tools;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using WGShare.API.Controllers.Basic;
using WGShare.Domain.DTOs.Perm;
using WGShare.Domain.DTOs.Role;
using WGShare.Domain.Entities;
using WGShare.Domain.FriendlyException;
using Yitter.IdGenerator;
namespace WGShare.API.Controllers.Backend
{
[Route("be/perm")]
public class PremController : BasicController
{
private readonly ISqlSugarClient _sqlSugar;
public PremController(ISqlSugarClient sqlSugar)
{
_sqlSugar = sqlSugar;
}
[HttpGet("{id}")]
public async Task<Permission> GetSingle([FromRoute] string id)
{
return await _sqlSugar.Queryable<Permission>().FirstAsync(x => x.Id == id);
}
[HttpGet("all")]
public async Task<List<Permission>> GetAll()
{
return await _sqlSugar.Queryable<Permission>().ToListAsync();
}
[HttpPost]
public async Task<bool> Add([FromBody] PermissionInputDTO input)
{
var entity = input.Adapt<Permission>();
if (await _sqlSugar.Queryable<Permission>().AnyAsync(x => x.PermValue == input.PermValue))
{
throw Oops.Oh("权限值不能重复");
}
entity.Id = YitIdHelper.NextId().ToString();
return await _sqlSugar.Insertable(entity).ExecuteCommandAsync() > 0;
}
/// <summary>
/// 获取最新权限值
/// </summary>
/// <returns></returns>
[HttpGet("vale")]
public async Task<int> GetPermValue()
{
var maxPerm = await _sqlSugar.Queryable<Permission>().MaxAsync(x => x.PermValue);
if (maxPerm == 0)
{
return 1;
}
return maxPerm << 1;
}
[HttpPut]
public async Task<bool> Modify([FromBody] PermissionInputDTO input)
{
var entity = input.Adapt<Permission>();
if (await _sqlSugar.Queryable<Permission>().AnyAsync(x => x.PermValue == input.PermValue && x.Id != input.Id))
{
throw Oops.Oh("权限值不能重复");
}
return await _sqlSugar.Updateable(entity).ExecuteCommandAsync() > 0;
}
[HttpDelete]
public async Task<bool> Delete([FromQuery] string id)
{
var roles = await _sqlSugar.Queryable<Role>()
.InnerJoin<RolePrem>((r, rp) => r.Id == rp.RoleId)
.Where((r, rp) => rp.PermId == id)
.Select((r, rp) => r.RoleName).ToListAsync();
if (!roles.IsNullOrEmpty())
{
throw Oops.Oh($@"[{string.Join(',', roles)}]角色已使用,无法删除!");
}
return await _sqlSugar.Deleteable<Permission>().Where(x => x.Id == id).ExecuteCommandHasChangeAsync();
}
}
}

View File

@ -0,0 +1,86 @@
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using WGShare.API.Controllers.Basic;
using WGShare.Domain.DTOs.Role;
using WGShare.Domain.Entities;
using Yitter.IdGenerator;
namespace WGShare.API.Controllers.Backend
{
[Route("be/role")]
public class RoleController : BasicController
{
private readonly ISqlSugarClient _sqlSugar;
public RoleController(ISqlSugarClient sqlSugar)
{
_sqlSugar = sqlSugar;
}
[HttpGet("{id}")]
public async Task<Role> GetSingle([FromRoute] string id)
{
return await _sqlSugar.Queryable<Role>().FirstAsync(x => x.Id == id);
}
[HttpGet("list")]
public async Task<List<Role>> GetPageList()
{
return await _sqlSugar.Queryable<Role>().ToListAsync();
}
[HttpPost]
public async Task<bool> Add([FromBody] RoleInputDTO inputDTO)
{
var entity = inputDTO.Adapt<Role>();
entity.Id = YitIdHelper.NextId().ToString();
return await _sqlSugar.Insertable(entity).ExecuteCommandAsync() > 0;
}
[HttpPut]
public async Task<bool> Modify([FromBody] RoleInputDTO inputDTO)
{
var entity = inputDTO.Adapt<Role>();
return await _sqlSugar.Updateable(entity)
.UpdateColumns(x => new { x.RoleName }).ExecuteCommandAsync() > 0;
}
[HttpDelete]
public async Task<bool> Delete([FromBody] params string[] ids)
{
return await _sqlSugar.Updateable<Role>()
.SetColumns(x => x.IsDelete == true)
.Where(x => ids.Contains(x.Id)).ExecuteCommandHasChangeAsync();
}
[HttpGet("dp-list")]
public async Task<List<Role>> GetDropDownList()
{
return await _sqlSugar.Queryable<Role>().Where(x => x.IsDelete == false).ToListAsync();
}
[HttpPost("auth-perm")]
public async Task<bool> PermAuth([FromQuery] string roleId, [FromBody] List<RolePermInputDTO> inputDTO)
{
var entity = inputDTO.Adapt<List<RolePrem>>();
await _sqlSugar.Deleteable<RolePrem>()
.Where(x => x.RoleId == roleId).ExecuteCommandAsync();
return await _sqlSugar.Insertable(entity).ExecuteCommandAsync() > 0;
}
[HttpGet("auth-perm")]
public async Task<List<Permission>> GetPermAuth([FromQuery] string roleId)
{
return await _sqlSugar.Queryable<Permission>()
.InnerJoin<RolePrem>((p, rp) => p.Id == rp.PermId)
.Where((p, rp) => rp.RoleId == roleId)
.ToListAsync();
}
}
}

View File

@ -0,0 +1,69 @@
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using WGShare.API.Controllers.Basic;
using WGShare.Domain.DTOs.Tenant;
using WGShare.Domain.DTOs.User;
using WGShare.Domain.Entities;
using WGShare.Domain.FriendlyException;
using WGShare.Domain.GeneralModel;
using Yitter.IdGenerator;
namespace WGShare.API.Controllers.Backend
{
[Route("be/tenant")]
public class TenantController : BasicController
{
private readonly ISqlSugarClient _sqlSugar;
public TenantController(ISqlSugarClient sqlSugar)
{
_sqlSugar = sqlSugar;
}
[HttpGet("{id}")]
public async Task<Tenant> GetSingle([FromRoute] string id)
{
return await _sqlSugar.Queryable<Tenant>().FirstAsync(x => x.Id == id);
}
[HttpGet("list")]
public async Task<List<Tenant>> GetList()
{
return await _sqlSugar.Queryable<Tenant>().ToListAsync();
}
[HttpPost]
public async Task<bool> Add([FromBody] TenantInputDTO inputDTO)
{
var entity = inputDTO.Adapt<Tenant>();
entity.Id = YitIdHelper.NextId().ToString();
return await _sqlSugar.Insertable(entity).ExecuteCommandAsync() > 0;
}
[HttpPut]
public async Task<bool> Modify([FromBody] TenantInputDTO inputDTO)
{
var entity = inputDTO.Adapt<Tenant>();
return await _sqlSugar.Updateable(entity)
.UpdateColumns(x => new { x.TenantName }).ExecuteCommandAsync() > 0;
}
[HttpGet]
public async Task<bool> Delete([FromQuery] string id, [FromQuery] bool enable)
{
return await _sqlSugar.Updateable<Tenant>()
.SetColumns(x => x.IsDelete == enable)
.Where(x => x.Id == id).ExecuteCommandHasChangeAsync();
}
[HttpGet("dp-list")]
public async Task<List<Tenant>> GetDropDownList()
{
return await _sqlSugar.Queryable<Tenant>().Where(x => x.IsDelete == false).ToListAsync();
}
}
}

View File

@ -0,0 +1,118 @@
using Mapster;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using WGShare.API.Controllers.Basic;
using WGShare.Domain.DTOs.User;
using WGShare.Domain.Entities;
using WGShare.Domain.FriendlyException;
using WGShare.Domain.GeneralModel;
using Yitter.IdGenerator;
namespace WGShare.API.Controllers.Backend
{
[Route("be/user")]
public class UserController : BasicController
{
private readonly ISqlSugarClient _sqlSugar;
public UserController(ISqlSugarClient sqlSugar)
{
_sqlSugar = sqlSugar;
}
[HttpGet("{id}")]
public async Task<User> GetSingle([FromRoute] string id)
{
return await _sqlSugar.Queryable<User>().FirstAsync(x => x.Id == id);
}
[HttpGet("list")]
public async Task<PagedResult<User>> GetPageList([FromQuery] UserSearchDTO searchDTO)
{
RefAsync<int> total = 0;
var list = await _sqlSugar.Queryable<User>()
.InnerJoin<Role>((u, r) => u.RoleId == r.Id)
.InnerJoin<Tenant>((u, r, t) => u.TenantId == t.Id)
.WhereIF(!string.IsNullOrWhiteSpace(searchDTO.keyword),
u => u.UserName.Contains(searchDTO.keyword) || u.Account.Contains(searchDTO.keyword) || u.Id.Contains(searchDTO.keyword))
.WhereIF(!string.IsNullOrWhiteSpace(searchDTO.TenantId), u => u.TenantId == searchDTO.TenantId)
.WhereIF(!string.IsNullOrWhiteSpace(searchDTO.RoleId), u => u.RoleId == searchDTO.RoleId)
//.Where(u => u.IsDelete == false)
.Select((u, r, t) => new User
{
Id = u.Id.SelectAll(),
RoleName = r.RoleName,
TenantName = t.TenantName
})
.ToPageListAsync(searchDTO.PageIndex, searchDTO.PageSize, total);
return PagedResult<User>.Create(list, total.Value);
}
[HttpPost]
public async Task<bool> Add([FromBody] UserInputDTO userInput)
{
var entity = userInput.Adapt<User>();
entity.Id = YitIdHelper.NextId().ToString();
if (await _sqlSugar.Queryable<User>().AnyAsync(x => x.Account == entity.Account))
{
throw Oops.Oh("账号已存在!");
}
return await _sqlSugar.Insertable(entity).ExecuteCommandAsync() > 0;
}
[HttpPut]
public async Task<bool> Modify([FromBody] UserInputDTO inputDTO)
{
var entity = inputDTO.Adapt<User>();
if (await _sqlSugar.Queryable<User>().AnyAsync(x => x.Account == entity.Account && x.Id != inputDTO.Id))
{
throw Oops.Oh("账号已存在!");
}
return await _sqlSugar.Updateable(entity)
.IgnoreColumns(x => new { x.Pwd }).ExecuteCommandAsync() > 0;
}
[HttpPut("pwd")]
public async Task<bool> ModifyPassword([FromBody] UserChangePwdDTO inputDTO)
{
var entity = inputDTO.Adapt<User>();
return await _sqlSugar.Updateable(entity)
.UpdateColumns(x => new { x.Pwd }).ExecuteCommandAsync() > 0;
}
[HttpDelete]
public async Task<bool> Delete([FromBody] params string[] ids)
{
return await _sqlSugar.Updateable<User>()
.SetColumns(x => x.IsDelete == true)
.Where(x => ids.Contains(x.Id)).ExecuteCommandHasChangeAsync();
}
/// <summary>
/// 权限修改
/// </summary>
/// <returns></returns>
[HttpPut("auth-prem")]
[Obsolete]
public async Task EditPremissions([FromBody] List<UserPremInputDTO> inputDTOs)
{
var entity = inputDTOs.Adapt<UserPrem>();
await _sqlSugar.Deleteable<UserPrem>()
.Where(x => inputDTOs.Select(x => x.UserId).Contains(x.UserId)).ExecuteCommandAsync();
await _sqlSugar.Insertable(entity).ExecuteCommandAsync();
}
}
}

View File

@ -0,0 +1,51 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SqlSugar.Extensions;
using WGShare.Domain.FriendlyException;
namespace WGShare.API.Controllers.Basic
{
[ApiController]
[Authorize]
public class BasicController : ControllerBase
{
public string UId
{
get
{
var uid = HttpContext.User.Claims.FirstOrDefault(x => x.Type == "uid").Value;
if (string.IsNullOrWhiteSpace(uid))
{
throw Oops.Oh("用户信息有误,请重新登录");
}
return uid;
}
}
public string RoleId
{
get
{
var roleId = HttpContext.User.Claims.FirstOrDefault(x => x.Type == "role").Value;
if (string.IsNullOrWhiteSpace(roleId))
{
throw Oops.Oh("用户信息有误,请重新登录");
}
return roleId;
}
}
public string TenantId
{
get
{
var tenant = HttpContext.User.Claims.FirstOrDefault(x => x.Type == "tenant").Value;
if (string.IsNullOrWhiteSpace(tenant))
{
throw Oops.Oh("用户信息有误,请重新登录");
}
return tenant;
}
}
}
}

View File

@ -0,0 +1,66 @@
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using WGShare.API.Controllers.Basic;
using WGShare.Domain.DTOs.Room;
using WGShare.Domain.Entities;
using WGShare.Domain.FriendlyException;
using WGShare.Domain.GeneralModel;
using Yitter.IdGenerator;
namespace WGShare.API.Controllers.Frontend
{
/// <summary>
/// 首页接口
/// </summary>
[Route("home")]
public class HomeController : BasicController
{
private readonly ISqlSugarClient _sqlSugar;
public HomeController(ISqlSugarClient sqlSugar)
{
_sqlSugar = sqlSugar;
}
/// <summary>
/// 获取会议室列表
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
[HttpGet("room")]
public async Task<PagedResult<RoomOutputDTO>> GetRooms(PagedBaseDto dto)
{
RefAsync<int> total = 0;
var list = await _sqlSugar.Queryable<Room>()
.Where(x => x.TenantId == TenantId && x.IsDelete == false)
.ToPageListAsync(dto.PageIndex, dto.PageSize, total);
return PagedResult<RoomOutputDTO>.Create(list.Adapt<List<RoomOutputDTO>>(), total.Value);
}
/// <summary>
/// 创建会议室
/// </summary>
/// <param name="inputDTO"></param>
/// <returns></returns>
[HttpPost("room")]
public async Task<bool> CreateRoom([FromBody] RoomInputDTO inputDTO)
{
var entity = inputDTO.Adapt<Room>();
entity.Id = YitIdHelper.NextId().ToString();
entity.TenantId = TenantId;
if (await _sqlSugar.Queryable<Room>().AnyAsync(x => x.RoomNum == inputDTO.RoomNum))
{
throw Oops.Oh("无效会议号,请重新输入");
}
return await _sqlSugar.Insertable(entity).ExecuteCommandAsync() > 0;
}
}
}

View File

@ -0,0 +1,163 @@
using Mapster;
using Masuit.Tools;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using System.CodeDom;
using WGShare.API.Controllers.Basic;
using WGShare.Domain.DTOs.File;
using WGShare.Domain.DTOs.Room;
using WGShare.Domain.DTOs.User;
using WGShare.Domain.Entities;
using WGShare.Domain.FriendlyException;
using WGShare.Domain.GeneralModel;
using Yitter.IdGenerator;
using ZstdSharp.Unsafe;
namespace WGShare.API.Controllers.Frontend
{
/// <summary>
/// 会议室接口
/// </summary>
[Route("room")]
public class RoomController : BasicController
{
private readonly ISqlSugarClient _sqlSugar;
public RoomController(ISqlSugarClient sqlSugar)
{
this._sqlSugar = sqlSugar;
}
/// <summary>
/// 获取会议室管理员
/// </summary>
/// <returns></returns>
[HttpGet("manager")]
public async Task<List<string>> GetRoomManager([FromQuery] string roomId)
{
return await _sqlSugar.Queryable<RoomManager>()
.Where(x => x.RoomId == roomId)
.Select(x => x.UserId)
.ToListAsync();
}
/// <summary>
/// 设置房间管理员
/// </summary>
/// <returns></returns>
[HttpPost("manager")]
public async Task<bool> SetRoomManager([FromQuery] string roomId, [FromBody] List<string> userIds)
{
var entities = userIds.ConvertAll(x => new RoomManager
{
RoomId = roomId,
UserId = x
});
return await _sqlSugar.Insertable(entities).ExecuteCommandAsync() > 0;
}
/// <summary>
/// 查询用户信息
/// </summary>
/// <returns></returns>
[HttpGet("user")]
public async Task<List<UserOutputDTO>> GetUsers([FromQuery] string uidStr)
{
var uid = uidStr.Split(',', StringSplitOptions.RemoveEmptyEntries);
if (uid.IsNullOrEmpty())
{
throw Oops.Oh("请输入需要查询的用户id,多id请用英文逗号,分割");
}
var users = await _sqlSugar.Queryable<User>()
.Where(x => uid.Contains(x.Id))
.ToListAsync();
return users.Adapt<List<UserOutputDTO>>();
}
/// <summary>
/// 检验房间是否存在
/// </summary>
/// <returns></returns>
[HttpGet("checkout"), AllowAnonymous]
public async Task<bool> ExistsRoom([FromQuery] string roomNum)
{
return await _sqlSugar.Queryable<Room>().AnyAsync(x => x.RoomNum == roomNum && x.IsDelete == false);
}
/// <summary>
/// 获取单个会议室信息
/// </summary>
/// <returns></returns>
[HttpGet("{roomNum}")]
public async Task<RoomOutputDTO> GetRoom([FromRoute] string roomNum)
{
var room = await _sqlSugar.Queryable<Room>().FirstAsync(x => x.RoomNum == roomNum && x.IsDelete == false);
if (room == null)
{
throw Oops.Oh("会议号无效");
}
return room.Adapt<RoomOutputDTO>();
}
/// <summary>
/// 分享上传文件
/// </summary>
/// <param name="inputDTO"></param>
/// <returns></returns>
[HttpPost("file")]
public async Task<bool> AddFile([FromBody] ShareFileInputDTO inputDTO)
{
var entity = inputDTO.Adapt<ShareFile>();
entity.Id = YitIdHelper.NextId().ToString();
entity.UserId = UId;
return await _sqlSugar.Insertable(entity).ExecuteCommandAsync() > 0;
}
/// <summary>
/// 删除文件
/// </summary>
/// <returns></returns>
[HttpDelete("file")]
public async Task<bool> DeleteFile([FromBody] List<string> ids)
{
return await _sqlSugar.Updateable<ShareFile>()
.SetColumns(x => x.IsDelete == true)
.Where(x => ids.Contains(x.Id))
.ExecuteCommandHasChangeAsync();
}
/// <summary>
/// 获取分享文件列表
/// </summary>
/// <returns></returns>
[HttpGet("file")]
public async Task<PagedResult<ShareFileOutputDTO>> GetFilesList([FromQuery] string roomId, [FromBody] PagedBaseDto pagedBaseDto)
{
RefAsync<int> total = 0;
var list = await _sqlSugar.Queryable<ShareFile>()
.LeftJoin<User>((sf, u) => sf.UserId == u.Id)
.Where(x => x.IsDelete == false && x.RoomId == roomId)
.Select((sf, u) => new ShareFileOutputDTO
{
Id = sf.Id,
UserId = u.Id,
UserName = u.UserName,
FileName = sf.FileName,
FileUrl = sf.FileUrl,
RoomId = u.Id,
Size = sf.Size,
ModifyTime = sf.ModifyTime,
DownloadCount = sf.DownloadCount,
}).ToPageListAsync(pagedBaseDto.PageIndex, pagedBaseDto.PageSize, total);
return PagedResult<ShareFileOutputDTO>.Create(list, total.Value);
}
}
}

View File

@ -0,0 +1,53 @@
using Masuit.Tools;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
namespace WGShare.API.Helpers
{
public class JwtHelper
{
private readonly IConfiguration _configuration;
public JwtHelper(IConfiguration configuration)
{
_configuration = configuration;
}
public string CreateToken(string uid, List<Claim> claims = null)
{
if (claims.IsNullOrEmpty())
claims = new();
claims.AddRange(new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim("uid", uid),
});
// 2. 从 appsettings.json 中读取SecretKey
var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:SecretKey"]));
// 3. 选择加密算法
var algorithm = SecurityAlgorithms.HmacSha256;
// 4. 生成Credentials
var signingCredentials = new SigningCredentials(secretKey, algorithm);
// 5. 根据以上生成token
var jwtSecurityToken = new JwtSecurityToken(
_configuration["Jwt:Issuer"], //Issuer
_configuration["Jwt:Audience"], //Audience
claims, //Claims,
DateTime.Now, //notBefore
DateTime.Now.AddSeconds(_configuration["Jwt:Expires"].ToDouble()), //expires
signingCredentials //Credentials
);
// 6. 将token变为string
var token = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
return token;
}
}
}

View File

@ -0,0 +1,47 @@
using FreeRedis;
namespace WGShare.API.Helpers
{
/// <summary>
/// redis静态访问类
/// </summary>
public abstract class RedisHelper
{
private static RedisClient _instance;
/// <summary>
/// redis实例
/// </summary>
public static RedisClient Instance
{
get
{
if (_instance == null)
{
throw new Exception("使用前初始化redis静态访问类 RedisHelper.Initialization(new FreeRedis.RedisClient(\"127.0.0.1:6379,password=123,defaultDatabase=13,maxpoolsize=50,prefix=key前辍\"));");
}
return _instance;
}
}
/// <summary>
/// 初始化redis静态访问类 RedisHelper.Initialization(new FreeRedis.RedisClient(\"127.0.0.1:6379,password=123,defaultDatabase=13,maxpoolsize=50,prefix=key前辍\"))
/// </summary>
/// <param name="redisClient"></param>
internal static void Initialization(FreeRedis.RedisClient redisClient)
{
_instance = redisClient;
}
internal static ThreadLocal<Random> rnd = new ThreadLocal<Random>(() => new Random());
/// <summary>
/// 随机秒防止所有key同一时间过期雪崩
/// </summary>
/// <param name="minTimeoutSeconds">最小秒数</param>
/// <param name="maxTimeoutSeconds">最大秒数</param>
/// <returns></returns>
public static int RandomExpired(int minTimeoutSeconds, int maxTimeoutSeconds) => rnd.Value.Next(minTimeoutSeconds, maxTimeoutSeconds);
}
}

81
WGShare.API/Program.cs Normal file
View File

@ -0,0 +1,81 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using SqlSugar;
using WGShare.API.Helpers;
using WGShare.API.ServiceConfigs;
using Yitter.IdGenerator;
namespace WGShare.API
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
var configuration = builder.Configuration;
// Add services to the container.
builder.Services.AddControllers(options =>
{
// 全局异常捕获,无需在代码中 写 try catch
options.Filters.Add<GlobalExceptionFilter>();
// 全局模型赋值默认值 和 统一返回格式处理
options.Filters.Add<ModelActionFilter>();
}).AddNewtonsoftJson(options =>
{
//修改属性名称的序列化方式,首字母小写,即驼峰样式
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
//日期类型默认格式化处理 方式1
options.SerializerSettings.Converters.Add(new IsoDateTimeConverter() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });
//忽略循环引用
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
//空值处理
//options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
});
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSingleton(new JwtHelper(configuration));
builder.Services.AddAuth(configuration["Jwt:Issuer"],
configuration["Jwt:Audience"],
configuration["Jwt:SecretKey"]);
builder.Services.AddSqlsugar(builder.Environment.EnvironmentName, new ConnectionConfig
{
DbType = DbType.MySql,
ConfigId = "metting",
ConnectionString = configuration.GetConnectionString("metting"),
IsAutoCloseConnection = true
},
new ConnectionConfig
{
DbType = DbType.MySql,
ConfigId = "usercenter",
ConnectionString = configuration.GetConnectionString("usercenter"),
IsAutoCloseConnection = true
});
YitIdHelper.SetIdGenerator(new IdGeneratorOptions(1));
RedisHelper.Initialization(new FreeRedis.RedisClient(configuration["Redis:master"]));
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
app.UseCustomCors();
}
//调用中间件UseAuthentication认证必须在所有需要身份认证的中间件前调用比如 UseAuthorization授权
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
}
}

View File

@ -0,0 +1,31 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:42628",
"sslPort": 0
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5192",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -0,0 +1,52 @@
using Mapster;
using MapsterMapper;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using System.Reflection.Metadata;
namespace WGShare.API.ServiceConfigs
{
public static class AuthenticationServiceExtensions
{
/// <summary>
/// 添加认证和授权
/// </summary>
/// <param name="services">服务集合</param>
/// <returns></returns>
public static IServiceCollection AddAuth(this IServiceCollection services, string issuer, string audience, string secretKey)
{
services.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true, //是否验证Issuer
ValidIssuer = issuer, //发行人Issuer
ValidateAudience = true, //是否验证Audience
ValidAudience = audience, //订阅人Audience
ValidateIssuerSigningKey = true, //是否验证SecurityKey
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey)), //SecurityKey
ValidateLifetime = true, //是否验证失效时间
ClockSkew = TimeSpan.FromSeconds(30), //过期时间容错值,解决服务器端时间不同步问题(秒)
RequireExpirationTime = true,
};
});
return services;
//services.AddAuthorization(options =>
//{
// options.AddPolicy(Constant.Policy.FreePolicyName,
// policy => policy.RequireClaim(Constant.Auth.PermissionsKey, Constant.Auth.FreeClaimValue, Constant.Auth.VipClaimValue));
// options.AddPolicy(Constant.Policy.VipPolicyName,
// policy => policy.RequireClaim(Constant.Auth.PermissionsKey, Constant.Auth.VipClaimValue));
//});
}
}
}

View File

@ -0,0 +1,30 @@
using Microsoft.AspNetCore.Builder;
namespace WGShare.API.ServiceConfigs
{
/// <summary>
/// 跨域配置扩展服务
/// </summary>
public static class CorsAppBuilderExtensions
{
/// <summary>
/// 允许所有跨域请求 (属于基础服务,若已调用 UseBasicServices 则无需调用)
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public static IApplicationBuilder UseCustomCors(this IApplicationBuilder app)
{
//// 获取配置文件中的允许跨域的地址
//var hosts = AppSetting.AllowedHosts.Split("|", StringSplitOptions.RemoveEmptyEntries);
app.UseCors(options =>
{
options.WithOrigins("*") // 允许跨域请求的地址
.AllowAnyHeader() // 允许的请求标头
.AllowAnyMethod(); // 允许跨域请求的类型 (GET,POST等)
});
return app;
}
}
}

View File

@ -0,0 +1,68 @@
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;
using WGShare.Domain.GeneralModel;
using Masuit.Tools;
using WGShare.Domain.FriendlyException.Exceptions;
using WGShare.Domain.FriendlyException;
namespace WGShare.API.ServiceConfigs
{
/// <summary>
/// 全局异常捕获
/// </summary>
public class GlobalExceptionFilter : IAsyncExceptionFilter
{
private readonly ILogger<GlobalExceptionFilter> _logger;
public GlobalExceptionFilter(ILogger<GlobalExceptionFilter> logger)
{
_logger = logger; //在构造函数中注入日志处理实例
}
public async Task OnExceptionAsync(ExceptionContext context)
{
// 如果异常没有被处理则进行处理
if (context.ExceptionHandled == false)
{
// 定义返回类型
UniformResult<object> result;
// 如果为业务逻辑抛出的内部异常
if (context.Exception is FriendlyInternalException ex)
{
// 企业微信异常通知
//await ExceptionNotice.SendFriendlyExceptionAsync(ex);
result = UniformResult<object>
.Create(ex.FriendlyData, ex.ErrorCode, context.Exception.Message);
}
else
{
// 程序异常,不对外暴露程序异常细节
result = UniformResult<object>
.Create(null, 500, "程序出错啦🐞🐞🐞!");
//使用日志对象 _logger 的 LogError() 方法将异常信息写入日志文件
_logger.LogError(context.Exception, context.Exception.Message);
// 企业微信异常通知
await ExceptionNotice.SendAsync(context.Exception, "全局异常捕获");
}
context.Result = new ContentResult
{
// 返回状态码设置为200表示成功
StatusCode = StatusCodes.Status200OK,
// 设置返回格式
ContentType = "application/json;charset=utf-8",
Content = result.ToJsonString()
};
}
// 设置为true表示异常已经被处理了
context.ExceptionHandled = true;
}
}
}

View File

@ -0,0 +1,60 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using WGShare.Domain.GeneralModel;
namespace WGShare.API.ServiceConfigs
{
public class ModelActionFilter : ActionFilterAttribute
{
/// <summary>
/// 在Controller的Action执行后执行
/// </summary>
/// <param name="context"></param>
public override void OnActionExecuted(ActionExecutedContext context)
{
//特殊处理对有ApiResultIgnoreAttribute标签的不进行返回结果包装原样输出
//var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
//if (controllerActionDescriptor != null)
//{
// var isDefined = controllerActionDescriptor.EndpointMetadata.Any(a => a.GetType().Equals(typeof(ApiResultIgnoreAttribute)));
// if (isDefined)
// {
// return;
// }
//}
// 返回结果为JsonResult的请求进行Result包装
if (context.Result != null)
{
switch (context.Result)
{
case ObjectResult:
{
var result = context.Result as ObjectResult;
context.Result = new JsonResult(UniformResult<object>.Create(result.Value));
break;
}
case EmptyResult:
context.Result = new JsonResult(UniformResult<object>.Create(null));
break;
case ContentResult:
{
var result = context.Result as ContentResult;
context.Result = new JsonResult(UniformResult<object>.Create(result.Content));
break;
}
}
}
base.OnActionExecuted(context);
}
/// <summary>
/// 在Controller的Action执行前执行
/// </summary>
/// <param name="context"></param>
public override void OnActionExecuting(ActionExecutingContext context)
{
base.OnActionExecuting(context);
}
}
}

View File

@ -0,0 +1,66 @@
using Mapster;
using MapsterMapper;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using System.Reflection.Metadata;
using SqlSugar;
using System.Text.RegularExpressions;
namespace WGShare.API.ServiceConfigs
{
public static class SqlsugarServiceExtensions
{
/// <summary>
/// 添加SqlSugar
/// </summary>
/// <param name="services">服务集合</param>
/// <returns></returns>
public static IServiceCollection AddSqlsugar(this IServiceCollection services, string env, params ConnectionConfig[] connectionConfigs)
{
SqlSugarScope sqlSugar = new SqlSugarScope(connectionConfigs.ToList(),
db =>
{
if (env == Environments.Development)
{
// 正则表达式匹配Ip
var ipMatch = Regex.Match(db.CurrentConnectionConfig.ConnectionString, @"((25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))");
var connections = db.CurrentConnectionConfig.ConnectionString.Split(';');
string dbNamne = string.Empty;
foreach (var item in connections)
{
if (item.Contains("Database"))
{
dbNamne = item.Split('=')[1];
}
}
//SQL执行前
db.Aop.OnLogExecuting = (sql, pars) =>
{
// 打印 Sql 语句
Console.WriteLine($@"{new string('=', 10)}BEGIN{new string('=', 5)} DB-IP{ipMatch.Value} {new string('=', 5)} DB-Name:{dbNamne} {new string('=', 15)}");
Console.WriteLine($"执行Sql:{Environment.NewLine}{sql}");
Console.WriteLine($"参数:{db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value))}");
};
//SQL执行完成
db.Aop.OnLogExecuted = (sql, pars) =>
{
//执行完了可以输出SQL执行时间
Console.WriteLine("Sql用时:" + db.Ado.SqlExecutionTime.ToString());
Console.WriteLine($@"{new string('=', 10)}END{new string('=', 7)} DB-IP{ipMatch.Value} {new string('=', 5)} DB-Name:{dbNamne} {new string('=', 15)}");
};
}
});
services.AddSingleton<ISqlSugarClient>(sqlSugar);
return services;
}
}
}

View File

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WGShare.Domain\WGShare.Domain.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,15 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"ConnectionStrings": {
"metting": "Database=metting;Server=192.168.2.9;Port=3306;Uid=root;Pwd=qwe123!@#;AllowZeroDateTime=True;ConvertZeroDateTime=True;",
"usercenter": "Database=usercenter;Server=192.168.2.9;Port=3306;Uid=root;Pwd=qwe123!@#;AllowZeroDateTime=True;ConvertZeroDateTime=True;"
},
"Redis": {
"master": "192.168.2.7:6379,password=qwe123!@#,defaultDatabase=12,name=wgshare,prefix=wgshare"
}
}

View File

@ -0,0 +1,23 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Jwt": {
"SecretKey": "apDbztyqjSNuvWnezhbdUxduhDidZbF897t2uTJs53RMdY9Cai7eexavBhka3HN6mcTe9oohjFg6bNffRRkcfMqnVKNBnmyPzkRgNopHGJAL7KMwkeZdZ7BaWnT57jCi",
"Issuer": "WGshareApi",
"Audience": "WGshareClient",
//
"Expires": 14400
},
"ConnectionStrings": {
"metting": "Database=metting;Server=192.168.2.9;Port=3306;Uid=root;Pwd=qwe123!@#;AllowZeroDateTime=True;ConvertZeroDateTime=True;",
"usercenter": "Database=usercenter;Server=192.168.2.9;Port=3306;Uid=root;Pwd=qwe123!@#;AllowZeroDateTime=True;ConvertZeroDateTime=True;"
},
"Redis": {
"master": ""
}
}

View File

@ -0,0 +1,29 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WGShare.Domain.DTOs.File
{
public class ShareFileInputDTO
{
/// <summary>
/// 文件地址
///</summary>
public string FileUrl { get; set; }
/// <summary>
/// 文件大小 kb
///</summary>
public double Size { get; set; }
/// <summary>
/// 文件名称
///</summary>
public string FileName { get; set; }
/// <summary>
/// 会议房间Id
///</summary>
public string RoomId { get; set; }
}
}

View File

@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WGShare.Domain.DTOs.File
{
public class ShareFileOutputDTO
{
public string Id { get; set; }
/// <summary>
/// 文件地址
///</summary>
public string FileUrl { get; set; }
/// <summary>
/// 文件大小 kb
///</summary>
public double Size { get; set; }
/// <summary>
/// 文件名称
///</summary>
public string FileName { get; set; }
/// <summary>
/// 会议房间Id
///</summary>
public string RoomId { get; set; }
public string UserId { get; set; }
/// <summary>
/// 上传者名称
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 更新时间
/// </summary>
public DateTime ModifyTime { get; set; }
public int DownloadCount { get; set; }
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WGShare.Domain.DTOs.Login
{
public class AnonymousLoginDTO
{
public string NickName { get; set; }
public string MachineName { get; set; }
public string Mac { get; set; }
public string RoomId { get; set; }
}
}

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WGShare.Domain.DTOs.Login
{
public class UserLoginDTO
{
public string Account { get; set; }
public string Pwd { get; set; }
}
}

View File

@ -0,0 +1,26 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yitter.IdGenerator;
namespace WGShare.Domain.DTOs.Perm
{
public class PermissionInputDTO
{
/// <summary>
/// 菜单/按钮Id
///</summary>
public string? Id { get; set; }
/// <summary>
/// 权限名称
///</summary>
public string PermName { get; set; }
/// <summary>
/// 权限值
///</summary>
public int PermValue { get; set; }
}
}

View File

@ -0,0 +1,22 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yitter.IdGenerator;
namespace WGShare.Domain.DTOs.Role
{
public class RoleInputDTO
{
/// <summary>
///
///</summary>
public string? Id { get; set; }
/// <summary>
/// 角色名
///</summary>
public string RoleName { get; set; }
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WGShare.Domain.DTOs.Role
{
public class RolePermInputDTO
{
public string RoleId { get; set; }
public string PermId { get; set; }
}
}

View File

@ -0,0 +1,24 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yitter.IdGenerator;
namespace WGShare.Domain.DTOs.Room
{
public class RoomInputDTO
{
/// <summary>
/// 会议室名称
///</summary>
[SugarColumn(ColumnName = "room_name")]
public string RoomName { get; set; }
/// <summary>
/// 会议号
///</summary>
[SugarColumn(ColumnName = "room_num")]
public string RoomNum { get; set; }
}
}

View File

@ -0,0 +1,24 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yitter.IdGenerator;
namespace WGShare.Domain.DTOs.Room
{
public class RoomOutputDTO
{
public string Id { get; set; }
/// <summary>
/// 会议室名称
///</summary>
public string RoomName { get; set; }
/// <summary>
/// 会议号
/// </summary>
public string RoomNum { get; set; }
}
}

View File

@ -0,0 +1,23 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yitter.IdGenerator;
namespace WGShare.Domain.DTOs.Tenant
{
public class TenantInputDTO
{
/// <summary>
///
///</summary>
public string? Id { get; set; }
/// <summary>
/// 租户名称
///</summary>
public string TenantName { get; set; }
}
}

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WGShare.Domain.DTOs.User
{
public class UserChangePwdDTO
{
public string Id { get; set; }
public string Pwd { get; set; }
}
}

View File

@ -0,0 +1,35 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WGShare.Domain.DTOs.User
{
public class UserInputDTO
{
public string? Id { get; set; }
/// <summary>
/// 用户名称
///</summary>
public string UserName { get; set; }
/// <summary>
/// 账号
///</summary>
public string Account { get; set; }
/// <summary>
/// 密码
///</summary>
public string Pwd { get; set; }
/// <summary>
///
///</summary>
public string RoleId { get; set; }
/// <summary>
/// 租户id
///</summary>
public string TenantId { get; set; }
}
}

View File

@ -0,0 +1,25 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WGShare.Domain.DTOs.User
{
public class UserOutputDTO
{
public string Id { get; set; }
/// <summary>
/// 用户名称
///</summary>
public string UserName { get; set; }
/// <summary>
/// 账号
///</summary>
public string Account { get; set; }
public string RoleId { get; set; }
public string RoleName { get; set; }
}
}

View File

@ -0,0 +1,22 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WGShare.Domain.DTOs.User
{
public class UserPremInputDTO
{
/// <summary>
/// 用户Id
///</summary>
public string UserId { get; set; }
/// <summary>
/// 权限Id
///</summary>
public string PermId { get; set; }
}
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WGShare.Domain.GeneralModel;
namespace WGShare.Domain.DTOs.User
{
public class UserSearchDTO: PagedBaseDto
{
public string? keyword { get; set; }
public string? TenantId { get; set; }
public string? RoleId { get; set; }
}
}

View File

@ -0,0 +1,38 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yitter.IdGenerator;
namespace WGShare.Domain.Entities
{
/// <summary>
/// 超级管理员
///</summary>
[SugarTable("admin")]
public class Admin
{
/// <summary>
///
///</summary>
[SugarColumn(ColumnName = "id", IsPrimaryKey = true)]
public string Id { get; set; }
/// <summary>
///
///</summary>
[SugarColumn(ColumnName = "Name")]
public string Name { get; set; }
/// <summary>
///
///</summary>
[SugarColumn(ColumnName = "Account")]
public string Account { get; set; }
/// <summary>
///
///</summary>
[SugarColumn(ColumnName = "Password")]
public string Password { get; set; }
}
}

View File

@ -0,0 +1,40 @@
using SqlSugar;
using WGShare.Domain.Enums;
using Yitter.IdGenerator;
namespace WGShare.Domain.Entities
{
/// <summary>
/// 权限表
///</summary>
[SugarTable("permission")]
public class Permission
{
/// <summary>
/// 菜单/按钮Id
///</summary>
[SugarColumn(ColumnName = "id", IsPrimaryKey = true)]
public string Id { get; set; } = YitIdHelper.NextId().ToString();
/// <summary>
/// 创建时间
/// 默认值: CURRENT_TIMESTAMP
///</summary>
[SugarColumn(ColumnName = "create_time", IsOnlyIgnoreInsert = true, IsOnlyIgnoreUpdate = true)]
public DateTime CreateTime { get; set; }
/// <summary>
/// 修改时间
///</summary>
[SugarColumn(ColumnName = "modify_time", IsOnlyIgnoreInsert = true, IsOnlyIgnoreUpdate = true)]
public DateTime ModifyTime { get; set; }
/// <summary>
/// 权限名称
///</summary>
[SugarColumn(ColumnName = "perm_name")]
public string PermName { get; set; }
/// <summary>
/// 权限值
///</summary>
[SugarColumn(ColumnName = "perm_value")]
public int PermValue { get; set; }
}
}

View File

@ -0,0 +1,40 @@
using SqlSugar;
using Yitter.IdGenerator;
namespace WGShare.Domain.Entities
{
/// <summary>
/// 用户角色表
///</summary>
[SugarTable("role")]
public class Role
{
/// <summary>
///
///</summary>
[SugarColumn(ColumnName = "id", IsPrimaryKey = true)]
public string Id { get; set; } = YitIdHelper.NextId().ToString();
/// <summary>
/// 是否删除
/// 默认值: b'0'
///</summary>
[SugarColumn(ColumnName = "is_delete")]
public bool IsDelete { get; set; }
/// <summary>
/// 创建时间
/// 默认值: CURRENT_TIMESTAMP
///</summary>
[SugarColumn(ColumnName = "create_time", IsOnlyIgnoreInsert = true, IsOnlyIgnoreUpdate = true)]
public DateTime CreateTime { get; set; }
/// <summary>
/// 修改时间
///</summary>
[SugarColumn(ColumnName = "modify_time", IsOnlyIgnoreInsert = true, IsOnlyIgnoreUpdate = true)]
public DateTime ModifyTime { get; set; }
/// <summary>
/// 角色名
///</summary>
[SugarColumn(ColumnName = "role_name")]
public string RoleName { get; set; }
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SqlSugar;
namespace WGShare.Domain.Entities
{
/// <summary>
/// 角色权限关系表
///</summary>
[SugarTable("role_perm")]
public class RolePrem
{
/// <summary>
/// 角色Id
///</summary>
[SugarColumn(ColumnName = "role_id", IsPrimaryKey = true)]
public string RoleId { get; set; }
/// <summary>
/// 权限Id
///</summary>
[SugarColumn(ColumnName = "perm_id", IsPrimaryKey = true)]
public string PermId { get; set; }
}
}

View File

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SqlSugar;
using Yitter.IdGenerator;
namespace WGShare.Domain.Entities
{
/// <summary>
/// 会议室房间表
///</summary>
[SugarTable("room")]
public class Room
{
/// <summary>
///
///</summary>
[SugarColumn(ColumnName = "id", IsPrimaryKey = true)]
public string Id { get; set; } = YitIdHelper.NextId().ToString();
/// <summary>
/// 是否删除
/// 默认值: b'0'
///</summary>
[SugarColumn(ColumnName = "is_delete")]
public bool IsDelete { get; set; }
/// <summary>
/// 创建时间
/// 默认值: CURRENT_TIMESTAMP
///</summary>
[SugarColumn(ColumnName = "create_time", IsOnlyIgnoreInsert = true, IsOnlyIgnoreUpdate = true)]
public DateTime CreateTime { get; set; }
/// <summary>
/// 修改时间
///</summary>
[SugarColumn(ColumnName = "modify_time", IsOnlyIgnoreInsert = true, IsOnlyIgnoreUpdate = true)]
public DateTime ModifyTime { get; set; }
/// <summary>
/// 会议室名称
///</summary>
[SugarColumn(ColumnName = "room_name")]
public string RoomName { get; set; }
/// <summary>
/// 租户id
///</summary>
[SugarColumn(ColumnName = "tenant_id")]
public string TenantId { get; set; }
/// <summary>
/// 会议号
///</summary>
[SugarColumn(ColumnName = "room_num")]
public string RoomNum { get; set; }
}
}

View File

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SqlSugar;
using Yitter.IdGenerator;
namespace WGShare.Domain.Entities
{
/// <summary>
/// 会议室管理员关系表
///</summary>
[SugarTable("room_manager")]
public class RoomManager
{
/// <summary>
/// 用户Id
///</summary>
[SugarColumn(ColumnName = "user_id", IsPrimaryKey = true)]
public string UserId { get; set; }
/// <summary>
/// 房间Id
///</summary>
[SugarColumn(ColumnName = "room_id", IsPrimaryKey = true)]
public string RoomId { get; set; }
}
}

View File

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SqlSugar;
using Yitter.IdGenerator;
namespace WGShare.Domain.Entities
{
/// <summary>
/// 会议室文件分享
///</summary>
[SugarTable("share_file")]
public class ShareFile
{
/// <summary>
///
///</summary>
[SugarColumn(ColumnName = "id", IsPrimaryKey = true)]
public string Id { get; set; } = YitIdHelper.NextId().ToString();
/// <summary>
/// 是否删除
/// 默认值: b'0'
///</summary>
[SugarColumn(ColumnName = "is_delete")]
public bool IsDelete { get; set; }
/// <summary>
/// 创建时间
/// 默认值: CURRENT_TIMESTAMP
///</summary>
[SugarColumn(ColumnName = "create_time", IsOnlyIgnoreInsert = true, IsOnlyIgnoreUpdate = true)]
public DateTime CreateTime { get; set; }
/// <summary>
/// 修改时间
///</summary>
[SugarColumn(ColumnName = "modify_time", IsOnlyIgnoreInsert = true, IsOnlyIgnoreUpdate = true)]
public DateTime ModifyTime { get; set; }
/// <summary>
/// 文件地址
///</summary>
[SugarColumn(ColumnName = "file_url")]
public string FileUrl { get; set; }
/// <summary>
/// 上传者id
///</summary>
[SugarColumn(ColumnName = "user_id")]
public string UserId { get; set; }
/// <summary>
/// 文件大小 kb
///</summary>
[SugarColumn(ColumnName = "size")]
public double Size { get; set; }
/// <summary>
/// 文件名称
///</summary>
[SugarColumn(ColumnName = "file_name")]
public string FileName { get; set; }
/// <summary>
/// 会议房间Id
///</summary>
[SugarColumn(ColumnName = "room_id")]
public string RoomId { get; set; }
/// <summary>
/// 下载次数
///</summary>
[SugarColumn(ColumnName = "download_count")]
public int DownloadCount { get; set; }
}
}

View File

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SqlSugar;
using Yitter.IdGenerator;
namespace WGShare.Domain.Entities
{
/// <summary>
/// 租户表
///</summary>
[SugarTable("tenant")]
public class Tenant
{
/// <summary>
///
///</summary>
[SugarColumn(ColumnName = "id", IsPrimaryKey = true)]
public string Id { get; set; } = YitIdHelper.NextId().ToString();
/// <summary>
/// 是否删除
/// 默认值: b'0'
///</summary>
[SugarColumn(ColumnName = "is_delete")]
public bool IsDelete { get; set; }
/// <summary>
/// 创建时间
/// 默认值: CURRENT_TIMESTAMP
///</summary>
[SugarColumn(ColumnName = "create_time", IsOnlyIgnoreInsert = true, IsOnlyIgnoreUpdate = true)]
public DateTime CreateTime { get; set; }
/// <summary>
/// 修改时间
///</summary>
[SugarColumn(ColumnName = "modify_time", IsOnlyIgnoreInsert = true, IsOnlyIgnoreUpdate = true)]
public DateTime ModifyTime { get; set; }
/// <summary>
/// 租户名称
///</summary>
[SugarColumn(ColumnName = "tenant_name")]
public string TenantName { get; set; }
}
}

View File

@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SqlSugar;
using Yitter.IdGenerator;
namespace WGShare.Domain.Entities
{
/// <summary>
/// 用户表
///</summary>
[SugarTable("user")]
public class User
{
/// <summary>
///
///</summary>
[SugarColumn(ColumnName = "id", IsPrimaryKey = true)]
public string Id { get; set; } = YitIdHelper.NextId().ToString();
/// <summary>
/// 是否删除
/// 默认值: b'0'
///</summary>
[SugarColumn(ColumnName = "is_delete")]
public bool IsDelete { get; set; }
/// <summary>
/// 创建时间
/// 默认值: CURRENT_TIMESTAMP
///</summary>
[SugarColumn(ColumnName = "create_time", IsOnlyIgnoreInsert = true, IsOnlyIgnoreUpdate = true)]
public DateTime CreateTime { get; set; }
/// <summary>
/// 修改时间
///</summary>
[SugarColumn(ColumnName = "modify_time", IsOnlyIgnoreInsert = true, IsOnlyIgnoreUpdate = true)]
public DateTime ModifyTime { get; set; }
/// <summary>
/// 用户名称
///</summary>
[SugarColumn(ColumnName = "user_name")]
public string UserName { get; set; }
/// <summary>
/// 账号
///</summary>
[SugarColumn(ColumnName = "account")]
public string Account { get; set; }
/// <summary>
/// 密码
///</summary>
[SugarColumn(ColumnName = "pwd")]
public string Pwd { get; set; }
/// <summary>
///
///</summary>
[SugarColumn(ColumnName = "role_id")]
public string RoleId { get; set; }
/// <summary>
/// 租户id
///</summary>
[SugarColumn(ColumnName = "tenant_id")]
public string TenantId { get; set; }
[SugarColumn(IsIgnore = true)]
public string RoleName { get; set; }
[SugarColumn(IsIgnore = true)]
public string TenantName { get; set; }
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SqlSugar;
namespace WGShare.Domain.Entities
{
/// <summary>
/// 用户权限关系表
///</summary>
[SugarTable("user_perm")]
public class UserPrem
{
/// <summary>
/// 用户Id
///</summary>
[SugarColumn(ColumnName = "user_id", IsPrimaryKey = true)]
public string UserId { get; set; }
/// <summary>
/// 权限Id
///</summary>
[SugarColumn(ColumnName = "perm_id", IsPrimaryKey = true)]
public string PermId { get; set; }
}
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WGShare.Domain.Enums
{
/// <summary>
/// 菜单类型
/// </summary>
public enum MenuType
{
Menu = 0,
Button
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WGShare.Domain.FriendlyException
{
/// <summary>
/// 错误代码
/// </summary>
public class ErrorCode
{
/// <summary>
/// 业务逻辑错误
/// </summary>
public const int x1000 = 1000;
}
}

View File

@ -0,0 +1,44 @@
using System.Net.Http.Json;
namespace WGShare.Domain.FriendlyException
{
/// <summary>
/// 异常通知
/// </summary>
public class ExceptionNotice
{
private static HttpClient httpClient = new HttpClient()
{
BaseAddress = new Uri("https://oapi.dingtalk.com/robot/send?access_token=6ddafcada8f44f4bad4a7314c4d9bd19a895ded0a1ba1afdaff5dd01a5af6781"),
};
/// <summary>
/// 发送异常信息
/// </summary>
/// <param name="exp">异常</param>
/// <param name="expSrc">异常来源(用于显示)</param>
/// <returns></returns>
public static async Task<bool> SendAsync(Exception exp, string expSrc)
{
#if DEBUG
Console.WriteLine("*************** Excpetion ***************");
Console.WriteLine(exp.Message, exp);
Console.WriteLine("*************** Excpetion ***************");
return true;
#endif
var reponse = await httpClient.PostAsync(string.Empty, JsonContent.Create(new
{
msgtype = "markdown",
markdown = new
{
title = "WGShare异常",
text = $"WGShare异常.描述:{exp.Message}\n详情:{exp}"
},
}));
return reponse.IsSuccessStatusCode;
}
}
}

View File

@ -0,0 +1,19 @@
using System;
namespace WGShare.Domain.FriendlyException.Exceptions
{
/// <summary>
/// Api内部错误错误细节不暴露给外部
/// </summary>
public class FriendlyInternalException : Exception
{
public int ErrorCode { get; private set; }
public object FriendlyData { get; private set; }
public FriendlyInternalException(string message, object friendlyData = null, int errorCode = FriendlyException.ErrorCode.x1000) : base(message)
{
ErrorCode = errorCode;
FriendlyData = friendlyData;
}
}
}

View File

@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WGShare.Domain.FriendlyException.Exceptions;
namespace WGShare.Domain.FriendlyException
{
/// <summary>
/// 异常抛出帮助类
/// </summary>
public static class Oops
{
public static FriendlyInternalException Oh(string message)
{
return new FriendlyInternalException(message);
}
/// <summary>
/// 删除失败异常
/// </summary>
/// <returns></returns>
public static FriendlyInternalException OhDeleteFailed()
{
return new FriendlyInternalException("删除失败!");
}
/// <summary>
/// 数据不存在异常
/// </summary>
/// <returns></returns>
public static FriendlyInternalException OhDataNotExists()
{
return new FriendlyInternalException("数据不存在!");
}
/// <summary>
/// 更新失败异常
/// </summary>
/// <returns></returns>
public static FriendlyInternalException OhUpdateFailed()
{
return new FriendlyInternalException("更新失败!");
}
/// <summary>
/// 新增失败异常
/// </summary>
/// <returns></returns>
public static FriendlyInternalException OhAddFailed()
{
return new FriendlyInternalException("新增失败!");
}
/// <summary>
/// 业务处理失败自定义消息
/// </summary>
/// <returns></returns>
public static FriendlyInternalException OhBusinessFailed(string msg, object data)
{
return new FriendlyInternalException(msg, data, 200);
}
/// <summary>
/// 操作失败
/// </summary>
/// <returns></returns>
public static FriendlyInternalException OperationFailed()
{
return new FriendlyInternalException("操作失败!");
}
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WGShare.Domain.GeneralModel
{
/// <summary>
/// 分页查询基础DTO
/// </summary>
public class PagedBaseDto
{
/// <summary>
/// 当前页码
/// </summary>
public int PageIndex { get; set; } = 1;
/// <summary>
/// 分页大小
/// </summary>
public int PageSize { get; set; } = 10;
}
}

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace WGShare.Domain.GeneralModel
{
/// <summary>
/// 统一分页返回结果模型
/// </summary>
/// <typeparam name="TEntity"></typeparam>
public class PagedResult<TEntity>
{
public PagedResult() { }
public PagedResult(IEnumerable<TEntity> list, int total)
{
Total = total;
Items = list;
}
public int Total { get; set; }
public IEnumerable<TEntity> Items { get; private set; }
public static PagedResult<TEntity> Create(IEnumerable<TEntity> list, int total)
{
return new PagedResult<TEntity>(list, total);
}
}
}

View File

@ -0,0 +1,46 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WGShare.Domain.GeneralModel
{
/// <summary>
/// 统一返回结果模型
/// </summary>
/// <typeparam name="T"></typeparam>
public class UniformResult<T>
{
public UniformResult(T data, int code = 200, string msg = "success")
{
this.data = data;
this.code = code;
message = msg;
}
/// <summary>
/// 消息
/// </summary>
public string message { get; set; } = "success";
/// <summary>
/// 返回代码
/// </summary>
public int code { get; set; }
/// <summary>
/// 数据
/// </summary>
public T data { get; set; }
public static UniformResult<T> Create(T data, int code = 200, string msg = "success")
{
return new UniformResult<T>(data, code, msg);
}
}
}

View File

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FreeRedis" Version="1.2.15" />
<PackageReference Include="Mapster" Version="7.4.0" />
<PackageReference Include="Masuit.Tools.Core" Version="2024.3.4" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.6" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.6" />
<PackageReference Include="SqlSugarCore" Version="5.1.4.158" />
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
</ItemGroup>
</Project>