From 92a4c85135e98c5b848a76ddcdcc55a640e38215 Mon Sep 17 00:00:00 2001 From: xiaochanghai Date: Wed, 19 Jun 2024 15:43:14 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A2=98=E5=BA=93=E5=AE=9A=E5=88=B6=E5=8C=96?= =?UTF-8?q?=E5=AF=BC=E5=85=A5Excwl=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Base/BaseController.cs | 17 +- .../Ghre/Ghre_QuestionController.cs | 8 - Tiobon.Core.Api/Tiobon.Core.xml | 2 +- Tiobon.Core.Common/Helper/NPOIHelper.cs | 36 +++- Tiobon.Core.IServices/BASE/IBaseServices.cs | 5 +- .../Ghre/IGhre_QuestionServices.cs | 20 +-- .../Ghre_CourseWareAttachment.Dto.Base.cs | 2 +- Tiobon.Core.Services/BASE/BaseServices.cs | 15 +- .../Ghre/Ghre_CourseServices.cs | 4 +- .../Ghre/Ghre_QuestionServices.cs | 169 +++++++++++++----- Tiobon.Core/Tiobon.Core.xml | 2 +- 11 files changed, 202 insertions(+), 78 deletions(-) diff --git a/Tiobon.Core.Api/Controllers/Base/BaseController.cs b/Tiobon.Core.Api/Controllers/Base/BaseController.cs index e2c2fff4..58b3dba4 100644 --- a/Tiobon.Core.Api/Controllers/Base/BaseController.cs +++ b/Tiobon.Core.Api/Controllers/Base/BaseController.cs @@ -210,10 +210,21 @@ public class BaseController /// /// - [HttpPost, Route("Export")] - public async Task> Export([FromBody] QueryBody body) + [HttpPost, Route("ExportExcel")] + public async Task> ExportExcel([FromBody] QueryBody body) { - var data = (await InvokeServiceAsync("Export", [body])) as ServiceResult; + var data = (await InvokeServiceAsync("ExportExcel", [body])) as ServiceResult; + return data; + } + #endregion + + + + #region Excel导入 + [HttpPost("ImportExcel")] + public async Task> ImportExcel(IFormFile file) + { + var data = (await InvokeServiceAsync("ImportExcel", [file])) as ServiceResult; return data; } #endregion diff --git a/Tiobon.Core.Api/Controllers/Ghre/Ghre_QuestionController.cs b/Tiobon.Core.Api/Controllers/Ghre/Ghre_QuestionController.cs index 0f976602..aca2ff58 100644 --- a/Tiobon.Core.Api/Controllers/Ghre/Ghre_QuestionController.cs +++ b/Tiobon.Core.Api/Controllers/Ghre/Ghre_QuestionController.cs @@ -60,12 +60,4 @@ public class Ghre_QuestionController : BaseController ImportExcelAsync(IFormFile file) - { - return await _service.ImportExcelAsync(file); - } - #endregion - } \ No newline at end of file diff --git a/Tiobon.Core.Api/Tiobon.Core.xml b/Tiobon.Core.Api/Tiobon.Core.xml index 2caf0163..8aeb043f 100644 --- a/Tiobon.Core.Api/Tiobon.Core.xml +++ b/Tiobon.Core.Api/Tiobon.Core.xml @@ -141,7 +141,7 @@ 主键IDs - + Excel导出 diff --git a/Tiobon.Core.Common/Helper/NPOIHelper.cs b/Tiobon.Core.Common/Helper/NPOIHelper.cs index 44a60c4f..7993eac4 100644 --- a/Tiobon.Core.Common/Helper/NPOIHelper.cs +++ b/Tiobon.Core.Common/Helper/NPOIHelper.cs @@ -1,4 +1,5 @@ using System.Data; +using System.IO; using System.Text; using NPOI.HPSF; using NPOI.HSSF.UserModel; @@ -16,11 +17,28 @@ public class NPOIHelper /// 源 DataTable /// 表头文本 空值未不要表头标题 /// - public static MemoryStream ExportExcel(DataTable dtSource, string strHeaderText) + public static MemoryStream GenerateExportExcel(DataTable dtSource, string strHeaderText, string sheetName, string strFileName = null) { - //HSSFWorkbook workbook = new HSSFWorkbook(); - XSSFWorkbook workbook = new XSSFWorkbook(); - ISheet sheet = workbook.CreateSheet(); + IWorkbook workbook = new XSSFWorkbook(); + ISheet sheet; + if (!File.Exists(strFileName)) + { + sheet = workbook.CreateSheet(sheetName); + } + else + { + using (FileStream file = new FileStream(strFileName, FileMode.Open, FileAccess.Read)) + { + //hssfworkbook = new HSSFWorkbook(file); + //hssfworkbook = new XSSFWorkbook(file); + workbook = WorkbookFactory.Create(file); + } + if (workbook == null) throw new Exception("未能加载excel"); + + sheet = workbook.CreateSheet(sheetName); + } + + #region 文件属性 DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation(); dsi.Company = "EUCloud"; @@ -72,7 +90,7 @@ public class NPOIHelper intTop = 0; #region 表头及样式 { - if (strHeaderText.Length > 0) + if (!string.IsNullOrWhiteSpace(strHeaderText) && strHeaderText.Length > 0) { IRow headerRow = sheet.CreateRow(intTop); intTop += 1; @@ -190,6 +208,7 @@ public class NPOIHelper { workbook.Write(ms); ms.Flush(); + workbook.Dispose(); //ms.Position = 0; return ms; } @@ -203,9 +222,9 @@ public class NPOIHelper /// 源 DataaTable /// 表头文本 /// 保存位置(文件名及路径) - public static void ExportExcel(DataTable dtSource, string strHeaderText, string strFileName) + public static void ExportExcel(DataTable dtSource, string strHeaderText, string sheetName = null, string strFileName = null) { - using (MemoryStream ms = ExportExcel(dtSource, strHeaderText)) + using (MemoryStream ms = GenerateExportExcel(dtSource, strHeaderText, sheetName, strFileName)) { using (FileStream fs = new FileStream(strFileName, FileMode.Create, FileAccess.Write)) { @@ -260,7 +279,8 @@ public class NPOIHelper for (int j = 0; j < cellCount; j++) { ICell cell = headerRow.GetCell(j); - dt.Columns.Add(cell.ToString()); + if (!string.IsNullOrWhiteSpace(cell.ToString())) + dt.Columns.Add(cell.ToString()); } for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++) { diff --git a/Tiobon.Core.IServices/BASE/IBaseServices.cs b/Tiobon.Core.IServices/BASE/IBaseServices.cs index d6fa9fdf..fcc4b6f1 100644 --- a/Tiobon.Core.IServices/BASE/IBaseServices.cs +++ b/Tiobon.Core.IServices/BASE/IBaseServices.cs @@ -1,5 +1,6 @@ using System.Data; using System.Linq.Expressions; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using SqlSugar; using Tiobon.Core.Common; @@ -150,7 +151,9 @@ namespace Tiobon.Core.IServices.BASE Task> QueryPage(Expression> whereExpression, int pageIndex = 1, int pageSize = 20, string orderByFields = null); Task> QueryFilterPage([FromBody] QueryBody body); Task> QueryFilterPage(QueryBody filter, string condition); - Task> Export([FromBody] QueryBody body); + Task> ExportExcel([FromBody] QueryBody body); + + Task> ImportExcel(IFormFile file); Task> QueryMuch( Expression> joinExpression, diff --git a/Tiobon.Core.IServices/Ghre/IGhre_QuestionServices.cs b/Tiobon.Core.IServices/Ghre/IGhre_QuestionServices.cs index 05a4e692..c640809b 100644 --- a/Tiobon.Core.IServices/Ghre/IGhre_QuestionServices.cs +++ b/Tiobon.Core.IServices/Ghre/IGhre_QuestionServices.cs @@ -4,17 +4,15 @@ using Tiobon.Core.Model; using Tiobon.Core.Model.Models; namespace Tiobon.Core.IServices -{ - /// - /// 题目(自定义服务接口) - /// - public interface IGhre_QuestionServices :IBaseServices - { - Task> QueryFrom(long Id); - Task InsertFrom(FromGhre_QuestionPageData insertModel); +{ + /// + /// 题目(自定义服务接口) + /// + public interface IGhre_QuestionServices : IBaseServices + { + Task> QueryFrom(long Id); + Task InsertFrom(FromGhre_QuestionPageData insertModel); - Task UpdareFrom(long Id, FromGhre_QuestionPageData insertModel); - - Task ImportExcelAsync(IFormFile file); + Task UpdareFrom(long Id, FromGhre_QuestionPageData insertModel); } } \ No newline at end of file diff --git a/Tiobon.Core.Model/Base/Ghre/Ghre_CourseWareAttachment.Dto.Base.cs b/Tiobon.Core.Model/Base/Ghre/Ghre_CourseWareAttachment.Dto.Base.cs index e1eacaff..f78bd748 100644 --- a/Tiobon.Core.Model/Base/Ghre/Ghre_CourseWareAttachment.Dto.Base.cs +++ b/Tiobon.Core.Model/Base/Ghre/Ghre_CourseWareAttachment.Dto.Base.cs @@ -40,7 +40,7 @@ namespace Tiobon.Core.Model.Models /// /// 扩展名 /// - [Display(Name = "AttachFileExtension"), Description("扩展名"), MaxLength(32, ErrorMessage = "扩展名 不能超过 32 个字符")] + [Display(Name = "AttachFileExtension"), Description("扩展名"), MaxLength(256, ErrorMessage = "扩展名 不能超过 256 个字符")] public string AttachFileExtension { get; set; } /// diff --git a/Tiobon.Core.Services/BASE/BaseServices.cs b/Tiobon.Core.Services/BASE/BaseServices.cs index d320c2a9..8242db45 100644 --- a/Tiobon.Core.Services/BASE/BaseServices.cs +++ b/Tiobon.Core.Services/BASE/BaseServices.cs @@ -20,6 +20,7 @@ using Tiobon.Core.Common.Helper; using Tiobon.Core.Common.UserManager; using Tiobon.Core.DataAccess; using Tiobon.Core.IRepository.Base; +using Tiobon.Core.IServices; using Tiobon.Core.IServices.BASE; using Tiobon.Core.Model; using Tiobon.Core.Model.Models; @@ -788,7 +789,7 @@ public class BaseServices : IBaseServ return new ServicePageResult(filter.pageNum, total, filter.pageSize, entitys); } - public async Task> Export(QueryBody body) + public async Task> ExportExcel(QueryBody body) { //sql = @$"SELECT field, // [dbo].[FLangKeyToValue] (mkey, {body.langId}, label) @@ -816,6 +817,18 @@ public class BaseServices : IBaseServ } + public async virtual Task> ImportExcel(IFormFile file) + { + //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); + + + return ServiceResult.OprateSuccess("导入成功!"); + } + public async Task> QueryMuch(Expression> joinExpression, Expression> selectExpression, Expression> whereLambda = null) where T : class, new() { return await BaseDal.QueryMuch(joinExpression, selectExpression, whereLambda); diff --git a/Tiobon.Core.Services/Ghre/Ghre_CourseServices.cs b/Tiobon.Core.Services/Ghre/Ghre_CourseServices.cs index 0bafbd65..0b03ec38 100644 --- a/Tiobon.Core.Services/Ghre/Ghre_CourseServices.cs +++ b/Tiobon.Core.Services/Ghre/Ghre_CourseServices.cs @@ -139,7 +139,7 @@ public class Ghre_CourseServices : BaseServices ImportExcelAsync(IFormFile file) + public override async Task> ImportExcel(IFormFile file) { long id = SnowFlakeSingle.instance.getID(); - var path = $"{$"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}wwwroot{Path.DirectorySeparatorChar}files{Path.DirectorySeparatorChar}import{Path.DirectorySeparatorChar}{id}{Path.DirectorySeparatorChar}"}"; - if (!Directory.Exists(path)) - Directory.CreateDirectory(path); + 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 = path + file.FileName; + 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 { "单选题", - //"多选题", - //"判断题", + "多选题", + "判断题", //"填空题", //"简答题", }; @@ -818,35 +818,68 @@ public class Ghre_QuestionServices : BaseServices - { + 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); + //}); + + types.ForEach(async x => + { + + string questionType = ConvertQuestionType1(x); + DataTable dt = NPOIHelper.ImportExcel(filepath, x); + if (dt.Columns["Comments"] == null) + dt.Columns.Add("Comments", typeof(string)); - string questionType = ConvertQuestionType1(x); - DataTable dt = NPOIHelper.ImportExcel(filepath, "单选题"); - for (int i = 0; i < dt.Rows.Count; i++) + 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 = 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()) { - var course = await _ghre_CourseServices.Query(x => x.CourseName == dt.Rows[i]["课程(必填)"].ToString()); - var questionContent = dt.Rows[i]["题干(必填)"].ToString(); - var correctAnswer = dt.Rows[i]["正确答案(必填)"].ToString(); - var questionAnalysis = dt.Rows[i]["解析"].ToString(); - var difficultyLevel = dt.Rows[i]["难度"].ToString(); + if (string.IsNullOrEmpty(courseName)) + comments.Add("课程为必填项!"); + if (string.IsNullOrWhiteSpace(correctAnswer)) + comments.Add("正确答案未标记!"); + if (string.IsNullOrWhiteSpace(difficultyLevel)) + comments.Add("难易程度必填!"); + if (string.IsNullOrWhiteSpace(questionAnalysis)) + comments.Add("题目解析必填!"); - var question = await base.Query(x => x.QuestionContent == questionContent); - if (!question.Any()) + var course = await _ghre_CourseServices.QuerySingleDto(x => x.CourseName == courseName); + if (course is null) + comments.Add("课程不存在,请修正!"); + + var insert = new InsertGhre_QuestionInput() { - var insert = new InsertGhre_QuestionInput() - { - CourseId = course.FirstOrDefault().Id, - QuestionNo = await GenerateContinuousSequence(questionType.Substring(0, 1)), - DifficultyLevel = ConvertDifficultyLevel1(difficultyLevel), - QuestionType = questionType, - QuestionContent = questionContent, - QuestionAnalysis = questionAnalysis - }; - var id = await base.Add(insert); - var insertAnswers = new List(); + 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 => { @@ -855,14 +888,14 @@ public class Ghre_QuestionServices : BaseServices o.IsCorrect == true)) + comments.Add("正确答案未标记!"); + + if (questionType == "Multiple" && insertAnswers.Where(o => o.IsCorrect == true).Count() < 2) + comments.Add("答案至少需标记处两个正确答案!"); + #endregion } - else + 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 } + if (comments.Any()) + { + dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a)); + isExistError = true; + continue; + } + else + { + var id = await base.Add(insert); + insertAnswers.ForEach(x => x.QuestionId = id); + await _ghre_QuestionAnswerServices.Add(insertAnswers); + } } - }); - - return ServiceResult.OprateSuccess("新增成功!"); - + else + { + dt.Rows[i]["Comments"] = "试题在系统中已存在!"; + isExistError = true; + continue; + } + + } + + + if (isExistError) + NPOIHelper.ExportExcel(dt, null, x, physicsPath + errorFileName); + }); + + if (isExistError) + return ServiceResult.OprateFailed("导入文件存在错误,请下载后查看!", errorFileName); + else + return ServiceResult.OprateSuccess("导入成功!"); } #endregion } \ No newline at end of file diff --git a/Tiobon.Core/Tiobon.Core.xml b/Tiobon.Core/Tiobon.Core.xml index 2caf0163..8aeb043f 100644 --- a/Tiobon.Core/Tiobon.Core.xml +++ b/Tiobon.Core/Tiobon.Core.xml @@ -141,7 +141,7 @@ 主键IDs - + Excel导出