题库定制化导入Excwl开发

master
xiaochanghai 1 year ago
parent d5631012a5
commit 92a4c85135
  1. 17
      Tiobon.Core.Api/Controllers/Base/BaseController.cs
  2. 8
      Tiobon.Core.Api/Controllers/Ghre/Ghre_QuestionController.cs
  3. 2
      Tiobon.Core.Api/Tiobon.Core.xml
  4. 34
      Tiobon.Core.Common/Helper/NPOIHelper.cs
  5. 5
      Tiobon.Core.IServices/BASE/IBaseServices.cs
  6. 4
      Tiobon.Core.IServices/Ghre/IGhre_QuestionServices.cs
  7. 2
      Tiobon.Core.Model/Base/Ghre/Ghre_CourseWareAttachment.Dto.Base.cs
  8. 15
      Tiobon.Core.Services/BASE/BaseServices.cs
  9. 4
      Tiobon.Core.Services/Ghre/Ghre_CourseServices.cs
  10. 131
      Tiobon.Core.Services/Ghre/Ghre_QuestionServices.cs
  11. 2
      Tiobon.Core/Tiobon.Core.xml

@ -210,10 +210,21 @@ public class BaseController<IServiceBase, TEntity, TEntityDto, TInsertDto, TEdit
/// </summary>
/// <param name="body"></param>
/// <returns></returns>
[HttpPost, Route("Export")]
public async Task<ServiceResult<long>> Export([FromBody] QueryBody body)
[HttpPost, Route("ExportExcel")]
public async Task<ServiceResult<long>> ExportExcel([FromBody] QueryBody body)
{
var data = (await InvokeServiceAsync("Export", [body])) as ServiceResult<long>;
var data = (await InvokeServiceAsync("ExportExcel", [body])) as ServiceResult<long>;
return data;
}
#endregion
#region Excel导入
[HttpPost("ImportExcel")]
public async Task<ServiceResult<string>> ImportExcel(IFormFile file)
{
var data = (await InvokeServiceAsync("ImportExcel", [file])) as ServiceResult<string>;
return data;
}
#endregion

@ -60,12 +60,4 @@ public class Ghre_QuestionController : BaseController<IGhre_QuestionServices, Gh
#endregion\
#region Excel导入
[HttpPost("ImportExcel")]
public async Task<ServiceResult> ImportExcelAsync(IFormFile file)
{
return await _service.ImportExcelAsync(file);
}
#endregion
}

@ -141,7 +141,7 @@
<param name="Ids">主键IDs</param>
<returns></returns>
</member>
<member name="M:Tiobon.Core.Controllers.BaseController`5.Export(Tiobon.Core.Common.QueryBody)">
<member name="M:Tiobon.Core.Controllers.BaseController`5.ExportExcel(Tiobon.Core.Common.QueryBody)">
<summary>
Excel导出
</summary>

@ -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
/// <param name="dtSource">源 DataTable</param>
/// <param name="strHeaderText">表头文本 空值未不要表头标题</param>
/// <returns></returns>
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
/// <param name="dtSource">源 DataaTable</param>
/// <param name="strHeaderText">表头文本</param>
/// <param name="strFileName">保存位置(文件名及路径)</param>
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,6 +279,7 @@ public class NPOIHelper
for (int j = 0; j < cellCount; j++)
{
ICell cell = headerRow.GetCell(j);
if (!string.IsNullOrWhiteSpace(cell.ToString()))
dt.Columns.Add(cell.ToString());
}
for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++)

