using System.Data; using System.Net; using AgileObjects.AgileMapper; using AgileObjects.AgileMapper.Extensions; using Microsoft.AspNetCore.Http; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using NPOI.SS.Util; using NPOI.XSSF.UserModel; using SqlSugar; using Tiobon.Core.Common; using Tiobon.Core.Common.Caches; using Tiobon.Core.Common.DB.Dapper.Extensions; using Tiobon.Core.Common.Helper; using Tiobon.Core.IRepository.Base; using Tiobon.Core.IServices; using Tiobon.Core.Model; using Tiobon.Core.Model.Models; using Tiobon.Core.Services.BASE; using static Tiobon.Core.DataAccess.ReportHelper; namespace Tiobon.Core.Services; /// /// 题目 (服务) /// public class Ghre_QuestionServices : BaseServices, IGhre_QuestionServices { private readonly IBaseRepository _dal; private IGhre_QuestionAnswerServices _ghre_QuestionAnswerServices; private IGhre_CourseServices _ghre_CourseServices; private IGhre_CourseClassServices _ghre_CourseClassServices; public Ghre_QuestionServices(IBaseRepository dal, IGhre_QuestionAnswerServices ghre_QuestionAnswerServices, IGhre_CourseServices ghre_CourseServices, ICaching caching, IGhre_CourseClassServices ghre_CourseClassServices) { this._dal = dal; base.BaseDal = dal; base._caching = caching; _ghre_QuestionAnswerServices = ghre_QuestionAnswerServices; _ghre_CourseServices = ghre_CourseServices; _ghre_CourseClassServices = ghre_CourseClassServices; } public async Task> QueryFilterPage1(QueryBody filter) { //var data1 = await BaseDal.QueryFilterPage(body); RefAsync totalCount = 0; var query = Db.Queryable(); if (string.IsNullOrWhiteSpace(filter.orderBy)) filter.orderBy = "UpdateTime DESC,CreateTime DESC"; string conditions = "1=1"; if (filter.jsonParam != null) foreach (JProperty jProperty in filter.jsonParam.Properties()) { var name = jProperty.Name; var value = jProperty.Value.ToString(); if (name == "page" || name == "pageSize") continue; if (name == "CourseName") { string sql = string.Empty; if (!string.IsNullOrWhiteSpace(value)) { var jsonParam = JsonConvert.DeserializeObject(value); switch (jsonParam.operationKey) { case "Include": var ids = await Db.Queryable().Where(x => x.CourseName.Contains(jsonParam.columnValue.ToString())).Select(x => x.Id).ToListAsync(); query = query.Where(x => x.CourseId != null && ids.Contains(x.CourseId.Value)); break; case "NotInclude": var ids1 = await Db.Queryable().Where(x => x.CourseName.Contains(jsonParam.columnValue.ToString())).Select(x => x.Id).ToListAsync(); query = query.Where(x => x.CourseId != null && !ids1.Contains(x.CourseId.Value)); break; case "IsNull": query = query.Where(x => x.CourseId == null); break; case "NotNull": query = query.Where(x => x.CourseId != null); break; case "Equal": var id = await Db.Queryable().Where(x => x.CourseName == jsonParam.columnValue).Select(x => x.Id).FirstAsync(); query = query.Where(x => x.CourseId == id); break; case "NotEqual": var id1 = await Db.Queryable().Where(x => x.CourseName == jsonParam.columnValue).Select(x => x.Id).FirstAsync(); query = query.Where(x => x.CourseId != id1); break; default: break; } } } else if (!string.IsNullOrWhiteSpace(value)) { var jsonParam = JsonConvert.DeserializeObject(value); switch (jsonParam.operationKey) { case "Include": conditions += $" AND {name} LIKE '%{jsonParam.columnValue}%'"; break; case "NotInclude": conditions += $" AND {name} NOT LIKE '%{jsonParam.columnValue}%'"; break; case "IsNull": conditions += $" AND {name} IS NULL"; break; case "NotNull": conditions += $" AND {name} IS NOT NULL"; break; case "Equal": conditions += $" AND {name} ='{jsonParam.columnValue}'"; break; case "NotEqual": conditions += $" AND {name} !='{jsonParam.columnValue}'"; break; default: break; } } } if (filter.pageSize == 0) filter.pageSize = 10000; query = query.Where(conditions); var list = await query .OrderByIF(!string.IsNullOrEmpty(filter.orderBy), filter.orderBy) .ToPageListAsync(filter.pageNum, filter.pageSize, totalCount); var data1 = new ServicePageResult(filter.pageNum, totalCount, filter.pageSize, list); var data = Mapper.Map(data1.result.DT_TableDataT1).ToANew>(); var courseIds = data.Where(x => x.CourseId != null).Select(x => x.CourseId).Distinct().ToList(); var courses = await _ghre_CourseServices.Query(x => courseIds.Contains(x.Id)); var classsIds1 = courses.Select(x => x.CourseClassId).Distinct().ToList(); var classsIds = new List(); classsIds1.ForEach(x => { if (!string.IsNullOrWhiteSpace(x)) { var courseClassIds = JsonConvert.DeserializeObject>(x); classsIds = classsIds.Concat(courseClassIds).ToList(); } }); classsIds = classsIds.Distinct().ToList(); var classs = await _ghre_CourseClassServices.Query(x => classsIds.Contains(x.Id)); data.ForEach(async x => { x.DifficultyLevelLabel = await GetParaLabel("DifficultyLevel", x.DifficultyLevel); x.QuestionTypeLabel = await GetParaLabel("QuestionType", x.QuestionType); if (x.CourseId != null) { var course = courses.Where(a => a.Id == x.CourseId).FirstOrDefault(); x.CourseName = course?.CourseName; var courseClass = classs.Where(a => course.CourseClassId.Contains(a.Id.ToString())).ToList(); x.CourseType = string.Join(",", courseClass.Select(a => a.ClassName)); //x.CourseTypeId = courseClass.Id; } }); return new ServicePageResult(filter.pageNum, data1.result.DT_TablePageInfoT1.TotalCount, filter.pageSize, data); } public override async Task> QueryFilterPage(QueryBody filter, string condition, bool? IsEnable = true) { RefAsync totalCount = 0; string sql = @"SELECT * FROM (SELECT A.*, B.CourseName, B.CourseClassId CourseTypeId, G.UserName CreateDataInfo, H.UserName UpdateDataInfo, ISNULL(A.UpdateTime, A.CreateTime) CreateTime1 FROM Ghre_Question A LEFT JOIN Ghre_Course B ON A.CourseId = B.Id LEFT JOIN Ghrs_User G ON A.CreateBy = G.UserId LEFT JOIN Ghrs_User H ON A.UpdateBy = H.UserId WHERE A.IsEnable = 1) A"; if (string.IsNullOrWhiteSpace(filter.orderBy)) filter.orderBy = "CreateTime1 DESC"; string conditions = " WHERE 1=1"; if (filter.jsonParam != null) foreach (JProperty jProperty in filter.jsonParam.Properties()) { var name = jProperty.Name; var value = jProperty.Value.ToString(); if (name == "page" || name == "pageSize") continue; if (!string.IsNullOrWhiteSpace(value)) { var jsonParam = JsonConvert.DeserializeObject(value); switch (jsonParam.operationKey) { case "Include": conditions += $" AND {name} LIKE '%{jsonParam.columnValue}%'"; break; case "NotInclude": conditions += $" AND {name} NOT LIKE '%{jsonParam.columnValue}%'"; break; case "IsNull": conditions += $" AND {name} IS NULL"; break; case "NotNull": conditions += $" AND {name} IS NOT NULL"; break; case "Equal": conditions += $" AND {name} ='{jsonParam.columnValue}'"; break; case "NotEqual": conditions += $" AND {name} !='{jsonParam.columnValue}'"; break; default: break; } } } if (filter.pageSize == 0) filter.pageSize = 10000; sql += conditions; var data = await Db.SqlQueryable(sql) .OrderBy(filter.orderBy) .ToPageListAsync(filter.pageNum, filter.pageSize, totalCount); var classsIds1 = data.Select(x => x.CourseClassId).Distinct().ToList(); var classsIds = new List(); classsIds1.ForEach(x => { if (!string.IsNullOrWhiteSpace(x)) { var courseClassIds = JsonConvert.DeserializeObject>(x); classsIds = classsIds.Concat(courseClassIds).ToList(); } }); classsIds = classsIds.Distinct().ToList(); var classs = await _ghre_CourseClassServices.Query(x => classsIds.Contains(x.Id)); data.ForEach(async x => { x.DifficultyLevelLabel = await GetParaLabel("DifficultyLevel", x.DifficultyLevel); x.QuestionTypeLabel = await GetParaLabel("QuestionType", x.QuestionType); if (!string.IsNullOrEmpty(x.QuestionContent)) x.QuestionContent = WebUtility.HtmlDecode(x.QuestionContent); var courseClass = classs.Where(a => x.CourseClassId.Contains(a.Id.ToString())).ToList(); x.CourseType = string.Join(",", courseClass.Select(a => a.ClassName)); }); return new ServicePageResult(filter.pageNum, totalCount, filter.pageSize, data); } /// /// /// /// /// public async Task> QueryFrom(long Id) { var data = new FromGhre_QuestionInput(); #region Column data.Column.Add(new FromGhre_QuestionColumn() { label = "课程名称", field = "courseID", elementType = "ApiSelect", required = true, multipleSelect = true, editable = true, dataSource = "api/Common/GetSelect/Ghre_Course?FW=DOTNETCORE" }); data.Column.Add(new FromGhre_QuestionColumn() { label = "题目编号", field = "questionNo", elementType = "Input", required = false, multipleSelect = false, editable = false, dataSource = "", placeholder = "保存后自动生成" }); #endregion #region PageData var answerList = new List { new FromGhre_QuestionQuestionAnswerList() { No = "A", }, new FromGhre_QuestionQuestionAnswerList() { No = "B", }, new FromGhre_QuestionQuestionAnswerList() { No = "C", }, new FromGhre_QuestionQuestionAnswerList() { No = "D", } }; var answerList1 = new List { new FromGhre_QuestionQuestionAnswerList() { No = "A", label="对" }, new FromGhre_QuestionQuestionAnswerList() { No = "B", label="错" } }; data.PageData.questionType = new List { new FromGhre_QuestionQuestionType() { label = "单选题", type = "Single", isActive = 1, detail= new FromGhre_QuestionQuestionTypeDetail() { answerList=answerList } }, new FromGhre_QuestionQuestionType() { label = "多选题", type = "Multiple", isActive = 0, detail= new FromGhre_QuestionQuestionTypeDetail() { answerList=answerList } }, new FromGhre_QuestionQuestionType() { label = "判断题", type = "TrueOrFalse", isActive = 0, detail= new FromGhre_QuestionQuestionTypeDetail() { answerList=answerList1 } }, new FromGhre_QuestionQuestionType() { label = "填空题", type = "Completion", isActive = 0, detail = new FromGhre_QuestionQuestionTypeDetail() { content = "演示演示____演示", answerList= new List { new FromGhre_QuestionQuestionAnswerList() { No = "A", } } } }, new FromGhre_QuestionQuestionType() { label = "简答题", type = "ShortAnswer", isActive = 0, detail = new FromGhre_QuestionQuestionTypeDetail() { answerList= new List(), answer1 = new List { "" } } } }; if (Id != 0) { var question = await base.QueryById(Id); data.PageData.questionType.ForEach(x => x.isActive = 0); data.PageData.baseData.questionNo = question.QuestionNo; data.PageData.baseData.courseID.Add(question.CourseId); data.PageData.baseData.CreateDataInfo = question.CreateDataInfo; data.PageData.baseData.UpdateDataInfo = question.UpdateDataInfo; var questionType = data.PageData.questionType.Where(x => x.type == question.QuestionType).FirstOrDefault(); if (questionType != null) { var answers = await _ghre_QuestionAnswerServices.Query(x => x.QuestionId == Id, "TaxisNo ASC"); questionType.isActive = 1; questionType.detail.difficulty = question.DifficultyLevel; questionType.detail.answer = answers.Where(x => x.IsCorrect == true).FirstOrDefault()?.QuestionNo; questionType.detail.answer1 = answers.Where(x => x.IsCorrect == true).Select(x => x.QuestionNo).ToList(); questionType.detail.content = question.QuestionContent; if (!string.IsNullOrEmpty(questionType.detail.content)) questionType.detail.content = WebUtility.HtmlDecode(questionType.detail.content); questionType.detail.RemarkSz = question.QuestionAnalysis; questionType.detail.answerList = answers.Select(x => new FromGhre_QuestionQuestionAnswerList() { No = x.QuestionNo, label = x.AnswerContent, imageUrl = x.ImageUrl, imgWidthPc = x.ImageWidthPc, imgWidthApp = x.ImageWidthApp, }).ToList(); } } #endregion return ServiceResult.OprateSuccess("查询成功!", data); } public async Task InsertFrom(FromGhre_QuestionPageData insertModel) { var questionType = insertModel.questionType.Where(x => x.isActive == 1).FirstOrDefault(); #region 填空题处理 if (questionType.type == "Completion") questionType.detail.answerList = questionType.detail.answer1 .Select(x => new FromGhre_QuestionQuestionAnswerList() { No = x, label = x, }).ToList(); else if (questionType.type == "ShortAnswer") questionType.detail.answer1 = questionType.detail.answerList.Select(x => x.No).ToList(); #endregion ValidForm(insertModel); await Db.Ado.BeginTranAsync(); try { string questionTypeName = ConvertQuestionType(questionType.type); if (!string.IsNullOrEmpty(questionType.detail.content)) questionType.detail.content = WebUtility.HtmlEncode(questionType.detail.content); #region 判断是否重复 for (int j = 0; j < insertModel.baseData.courseID.Count; j++) { var courseID = insertModel.baseData.courseID[j]; string sql = "SELECT * FROM Ghre_Question where QuestionType='{0}' and CourseId='{1}' and QuestionContent ='{2}'"; sql = string.Format(sql, questionType.type, courseID, questionType.detail.content); DataTable dt = Db.Ado.GetDataTable(sql); if (dt.Rows.Count > 0) { var course = await _ghre_CourseServices.QueryById(courseID); throw new Exception($"课程【{course.CourseName}】存在相同内容【{questionTypeName}】"); } } #endregion for (int j = 0; j < insertModel.baseData.courseID.Count; j++) { var courseID = insertModel.baseData.courseID[j]; var insert = new InsertGhre_QuestionInput(); insert.CourseId = courseID; insert.QuestionType = questionType.type; insert.DifficultyLevel = questionType.detail.difficulty; insert.QuestionContent = questionType.detail.content; insert.QuestionAnalysis = questionType.detail.RemarkSz; insert.QuestionNo = await GenerateContinuousSequence(insert.QuestionType.Substring(0, 1)); var id = await base.Add(insert); var insertAnswers = questionType.detail.answerList.Select(x => new InsertGhre_QuestionAnswerInput() { QuestionNo = x.No, AnswerContent = x.label, ImageUrl = x.imageUrl, ImageWidthPc = x.imgWidthPc, ImageWidthApp = x.imgWidthApp, }).ToList(); int i = 100; insertAnswers.ForEach(x => { x.TaxisNo = i; x.QuestionId = id; if (questionType.detail.answer != null && questionType.detail.answer == x.QuestionNo && (insert.QuestionType == "Single" || insert.QuestionType == "TrueOrFalse")) x.IsCorrect = true; if (questionType.detail.answer1 != null && questionType.detail.answer1.Contains(x.QuestionNo) && (insert.QuestionType == "ShortAnswer" || insert.QuestionType == "Multiple" || insert.QuestionType == "Completion")) x.IsCorrect = true; i = i + 100; }); if (insertAnswers.Where(b => string.IsNullOrWhiteSpace(b.AnswerContent) && string.IsNullOrWhiteSpace(b.ImageUrl)).Any()) throw new Exception(insert.QuestionType == "ShortAnswer" ? "关键词存在空值!" : "答案选项存在空值!"); if (!insertAnswers.Where(b => b.IsCorrect == true).Any()) throw new Exception(insert.QuestionType == "ShortAnswer" ? "关键词未填写!" : "正确答案未标记!"); await _ghre_QuestionAnswerServices.Add(insertAnswers); } await Db.Ado.CommitTranAsync(); return ServiceResult.OprateSuccess("新增成功!"); } catch (Exception) { await Db.Ado.RollbackTranAsync(); throw; } } public async Task UpdareFrom(long Id, FromGhre_QuestionPageData editModel) { var questionType = editModel.questionType.Where(x => x.isActive == 1).FirstOrDefault(); if (!string.IsNullOrEmpty(questionType.detail.content)) questionType.detail.content = WebUtility.HtmlEncode(questionType.detail.content); #region 填空题处理 if (questionType.type == "Completion") questionType.detail.answerList = questionType.detail.answer1 .Select(x => new FromGhre_QuestionQuestionAnswerList() { No = x, label = x, }).ToList(); else if (questionType.type == "ShortAnswer") questionType.detail.answer1 = questionType.detail.answerList.Select(x => x.No).ToList(); #endregion ValidForm(editModel); await Db.Ado.BeginTranAsync(); try { string questionTypeName = ConvertQuestionType(questionType.type); #region 判断是否重复 for (int j = 0; j < editModel.baseData.courseID.Count; j++) { var courseID = editModel.baseData.courseID[j]; string sql = "SELECT * FROM Ghre_Question where QuestionType='{0}' and CourseId='{1}' and QuestionContent ='{2}' AND Id !='{3}'"; sql = string.Format(sql, questionType.type, courseID, questionType.detail.content, Id); DataTable dt = Db.Ado.GetDataTable(sql); if (dt.Rows.Count > 0) { var course = await _ghre_CourseServices.QueryById(courseID); throw new Exception($"课程【{course.CourseName}】存在相同内容【{questionTypeName}】"); } } #endregion var data = await base.QueryById(Id); await _ghre_QuestionAnswerServices.Delete(x => x.QuestionId == Id); var edit = Mapper.Map(data).ToANew(); edit.CourseId = editModel.baseData.courseID[0]; edit.QuestionType = questionType.type; edit.DifficultyLevel = questionType.detail.difficulty; edit.QuestionContent = questionType.detail.content; edit.QuestionAnalysis = questionType.detail.RemarkSz; await base.Update(Id, edit); var insertAnswers = questionType.detail.answerList.Select(x => new InsertGhre_QuestionAnswerInput() { QuestionNo = x.No, AnswerContent = x.label, ImageUrl = x.imageUrl, ImageWidthPc = x.imgWidthPc, ImageWidthApp = x.imgWidthApp, }).ToList(); int i = 100; insertAnswers.ForEach(x => { x.TaxisNo = i; x.QuestionId = Id; if (questionType.detail.answer != null && questionType.detail.answer == x.QuestionNo && (edit.QuestionType == "Single" || edit.QuestionType == "TrueOrFalse")) x.IsCorrect = true; if (questionType.detail.answer1 != null && questionType.detail.answer1.Contains(x.QuestionNo) && (edit.QuestionType == "ShortAnswer" || edit.QuestionType == "Multiple" || edit.QuestionType == "Completion")) x.IsCorrect = true; i = i + 100; }); if (insertAnswers.Where(b => string.IsNullOrWhiteSpace(b.AnswerContent) && string.IsNullOrWhiteSpace(b.ImageUrl)).Any()) throw new Exception(edit.QuestionType == "ShortAnswer" ? "关键词存在空值!" : "答案选项存在空值!"); if (!insertAnswers.Where(b => b.IsCorrect == true).Any()) throw new Exception(edit.QuestionType == "ShortAnswer" ? "关键词未填写!" : "正确答案未标记!"); await _ghre_QuestionAnswerServices.Add(insertAnswers); for (int j = 0; j < editModel.baseData.courseID.Count; j++) { if (j == 0) continue; var courseID = editModel.baseData.courseID[j]; var insert = new InsertGhre_QuestionInput(); insert.CourseId = courseID; insert.QuestionType = questionType.type; insert.DifficultyLevel = questionType.detail.difficulty; insert.QuestionContent = questionType.detail.content; insert.QuestionAnalysis = questionType.detail.RemarkSz; insert.QuestionNo = await GenerateContinuousSequence(insert.QuestionType.Substring(0, 1)); var id = await base.Add(insert); insertAnswers = questionType.detail.answerList.Select(x => new InsertGhre_QuestionAnswerInput() { QuestionNo = x.No, AnswerContent = x.label, ImageUrl = x.imageUrl, ImageWidthPc = x.imgWidthPc, ImageWidthApp = x.imgWidthApp, }).ToList(); i = 100; insertAnswers.ForEach(x => { x.TaxisNo = i; x.QuestionId = id; if (questionType.detail.answer != null && questionType.detail.answer == x.QuestionNo && (insert.QuestionType == "Single" || insert.QuestionType == "TrueOrFalse")) x.IsCorrect = true; if (questionType.detail.answer1 != null && questionType.detail.answer1.Contains(x.QuestionNo) && (insert.QuestionType == "ShortAnswer" || insert.QuestionType == "Multiple" || insert.QuestionType == "Completion")) x.IsCorrect = true; i = i + 100; }); if (insertAnswers.Where(b => string.IsNullOrWhiteSpace(b.AnswerContent)).Any()) throw new Exception(insert.QuestionType == "ShortAnswer" ? "关键词存在空值!" : "答案选项存在空值!"); if (!insertAnswers.Where(b => b.IsCorrect == true).Any()) throw new Exception(insert.QuestionType == "ShortAnswer" ? "关键词未填写!" : "正确答案未标记!"); await _ghre_QuestionAnswerServices.Add(insertAnswers); } await Db.Ado.CommitTranAsync(); return ServiceResult.OprateSuccess("更新成功!"); } catch (Exception) { await Db.Ado.RollbackTranAsync(); throw; } } public async Task GenerateContinuousSequence(string prefixTemp) { try { string result = string.Empty; string tableCode = "Ghre_Question"; string columnCode = "QuestionNo"; int length = 7; int tempLength = 6; int sequence; #region 查询 DbSelect dbSelect = new DbSelect(tableCode + " A", "A", null); dbSelect.IsInitDefaultValue = false; if (!string.IsNullOrEmpty(prefixTemp)) dbSelect.Select("MAX(SUBSTRING(A." + columnCode + "," + (prefixTemp.Length + 1).ToString() + "," + tempLength.ToString() + "))"); else dbSelect.Select("MAX(A." + columnCode + ")"); //} //dbSelect.Select("MAX(CONVERT(DECIMAL,SUBSTRING(A.ISSUE_NO," + (prefix.Length + dateString.Length + 1).ToString() + "," + tempLength.ToString() + ")))"); if (!string.IsNullOrEmpty(prefixTemp)) dbSelect.Where("SUBSTRING(A." + columnCode + ",1," + (prefixTemp.Length).ToString() + ")", " = ", prefixTemp); dbSelect.Where("LEN(A." + columnCode + ")", "=", length); string sql = dbSelect.GetSql(); //await Db.Ado.GetScalarAsync(sql) string maxSequence = Convert.ToString(await Db.Ado.GetScalarAsync(sql)); #endregion //tempLength = tempLength - dateString.Length; if (string.IsNullOrEmpty(maxSequence)) result = prefixTemp + Convert.ToString(1).PadLeft(tempLength, '0'); else { if (!string.IsNullOrEmpty(prefixTemp)) { if (int.TryParse(maxSequence, out sequence)) { sequence += 1; if (sequence.ToString().Length > tempLength) throw new Exception("自动生成字串长度已经超过设定长度!"); } else throw new Exception("表中的数据无法进行自动编号,请联系软件开发商!"); result = prefixTemp + sequence.ToString().PadLeft(tempLength, '0'); } else { if (int.TryParse(maxSequence, out sequence)) { sequence += 1; if (sequence.ToString().Length > length) throw new Exception("自动生成字串长度已经超过设定长度!"); } else throw new Exception("表中的数据无法进行自动编号,请联系软件开发商!"); result = sequence.ToString().PadLeft(length, '0'); } } return result; } catch (Exception) { throw; } } public static string ConvertQuestionType(string type) { string questionTypeName = string.Empty; if (type == "Single") questionTypeName = "单选题"; else if (type == "Multiple") questionTypeName = "多选题"; else if (type == "TrueOrFalse") questionTypeName = "判断题"; else if (type == "Completion") questionTypeName = "填空题"; else if (type == "ShortAnswer") questionTypeName = "简答题"; return questionTypeName; } public static string ConvertDifficultyLevel(string type) { string questionTypeName = string.Empty; if (type == "Easy") questionTypeName = "简单"; else if (type == "Normal") questionTypeName = "普通"; else if (type == "Hard") questionTypeName = "困难"; return questionTypeName; } public static string ConvertQuestionType1(string type) { string questionTypeName = string.Empty; if (type == "单选题") questionTypeName = "Single"; else if (type == "多选题") questionTypeName = "Multiple"; else if (type == "判断题") questionTypeName = "TrueOrFalse"; else if (type == "填空题") questionTypeName = "Completion"; else if (type == "简答题") questionTypeName = "ShortAnswer"; return questionTypeName; } public static string ConvertDifficultyLevel1(string type) { string questionTypeName = string.Empty; if (type == "简单") questionTypeName = "Easy"; else if (type == "普通") questionTypeName = "Normal"; else if (type == "困难") questionTypeName = "Hard"; return questionTypeName; } public static void ValidForm(FromGhre_QuestionPageData model) { if (model.baseData.courseID is null || (model.baseData.courseID != null && !model.baseData.courseID.Any())) throw new Exception("课程必填!"); var questionType = model.questionType.Where(x => x.isActive == 1).FirstOrDefault(); if (questionType is null) throw new Exception("提交参数异常!"); if (string.IsNullOrWhiteSpace(questionType.detail.difficulty)) throw new Exception("难易程度必填!"); if (string.IsNullOrWhiteSpace(ConvertDifficultyLevel(questionType.detail.difficulty))) throw new Exception("无效的难易程度类型!"); if (string.IsNullOrWhiteSpace(questionType.detail.content)) throw new Exception("题目内容必填!"); if (questionType.detail.answerList is null || (questionType.detail.answerList != null && !questionType.detail.answerList.Any())) throw new Exception(questionType.type == "ShortAnswer" ? "关键词未填写!" : "答案选项必填!"); if (questionType.detail.answerList.Count < 2 && questionType.type != "ShortAnswer" && questionType.type != "Completion") throw new Exception("答案选项不能少于两个!"); if ((questionType.type == "Single" || questionType.type == "TrueOrFalse") && string.IsNullOrWhiteSpace(questionType.detail.answer)) throw new Exception("正确答案未标记!"); else if (questionType.type == "Multiple" && (questionType.detail.answer1 == null || (questionType.detail.answer1 != null && !questionType.detail.answer1.Any()))) throw new Exception("正确答案未标记!"); if (questionType.type == "Multiple" && questionType.detail.answer1.Count < 2) throw new Exception("答案至少需标记处两个正确答案!"); if (string.IsNullOrWhiteSpace(questionType.detail.RemarkSz)) throw new Exception("题目解析必填!"); } #region Excel导入 public override async Task> ImportExcel(IFormFile file) { var data = new ExcelData(); long id = SnowFlakeSingle.instance.getID(); var physicsPath = $"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}wwwroot"; var path = $"{$"{Path.DirectorySeparatorChar}files{Path.DirectorySeparatorChar}import{Path.DirectorySeparatorChar}{id}{Path.DirectorySeparatorChar}"}"; if (!Directory.Exists(physicsPath + path)) Directory.CreateDirectory(physicsPath + path); var filepath = physicsPath + path + file.FileName; using (var stream = File.Create(filepath)) { await file.CopyToAsync(stream); } string extension = Path.GetExtension(filepath); var types = new List { "单选题", "多选题", "判断题", "填空题", "简答题", }; var answers = new List { "A", "B", "C", "D", "E", "F", "G", "H", }; bool isExistError = false; var id1 = SnowFlakeSingle.instance.getID(); string errorFileName = path + SnowFlakeSingle.instance.getID() + extension; //types.ForEach(async x => //{ // string questionType = ConvertQuestionType1(x); // DataTable dt = NPOIHelper.ImportExcel(filepath, x); // NPOIHelper.ExportExcel(dt, null, x, path + id1 + extension); //}); for (int jj = 0; jj < types.Count; jj++) { var x = types[jj]; string questionType = ConvertQuestionType1(x); DataTable dt = NPOIHelper.ImportExcel(filepath, x); if (dt.Columns["Comments"] == null) dt.Columns.Add("Comments", typeof(string)); for (int i = 0; i < dt.Rows.Count; i++) { var comments = new List(); var courseName = dt.Rows[i]["课程(必填)"].ToString(); var questionContent = dt.Rows[i]["题目内容(必填)"].ToString(); var correctAnswer = string.Empty; if (questionType != "Completion" && questionType != "ShortAnswer") correctAnswer = dt.Rows[i]["正确答案(必填)"].ToString(); var questionAnalysis = dt.Rows[i]["解析"].ToString(); var difficultyLevel = dt.Rows[i]["难度"].ToString() ?? "普通"; if (string.IsNullOrEmpty(questionContent)) comments.Add("题目内容为必填项!"); var question = await base.Query(x => x.QuestionContent == questionContent && x.QuestionType == questionType); if (!question.Any()) { if (string.IsNullOrEmpty(courseName)) comments.Add("课程为必填项!"); if (string.IsNullOrWhiteSpace(correctAnswer) && questionType != "Completion" && questionType != "ShortAnswer") comments.Add("正确答案未标记!"); if (string.IsNullOrWhiteSpace(difficultyLevel)) comments.Add("难易程度必填!"); if (string.IsNullOrWhiteSpace(questionAnalysis)) comments.Add("题目解析必填!"); Ghre_CourseDto course = null; if (!string.IsNullOrEmpty(courseName)) { course = await _ghre_CourseServices.QuerySingleDto(x => x.CourseName == courseName); if (course is null) comments.Add("课程不存在,请修正!"); } var insert = new InsertGhre_QuestionInput() { CourseId = course?.Id, QuestionNo = await GenerateContinuousSequence(questionType.Substring(0, 1)), DifficultyLevel = ConvertDifficultyLevel1(difficultyLevel), QuestionType = questionType, QuestionContent = questionContent, QuestionAnalysis = questionAnalysis }; var insertAnswers = new List(); if (questionType == "Single" || questionType == "Multiple") { #region 单选题/多选题 int j = 100; answers.ForEach(a => { var answer = dt.Rows[i]["选项" + a].ToString(); if (!string.IsNullOrWhiteSpace(answer)) { var isCorrect = false; if (correctAnswer.Contains(a)) isCorrect = true; insertAnswers.Add(new InsertGhre_QuestionAnswerInput() { TaxisNo = j, QuestionNo = a, //QuestionId = id, AnswerContent = answer, IsCorrect = isCorrect }); } j = j + 100; }); if (!insertAnswers.Any()) comments.Add(questionType == "ShortAnswer" ? "关键词未填写!" : "答案选项必填!"); if (insertAnswers.Count < 2 && questionType != "ShortAnswer" && questionType != "Completion") comments.Add("答案选项不能少于两个!"); if ((questionType == "Single" || questionType == "Multiple" || questionType == "TrueOrFalse") && !insertAnswers.Any(o => o.IsCorrect == true)) comments.Add("正确答案未标记!"); if (questionType == "Multiple" && insertAnswers.Where(o => o.IsCorrect == true).Count() < 2) comments.Add("答案至少需标记处两个正确答案!"); #endregion } else if (questionType == "TrueOrFalse") { #region 判断题 insertAnswers.Add(new InsertGhre_QuestionAnswerInput() { TaxisNo = 100, QuestionNo = "A", //QuestionId = id, AnswerContent = "对", IsCorrect = correctAnswer == "正确" }); insertAnswers.Add(new InsertGhre_QuestionAnswerInput() { TaxisNo = 200, QuestionNo = "B", //QuestionId = id, AnswerContent = "错", IsCorrect = correctAnswer == "错误" }); #endregion } else if (questionType == "Completion") { questionContent = questionContent.Replace("()", "()"); var completionCount = 0; for (int ii = 1; ii < 11; ii++) { var answer = dt.Rows[i]["答案" + ii].ToString(); if (!string.IsNullOrWhiteSpace(answer)) { completionCount++; int index = questionContent.IndexOf("()"); if (index > -1) { if (questionContent.Length > index + 2) { if (questionContent.Substring(index + 2, 2) == "()") questionContent = questionContent.Substring(0, index) + "____、" + questionContent.Substring(index + 2); } else questionContent = questionContent.Substring(0, index) + "____" + questionContent.Substring(index + 2); insertAnswers.Add(new InsertGhre_QuestionAnswerInput() { TaxisNo = ii * 100, QuestionNo = answer, //QuestionId = id, AnswerContent = answer, IsCorrect = true }); } } } if (completionCount != insertAnswers.Count) comments.Add("题目内容填空个数与答案个数不匹配!"); else insert.QuestionContent = questionContent; } else if (questionType == "ShortAnswer") { for (int ii = 1; ii < 11; ii++) { var answer = dt.Rows[i]["关键词" + ii].ToString(); if (!string.IsNullOrWhiteSpace(answer)) { insertAnswers.Add(new InsertGhre_QuestionAnswerInput() { TaxisNo = ii * 100, QuestionNo = answer, //QuestionId = id, AnswerContent = answer, IsCorrect = true }); } } } if (comments.Any()) { data.ErrorCount++; dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a)); isExistError = true; continue; } else { data.SuccessCount++; id = await base.Add(insert); insertAnswers.ForEach(x => x.QuestionId = id); await _ghre_QuestionAnswerServices.Add(insertAnswers); } } else { dt.Rows[i]["Comments"] = "试题在系统中已存在!"; data.ErrorCount++; isExistError = true; continue; } } if (isExistError) { NPOIHelper.ExportExcel(dt, null, x, physicsPath + errorFileName); data.filePath = errorFileName; } } return ServiceResult.OprateSuccess("导入成功!", data); } public override async Task> DownloadExcel(string menuName) { var physicsPath = $"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}wwwroot"; var path = $"{$"{Path.DirectorySeparatorChar}files{Path.DirectorySeparatorChar}ExcelTemplate{Path.DirectorySeparatorChar}"}"; if (!Directory.Exists(physicsPath + path)) Directory.CreateDirectory(physicsPath + path); Type entityType = typeof(Ghre_Question); var fileName = entityType.GetEntityTableName() + ".xlsx"; //physicsPath = physicsPath + path + fileName; IWorkbook hssfworkbook; ISheet sheet; using (FileStream file = new FileStream(physicsPath + path + fileName, FileMode.Open, FileAccess.Read)) { //hssfworkbook = new HSSFWorkbook(file); //hssfworkbook = new XSSFWorkbook(file); hssfworkbook = WorkbookFactory.Create(file); } ISheet sheet2 = hssfworkbook.CreateSheet("下拉数据"); var newFileName = Guid.NewGuid() + ".xlsx"; int listColIndex = 0; string sql = @"select 'Course' field, Id id, CourseNo no, CourseName name from Ghre_Course where IsEnable=1 and Status='Released'"; var dataSourceLists = await Db.Ado.SqlQueryAsync(sql); if (dataSourceLists.Any()) { var types = new List { "单选题", "多选题", "判断题", "填空题", "简答题", }; types.ForEach(sheetName => { int sheetIndex = hssfworkbook.GetSheetIndex(sheetName); if (sheetIndex >= 0) { sheet = hssfworkbook.GetSheetAt(sheetIndex); SetCellDropdownList(sheet, 0, 0, dataSourceLists.Select(x => x.name).ToArray()); } }); MemoryStream ms; using (ms = new MemoryStream()) { hssfworkbook.Write(ms); ms.Flush(); hssfworkbook.Dispose(); //ms.Position = 0; //return ms; } using (FileStream fs = new FileStream(physicsPath + path + newFileName, FileMode.Create, FileAccess.Write)) { byte[] data = ms.ToArray(); fs.Write(data, 0, data.Length); fs.Flush(); } } var physicsPath1 = physicsPath + path + fileName; if (dataSourceLists.Any()) physicsPath1 = physicsPath + path + newFileName; var result = ServiceResult.OprateSuccess(fileName, physicsPath1); return result; } public static void SetCellDropdownList(ISheet sheet, int firstcol, int lastcol, string[] vals) { //設置生成下拉框的行和列 var cellRegions = new CellRangeAddressList(1, 65535, firstcol, lastcol); IDataValidation validation = null; if (sheet.GetType().Name.Contains("XSSF")) // .xlsx { XSSFDataValidationHelper helper = new XSSFDataValidationHelper((XSSFSheet)sheet);//获得一个数据验证Helper //IDataValidation validation = helper.CreateValidation( helper.CreateExplicitListConstraint(vals), cellRegions);//创建约束 } else // HSSF .xls { //設置 下拉框內容 DVConstraint constraint = DVConstraint.CreateExplicitListConstraint(vals); validation = new HSSFDataValidation(cellRegions, constraint); /*綁定下拉框和作用區域,並設置錯誤提示信息 HSSFDataValidation dataValidate = new HSSFDataValidation(cellRegions, constraint); dataValidate.CreateErrorBox("輸入不合法", "請輸入或選擇下拉列表中的值。"); dataValidate.ShowPromptBox = true; */ } validation.CreateErrorBox("输入不合法", "请输入或选择下拉列表中的值。"); validation.ShowPromptBox = true; sheet.AddValidationData(validation); } #endregion /// /// 删除指定ID的数据 /// /// 主键ID /// public override async Task DeleteById1(object id) { var entity = await BaseDal.QueryById(id); if (entity != null) { string sql = @$"SELECT A.* FROM Ghre_ExamPaper A JOIN Ghre_ExamPaperQuestion B ON B.ExamPaperId = A.Id WHERE B.QuestionId = '{id}' AND A.Status = 'Released'"; var entitys = await Db.SqlQueryable(sql) .ToPageListAsync(0, 10); if (entitys.Any()) throw new Exception($"题目【{entity.QuestionNo} 】已被试卷{string.Join("、", entitys.Select(x => $"【{x.PaperName}({x.PaperNo})】"))}关联,暂不可删除!"); } return await base.DeleteById1(id); } /// /// 删除指定ID集合的数据(批量删除) /// /// 主键ID集合 /// public override async Task DeleteByIds1(long[] ids) { foreach (var id in ids) { var entity = await BaseDal.QueryById(id); if (entity != null) { string sql = @$"SELECT A.* FROM Ghre_ExamPaper A JOIN Ghre_ExamPaperQuestion B ON B.ExamPaperId = A.Id WHERE B.QuestionId = '{id}' AND A.Status = 'Released'"; var entitys = await Db.SqlQueryable(sql) .ToPageListAsync(0, 10); if (entitys.Any()) throw new Exception($"题目【{entity.QuestionNo} 】已被试卷{string.Join("、", entitys.Select(x => $"【{x.PaperName}({x.PaperNo})】"))}关联,暂不可删除!"); } } return await base.DeleteByIds1(ids); } }