Files
QYZH.InteractiveMagazine/QYZH.InteractiveMagazine.WebApi/Controllers/JournalController.cs
glz 2d3fceb265 feat(journal task): add crud operations for task answers
重构了任务答案的处理逻辑,将原有的先删后插从任务更新中拆分出来,新增独立的答案增删改查接口:
1. 移除了JournalPageTaskUpdateInput中的TaskAnswer属性
2. 新增JournalTaskAnswerAddInput/UpdateInput DTO
3. 在服务层实现答案的增删改业务逻辑,包含OSS文件处理
4. 在控制器中添加对应的API接口
2026-06-22 17:49:37 +08:00

545 lines
20 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using QYZH.InteractiveMagazine.Models.Base;
using QYZH.InteractiveMagazine.Models.Dto.Journal;
using QYZH.InteractiveMagazine.Models.Dto.DotMatrix;
using QYZH.InteractiveMagazine.Models.Enum;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MiniExcelLibs;
using QYZH.InteractiveMagazine.Infrastructure.OSS;
using QYZH.InteractiveMagazine.IService;
using QYZH.InteractiveMagazine.Models.Common;
using QYZH.InteractiveMagazine.Models.Dto;
using QYZH.InteractiveMagazine.Models.Enum;
using QYZH.InteractiveMagazine.WebApi.Controllers;
using System.ComponentModel.DataAnnotations;
using System.Web;
namespace QYZH.InteractiveMagazine.WebApi.Controllers
{
/// <summary>
/// 期刊管理
/// </summary>
[ApiExplorerSettings(GroupName = nameof(ApiVersionEnum.Platform))]
[Route("api")]
public class JournalController(
OssService ossService,
IJournalCatalogService JournalCatalogService,
IJournalService JournalService,
IJournalPageService JournalPageService,
IJournalPageTaskService JournalPageTaskService,
IHttpClientFactory httpClientFactory,
Microsoft.Extensions.Configuration.IConfiguration configuration) : BaseController
{
#region
/// <summary>
/// 根据ID查询书籍数据
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet, Route("journal/detail/{id:long}")]
public async Task<BaseResponse<JournalDto>> GetByIdAsync([Required] long id)
{
var result = await JournalService.GetByExpressionAsync<JournalDto>(c => c.Id == id);
return BaseResponse<JournalDto>.Success(result);
}
/// <summary>
/// 分页查询书籍列表
/// </summary>
/// <param name="search">查询条件</param>
/// <returns></returns>
[HttpPost, Route("journal/pagelist")]
public async Task<BaseResponse<PageListModel<JournalDto>>> GetPageListAsync([FromBody] PageQueryModel<JournalQueryDto> search)
{
var result = await JournalService.GetPageListAsync(search);
return BaseResponse<PageListModel<JournalDto>>.Success(result);
}
/// <summary>
/// 查询书籍列表
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
[HttpPost, Route("journal/list")]
public async Task<BaseResponse<List<JournalDto>>> GetListAsync([FromQuery] JournalQueryDto dto)
{
var result = await JournalService.GetListAsync(dto);
return BaseResponse<List<JournalDto>>.Success(result);
}
/// <summary>
/// 创建杂志
/// </summary>
/// <param name="dto">创建杂志</param>
/// <returns></returns>
[HttpPost, Route("journal/add")]
public async Task<BaseResponse<long>> AddAsync([FromBody] JournalAddDto dto)
{
var result = await JournalService.AddAsync(dto);
return result;
}
/// <summary>
/// 编辑书籍
/// </summary>
/// <param name="dto">书籍对象</param>
/// <returns></returns>
[HttpPost, Route("journal/update")]
public async Task<BaseResponse> Edit([FromBody] JournalEditDto dto)
{
var result = await JournalService.EditAsync(dto);
return result;
}
/// <summary>
/// 批量删除
/// </summary>
/// <param name="ids"></param>
/// <returns></returns>
[HttpPost, Route("journal/delete")]
public async Task<BaseResponse<bool>> DeleteAsync([Required][FromBody] List<long> ids)
{
var result = await JournalService.DeleteAsync(ids);
return BaseResponse<bool>.Success(result);
}
/// <summary>
/// 书籍起始页
/// </summary>
/// <returns></returns>
[HttpPost, Route("journal/startpage")]
public async Task<BaseResponse<bool>> StartPageAsync([FromQuery]long id, [FromQuery] int index)
{
var data = await JournalService.StartPageAsync(id, index);
return BaseResponse<bool>.Success(data);
}
/// <summary>
/// 书籍归档
/// </summary>
/// <returns></returns>
[HttpPost, Route("journal/rchive/{id:long}")]
public async Task<BaseResponse<bool>> Archive(long id)
{
var data = await JournalService.StatusAsync(id, JournalStatusEnum.Archive);
return BaseResponse<bool>.Success(data);
}
/// <summary>
/// 书籍废弃
/// </summary>
/// <returns></returns>
[HttpPost]
[HttpPost, Route("journal/abandon/{id:long}")]
public async Task<BaseResponse<bool>> Abandon(long id)
{
var data = await JournalService.StatusAsync(id, JournalStatusEnum.Abandoned);
return BaseResponse<bool>.Success(data);
}
/// <summary>
/// 书籍铺码
/// </summary>
/// <returns></returns>
[HttpPost, Route("journal/printcode/{id:long}")]
public async Task<BaseResponse<DotMatrixOutput>> PrintCodeAsync(long id)
{
var data = await JournalService.PrintCodeAsync(id);
return BaseResponse<DotMatrixOutput>.Success(data);
}
/// <summary>
/// 上报铺码结果
/// </summary>
/// <param name="input"></param>
/// <param name="file"></param>
/// <returns></returns>
[HttpPost, Route("journal/resultreport")]
public async Task<BaseResponse<bool>> GenerateAsync([FromBody] DotMatrixNoteJournalReportInput input, [FromForm] IFormFile? file)
{
if (file != null)
{
input.FileKey = $"journal/{input.Id}/dotMatrixJournal.pdf";
input.FileUrl = ossService.PutObject(input.FileKey, file.OpenReadStream());
}
var data = await JournalService.ResultReportAsync(input);
return BaseResponse<bool>.Success(data);
}
/// <summary>
/// 书籍导入
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost, Route("journal/import")]
public async Task<BaseResponse<long>> JournalImport(JournalImportDto input)
{
var data = await JournalCatalogService.ImportAsync(input);
return BaseResponse<long>.Success(data);
}
/// <summary>
/// 题库代理请求接口
/// </summary>
/// <returns></returns>
[HttpGet, Route("tasklibrary/proxyget")]
public async Task<IActionResult> GetTaskLibraryData(string apiUrl = "")
{
var client = httpClientFactory.CreateClient();
var response = await client.GetAsync(configuration["TaskLibraryApi"] + apiUrl);
// 确保请求成功(状态码 200
response.EnsureSuccessStatusCode();
string result = await response.Content.ReadAsStringAsync();
return Content(result, "application/json");
}
#endregion
#region
///// <summary>
///// 书籍目录详情
///// </summary>
///// <returns></returns>
//[HttpGet, Route("catalog/tree/{JournalId:long}")]
//public async Task<BaseResponse<List<IcrJournalCatalog>>> CatalogDetailAsync(long JournalId)
//{
// var data = await _JournalCatalogService.DetailAsync(JournalId);
// return BaseResponse<List<IcrJournalCatalog>>.Success(data);
//}
/// <summary>
/// 书籍目录详情
/// </summary>
/// <returns></returns>
[HttpGet, Route("catalog/tree/{JournalId:long}")]
public async Task<BaseResponse<List<IcrJournalCatalogTreeDto>>> CatalogDetailAsync(long JournalId)
{
var data = await JournalCatalogService.GetJournalCataloTreeAsync(JournalId);
return BaseResponse<List<IcrJournalCatalogTreeDto>>.Success(data);
}
/// <summary>
/// 获取书分类及页码
/// </summary>
/// <param name="JournalId"></param>
/// <returns></returns>
[HttpGet, Route("catalog/list")]
public async Task<BaseResponse<List<JournalCatalogTreeListDto>>> GetJournalCatelogListAsync(long JournalId)
{
var data = await JournalCatalogService.GetJournalCatalogListAsync(JournalId);
return BaseResponse<List<JournalCatalogTreeListDto>>.Success(data);
}
/// <summary>
/// 下载书籍目录导入模板
/// </summary>
/// <returns></returns>
[HttpGet, Route("catalog/template")]
[AllowAnonymous]
public IActionResult ImportCatalogTemplateExcel()
{
var result = DownloadImportTemplate(new List<JournalCatalogTreeListDto>() { }, "书籍目录导入模板");
return ExportExcel(result.Item2, result.Item1);
}
/// <summary>
/// 书籍目录导出
/// </summary>
/// <param name="JournalId"></param>
/// <returns></returns>
[HttpGet, Route("catalog/export/{JournalId}")]
public async Task<IActionResult> CatalogExport(long JournalId)
{
var list = await JournalCatalogService.GetJournalCatalogListAsync(JournalId);
var result = ExportExcelMini(list, "sheet1", "书籍目录导出");
return ExportExcel(result.Item2, result.Item1);
}
/// <summary>
/// 书籍目录导入
/// </summary>
/// <param name="JournalId">file</param>
/// <param name="file">file</param>
/// <returns></returns>
[HttpPost, Route("catalog/import/{JournalId}")]
public async Task<BaseResponse<bool>> ImportAsync(long JournalId, [FromForm(Name = "file")] IFormFile file)
{
List<JournalCatalogTreeListDto> dto = new();
using (var stream = file.OpenReadStream())
{
dto = stream.Query<JournalCatalogTreeListDto>().ToList();
}
var result = await JournalCatalogService.ImportCatalogAsync(JournalId, dto);
return BaseResponse<bool>.Success(result);
}
/// <summary>
/// 书籍目录新增
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost, Route("catalog/add")]
public async Task<BaseResponse<long>> CatalogAdd(JournalCatalogInput input)
{
var data = await JournalCatalogService.InsertAsync(input);
return BaseResponse<long>.Success(data);
}
/// <summary>
/// 书籍目录修改
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost, Route("catalog/update")]
public async Task<BaseResponse<bool>> CatalogUpdate(JournalCatalogUpdateInput input)
{
var data = await JournalCatalogService.UpdateAsync(input);
return BaseResponse<bool>.Success(data);
}
/// <summary>
/// 书籍目录删除
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpPost, Route("catalog/delete/{id:long}")]
public async Task<BaseResponse<bool>> CatalogDelete(long id)
{
var data = await JournalCatalogService.DeleteAsync(id);
return BaseResponse<bool>.Success(data);
}
///// <summary>
///// 书籍目录复制
///// </summary>
///// <param name="input"></param>
///// <returns></returns>
//[HttpPost, Route("catalog/copy")]
//[ProducesResponseType(typeof(BaseResponse<bool>), 200)]
//public async Task<BaseResponse> CatalogCopy(CopyInput input)
//{
// var data = await _JournalCatalogServices.CopyAsync(input);
// return ApiResult(data, "书籍目录删除失败!");
//}
/// <summary>
/// 书籍目录移动
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost, Route("catalog/move")]
public async Task<BaseResponse<bool>> CatalogMove(MoveInput input)
{
var data = await JournalCatalogService.MoveAsync(input);
return BaseResponse<bool>.Success(data);
}
#endregion
#region
/// <summary>
/// 书页新增
/// </summary>
/// <returns></returns>
[HttpPost, Route("page/add")]
public async Task<BaseResponse<long>> PageAdd(JournalAddV2Input input)
{
var data = await JournalPageService.InsertAsync(input);
return BaseResponse<long>.Success(data);
}
/// <summary>
/// 书页修改
/// </summary>
/// <returns></returns>
[HttpPost, Route("page/update")]
public async Task<BaseResponse<bool>> PageUpdate(PageLayoutInput input)
{
var data = await JournalPageService.UpdateAsync(input);
return BaseResponse<bool>.Success(data);
}
/// <summary>
/// 自动铺码
/// </summary>
/// <returns></returns>
[HttpPost, Route("page/updatepageno/{JournalId:long}")]
public async Task<BaseResponse<bool>> PageUpdatePageNo([Required(ErrorMessage = "书籍编号不允许为空")] long JournalId)
{
var data = await JournalPageService.UpdatePageNoAsync(JournalId);
return BaseResponse<bool>.Success(data);
}
/// <summary>
/// 下载书籍页码点阵码PDF文件名称
/// </summary>
/// <returns></returns>
[HttpGet, Route("page/downloadJournalpagePdf/{JournalId:long}")]
public async Task<IActionResult> DownloadJournalPagePdf([Required(ErrorMessage = "书籍编号不允许为空")] long JournalId)
{
var entity = await JournalService.GetFirstAsync(x => x.Id == JournalId);
if (entity == null)
throw new BusinessException("书籍不存在");
var downloadUrl = entity.DownloadJournalPagePdfName;
if (string.IsNullOrWhiteSpace(downloadUrl))
throw new BusinessException("下载点阵码PDF文件为空,请先铺码");
var stream = await httpClientFactory.CreateClient().GetStreamAsync(downloadUrl); //创建文件流
if (stream == null)
throw new BusinessException("下载点阵码PDF文件失败");
Response.Headers.Append("Access-Control-Expose-Headers", "Content-Disposition");
return File(stream, "application/pdf", HttpUtility.UrlEncode(Path.GetFileName(downloadUrl)));
}
///// <summary>
///// 打印书页(全部) 暂时废弃这个方,直接使用 Adobe Reader X 软件打印就可以了
///// </summary>
///// <returns></returns>
//[HttpPost, Route("page/printJournalPage/{JournalId:long}")]
//public async Task<BaseResponse<bool>> PrintJournalPage([Required(ErrorMessage = "书籍编号不允许为空")] long JournalId)
//{
// var data = await JournalPageService.PrintJournalPageAsync(JournalId);
// return BaseResponse<bool>.Success(data);
//}
///// <summary>
///// 书页删除
///// </summary>
///// <returns></returns>
//[HttpPost, Route("page/delete/{id:long}")]
//[ProducesResponseType(typeof(BaseResponse<bool>), 200)]
//public async Task<IActionResult> PageDelete(long id)
//{
// var data = await _JournalPageServices.DeleteAsync(id);
// return ApiResult(data, "更新书页失败!");
//}
/// <summary>
/// 书页详情
/// </summary>
/// <returns></returns>
[HttpGet, Route("page/detail/{id:long}")]
public async Task<BaseResponse<JournalPageV2Output>> PageDetail(long id)
{
var data = await JournalPageService.DetailAsync(id);
return BaseResponse<JournalPageV2Output>.Success(data);
}
///// <summary>
///// 不包含有文章的书页
///// </summary>
///// <returns></returns>
//[HttpGet, Route("page/no-article/{JournalId:long}")]
//[ProducesResponseType(typeof(BaseResponse<List<JournalPageNoArticleOutput>>), 200)]
//public async Task<IActionResult> PageNoArticleAsync(long JournalId)
//{
// var data = await _JournalPageService.PageNoArticleAsync(JournalId);
// return BaseResponse<List<JournalPageNoArticleOutput>>(data, "查询书页失败!");
//}
#endregion
#region
/// <summary>
/// 书页问题新增
/// </summary>
/// <returns></returns>
[HttpPost, Route("page/task/add")]
[ProducesResponseType(typeof(BaseResponse<long>), 200)]
public async Task<BaseResponse<long>> PageTaskAdd(JournalPageTaskAddInput input)
{
var data = await JournalPageTaskService.InsertAsync(input);
return BaseResponse<long>.Success(data.Value);
}
/// <summary>
/// 书页问题更新
/// </summary>
/// <returns></returns>
[HttpPost, Route("page/task/update")]
[ProducesResponseType(typeof(BaseResponse<bool>), 200)]
public async Task<BaseResponse<bool>> PageTaskUpdate(JournalPageTaskUpdateInput input)
{
var data = await JournalPageTaskService.UpdateAsync(input);
return BaseResponse<bool>.Success(data);
}
/// <summary>
/// 书页问题详情 + 题库那边需要用
/// </summary>
/// <returns></returns>
[AllowAnonymous]
[HttpGet, Route("page/task/detail/{id:long}")]
public async Task<BaseResponse<JournalPageTaskOutput>> PageTaskDetail(long id)
{
var data = await JournalPageTaskService.DetailAsync(id);
return BaseResponse<JournalPageTaskOutput>.Success(data);
}
/// <summary>
/// 书页问题删除
/// </summary>
/// <returns></returns>
[HttpPost, Route("page/task/delete/{id:long}")]
public async Task<BaseResponse<bool>> PageTaskDelete(long id)
{
var data = await JournalPageTaskService.DeleteAsync(id);
return BaseResponse<bool>.Success(data);
}
/// <summary>
/// 书页问题补充
/// </summary>
/// <returns></returns>
[HttpPost, Route("page/task/complement")]
public async Task<BaseResponse<bool>> ComplementAnsync(JournalPageTaskComplementInput input)
{
var data = await JournalPageTaskService.ComplementAsync(input);
return BaseResponse<bool>.Success(data);
}
/// <summary>
/// 答案新增
/// </summary>
/// <returns></returns>
[HttpPost, Route("page/task/answer/add")]
public async Task<BaseResponse<long>> AnswerAdd(JournalTaskAnswerAddInput input)
{
var data = await JournalPageTaskService.AddAnswerAsync(input);
return BaseResponse<long>.Success(data);
}
/// <summary>
/// 答案更新
/// </summary>
/// <returns></returns>
[HttpPost, Route("page/task/answer/update")]
public async Task<BaseResponse<bool>> AnswerUpdate(JournalTaskAnswerUpdateInput input)
{
var data = await JournalPageTaskService.UpdateAnswerAsync(input);
return BaseResponse<bool>.Success(data);
}
/// <summary>
/// 答案删除
/// </summary>
/// <returns></returns>
[HttpPost, Route("page/task/answer/delete/{id:long}")]
public async Task<BaseResponse<bool>> AnswerDelete(long id)
{
var data = await JournalPageTaskService.DeleteAnswerAsync(id);
return BaseResponse<bool>.Success(data);
}
#endregion
}
}