feat: add EditorGridSizePicker and EditorSelectionFrame components; implement FreeCreateView for article management; introduce ArticleSelectionOptimizeService for optimizing article selections

This commit is contained in:
2026-04-06 22:18:55 +08:00
parent 08ace0a9e0
commit 1e844704e4
20 changed files with 3033 additions and 740 deletions
@@ -314,6 +314,54 @@ func (s *ArticleService) Detail(ctx context.Context, id int64) (*ArticleDetailRe
return &d, nil
}
type CreateArticleRequest struct {
Title string `json:"title"`
}
func (s *ArticleService) Create(ctx context.Context, req CreateArticleRequest) (*ArticleDetailResponse, error) {
actor := auth.MustActor(ctx)
title := strings.TrimSpace(req.Title)
tx, err := s.pool.Begin(ctx)
if err != nil {
return nil, response.ErrInternal(50014, "create_failed", "failed to begin article creation transaction")
}
defer tx.Rollback(ctx)
var articleID int64
if err := tx.QueryRow(ctx, `
INSERT INTO articles (tenant_id, source_type, template_id, generate_status, publish_status)
VALUES ($1, 'free_create', NULL, 'completed', 'unpublished')
RETURNING id
`, actor.TenantID).Scan(&articleID); err != nil {
return nil, response.ErrInternal(50014, "create_failed", "failed to create article")
}
sourceLabel := "自由创作"
var versionID int64
if err := tx.QueryRow(ctx, `
INSERT INTO article_versions (article_id, version_no, title, html_content, markdown_content, word_count, source_label)
VALUES ($1, 1, $2, NULL, '', 0, $3)
RETURNING id
`, articleID, title, sourceLabel).Scan(&versionID); err != nil {
return nil, response.ErrInternal(50014, "create_failed", "failed to create article version")
}
if _, err := tx.Exec(ctx, `
UPDATE articles SET current_version_id = $1, updated_at = NOW()
WHERE id = $2 AND tenant_id = $3
`, versionID, articleID, actor.TenantID); err != nil {
return nil, response.ErrInternal(50014, "create_failed", "failed to link article version")
}
if err := tx.Commit(ctx); err != nil {
return nil, response.ErrInternal(50014, "create_failed", "failed to commit article creation")
}
return s.Detail(ctx, articleID)
}
type UpdateArticleRequest struct {
Title string `json:"title"`
MarkdownContent string `json:"markdown_content"`