优化 赴校信息导入功能

新增 角色授权流程
This commit is contained in:
小肥羊 2025-08-21 18:16:16 +08:00
parent 1278fed18d
commit a414aecac3
13 changed files with 167 additions and 53 deletions

View File

@ -48,10 +48,8 @@ namespace Learn.Archives.API.Controllers
? ["*:*:*"]
: await menuRelationDB.AsQueryable()
.LeftJoin<Menu>((mr, m) => mr.MenuId == m.Id)
.Where((mr, m) => mr.RoleId == admin.RoleId)
.Select((mr, m) => m)
.Where(m =>m.IsButton)
.Select(m=>m.Auths)
.Where((mr, m) => mr.RoleId == admin.RoleId && m.IsButton)
.Select((mr, m) => m.Auths)
.ToArrayAsync();
@ -65,6 +63,7 @@ namespace Learn.Archives.API.Controllers
NickName = admin.Name,
AccessToken = JwtHelper.GetToken(AppCommon.Config.AuthKey,
[
new Claim(ClaimEnum.UserCenterRole,"1"),//让所有用户都有用户中心操作权限
new Claim(ClaimEnum.Role,admin.RoleId.ToString()),
new Claim(ClaimEnum.UserId,admin.RoleId.ToString()),
new Claim(ClaimEnum.Id, admin.Id.ToString()),
@ -73,6 +72,7 @@ namespace Learn.Archives.API.Controllers
};
}
public override Task<bool> Edit([FromBody] Admin model)
{
//创建用户时 密码加密

View File

@ -1,77 +1,83 @@
using MiniExcelLibs.Attributes;
using Learn.Archives.Core.Model;
using MiniExcelLibs.Attributes;
namespace Learn.Archives.API.Controllers.Dto
{
public class SchoolBusinessDto
public class SchoolBusinessDto: SchoolBusiness
{
public string? StartTimeStr => StartTime.ToString("yyyy-MM-dd");
/// <summary>
/// 可以操作数据?
/// </summary>
public bool CanOperate { get; set; }
}
public class SchoolBusinessImportError : SchoolBusinessImport
{
[ExcelColumnName("错误信息")]
[ExcelColumn(Name = "错误信息", Width = 50)]
public string Error { get; set; }
}
public class SchoolBusinessImport
{
[ExcelColumnName("学校")]
[ExcelColumn(Name = "学校", Width = 15)]
public string School { get; set; }
[ExcelColumnName("年级")]
[ExcelColumn(Name = "年级", Width = 15)]
public string Grade { get; set; }
/// <summary>
/// 赴校人员
/// <para>多个,分割</para>
/// </summary>
[ExcelColumnName("赴校人员")]
[ExcelColumn(Name = "赴校人员", Width = 27)]
public string Users { get; set; }
[ExcelColumnName("赴校时间")]
[ExcelColumn(Name = "赴校时间", Width = 15)]
public DateTime StartTime { get; set; }
[ExcelColumnName("开展会谈")]
public bool IsDiscussion { get; set; }
public string IsDiscussion { get; set; }
[ExcelColumnName("开展会谈情况")]
[ExcelColumn(Name = "开展会谈情况",Width =27)]
public string Discussion { get; set; }
[ExcelColumnName("开展班会")]
public bool IsClassMeeting { get; set; }
[ExcelColumnName("开展班会情况")]
public string IsClassMeeting { get; set; }
[ExcelColumn(Name = "开展班会情况", Width = 27)]
public string ClassMeeting { get; set; }
//----------------------------问题列表
[ExcelColumnName("[问题]")]
[ExcelColumn(Name = "[问题]", Width = 30)]
public string Q学校领导班子 { get; set; }
[ExcelColumnName("[问题]")]
[ExcelColumn(Name = "[问题]", Width = 30)]
public string Q双师课堂 { get; set; }
[ExcelColumnName("[问题]")]
[ExcelColumn(Name = "[问题]", Width = 30)]
public string Q设备 { get; set; }
[ExcelColumnName("[问题]")]
[ExcelColumn(Name = "[问题]", Width = 30)]
public string Q学生 { get; set; }
[ExcelColumnName("[问题]")]
[ExcelColumn(Name = "[问题]", Width = 30)]
public string Q其他 { get; set; }
//----------------------------解决办法
[ExcelColumnName("[解决]")]
[ExcelColumn(Name = "[解决]", Width = 30)]
public string P学校领导班子 { get; set; }
[ExcelColumnName("[解决]")]
[ExcelColumn(Name = "[解决]", Width = 30)]
public string P双师课堂 { get; set; }
[ExcelColumnName("[解决]")]
[ExcelColumn(Name = "[解决]", Width = 30)]
public string P设备 { get; set; }
[ExcelColumnName("[解决]")]
[ExcelColumn(Name = "[解决]", Width = 30)]
public string P学生 { get; set; }
[ExcelColumnName("[解决]")]
[ExcelColumn(Name = "[解决]", Width = 30)]
public string P其他 { get; set; }
//----------------------------额外需求
[ExcelColumnName("需求/方案")]
[ExcelColumn(Name = "需求/方案", Width = 30)]
public string Solution { get; set; }
[ExcelColumnName("沟通时间/执行记录")]
[ExcelColumn(Name = "沟通时间/执行记录", Width = 30)]
public string Record { get; set; }
[ExcelColumnName("完结记录")]
[ExcelColumn(Name = "完结记录", Width = 30)]
public string EndRecord { get; set; }
[ExcelColumnName("备注")]
[ExcelColumn(Name = "备注", Width = 40)]
public string Remark { get; set; }

View File

@ -169,6 +169,9 @@ namespace Learn.Archives.API.Controllers
EntryPersonId = userInfo.Id,
BaseSchoolScore = exam.BaseSchoolScore,
EntryPerson = userInfo.Name,
TestPaperType = exam.TestPaperType,
Type = exam.Type,
Average1 = exam.BaseSchoolScore,
};
insertClassInfo.Add(eCInfo);
var avgTotal = 0m;

View File

@ -49,15 +49,14 @@ namespace Learn.Archives.API.Controllers
var rId = userInfo.RoleId;
if (rId == 0) Oh.Error("登录了无效的用户");
Menu[] menuArr ;
if (userInfo.RoleId == 1)
if (userInfo.IsSa)
menuArr = await baseService.AsQueryable()
.Where(m => !m.IsButton).ToArrayAsync();
else
menuArr = await menuRelationDB.AsQueryable()
.LeftJoin<Menu>((mr, m) => mr.MenuId == m.Id)
.Where((mr, m) => mr.RoleId == userInfo.RoleId)
.Where((mr, m) => mr.RoleId == userInfo.RoleId && !m.IsButton)
.Select((mr, m) => m)
.Where(m=>!m.IsButton)
.ToArrayAsync();
return GetChildren(menuArr, 0);
}

View File

@ -0,0 +1,66 @@
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 MenuRelationController : BackController<MenuRelation>
{
readonly Repository<AdminRole> roleService;
readonly Repository<MenuRelation> mrService;
readonly LiveUserInfo userInfo;
public MenuRelationController(Repository<AdminRole> baseService, LiveUserInfo userInfo, Repository<MenuRelation> mrService) : base(mrService)
{
this.roleService = baseService;
this.userInfo = userInfo;
this.mrService = mrService;
}
public class SetMenuInput
{
public long RoleId { get; set; }
public long[] MenuId { get; set; }
}
/// <summary>
/// 获取角色菜单ids
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<long[]> RoleMenu(long roleId)
{
if (roleId == 0) Oh.Error("无效的角色");
if (!userInfo.IsSa) Oh.Error("无权访问");
var role = roleService.GetByIdAsync(roleId);
if (role == null) Oh.Error("无效的角色");
return await mrService.AsQueryable()
.Where(s=>s.RoleId==roleId)
.Select(s=>s.MenuId)
.ToArrayAsync();
}
/// <summary>
/// 设置角色菜单
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<bool> SetMenu(SetMenuInput input)
{
if (input.MenuId == null || input.MenuId.Length==0) Oh.Error("选择了无可用的菜单");
if (!userInfo.IsSa) Oh.Error("登录了无效的用户");
var role = await roleService.GetByIdAsync(input.RoleId);
if (role == null) Oh.Error("无效的角色");
var insertData= input.MenuId!
.Select(s=>new MenuRelation() {RoleId = role!.Id,MenuId = s })
.ToArray();
await mrService.AsDeleteable().Where(s=>s.RoleId == role!.Id).ExecuteCommandAsync();
return await mrService.InsertRangeAsync(insertData);
}
}
}