@ -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<PageModel<TEntity>> QueryPage(Expression<Func<TEntity, bool>> whereExpression, int pageIndex = 1, int pageSize = 20, string orderByFields = null);
Task<ServicePageResult<TEntityDto>> QueryFilterPage([FromBody] QueryBody body);
Task<ServicePageResult<TEntityDto>> QueryFilterPage(QueryBody filter, string condition);
Task<ServiceResult<long>> Export([FromBody] QueryBody body);
Task<ServiceResult<long>> ExportExcel([FromBody] QueryBody body);
Task<ServiceResult<string>> ImportExcel(IFormFile file);
Task<List<TResult>> QueryMuch<T, T2, T3, TResult>(
Expression<Func<T, T2, T3, object[]>> joinExpression,

@ -8,13 +8,11 @@ namespace Tiobon.Core.IServices
/// <summary>
/// 题目(自定义服务接口)
/// </summary>
public interface IGhre_QuestionServices :IBaseServices<Ghre_Question, Ghre_QuestionDto, InsertGhre_QuestionInput, EditGhre_QuestionInput>
public interface IGhre_QuestionServices : IBaseServices<Ghre_Question, Ghre_QuestionDto, InsertGhre_QuestionInput, EditGhre_QuestionInput>
{
Task<ServiceResult<FromGhre_QuestionInput>> QueryFrom(long Id);
Task<ServiceResult> InsertFrom(FromGhre_QuestionPageData insertModel);
Task<ServiceResult> UpdareFrom(long Id, FromGhre_QuestionPageData insertModel);
Task<ServiceResult> ImportExcelAsync(IFormFile file);
}
}

@ -40,7 +40,7 @@ namespace Tiobon.Core.Model.Models
/// <summary>
/// 扩展名
/// </summary>
[Display(Name = "AttachFileExtension"), Description("扩展名"), MaxLength(32, ErrorMessage = "扩展名 不能超过 32 个字符")]
[Display(Name = "AttachFileExtension"), Description("扩展名"), MaxLength(256, ErrorMessage = "扩展名 不能超过 256 个字符")]
public string AttachFileExtension { get; set; }
/// <summary>

@ -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<TEntity, TEntityDto, TInsertDto, TEditDto> : IBaseServ
return new ServicePageResult<TEntityDto>(filter.pageNum, total, filter.pageSize, entitys);
}
public async Task<ServiceResult<long>> Export(QueryBody body)
public async Task<ServiceResult<long>> ExportExcel(QueryBody body)
{
//sql = @$"SELECT field,
// [dbo].[FLangKeyToValue] (mkey, {body.langId}, label)
@ -816,6 +817,18 @@ public class BaseServices<TEntity, TEntityDto, TInsertDto, TEditDto> : IBaseServ
}
public async virtual Task<ServiceResult<string>> 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<string>.OprateSuccess("导入成功!");
}
public async Task<List<TResult>> QueryMuch<T, T2, T3, TResult>(Expression<Func<T, T2, T3, object[]>> joinExpression, Expression<Func<T, T2, T3, TResult>> selectExpression, Expression<Func<T, T2, T3, bool>> whereLambda = null) where T : class, new()
{
return await BaseDal.QueryMuch(joinExpression, selectExpression, whereLambda);

@ -139,7 +139,7 @@ public class Ghre_CourseServices : BaseServices<Ghre_Course, Ghre_CourseDto, Ins
CASE A.InOrOut
WHEN 'In' THEN F.StaffName
WHEN 'Out' THEN J.TeacherName
END TeacherName
END TeacherName, ISNULL(A.UpdateTime, A.CreateTime) CreateTime1
FROM Ghre_Course A
LEFT JOIN Ghre_CourseClass B ON A.CourseClassId = B.Id
LEFT JOIN Ghre_CourseClass C ON A.CourseClassId2 = C.Id
@ -153,7 +153,7 @@ public class Ghre_CourseServices : BaseServices<Ghre_Course, Ghre_CourseDto, Ins
WHERE A.IsEnable = 1) A";
if (string.IsNullOrWhiteSpace(filter.orderBy))
filter.orderBy = "CreateTime DESC";
filter.orderBy = "CreateTime1 DESC";
string conditions = " WHERE 1=1";

