using System; using Dapper; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using VOL.Business.IRepositories.ShangWaiMao; using VOL.Core.DBManager; using VOL.Core.Dapper; using VOL.Core.Extensions.AutofacManager; using VOL.Entity.DomainModels; using VOL.Model; using VOL.Model.ShangWaiMao.Request; using VOL.Model.ShangWaiMao.Response; namespace VOL.Business.Repositories.ShangWaiMao { /// /// 上外贸体测成绩临时表仓储 /// public class TempTccjRepository : ITempTccjRepository { private const string TableName = "temp_tccj"; private ISqlDapper Dapper => DBServerProvider.SqlDapperSwmMySql; public static ITempTccjRepository Instance { get { return AutofacContainerModule.GetService(); } } public async Task GetFilterOptionsAsync() { const string sql = @" select distinct case sex when '1' then '男' when '2' then '女' else sex end as Label, sex as Value from temp_tccj where ifnull(sex, '') <> '' order by sex; select distinct college_name as Label, college_name as Value from temp_tccj where ifnull(college_name, '') <> '' order by college_name; select distinct grade_no as Label, grade_no as Value from temp_tccj where ifnull(grade_no, '') <> '' order by grade_no; select distinct class_name as Label, class_name as Value from temp_tccj where ifnull(class_name, '') <> '' order by class_name; select distinct conclusion as Label, conclusion as Value from temp_tccj where ifnull(conclusion, '') <> '' order by conclusion;"; var (sexList, collegeList, gradeList, administrativeClassList, conclusionList) = await Dapper.QueryMultipleAsync(sql, null); return new ShangWaiMaoTempTccjFilterOptions { SexList = sexList.ToList(), CollegeList = collegeList.ToList(), GradeList = gradeList.ToList(), AdministrativeClassList = administrativeClassList.ToList(), SportsClassList = new List(), ConclusionList = conclusionList.ToList() }; } public async Task> GetPageListAsync(ShangWaiMaoTempTccjPageParam param) { param ??= new ShangWaiMaoTempTccjPageParam(); param.PageIndex = param.PageIndex <= 0 ? 1 : param.PageIndex; param.PageSize = param.PageSize <= 0 ? 20 : param.PageSize; var whereBuilder = new StringBuilder(" where 1=1 "); var dbParams = new DynamicParameters(); if (!string.IsNullOrWhiteSpace(param.StudentNo)) { whereBuilder.Append(" and student_no like concat('%', @StudentNo, '%') "); dbParams.Add("StudentNo", param.StudentNo.Trim()); } if (!string.IsNullOrWhiteSpace(param.Name)) { whereBuilder.Append(" and name like concat('%', @Name, '%') "); dbParams.Add("Name", param.Name.Trim()); } if (!string.IsNullOrWhiteSpace(param.Sex)) { whereBuilder.Append(" and sex = @Sex "); dbParams.Add("Sex", NormalizeSex(param.Sex)); } if (!string.IsNullOrWhiteSpace(param.CollegeName)) { whereBuilder.Append(" and college_name = @CollegeName "); dbParams.Add("CollegeName", param.CollegeName.Trim()); } if (!string.IsNullOrWhiteSpace(param.GradeNo)) { whereBuilder.Append(" and grade_no = @GradeNo "); dbParams.Add("GradeNo", param.GradeNo.Trim()); } if (!string.IsNullOrWhiteSpace(param.AdministrativeClass)) { whereBuilder.Append(" and class_name = @AdministrativeClass "); dbParams.Add("AdministrativeClass", param.AdministrativeClass.Trim()); } if (!string.IsNullOrWhiteSpace(param.Conclusion)) { whereBuilder.Append(" and conclusion = @Conclusion "); dbParams.Add("Conclusion", param.Conclusion.Trim()); } var countSql = $"select count(1) from {TableName} {whereBuilder}"; var totalObj = await Dapper.ExecuteScalarAsync(countSql, dbParams); var total = int.TryParse(totalObj?.ToString(), out var parsedTotal) ? parsedTotal : 0; dbParams.Add("Offset", (param.PageIndex - 1) * param.PageSize); dbParams.Add("PageSize", param.PageSize); var listSql = $@" select student_no as StudentNo, name as Name, case sex when '1' then '男' when '2' then '女' else sex end as Sex, grade_no as GradeNo, class_name as AdministrativeClass, '' as SportsClass, case test_state when 0 then '未测试' when 1 then '已测试' when 2 then '缺项' else '' end as TestState, case exempt when 0 then '测试' when 1 then '免试' else '' end as Exempt, add_score as AddScore, health_score as HealthScore, score as Score, conclusion as Conclusion, '' as Remark, college_name as CollegeName from {TableName} {whereBuilder} order by student_no limit @Offset, @PageSize"; var datas = (await Dapper.QueryListAsync(listSql, dbParams)).ToList(); return new PageDataDto { Total = total, TotalPages = total == 0 ? 0 : (total + param.PageSize - 1) / param.PageSize, PageIndex = param.PageIndex, PageSize = param.PageSize, Datas = datas }; } public async Task GetDetailAsync(ShangWaiMaoTempTccjDetailParam param) { if (string.IsNullOrWhiteSpace(param?.StudentNo)) { throw new Exception("学号不能为空"); } var whereBuilder = new StringBuilder(" where student_no = @StudentNo "); var dbParams = new DynamicParameters(); dbParams.Add("StudentNo", param.StudentNo.Trim()); if (!string.IsNullOrWhiteSpace(param.SchoolYear)) { whereBuilder.Append(" and school_year = @SchoolYear "); dbParams.Add("SchoolYear", param.SchoolYear.Trim()); } if (!string.IsNullOrWhiteSpace(param.SchoolTerm)) { whereBuilder.Append(" and school_term = @SchoolTerm "); dbParams.Add("SchoolTerm", param.SchoolTerm.Trim()); } var sql = $@" select * from {TableName} {whereBuilder} order by school_year desc, school_term desc limit 1; select avg(lungs_score) as LungsScore, avg(meter50_score) as Meter50Score, avg(standing_long_jump_score) as StandingLongJumpScore, avg(sit_and_reach_score) as SitAndReachScore, avg(case when sex = '1' then meter1000_score when sex = '2' then meter800_score else null end) as EnduranceScore, avg(case when sex = '1' then pull_up_score when sex = '2' then sit_up_score else null end) as StrengthScore from {TableName};"; var (studentList, averageList) = await Dapper.QueryMultipleAsync(sql, dbParams); var student = studentList.FirstOrDefault(); if (student == null) { throw new Exception("未找到该学生体测详情"); } var averages = averageList.FirstOrDefault() ?? new TempTccjPortraitAverageData(); return new ShangWaiMaoTempTccjDetailDto { BasicInfo = BuildBasicInfo(student), DetailItems = BuildDetailItems(student), PortraitItems = BuildPortraitItems(student, averages) }; } private static string NormalizeSex(string sex) { var normalized = sex?.Trim(); return normalized switch { "男" => "1", "女" => "2", _ => normalized }; } private static ShangWaiMaoTempTccjBasicInfo BuildBasicInfo(TempTccj student) { return new ShangWaiMaoTempTccjBasicInfo { CollegeName = student.college_name, GradeName = GetGradeDisplayName(student.grade_no), AdministrativeClass = student.class_name, StudentNo = student.student_no, Name = student.name, Sex = GetSexDisplayName(student.sex), HealthScore = FormatDisplayValue(student.health_score), AddScore = FormatDisplayValue(student.add_score), TotalScore = FormatDisplayValue(student.score), Conclusion = student.conclusion, Remark = string.Empty }; } private static List BuildDetailItems(TempTccj student) { var isMale = student.sex == "1"; return new List { CreateDetailItem("身高", student.height, "厘米"), CreateDetailItem("体重", student.weight, "公斤"), CreateDetailItem("肺活量", student.lungs, "毫升", null, student.lungs_score, student.lungs_leve), CreateDetailItem("50米跑", student.meter50, "秒", null, student.meter50_score, student.meter50_leve), CreateDetailItem("立定跳远", student.standing_long_jump, "厘米", null, student.standing_long_jump_score, student.standing_long_jump_leve), CreateDetailItem("坐位体前屈", student.sit_and_reach, "厘米", null, student.sit_and_reach_score, student.sit_and_reach_leve), CreateDetailItem(isMale ? "1000米跑" : "800米跑", isMale ? student.meter1000 : student.meter800, "分/秒", student.bonus2_df, isMale ? student.meter1000_score : student.meter800_score, isMale ? student.meter1000_leve : student.meter800_leve), CreateDetailItem(isMale ? "引体向上" : "1分钟仰卧起坐", isMale ? student.pull_up : student.sit_up, isMale ? "次" : "次/分钟", student.bonus1_df, isMale ? student.pull_up_score : student.sit_up_score, isMale ? student.pull_up_leve : student.sit_up_leve), CreateDetailItem("左眼裸眼视力", student.leftVision), CreateDetailItem("右眼裸眼视力", student.rightVision), CreateDetailItem("左眼球镜", student.left_sphere), CreateDetailItem("右眼球镜", student.right_sphere), CreateDetailItem("左眼柱镜", student.left_cytdnder), CreateDetailItem("右眼柱镜", student.right_cytdnder) }; } private static List BuildPortraitItems(TempTccj student, TempTccjPortraitAverageData averages) { var isMale = student.sex == "1"; return new List { CreatePortraitItem("肺活量", student.lungs_score, averages.LungsScore), CreatePortraitItem("中长跑", isMale ? student.meter1000_score : student.meter800_score, averages.EnduranceScore), CreatePortraitItem("引体/仰卧", isMale ? student.pull_up_score : student.sit_up_score, averages.StrengthScore), CreatePortraitItem("立定跳远", student.standing_long_jump_score, averages.StandingLongJumpScore), CreatePortraitItem("坐位体前屈", student.sit_and_reach_score, averages.SitAndReachScore), CreatePortraitItem("50米跑", student.meter50_score, averages.Meter50Score) }; } private static ShangWaiMaoTempTccjDetailItem CreateDetailItem(string itemName, decimal? achievement, string unit = "", decimal? addScore = null, decimal? score = null, string level = "") { return new ShangWaiMaoTempTccjDetailItem { ItemName = itemName, Achievement = FormatDisplayValue(achievement), Unit = unit, AddScore = FormatDisplayValue(addScore), Score = FormatDisplayValue(score), Level = level ?? string.Empty }; } private static ShangWaiMaoTempTccjDetailItem CreateDetailItem(string itemName, string achievement, string unit = "", string addScore = "", string score = "", string level = "") { return new ShangWaiMaoTempTccjDetailItem { ItemName = itemName, Achievement = achievement ?? string.Empty, Unit = unit, AddScore = addScore ?? string.Empty, Score = score ?? string.Empty, Level = level ?? string.Empty }; } private static ShangWaiMaoTempTccjPortraitItem CreatePortraitItem(string itemName, decimal? personalScore, decimal? schoolAverageScore) { return new ShangWaiMaoTempTccjPortraitItem { ItemName = itemName, PersonalScore = personalScore, SchoolAverageScore = schoolAverageScore }; } private static string GetSexDisplayName(string sex) { return sex switch { "1" => "男", "2" => "女", _ => sex ?? string.Empty }; } private static string GetGradeDisplayName(string gradeNo) { var normalized = gradeNo?.Trim(); return normalized switch { "41" => "大一", "42" => "大二", "43" => "大三", "44" => "大四", _ => normalized ?? string.Empty }; } private static string FormatDisplayValue(decimal? value) { return value.HasValue ? value.Value.ToString("0.##") : string.Empty; } private sealed class TempTccjPortraitAverageData { public decimal? LungsScore { get; set; } public decimal? Meter50Score { get; set; } public decimal? StandingLongJumpScore { get; set; } public decimal? SitAndReachScore { get; set; } public decimal? EnduranceScore { get; set; } public decimal? StrengthScore { get; set; } } public async Task> GetAllAsync() { var result = await Dapper.QueryListAsync($"select * from {TableName}", null); return result.ToList(); } public Task InsertAsync(TempTccj entity) { const string sql = @" insert into temp_tccj ( school_year, school_term, student_no, name, sex, class_no, grade_no, class_name, college_name, test_state, exempt, add_score, health_score, score, conclusion, height, weight, bmi, bmi_df, bmi_score, bmi_leve, lungs, lungs_df, lungs_score, lungs_leve, meter50, meter50_df, meter50_score, meter50_leve, standing_long_jump, standing_long_jump_df, standing_long_jump_score, standing_long_jump_leve, sit_and_reach, sit_and_reach_df, sit_and_reach_score, sit_and_reach_leve, meter800, meter800_df, meter800_score, meter800_leve, meter1000, meter1000_df, meter1000_score, meter1000_leve, sit_up, sit_up_df, sit_up_score, sit_up_leve, pull_up, pull_up_df, pull_up_score, pull_up_leve, skip, skip_df, skip_score, skip_leve, shuttle_run, shuttle_run_df, shuttle_run_score, shuttle_run_leve, leftVision, rightVision, leftMirror, rightMirror, leftAmetropia, rightAmetropia, left_sphere, right_sphere, left_cytdnder, right_cytdnder, left_axial, right_axial, is_ok_mirror, bonus1, bonus1_df, bonus2, bonus2_df ) values ( @school_year, @school_term, @student_no, @name, @sex, @class_no, @grade_no, @class_name, @college_name, @test_state, @exempt, @add_score, @health_score, @score, @conclusion, @height, @weight, @bmi, @bmi_df, @bmi_score, @bmi_leve, @lungs, @lungs_df, @lungs_score, @lungs_leve, @meter50, @meter50_df, @meter50_score, @meter50_leve, @standing_long_jump, @standing_long_jump_df, @standing_long_jump_score, @standing_long_jump_leve, @sit_and_reach, @sit_and_reach_df, @sit_and_reach_score, @sit_and_reach_leve, @meter800, @meter800_df, @meter800_score, @meter800_leve, @meter1000, @meter1000_df, @meter1000_score, @meter1000_leve, @sit_up, @sit_up_df, @sit_up_score, @sit_up_leve, @pull_up, @pull_up_df, @pull_up_score, @pull_up_leve, @skip, @skip_df, @skip_score, @skip_leve, @shuttle_run, @shuttle_run_df, @shuttle_run_score, @shuttle_run_leve, @leftVision, @rightVision, @leftMirror, @rightMirror, @leftAmetropia, @rightAmetropia, @left_sphere, @right_sphere, @left_cytdnder, @right_cytdnder, @left_axial, @right_axial, @is_ok_mirror, @bonus1, @bonus1_df, @bonus2, @bonus2_df );"; return Dapper.ExcuteNonQueryAsync(sql, entity); } public Task InsertRangeAsync(IEnumerable entities) { var entityList = entities?.ToList() ?? new List(); if (entityList.Count == 0) { return Task.FromResult(0); } const string sql = @" insert into temp_tccj ( school_year, school_term, student_no, name, sex, class_no, grade_no, class_name, college_name, test_state, exempt, add_score, health_score, score, conclusion, height, weight, bmi, bmi_df, bmi_score, bmi_leve, lungs, lungs_df, lungs_score, lungs_leve, meter50, meter50_df, meter50_score, meter50_leve, standing_long_jump, standing_long_jump_df, standing_long_jump_score, standing_long_jump_leve, sit_and_reach, sit_and_reach_df, sit_and_reach_score, sit_and_reach_leve, meter800, meter800_df, meter800_score, meter800_leve, meter1000, meter1000_df, meter1000_score, meter1000_leve, sit_up, sit_up_df, sit_up_score, sit_up_leve, pull_up, pull_up_df, pull_up_score, pull_up_leve, skip, skip_df, skip_score, skip_leve, shuttle_run, shuttle_run_df, shuttle_run_score, shuttle_run_leve, leftVision, rightVision, leftMirror, rightMirror, leftAmetropia, rightAmetropia, left_sphere, right_sphere, left_cytdnder, right_cytdnder, left_axial, right_axial, is_ok_mirror, bonus1, bonus1_df, bonus2, bonus2_df ) values ( @school_year, @school_term, @student_no, @name, @sex, @class_no, @grade_no, @class_name, @college_name, @test_state, @exempt, @add_score, @health_score, @score, @conclusion, @height, @weight, @bmi, @bmi_df, @bmi_score, @bmi_leve, @lungs, @lungs_df, @lungs_score, @lungs_leve, @meter50, @meter50_df, @meter50_score, @meter50_leve, @standing_long_jump, @standing_long_jump_df, @standing_long_jump_score, @standing_long_jump_leve, @sit_and_reach, @sit_and_reach_df, @sit_and_reach_score, @sit_and_reach_leve, @meter800, @meter800_df, @meter800_score, @meter800_leve, @meter1000, @meter1000_df, @meter1000_score, @meter1000_leve, @sit_up, @sit_up_df, @sit_up_score, @sit_up_leve, @pull_up, @pull_up_df, @pull_up_score, @pull_up_leve, @skip, @skip_df, @skip_score, @skip_leve, @shuttle_run, @shuttle_run_df, @shuttle_run_score, @shuttle_run_leve, @leftVision, @rightVision, @leftMirror, @rightMirror, @leftAmetropia, @rightAmetropia, @left_sphere, @right_sphere, @left_cytdnder, @right_cytdnder, @left_axial, @right_axial, @is_ok_mirror, @bonus1, @bonus1_df, @bonus2, @bonus2_df );"; return Dapper.ExcuteNonQueryAsync(sql, entityList); } } }