feat(desktop): drop parked review flow, add publish management
SaaS 侧人工审核后才创建 publish job,desktop 不再做二次审核:移除 manual/waiting_user/parked/from_parked 状态机与 LeaseFromParked 查询, desktop client 只执行发布并新增"发布管理"页(待发布队列 / 历史 / 再次 发送)。同时抽离 @geo/publisher-platforms 共享适配器包、新增 Redis-based desktop_presence 与 publish_record_support,刷新 admin-web 发布弹窗与 媒体库;plan A / spec 文档同步口径。
This commit is contained in:
@@ -27,6 +27,7 @@ interface DesktopSession {
|
||||
|
||||
const sessionStorageKey = "geo.desktop.session.v1";
|
||||
const apiBaseURLStorageKey = "geo.desktop.api-base-url";
|
||||
const clientRegistrationStoragePrefix = "geo.desktop.client-registration.v1";
|
||||
|
||||
const session = shallowRef<DesktopSession | null>(readStoredSession());
|
||||
const apiBaseURL = shallowRef(readStoredApiBaseURL());
|
||||
@@ -125,8 +126,50 @@ function createAuthenticatedClient() {
|
||||
});
|
||||
}
|
||||
|
||||
function registerPayload(): DesktopClientRegisterRequest {
|
||||
function clientRegistrationStorageKey(user: UserInfo): string {
|
||||
return `${clientRegistrationStoragePrefix}:${user.primary_workspace_id}:${user.id}`;
|
||||
}
|
||||
|
||||
function readStoredClientRegistrationID(user: UserInfo): string | null {
|
||||
if (typeof window === "undefined") {
|
||||
return null;
|
||||
}
|
||||
return window.localStorage.getItem(clientRegistrationStorageKey(user));
|
||||
}
|
||||
|
||||
function persistClientRegistrationID(user: UserInfo, clientID: string): void {
|
||||
if (typeof window === "undefined") {
|
||||
return;
|
||||
}
|
||||
window.localStorage.setItem(clientRegistrationStorageKey(user), clientID);
|
||||
}
|
||||
|
||||
function generateUUID(): string {
|
||||
if (globalThis.crypto?.randomUUID) {
|
||||
return globalThis.crypto.randomUUID();
|
||||
}
|
||||
|
||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (char) => {
|
||||
const random = Math.floor(Math.random() * 16);
|
||||
const value = char === "x" ? random : (random & 0x3) | 0x8;
|
||||
return value.toString(16);
|
||||
});
|
||||
}
|
||||
|
||||
function getOrCreateClientRegistrationID(user: UserInfo): string {
|
||||
const existing = readStoredClientRegistrationID(user)?.trim();
|
||||
if (existing) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
const generated = generateUUID();
|
||||
persistClientRegistrationID(user, generated);
|
||||
return generated;
|
||||
}
|
||||
|
||||
function registerPayload(user: UserInfo): DesktopClientRegisterRequest {
|
||||
return {
|
||||
client_id: getOrCreateClientRegistrationID(user),
|
||||
device_name: `Desktop ${navigator.platform || "unknown"}`,
|
||||
os: navigator.platform || "unknown",
|
||||
cpu_arch: "renderer-preview",
|
||||
@@ -217,7 +260,9 @@ async function login(payload: LoginRequest): Promise<void> {
|
||||
const registered = await createAuthenticatedClient().post<
|
||||
DesktopClientRegisterResponse,
|
||||
DesktopClientRegisterRequest
|
||||
>("/api/desktop/clients/register", registerPayload());
|
||||
>("/api/desktop/clients/register", registerPayload(authData.user));
|
||||
|
||||
persistClientRegistrationID(authData.user, registered.client.id);
|
||||
|
||||
persistSession({
|
||||
mode: "authenticated",
|
||||
@@ -250,8 +295,24 @@ function enterPreview(): void {
|
||||
});
|
||||
}
|
||||
|
||||
function logout(): void {
|
||||
async function logout(): Promise<void> {
|
||||
error.value = null;
|
||||
const current = session.value;
|
||||
|
||||
if (current?.mode === "authenticated") {
|
||||
try {
|
||||
await window.desktopBridge?.app?.releaseRuntimeSession?.(true);
|
||||
} catch (err) {
|
||||
console.warn("[desktop-session] releaseRuntimeSession failed", err);
|
||||
}
|
||||
|
||||
try {
|
||||
await createAuthenticatedClient().post<null, Record<string, never>>("/api/auth/logout", {});
|
||||
} catch (err) {
|
||||
console.warn("[desktop-session] auth logout failed", err);
|
||||
}
|
||||
}
|
||||
|
||||
persistSession(null);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user