2026-04-07 16:07:21 +08:00
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
|
import { QuestionCircleOutlined, UserOutlined } from "@ant-design/icons-vue";
|
|
|
|
|
|
import { useQuery } from "@tanstack/vue-query";
|
2026-04-20 09:52:48 +08:00
|
|
|
|
import type { MediaPlatform } from "@geo/shared-types";
|
2026-04-07 16:07:21 +08:00
|
|
|
|
import { computed, ref } from "vue";
|
|
|
|
|
|
import { useI18n } from "vue-i18n";
|
|
|
|
|
|
|
2026-04-20 09:52:48 +08:00
|
|
|
|
import { articlesApi, mediaApi } from "@/lib/api";
|
2026-04-07 16:07:21 +08:00
|
|
|
|
import { getPublishStatusMeta } from "@/lib/display";
|
|
|
|
|
|
import { getPublishPlatformMeta, normalizePublishPlatformId } from "@/lib/publish-platforms";
|
|
|
|
|
|
|
|
|
|
|
|
interface PublishPlatformEntry {
|
|
|
|
|
|
key: string;
|
|
|
|
|
|
name: string;
|
|
|
|
|
|
shortName: string;
|
|
|
|
|
|
accent: string;
|
|
|
|
|
|
accountName: string;
|
|
|
|
|
|
avatarUrl: string;
|
|
|
|
|
|
status: PublishRecordStatus;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-20 11:44:47 +08:00
|
|
|
|
type PublishRecordStatus = "success" | "failed" | "publishing";
|
2026-04-07 16:07:21 +08:00
|
|
|
|
|
|
|
|
|
|
interface PublishPlatformSection {
|
|
|
|
|
|
key: PublishRecordStatus;
|
|
|
|
|
|
label: string;
|
|
|
|
|
|
tone: "success" | "failed" | "pending";
|
|
|
|
|
|
entries: PublishPlatformEntry[];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const props = withDefaults(defineProps<{
|
|
|
|
|
|
status?: string | null;
|
|
|
|
|
|
articleId?: number | null;
|
|
|
|
|
|
showPlatforms?: boolean;
|
|
|
|
|
|
}>(), {
|
|
|
|
|
|
status: null,
|
|
|
|
|
|
articleId: null,
|
|
|
|
|
|
showPlatforms: true,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const { t } = useI18n();
|
|
|
|
|
|
const popoverOpen = ref(false);
|
|
|
|
|
|
const shouldLoadPlatforms = computed(() => props.showPlatforms && Boolean(props.articleId) && props.status !== "unpublished");
|
|
|
|
|
|
|
|
|
|
|
|
const platformsQuery = useQuery({
|
|
|
|
|
|
queryKey: ["media", "platforms", "publish-status"],
|
|
|
|
|
|
enabled: computed(() => popoverOpen.value && shouldLoadPlatforms.value),
|
|
|
|
|
|
queryFn: () => mediaApi.platforms(),
|
|
|
|
|
|
staleTime: 5 * 60 * 1000,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const publishRecordsQuery = useQuery({
|
|
|
|
|
|
queryKey: computed(() => ["articles", "publish-records", props.articleId, "publish-status"]),
|
|
|
|
|
|
enabled: computed(() => popoverOpen.value && shouldLoadPlatforms.value),
|
|
|
|
|
|
queryFn: () => articlesApi.publishRecords(props.articleId as number),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const hasPopover = computed(() => shouldLoadPlatforms.value);
|
|
|
|
|
|
|
|
|
|
|
|
const platformMap = computed(() => {
|
|
|
|
|
|
return new Map(
|
|
|
|
|
|
(platformsQuery.data.value ?? []).map((platform: MediaPlatform) => [
|
|
|
|
|
|
normalizePublishPlatformId(platform.platform_id),
|
|
|
|
|
|
platform,
|
|
|
|
|
|
]),
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const platformEntries = computed<PublishPlatformEntry[]>(() => {
|
|
|
|
|
|
const seen = new Set<string>();
|
|
|
|
|
|
const entries: PublishPlatformEntry[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
for (const record of publishRecordsQuery.data.value ?? []) {
|
|
|
|
|
|
const key = `${record.platform_id}:${record.platform_account_id}`;
|
|
|
|
|
|
if (seen.has(key)) {
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
seen.add(key);
|
|
|
|
|
|
|
|
|
|
|
|
const normalizedId = normalizePublishPlatformId(record.platform_id);
|
|
|
|
|
|
const platform = platformMap.value.get(normalizedId);
|
|
|
|
|
|
const fallback = getPublishPlatformMeta(normalizedId);
|
|
|
|
|
|
|
|
|
|
|
|
entries.push({
|
|
|
|
|
|
key,
|
|
|
|
|
|
name: record.platform_name || platform?.name || fallback.name,
|
|
|
|
|
|
shortName: platform?.short_name || fallback.shortName,
|
|
|
|
|
|
accent: platform?.accent_color || fallback.accent,
|
2026-04-20 09:52:48 +08:00
|
|
|
|
accountName: record.platform_nickname || "--",
|
|
|
|
|
|
avatarUrl: "",
|
2026-04-07 16:07:21 +08:00
|
|
|
|
status: normalizePublishRecordStatus(record.status),
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return entries;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const successEntries = computed(() =>
|
|
|
|
|
|
platformEntries.value.filter((entry) => entry.status === "success"),
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const failedEntries = computed(() =>
|
|
|
|
|
|
platformEntries.value.filter((entry) => entry.status === "failed"),
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const pendingEntries = computed(() =>
|
2026-04-20 11:44:47 +08:00
|
|
|
|
platformEntries.value.filter((entry) => entry.status === "publishing"),
|
2026-04-07 16:07:21 +08:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const displayStatus = computed(() => {
|
|
|
|
|
|
if (successEntries.value.length > 0) {
|
|
|
|
|
|
return "success";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (platformEntries.value.length > 0 && failedEntries.value.length === platformEntries.value.length) {
|
|
|
|
|
|
return "failed";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (pendingEntries.value.some((entry) => entry.status === "publishing")) {
|
|
|
|
|
|
return "publishing";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (pendingEntries.value.length > 0) {
|
2026-04-20 11:44:47 +08:00
|
|
|
|
return "publishing";
|
2026-04-07 16:07:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (props.status === "partial_success") {
|
|
|
|
|
|
return "success";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (props.status === "publish_success" || props.status === "published") {
|
|
|
|
|
|
return "success";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (props.status === "publish_failed") {
|
|
|
|
|
|
return "failed";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-20 11:44:47 +08:00
|
|
|
|
if (props.status === "pending_review") {
|
|
|
|
|
|
return "failed";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-07 16:07:21 +08:00
|
|
|
|
return props.status ?? null;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const statusMeta = computed(() => getPublishStatusMeta(displayStatus.value));
|
|
|
|
|
|
|
|
|
|
|
|
const statusTone = computed(() => {
|
|
|
|
|
|
switch (displayStatus.value) {
|
|
|
|
|
|
case "success":
|
|
|
|
|
|
return "success";
|
|
|
|
|
|
case "failed":
|
|
|
|
|
|
return "failed";
|
|
|
|
|
|
case "publishing":
|
|
|
|
|
|
return "processing";
|
|
|
|
|
|
default:
|
|
|
|
|
|
return "default";
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const popoverSections = computed<PublishPlatformSection[]>(() => {
|
|
|
|
|
|
const sections: PublishPlatformSection[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
if (successEntries.value.length > 0) {
|
|
|
|
|
|
sections.push({
|
|
|
|
|
|
key: "success",
|
|
|
|
|
|
label: `${getPublishStatusMeta("success").label}:`,
|
|
|
|
|
|
tone: "success",
|
|
|
|
|
|
entries: successEntries.value,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (failedEntries.value.length > 0) {
|
|
|
|
|
|
sections.push({
|
|
|
|
|
|
key: "failed",
|
|
|
|
|
|
label: `${getPublishStatusMeta("failed").label}:`,
|
|
|
|
|
|
tone: "failed",
|
|
|
|
|
|
entries: failedEntries.value,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (pendingEntries.value.length > 0) {
|
|
|
|
|
|
sections.push({
|
2026-04-20 11:44:47 +08:00
|
|
|
|
key: "publishing",
|
|
|
|
|
|
label: `${getPublishStatusMeta("publishing").label}:`,
|
2026-04-07 16:07:21 +08:00
|
|
|
|
tone: "pending",
|
|
|
|
|
|
entries: pendingEntries.value,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return sections;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
function handlePopoverChange(nextOpen: boolean): void {
|
|
|
|
|
|
popoverOpen.value = nextOpen;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function normalizePublishRecordStatus(status?: string | null): PublishRecordStatus {
|
|
|
|
|
|
switch (String(status ?? "").trim()) {
|
|
|
|
|
|
case "success":
|
|
|
|
|
|
case "published":
|
|
|
|
|
|
case "publish_success":
|
|
|
|
|
|
return "success";
|
|
|
|
|
|
case "publishing":
|
|
|
|
|
|
case "running":
|
|
|
|
|
|
case "queued":
|
|
|
|
|
|
return "publishing";
|
|
|
|
|
|
case "pending_review":
|
2026-04-20 11:44:47 +08:00
|
|
|
|
return "failed";
|
2026-04-07 16:07:21 +08:00
|
|
|
|
case "failed":
|
|
|
|
|
|
case "publish_failed":
|
|
|
|
|
|
default:
|
|
|
|
|
|
return "failed";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getAccountInitial(accountName: string): string {
|
|
|
|
|
|
const trimmed = String(accountName ?? "").trim();
|
|
|
|
|
|
if (!trimmed || trimmed === "--") {
|
|
|
|
|
|
return "";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return trimmed.slice(0, 1).toUpperCase();
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
|
<a-popover
|
|
|
|
|
|
v-if="hasPopover"
|
|
|
|
|
|
placement="top"
|
|
|
|
|
|
trigger="hover"
|
|
|
|
|
|
overlay-class-name="article-publish-status__popover-overlay"
|
|
|
|
|
|
@openChange="handlePopoverChange"
|
|
|
|
|
|
>
|
|
|
|
|
|
<template #content>
|
|
|
|
|
|
<div class="article-publish-status__popover">
|
|
|
|
|
|
<div
|
2026-04-20 09:52:48 +08:00
|
|
|
|
v-if="publishRecordsQuery.isPending.value || platformsQuery.isPending.value"
|
2026-04-07 16:07:21 +08:00
|
|
|
|
class="article-publish-status__loading"
|
|
|
|
|
|
>
|
|
|
|
|
|
<a-spin size="small" />
|
|
|
|
|
|
<span>{{ t("common.loading") }}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div v-else-if="popoverSections.length" class="article-publish-status__sections">
|
|
|
|
|
|
<section
|
|
|
|
|
|
v-for="section in popoverSections"
|
|
|
|
|
|
:key="section.key"
|
|
|
|
|
|
class="article-publish-status__section"
|
|
|
|
|
|
>
|
|
|
|
|
|
<header
|
|
|
|
|
|
class="article-publish-status__section-title"
|
|
|
|
|
|
:class="`article-publish-status__section-title--${section.tone}`"
|
|
|
|
|
|
>
|
|
|
|
|
|
<span class="article-publish-status__section-dot" />
|
|
|
|
|
|
<span>{{ section.label }}</span>
|
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="article-publish-status__platforms">
|
|
|
|
|
|
<a-popover
|
|
|
|
|
|
v-for="entry in section.entries"
|
|
|
|
|
|
:key="entry.key"
|
|
|
|
|
|
placement="top"
|
|
|
|
|
|
overlay-class-name="article-publish-status__account-popover"
|
|
|
|
|
|
>
|
|
|
|
|
|
<template #content>
|
|
|
|
|
|
<div class="article-publish-status__account-card">
|
|
|
|
|
|
<span class="article-publish-status__account-avatar">
|
|
|
|
|
|
<img
|
|
|
|
|
|
v-if="entry.avatarUrl"
|
|
|
|
|
|
:src="entry.avatarUrl"
|
|
|
|
|
|
:alt="entry.accountName"
|
|
|
|
|
|
class="article-publish-status__account-avatar-img"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<template v-else-if="getAccountInitial(entry.accountName)">
|
|
|
|
|
|
{{ getAccountInitial(entry.accountName) }}
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<UserOutlined v-else />
|
|
|
|
|
|
</span>
|
|
|
|
|
|
<span class="article-publish-status__account-name">{{ entry.accountName }}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="article-publish-status__platform-chip"
|
|
|
|
|
|
:class="`article-publish-status__platform-chip--${section.tone}`"
|
|
|
|
|
|
>
|
|
|
|
|
|
<span
|
|
|
|
|
|
class="article-publish-status__platform-mark"
|
|
|
|
|
|
:style="{ background: entry.accent }"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ entry.shortName }}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
<span class="article-publish-status__platform-name">{{ entry.name }}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</a-popover>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<span v-else class="article-publish-status__empty">
|
|
|
|
|
|
{{ t("media.records.empty") }}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<span class="article-publish-status__trigger">
|
|
|
|
|
|
<span
|
|
|
|
|
|
class="article-publish-status__badge"
|
|
|
|
|
|
:class="`article-publish-status__badge--${statusTone}`"
|
|
|
|
|
|
>
|
|
|
|
|
|
<span class="article-publish-status__badge-dot" />
|
|
|
|
|
|
<span>{{ statusMeta.label }}</span>
|
|
|
|
|
|
<QuestionCircleOutlined class="article-publish-status__icon" />
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</a-popover>
|
|
|
|
|
|
|
|
|
|
|
|
<span
|
|
|
|
|
|
v-else
|
|
|
|
|
|
class="article-publish-status__badge"
|
|
|
|
|
|
:class="`article-publish-status__badge--${statusTone}`"
|
|
|
|
|
|
>
|
|
|
|
|
|
<span class="article-publish-status__badge-dot" />
|
|
|
|
|
|
<span>{{ statusMeta.label }}</span>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
.article-publish-status__trigger {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__badge {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
padding: 3px 12px;
|
|
|
|
|
|
border: 1px solid transparent;
|
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
line-height: 22px;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
transition: border-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__badge--success {
|
|
|
|
|
|
background: #f4fbec;
|
|
|
|
|
|
border-color: #b7eb8f;
|
|
|
|
|
|
color: #4d6b18;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__badge--failed {
|
|
|
|
|
|
background: #fff3f0;
|
|
|
|
|
|
border-color: #ffccc7;
|
|
|
|
|
|
color: #cf1322;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__badge--processing {
|
|
|
|
|
|
background: #eff6ff;
|
|
|
|
|
|
border-color: #bfdbfe;
|
|
|
|
|
|
color: #1d4ed8;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__badge--warning {
|
|
|
|
|
|
background: #fff8e6;
|
|
|
|
|
|
border-color: #ffd591;
|
|
|
|
|
|
color: #ad6800;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__badge--default {
|
|
|
|
|
|
background: #f7f8fa;
|
|
|
|
|
|
border-color: #d9d9d9;
|
|
|
|
|
|
color: #595959;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__badge-dot {
|
|
|
|
|
|
width: 6px;
|
|
|
|
|
|
height:6px;
|
|
|
|
|
|
border-radius: 999px;
|
|
|
|
|
|
flex: 0 0 auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__badge--success .article-publish-status__badge-dot,
|
|
|
|
|
|
.article-publish-status__section-title--success .article-publish-status__section-dot {
|
|
|
|
|
|
background: #52c41a;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__badge--failed .article-publish-status__badge-dot,
|
|
|
|
|
|
.article-publish-status__section-title--failed .article-publish-status__section-dot {
|
|
|
|
|
|
background: #ff4d4f;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__badge--processing .article-publish-status__badge-dot,
|
|
|
|
|
|
.article-publish-status__section-title--pending .article-publish-status__section-dot {
|
|
|
|
|
|
background: #1677ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__badge--warning .article-publish-status__badge-dot {
|
|
|
|
|
|
background: #faad14;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__badge--default .article-publish-status__badge-dot {
|
|
|
|
|
|
background: #98a2b3;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__icon {
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
opacity: 0.72;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__popover {
|
|
|
|
|
|
min-width: 360px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__loading {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
color: #667085;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__sections {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: 18px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__section {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__section-title {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
color: #344054;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
line-height: 1.25;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__section-dot {
|
|
|
|
|
|
width: 8px;
|
|
|
|
|
|
height: 8px;
|
|
|
|
|
|
border-radius: 999px;
|
|
|
|
|
|
flex: 0 0 auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__platforms {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
gap: 8px 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__platform-chip {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
min-height: 36px;
|
|
|
|
|
|
padding: 4px 12px 4px 4px;
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
background: #f9f9f9;
|
|
|
|
|
|
border: 1px solid transparent;
|
|
|
|
|
|
color: #141414;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
transition: all 0.2s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__platform-chip:hover {
|
|
|
|
|
|
transform: translateY(-1px);
|
|
|
|
|
|
background: #f0f0f0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__platform-chip--success:hover {
|
|
|
|
|
|
background: #f0f0f0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__platform-chip--failed {
|
|
|
|
|
|
background: #fffafa;
|
|
|
|
|
|
border-color: #ffccc7;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__platform-chip--failed:hover {
|
|
|
|
|
|
border-color: rgba(255, 77, 79, 0.24);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__platform-chip--pending {
|
|
|
|
|
|
background: #f0f5ff;
|
|
|
|
|
|
border-color: #d6e4ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__platform-mark {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
min-width: 24px;
|
|
|
|
|
|
height: 24px;
|
|
|
|
|
|
padding: 0 4px;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
box-shadow: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__platform-name {
|
|
|
|
|
|
letter-spacing: 0.01em;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__empty {
|
|
|
|
|
|
color: #98a2b3;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__account-card {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 6px;
|
|
|
|
|
|
min-width: auto;
|
|
|
|
|
|
height: 30px;
|
|
|
|
|
|
padding: 0 10px;
|
|
|
|
|
|
background: #f8f9fa;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__account-avatar {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
width: 24px;
|
|
|
|
|
|
height: 24px;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
background: #f0f2f5;
|
|
|
|
|
|
color: #1f2937;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__account-avatar-img {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
object-fit: cover;
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.article-publish-status__account-name {
|
|
|
|
|
|
color: #344054;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
line-height: 1.2;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.article-publish-status__popover-overlay .ant-popover-inner) {
|
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
padding: 16px 20px;
|
|
|
|
|
|
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.08);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.article-publish-status__popover-overlay .ant-popover-inner-content) {
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.article-publish-status__popover-overlay .ant-popover-arrow:before) {
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.article-publish-status__account-popover .ant-popover-inner) {
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
padding: 6px 12px;
|
|
|
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.article-publish-status__account-popover .ant-popover-inner-content) {
|
|
|
|
|
|
color: #344054;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.article-publish-status__account-popover .ant-popover-arrow:before) {
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|