新增 部分接口

This commit is contained in:
小肥羊 2025-08-11 18:25:16 +08:00
parent 658b75e3ad
commit 6aa945adbd
15 changed files with 376 additions and 94 deletions

View File

@ -0,0 +1,55 @@
using Learn.Archives.API.Controllers.Dto;
using Learn.Archives.API.Expand;
using Learn.Archives.Core.Common;
using Learn.Archives.Core.Model;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using System.Security.Claims;
using UserCenter.Model;
namespace Learn.Archives.API.Controllers
{
[ApiExplorerSettings(GroupName = "公共接口")]
[Route("api/address")]
public class AddressController : Controller
{
private readonly Repository<Province> _provinceService;
private readonly Repository<City> _cityService;
private readonly Repository<Region> _regionService;
public AddressController(Repository<Province> provinceService, Repository<Region> regionService, Repository<City> cityService)
{
_provinceService = provinceService;
_regionService = regionService;
_cityService = cityService;
}
/// <summary>
/// 获取所有省份
/// </summary>
/// <returns></returns>
[HttpGet, Route("province"), AllowAnonymous]
public async Task<IList<Province>> GetProvince()
{
return await _provinceService.GetListAsync();
}
/// <summary>
/// 获取省份下的市区
/// </summary>
/// <returns></returns>
[HttpGet, Route("{pid}/city"), AllowAnonymous]
public async Task<IList<City>> GetProvince(int pid)
{
return await _cityService.GetListAsync(s => s.Pid == pid);
}
/// <summary>
/// 获取市区下的区县
/// </summary>
/// <returns></returns>
[HttpGet, Route("{cid}/region"), AllowAnonymous]
public async Task<IList<Region>> GetRegion(int cid)
{
return await _regionService.GetListAsync(s => s.Cid == cid);
}
}
}

View File

@ -1,4 +1,5 @@
using Learn.Archives.API.Controllers.Dto;
using Azure.Core;
using Learn.Archives.API.Controllers.Dto;
using Learn.Archives.API.Expand;
using Learn.Archives.Core.Common;
using Learn.Archives.Core.Model;
@ -23,7 +24,7 @@ namespace Learn.Archives.API.Controllers
/// <returns></returns>
[HttpPost, AllowAnonymous]
[HttpLogEnable]
public async Task<string> Login([FromBody] AdminLoginReq model)
public async Task<object> Login([FromBody] AdminLoginReq model)
{
if (string.IsNullOrWhiteSpace(model.Account))
Oh.Error("登录失败,用户名不能为空");
@ -41,12 +42,18 @@ namespace Learn.Archives.API.Controllers
// 获取租户信息
//获取
return JwtHelper.GetToken(AppCommon.Config.AuthKey,
return new
{
//用户名
UserName = admin.Name,
NickName = admin.Name,
AccessToken = JwtHelper.GetToken(AppCommon.Config.AuthKey,
[
new Claim(ClaimEnum.Role,admin.RoleId.ToString()),
new Claim(ClaimEnum.Id, admin.Id.ToString()),
new Claim(ClaimEnum.Name, admin.Name),
]);
])
};
}

View File

@ -0,0 +1,26 @@
using Learn.Archives.API.Controllers.Dto;
using Learn.Archives.API.Expand;
using Learn.Archives.Core.Common;
using Learn.Archives.Core.Model;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using System.Security.Claims;
using UserCenter.Model;
namespace Learn.Archives.API.Controllers
{
/// <summary>
/// 管理员角色控制器
/// </summary>
public class AdminRoleController : BackController<AdminRole>
{
readonly Repository<AdminRole> baseService;
readonly LiveUserInfo userInfo;
public AdminRoleController(Repository<AdminRole> baseService, LiveUserInfo userInfo) : base(baseService)
{
this.baseService = baseService;
this.userInfo = userInfo;
}
}
}

View File

@ -0,0 +1,26 @@
using Learn.Archives.API.Controllers.Dto;
using Learn.Archives.API.Expand;
using Learn.Archives.Core.Common;
using Learn.Archives.Core.Model;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using System.Security.Claims;
using UserCenter.Model;
namespace Learn.Archives.API.Controllers
{
/// <summary>
/// 班级控制器
/// </summary>
public class ClassController : BackController<Classes>
{
readonly Repository<Classes> baseService;
readonly LiveUserInfo userInfo;
public ClassController(Repository<Classes> baseService, LiveUserInfo userInfo) : base(baseService)
{
this.baseService = baseService;
this.userInfo = userInfo;
}
}
}

