diff --git a/apps/admin-web/src/components/kol/KolVariableConfig.vue b/apps/admin-web/src/components/kol/KolVariableConfig.vue
index 18d6b77..c3ea233 100644
--- a/apps/admin-web/src/components/kol/KolVariableConfig.vue
+++ b/apps/admin-web/src/components/kol/KolVariableConfig.vue
@@ -254,13 +254,11 @@ defineExpose({
diff --git a/apps/admin-web/src/lib/api.ts b/apps/admin-web/src/lib/api.ts
index fc01482..1d94f79 100644
--- a/apps/admin-web/src/lib/api.ts
+++ b/apps/admin-web/src/lib/api.ts
@@ -35,6 +35,10 @@ import type {
CreatePublishJobRequest,
CreatePublishJobResponse,
DesktopAccountInfo,
+ DesktopClientDownloadableRelease,
+ DesktopClientDownloadableReleaseListResponse,
+ DesktopClientReleaseCheckResponse,
+ DesktopClientReleaseDownloadURLResponse,
FolderDeletePreview,
GenerateFromRuleRequest,
GenerateFromRuleResponse,
@@ -1285,6 +1289,80 @@ export const tenantAccountsApi = {
},
}
+export const desktopClientApi = {
+ downloadableReleases(channel = 'stable') {
+ return apiClient.get(
+ '/api/tenant/desktop-client/releases/downloadable',
+ { params: { channel } },
+ )
+ },
+ publicLatest(params: { platform: string; arch: string; channel?: string; version?: string }) {
+ return publicClient.get('/api/desktop/releases/latest', {
+ params: {
+ platform: params.platform,
+ arch: params.arch,
+ channel: params.channel ?? 'stable',
+ version: params.version ?? '0.0.0',
+ },
+ })
+ },
+ publicDownloadURL(params: {
+ platform: string
+ arch: string
+ channel?: string
+ version?: string
+ }) {
+ return publicClient.get(
+ '/api/desktop/releases/download-url',
+ {
+ params: {
+ platform: params.platform,
+ arch: params.arch,
+ channel: params.channel ?? 'stable',
+ version: params.version ?? '0.0.0',
+ },
+ },
+ )
+ },
+ async publicFallbackDownloadableReleases(): Promise {
+ const targets = [
+ { platform: 'win32', arch: 'x64' },
+ { platform: 'darwin', arch: 'arm64' },
+ ]
+ const results = await Promise.allSettled(
+ targets.map((target) => this.publicLatest({ ...target, channel: 'stable' })),
+ )
+ return {
+ items: results.flatMap((result, index) => {
+ if (result.status !== 'fulfilled') {
+ return []
+ }
+ const release = result.value
+ const target = targets[index]
+ const item: DesktopClientDownloadableRelease = {
+ id: index + 1,
+ platform: release.platform ?? target.platform,
+ arch: release.arch ?? target.arch,
+ channel: release.channel ?? 'stable',
+ version: release.latest_version,
+ download_url: release.download_url ?? null,
+ oss_object_key: release.oss_object_key ?? null,
+ file_name: release.file_name ?? null,
+ file_size_bytes: release.file_size_bytes ?? null,
+ sha256: release.sha256 ?? null,
+ release_notes: release.release_notes ?? null,
+ published_at: release.published_at ?? null,
+ updated_at: release.published_at ?? new Date(0).toISOString(),
+ force_update: release.force_update,
+ min_supported_version: release.min_supported_version,
+ download_source: release.download_source,
+ }
+ return [item]
+ }),
+ }
+ },
+}
+
export const publishJobsApi = {
create(payload: CreatePublishJobRequest) {
return apiClient.post(
diff --git a/apps/admin-web/src/views/MediaView.vue b/apps/admin-web/src/views/MediaView.vue
index 14ab91b..5017bf1 100644
--- a/apps/admin-web/src/views/MediaView.vue
+++ b/apps/admin-web/src/views/MediaView.vue
@@ -1,13 +1,18 @@