View File

@ -4,6 +4,7 @@ using Learn.Archives.Core.Common;
using Learn.Archives.Core.Model;
using Learn.Archives.Core.Model.Dto;
using Learn.Archives.Core.Model.Enum;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MiniExcelLibs;
@ -24,12 +25,14 @@ namespace Learn.Archives.API.Controllers
readonly Repository<School> schoolService;
readonly Repository<Core.Model.Admin> adminService;
readonly IHttpContextAccessor accessor;
public SchoolBusinessController(Repository<SchoolBusiness> baseService, Repository<School> schoolService, IHttpContextAccessor accessor, Repository<Core.Model.Admin> adminService) : base(baseService)
readonly LiveUserInfo userInfo;
public SchoolBusinessController(Repository<SchoolBusiness> baseService, Repository<School> schoolService, IHttpContextAccessor accessor, Repository<Core.Model.Admin> adminService, LiveUserInfo userInfo) : base(baseService)
{
this.baseService = baseService;
this.schoolService = schoolService;
this.accessor = accessor;
this.adminService = adminService;
this.userInfo = userInfo;
}
public class QueryPageDto
@ -45,7 +48,7 @@ namespace Learn.Archives.API.Controllers
/// <summary>
/// 赴校人员ID
/// </summary>
public long? UserId { get; set; }
public string? UserName{ get; set; }
/// <summary>
/// 是否查询完结
/// </summary>
@ -77,15 +80,18 @@ namespace Learn.Archives.API.Controllers
return base.Edit(model);
}
public override async Task<dynamic> Info(long id)
{
return (await base.Info(id) as object).Adapt<SchoolBusinessDto>();
}
/// <summary>
/// 查询 赴校列表
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<PageResult<SchoolBusiness>> QueryPageList(QueryPageDto dto)
public async Task<PageResult<SchoolBusinessDto>> QueryPageList(QueryPageDto dto)
{
var uid = dto.UserId.ToString();
var gInfo = GradeHelper.GetStudentGradeBaseByGrade(dto.Grade);
RefAsync<int> total = 0;
var resData = await baseService.AsQueryable()
@ -94,13 +100,16 @@ namespace Learn.Archives.API.Controllers
.WhereIF(dto.SolutionEnd != null, s => s.SolutionEnd == dto.SolutionEnd)
.WhereIF(dto.StartTime != null, s => s.StartTime >= dto.StartTime)
.WhereIF(dto.EndTime != null, s => s.StartTime <= dto.EndTime)
.WhereIF(uid != null, s => s.SchoolBusinessUser != null && SqlFunc.JsonLike(s.SchoolBusinessUser, uid))
.WhereIF(!string.IsNullOrEmpty(dto.UserName), s => s.SchoolBusinessUser != null && SqlFunc.JsonLike(s.SchoolBusinessUser, dto.UserName))
.OrderByDescending(s => s.Id)
.Select<SchoolBusinessDto>()
.ToPageListAsync(dto.PageIndex, dto.PageSize, total);
return new PageResult<SchoolBusiness>() { Data = resData, Total = total };
foreach (var item in resData)
item.CanOperate =userInfo.IsSa || (item.SchoolBusinessUser?.Contains(userInfo.Name) ?? false);
return new PageResult<SchoolBusinessDto>() { Data = resData, Total = total };
}
/// <summary>
/// 导入考试信息
@ -157,7 +166,7 @@ namespace Learn.Archives.API.Controllers
}
var adminArr = await adminService.AsQueryable()
.Where(s => adminNameArr.Contains(s.Name))
.Select(s => s.Id).ToArrayAsync();
.Select(s => s.Name).ToArrayAsync();
var qStr = new Dictionary<FeedbackQuestionTypeEnum, (string Questions, string Solutions)>()
{
{FeedbackQuestionTypeEnum.,(imp.Q学校领导班子,imp.P学校领导班子) },
@ -173,6 +182,8 @@ namespace Learn.Archives.API.Controllers
var questionType = kvp.Key;
var questions = kvp.Value.Questions;
var solutions = kvp.Value.Solutions;
if (string.IsNullOrEmpty(questions) || string.IsNullOrEmpty(solutions))
continue;
// 解析问题
var questionMatches = regex.Matches(questions);
var solutionMatches = regex.Matches(solutions);
@ -236,6 +247,8 @@ namespace Learn.Archives.API.Controllers
Record = record,
}
};
business.SolutionEnd = business.SolutionRecord.EndRecordTime != null;
insertInfo.Add(business);
};
@ -243,7 +256,7 @@ namespace Learn.Archives.API.Controllers
return File(errorExcelInfo.ExportExcel(), "application/ms-excel");
//写入数据库
await baseService.InsertRangeAsync(insertInfo);
return Ok();
}
@ -255,7 +268,7 @@ namespace Learn.Archives.API.Controllers
public IActionResult DwImportTemplate()
{
var resultList = new List<SchoolBusinessImport>() { new SchoolBusinessImport() { } };
return File(resultList.ExportExcel(), "application/ms-excel");
return File(resultList.ExportExcel(), "application/ms-excel", "导入赴校信息模板.xlsx");
}

