feat(sdk): 添加鸿蒙SDK核心功能模块
- 实现SDKContext用于配置管理和数据持久化存储 - 定义完整的类型系统包括消息、用户、群组等接口 - 集成更新SDK支持原生应用和RN热更新检查 - 提供统一的XuqmSDK入口类和模块导出 - 编写详细的开发文档和使用示例
这个提交包含在:
父节点
470521c3a8
当前提交
e47f510a0b
3
tenant-platform/components.d.ts
vendored
3
tenant-platform/components.d.ts
vendored
@ -15,6 +15,8 @@ declare module 'vue' {
|
||||
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
||||
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
|
||||
ElCol: typeof import('element-plus/es')['ElCol']
|
||||
ElCollapse: typeof import('element-plus/es')['ElCollapse']
|
||||
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
|
||||
ElContainer: typeof import('element-plus/es')['ElContainer']
|
||||
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
||||
ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
|
||||
@ -29,6 +31,7 @@ declare module 'vue' {
|
||||
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||
ElHeader: typeof import('element-plus/es')['ElHeader']
|
||||
ElIcon: typeof import('element-plus/es')['ElIcon']
|
||||
ElImage: typeof import('element-plus/es')['ElImage']
|
||||
ElInput: typeof import('element-plus/es')['ElInput']
|
||||
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
|
||||
ElLink: typeof import('element-plus/es')['ElLink']
|
||||
|
||||
@ -39,8 +39,31 @@ updateClient.interceptors.request.use((config) => {
|
||||
return config
|
||||
})
|
||||
|
||||
export type StoreType = 'HUAWEI' | 'MI' | 'OPPO' | 'VIVO' | 'HONOR' | 'APP_STORE' | 'GOOGLE_PLAY'
|
||||
export type StoreType = 'HUAWEI' | 'MI' | 'OPPO' | 'VIVO' | 'HONOR' | 'APP_STORE' | 'GOOGLE_PLAY' | 'HARMONY_APP' | 'REVIEW_WEBHOOK'
|
||||
export type StoreReviewState = 'PENDING' | 'UNDER_REVIEW' | 'APPROVED' | 'REJECTED'
|
||||
export type PublishMode = 'MANUAL' | 'NOW' | 'SCHEDULED' | 'AUTO_REVIEW'
|
||||
export type GrayMode = 'PERCENT' | 'MEMBERS'
|
||||
export type GraySelectionSource = 'LOCAL' | 'CALLBACK'
|
||||
|
||||
export interface PublishConfig {
|
||||
id: string
|
||||
appId: string
|
||||
configJson?: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export interface GrayMember {
|
||||
userId: string
|
||||
name?: string
|
||||
groupName?: string
|
||||
extraJson?: string
|
||||
updatedAt?: string
|
||||
}
|
||||
|
||||
export interface GrayMemberGroup {
|
||||
groupName: string
|
||||
members: GrayMember[]
|
||||
}
|
||||
|
||||
export interface StoreConfig {
|
||||
id: string
|
||||
@ -71,6 +94,10 @@ export interface AppVersion {
|
||||
webhookUrl?: string
|
||||
storeSubmitTargets?: string
|
||||
storeReviewStatus?: string
|
||||
storeSubmitMode?: PublishMode
|
||||
storeSubmitScheduledAt?: string
|
||||
grayMode?: GrayMode
|
||||
grayMemberIds?: string
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
@ -94,8 +121,12 @@ export interface RnBundle {
|
||||
packageName?: string
|
||||
note?: string
|
||||
publishStatus: 'DRAFT' | 'PUBLISHED' | 'DEPRECATED'
|
||||
publishMode?: PublishMode
|
||||
scheduledPublishAt?: string
|
||||
grayEnabled: boolean
|
||||
grayPercent: number
|
||||
grayMode?: GrayMode
|
||||
grayMemberIds?: string
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
@ -144,16 +175,22 @@ export const updateAdminApi = {
|
||||
})
|
||||
},
|
||||
|
||||
publishAppVersion(id: string) {
|
||||
return updateClient.post(`/api/v1/updates/app/${id}/publish`)
|
||||
publishAppVersion(id: string, body?: { publishImmediately?: boolean; scheduledPublishAt?: string; forceUpdate?: boolean }) {
|
||||
return updateClient.post(`/api/v1/updates/app/${id}/publish`, body ?? {})
|
||||
},
|
||||
|
||||
unpublishAppVersion(id: string) {
|
||||
return updateClient.post(`/api/v1/updates/app/${id}/unpublish`)
|
||||
},
|
||||
|
||||
grayAppVersion(id: string, enabled: boolean, percent: number) {
|
||||
return updateClient.post(`/api/v1/updates/app/${id}/gray`, { enabled, percent })
|
||||
grayAppVersion(id: string, body: {
|
||||
enabled: boolean
|
||||
grayMode: GrayMode
|
||||
percent?: number
|
||||
memberIds?: string[]
|
||||
selectionSource?: GraySelectionSource
|
||||
}) {
|
||||
return updateClient.post(`/api/v1/updates/app/${id}/gray`, body)
|
||||
},
|
||||
|
||||
uploadAppVersion(formData: FormData) {
|
||||
@ -172,16 +209,22 @@ export const updateAdminApi = {
|
||||
})
|
||||
},
|
||||
|
||||
publishRnBundle(id: string) {
|
||||
return updateClient.post(`/api/v1/rn/${id}/publish`)
|
||||
publishRnBundle(id: string, body?: { publishImmediately?: boolean; scheduledPublishAt?: string }) {
|
||||
return updateClient.post(`/api/v1/rn/${id}/publish`, body ?? {})
|
||||
},
|
||||
|
||||
unpublishRnBundle(id: string) {
|
||||
return updateClient.post(`/api/v1/rn/${id}/unpublish`)
|
||||
},
|
||||
|
||||
grayRnBundle(id: string, enabled: boolean, percent: number) {
|
||||
return updateClient.post(`/api/v1/rn/${id}/gray`, { enabled, percent })
|
||||
grayRnBundle(id: string, body: {
|
||||
enabled: boolean
|
||||
grayMode: GrayMode
|
||||
percent?: number
|
||||
memberIds?: string[]
|
||||
selectionSource?: GraySelectionSource
|
||||
}) {
|
||||
return updateClient.post(`/api/v1/rn/${id}/gray`, body)
|
||||
},
|
||||
|
||||
uploadRnBundle(formData: FormData) {
|
||||
@ -214,10 +257,16 @@ export const updateAdminApi = {
|
||||
return updateClient.delete(`/api/v1/updates/store/configs/${storeType}`, { params: { appId } })
|
||||
},
|
||||
|
||||
executeSubmitToStores(versionId: string, storeTypes: StoreType[]) {
|
||||
executeSubmitToStores(
|
||||
versionId: string,
|
||||
storeTypes: StoreType[],
|
||||
submitMode: PublishMode = 'MANUAL',
|
||||
scheduledPublishAt?: string,
|
||||
autoPublishAfterReview = false,
|
||||
) {
|
||||
return updateClient.post<{ data: AppVersion }>(
|
||||
`/api/v1/updates/store/app/${versionId}/execute-submit`,
|
||||
{ storeTypes },
|
||||
{ storeTypes, submitMode, scheduledPublishAt, autoPublishAfterReview },
|
||||
)
|
||||
},
|
||||
|
||||
@ -227,4 +276,24 @@ export const updateAdminApi = {
|
||||
{ storeType, state },
|
||||
)
|
||||
},
|
||||
|
||||
getPublishConfig(appId: string) {
|
||||
return updateClient.get<{ data: PublishConfig }>('/api/v1/updates/publish/config', { params: { appId } })
|
||||
},
|
||||
|
||||
savePublishConfig(appId: string, config: Record<string, unknown>) {
|
||||
return updateClient.put<{ data: PublishConfig }>('/api/v1/updates/publish/config', config, { params: { appId } })
|
||||
},
|
||||
|
||||
listGrayMembers(appId: string, keyword?: string, groupName?: string) {
|
||||
return updateClient.get<{ data: GrayMemberGroup[] }>('/api/v1/updates/gray/members', {
|
||||
params: { appId, ...(keyword && { keyword }), ...(groupName && { groupName }) },
|
||||
})
|
||||
},
|
||||
|
||||
syncGrayMembers(appId: string) {
|
||||
return updateClient.post<{ data: GrayMemberGroup[] }>('/api/v1/updates/gray/members/sync', null, {
|
||||
params: { appId },
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
@ -53,10 +53,6 @@ const router = createRouter({
|
||||
path: 'apps/:appId/update',
|
||||
component: () => import('@/views/update/VersionManagementView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'apps/:appId/update-guide',
|
||||
component: () => import('@/views/update/StoreGuideView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'accounts',
|
||||
component: () => import('@/views/accounts/SubAccountView.vue'),
|
||||
|
||||
@ -60,9 +60,9 @@
|
||||
<el-card v-for="svcType in ['PUSH', 'UPDATE']" :key="svcType" class="service-card">
|
||||
<div class="service-header">
|
||||
<div class="service-title-block">
|
||||
<span class="service-name">{{ serviceLabel(svcType) }}</span>
|
||||
<span class="service-help">{{ serviceHelp(svcType) }}</span>
|
||||
</div>
|
||||
<span class="service-name">{{ serviceLabel(svcType) }}</span>
|
||||
<span class="service-help">{{ serviceHelp(svcType) }}</span>
|
||||
</div>
|
||||
<el-switch
|
||||
:model-value="isServiceEnabled(svcType)"
|
||||
@change="(val: boolean) => onToggleService(svcType, val)"
|
||||
@ -74,7 +74,7 @@
|
||||
</el-tag>
|
||||
<span class="service-status-text">
|
||||
{{ svcType === 'UPDATE'
|
||||
? 'Android / iOS / 鸿蒙版本在版本管理页内分别配置。'
|
||||
? 'Android 整包版本在版本管理页上传;iOS / 鸿蒙仅记录版本号和市场跳转页。商店配置与发布配置都在版本管理页。'
|
||||
: '推送服务开通后即可在终端接收设备级推送。' }}
|
||||
</span>
|
||||
</div>
|
||||
@ -169,7 +169,7 @@ function serviceHelp(type: string) {
|
||||
return {
|
||||
IM: 'IM 服务独立开通后,在管理页配置回调和消息能力。',
|
||||
PUSH: '一次开通后,推送配置在服务管理页按平台维护。',
|
||||
UPDATE: '一次开通后,版本管理页按平台维护版本和发布。',
|
||||
UPDATE: '一次开通后,版本管理页只管理 Android 整包版本,iOS / 鸿蒙仅记录提醒信息。',
|
||||
}[type] ?? ''
|
||||
}
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<el-page-header @back="$router.back()" :content="`应用配置指引 — ${appId}`" />
|
||||
|
||||
<el-alert
|
||||
title="这里是应用商店配置的独立指引页。建议先完成凭据配置,再回到版本管理页提交审核。Harmony 应用仅跳转应用市场,不做本地安装。"
|
||||
title="这里是应用商店配置的独立指引页。建议先完成凭据配置和市场跳转页,再回到版本管理页提交审核。Harmony 应用仅跳转应用市场,不做本地安装。"
|
||||
type="info"
|
||||
show-icon
|
||||
:closable="false"
|
||||
@ -117,6 +117,20 @@ const STORE_GUIDES = [
|
||||
image: honorGuideImage,
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
type: 'HARMONY_APP',
|
||||
label: '鸿蒙应用',
|
||||
subtitle: '鸿蒙应用市场独立跳转页',
|
||||
url: 'https://developer.huawei.com/consumer/cn/',
|
||||
urlLabel: '查看鸿蒙官方文档',
|
||||
steps: [
|
||||
{ title: '确认鸿蒙应用页', description: '准备独立的鸿蒙应用市场详情页。' },
|
||||
{ title: '复制跳转链接', description: '把市场详情页链接填写到应用商店配置。' },
|
||||
{ title: '回到版本管理页', description: '鸿蒙版本仅记录版本号和跳转页。' },
|
||||
],
|
||||
hint: '鸿蒙应用配置只维护市场跳转页,不参与 Android 审核上传。',
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
type: 'APP_STORE',
|
||||
label: 'Apple App Store',
|
||||
|
||||
文件差异内容过多而无法显示
加载差异
正在加载...
在新工单中引用
屏蔽一个用户