From f36d657bba337fdab9d291c9fdf9959c3353a487 Mon Sep 17 00:00:00 2001 From: XuqmGroup Date: Thu, 7 May 2026 13:53:02 +0800 Subject: [PATCH] feat: add quick service entry portal with in-page app switcher MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add sidebar sub-menu for 服务管理 (IM / 离线推送 / 版本管理) - Service pages load directly with optional appId route param - Each service page shows a portal bar (app selector) when accessed via /services/* path - Content is guarded with v-if so empty state shows when no app is selected - Router-view keyed by path so component re-creates on app switch - App-level package name split into Android/iOS/HarmonyOS fields - Push vendor channel config: Xiaomi channelId, Huawei category, vivo category+receiptId, OPPO channelId - Remove packageName from push vendor config (moved to app-level) - Format device last-login time in push management view Co-Authored-By: Claude Sonnet 4.6 --- tenant-platform/components.d.ts | 2 + tenant-platform/src/api/app.ts | 8 ++- tenant-platform/src/router/index.ts | 12 +++++ .../src/views/apps/AppDetailView.vue | 4 +- .../src/views/apps/AppListView.vue | 10 +++- .../src/views/im/ImManagementView.vue | 36 ++++++++++++- .../src/views/layout/MainLayout.vue | 54 +++++++++++-------- .../src/views/push/PushConfigView.vue | 35 +++++++----- .../src/views/push/PushManagementView.vue | 50 +++++++++++++++-- .../views/update/VersionManagementView.vue | 35 +++++++++++- 10 files changed, 197 insertions(+), 49 deletions(-) diff --git a/tenant-platform/components.d.ts b/tenant-platform/components.d.ts index 237a0de..89f0163 100644 --- a/tenant-platform/components.d.ts +++ b/tenant-platform/components.d.ts @@ -43,6 +43,7 @@ declare module 'vue' { ElPageHeader: typeof import('element-plus/es')['ElPageHeader'] ElPagination: typeof import('element-plus/es')['ElPagination'] ElProgress: typeof import('element-plus/es')['ElProgress'] + ElRadio: typeof import('element-plus/es')['ElRadio'] ElRadioButton: typeof import('element-plus/es')['ElRadioButton'] ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] ElRow: typeof import('element-plus/es')['ElRow'] @@ -53,6 +54,7 @@ declare module 'vue' { ElStatistic: typeof import('element-plus/es')['ElStatistic'] ElStep: typeof import('element-plus/es')['ElStep'] ElSteps: typeof import('element-plus/es')['ElSteps'] + ElSubMenu: typeof import('element-plus/es')['ElSubMenu'] ElSwitch: typeof import('element-plus/es')['ElSwitch'] ElTable: typeof import('element-plus/es')['ElTable'] ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] diff --git a/tenant-platform/src/api/app.ts b/tenant-platform/src/api/app.ts index 6152c71..515df9f 100644 --- a/tenant-platform/src/api/app.ts +++ b/tenant-platform/src/api/app.ts @@ -4,6 +4,8 @@ export interface App { id: string tenantId: string packageName: string + iosBundleId?: string + harmonyBundleName?: string name: string description?: string iconUrl?: string @@ -14,6 +16,8 @@ export interface App { export interface CreateAppRequest { packageName: string + iosBundleId?: string + harmonyBundleName?: string name: string description?: string iconUrl?: string @@ -61,7 +65,6 @@ export interface PushVendorConfig { appId?: string appKey?: string appSecret?: string - packageName?: string masterSecret?: string clientId?: string clientSecret?: string @@ -71,6 +74,9 @@ export interface PushVendorConfig { keyPath?: string sandbox?: boolean serviceAccountJson?: string + channelId?: string + category?: string + receiptId?: string } export interface PushServiceConfig { diff --git a/tenant-platform/src/router/index.ts b/tenant-platform/src/router/index.ts index f56f990..57cf852 100644 --- a/tenant-platform/src/router/index.ts +++ b/tenant-platform/src/router/index.ts @@ -81,6 +81,18 @@ const router = createRouter({ path: 'apps/:appId/update', component: () => import('@/views/update/VersionManagementView.vue'), }, + { + path: 'services/im/:appId?', + component: () => import('@/views/im/ImManagementView.vue'), + }, + { + path: 'services/push/:appId?', + component: () => import('@/views/push/PushManagementView.vue'), + }, + { + path: 'services/update/:appId?', + component: () => import('@/views/update/VersionManagementView.vue'), + }, { path: 'accounts', component: () => import('@/views/accounts/SubAccountView.vue'), diff --git a/tenant-platform/src/views/apps/AppDetailView.vue b/tenant-platform/src/views/apps/AppDetailView.vue index e5da75c..3997a4f 100644 --- a/tenant-platform/src/views/apps/AppDetailView.vue +++ b/tenant-platform/src/views/apps/AppDetailView.vue @@ -5,7 +5,9 @@ {{ app.name }} - {{ app.packageName }} + {{ app.packageName }} + {{ app.iosBundleId ?? '-' }} + {{ app.harmonyBundleName ?? '-' }} {{ app.appKey }} diff --git a/tenant-platform/src/views/apps/AppListView.vue b/tenant-platform/src/views/apps/AppListView.vue index 78682c2..c5244a1 100644 --- a/tenant-platform/src/views/apps/AppListView.vue +++ b/tenant-platform/src/views/apps/AppListView.vue @@ -26,9 +26,15 @@ - + + + + + + + @@ -58,7 +64,7 @@ const createFormRef = ref() const isMobile = ref(false) const dialogWidth = computed(() => (isMobile.value ? 'calc(100vw - 24px)' : '480px')) -const createForm = reactive({ packageName: '', name: '', description: '' }) +const createForm = reactive({ packageName: '', iosBundleId: '', harmonyBundleName: '', name: '', description: '' }) const createRules: FormRules = { packageName: [{ required: true, message: '请输入包名' }], name: [{ required: true, message: '请输入应用名' }], diff --git a/tenant-platform/src/views/im/ImManagementView.vue b/tenant-platform/src/views/im/ImManagementView.vue index 7134f62..a6bf868 100644 --- a/tenant-platform/src/views/im/ImManagementView.vue +++ b/tenant-platform/src/views/im/ImManagementView.vue @@ -1,7 +1,15 @@ + + diff --git a/tenant-platform/src/views/update/VersionManagementView.vue b/tenant-platform/src/views/update/VersionManagementView.vue index f92e898..e7c3d47 100644 --- a/tenant-platform/src/views/update/VersionManagementView.vue +++ b/tenant-platform/src/views/update/VersionManagementView.vue @@ -1,7 +1,15 @@