2025-06-06 16:00:39 +08:00
|
|
|
|
using AutoMapper;
|
|
|
|
|
using Castle.DynamicProxy.Generators;
|
|
|
|
|
using Google.Protobuf.Collections;
|
|
|
|
|
using Microsoft.AspNetCore.Http;
|
|
|
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using VOL.Business.IServices.Norm;
|
|
|
|
|
using VOL.Business.IServices.School;
|
|
|
|
|
using VOL.Core.CacheManager;
|
|
|
|
|
using VOL.Core.Configuration;
|
|
|
|
|
using VOL.Core.Extensions;
|
|
|
|
|
using VOL.Core.Extensions.AutofacManager;
|
|
|
|
|
using VOL.Core.ManageUser;
|
|
|
|
|
using VOL.Core.Utilities;
|
|
|
|
|
using VOL.Entity.DomainModels;
|
|
|
|
|
using VOL.Entity.Enum;
|
|
|
|
|
using VOL.Model;
|
|
|
|
|
using VOL.Model.Ai;
|
|
|
|
|
using VOL.Model.IOT.Request;
|
|
|
|
|
using VOL.Model.Norm.Response;
|
|
|
|
|
using VOL.Model.School.Response;
|
|
|
|
|
using VOL.System.IRepositories;
|
|
|
|
|
using VOL.System.Repositories;
|
|
|
|
|
using static Dapper.SqlMapper;
|
|
|
|
|
|
|
|
|
|
namespace VOL.Business.Services.School
|
|
|
|
|
{
|
|
|
|
|
public class S_TeacherService : IS_TeacherService, IDependency
|
|
|
|
|
{
|
|
|
|
|
#region 初始化
|
|
|
|
|
private readonly IMapper _mapper;
|
|
|
|
|
private readonly ICacheService _cacheService;
|
|
|
|
|
private readonly ICacheQueryService _cacheQueryService;
|
|
|
|
|
private readonly IotDataSyncService _iotDataSyncService;
|
|
|
|
|
private readonly IS_TeacherRepository _teacherRepository;
|
|
|
|
|
private readonly ISys_UserRepository _sys_UserRepository;
|
|
|
|
|
private readonly IS_ClassAssocTeacherRepository _classAssocTeacherRepository;
|
|
|
|
|
private readonly IS_StudentRepository _studentRepository;
|
|
|
|
|
private readonly IN_SportsTestCategoryRepository _sportsTestCategoryRepository;
|
|
|
|
|
private readonly IN_SportsTestResultRepository _sportsTestResultRepository;
|
|
|
|
|
private readonly IS_ClassRepository _classRepository;
|
|
|
|
|
|
|
|
|
|
[ActivatorUtilitiesConstructor]
|
|
|
|
|
public S_TeacherService(IMapper mapper,
|
|
|
|
|
ICacheService cacheService,
|
|
|
|
|
ICacheQueryService cacheQueryService,
|
|
|
|
|
IS_TeacherRepository teacherRepository,
|
|
|
|
|
ISys_UserRepository sys_UserRepository,
|
|
|
|
|
IS_ClassAssocTeacherRepository classAssocTeacherRepository,
|
|
|
|
|
IS_StudentRepository studentRepository,
|
|
|
|
|
IN_SportsTestCategoryRepository sportsTestCategoryRepository,
|
|
|
|
|
IN_SportsTestResultRepository sportsTestResultRepository,
|
|
|
|
|
IS_ClassRepository classRepository,
|
|
|
|
|
IotDataSyncService iotDataSyncService)
|
|
|
|
|
{
|
|
|
|
|
_mapper = mapper;
|
|
|
|
|
_cacheService = cacheService;
|
|
|
|
|
_cacheQueryService = cacheQueryService;
|
|
|
|
|
_teacherRepository = teacherRepository;
|
|
|
|
|
_sys_UserRepository = sys_UserRepository;
|
|
|
|
|
_classAssocTeacherRepository = classAssocTeacherRepository;
|
|
|
|
|
_studentRepository = studentRepository;
|
|
|
|
|
_sportsTestCategoryRepository = sportsTestCategoryRepository;
|
|
|
|
|
_sportsTestResultRepository = sportsTestResultRepository;
|
|
|
|
|
_classRepository = classRepository;
|
|
|
|
|
_iotDataSyncService = iotDataSyncService;
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
public async Task<List<TeacherNameModel>> GetTeacherNames()
|
|
|
|
|
{
|
|
|
|
|
var isTeacher = (UserContext.Current.RoleId == 3);
|
|
|
|
|
|
2025-06-12 14:59:44 +08:00
|
|
|
|
var list = await _teacherRepository.FindAsIQueryable(x =>
|
|
|
|
|
x.SchoolCode.Equals(UserContext.Current.TenantId) &&
|
2025-06-06 16:00:39 +08:00
|
|
|
|
x.TeacherStatus != TeacherStatus.Depart &&
|
|
|
|
|
(!isTeacher || x.TeacherPhoneNo == UserContext.Current.UserInfo.PhoneNo)
|
|
|
|
|
).Select(x => new TeacherNameModel()
|
2025-06-12 14:59:44 +08:00
|
|
|
|
{
|
|
|
|
|
Id = x.Id,
|
|
|
|
|
TeacherPhone = x.TeacherPhoneNo,
|
|
|
|
|
TeacherName = x.TeacherName
|
|
|
|
|
}).ToListAsync();
|
2025-06-06 16:00:39 +08:00
|
|
|
|
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<List<TeacherListByGradeIdModel>> GetTeacherNamesByGradeId(TeacherListByGradeIdParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var query = from t in _teacherRepository.DbContext.Set<S_Teacher>()
|
|
|
|
|
join a in _teacherRepository.DbContext.Set<S_ClassAssocTeacher>()
|
|
|
|
|
on t.Id equals a.TeacherId into assoc
|
|
|
|
|
from a in assoc.DefaultIfEmpty()
|
|
|
|
|
join c in _teacherRepository.DbContext.Set<S_Class>()
|
|
|
|
|
on a.ClassId equals c.Id into classes
|
|
|
|
|
from c in classes.DefaultIfEmpty()
|
|
|
|
|
where t.SchoolCode.Equals(UserContext.Current.TenantId)
|
|
|
|
|
&& t.TeacherStatus != TeacherStatus.Depart
|
|
|
|
|
select new TeacherListByGradeIdModel()
|
|
|
|
|
{
|
|
|
|
|
Id = t.Id,
|
|
|
|
|
TeacherName = t.TeacherName,
|
|
|
|
|
TeacherPhone = t.TeacherPhoneNo,
|
|
|
|
|
GradeId = c != null ? c.GradeId : 0,
|
|
|
|
|
ClassId = c != null ? c.Id : 0
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (paramDto.GradeId.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.GradeId == paramDto.GradeId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.ClassId.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.ClassId == paramDto.ClassId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var list = await query
|
|
|
|
|
.GroupBy(x => x.Id)
|
|
|
|
|
.Select(g => new TeacherListByGradeIdModel
|
|
|
|
|
{
|
|
|
|
|
Id = g.Key,
|
|
|
|
|
TeacherName = g.FirstOrDefault().TeacherName,
|
|
|
|
|
TeacherPhone = g.FirstOrDefault().TeacherPhone,
|
|
|
|
|
GradeId = g.FirstOrDefault().GradeId,
|
|
|
|
|
ClassId = g.FirstOrDefault().ClassId
|
|
|
|
|
})
|
|
|
|
|
.OrderBy(x => x.Id)
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public async Task<List<TeacherPageListModel>> GetTeacherList(TeacherExportParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var res = new PageDataDto<TeacherPageListModel>();
|
|
|
|
|
|
|
|
|
|
// 主查询,仅查询教师表
|
|
|
|
|
var query = _teacherRepository.DbContext.Set<S_Teacher>()
|
|
|
|
|
.Where(t => t.SchoolCode.Equals(UserContext.Current.TenantId) && t.TeacherStatus != TeacherStatus.Depart)
|
|
|
|
|
.Select(t => new TeacherPageListModel()
|
|
|
|
|
{
|
|
|
|
|
Id = t.Id,
|
|
|
|
|
PhoneNo = t.TeacherPhoneNo,
|
|
|
|
|
TeacherName = t.TeacherName,
|
|
|
|
|
TeacherStatus = t.TeacherStatus,
|
|
|
|
|
InductionDate = t.InductionDate,
|
|
|
|
|
Sex = t.Sex
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 过滤条件
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(paramDto.TeacherName))
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.TeacherName.Contains(paramDto.TeacherName));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(paramDto.PhoneNo))
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.PhoneNo.Contains(paramDto.PhoneNo));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.Sex > 0)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.Sex == paramDto.Sex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.TeacherStatus > 0)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.TeacherStatus == paramDto.TeacherStatus);
|
|
|
|
|
}
|
|
|
|
|
var list = await query.OrderBy(x => x.Id).ToListAsync();
|
|
|
|
|
|
|
|
|
|
// 统计每个教师的班级和学生数量
|
|
|
|
|
foreach (var item in list)
|
|
|
|
|
{
|
|
|
|
|
var assocTeachers = _teacherRepository.DbContext.Set<S_ClassAssocTeacher>()
|
|
|
|
|
.Where(at => at.TeacherId == item.Id);
|
|
|
|
|
|
|
|
|
|
// 学生数量
|
|
|
|
|
item.StudentCount = (from at in assocTeachers
|
|
|
|
|
join s in _teacherRepository.DbContext.Set<S_Student>() on at.ClassId equals s.ClassId
|
|
|
|
|
select s.Id).Distinct().Count();
|
|
|
|
|
|
|
|
|
|
// 班级数量
|
|
|
|
|
item.ClassCount = assocTeachers.Select(at => at.ClassId).Distinct().Count();
|
|
|
|
|
|
|
|
|
|
// 按年级分组的班级信息
|
|
|
|
|
var groupedClassIdsByGrade = (from at in assocTeachers
|
|
|
|
|
join c in _teacherRepository.DbContext.Set<S_Class>() on at.ClassId equals c.Id
|
|
|
|
|
group at.ClassId by c.GradeId into groupedData
|
|
|
|
|
select new
|
|
|
|
|
{
|
|
|
|
|
GradeId = groupedData.Key,
|
|
|
|
|
ClassIds = groupedData.ToList()
|
|
|
|
|
}).ToList();
|
|
|
|
|
|
|
|
|
|
item.GradeAndClassIds = groupedClassIdsByGrade.ToDictionary(x => x.GradeId, x => x.ClassIds);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
public async Task<PageDataDto<TeacherPageListModel>> GetTeacherPageList(TeacherPageListParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var res = new PageDataDto<TeacherPageListModel>();
|
|
|
|
|
|
|
|
|
|
// 主查询,仅查询教师表
|
|
|
|
|
var query = _teacherRepository.DbContext.Set<S_Teacher>()
|
|
|
|
|
.Where(t => t.SchoolCode.Equals(UserContext.Current.TenantId) && t.TeacherStatus != TeacherStatus.Depart)
|
|
|
|
|
.Select(t => new TeacherPageListModel()
|
|
|
|
|
{
|
|
|
|
|
Id = t.Id,
|
|
|
|
|
PhoneNo = t.TeacherPhoneNo,
|
|
|
|
|
TeacherName = t.TeacherName,
|
|
|
|
|
TeacherStatus = t.TeacherStatus,
|
|
|
|
|
InductionDate = t.InductionDate,
|
|
|
|
|
Sex = t.Sex,
|
|
|
|
|
TeacherPhoto = t.TeacherPhoto,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 过滤条件
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(paramDto.TeacherName))
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.TeacherName.Contains(paramDto.TeacherName));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(paramDto.PhoneNo))
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.PhoneNo.Contains(paramDto.PhoneNo));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.Sex > 0)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.Sex == paramDto.Sex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.TeacherStatus > 0)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.TeacherStatus == paramDto.TeacherStatus);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取总数用于分页
|
|
|
|
|
res.Total = await query.CountAsync();
|
|
|
|
|
|
|
|
|
|
// 分页数据
|
|
|
|
|
var list = await query
|
|
|
|
|
.Skip((paramDto.PageIndex - 1) * paramDto.PageSize)
|
|
|
|
|
.Take(paramDto.PageSize)
|
|
|
|
|
.OrderBy(x => x.Id)
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
|
|
// 统计每个教师的班级和学生数量
|
|
|
|
|
foreach (var item in list)
|
|
|
|
|
{
|
|
|
|
|
var assocTeachers = _teacherRepository.DbContext.Set<S_ClassAssocTeacher>()
|
|
|
|
|
.Where(at => at.TeacherId == item.Id);
|
|
|
|
|
|
|
|
|
|
// 学生数量
|
|
|
|
|
item.StudentCount = (from at in assocTeachers
|
|
|
|
|
join s in _teacherRepository.DbContext.Set<S_Student>() on at.ClassId equals s.ClassId
|
|
|
|
|
select s.Id).Distinct().Count();
|
|
|
|
|
|
|
|
|
|
// 班级数量
|
|
|
|
|
item.ClassCount = assocTeachers.Select(at => at.ClassId).Distinct().Count();
|
|
|
|
|
|
|
|
|
|
// 按年级分组的班级信息
|
|
|
|
|
var groupedClassIdsByGrade = (from at in assocTeachers
|
|
|
|
|
join c in _teacherRepository.DbContext.Set<S_Class>() on at.ClassId equals c.Id
|
|
|
|
|
group at.ClassId by c.GradeId into groupedData
|
|
|
|
|
select new
|
|
|
|
|
{
|
|
|
|
|
GradeId = groupedData.Key,
|
|
|
|
|
ClassIds = groupedData.ToList()
|
|
|
|
|
}).ToList();
|
|
|
|
|
|
|
|
|
|
item.GradeAndClassIds = groupedClassIdsByGrade.ToDictionary(x => x.GradeId, x => x.ClassIds);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res.Datas = list;
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task AddTeacher(AddTeacherParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var tenantId = UserContext.Current.TenantId;
|
|
|
|
|
|
|
|
|
|
var teacherExists = await _teacherRepository.ExistsAsync(x => x.SchoolCode == tenantId && x.TeacherPhoneNo == paramDto.TeacherPhoneNo);
|
|
|
|
|
if (teacherExists)
|
|
|
|
|
throw new Exception($"手机号{paramDto.TeacherPhoneNo}的老师已存在!");
|
|
|
|
|
|
|
|
|
|
var teacherEntity = _mapper.Map<S_Teacher>(paramDto);
|
|
|
|
|
teacherEntity.TeacherStatus = TeacherStatus.Normal;
|
|
|
|
|
teacherEntity.SchoolCode = UserContext.Current.TenantId;
|
|
|
|
|
teacherEntity.Creator = UserContext.Current.UserId;
|
|
|
|
|
teacherEntity.CreateDate = DateTime.Now;
|
2025-06-06 16:55:14 +08:00
|
|
|
|
teacherEntity.AppletPwd = "000000";
|
2025-06-06 16:00:39 +08:00
|
|
|
|
|
2025-06-12 14:59:44 +08:00
|
|
|
|
var roleId = UserContext.Current.RoleId;
|
|
|
|
|
|
|
|
|
|
|
2025-06-06 16:00:39 +08:00
|
|
|
|
using (var transaction = _teacherRepository.DbContext.Database.BeginTransaction())
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
await _teacherRepository.AddAsync(teacherEntity);
|
|
|
|
|
await _teacherRepository.SaveChangesAsync();
|
|
|
|
|
|
|
|
|
|
int teacherId = teacherEntity.Id;
|
|
|
|
|
|
|
|
|
|
var userEntity = new Sys_User()
|
|
|
|
|
{
|
2025-06-12 14:59:44 +08:00
|
|
|
|
Role_Id = roleId == 2 ? 3 : 5,
|
2025-06-06 16:00:39 +08:00
|
|
|
|
RoleName = "学校老师",
|
|
|
|
|
PhoneNo = paramDto.TeacherPhoneNo,
|
|
|
|
|
SchoolName = UserContext.Current.SchoolName,
|
|
|
|
|
UserTrueName = paramDto.TeacherName,
|
|
|
|
|
Enable = 1,
|
|
|
|
|
UserName = paramDto.TeacherPhoneNo,
|
|
|
|
|
//UserPwd = paramDto.Password.EncryptDES(AppSetting.Secret.User),
|
|
|
|
|
UserPwd = paramDto.Password,
|
|
|
|
|
CreateID = teacherId,
|
|
|
|
|
SchoolCode = tenantId,
|
|
|
|
|
CreateDate = DateTime.Now
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
await _sys_UserRepository.AddAsync(userEntity);
|
|
|
|
|
|
|
|
|
|
var classAssocTeacherList = new List<S_ClassAssocTeacher>();
|
|
|
|
|
|
|
|
|
|
if (paramDto.ClassIds != null && paramDto.ClassIds.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
paramDto.ClassIds.ForEach(x =>
|
|
|
|
|
{
|
|
|
|
|
classAssocTeacherList.Add(new S_ClassAssocTeacher()
|
|
|
|
|
{
|
|
|
|
|
ClassId = x,
|
|
|
|
|
TeacherId = teacherId,
|
|
|
|
|
Creator = UserContext.Current.UserId,
|
|
|
|
|
CreateDate = DateTime.Now,
|
|
|
|
|
Modifier = UserContext.Current.UserId,
|
|
|
|
|
ModifyDate = DateTime.Now,
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
await _classAssocTeacherRepository.AddRangeAsync(classAssocTeacherList);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
await _sys_UserRepository.SaveChangesAsync();
|
|
|
|
|
|
2025-06-06 16:00:39 +08:00
|
|
|
|
// 提交事务
|
|
|
|
|
transaction.Commit();
|
|
|
|
|
|
|
|
|
|
var teacherJson = new object[]
|
|
|
|
|
{
|
|
|
|
|
new
|
|
|
|
|
{
|
|
|
|
|
teacherEntity.Id,
|
|
|
|
|
teacherEntity.SchoolCode,
|
|
|
|
|
teacherEntity.TeacherName,
|
|
|
|
|
teacherEntity.Age,
|
|
|
|
|
teacherEntity.Sex,
|
|
|
|
|
teacherEntity.TeacherStatus,
|
|
|
|
|
teacherEntity.TeacherPhoto,
|
|
|
|
|
teacherEntity.InductionDate,
|
|
|
|
|
teacherEntity.TeacherPhoneNo,
|
|
|
|
|
teacherEntity.Ology,
|
|
|
|
|
teacherEntity.AccumulatedTeachingTimes,
|
|
|
|
|
teacherEntity.AppletPwd,
|
|
|
|
|
teacherEntity.Remarks,
|
|
|
|
|
paramDto.ClassIds
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//调用回调函数,同步数据到IOT
|
|
|
|
|
//_ = Task.Run(() => _iotDataSyncService.DataSyncCallBack(new DataSyncCallBackParam
|
|
|
|
|
//{
|
|
|
|
|
// EventType = EventType.Add.GetDisplayName(),
|
|
|
|
|
// DataType = IOTDataSyncType.Teacher.GetDisplayName(),
|
|
|
|
|
// Json = JsonConvert.SerializeObject(new List<S_Teacher>() { teacherEntity })
|
|
|
|
|
//}));
|
|
|
|
|
|
|
|
|
|
await _iotDataSyncService.DataSyncCallBack(new DataSyncCallBackParam
|
|
|
|
|
{
|
|
|
|
|
EventType = EventType.Add.GetDisplayName(),
|
|
|
|
|
DataType = IOTDataSyncType.Teacher.GetDisplayName(),
|
|
|
|
|
//Json = JsonConvert.SerializeObject(new List<S_Teacher>() { teacherJson }),
|
|
|
|
|
|
|
|
|
|
Json = JsonConvert.SerializeObject(teacherJson)
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
transaction.Rollback();
|
|
|
|
|
throw new Exception($"新增失败:{ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task ModifyTeacher(AddTeacherParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var tenantId = UserContext.Current.TenantId;
|
|
|
|
|
|
|
|
|
|
var teacherModel = await _teacherRepository.FindAsyncFirst(x => x.Id == paramDto.Id);
|
|
|
|
|
if (teacherModel == null)
|
|
|
|
|
throw new ArgumentNullException("未找到要更新的数据");
|
|
|
|
|
|
|
|
|
|
var teacherExists = await _teacherRepository.ExistsAsync(x => x.SchoolCode == tenantId && x.TeacherPhoneNo == paramDto.TeacherPhoneNo && x.Id != teacherModel.Id);
|
|
|
|
|
if (teacherExists)
|
|
|
|
|
throw new Exception($"手机号{paramDto.TeacherPhoneNo}的老师已存在!");
|
|
|
|
|
|
|
|
|
|
teacherModel.TeacherName = paramDto.TeacherName;
|
|
|
|
|
teacherModel.TeacherPhoneNo = paramDto.TeacherPhoneNo;
|
|
|
|
|
teacherModel.TeacherPhoto = paramDto.TeacherPhoto;
|
|
|
|
|
teacherModel.InductionDate = paramDto.InductionDate;
|
|
|
|
|
teacherModel.Sex = paramDto.Sex;
|
|
|
|
|
teacherModel.Modifier = UserContext.Current.UserId;
|
|
|
|
|
teacherModel.ModifyDate = DateTime.Now;
|
|
|
|
|
|
|
|
|
|
//var userModel = await _sys_UserRepository.FindAsyncFirst(x => x.PhoneNo == paramDto.TeacherPhoneNo);
|
|
|
|
|
//if (userModel == null)
|
|
|
|
|
// throw new ArgumentNullException("未找到要更新的数据");
|
|
|
|
|
|
|
|
|
|
//userModel.UserPwd = paramDto.Password;
|
|
|
|
|
//userModel.PhoneNo = paramDto.TeacherPhoneNo;
|
|
|
|
|
|
|
|
|
|
var classAssocTeacherList = await _classAssocTeacherRepository.FindAsync(x => x.TeacherId == teacherModel.Id);
|
|
|
|
|
|
|
|
|
|
using (var transaction = _teacherRepository.DbContext.Database.BeginTransaction())
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
_teacherRepository.Update(teacherModel);
|
|
|
|
|
|
|
|
|
|
//_sys_UserRepository.Update(userModel);
|
|
|
|
|
|
|
|
|
|
if (classAssocTeacherList.Count > 0)
|
|
|
|
|
_classAssocTeacherRepository.DbContext.RemoveRange(classAssocTeacherList);
|
|
|
|
|
|
|
|
|
|
var classAssocTeacherEntitys = new List<S_ClassAssocTeacher>();
|
|
|
|
|
|
|
|
|
|
paramDto.ClassIds.ForEach(x =>
|
|
|
|
|
{
|
|
|
|
|
classAssocTeacherEntitys.Add(new S_ClassAssocTeacher()
|
|
|
|
|
{
|
|
|
|
|
ClassId = x,
|
|
|
|
|
TeacherId = teacherModel.Id,
|
|
|
|
|
Creator = teacherModel.Id,
|
|
|
|
|
CreateDate = DateTime.Now,
|
|
|
|
|
Modifier = teacherModel.Id,
|
|
|
|
|
ModifyDate = DateTime.Now,
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (classAssocTeacherEntitys.Count > 0)
|
|
|
|
|
await _classAssocTeacherRepository.AddRangeAsync(classAssocTeacherEntitys);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await _teacherRepository.SaveChangesAsync();
|
|
|
|
|
|
|
|
|
|
// 提交事务
|
|
|
|
|
transaction.Commit();
|
|
|
|
|
|
|
|
|
|
var teacherJson = new
|
|
|
|
|
{
|
|
|
|
|
teacherModel.Id,
|
|
|
|
|
teacherModel.SchoolCode,
|
|
|
|
|
teacherModel.TeacherName,
|
|
|
|
|
teacherModel.Age,
|
|
|
|
|
teacherModel.Sex,
|
|
|
|
|
teacherModel.TeacherStatus,
|
|
|
|
|
teacherModel.TeacherPhoto,
|
|
|
|
|
teacherModel.InductionDate,
|
|
|
|
|
teacherModel.TeacherPhoneNo,
|
|
|
|
|
teacherModel.Ology,
|
|
|
|
|
teacherModel.AccumulatedTeachingTimes,
|
|
|
|
|
teacherModel.AppletPwd,
|
|
|
|
|
teacherModel.Remarks,
|
|
|
|
|
paramDto.ClassIds
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//调用回调函数,同步数据到IOT
|
|
|
|
|
//_ = Task.Run(() => _iotDataSyncService.DataSyncCallBack(new DataSyncCallBackParam
|
|
|
|
|
//{
|
|
|
|
|
// EventType = EventType.Update.GetDisplayName(),
|
|
|
|
|
// DataType = IOTDataSyncType.Teacher.GetDisplayName(),
|
|
|
|
|
// Json = JsonConvert.SerializeObject(teacherJson)
|
|
|
|
|
//}));
|
|
|
|
|
|
|
|
|
|
await _iotDataSyncService.DataSyncCallBack(new DataSyncCallBackParam
|
|
|
|
|
{
|
|
|
|
|
EventType = EventType.Update.GetDisplayName(),
|
|
|
|
|
DataType = IOTDataSyncType.Teacher.GetDisplayName(),
|
|
|
|
|
Json = JsonConvert.SerializeObject(teacherJson)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
// 发生错误,回滚事务
|
|
|
|
|
transaction.Rollback();
|
|
|
|
|
throw new Exception("事务回滚:" + ex.Message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task UpdateTeacherStatus(UpdateTeacherStatusParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var teacher = await _teacherRepository.FindAsyncFirst(x => x.TeacherPhoneNo == paramDto.TeacherPhoneNo);
|
|
|
|
|
if (teacher == null)
|
|
|
|
|
throw new ArgumentNullException("未找到要更新的数据");
|
|
|
|
|
teacher.TeacherStatus = paramDto.Status;
|
|
|
|
|
|
|
|
|
|
_studentRepository.Update(teacher);
|
|
|
|
|
await _studentRepository.SaveChangesAsync();
|
|
|
|
|
|
|
|
|
|
var classIds = await _classAssocTeacherRepository.FindAsIQueryable(x => x.TeacherId == teacher.Id).Select(x => x.ClassId).ToListAsync();
|
|
|
|
|
|
|
|
|
|
var teacherJson = new
|
|
|
|
|
{
|
|
|
|
|
teacher.Id,
|
|
|
|
|
teacher.SchoolCode,
|
|
|
|
|
teacher.TeacherName,
|
|
|
|
|
teacher.Age,
|
|
|
|
|
teacher.Sex,
|
|
|
|
|
teacher.TeacherStatus,
|
|
|
|
|
teacher.TeacherPhoto,
|
|
|
|
|
teacher.InductionDate,
|
|
|
|
|
teacher.TeacherPhoneNo,
|
|
|
|
|
teacher.Ology,
|
|
|
|
|
teacher.AccumulatedTeachingTimes,
|
|
|
|
|
teacher.AppletPwd,
|
|
|
|
|
teacher.Remarks,
|
|
|
|
|
ClassIds = classIds
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//调用回调函数,同步数据到IOT
|
|
|
|
|
//_ = Task.Run(() => _iotDataSyncService.DataSyncCallBack(new DataSyncCallBackParam
|
|
|
|
|
//{
|
|
|
|
|
// EventType = EventType.Update.GetDisplayName(),
|
|
|
|
|
// DataType = IOTDataSyncType.Teacher.GetDisplayName(),
|
|
|
|
|
// Json = JsonConvert.SerializeObject(teacherJson)
|
|
|
|
|
//}));
|
|
|
|
|
|
|
|
|
|
await _iotDataSyncService.DataSyncCallBack(new DataSyncCallBackParam
|
|
|
|
|
{
|
|
|
|
|
EventType = EventType.Update.GetDisplayName(),
|
|
|
|
|
DataType = IOTDataSyncType.Teacher.GetDisplayName(),
|
|
|
|
|
Json = JsonConvert.SerializeObject(teacherJson)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task UpdateTeacherPwd(UpdateTeacherPwdParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var teacher = await _teacherRepository.FindAsyncFirst(x => x.TeacherPhoneNo == paramDto.TeacherPhoneNo);
|
|
|
|
|
if (teacher == null)
|
|
|
|
|
throw new ArgumentNullException("未找到要更新的数据");
|
|
|
|
|
teacher.AppletPwd = AppSetting.OriginalPwd;
|
|
|
|
|
|
|
|
|
|
var user = await _sys_UserRepository.FindAsyncFirst(x => x.UserName == paramDto.TeacherPhoneNo);
|
|
|
|
|
if (user == null)
|
|
|
|
|
throw new ArgumentNullException("未找到该用户");
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
user.UserPwd = teacher.AppletPwd;
|
2025-06-06 16:00:39 +08:00
|
|
|
|
user.LastLoginDate = DateTime.Now;
|
|
|
|
|
|
|
|
|
|
_sys_UserRepository.Update(user);
|
|
|
|
|
|
|
|
|
|
_studentRepository.Update(teacher);
|
|
|
|
|
await _studentRepository.SaveChangesAsync();
|
|
|
|
|
await _sys_UserRepository.SaveChangesAsync();
|
|
|
|
|
|
|
|
|
|
var classIds = await _classAssocTeacherRepository.FindAsIQueryable(x => x.TeacherId == teacher.Id).Select(x => x.ClassId).ToListAsync();
|
|
|
|
|
|
|
|
|
|
var teacherJson = new
|
|
|
|
|
{
|
|
|
|
|
teacher.Id,
|
|
|
|
|
teacher.SchoolCode,
|
|
|
|
|
teacher.TeacherName,
|
|
|
|
|
teacher.Age,
|
|
|
|
|
teacher.Sex,
|
|
|
|
|
teacher.TeacherStatus,
|
|
|
|
|
teacher.TeacherPhoto,
|
|
|
|
|
teacher.InductionDate,
|
|
|
|
|
teacher.TeacherPhoneNo,
|
|
|
|
|
teacher.Ology,
|
|
|
|
|
teacher.AccumulatedTeachingTimes,
|
|
|
|
|
teacher.AppletPwd,
|
|
|
|
|
teacher.Remarks,
|
|
|
|
|
ClassIds = classIds
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//调用回调函数,同步数据到IOT
|
|
|
|
|
//_ = Task.Run(() => _iotDataSyncService.DataSyncCallBack(new DataSyncCallBackParam
|
|
|
|
|
//{
|
|
|
|
|
// EventType = EventType.Update.GetDisplayName(),
|
|
|
|
|
// DataType = IOTDataSyncType.Teacher.GetDisplayName(),
|
|
|
|
|
// Json = JsonConvert.SerializeObject(teacherJson)
|
|
|
|
|
//}));
|
|
|
|
|
|
|
|
|
|
await _iotDataSyncService.DataSyncCallBack(new DataSyncCallBackParam
|
|
|
|
|
{
|
|
|
|
|
EventType = EventType.Update.GetDisplayName(),
|
|
|
|
|
DataType = IOTDataSyncType.Teacher.GetDisplayName(),
|
|
|
|
|
Json = JsonConvert.SerializeObject(teacherJson)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 上传老师头像
|
|
|
|
|
/// </summary>
|
|
|
|
|
public async Task<string> UploadTeacherPhoto(IFormFile file, string teacherPhoneNo, string teacherName)
|
|
|
|
|
{
|
|
|
|
|
// 设置照片最大允许大小 (5MB)
|
|
|
|
|
const long MaxFileSize = 2 * 1024 * 1024;
|
|
|
|
|
|
|
|
|
|
// 检查文件大小是否超过限制
|
|
|
|
|
if (file.Length > MaxFileSize)
|
|
|
|
|
{
|
|
|
|
|
throw new Exception("上传的照片文件大小不能超过2MB");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var url = ALiYunOss.Upload(file, $"Upload/{UserContext.Current.TenantId}/Photo/Teacher/", teacherPhoneNo);
|
|
|
|
|
|
|
|
|
|
var faceEntityWithRequest = new FaceEntityWithDto()
|
|
|
|
|
{
|
|
|
|
|
EntityId = teacherPhoneNo,
|
|
|
|
|
SchoolCode = UserContext.Current.TenantId,
|
|
|
|
|
IsStudent = false
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
await ALiYunFace.DeleteFaceEntityWith(faceEntityWithRequest);
|
|
|
|
|
|
|
|
|
|
var faceEntityWithReuslt = await ALiYunFace.FaceEntityWith(faceEntityWithRequest);
|
|
|
|
|
if (!faceEntityWithReuslt)
|
|
|
|
|
{
|
|
|
|
|
throw new Exception("上传失败");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var faceWithReuslt = await ALiYunFace.FaceWith(new FaceWithDto()
|
|
|
|
|
{
|
|
|
|
|
SchoolCode = UserContext.Current.TenantId,
|
|
|
|
|
Name = teacherName,
|
|
|
|
|
IsStudent = false,
|
|
|
|
|
EntityId = teacherPhoneNo,
|
|
|
|
|
ImageUrl = url
|
|
|
|
|
});
|
|
|
|
|
if (!faceWithReuslt)
|
|
|
|
|
{
|
|
|
|
|
throw new Exception("上传失败");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return url;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task ResetPassword(int teacherId)
|
|
|
|
|
{
|
|
|
|
|
var user = await _sys_UserRepository.FindAsyncFirst(x => x.User_Id == teacherId);
|
|
|
|
|
if (user == null)
|
|
|
|
|
throw new ArgumentNullException("未找到该用户");
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
user.UserPwd = AppSetting.OriginalPwd;
|
2025-06-06 16:00:39 +08:00
|
|
|
|
user.LastLoginDate = DateTime.Now;
|
|
|
|
|
|
|
|
|
|
_sys_UserRepository.Update(user);
|
|
|
|
|
await _sys_UserRepository.SaveChangesAsync();
|
|
|
|
|
|
|
|
|
|
var teacher = await _teacherRepository.FindAsyncFirst(x => x.Id == teacherId);
|
|
|
|
|
if (teacher == null)
|
|
|
|
|
throw new ArgumentNullException("未找到要更新的数据");
|
|
|
|
|
|
|
|
|
|
var classIds = await _classAssocTeacherRepository.FindAsIQueryable(x => x.TeacherId == teacher.Id).Select(x => x.ClassId).ToListAsync();
|
|
|
|
|
|
|
|
|
|
var teacherJson = new
|
|
|
|
|
{
|
|
|
|
|
teacher.Id,
|
|
|
|
|
teacher.SchoolCode,
|
|
|
|
|
teacher.TeacherName,
|
|
|
|
|
teacher.Age,
|
|
|
|
|
teacher.Sex,
|
|
|
|
|
teacher.TeacherStatus,
|
|
|
|
|
teacher.TeacherPhoto,
|
|
|
|
|
teacher.InductionDate,
|
|
|
|
|
teacher.TeacherPhoneNo,
|
|
|
|
|
teacher.Ology,
|
|
|
|
|
teacher.AccumulatedTeachingTimes,
|
|
|
|
|
AppletPwd = "123456",
|
|
|
|
|
teacher.Remarks,
|
|
|
|
|
ClassIds = classIds
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//调用回调函数,同步数据到IOT
|
|
|
|
|
//_ = Task.Run(() => _iotDataSyncService.DataSyncCallBack(new DataSyncCallBackParam
|
|
|
|
|
//{
|
|
|
|
|
// EventType = EventType.Update.GetDisplayName(),
|
|
|
|
|
// DataType = IOTDataSyncType.Teacher.GetDisplayName(),
|
|
|
|
|
// Json = JsonConvert.SerializeObject(user)
|
|
|
|
|
//}));
|
|
|
|
|
|
|
|
|
|
await _iotDataSyncService.DataSyncCallBack(new DataSyncCallBackParam
|
|
|
|
|
{
|
|
|
|
|
EventType = EventType.Update.GetDisplayName(),
|
|
|
|
|
DataType = IOTDataSyncType.Teacher.GetDisplayName(),
|
|
|
|
|
Json = JsonConvert.SerializeObject(user)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 教师统计
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="ArgumentNullException"></exception>
|
|
|
|
|
public async Task<TeacherDataStatsModel> TeacherDataStats(TeacherDataStatsParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var res = new TeacherDataStatsModel();
|
|
|
|
|
var tenantId = UserContext.Current.TenantId;
|
|
|
|
|
|
|
|
|
|
if (!paramDto.TeacherId.HasValue || paramDto.TeacherId <= 0)
|
|
|
|
|
{
|
|
|
|
|
paramDto.TeacherId = this._teacherRepository.DbContext.Set<S_Teacher>().First().Id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var teacherModel = await (from t in _teacherRepository.DbContext.Set<S_Teacher>()
|
|
|
|
|
join a in _teacherRepository.DbContext.Set<S_ClassAssocTeacher>() on t.Id equals a.TeacherId
|
|
|
|
|
join s in _teacherRepository.DbContext.Set<S_Student>() on a.ClassId equals s.ClassId
|
|
|
|
|
where t.Id == paramDto.TeacherId && t.SchoolCode.Equals(UserContext.Current.TenantId)
|
|
|
|
|
group new { t, a } by new { t.Id } into groupedData
|
|
|
|
|
select new
|
|
|
|
|
{
|
|
|
|
|
groupedData.Key.Id,
|
|
|
|
|
TeacherName = groupedData.Select(x => x.t.TeacherName).FirstOrDefault(),
|
|
|
|
|
AccumulatedTeachingTimes = groupedData.Select(x => x.t.AccumulatedTeachingTimes).FirstOrDefault(),
|
|
|
|
|
StudentCount = groupedData.Count(),
|
|
|
|
|
ClassCount = groupedData.Select(x => x.a.ClassId).Distinct().Count(),
|
|
|
|
|
ClassIds = groupedData.Select(x => x.a.ClassId).Distinct().ToList()
|
|
|
|
|
}).FirstOrDefaultAsync();
|
|
|
|
|
|
|
|
|
|
if (teacherModel == null)
|
|
|
|
|
throw new ArgumentNullException("未找到老师数据");
|
|
|
|
|
|
|
|
|
|
res.TeacherName = teacherModel.TeacherName;
|
|
|
|
|
res.ClassCount = teacherModel.ClassCount;
|
|
|
|
|
res.StudentCount = teacherModel.StudentCount;
|
|
|
|
|
|
|
|
|
|
var grades = await (
|
|
|
|
|
from g in _classRepository.DbContext.Set<S_Grade>()
|
|
|
|
|
join c in _classRepository.DbContext.Set<S_Class>() on g.Id equals c.GradeId into classGroup
|
|
|
|
|
from c in classGroup.DefaultIfEmpty()
|
|
|
|
|
where teacherModel.ClassIds.Contains(c.Id) && c.SchoolCode.Equals(UserContext.Current.TenantId)
|
|
|
|
|
select new GradeAndClassNames
|
|
|
|
|
{
|
|
|
|
|
ClassId = c.Id,
|
|
|
|
|
GradeAndClassName = $"{g.GradeName}{c.ClassName}"
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
var classIds = grades.Select(x => x.ClassId).ToList();
|
|
|
|
|
|
|
|
|
|
// 从缓存中获取数据
|
|
|
|
|
var sportsTestResults = await _cacheQueryService.GeSportsTestDataCacheAsync(x => x.SchoolCode.Equals(tenantId) && x.TeacherId == paramDto.TeacherId && classIds.Contains(x.ClassId), paramDto.Mode);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var monitorList = sportsTestResults
|
|
|
|
|
.GroupBy(x => new { x.StudentNo })
|
|
|
|
|
.Select(g => new
|
|
|
|
|
{
|
|
|
|
|
g.Key.StudentNo,
|
|
|
|
|
g.First().Sex,
|
|
|
|
|
g.First().ClassId,
|
|
|
|
|
g.First().ClassName,
|
|
|
|
|
g.First().GradeId,
|
|
|
|
|
g.First().GradeName,
|
|
|
|
|
g.First().TeacherId,
|
|
|
|
|
g.First().TeacherName,
|
|
|
|
|
g.First().ClassRoomRecordId,
|
|
|
|
|
g.First().ScoreTime,
|
|
|
|
|
Score = (g.Sum(x => x.Score) + g.Sum(x => x.AdditionalScore)) / (g.Select(x => x.CategoryEnum).Distinct().Count())
|
|
|
|
|
})
|
|
|
|
|
.Select(x => new
|
|
|
|
|
{
|
|
|
|
|
x.StudentNo,
|
|
|
|
|
x.Sex,
|
|
|
|
|
x.ClassId,
|
|
|
|
|
x.ClassName,
|
|
|
|
|
x.GradeId,
|
|
|
|
|
x.GradeName,
|
|
|
|
|
x.TeacherId,
|
|
|
|
|
x.TeacherName,
|
|
|
|
|
x.ClassRoomRecordId,
|
|
|
|
|
x.Score,
|
|
|
|
|
x.ScoreTime,
|
|
|
|
|
Rank = x.Score.GetRank()
|
|
|
|
|
}).ToList();
|
|
|
|
|
|
|
|
|
|
// 计算总人数
|
|
|
|
|
double totalCount = monitorList.Count();
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
res.ExcellentRate = totalCount > 0 ? Math.Round((monitorList.Count(x => x.Rank == "优秀") / totalCount) * 100) : 0;
|
|
|
|
|
res.FineRate = totalCount > 0 ? Math.Round((monitorList.Count(x => x.Rank == "良好") / totalCount) * 100) : 0;
|
|
|
|
|
res.PassRate = totalCount > 0 ? Math.Round((monitorList.Count(x => x.Rank == "及格") / totalCount) * 100) : 0;
|
|
|
|
|
res.FailRate = totalCount > 0 ? Math.Round((monitorList.Count(x => x.Rank == "不及格") / totalCount) * 100) : 0;
|
2025-06-06 16:00:39 +08:00
|
|
|
|
|
|
|
|
|
if (res != null)
|
|
|
|
|
{
|
|
|
|
|
// 计算并调整最后一个百分比(确保总和为100%)
|
|
|
|
|
double sum = (res.ExcellentRate + res.FineRate + res.PassRate + res.FailRate);
|
|
|
|
|
double adjustment = 100 - sum;
|
2025-06-06 16:55:14 +08:00
|
|
|
|
res.FailRate += (totalCount > 0 ? adjustment : 0);
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float CalculatePassRate(int passed, int total) => total > 0 ? (float)Math.Truncate((double)passed / total * 100) / 100 : 0;
|
2025-06-12 14:59:44 +08:00
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
// 获取所有班级的学生人数
|
|
|
|
|
var classStudentCounts = await (
|
|
|
|
|
from s in _classRepository.DbContext.Set<S_Student>()
|
|
|
|
|
where teacherModel.ClassIds.Contains(s.ClassId)
|
|
|
|
|
group s by s.ClassId into g
|
|
|
|
|
select new
|
|
|
|
|
{
|
|
|
|
|
ClassId = g.Key,
|
|
|
|
|
StudentCount = g.Count()
|
|
|
|
|
}
|
|
|
|
|
).ToDictionaryAsync(x => x.ClassId, x => x.StudentCount);
|
|
|
|
|
|
|
|
|
|
// 获取所有班级的教学次数
|
|
|
|
|
var classTeachingTimes = await (
|
|
|
|
|
from r in _classRepository.DbContext.Set<Ai_ClassRoomRecord>()
|
|
|
|
|
where r.TeacherId == paramDto.TeacherId && teacherModel.ClassIds.Contains(r.ClassId)
|
|
|
|
|
group r by r.ClassId into g
|
|
|
|
|
select new
|
|
|
|
|
{
|
|
|
|
|
ClassId = g.Key,
|
|
|
|
|
TeachingTimes = g.Count()
|
|
|
|
|
}
|
|
|
|
|
).ToDictionaryAsync(x => x.ClassId, x => x.TeachingTimes);
|
2025-06-06 16:00:39 +08:00
|
|
|
|
|
|
|
|
|
foreach (var c in grades)
|
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
if (!c.ClassId.HasValue)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// 从字典中获取当前班级的学生人数
|
|
|
|
|
var totalStudentsInClass = classStudentCounts.TryGetValue(c.ClassId.Value, out var count) ? count : 0;
|
|
|
|
|
|
|
|
|
|
// 从字典中获取当前班级的教学次数
|
|
|
|
|
var accumulatedTeachingTimes = classTeachingTimes.TryGetValue(c.ClassId.Value, out var teachingTimes) ? teachingTimes : 0;
|
|
|
|
|
|
2025-06-06 16:00:39 +08:00
|
|
|
|
var classResults = monitorList.Where(x => x.ClassId == c.ClassId).ToList();
|
|
|
|
|
|
|
|
|
|
var totalFemale = classResults.Count(x => x.Sex == SexType.Female);
|
|
|
|
|
var totalMale = classResults.Count(x => x.Sex == SexType.Male);
|
|
|
|
|
var totalPassedFemale = classResults.Count(x => x.Sex == SexType.Female && x.Rank != "不及格");
|
|
|
|
|
var totalPassedMale = classResults.Count(x => x.Sex == SexType.Male && x.Rank != "不及格");
|
|
|
|
|
var totalPassedOverall = classResults.Count(x => x.Rank != "不及格");
|
|
|
|
|
|
|
|
|
|
var sexAndOverall = new SexAndOverall
|
|
|
|
|
{
|
|
|
|
|
FemaleValue = CalculatePassRate(totalPassedFemale, totalFemale),
|
|
|
|
|
MaleValue = CalculatePassRate(totalPassedMale, totalMale),
|
2025-06-06 16:55:14 +08:00
|
|
|
|
OverallValue = CalculatePassRate(totalPassedOverall, totalStudentsInClass)
|
2025-06-06 16:00:39 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
res.TestResultPassRate.AxisX.Add(c.GradeAndClassName);
|
|
|
|
|
res.TestResultPassRate.AxisY.Add(sexAndOverall);
|
|
|
|
|
|
|
|
|
|
var classResult = classResults.FirstOrDefault();
|
|
|
|
|
|
|
|
|
|
var result = classResults
|
|
|
|
|
.GroupBy(c => c.ScoreTime)
|
|
|
|
|
.Select(g => new
|
|
|
|
|
{
|
|
|
|
|
ScoreTime = g.Key,
|
|
|
|
|
Count = g.Count()
|
|
|
|
|
})
|
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
res.TeacherDetailsList.Add(new TeacherDetails()
|
|
|
|
|
{
|
|
|
|
|
ClassId = c.ClassId,
|
|
|
|
|
GradeAndClassName = c.GradeAndClassName,
|
2025-06-06 16:55:14 +08:00
|
|
|
|
Count = totalStudentsInClass,
|
2025-06-06 16:00:39 +08:00
|
|
|
|
TeacherName = teacherModel.TeacherName,
|
2025-06-06 16:55:14 +08:00
|
|
|
|
AccumulatedTeachingTimes = accumulatedTeachingTimes,
|
|
|
|
|
PassRate = CalculatePassRate(totalPassedOverall, totalStudentsInClass)
|
2025-06-06 16:00:39 +08:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 班级体测平均成绩
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<Dictionary<string, float>> TestResultAvg(ClassDataStatsParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var sportsTestResults = await _cacheQueryService.GeSportsTestDataCacheAsync(x => x.ClassId == paramDto.ClassId && x.SchoolCode.Equals(UserContext.Current.TenantId), paramDto.Mode);
|
|
|
|
|
|
|
|
|
|
var now = DateTime.Now;
|
|
|
|
|
var currentQuarter = (now.Month - 1) / 3 + 1;
|
|
|
|
|
var currentYear = now.Year;
|
|
|
|
|
|
|
|
|
|
// 处理跨年情况
|
|
|
|
|
var quarters = new[]
|
|
|
|
|
{
|
|
|
|
|
new { Label = "本季度", Quarter = currentQuarter, Year = currentYear },
|
|
|
|
|
new { Label = "上季度", Quarter = currentQuarter - 1 == 0 ? 4 : currentQuarter - 1, Year = currentQuarter == 1 ? currentYear - 1 : currentYear },
|
|
|
|
|
new { Label = "前季度", Quarter = currentQuarter - 2 == 0 ? 4 : currentQuarter - 2 == -1 ? 3 : currentQuarter - 2, Year = currentQuarter <= 2 ? currentYear - 1 : currentYear }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return quarters.ToDictionary(
|
|
|
|
|
q => q.Label,
|
|
|
|
|
q =>
|
|
|
|
|
{
|
|
|
|
|
var filteredResults = sportsTestResults
|
|
|
|
|
.Where(x => x.ScoreTime >= Tool.GetQuarterStartDate(q.Quarter, q.Year) && x.ScoreTime <= Tool.GetQuarterEndDate(q.Quarter, q.Year))
|
|
|
|
|
.Select(x => x.Score)
|
|
|
|
|
.ToList();
|
|
|
|
|
return filteredResults.Any() ? filteredResults.Average() : 0;
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 各班级授课次数占比
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public async Task<Dictionary<string, float>> ClassTeachingCountRatio(QuarterlyParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var res = new Dictionary<string, float>();
|
|
|
|
|
|
|
|
|
|
var now = DateTime.Now;
|
|
|
|
|
var currentQuarter = (now.Month - 1) / 3 + 1;
|
|
|
|
|
var currentYear = now.Year;
|
|
|
|
|
|
|
|
|
|
// 定义 sportsTestResults 变量
|
|
|
|
|
List<SportsTestValueModel> sportsTestResults = new List<SportsTestValueModel>();
|
|
|
|
|
|
|
|
|
|
// 根据 QuarterlyCycle 选择不同的查询范围
|
|
|
|
|
var quarterOffset = paramDto.QuarterlyCycle switch
|
|
|
|
|
{
|
|
|
|
|
QuarterlyCycleEnum.ForTheQuarter => 0,
|
|
|
|
|
QuarterlyCycleEnum.PreviousQuarter => 1,
|
|
|
|
|
QuarterlyCycleEnum.LastQuarter => 2,
|
|
|
|
|
_ => 0
|
|
|
|
|
};
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
// 计算目标季度和年份
|
|
|
|
|
var targetQuarter = currentQuarter - quarterOffset;
|
|
|
|
|
var targetYear = currentYear;
|
2025-06-06 16:00:39 +08:00
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
// 处理跨年情况
|
|
|
|
|
if (targetQuarter < 1)
|
|
|
|
|
{
|
|
|
|
|
targetQuarter += 4; // 调整季度
|
|
|
|
|
targetYear--; // 调整年份
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
2025-06-06 16:55:14 +08:00
|
|
|
|
else if (targetQuarter > 4)
|
|
|
|
|
{
|
|
|
|
|
targetQuarter -= 4; // 调整季度
|
|
|
|
|
targetYear++; // 调整年份
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var startDate = Tool.GetQuarterStartDate(targetQuarter, targetYear);
|
|
|
|
|
var endDate = Tool.GetQuarterEndDate(targetQuarter, targetYear);
|
2025-06-06 16:00:39 +08:00
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
sportsTestResults = await _cacheQueryService.GeSportsTestDataCacheAsync(x => x.TeacherId == paramDto.TeacherId &&
|
|
|
|
|
x.SchoolCode == UserContext.Current.TenantId &&
|
|
|
|
|
x.ScoreTime >= startDate &&
|
|
|
|
|
x.ScoreTime <= endDate, paramDto.Mode);
|
2025-06-06 16:00:39 +08:00
|
|
|
|
// 分组并计算每个分组的 Count
|
|
|
|
|
var groupResult = sportsTestResults
|
|
|
|
|
.GroupBy(c => new { c.ClassId, c.ClassName, c.GradeName })
|
|
|
|
|
.Select(g => new
|
|
|
|
|
{
|
|
|
|
|
g.Key.ClassId,
|
|
|
|
|
g.Key.ClassName,
|
|
|
|
|
g.Key.GradeName,
|
|
|
|
|
Count = g.DistinctBy(x => x.ScoreTime).Count()
|
|
|
|
|
})
|
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
// 计算总数
|
|
|
|
|
var totalCount = groupResult.Sum(gr => gr.Count);
|
|
|
|
|
|
|
|
|
|
// 生成结果字典
|
|
|
|
|
res = groupResult.ToDictionary(
|
|
|
|
|
gr => $"{gr.GradeName}{gr.ClassName}",
|
|
|
|
|
gr => totalCount > 0 ? (float)gr.Count / totalCount : 0f
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|