Files
geo/apps/admin-web/src/components/ArticleSourceMeta.vue
T
root 40d9a6cc63 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>
2026-04-25 21:36:44 +08:00

173 lines
3.9 KiB
Vue

<script setup lang="ts">
import {
AppstoreOutlined,
CalendarOutlined,
ClockCircleOutlined,
CopyOutlined,
EditOutlined,
TeamOutlined,
ThunderboltOutlined,
} from "@ant-design/icons-vue";
import { computed, type Component } from "vue";
import { formatDateTime, getSourceTypeLabel } from "@/lib/display";
const props = defineProps<{
sourceType?: string | null;
generationMode?: string | null;
createdAt?: string | null;
}>();
const sourceLabel = computed(() =>
getSourceTypeLabel(props.sourceType, props.generationMode),
);
const createdAtLabel = computed(() => formatDateTime(props.createdAt));
const sourceVariant = computed<
"template" | "custom" | "instant" | "schedule" | "free-create" | "imitation" | "kol" | "default"
>(() => {
if (props.sourceType === "template") {
return "template";
}
if (props.sourceType === "free_create") {
return "free-create";
}
if (props.sourceType === "imitation") {
return "imitation";
}
if (props.sourceType === "kol") {
return "kol";
}
if (props.sourceType === "custom_generation") {
if (props.generationMode === "schedule") {
return "schedule";
}
if (props.generationMode === "instant") {
return "instant";
}
return "custom";
}
return "default";
});
const badgeIcon = computed<Component>(() => {
switch (sourceVariant.value) {
case "template":
return AppstoreOutlined;
case "instant":
return ThunderboltOutlined;
case "schedule":
return CalendarOutlined;
case "custom":
return ThunderboltOutlined;
case "free-create":
return EditOutlined;
case "imitation":
return CopyOutlined;
case "kol":
return TeamOutlined;
default:
return AppstoreOutlined;
}
});
</script>
<template>
<div class="article-source-meta">
<span
class="article-source-meta__badge"
:class="`article-source-meta__badge--${sourceVariant}`"
>
<component :is="badgeIcon" />
<span>{{ sourceLabel }}</span>
</span>
<span class="article-source-meta__time">
<ClockCircleOutlined />
<span>{{ createdAtLabel }}</span>
</span>
</div>
</template>
<style scoped>
.article-source-meta {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 10px 14px;
}
.article-source-meta__badge {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 4px 8px;
border-radius: 6px;
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
font-size: 12px;
font-weight: 600;
line-height: 1;
}
.article-source-meta__badge--template {
border: 1px solid #d9e5ff;
background: linear-gradient(180deg, #fbfcff 0%, #f3f7ff 100%);
color: #225fd1;
}
.article-source-meta__badge--custom {
border: 1px solid #d9ccff;
background: linear-gradient(180deg, #f7f4ff 0%, #efe9ff 100%);
color: #6941c6;
}
.article-source-meta__badge--instant {
border: 1px solid #f3c796;
background: linear-gradient(180deg, #fff5e9 0%, #ffe9d2 100%);
color: #b54708;
}
.article-source-meta__badge--schedule {
border: 1px solid #a7ddd3;
background: linear-gradient(180deg, #eefaf7 0%, #def3ee 100%);
color: #0b6b61;
}
.article-source-meta__badge--free-create {
border: 1px solid #d4ead8;
background: linear-gradient(180deg, #f7fcf8 0%, #eef8f1 100%);
color: #18794e;
}
.article-source-meta__badge--imitation {
border: 1px solid #bfdbfe;
background: linear-gradient(180deg, #f8fbff 0%, #e6f0ff 100%);
color: #1d4ed8;
}
.article-source-meta__badge--kol {
border: 1px solid #d6e4ff;
background: linear-gradient(180deg, #f5f8ff 0%, #eaf1ff 100%);
color: #1d4ed8;
}
.article-source-meta__badge--default {
border: 1px solid #dde3ea;
background: linear-gradient(180deg, #fbfcfd 0%, #f4f6f8 100%);
color: #44546a;
}
.article-source-meta__time {
display: inline-flex;
align-items: center;
gap: 6px;
color: #667085;
font-size: 12px;
line-height: 1;
}
.article-source-meta :deep(.anticon) {
font-size: 12px;
}
</style>