@ -4,7 +4,6 @@ using AgileObjects.AgileMapper;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SharpCompress.Common;
using SqlSugar;
using Tiobon.Core.Common;
using Tiobon.Core.Common.Caches;
@ -785,24 +784,25 @@ public class Ghre_QuestionServices : BaseServices<Ghre_Question, Ghre_QuestionDt
}
#region Excel导入
public async Task<ServiceResult> ImportExcelAsync(IFormFile file)
public override async Task<ServiceResult<string>> 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<string>
{
"单选题",
//"多选题",
//"判断题",
"多选题",
"判断题",
//"填空题",
//"简答题",
};
@ -818,35 +818,68 @@ public class Ghre_QuestionServices : BaseServices<Ghre_Question, Ghre_QuestionDt
"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);
//});
types.ForEach(async x =>
{
string questionType = ConvertQuestionType1(x);
DataTable dt = NPOIHelper.ImportExcel(filepath, "单选题");
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 course = await _ghre_CourseServices.Query(x => x.CourseName == dt.Rows[i]["课程(必填)"].ToString());
var questionContent = dt.Rows[i]["题干(必填)"].ToString();
var comments = new List<string>();
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();
var difficultyLevel = dt.Rows[i]["难度"].ToString() ?? "普通";
if (string.IsNullOrEmpty(questionContent))
comments.Add("题目内容为必填项!");
var question = await base.Query(x => x.QuestionContent == questionContent);
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))
comments.Add("正确答案未标记!");
if (string.IsNullOrWhiteSpace(difficultyLevel))
comments.Add("难易程度必填!");
if (string.IsNullOrWhiteSpace(questionAnalysis))
comments.Add("题目解析必填!");
var course = await _ghre_CourseServices.QuerySingleDto(x => x.CourseName == courseName);
if (course is null)
comments.Add("课程不存在,请修正!");
var insert = new InsertGhre_QuestionInput()
{
CourseId = course.FirstOrDefault().Id,
CourseId = course.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<InsertGhre_QuestionAnswerInput>();
if (questionType == "Single" || questionType == "Multiple")
{
#region 单选题/多选题
int j = 100;
answers.ForEach(a =>
{
@ -855,14 +888,14 @@ public class Ghre_QuestionServices : BaseServices<Ghre_Question, Ghre_QuestionDt
{
var isCorrect = false;
if (x == "单选题" && correctAnswer == a)
if (correctAnswer.Contains(a))
isCorrect = true;
insertAnswers.Add(new InsertGhre_QuestionAnswerInput()
{
TaxisNo = j,
QuestionNo = a,
QuestionId = id,
//QuestionId = id,
AnswerContent = answer,
IsCorrect = isCorrect
});
@ -871,19 +904,73 @@ public class Ghre_QuestionServices : BaseServices<Ghre_Question, Ghre_QuestionDt
j = j + 100;
});
await _ghre_QuestionAnswerServices.Add(insertAnswers);
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
}
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);
}
}
else
{
dt.Rows[i]["Comments"] = "试题在系统中已存在!";
isExistError = true;
continue;
}
}
});
return ServiceResult.OprateSuccess("新增成功!");
if (isExistError)
NPOIHelper.ExportExcel(dt, null, x, physicsPath + errorFileName);
});
if (isExistError)
return ServiceResult<string>.OprateFailed("导入文件存在错误,请下载后查看!", errorFileName);
else
return ServiceResult<string>.OprateSuccess("导入成功!");
}
#endregion
}

@ -141,7 +141,7 @@
<param name="Ids">主键IDs</param>
<returns></returns>
</member>
<member name="M:Tiobon.Core.Controllers.BaseController`5.Export(Tiobon.Core.Common.QueryBody)">
<member name="M:Tiobon.Core.Controllers.BaseController`5.ExportExcel(Tiobon.Core.Common.QueryBody)">
<summary>
Excel导出
</summary>

Loading…
Cancel
Save