feat(imitation): add article imitation create flow

Introduce 仿写创作: new list and create views, backend imitation service
and prompt templates, worker task routing for imitation jobs, and one-click
rewrite triggers from question citation sources. Surface source article
URL/title on article list/detail, and restrict failed articles to delete-only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-25 21:36:44 +08:00
parent 46d0a7aea0
commit 40d9a6cc63
29 changed files with 2678 additions and 120 deletions
@@ -22,6 +22,7 @@ type ArticleHandler struct {
svc *app.ArticleService
selectionOptimize *app.ArticleSelectionOptimizeService
promptGenerateSvc *app.PromptRuleGenerationService
imitationSvc *app.ArticleImitationService
streams *stream.GenerationHub
streamEnabled bool
assets *AssetHandler
@@ -57,6 +58,15 @@ func NewArticleHandler(a *bootstrap.App) *ArticleHandler {
a.Config.Generation,
a.Config.LLM.MaxOutputTokens,
).WithCache(a.Cache),
imitationSvc: app.NewArticleImitationService(
a.DB,
a.LLM,
a.RabbitMQ,
knowledgeSvc,
a.GenerationStreams,
a.Config.Generation,
a.Config.LLM.MaxOutputTokens,
).WithCache(a.Cache),
streams: a.GenerationStreams,
streamEnabled: a.Config.Generation.StreamEnabled,
assets: NewAssetHandler(a),
@@ -162,6 +172,22 @@ func (h *ArticleHandler) GenerateFromRule(c *gin.Context) {
response.SuccessWithStatus(c, http.StatusCreated, data)
}
func (h *ArticleHandler) GenerateImitation(c *gin.Context) {
var req app.GenerateImitationRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, response.ErrBadRequest(40001, "invalid_params", err.Error()))
return
}
data, err := h.imitationSvc.Generate(c.Request.Context(), req)
if err != nil {
response.Error(c, err)
return
}
response.SuccessWithStatus(c, http.StatusCreated, data)
}
func (h *ArticleHandler) Create(c *gin.Context) {
var req app.CreateArticleRequest
if err := c.ShouldBindJSON(&req); err != nil {