feat(migrations): Harden task audit tracking and optimize article templates

- Added migration to harden task audit tracking by modifying audit_logs and related tables.
- Introduced operator_id to several tables for better tracking of actions.
- Updated article_templates with new prompt templates for various article types, enhancing content generation.
- Created prompt_rules and schedule_tasks tables to manage content generation rules and scheduling.
- Added foreign key constraints to articles for better data integrity.
This commit is contained in:
2026-04-02 00:31:28 +08:00
parent de30497f59
commit b31d8d0096
101 changed files with 16671 additions and 721 deletions
@@ -17,7 +17,6 @@ import {
getPublishStatusMeta,
getSourceTypeLabel,
} from "@/lib/display";
import { formatError } from "@/lib/errors";
const props = defineProps<{
open: boolean;
@@ -35,7 +34,6 @@ const enabled = computed(() => props.open && Boolean(props.articleId));
const streamTitle = ref("");
const streamMarkdown = ref("");
const streamStatus = ref<string | null>(null);
const streamError = ref("");
const streamFeatureEnabled = isGenerationStreamEnabled();
const detailQuery = useQuery({
@@ -85,7 +83,6 @@ const versionColumns = computed<TableColumnsType<ArticleVersion>>(() => [
const detail = computed(() => detailQuery.data.value);
const displayTitle = computed(() => streamTitle.value || detail.value?.title || t("article.untitled"));
const displayMarkdown = computed(() => streamMarkdown.value || detail.value?.markdown_content || "");
const displayError = computed(() => streamError.value || detail.value?.generation_error_message || "");
const generateMeta = computed(() =>
getGenerateStatusMeta(streamStatus.value || detail.value?.generate_status),
);
@@ -117,11 +114,11 @@ watch(
},
},
controller.signal,
).catch((error) => {
).catch(() => {
if (controller.signal.aborted) {
return;
}
streamError.value = formatError(error);
void refreshArticleData();
});
onCleanup(() => {
@@ -160,9 +157,6 @@ function handleStreamEvent(event: ArticleGenerationStreamEvent): void {
if (event.status) {
streamStatus.value = event.status;
}
if (event.error) {
streamError.value = event.error;
}
if (event.type === "snapshot" || event.type === "completed") {
if (event.content) {
@@ -185,7 +179,6 @@ function resetStreamState(): void {
streamTitle.value = "";
streamMarkdown.value = "";
streamStatus.value = null;
streamError.value = "";
}
async function refreshArticleData(): Promise<void> {
@@ -244,15 +237,6 @@ async function refreshArticleData(): Promise<void> {
</a-descriptions>
</section>
<a-alert
v-if="displayError"
class="article-drawer__alert"
type="error"
show-icon
:message="t('common.generateStatus')"
:description="displayError"
/>
<a-tabs v-model:activeKey="activeTab" class="article-drawer__tabs">
<a-tab-pane key="content" :tab="t('article.preview')">
<div