View File

@ -1,4 +1,6 @@
using Learn.Archives.Core.Model;
using SqlSugar;
using System.Text.Json.Serialization;
namespace Learn.Archives.API.Controllers.Dto
{
@ -7,9 +9,46 @@ namespace Learn.Archives.API.Controllers.Dto
/// </summary>
public class MenuTree : Menu
{
[JsonIgnore]
public override string Title { get; set; }
[JsonIgnore]
public override string? Icon { get; set; }
[JsonIgnore]
public override int Rank { get; set; }
[JsonIgnore]
public override bool ShowLink { get; set; }
[JsonIgnore]
public override long ParentId { get; set; }
[JsonIgnore]
public override bool IsButton { get; set; }
/// <summary>
/// 子菜单列表
/// </summary>
public MenuTree[] Children { get; set; } = Array.Empty<MenuTree>();
public MenuTree[]? Children { get; set; }
public MenuMeta Meta { get; set; }
}
/// <summary>
/// 菜单树媒体
/// </summary>
public class MenuMeta
{
/// <summary>
/// 菜单名称
/// </summary>
public string Title { get; set; }
/// <summary>
/// 图标
/// </summary>
public string? Icon { get; set; }
/// <summary>
/// 排名
/// </summary>
public int Rank { get; set; }
/// <summary>
/// 显示菜单?
/// </summary>
public bool ShowLink { get; set; }
}
}

View File

@ -0,0 +1,26 @@
using Learn.Archives.API.Controllers.Dto;
using Learn.Archives.API.Expand;
using Learn.Archives.Core.Common;
using Learn.Archives.Core.Model;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using System.Security.Claims;
using UserCenter.Model;
namespace Learn.Archives.API.Controllers
{
/// <summary>
/// 年级控制器
/// </summary>
public class GradeController : BackController<Grade>
{
readonly Repository<Grade> baseService;
readonly LiveUserInfo userInfo;
public GradeController(Repository<Grade> baseService, LiveUserInfo userInfo) : base(baseService)
{
this.baseService = baseService;
this.userInfo = userInfo;
}
}
}

View File

@ -2,6 +2,7 @@
using Learn.Archives.API.Expand;
using Learn.Archives.Core.Common;
using Learn.Archives.Core.Model;
using Learn.Archives.Core.Model.Dto;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
@ -16,13 +17,26 @@ namespace Learn.Archives.API.Controllers
public class MenuController : BackController<Menu>
{
readonly Repository<Menu> baseService;
readonly Repository<AdminRole> roleService;
readonly Repository<MenuRelation> menuRelationDB;
readonly LiveUserInfo userInfo;
public MenuController(Repository<Menu> baseService, LiveUserInfo userInfo, Repository<MenuRelation> menuRelationDB) : base(baseService)
public MenuController(Repository<Menu> baseService, LiveUserInfo userInfo, Repository<MenuRelation> menuRelationDB, Repository<AdminRole> roleService) : base(baseService)
{
this.baseService = baseService;
this.userInfo = userInfo;
this.menuRelationDB = menuRelationDB;
this.roleService = roleService;
}
/// <summary>
/// 管理员菜单
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<List<Menu>> All()
{
var rId = userInfo.RoleId;
if (rId != 1) Oh.Error("登录了无效的用户");
return await baseService.GetListAsync();
}
/// <summary>
@ -34,37 +48,44 @@ namespace Learn.Archives.API.Controllers
{
var rId = userInfo.RoleId;
if (rId == 0) Oh.Error("登录了无效的用户");
var menuArr = await menuRelationDB.AsQueryable()
.LeftJoin<Menu>((mr, m) => mr.MenuId == m.Id)
.Where((mr,m)=> mr.RoleId == userInfo.RoleId)
.Select((mr, m) => m)
.ToArrayAsync();
return GetChildren(menuArr, menuArr.First().Id);
Menu[] menuArr ;
if (userInfo.RoleId == 1)
menuArr = await baseService.AsQueryable().ToArrayAsync();
else
menuArr = await menuRelationDB.AsQueryable()
.LeftJoin<Menu>((mr, m) => mr.MenuId == m.Id)
.Where((mr, m) => mr.RoleId == userInfo.RoleId)
.Select((mr, m) => m)
.ToArrayAsync();
return GetChildren(menuArr, 0);
}
/// <summary>
/// 递归获取子菜单
/// </summary>
[NonAction]
private static MenuTree[] GetChildren(IEnumerable<Menu> menus, long parentId)
private static MenuTree[]? GetChildren(IEnumerable<Menu> menus, long parentId)
{
return menus
var res = menus
.Where(m => m.ParentId == parentId)
.OrderBy(m => m.Rank)
.Select(m => new MenuTree
{
Id = m.Id,
Name = m.Name,
Title = m.Title,
Path = m.Path,
IsButton = m.IsButton,
Icon = m.Icon,
Auths = m.Auths,
Rank = m.Rank,
ShowLink = m.ShowLink,
Meta = new MenuMeta()
{
Title = m.Title,
Icon = m.Icon,
Rank = m.Rank,
ShowLink = m.ShowLink,
//Auths = m.Auths,
},
ParentId = m.ParentId,
Children = GetChildren(menus, m.Id)
})
.ToArray();
return res.Length==0?null: res;
}
}

