新建项目 Shop.Admin
新建 Api,Model,Interface, Service 层
数据库模型设计(角色 用户 菜单)
SqlSugar 安装
公用表
public class IBase
{
/// <summary>
/// 主键
/// </summary>
[SugarColumn(IsPrimaryKey = true)]
public string Id { get; set; }
}
/// <summary>
/// 公用
/// </summary>
public class IEntity:IBase
{
/// <summary>
/// 描述
/// </summary>
[SugarColumn(IsNullable =true)]
public string Description { get; set; }
/// <summary>
/// 创建人ID
/// </summary>
[SugarColumn(IsNullable =false)]
public string CreateUserId { get; set; }
/// <summary>
/// 修改人id
/// </summary>
[SugarColumn(IsNullable =true)]
public string ModifyUserId { get; set; }
/// <summary>
/// 创建日期
/// </summary>
[SugarColumn(IsNullable = false)]
public DateTime CreateTime { get; set; }
/// <summary>
/// 修改日期
/// </summary>
[SugarColumn(IsNullable =false)]
public DateTime ModifyDate { get; set; }
/// <summary>
/// 是否删除
/// </summary>
[SugarColumn(IsNullable =false)]
public bool IsDeleted { get; set; }
}
用户表设计
/// <summary>
/// 用户表
/// </summary>
public class Users:IEntity
{
/// <summary>
/// 用户名
/// </summary>
[SugarColumn(IsNullable =false)]
public string Name { get; set; }
/// <summary>
/// 昵称
/// </summary>
[SugarColumn(IsNullable =false)]
public string NickName { get; set; }
/// <summary>
/// 密码
/// </summary>
[SugarColumn(IsNullable =false)]
public string Password { get; set; }
/// <summary>
/// 用户类型(0=超级管理员,1=普通用户)
/// </summary>
[SugarColumn(IsNullable =false)]
public int UserType { get; set; }
/// <summary>
/// 是否启用(0=未启用,1=启用)
/// </summary>
[SugarColumn(IsNullable =false)]
public bool IsEnable { get; set; }
/// <summary>
/// 头像
/// </summary>
[SugarColumn(IsNullable = true)]
public string Avatar { get; set; }
角色表设计
/// <summary>
/// 角色表
/// </summary>
public class Role:IEntity
{
/// <summary>
/// 名称
/// </summary>
[SugarColumn(IsNullable =false)]
public string Name { get; set; }
/// <summary>
/// 排序
/// </summary>
[SugarColumn(IsNullable =false)]
public int Order { get; set; }
/// <summary>
/// 是否启用 (0=未启用,1=启用)
/// </summary>
[SugarColumn(IsNullable =false)]
public bool IsEnable { get; set; }
//用例1:主键模式 Role(主表)表中的 和CreateUserId 和Users(子表)中的主键关联
[Navigate(NavigateType.OneToOne, nameof(CreateUserId))]//一对一
public Users UserInfo { get; set; }
菜单表设计
/// <summary>
/// 菜单表
/// </summary>
public class Menu:IEntity
{
/// <summary>
/// 名称
/// </summary>
[SugarColumn(IsNullable =false)]
public string Title { get; set; }
/// <summary>
/// 页面路径
/// </summary>
[SugarColumn(IsNullable =false,Length =500)]
public string Path { get; set; }
/// <summary>
/// 路由地址
/// </summary>
[SugarColumn(IsNullable =false)]
public string Component { get; set; }
/// <summary>
/// 父级Id
/// </summary>
[SugarColumn(IsNullable =false)]
public string ParentId { get; set; }
/// <summary>
/// 排序
/// </summary>
[SugarColumn(IsNullable =false)]
public int Order { get; set; }
/// <summary>
/// 是否启用(0=未启用,1=启用)
/// </summary>
[SugarColumn(IsNullable = false)]
public bool IsEnable { get; set; }
/// <summary>
/// 图标
/// </summary>
[SugarColumn(IsNullable = false)]
public string Icon { get; set; }
/// <summary>
/// 菜单类型 (0=目录,1=菜单,1=按钮)
/// </summary>
[SugarColumn(IsNullable = false)]
public int menuType { get; set; }
用户角色关系表设计
/// <summary>
/// 用户角色关系
/// </summary>
public class UserRoleRelation:IBase
{
/// <summary>
/// 用户主键
/// </summary>
[SugarColumn(IsNullable =false)]
public string UserId { get; set; }
/// <summary>
/// 角色主键
/// </summary>
[SugarColumn(IsNullable =false)]
public string RoleId { get; set; }
}
菜单角色关系表设计
/// <summary>
/// 菜单角色关系
/// </summary>
public class MenuRoleRelation: IBase
{
/// <summary>
/// 菜单主键
/// </summary>
public string MenuId { get; set; }
/// <summary>
/// 角色主键
/// </summary>
public string RoleId { get; set; }
}
实体Dto 表
登录
/// <summary>
/// 用户登录
/// </summary>
public class LoginReq
{
[Required(ErrorMessage = "自定义的错误信息1")]
public string UserName { get; set; }
[Required(ErrorMessage = "自定义的错误信息2")]
public string PassWord { get; set; }
}
用户
public class UserAdd
{
public string Name { get; set; }
public string NickName { get; set; }
public string Password { get; set; }
public bool IsEnable { get; set; }
public string Description { get; set; }
}
public class UserEdit
{
public string Id { get; set; }
public string Name { get; set; }
public string NickName { get; set; }
public string Password { get; set; }
//public int UserType { get; set; }
public bool IsEnable { get; set; }
public string Description { get; set; }
public string Avatar { get; set; }
}
public class UserReq
{
public string Name { get; set; }
public string NickName { get; set; }
public int UserType { get; set; }
public bool IsEnable { get; set; }
public string Description { get; set; }
public int PageIndex { get; set; }
public int PageSize { get; set; }
}
public class UserRes
{
/// <summary>
/// 主键
/// </summary>
public string Id { get; set; }
/// <summary>
/// 用户名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 昵称
/// </summary>
public string NickName { get; set; }
/// <summary>
/// 密码
/// </summary>
public string Password { get; set; }
/// <summary>
/// 用户类型
/// </summary>
public int UserType { get; set; }
/// <summary>
/// 角色名
/// </summary>
public string RoleName { get; set; }
/// <summary>
/// 创建人
/// </summary>
public string CreateUserName { get; set; }
/// <summary>
/// 创建日期
/// </summary>
public DateTime CreateDate { get; set; }
/// <summary>
/// 修改人Id
/// </summary>
public string ModifyUserName { get; set; }
/// <summary>
/// 修改日期
/// </summary>
public DateTime? ModifyDate { get; set; }
/// <summary>
/// 是否启用
/// </summary>
public bool IsEnable { get; set; }
/// <summary>
/// 是否删除
/// </summary>
public bool IsDeleted { get; set; }
/// <summary>
/// 描述
/// </summary>
public string Description { get; set; }
/// <summary>
/// 头像
/// </summary>
public string Avatar { get; set; }
}
角色
public class RoleAdd
{
public string Name { get; set; }
public int Order { get; set; }
public bool IsEnable { get; set; }
public string Description { get; set; }
}
public class RoleEdit
{
public string Id { get; set; }
public string Name { get; set; }
public int Order { get; set; }
public bool IsEnable { get; set; }
public string Description { get; set; }
}
public class RoleReq
{
public string Name { get; set; }
[DefaultValue("Hello")]
public string Description { get; set; }
public int PageIndex { get; set; }
public int PageSize { get; set; }
}
public class RoleRes
{
public string Id { get; set; }
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 排序
/// </summary>
public int Order { get; set; }
/// <summary>
/// 是否启用(0=未启用,1=启用)
/// </summary>
public bool IsEnable { get; set; }
/// <summary>
/// 描述
/// </summary>
public string Description { get; set; }
/// <summary>
/// 创建人
/// </summary>
public string CreateUserName { get; set; }
/// <summary>
/// 创建日期
/// </summary>
public DateTime CreateDate { get; set; }
/// <summary>
/// 修改人Id
/// </summary>
public string ModifyUserName { get; set; }
/// <summary>
/// 修改日期
/// </summary>
public DateTime? ModifyDate { get; set; }
/// <summary>
/// 是否删除
/// </summary>
public int IsDeleted { get; set; }
}
菜单
public class MenuAdd
{
public string Name { get; set; }
public string Index { get; set; }
public string FilePath { get; set; }
public string ParentId { get; set; }
public int Order { get; set; }
public bool IsEnable { get; set; }
public string Icon { get; set; }
public string Description { get; set; }
public int menuType { get; set; } = 0;
}
public class MenuEdit
{
public string Id { get; set; }
public string Name { get; set; }
public string Index { get; set; }
public string FilePath { get; set; }
public string ParentId { get; set; }
public int Order { get; set; }
public bool IsEnable { get; set; }
public string Icon { get; set; }
public string Description { get; set; }
public int menuType { get; set; }
}
public class MenuReq
{
public string Name { get; set; }
public string Index { get; set; }
public string FilePath { get; set; }
public string Description { get; set; }
}
public class MenuRes
{
[SugarColumn(IsTreeKey = true)]
public string Id { get; set; }
public string Name { get; set; }
public string Index { get; set; }
public string FilePath { get; set; }
public string ParentId { get; set; }
public string ParentName { get; set; }
public int Order { get; set; }
public bool IsEnable { get; set; }
public string Icon { get; set; }
public string Description { get; set; }
public DateTime CreateDate { get; set; }
/// <summary>
/// 子级
/// </summary>
[SqlSugar.SugarColumn(IsIgnore = true)]
public List<MenuRes> Children { get; set; }
}
创建控制器并生成初始数据 ToolController
/// <summary>
/// 初始化数据库
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<bool> InitData()
{
//1. 创建数据库
_db.DbMaintenance.CreateDatabase();
//2. 通过反射,加载程序集,读取到所有的类型,然后根据实体创建表
string nspace = "Model.Entitys";
Type[] ass = Assembly.LoadFrom(AppContext.BaseDirectory+"Model.dll")
.GetTypes().Where(p=>p.Namespace == nspace).ToArray();
//3. 创建表
_db.CodeFirst.SetStringDefaultLength(200).InitTables(ass);
// 初始化数据
Users user = new Users()
{
Id = Guid.NewGuid().ToString(),
Name = "admin",
NickName = "炒鸡管理员",
Password = "123456",
UserType = 0,
IsEnable = true,
Description = "数据库初始化时默认添加的炒鸡管理员",
CreateDate = DateTime.Now,
CreateUserId = "",
};
// 插入数据并返回用户ID
string userId = (await _db.Insertable(user).ExecuteReturnEntityAsync()).Id;
var m1 = new Menu()
{
Id = Guid.NewGuid().ToString(),
Title = "系统管理",
Component = "",
Path = "/system",
ParentId = "",
Order = 1,
IsEnable = true,
Icon = "folder",
MenuType = 0,
Description = "数据库初始化时默认添加的默认菜单",
CreateDate = DateTime.Now,
CreateUserId = userId
};
string mid1 = (await _db.Insertable(m1).ExecuteReturnEntityAsync()).Id;
// 菜单
var m11 = new Menu()
{
Id = Guid.NewGuid().ToString(),
Title = "菜单管理",
Component = "/system/menu",
Path = "/system/menu",
ParentId = mid1,
Order = 1,
IsEnable = true,
Icon = "notebook",
MenuType =0,
Description = "数据库初始化时默认添加的默认菜单",
CreateDate = DateTime.Now,
CreateUserId = userId
};
await _db.Insertable(m11).ExecuteReturnEntityAsync();
// 角色
var m2 = new Menu()
{
Id = Guid.NewGuid().ToString(),
Title = "角色管理",
Component = "/system/role",
Path = "/system/role",
ParentId = mid1,
Order = 1,
IsEnable = true,
Icon = "folder",
Description = "数据库初始化时默认添加的默认菜单",
CreateDate = DateTime.Now,
CreateUserId = userId,
MenuType = 0,
};
await _db.Insertable(m2).ExecuteReturnEntityAsync();
// 用户
var m3 = new Menu()
{
Id = Guid.NewGuid().ToString(),
Title = "用户管理",
Component = "/system/userr",
Path = "/system/user",
ParentId = mid1,
Order = 1,
IsEnable = true,
Icon = "notebook",
Description = "数据库初始化时默认添加的默认菜单",
CreateDate = DateTime.Now,
CreateUserId = userId,
MenuType = 0,
};
return await _db.Insertable(m3).ExecuteCommandIdentityIntoEntityAsync();
}
}
Autofac 安装
Autofac 批量注册
autofac 安装
autofac.DependencyInjection 安装
API项目中新建 Config 文件夹并创建AutofacModuleRegister类
/// <summary>
/// 批量注册依赖注入模块
/// </summary>
public class AutofacModuleRegister:Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
Assembly InterfaceAssembly = Assembly.Load("Interface");
Assembly ServicesAssembly = Assembly.Load("Services");
builder.RegisterAssemblyTypes(InterfaceAssembly, ServicesAssembly).AsImplementedInterfaces();
}
}
备注: 项目引用 Model,Interface, Service 层
Program.cs 注册 AutofacModuleRegister 类
// 替换内置IOC容器为Autofac
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(builder =>
{
builder.RegisterModule (new AutofacModuleRegister());
});
AutoMapper 安装
作用: Dto 与实体之间的映射,代替手动赋值
API项目中新建 Config 文件夹并创建AutoMapperConfigs类
/// <summary>
/// Dto 映射关系
/// </summary>
public class AutoMapperConfigs:Profile
{
public AutoMapperConfigs()
{
// 角色
CreateMap<RoleAdd, Role>();
CreateMap<RoleEdit, Role>();
// 用户
CreateMap<UserAdd, Users>();
CreateMap<UserEdit, Users>();
// 菜单
CreateMap<MenuAdd, Menu>();
CreateMap<MenuEdit, Menu>();
}
}
// Program.cs 注册 Automapper 映射
builder.Services.AddAutoMapper(typeof(AutoMapperConfigs));
创建接口层和服务层
/// <summary>
/// 接口层
/// </summary>
public interface IUserService
{
/// <summary>
/// 获取用户信息
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
Task<UserRes> GetUser(LoginReq req);
}
/// <summary>
/// 实现层
/// </summary>
public class UserService : IUserService
{
private ISqlSugarClient _db { get; set; }
public UserService(ISqlSugarClient db)
{
_db = db;
}
/// <summary>
/// /获取用户
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<UserRes> GetUser(LoginReq req)
{
var user = await _db.Queryable<Users>().Where(n=>n.Name == req.UserName && n.Password == req.PassWord)
// 属性手动赋值
// automapper
// 通过sqlsugar 自带的功能实现 true- 把Users 自动映射到UserRes
.Select(p=> new UserRes() { },true).FirstAsync();
return user;
}
}
JWT token
Microsoft.AspNetCore.Authentication.JwtBearer Service 安装
/// <summary>
/// jwt token
/// </summary>
public interface ICustomJWTService
{
/// <summary>
/// 获取Tokne
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
Task<string> GetToken(UserRes user);
}
/// <summary>
/// jwt token 实现层
/// </summary>
public class CustomJWTService : ICustomJWTService
{
// 来自 appsettings.json 配置文件
private readonly JWTTokenOptions _jWTToken;
public CustomJWTService(IOptionsMonitor<JWTTokenOptions> jWTToken)
{
_jWTToken = jWTToken.CurrentValue;
}
public async Task<string> GetToken(UserRes user)
{
var result =await Task.Run(() => {
var claims = new[]
{
new Claim("Id",user.Id),
new Claim("NickName",user.NickName),
new Claim("Name",user.Name),
new Claim("UserType",user.UserType.ToString()),
new Claim("Avatar",user.Avatar==null?"":user.Avatar)
};
//需要加密:需要加密key:
//Nuget引入:Microsoft.IdentityModel.Tokens
SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jWTToken.SecurityKey));
SigningCredentials creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
//Nuget引入:System.IdentityModel.Tokens.Jwt
JwtSecurityToken token = new JwtSecurityToken(
issuer: _jWTToken.Issuer,
audience: _jWTToken.Audience,
claims: claims,
expires: DateTime.Now.AddMinutes(10),//10分钟有效期
notBefore: null,
signingCredentials: creds);
string res = new JwtSecurityTokenHandler().WriteToken(token);
return res;
});
return result;
}
}
/// <summary>
/// 获取 Token
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
[HttpPost("GetToken")]
public async Task<ApiResult> GetToken([FromBody] LoginReq req)
{
// 通过模型验证
if (ModelState.IsValid)
{
UserRes user = await _userService.GetUser(req);
if (user == null)
{
return ResultHelper.Error("账号不存在,用户名或密码错误!");
}
_logger.LogInformation("登录");
return ResultHelper.Success(await _jwtService.GetToken(user));
}
else
{
return ResultHelper.Error("参数错误!");
}
}
}
设置JSON返回的日期格式
安装 Microsoft.AspNetCore.Mvc.NewtonsoftJson
Program.cs 配置
// 设置JSON返回的日期格式
builder.Services.AddControllers().AddNewtonsoftJson(options =>
{
// 忽略循环引用
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
// 统一设置API的日期格式
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
// 设置JSON返回格式同model一致(默认JSON里的首字母为小写,这里改为同后端Mode一致)
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});