Files
tiku-backend.net/Tiku.Api/Controllers/ContentV2AuthoringController.cs
xiong 3f5957d744
Some checks failed
ci / release-gate (push) Has been cancelled
feat(content): establish v2 learning delivery foundation
2026-08-06 09:52:18 +08:00

108 lines
4.0 KiB
C#

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Tiku.Api.Contracts;
using Tiku.Api.Security;
using Tiku.Application.Content;
using Tiku.Application.Security;
namespace Tiku.Api.Controllers;
[ApiController]
[Tags("租户端-内容 V2 录题")]
[Authorize(Policy = BackendPermissions.TenantContentManage)]
[Authorize(Policy = TikuPolicies.TenantAllDataScope)]
[RequireSaasFeature(SaasFeatureCatalog.PrivateQuestionBank)]
[Produces("application/json")]
[Route("api/tenant/content-v2")]
public sealed class ContentV2AuthoringController(
IContentV2AuthoringService service,
IContentReleaseCompiler releaseCompiler,
DirectContentActorResolver actorResolver) : ControllerBase
{
[HttpPost("questions/duplicate-search")]
[EndpointSummary("查询当前租户和平台公共范围内的精确/相似题")]
public Task<QuestionDuplicateSearchResult> SearchDuplicates(
QuestionDuplicateSearchDto request,
CancellationToken cancellationToken)
{
return service.SearchDuplicatesAsync(Actor(), request.Draft.ToCommand(), request.Limit, cancellationToken);
}
[HttpPost("questions/execute")]
[EndpointSummary("按复用、新建、变体、跳过或人工复核决策执行录题")]
public Task<QuestionAuthoringResult> Execute(
ExecuteQuestionAuthoringDto request,
CancellationToken cancellationToken)
{
return service.ExecuteAsync(Actor(), request.ToCommand(), cancellationToken);
}
[HttpPost("questions/{questionAssetId:guid}/revisions")]
[EndpointSummary("为租户题目资产创建不可变 Revision")]
public Task<QuestionAuthoringResult> CreateRevision(
Guid questionAssetId,
CreateQuestionRevisionV2Dto request,
CancellationToken cancellationToken)
{
return service.CreateRevisionAsync(
Actor(), questionAssetId, request.Draft.ToCommand(), request.PublishAsset, cancellationToken);
}
[HttpPost("questions/placements")]
[EndpointSummary("把租户私题或平台公共题放置到大纲并配置适用规则")]
public Task<QuestionPlacementItem> CreatePlacement(
CreateQuestionPlacementDto request,
CancellationToken cancellationToken)
{
return service.CreatePlacementAsync(Actor(), request.ToCommand(), cancellationToken);
}
[HttpPost("imports/questions/preview")]
[EndpointSummary("预览 Excel/Word 解析后的题目行并给出精确复用或人工复核建议")]
public Task<QuestionImportPreviewResult> PreviewImport(
PreviewQuestionImportV2Dto request,
CancellationToken cancellationToken)
{
return service.PreviewImportAsync(
Actor(),
request.Rows.Select(row => (row.RowKey, row.Draft.ToCommand())).ToArray(),
cancellationToken);
}
[HttpPost("imports/questions/execute")]
[EndpointSummary("按逐行复用、新建、变体、跳过或人工复核决策执行导入")]
public Task<QuestionImportExecutionResult> ExecuteImport(
ExecuteQuestionImportV2Dto request,
CancellationToken cancellationToken)
{
return service.ExecuteImportAsync(
Actor(),
request.Rows.Select(row => new ExecuteQuestionImportRow(
row.RowKey,
row.Command.ToCommand())).ToArray(),
cancellationToken);
}
[HttpPost("releases/publish")]
[EndpointSummary("校验并发布不可变内容 Release")]
public Task<ContentReleaseCompilationResult> PublishRelease(
PublishContentReleaseDto request,
CancellationToken cancellationToken)
{
var actor = Actor();
return releaseCompiler.PublishAsync(
new PublishContentReleaseCommand(
actor.TenantId,
actor.UserId,
request.CurriculumVersionId,
request.Name),
cancellationToken);
}
private ContentAuthorActor Actor()
{
var actor = actorResolver.Resolve();
return new ContentAuthorActor(actor.TenantId, actor.UserId);
}
}