XuqmGroup-Web/tenant-platform/src/api/update.ts

300 行
8.4 KiB
TypeScript

import axios from 'axios'
const updateClient = axios.create({
baseURL: 'http://192.168.116.9:8084',
timeout: 30000,
})
if (import.meta.env.DEV) {
updateClient.interceptors.request.use((config) => {
console.debug('[tenant-platform][UPDATE] request', {
method: config.method?.toUpperCase(),
url: config.baseURL ? `${config.baseURL}${config.url ?? ''}` : config.url,
params: config.params,
})
return config
})
updateClient.interceptors.response.use((res) => {
console.debug('[tenant-platform][UPDATE] response', {
status: res.status,
url: res.config.url,
})
return res
})
}
updateClient.interceptors.request.use((config) => {
const url = config.url ?? ''
const skipAuth = (
url.startsWith('/api/v1/updates/app/check') ||
url.startsWith('/api/v1/updates/app/inspect') ||
url.startsWith('/api/v1/rn/update/check') ||
url.startsWith('/api/v1/rn/inspect') ||
url.startsWith('/api/v1/rn/files/')
)
if (!skipAuth) {
const token = localStorage.getItem('token')
if (token) config.headers.Authorization = `Bearer ${token}`
}
return config
})
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
appId: string
storeType: StoreType
configJson?: string
enabled: boolean
updatedAt: string
}
export interface AppVersion {
id: string
appId: string
platform: 'ANDROID' | 'IOS' | 'HARMONY'
versionName: string
versionCode: number
packageName?: string
downloadUrl?: string
changeLog?: string
forceUpdate: boolean
publishStatus: 'DRAFT' | 'PUBLISHED' | 'DEPRECATED'
grayEnabled: boolean
grayPercent: number
appStoreUrl?: string
marketUrl?: string
scheduledPublishAt?: string
autoPublishAfterReview: boolean
webhookUrl?: string
storeSubmitTargets?: string
storeReviewStatus?: string
storeSubmitMode?: PublishMode
storeSubmitScheduledAt?: string
grayMode?: GrayMode
grayMemberIds?: string
createdAt: string
}
export interface AppPackageInspectResult {
platform: 'ANDROID' | 'IOS' | 'HARMONY'
packageName?: string
versionName?: string
versionCode?: number
fileName?: string
detected: boolean
}
export interface RnBundle {
id: string
appId: string
moduleId: string
platform: 'ANDROID' | 'IOS' | 'HARMONY'
version: string
md5: string
minCommonVersion?: string
packageName?: string
note?: string
publishStatus: 'DRAFT' | 'PUBLISHED' | 'DEPRECATED'
publishMode?: PublishMode
scheduledPublishAt?: string
grayEnabled: boolean
grayPercent: number
grayMode?: GrayMode
grayMemberIds?: string
createdAt: string
}
export interface RnBundleInspectResult {
moduleId?: string
platform?: 'ANDROID' | 'IOS' | 'HARMONY'
version?: string
minCommonVersion?: string
packageName?: string
fileName?: string
detected: boolean
}
export interface UnifiedAppUploadItem {
fileKey: string
platform: 'ANDROID' | 'IOS' | 'HARMONY'
versionName: string
versionCode: number
changeLog?: string
forceUpdate: boolean
packageName?: string
appStoreUrl?: string
marketUrl?: string
publishImmediately: boolean
}
export interface UnifiedRnUploadItem {
fileKey: string
moduleId: string
platform: 'ANDROID' | 'IOS' | 'HARMONY'
version: string
minCommonVersion?: string
packageName?: string
note?: string
}
export interface UnifiedReleaseManifest {
appVersions: UnifiedAppUploadItem[]
rnBundles: UnifiedRnUploadItem[]
}
export const updateAdminApi = {
listAppVersions(appId: string, platform: 'ANDROID' | 'IOS' | 'HARMONY') {
return updateClient.get<{ data: AppVersion[] }>('/api/v1/updates/app/list', {
params: { appId, platform },
})
},
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, body: {
enabled: boolean
grayMode: GrayMode
percent?: number
memberIds?: string[]
selectionSource?: GraySelectionSource
}) {
return updateClient.post(`/api/v1/updates/app/${id}/gray`, body)
},
uploadAppVersion(formData: FormData) {
return updateClient.post<{ data: AppVersion }>('/api/v1/updates/app/upload', formData)
},
inspectAppPackage(apkUrl: string) {
return updateClient.get<{ data: AppPackageInspectResult }>('/api/v1/updates/app/inspect', {
params: { apkUrl },
})
},
listRnBundles(appId: string, moduleId?: string, platform?: string) {
return updateClient.get<{ data: RnBundle[] }>('/api/v1/rn/list', {
params: { appId, ...(moduleId && { moduleId }), ...(platform && { platform }) },
})
},
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, body: {
enabled: boolean
grayMode: GrayMode
percent?: number
memberIds?: string[]
selectionSource?: GraySelectionSource
}) {
return updateClient.post(`/api/v1/rn/${id}/gray`, body)
},
uploadRnBundle(formData: FormData) {
return updateClient.post<{ data: RnBundle }>('/api/v1/rn/upload', formData)
},
inspectRnBundle(formData: FormData) {
return updateClient.post<{ data: RnBundleInspectResult }>('/api/v1/rn/inspect', formData)
},
uploadUnifiedRelease(formData: FormData) {
return updateClient.post('/api/v1/updates/unified/upload', formData)
},
// ── Store config ────────────────────────────────────────────────────────
getStoreConfigs(appId: string) {
return updateClient.get<{ data: StoreConfig[] }>('/api/v1/updates/store/configs', { params: { appId } })
},
saveStoreConfig(appId: string, storeType: StoreType, configJson: string, enabled: boolean) {
return updateClient.put<{ data: StoreConfig }>(
`/api/v1/updates/store/configs/${storeType}`,
{ configJson, enabled },
{ params: { appId } },
)
},
deleteStoreConfig(appId: string, storeType: StoreType) {
return updateClient.delete(`/api/v1/updates/store/configs/${storeType}`, { params: { appId } })
},
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, submitMode, scheduledPublishAt, autoPublishAfterReview },
)
},
updateStoreReview(versionId: string, storeType: StoreType, state: StoreReviewState) {
return updateClient.post<{ data: AppVersion }>(
`/api/v1/updates/store/app/${versionId}/review`,
{ 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 },
})
},
}