Refactor brand service and related components

- Removed ListQuestionVersions method and associated types from BrandService and Queries.
- Updated PromptRuleGenerationService to change task naming and handling.
- Enhanced ScheduleTaskService to support filtering by created date range and keyword.
- Introduced InstantTaskService for managing instant tasks with appropriate filtering and response structures.
- Added InstantTaskHandler for handling API requests related to instant tasks.
- Created InstantTaskTab component for the admin web interface to display and manage instant tasks.
- Updated database migrations to rename source types for articles and generation tasks.
- Adjusted models and repository queries to reflect the removal of question version handling.
This commit is contained in:
2026-04-02 21:16:12 +08:00
parent 111498a65f
commit 8958cb44c0
36 changed files with 1378 additions and 358 deletions
+8 -4
View File
@@ -11,6 +11,8 @@ import type {
CompetitorRequest,
GenerateFromRuleRequest,
GenerateFromRuleResponse,
InstantTaskListParams,
InstantTaskListResponse,
JsonValue,
Keyword,
KeywordRequest,
@@ -27,7 +29,6 @@ import type {
QuotaSummary,
Question,
QuestionRequest,
QuestionVersion,
RecentArticle,
RefreshResponse,
ScheduleTask,
@@ -319,9 +320,6 @@ export const brandsApi = {
removeQuestion(brandId: number, questionId: number) {
return apiClient.remove<null>(`/api/tenant/brands/${brandId}/questions/${questionId}`);
},
listQuestionVersions(brandId: number) {
return apiClient.get<QuestionVersion[]>(`/api/tenant/brands/${brandId}/question-versions`);
},
listCompetitors(brandId: number) {
return apiClient.get<Competitor[]>(`/api/tenant/brands/${brandId}/competitors`);
},
@@ -408,6 +406,12 @@ export const generateApi = {
},
};
export const instantTasksApi = {
list(params?: InstantTaskListParams) {
return apiClient.get<InstantTaskListResponse>("/api/tenant/instant-tasks", { params });
},
};
export function normalizeInputParams(
payload: Record<string, JsonValue>,
articleId?: number,
+31 -1
View File
@@ -4,6 +4,7 @@ import { i18n } from "@/i18n";
const generateStatusMap: Record<string, { label: string; color: string }> = {
draft: { label: "status.generate.draft", color: "default" },
queued: { label: "status.generate.queued", color: "processing" },
generating: { label: "status.generate.generating", color: "processing" },
running: { label: "status.generate.running", color: "processing" },
completed: { label: "status.generate.completed", color: "success" },
@@ -43,16 +44,45 @@ export function getPublishStatusMeta(status?: string | null): { label: string; c
return meta ? { label: i18n.global.t(meta.label), color: meta.color } : { label: status, color: "default" };
}
export function getSourceTypeLabel(sourceType?: string | null): string {
export function getSourceTypeLabel(sourceType?: string | null, generationMode?: string | null): string {
if (!sourceType) {
return "--";
}
if (sourceType === "template") {
return i18n.global.t("status.sourceType.template");
}
if (sourceType === "custom_generation") {
if (generationMode === "schedule") {
return i18n.global.t("status.sourceType.schedule_task");
}
if (generationMode === "instant") {
return i18n.global.t("status.sourceType.instant_task");
}
return i18n.global.t("status.sourceType.custom_generation");
}
return sourceType;
}
export function formatCronExecutionTime(cronExpr?: string | null): string {
if (!cronExpr) {
return "--";
}
const fiveFieldMatch = cronExpr.match(/^(\d{1,2})\s+(\d{1,2})\s+\*\s+\*\s+\*$/);
if (fiveFieldMatch) {
const [, minute, hour] = fiveFieldMatch;
return `${hour.padStart(2, "0")}:${minute.padStart(2, "0")}`;
}
const sixFieldMatch = cronExpr.match(/^(\d{1,2})\s+(\d{1,2})\s+(\d{1,2})\s+\*\s+\*\s+\*$/);
if (sixFieldMatch) {
const [, second, minute, hour] = sixFieldMatch;
return `${hour.padStart(2, "0")}:${minute.padStart(2, "0")}:${second.padStart(2, "0")}`;
}
return cronExpr;
}
export function getTemplateMeta(templateKey: string): {
eyebrow: string;
helper: string;