View File

@ -0,0 +1,55 @@
using Learn.Archives.API.Controllers.Dto;
using Learn.Archives.API.Expand;
using Learn.Archives.Core.Common;
using Learn.Archives.Core.Model;
using Learn.Archives.Core.Model.Dto;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using System.Security.Claims;
using UserCenter.Model;
namespace Learn.Archives.API.Controllers
{
/// <summary>
/// 通用接口
/// </summary>
[Authorize(AuthenticationSchemes = Authentication.Admin)]
[Route("api/[controller]/[action]")]
public class PublicController : Controller
{
public PublicController(Repository<School> baseService)
{
}
/// <summary>
/// App.EntityDto.Enum 枚举转下拉列表
/// </summary>
/// <param name="type">枚举名称 例子type='ExamStatusEnum'</param>
/// <returns></returns>
[HttpGet, Route("enum/{type}")]
[ResponseCache(Duration = 5)]
public List<ComboModel> GetExamStatusData(string type)
{
if (!AppCommon.EnumType.ContainsKey(type))
Oh.Error("无效类型");
return Enum.GetValues(AppCommon.EnumType[type]).Cast<object>()
.Select(enumValue => new ComboModel() { Text = enumValue.ToString(), Value = (int)enumValue }).ToList();
}
/// <summary>
/// App.EntityDto.Enum 枚举转下拉列表
/// </summary>
/// <param name="type">枚举名称 例子type='ExamStatusEnum'</param>
/// <returns></returns>
[HttpGet, Route("enum/{type}/Dic")]
[ResponseCache(Duration = 5)]
public Dictionary<int, string?> GetExamStatusDictionary(string type)
{
if (!AppCommon.EnumType.ContainsKey(type))
Oh.Error("无效类型");
return Enum.GetValues(AppCommon.EnumType[type]).Cast<object>()
.ToDictionary(s => (int)s, s => s.ToString());
}
}
}

View File