View File

@ -20,6 +20,7 @@ using Microsoft.AspNetCore.Hosting;
using Learn.Archives.Core.Common;
using Learn.Archives.Core.Model.Dto;
using Learn.Archives.Core.Model;
using SqlSugar.IOC;
namespace Learn.Archives.API.Expand
{
@ -40,13 +41,11 @@ namespace Learn.Archives.API.Expand
/// </summary>
public class HttpLogAttribute : ActionFilterAttribute, IAsyncExceptionFilter
{
readonly Repository<HttpLog> logService;
readonly LiveUserInfo userInfo;
readonly Stopwatch _stopwatch;//统计程序耗时
public HttpLogAttribute(Repository<HttpLog> logService, LiveUserInfo userInfo)
public HttpLogAttribute( LiveUserInfo userInfo)
{
this.logService = logService;
_stopwatch = Stopwatch.StartNew();
this.userInfo = userInfo;
}
@ -174,7 +173,7 @@ namespace Learn.Archives.API.Expand
}
}
//写入队列
await logService.InsertAsync(new HttpLog
await DbScoped.Sugar.Insertable<HttpLog>(new HttpLog
{
Id = logId,
Url = context.Request.Path + context.Request.QueryString,
@ -188,9 +187,9 @@ namespace Learn.Archives.API.Expand
: string.Empty,
Exception = e?.ToString(),
ExceptionMessage = e?.Message,
AdminId = userInfo.Id ,
AdminId = userInfo.Id,
TotalMilliseconds = (double)_stopwatch.Elapsed.TotalMilliseconds
});
}).ExecuteCommandAsync();
}

