| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- import { Injectable } from '@angular/core';
- import { AssistantSuggestion } from './assistant.service';
- import { CreationBriefService } from './creation-brief.service';
- import { TopicPoolService } from './topic-pool.service';
- import { ViralAnalysisService } from './viral-analysis.service';
- import { CreationBrief } from '../models/creation-brief.model';
- import { TopicIdea, ViralAnalysis } from '../models/douyin-insight.model';
- import { ViralTopicBridgeService } from './viral-topic-bridge.service';
- export type ContentEntryTarget = 'topic-to-video' | 'digital-human';
- export interface ContentEntryNavigation {
- tab: ContentEntryTarget;
- brief: CreationBrief;
- message: string;
- }
- export interface SavedTopicResult {
- count: number;
- title: string;
- ids: string[];
- }
- @Injectable({ providedIn: 'root' })
- export class ContentProductionEntryService {
- constructor(
- private topicPool: TopicPoolService,
- private creationBriefs: CreationBriefService,
- private viralTopicBridge: ViralTopicBridgeService,
- private viralAnalysis: ViralAnalysisService,
- ) {}
- saveAssistantSuggestion(suggestion: AssistantSuggestion): TopicIdea {
- const payload = suggestion.payload || {};
- const title = String(payload['title'] || payload['topic'] || suggestion.label || '').trim();
- const angle = String(payload['angle'] || payload['description'] || payload['topic'] || title).trim();
- const tags = this.normalizeTags(payload['tags']);
- return this.topicPool.saveTopic({
- title: title || 'AI 助手选题',
- angle: angle || title || '来自 AI 助手的选题建议',
- sourceType: 'assistant',
- sourceVideoIds: [],
- sourceAuthorIds: [],
- tags: Array.from(new Set(['AI助手', ...tags])).slice(0, 12),
- audience: String(payload['audience'] || ''),
- hook: String(payload['hook'] || title || ''),
- outline: String(payload['outline'] || payload['scriptFrame'] || ''),
- status: 'idea',
- pipelineTarget: 'topic_video',
- confidence: 'medium',
- });
- }
- enterTopic(target: ContentEntryTarget, topic: TopicIdea): ContentEntryNavigation {
- const brief = this.creationBriefs.savePendingTopic(target, topic);
- return {
- tab: target,
- brief,
- message: `已带入选题:${topic.title}`,
- };
- }
- saveManualPrefill(target: ContentEntryTarget, payload: Record<string, unknown>): CreationBrief {
- return this.creationBriefs.savePendingManualPrefill(target, payload);
- }
- saveDailyReportTopics(topics: TopicIdea[]): SavedTopicResult {
- const saved = topics.map((topic) => this.topicPool.saveTopic({
- title: topic.title,
- angle: topic.angle,
- sourceType: 'daily_report',
- sourceVideoIds: topic.sourceVideoIds,
- sourceAuthorIds: topic.sourceAuthorIds,
- tags: topic.tags,
- audience: topic.audience,
- hook: topic.hook,
- outline: topic.outline,
- status: 'idea',
- pipelineTarget: topic.pipelineTarget,
- confidence: topic.confidence,
- }));
- return this.savedResult(saved);
- }
- enterDailyReportTopic(topic: TopicIdea): ContentEntryNavigation {
- return this.enterTopic('topic-to-video', topic);
- }
- saveViralAnalysisTopics(analysis: ViralAnalysis): { result: SavedTopicResult; analysis: ViralAnalysis } {
- const drafts = this.viralTopicBridge.buildTopicDrafts(analysis);
- const existing = this.topicPool.listTopics()
- .filter((topic) => topic.sourceType === 'viral_analysis' && topic.sourceVideoIds?.[0] === analysis.awemeId);
- const saved = drafts.map((draft) => {
- const matched = existing.find((topic) => topic.variantIndex === draft.variantIndex);
- return matched
- ? this.topicPool.updateTopic(matched.id, draft)
- : this.topicPool.saveTopic(draft);
- });
- const savedIds = new Set(saved.map((topic) => topic.id));
- existing
- .filter((topic) => !savedIds.has(topic.id) && topic.status !== 'archived')
- .forEach((topic) => this.topicPool.archiveTopic(topic.id));
- return {
- result: this.savedResult(saved),
- analysis: this.viralAnalysis.markTopicsSaved(analysis.id, saved.map((item) => item.id)),
- };
- }
- enterViralAnalysisTopicVideo(analysis: ViralAnalysis): ContentEntryNavigation {
- const brief = this.viralTopicBridge.buildTopicVideoBrief(analysis);
- this.creationBriefs.savePendingBrief('topic-to-video', brief);
- return {
- tab: 'topic-to-video',
- brief,
- message: `已整理选题:${brief.angle || brief.title}`,
- };
- }
- private normalizeTags(value: unknown): string[] {
- if (Array.isArray(value)) {
- return value.map((tag) => String(tag || '').trim()).filter(Boolean);
- }
- return String(value || '').split(/[,,\s]+/).map((tag) => tag.trim()).filter(Boolean);
- }
- private savedResult(topics: TopicIdea[]): SavedTopicResult {
- return {
- count: topics.length,
- title: topics[0]?.title || '',
- ids: topics.map((topic) => topic.id),
- };
- }
- }
|