@ -45,7 +45,7 @@ namespace Learn.Archives.API.Controllers
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet, Route("{id}")]
[HttpGet]
public virtual async Task<dynamic> Info(long id)
{
return await _baseRepository.GetByIdAsync(id);
@ -56,7 +56,7 @@ namespace Learn.Archives.API.Controllers
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[HttpPost, Route("edit")]
[HttpPost]
[HttpLogEnable]
public virtual async Task<bool> Edit([FromBody] T model)
{
@ -70,7 +70,7 @@ namespace Learn.Archives.API.Controllers
/// </summary>
/// <param name="ids"></param>
/// <returns></returns>
[HttpPost, Route("delete")]
[HttpPost]
[HttpLogEnable]
public virtual async Task<bool> Del([FromBody] params long[] ids)
{
@ -122,8 +122,8 @@ namespace Learn.Archives.API.Controllers
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[HttpPost, Route("pagelist")]
public virtual async Task<dynamic> GetPageList([FromBody] QueryRequestBase model)
[HttpPost]
public virtual async Task<dynamic> PageList([FromBody] QueryRequestBase model)
{
var sqlquery = BaseQuery(model);
RefAsync<int> total = 0;
@ -136,7 +136,7 @@ namespace Learn.Archives.API.Controllers
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[HttpPost, Route("querycombo")]
[HttpPost]
public virtual async Task<List<ComboModel>> QueryCombo([FromBody] QueryCombo model)
{
if (string.IsNullOrEmpty(model.ValueName) || string.IsNullOrEmpty(model.TextName))

View File

@ -35,6 +35,7 @@ namespace Learn.Archives.Core.Common
/// </summary>
public static readonly IEnumerable<Type> DbMatserType;
public static readonly IEnumerable<Type> UserCenterType;
public static readonly Dictionary<string, Type> EnumType;
static AppCommon()
{
try
@ -47,7 +48,15 @@ namespace Learn.Archives.Core.Common
DbMatserType = assembliesType
.Where(u => u.GetInterfaces().Contains(typeof(IDB)));
UserCenterType = assembliesType
.Where(u => u.FullName.Contains("UserCenter"));
.Where(u => u.FullName.Contains("UserCenter"));
EnumType = Assemblies
.Where(s => s.FullName.Contains("Model"))
.SelectMany(s => s.GetTypes().Where(x => x.IsEnum))
.ToDictionary(s => s.Name, s => s);
}
catch
{

View File

@ -6,7 +6,7 @@
public static string PositionId => "position";
public static string UserId => "user";
public static string Id => "id";
public static string Role => "role";
public static string Role => "roleid";
public static string Scope => "scope";
public static string Name => "name";
}

View File

@ -48,61 +48,74 @@ namespace Learn.Archives.Core.Common.Expand
//注入SqlSugar 主库
services.AddSqlSugar(dbList);
services.ConfigurationSugar(db =>
{
var config = db.CurrentConnectionConfig;
// 设置超时时间
db.Ado.CommandTimeOut = 61;
#if DEBUG
// 打印SQL语句
db.Aop.OnLogExecuting = (sql, pars) =>
{
if (!ShowSQL) return;
//var originColor = Console.ForegroundColor;
//if (sql.StartsWith("SELECT", StringComparison.OrdinalIgnoreCase))
// Console.ForegroundColor = ConsoleColor.Green;
//if (sql.StartsWith("UPDATE", StringComparison.OrdinalIgnoreCase) || sql.StartsWith("INSERT", StringComparison.OrdinalIgnoreCase))
// Console.ForegroundColor = ConsoleColor.Yellow;
//if (sql.StartsWith("DELETE", StringComparison.OrdinalIgnoreCase))
// Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"【{DateTime.Now}——执行SQL - [{config.ConfigId}]】\r\n" + UtilMethods.GetSqlString(config.DbType, sql, pars) + "\r\n");
//Console.ForegroundColor = originColor;
};
#endif
db.Aop.OnError = (ex) =>
{
if (ex.Parametres == null) return;
//var originColor = Console.ForegroundColor;
//Console.ForegroundColor = ConsoleColor.DarkRed;
Console.WriteLine($"【{DateTime.Now}——错误SQL - [{config.ConfigId}]】\r\n" + ex.Message + "\r\n" + UtilMethods.GetSqlString(config.DbType, ex.Sql, (SugarParameter[])ex.Parametres) + "\r\n");
Console.WriteLine();
//Console.ForegroundColor = originColor;
};
db.Aop.DataExecuting = (oldValue, entityInfo) =>
{
if (entityInfo.OperationType == DataFilterType.InsertByObject)
{
// 主键(long类型)且没有值的---赋值雪花Id
if (entityInfo.EntityColumnInfo.IsPrimarykey && !entityInfo.EntityColumnInfo.IsIdentity && entityInfo.EntityColumnInfo.PropertyInfo.PropertyType == typeof(long))
{
var id = entityInfo.EntityColumnInfo.PropertyInfo.GetValue(entityInfo.EntityValue);
if (id == null || (long)id == 0)
entityInfo.SetValue(YitIdHelper.NextId());
}
if (entityInfo.PropertyName == "CreateTime" && entityInfo.EntityValue is null)
entityInfo.SetValue(DateTime.Now);
}
if (entityInfo.OperationType == DataFilterType.UpdateByObject)
{
}
};
});
#endregion
services.ConfigurationSugar(SetDbAop);
}
/// <summary>
/// 配置Aop
/// </summary>
/// <param name="db"></param>
/// <param name="setOrgEntityFilter">配置 学校数据 sql过滤 <para>默认true</para></param>
public static void SetDbAop(ISqlSugarClient db)
{
if (db.Ado.CommandTimeOut == 61)
{
return;
}
var config = db.CurrentConnectionConfig;
// 设置超时时间
db.Ado.CommandTimeOut = 61;
#if DEBUG
// 打印SQL语句
db.Aop.OnLogExecuting = (sql, pars) =>
{
if (!ShowSQL) return;
Console.WriteLine($"【{DateTime.Now}——执行SQL - [{config.ConfigId}]】\r\n" + UtilMethods.GetSqlString(config.DbType, sql, pars) + "\r\n");
};
#endif
db.Aop.OnError = (ex) =>
{
if (ex.Parametres == null) return;
Console.WriteLine($"【{DateTime.Now}——错误SQL - [{config.ConfigId}]】\r\n" + ex.Message + "\r\n" + UtilMethods.GetSqlString(config.DbType, ex.Sql, (SugarParameter[])ex.Parametres) + "\r\n");
Console.WriteLine();
};
db.Aop.DataExecuting = (oldValue, entityInfo) =>
{
if (entityInfo.OperationType == DataFilterType.InsertByObject)
{
// 主键(long类型)且没有值的---赋值雪花Id
if (entityInfo.EntityColumnInfo.IsPrimarykey && !entityInfo.EntityColumnInfo.IsIdentity && entityInfo.EntityColumnInfo.PropertyInfo.PropertyType == typeof(long))
{
var id = entityInfo.EntityColumnInfo.PropertyInfo.GetValue(entityInfo.EntityValue);
if (id == null || (long)id == 0)
entityInfo.SetValue(YitIdHelper.NextId());
}
if (entityInfo.PropertyName == "CreateTime" && entityInfo.EntityValue is null)
entityInfo.SetValue(DateTime.Now);
}
if (entityInfo.OperationType == DataFilterType.UpdateByObject)
{
}
};
// 超管时排除各种过滤器
//if (App.User?.FindFirst(ClaimEnum.Role)?.Value == "1")
//return;
// 配置用户机构(数据范围)过滤器
//SetOrgEntityFilter(db);
}
public static void UseSqlSugarExpand(this IApplicationBuilder app)
{
ShowSQL = false;

View File

@ -1,4 +1,5 @@
using SqlSugar;
using Learn.Archives.Core.Common.Expand;
using SqlSugar;
using SqlSugar.IOC;
using System;
using System.Collections.Generic;
@ -23,6 +24,7 @@ namespace Learn.Archives.Core.Common
base.Context = DbScoped.Sugar;
else if (AppCommon.UserCenterType.Contains(t))
base.Context = DbScoped.Sugar.GetConnectionScope(1001);
SqlSugarExpand.SetDbAop(base.Context);
}
}
}

View File

@ -29,7 +29,7 @@ namespace Learn.Archives.Core.Model
/// 学校名称
/// </summary>
[SugarColumn(Length = 12)]
public required string SchoolName { get; set; }
public string SchoolName { get; set; } = string.Empty;
/// <summary>
/// 学校Id
/// </summary>

View File

@ -21,11 +21,6 @@ namespace Learn.Archives.Core.Model
[SugarColumn(Length = 50)]
public string Name { get; set; }
/// <summary>
/// 标题
/// </summary>
[SugarColumn(Length = 20)]
public string Title { get; set; }
/// <summary>
/// 路径
/// </summary>
[SugarColumn(IsNullable = true)]
@ -33,33 +28,41 @@ namespace Learn.Archives.Core.Model
/// <summary>
/// 是按钮权限
/// </summary>
public bool IsButton { get; set; }
public virtual bool IsButton { get; set; }
/// <summary>
/// 标题
/// </summary>
[SugarColumn(Length = 20)]
public virtual string Title { get; set; }
/// <summary>
/// 图标
/// </summary>
[SugarColumn(IsNullable = true)]
public string? Icon { get; set; }
public virtual string? Icon { get; set; }
/// <summary>
/// 需要的授权码
/// </summary>
[SugarColumn(IsNullable = true)]
public string? Auths { get; set; }
public virtual string? Auths { get; set; }
/// <summary>
/// 排名
/// </summary>
public int Rank { get; set; }
public virtual int Rank { get; set; }
/// <summary>
/// 显示菜单?
/// </summary>
public bool ShowLink { get; set; }
public virtual bool ShowLink { get; set; }
/// <summary>
/// 父级菜单ID
/// <para>属于<see cref="Menu.Id"/></para>
/// </summary>
[SugarColumn(IsNullable = true)]
public long ParentId { get; set; }
public virtual long ParentId { get; set; }
}
}