feat: implement browser extension for media publishing and add backend support for media management

This commit is contained in:
2026-04-03 00:39:15 +08:00
parent 8958cb44c0
commit 32d6a462cd
60 changed files with 8268 additions and 26 deletions
+91 -2
View File
@@ -112,7 +112,7 @@ const enUS = {
},
media: {
title: "Media Management",
description: "No matching backend APIs exist in this repository yet.",
description: "Manage media bindings, local extension state, and one-click publishing from a single control plane.",
},
brands: {
title: "Brand Library",
@@ -196,6 +196,9 @@ const enUS = {
publish: {
unpublished: "Unpublished",
publishing: "Publishing",
success: "Published",
failed: "Failed",
partial_success: "Partial Success",
published: "Published",
publish_success: "Published",
publish_failed: "Failed",
@@ -230,6 +233,7 @@ const enUS = {
preview: "Preview",
edit: "Edit article",
editDisabled: "Only draft, failed, or completed articles can be edited",
publishDisabled: "Only completed articles can be published",
versions: "Versions",
deleteConfirm: "Delete this article?",
deleteSuccess: "Article deleted.",
@@ -384,6 +388,7 @@ const enUS = {
drawerTitle: "Article details",
preview: "Content preview",
versionHistory: "Version history",
publishedDetails: "Published details",
untitled: "Untitled article",
noContent: "This article does not have generated content yet.",
editor: {
@@ -405,7 +410,7 @@ const enUS = {
saved: "Article saved.",
generating: "This article is still generating. Try editing it later.",
locked: "Only completed articles can be edited.",
publishPending: "Publishing is not wired yet. The current action only saves content.",
publishPending: "Save the article first, then choose the target platforms.",
},
platforms: {
zhihu: "Zhihu",
@@ -419,6 +424,90 @@ const enUS = {
},
versionUntitled: "Untitled version",
},
media: {
hero: {
eyebrow: "Publisher",
},
plugin: {
title: "Browser Publisher",
ready: "Extension connected",
notInstalled: "Extension not connected",
installTitle: "Install and open the GEO Publisher extension first",
installDesc: "Binding and publishing depend on the browser's local platform sessions. The extension stores its own installation identity so future background checks can continue after the SaaS page is closed.",
backgroundHint: "The extension should not reuse the web app's access token directly. This implementation already registers a dedicated installation identity for future background scanning and inclusion checks.",
versionLabel: "Extension version",
installationLabel: "Installation ID",
connectedSummary: "Locally signed-in platforms",
registerRequired: "The extension installation is not registered yet. Please re-detect first.",
},
actions: {
redetect: "Re-detect",
bind: "Bind",
rebind: "Rebind",
unbind: "Unbind",
},
card: {
bound: "Bound",
unbound: "Unbound",
unboundHint: "{platform} has not been bound to this tenant yet.",
needsAttention: "Needs attention",
expiredHint: "This account is no longer healthy. Rebind it to restore publishing.",
localMissing: "Local session missing",
localMismatch: "Local account mismatch",
readyHint: "The correct local account is available and ready for publish or future background checks.",
accountLabel: "SaaS account",
uidLabel: "Platform UID",
localLabel: "Local state",
localConnected: "Session detected",
localDisconnected: "No session detected",
updatedAt: "Last sync",
multiAccount: "{count} accounts bound",
openPlatform: "Open platform",
},
account: {
localMissing: "The tenant account is bound, but this browser does not currently have the matching local session.",
localMismatch: "This browser is signed in to a different account. Rebind or switch the local account first.",
ready: "Ready",
selectable: "Selectable",
unavailable: "Unavailable",
},
empty: {
accounts: "No publishable media accounts are bound yet.",
},
messages: {
bindSuccess: "{platform} bound successfully.",
bindPending: "The extension did not detect a local session for this platform yet. Sign in via the extension and retry.",
unbindSuccess: "Account unbound.",
unbindConfirm: "Unbind this platform account? Publishing will no longer be available until it is bound again.",
},
publish: {
title: "Publish",
subtitle: "Multi-platform Dispatch",
description: "Choose tenant-bound accounts that are currently signed in locally. The extension executes the real publish flow and writes back the resulting links.",
platformsTitle: "Target platforms",
platformsHint: "Only tenant-bound accounts are listed here. Accounts with missing or mismatched local sessions are disabled automatically.",
coverTitle: "Cover image",
coverHint: "This version uses a cover asset URL. Upload and crop can be wired later.",
coverPlaceholder: "Enter an optional cover asset URL",
messages: {
success: "{count} publish tasks submitted.",
partial: "Publish finished with {success} succeeded and {failed} failed.",
selectPlatform: "Choose at least one available platform first.",
},
},
records: {
tabTitle: "Published details",
platform: "Platform",
status: "Status",
publishedAt: "Published at",
link: "Published link",
open: "Open",
copy: "Copy",
empty: "No publish records yet",
linkEmpty: "No link is available for this record yet.",
copySuccess: "Link copied.",
},
},
brands: {
eyebrow: "Brand Library",
title: "Brand Library",