From 88c37e50b2057863885a182e9f8047498fe157b8 Mon Sep 17 00:00:00 2001 From: liangxu Date: Sat, 6 Jun 2026 13:06:14 +0800 Subject: [PATCH] feat(enterprise-site): add PbootCMS enterprise site publisher Introduce a new enterprise-site publishing channel that lets tenants push articles to self-hosted PbootCMS sites alongside the existing media supply flow. Backend (server/internal/tenant): - enterprise_site_service: CRUD, ping, category sync, and article publish - enterprise_site_pbootcms: PbootCMS API client integration - enterprise_site_crypto: encrypt/decrypt stored site credentials - enterprise_site_handler + routes under /enterprise-sites - migrations for the enterprise site publisher tables - config: add SERVER_PUBLIC_BASE_URL (Server.PublicBaseURL) for callbacks - article/media services adjusted to support the publish flow Frontend (apps/admin-web): - PublishArticleModal & ArticlePublishStatus: enterprise-site publish UI - MediaView: manage enterprise sites and categories - api + shared-types: enterprise site endpoints and types - http-client: add PATCH method support Integrations: - pbootcms GeoPublisher controller plugin + install guide - docs/enterprise-site-publisher-v1.md design doc --- .../src/components/ArticlePublishStatus.vue | 21 +- .../src/components/PublishArticleModal.vue | 1349 +++++++-- apps/admin-web/src/lib/api.ts | 50 + apps/admin-web/src/views/MediaView.vue | 1903 ++++++++++--- docs/enterprise-site-publisher-v1.md | 237 ++ integrations/pbootcms/Install.md | 175 ++ .../api/controller/GeoPublisherController.php | 748 +++++ packages/http-client/src/index.ts | 4 + packages/shared-types/src/index.ts | 107 +- server/internal/shared/config/config.go | 4 + server/internal/tenant/app/article_service.go | 11 +- .../tenant/app/enterprise_site_crypto.go | 78 + .../tenant/app/enterprise_site_pbootcms.go | 402 +++ .../tenant/app/enterprise_site_service.go | 2412 +++++++++++++++++ .../app/enterprise_site_service_test.go | 436 +++ server/internal/tenant/app/media_service.go | 30 +- .../transport/enterprise_site_handler.go | 142 + server/internal/tenant/transport/router.go | 11 + ...000_add_enterprise_site_publisher.down.sql | 20 + ...10000_add_enterprise_site_publisher.up.sql | 96 + 20 files changed, 7708 insertions(+), 528 deletions(-) create mode 100644 docs/enterprise-site-publisher-v1.md create mode 100644 integrations/pbootcms/Install.md create mode 100644 integrations/pbootcms/apps/api/controller/GeoPublisherController.php create mode 100644 server/internal/tenant/app/enterprise_site_crypto.go create mode 100644 server/internal/tenant/app/enterprise_site_pbootcms.go create mode 100644 server/internal/tenant/app/enterprise_site_service.go create mode 100644 server/internal/tenant/app/enterprise_site_service_test.go create mode 100644 server/internal/tenant/transport/enterprise_site_handler.go create mode 100644 server/migrations/20260605110000_add_enterprise_site_publisher.down.sql create mode 100644 server/migrations/20260605110000_add_enterprise_site_publisher.up.sql diff --git a/apps/admin-web/src/components/ArticlePublishStatus.vue b/apps/admin-web/src/components/ArticlePublishStatus.vue index 7ccbe1b..b29b78a 100644 --- a/apps/admin-web/src/components/ArticlePublishStatus.vue +++ b/apps/admin-web/src/components/ArticlePublishStatus.vue @@ -18,6 +18,7 @@ interface PublishPlatformEntry { accountName: string avatarUrl: string status: PublishRecordStatus + targetType: string } type PublishRecordStatus = 'success' | 'failed' | 'publishing' @@ -83,7 +84,11 @@ const platformEntries = computed(() => { const entries: PublishPlatformEntry[] = [] for (const record of publishRecordsQuery.data.value ?? []) { - const key = `${record.platform_id}:${record.platform_account_id}` + const targetType = String(record.target_type ?? 'platform_account') + const key = + targetType === 'enterprise_site' + ? `${targetType}:${record.target_connection_id ?? record.id}` + : `${record.platform_id}:${record.platform_account_id}` if (seen.has(key)) { continue } @@ -91,7 +96,7 @@ const platformEntries = computed(() => { const normalizedId = normalizePublishPlatformId(record.platform_id) const platform = platformMap.value.get(normalizedId) - const fallback = getPublishPlatformMeta(normalizedId) + const fallback = enterprisePlatformFallback(normalizedId) entries.push({ key, @@ -101,6 +106,7 @@ const platformEntries = computed(() => { accountName: record.platform_nickname || '--', avatarUrl: '', status: normalizePublishRecordStatus(record.status), + targetType, }) } @@ -236,6 +242,17 @@ function getAccountInitial(accountName: string): string { return trimmed.slice(0, 1).toUpperCase() } + +function enterprisePlatformFallback(platformId: string) { + if (platformId === 'pbootcms') { + return { + name: 'PBootCMS', + shortName: 'CMS', + accent: '#0f766e', + } + } + return getPublishPlatformMeta(platformId) +}