一大波改动
这个提交包含在:
父节点
460ba5f112
当前提交
66801ca26c
@ -1 +0,0 @@
|
|||||||
../XuqmGroup-Web/node_modules
|
|
||||||
2233
package-lock.json
自动生成的
普通文件
2233
package-lock.json
自动生成的
普通文件
文件差异内容过多而无法显示
加载差异
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@xuqm/vue3-sdk",
|
"name": "@xuqm/vue3-sdk",
|
||||||
"version": "0.2.0",
|
"version": "0.2.2",
|
||||||
"description": "XuqmGroup Vue3 SDK — IM & platform integration for web",
|
"description": "XuqmGroup Vue3 SDK — IM & platform integration for web",
|
||||||
"private": false,
|
"private": false,
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
export const DEFAULT_API_BASE_URL = 'https://dev.xuqinmin.com'
|
export const DEFAULT_API_BASE_URL = 'https://dev.xuqinmin.com'
|
||||||
export const DEFAULT_IM_WS_URL = 'wss://dev.xuqinmin.com/ws/im'
|
export const DEFAULT_IM_WS_URL = 'wss://im.dev.xuqinmin.com/ws/im'
|
||||||
|
|||||||
@ -44,6 +44,13 @@ export class ImClient {
|
|||||||
private listeners: { [K in keyof ImEventMap]?: Set<EventListener<K>> } = {}
|
private listeners: { [K in keyof ImEventMap]?: Set<EventListener<K>> } = {}
|
||||||
private subscriptionSeed = 0
|
private subscriptionSeed = 0
|
||||||
private subscriptions = new Map<string, string>() // destination -> id
|
private subscriptions = new Map<string, string>() // destination -> id
|
||||||
|
private readonly tokenOverride: (() => string | null) | null
|
||||||
|
private readonly wsUrlOverride: string | null
|
||||||
|
|
||||||
|
constructor(options?: { tokenSupplier?: () => string | null; wsUrl?: string }) {
|
||||||
|
this.tokenOverride = options?.tokenSupplier ?? null
|
||||||
|
this.wsUrlOverride = options?.wsUrl ?? null
|
||||||
|
}
|
||||||
|
|
||||||
on<K extends keyof ImEventMap>(event: K, handler: EventListener<K>): this {
|
on<K extends keyof ImEventMap>(event: K, handler: EventListener<K>): this {
|
||||||
const store = this.listeners as Record<string, Set<unknown>>
|
const store = this.listeners as Record<string, Set<unknown>>
|
||||||
@ -66,9 +73,10 @@ export class ImClient {
|
|||||||
|
|
||||||
connect(): void {
|
connect(): void {
|
||||||
if (this.destroyed) return
|
if (this.destroyed) return
|
||||||
const config = getConfig()
|
const config = (() => { try { return getConfig() } catch { return { debug: false, wsUrl: '', appKey: '' } } })()
|
||||||
const token = getToken()
|
const token = this.tokenOverride ? this.tokenOverride() : getToken()
|
||||||
const url = `${config.wsUrl || DEFAULT_IM_WS_URL}?token=${token ?? ''}`
|
const baseWsUrl = this.wsUrlOverride ?? config.wsUrl ?? DEFAULT_IM_WS_URL
|
||||||
|
const url = `${baseWsUrl || DEFAULT_IM_WS_URL}?token=${token ?? ''}`
|
||||||
|
|
||||||
this.ws = new WebSocket(url)
|
this.ws = new WebSocket(url)
|
||||||
let buffer = ''
|
let buffer = ''
|
||||||
|
|||||||
@ -0,0 +1,81 @@
|
|||||||
|
import { ref, onUnmounted } from 'vue'
|
||||||
|
import { ImClient } from './ImClient'
|
||||||
|
import type { ImMessage } from '../types'
|
||||||
|
|
||||||
|
export interface StoreReviewNotification {
|
||||||
|
event: string
|
||||||
|
appKey: string
|
||||||
|
versionId: string
|
||||||
|
storeType: string
|
||||||
|
reviewState: string
|
||||||
|
reviewReason: string
|
||||||
|
stage: string
|
||||||
|
batchId: string
|
||||||
|
publishStatus: string
|
||||||
|
source: string
|
||||||
|
timestamp: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UseStoreReviewNotificationOptions {
|
||||||
|
tokenSupplier: () => Promise<string>
|
||||||
|
onNotification: (notification: StoreReviewNotification) => void
|
||||||
|
wsUrl?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useStoreReviewNotification(options: UseStoreReviewNotificationOptions) {
|
||||||
|
const connected = ref(false)
|
||||||
|
const error = ref<string | null>(null)
|
||||||
|
let client: ImClient | null = null
|
||||||
|
let currentToken: string | null = null
|
||||||
|
|
||||||
|
async function connect() {
|
||||||
|
try {
|
||||||
|
currentToken = await options.tokenSupplier()
|
||||||
|
} catch (e) {
|
||||||
|
error.value = e instanceof Error ? e.message : 'Failed to fetch platform IM token'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
client = new ImClient({ tokenSupplier: () => currentToken, wsUrl: options.wsUrl })
|
||||||
|
|
||||||
|
client.on('connected', () => {
|
||||||
|
connected.value = true
|
||||||
|
error.value = null
|
||||||
|
})
|
||||||
|
|
||||||
|
client.on('disconnected', () => {
|
||||||
|
connected.value = false
|
||||||
|
})
|
||||||
|
|
||||||
|
client.on('error', (e) => {
|
||||||
|
error.value = e instanceof Error ? e.message : (e as Event).type ?? 'IM connection error'
|
||||||
|
})
|
||||||
|
|
||||||
|
client.on('message', (msg: ImMessage) => {
|
||||||
|
if (msg.msgType !== 'NOTIFY') return
|
||||||
|
try {
|
||||||
|
const payload =
|
||||||
|
typeof msg.content === 'string'
|
||||||
|
? (JSON.parse(msg.content) as StoreReviewNotification)
|
||||||
|
: (msg.content as unknown as StoreReviewNotification)
|
||||||
|
if (payload?.event === 'store_review_update') {
|
||||||
|
options.onNotification(payload)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// ignore malformed NOTIFY content
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
client.connect()
|
||||||
|
}
|
||||||
|
|
||||||
|
function disconnect() {
|
||||||
|
client?.disconnect()
|
||||||
|
client = null
|
||||||
|
connected.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
onUnmounted(disconnect)
|
||||||
|
|
||||||
|
return { connect, disconnect, connected, error }
|
||||||
|
}
|
||||||
@ -67,6 +67,8 @@ export {
|
|||||||
syncOfflineMessages,
|
syncOfflineMessages,
|
||||||
} from './im/api'
|
} from './im/api'
|
||||||
export { useIm } from './im/useIm'
|
export { useIm } from './im/useIm'
|
||||||
|
export { useStoreReviewNotification } from './im/useStoreReviewNotification'
|
||||||
|
export type { StoreReviewNotification, UseStoreReviewNotificationOptions } from './im/useStoreReviewNotification'
|
||||||
export type {
|
export type {
|
||||||
SDKConfig,
|
SDKConfig,
|
||||||
MsgType,
|
MsgType,
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户