View File

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

View File

@ -36,7 +36,13 @@ namespace Learn.Archives.Core.Common
{
get => long.Parse(_httpContextAccessor.HttpContext?.User.FindFirst(ClaimEnum.Role)?.Value ?? "0");
}
/// <summary>
/// 是超管?
/// </summary>
public bool IsSa
{
get => RoleId == 1;
}
/// <summary>
/// 管理员id
/// </summary>

View File

@ -16,7 +16,7 @@ namespace Learn.Archives.Core.Model
public class Admin : EntityBaseId, IDB
{
/// <summary>
/// 账号
/// 名称
/// </summary>
[SugarColumn(Length = 12)]
public string Name { get; set; }

View File

@ -28,6 +28,8 @@ namespace Learn.Archives.Core.Model.Dto
/// 添加完结时间
/// </summary>
public DateTime? EndRecordTime { get; set; }
public string? ExecutionTimeStr => EndRecordTime?.ToString("yyyy-MM-dd");
/// <summary>
/// 执行记录
@ -48,8 +50,10 @@ namespace Learn.Archives.Core.Model.Dto
/// 执行时间
/// </summary>
public DateTime? ExecutionTime { get; set; }
public string? ExecutionTimeStr => ExecutionTime?.ToString("yyyy-MM-dd");
}
}
/// <summary>
@ -78,6 +82,9 @@ namespace Learn.Archives.Core.Model.Dto
/// 解决时间
/// </summary>
public DateTime? EndTime { get; set; }
public string? EndTimeStr=> EndTime?.ToString("yyyy-MM-dd");
}
/// <summary>
@ -97,5 +104,7 @@ namespace Learn.Archives.Core.Model.Dto
/// 解决时间
/// </summary>
public DateTime? EndTime { get; set; }
public string? EndTimeStr => EndTime?.ToString("yyyy-MM-dd");
}
}

View File

@ -31,12 +31,24 @@ namespace Learn.Archives.Core.Model
/// 考试班级id
/// </summary>
public long ClassId { get; set; }
/// <summary>
/// 考试班级名称
/// </summary>
[SugarColumn(Length = 20)]
public string ClassName { get; set; }
/// <summary>
/// 试卷类型
/// </summary>
public TestPaperTypeEnum TestPaperType { get; set; }
/// <summary>
/// 考试类型
/// </summary>
public ExamTypeEnum Type { get; set; }
/// <summary>
/// 考试班级所属学校ID
/// </summary>

View File

@ -48,7 +48,7 @@ namespace Learn.Archives.Core.Model
/// 赴校人员 逗号分隔
/// </summary>
[SugarColumn(IsNullable = true, IsJson = true)]
public long[]? SchoolBusinessUser { get; set; }
public string[]? SchoolBusinessUser { get; set; }
/// <summary>
/// 赴校时间
/// </summary>