362 lines
10 KiB
JavaScript
362 lines
10 KiB
JavaScript
/**
|
||
* 华为快应用 HwService JS SDK 统一封装
|
||
* 用于 H5 壳模式下的快应用环境,通过 hms-js-base 桥接层调用 HMS Core 服务
|
||
*
|
||
* 架构说明:
|
||
* - 所有 HMS 服务通过 @hw-hmscore/hms-js-base 的 hmsjsb.invoke() 统一桥接
|
||
* - Analytics Kit 有独立封装 @hw-hmscore/analytics-sdk-quickapp(可选安装)
|
||
* - Account Kit 无独立 quickapp npm 包,直接通过 hmsjsb.invoke 调用
|
||
* - Push Kit 无独立 quickapp npm 包,直接通过 hmsjsb.invoke 调用
|
||
*
|
||
* 使用方式:
|
||
* import HwService from '@/common/js/hw-jssdk.js'
|
||
*
|
||
* // 初始化
|
||
* await HwService.init()
|
||
*
|
||
* // 华为帐号登录
|
||
* const userInfo = await HwService.Account.signIn()
|
||
*
|
||
* // 分析服务埋点
|
||
* HwService.Analytics.onEvent('event_name', { key: 'value' })
|
||
*
|
||
* @version 1.1.0
|
||
*/
|
||
|
||
// hms-js-base 提供底层 JS Bridge 桥接能力
|
||
let hmsjsb = null
|
||
let hmsbase = null
|
||
|
||
// Analytics SDK 独立包(可选安装)
|
||
let HiAnalytics = null
|
||
|
||
// #ifdef H5_XCX_5G_QUICKAPP_COM || H5_XCX_AIGC_QUICKAPP_COM || H5_5G_AIGC_QUICKAPP_COM || H5_TEST_AIGC_QUICKAPP_COM
|
||
try {
|
||
// 加载基础桥接库(必装)
|
||
const hmsBase = require('@hw-hmscore/hms-js-base')
|
||
hmsjsb = hmsBase.hmsjsb
|
||
hmsbase = hmsBase.hmsbase
|
||
|
||
// 尝试加载 Analytics SDK(可选)
|
||
try {
|
||
HiAnalytics = require('@hw-hmscore/analytics-sdk-quickapp')
|
||
} catch (e) {
|
||
console.log('[HwService] Analytics SDK 未安装,将使用 invoke 桥接方式')
|
||
}
|
||
} catch (e) {
|
||
console.log('[HwService] hms-js-base 未安装或不在快应用环境')
|
||
}
|
||
// #endif
|
||
|
||
class HwService {
|
||
constructor() {
|
||
this._initialized = false
|
||
this._config = null
|
||
|
||
// 子服务实例
|
||
this.Account = null
|
||
this.Analytics = null
|
||
this.Push = null
|
||
}
|
||
|
||
/**
|
||
* 判断当前是否运行在快应用引擎环境
|
||
*/
|
||
isQuickAppEnv() {
|
||
// #ifdef H5_XCX_5G_QUICKAPP_COM || H5_XCX_AIGC_QUICKAPP_COM || H5_5G_AIGC_QUICKAPP_COM || H5_TEST_AIGC_QUICKAPP_COM
|
||
if (typeof window !== 'undefined') {
|
||
return !!(
|
||
window.qa ||
|
||
window.__HwService__ ||
|
||
window.hms ||
|
||
hmsjsb || // hms-js-base 加载成功
|
||
navigator.userAgent.indexOf('QuickApp') > -1
|
||
)
|
||
}
|
||
// #endif
|
||
return false
|
||
}
|
||
|
||
/**
|
||
* 初始化 HwService
|
||
* @param {Object} config { appId, clientId, clientSecret }
|
||
*/
|
||
async init(config = {}) {
|
||
if (this._initialized) {
|
||
console.log('[HwService] 已初始化,跳过')
|
||
return
|
||
}
|
||
|
||
this._config = config
|
||
console.log('[HwService] 开始初始化...')
|
||
|
||
try {
|
||
// 子服务实例化
|
||
this.Account = new AccountService(hmsjsb)
|
||
this.Analytics = new AnalyticsService(hmsjsb, HiAnalytics)
|
||
this.Push = new PushService(hmsjsb)
|
||
|
||
this._initialized = true
|
||
console.log('[HwService] 初始化完成')
|
||
} catch (error) {
|
||
console.error('[HwService] 初始化失败:', error)
|
||
throw error
|
||
}
|
||
}
|
||
}
|
||
|
||
// ============================================================
|
||
// 底层 invoke 封装
|
||
// ============================================================
|
||
|
||
/**
|
||
* 通过 hmsjsb.invoke 调用 HMS Core API 的 Promise 封装
|
||
* @param {Object} hmsjsbRef hmsjsb 引用
|
||
* @param {string} apiName API 名称
|
||
* @param {Object} args 参数
|
||
* @returns {Promise<Object>}
|
||
*/
|
||
function invokeHmsApi(hmsjsbRef, apiName, args = {}) {
|
||
return new Promise((resolve, reject) => {
|
||
if (!hmsjsbRef || typeof hmsjsbRef.invoke !== 'function') {
|
||
reject(new Error('[HwService] hmsjsb.invoke 不可用'))
|
||
return
|
||
}
|
||
hmsjsbRef.invoke({
|
||
apiName,
|
||
args,
|
||
success: (res) => resolve(res),
|
||
fail: (err) => reject(err)
|
||
})
|
||
})
|
||
}
|
||
|
||
// ============================================================
|
||
// 华为帐号服务 (Account Kit)
|
||
// 通过 hmsjsb.invoke 桥接(无独立 npm 包)
|
||
// ============================================================
|
||
class AccountService {
|
||
constructor(hmsjsbRef) {
|
||
this._hmsjsb = hmsjsbRef
|
||
}
|
||
|
||
/**
|
||
* 华为帐号登录
|
||
* @param {Array} scopes 授权范围
|
||
* @returns {Promise<Object>} 用户信息
|
||
*/
|
||
async signIn(scopes = ['openid', 'profile']) {
|
||
console.log('[HwService.Account] signIn...')
|
||
// apiName 需根据实际华为文档确认,常见值有:
|
||
// 'accountSignIn' | 'com.huawei.hms.api.Account.signIn'
|
||
const result = await invokeHmsApi(this._hmsjsb, 'accountSignIn', { scopes })
|
||
return this._formatUserInfo(result)
|
||
}
|
||
|
||
/**
|
||
* 静默获取华为帐号用户信息
|
||
*/
|
||
async getUserInfo() {
|
||
const result = await invokeHmsApi(this._hmsjsb, 'accountGetUserInfo', {})
|
||
return this._formatUserInfo(result)
|
||
}
|
||
|
||
/**
|
||
* 退出登录
|
||
*/
|
||
async signOut() {
|
||
try {
|
||
await invokeHmsApi(this._hmsjsb, 'accountSignOut', {})
|
||
} catch (e) {
|
||
console.warn('[HwService.Account] signOut 失败:', e)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 统一格式化用户信息
|
||
*/
|
||
_formatUserInfo(rawInfo) {
|
||
if (!rawInfo) return null
|
||
return {
|
||
openId: rawInfo.openId || rawInfo.openid || '',
|
||
unionId: rawInfo.unionId || rawInfo.unionid || '',
|
||
displayName: rawInfo.displayName || rawInfo.nickName || rawInfo.nickname || '',
|
||
avatarUrl: rawInfo.avatarUrl || rawInfo.avatar || rawInfo.headPictureUrl || '',
|
||
gender: rawInfo.gender || 0,
|
||
country: rawInfo.country || '',
|
||
province: rawInfo.province || '',
|
||
city: rawInfo.city || '',
|
||
raw: rawInfo
|
||
}
|
||
}
|
||
}
|
||
|
||
// ============================================================
|
||
// 华为分析服务 (Analytics Kit)
|
||
// 支持 @hw-hmscore/analytics-sdk-quickapp(优先)或 invoke 桥接
|
||
// ============================================================
|
||
class AnalyticsService {
|
||
constructor(hmsjsbRef, hiAnalyticsSdk) {
|
||
this._hmsjsb = hmsjsbRef
|
||
this._sdk = hiAnalyticsSdk
|
||
}
|
||
|
||
/**
|
||
* 上报事件
|
||
* @param {string} eventName 事件名称
|
||
* @param {Object} params 事件参数
|
||
*/
|
||
onEvent(eventName, params = {}) {
|
||
// 方案一:Analytics SDK(独立封装包)
|
||
if (this._sdk && typeof this._sdk.onEvent === 'function') {
|
||
this._sdk.onEvent(eventName, params)
|
||
return
|
||
}
|
||
if (this._sdk && typeof this._sdk.HiAnalytics?.getInstance === 'function') {
|
||
try {
|
||
const instance = this._sdk.HiAnalytics.getInstance()
|
||
instance.onEvent(eventName, params)
|
||
return
|
||
} catch (e) {
|
||
// fallthrough
|
||
}
|
||
}
|
||
// 方案二:invoke 桥接
|
||
if (this._hmsjsb) {
|
||
this._hmsjsb.invoke({
|
||
apiName: 'analyticsOnEvent',
|
||
args: { eventName, params },
|
||
success: () => {},
|
||
fail: (err) => console.warn('[HwService.Analytics] onEvent 失败:', err)
|
||
})
|
||
return
|
||
}
|
||
// fallback
|
||
console.log('[HwService.Analytics] onEvent (fallback):', eventName, params)
|
||
}
|
||
|
||
/**
|
||
* 设置用户属性
|
||
* @param {Object} profile
|
||
*/
|
||
setUserProfile(profile = {}) {
|
||
if (this._sdk && typeof this._sdk.setUserProfile === 'function') {
|
||
this._sdk.setUserProfile(profile)
|
||
return
|
||
}
|
||
if (this._sdk && typeof this._sdk.HiAnalytics?.getInstance === 'function') {
|
||
try {
|
||
const instance = this._sdk.HiAnalytics.getInstance()
|
||
instance.setUserProfile(profile)
|
||
return
|
||
} catch (e) {}
|
||
}
|
||
if (this._hmsjsb) {
|
||
this._hmsjsb.invoke({
|
||
apiName: 'analyticsSetUserProfile',
|
||
args: { profile },
|
||
success: () => {},
|
||
fail: (err) => console.warn('[HwService.Analytics] setUserProfile 失败:', err)
|
||
})
|
||
return
|
||
}
|
||
console.log('[HwService.Analytics] setUserProfile (fallback):', profile)
|
||
}
|
||
|
||
/**
|
||
* 设置用户 ID
|
||
* @param {string} userId
|
||
*/
|
||
setUserId(userId) {
|
||
if (this._sdk && typeof this._sdk.setUserId === 'function') {
|
||
this._sdk.setUserId(userId)
|
||
return
|
||
}
|
||
if (this._sdk && typeof this._sdk.HiAnalytics?.getInstance === 'function') {
|
||
try {
|
||
const instance = this._sdk.HiAnalytics.getInstance()
|
||
instance.setUserId(userId)
|
||
return
|
||
} catch (e) {}
|
||
}
|
||
if (this._hmsjsb) {
|
||
this._hmsjsb.invoke({
|
||
apiName: 'analyticsSetUserId',
|
||
args: { userId },
|
||
success: () => {},
|
||
fail: (err) => console.warn('[HwService.Analytics] setUserId 失败:', err)
|
||
})
|
||
return
|
||
}
|
||
console.log('[HwService.Analytics] setUserId (fallback):', userId)
|
||
}
|
||
|
||
/**
|
||
* 页面浏览事件
|
||
*/
|
||
onPageView(pageName, pageClassOverride = '') {
|
||
this.onEvent('$PageView', {
|
||
pageName,
|
||
pageClassOverride: pageClassOverride || pageName
|
||
})
|
||
}
|
||
}
|
||
|
||
// ============================================================
|
||
// 华为推送服务 (Push Kit)
|
||
// 通过 hmsjsb.invoke 桥接(无独立 npm 包)
|
||
// ============================================================
|
||
class PushService {
|
||
constructor(hmsjsbRef) {
|
||
this._hmsjsb = hmsjsbRef
|
||
this._token = null
|
||
}
|
||
|
||
/**
|
||
* 获取推送令牌
|
||
*/
|
||
async getToken() {
|
||
if (this._token) return this._token
|
||
try {
|
||
const result = await invokeHmsApi(this._hmsjsb, 'pushGetToken', {})
|
||
this._token = result.token || result
|
||
return this._token
|
||
} catch (e) {
|
||
console.warn('[HwService.Push] getToken 不可用:', e)
|
||
return null
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 监听推送令牌变更
|
||
*/
|
||
onTokenReceived(callback) {
|
||
if (!this._hmsjsb) return
|
||
this._hmsjsb.on('pushOnToken', callback)
|
||
}
|
||
|
||
/**
|
||
* 监听消息到达
|
||
*/
|
||
onMessageReceived(callback) {
|
||
if (!this._hmsjsb) return
|
||
this._hmsjsb.on('pushOnMessageReceived', callback)
|
||
}
|
||
|
||
/**
|
||
* 监听通知点击
|
||
*/
|
||
onNotificationClicked(callback) {
|
||
if (!this._hmsjsb) return
|
||
this._hmsjsb.on('pushOnNotificationClicked', callback)
|
||
}
|
||
}
|
||
|
||
// ============================================================
|
||
// 导出单例
|
||
// ============================================================
|
||
const hwService = new HwService()
|
||
export default hwService
|
||
|
||
export { AccountService, AnalyticsService, PushService }
|