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']
|
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
||||||
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
|
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
|
||||||
ElCol: typeof import('element-plus/es')['ElCol']
|
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']
|
ElContainer: typeof import('element-plus/es')['ElContainer']
|
||||||
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
||||||
ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
|
ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
|
||||||
@ -29,6 +31,7 @@ declare module 'vue' {
|
|||||||
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||||
ElHeader: typeof import('element-plus/es')['ElHeader']
|
ElHeader: typeof import('element-plus/es')['ElHeader']
|
||||||
ElIcon: typeof import('element-plus/es')['ElIcon']
|
ElIcon: typeof import('element-plus/es')['ElIcon']
|
||||||
|
ElImage: typeof import('element-plus/es')['ElImage']
|
||||||
ElInput: typeof import('element-plus/es')['ElInput']
|
ElInput: typeof import('element-plus/es')['ElInput']
|
||||||
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
|
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
|
||||||
ElLink: typeof import('element-plus/es')['ElLink']
|
ElLink: typeof import('element-plus/es')['ElLink']
|
||||||
|
|||||||
@ -39,8 +39,31 @@ updateClient.interceptors.request.use((config) => {
|
|||||||
return 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 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 {
|
export interface StoreConfig {
|
||||||
id: string
|
id: string
|
||||||
@ -71,6 +94,10 @@ export interface AppVersion {
|
|||||||
webhookUrl?: string
|
webhookUrl?: string
|
||||||
storeSubmitTargets?: string
|
storeSubmitTargets?: string
|
||||||
storeReviewStatus?: string
|
storeReviewStatus?: string
|
||||||
|
storeSubmitMode?: PublishMode
|
||||||
|
storeSubmitScheduledAt?: string
|
||||||
|
grayMode?: GrayMode
|
||||||
|
grayMemberIds?: string
|
||||||
createdAt: string
|
createdAt: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,8 +121,12 @@ export interface RnBundle {
|
|||||||
packageName?: string
|
packageName?: string
|
||||||
note?: string
|
note?: string
|
||||||
publishStatus: 'DRAFT' | 'PUBLISHED' | 'DEPRECATED'
|
publishStatus: 'DRAFT' | 'PUBLISHED' | 'DEPRECATED'
|
||||||
|
publishMode?: PublishMode
|
||||||
|
scheduledPublishAt?: string
|
||||||
grayEnabled: boolean
|
grayEnabled: boolean
|
||||||
grayPercent: number
|
grayPercent: number
|
||||||
|
grayMode?: GrayMode
|
||||||
|
grayMemberIds?: string
|
||||||
createdAt: string
|
createdAt: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,16 +175,22 @@ export const updateAdminApi = {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
publishAppVersion(id: string) {
|
publishAppVersion(id: string, body?: { publishImmediately?: boolean; scheduledPublishAt?: string; forceUpdate?: boolean }) {
|
||||||
return updateClient.post(`/api/v1/updates/app/${id}/publish`)
|
return updateClient.post(`/api/v1/updates/app/${id}/publish`, body ?? {})
|
||||||
},
|
},
|
||||||
|
|
||||||
unpublishAppVersion(id: string) {
|
unpublishAppVersion(id: string) {
|
||||||
return updateClient.post(`/api/v1/updates/app/${id}/unpublish`)
|
return updateClient.post(`/api/v1/updates/app/${id}/unpublish`)
|
||||||
},
|
},
|
||||||
|
|
||||||
grayAppVersion(id: string, enabled: boolean, percent: number) {
|
grayAppVersion(id: string, body: {
|
||||||
return updateClient.post(`/api/v1/updates/app/${id}/gray`, { enabled, percent })
|
enabled: boolean
|
||||||
|
grayMode: GrayMode
|
||||||
|
percent?: number
|
||||||
|
memberIds?: string[]
|
||||||
|
selectionSource?: GraySelectionSource
|
||||||
|
}) {
|
||||||
|
return updateClient.post(`/api/v1/updates/app/${id}/gray`, body)
|
||||||
},
|
},
|
||||||
|
|
||||||
uploadAppVersion(formData: FormData) {
|
uploadAppVersion(formData: FormData) {
|
||||||
@ -172,16 +209,22 @@ export const updateAdminApi = {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
publishRnBundle(id: string) {
|
publishRnBundle(id: string, body?: { publishImmediately?: boolean; scheduledPublishAt?: string }) {
|
||||||
return updateClient.post(`/api/v1/rn/${id}/publish`)
|
return updateClient.post(`/api/v1/rn/${id}/publish`, body ?? {})
|
||||||
},
|
},
|
||||||
|
|
||||||
unpublishRnBundle(id: string) {
|
unpublishRnBundle(id: string) {
|
||||||
return updateClient.post(`/api/v1/rn/${id}/unpublish`)
|
return updateClient.post(`/api/v1/rn/${id}/unpublish`)
|
||||||
},
|
},
|
||||||
|
|
||||||
grayRnBundle(id: string, enabled: boolean, percent: number) {
|
grayRnBundle(id: string, body: {
|
||||||
return updateClient.post(`/api/v1/rn/${id}/gray`, { enabled, percent })
|
enabled: boolean
|
||||||
|
grayMode: GrayMode
|
||||||
|
percent?: number
|
||||||
|
memberIds?: string[]
|
||||||
|
selectionSource?: GraySelectionSource
|
||||||
|
}) {
|
||||||
|
return updateClient.post(`/api/v1/rn/${id}/gray`, body)
|
||||||
},
|
},
|
||||||
|
|
||||||
uploadRnBundle(formData: FormData) {
|
uploadRnBundle(formData: FormData) {
|
||||||
@ -214,10 +257,16 @@ export const updateAdminApi = {
|
|||||||
return updateClient.delete(`/api/v1/updates/store/configs/${storeType}`, { params: { appId } })
|
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 }>(
|
return updateClient.post<{ data: AppVersion }>(
|
||||||
`/api/v1/updates/store/app/${versionId}/execute-submit`,
|
`/api/v1/updates/store/app/${versionId}/execute-submit`,
|
||||||
{ storeTypes },
|
{ storeTypes, submitMode, scheduledPublishAt, autoPublishAfterReview },
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -227,4 +276,24 @@ export const updateAdminApi = {
|
|||||||
{ storeType, state },
|
{ 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',
|
path: 'apps/:appId/update',
|
||||||
component: () => import('@/views/update/VersionManagementView.vue'),
|
component: () => import('@/views/update/VersionManagementView.vue'),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: 'apps/:appId/update-guide',
|
|
||||||
component: () => import('@/views/update/StoreGuideView.vue'),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: 'accounts',
|
path: 'accounts',
|
||||||
component: () => import('@/views/accounts/SubAccountView.vue'),
|
component: () => import('@/views/accounts/SubAccountView.vue'),
|
||||||
|
|||||||
@ -74,7 +74,7 @@
|
|||||||
</el-tag>
|
</el-tag>
|
||||||
<span class="service-status-text">
|
<span class="service-status-text">
|
||||||
{{ svcType === 'UPDATE'
|
{{ svcType === 'UPDATE'
|
||||||
? 'Android / iOS / 鸿蒙版本在版本管理页内分别配置。'
|
? 'Android 整包版本在版本管理页上传;iOS / 鸿蒙仅记录版本号和市场跳转页。商店配置与发布配置都在版本管理页。'
|
||||||
: '推送服务开通后即可在终端接收设备级推送。' }}
|
: '推送服务开通后即可在终端接收设备级推送。' }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@ -169,7 +169,7 @@ function serviceHelp(type: string) {
|
|||||||
return {
|
return {
|
||||||
IM: 'IM 服务独立开通后,在管理页配置回调和消息能力。',
|
IM: 'IM 服务独立开通后,在管理页配置回调和消息能力。',
|
||||||
PUSH: '一次开通后,推送配置在服务管理页按平台维护。',
|
PUSH: '一次开通后,推送配置在服务管理页按平台维护。',
|
||||||
UPDATE: '一次开通后,版本管理页按平台维护版本和发布。',
|
UPDATE: '一次开通后,版本管理页只管理 Android 整包版本,iOS / 鸿蒙仅记录提醒信息。',
|
||||||
}[type] ?? ''
|
}[type] ?? ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
<el-page-header @back="$router.back()" :content="`应用配置指引 — ${appId}`" />
|
<el-page-header @back="$router.back()" :content="`应用配置指引 — ${appId}`" />
|
||||||
|
|
||||||
<el-alert
|
<el-alert
|
||||||
title="这里是应用商店配置的独立指引页。建议先完成凭据配置,再回到版本管理页提交审核。Harmony 应用仅跳转应用市场,不做本地安装。"
|
title="这里是应用商店配置的独立指引页。建议先完成凭据配置和市场跳转页,再回到版本管理页提交审核。Harmony 应用仅跳转应用市场,不做本地安装。"
|
||||||
type="info"
|
type="info"
|
||||||
show-icon
|
show-icon
|
||||||
:closable="false"
|
:closable="false"
|
||||||
@ -117,6 +117,20 @@ const STORE_GUIDES = [
|
|||||||
image: honorGuideImage,
|
image: honorGuideImage,
|
||||||
enabled: true,
|
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',
|
type: 'APP_STORE',
|
||||||
label: 'Apple App Store',
|
label: 'Apple App Store',
|
||||||
|
|||||||
文件差异内容过多而无法显示
加载差异
正在加载...
在新工单中引用
屏蔽一个用户