703 lines
19 KiB
TypeScript
703 lines
19 KiB
TypeScript
|
|
import type {
|
|||
|
|
SystemDesktopSDK,
|
|||
|
|
SDKConfig,
|
|||
|
|
APIResponse,
|
|||
|
|
WindowSDK,
|
|||
|
|
StorageSDK,
|
|||
|
|
NetworkSDK,
|
|||
|
|
EventSDK,
|
|||
|
|
UISDK,
|
|||
|
|
SystemSDK,
|
|||
|
|
WindowState,
|
|||
|
|
WindowEvents,
|
|||
|
|
StorageEvents,
|
|||
|
|
NetworkRequestConfig,
|
|||
|
|
NetworkResponse,
|
|||
|
|
EventMessage,
|
|||
|
|
EventSubscriptionConfig,
|
|||
|
|
DialogOptions,
|
|||
|
|
NotificationOptions,
|
|||
|
|
FilePickerOptions,
|
|||
|
|
SystemInfo,
|
|||
|
|
AppInfo,
|
|||
|
|
PermissionStatus,
|
|||
|
|
} from './types'
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* SDK基础类
|
|||
|
|
*/
|
|||
|
|
abstract class SDKBase {
|
|||
|
|
protected appId: string = ''
|
|||
|
|
protected initialized: boolean = false
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 发送消息到系统
|
|||
|
|
*/
|
|||
|
|
protected sendToSystem<T = any>(type: string, data?: any): Promise<T> {
|
|||
|
|
return new Promise((resolve, reject) => {
|
|||
|
|
const requestId = Date.now().toString() + Math.random().toString(36).substr(2, 9)
|
|||
|
|
|
|||
|
|
const handler = (event: MessageEvent) => {
|
|||
|
|
if (event.data?.type === 'system:response' && event.data?.requestId === requestId) {
|
|||
|
|
window.removeEventListener('message', handler)
|
|||
|
|
if (event.data.success) {
|
|||
|
|
resolve(event.data.data)
|
|||
|
|
} else {
|
|||
|
|
reject(new Error(event.data.error || '系统调用失败'))
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
window.addEventListener('message', handler)
|
|||
|
|
|
|||
|
|
// 发送消息到父窗口(系统)
|
|||
|
|
window.parent.postMessage(
|
|||
|
|
{
|
|||
|
|
type: 'sdk:call',
|
|||
|
|
requestId,
|
|||
|
|
method: type,
|
|||
|
|
data,
|
|||
|
|
appId: this.appId,
|
|||
|
|
},
|
|||
|
|
'*',
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// 设置超时
|
|||
|
|
setTimeout(() => {
|
|||
|
|
window.removeEventListener('message', handler)
|
|||
|
|
reject(new Error('系统调用超时'))
|
|||
|
|
}, 10000)
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 包装API响应
|
|||
|
|
*/
|
|||
|
|
protected wrapResponse<T>(promise: Promise<T>): Promise<APIResponse<T>> {
|
|||
|
|
return promise
|
|||
|
|
.then((data) => ({ success: true, data }))
|
|||
|
|
.catch((error) => ({
|
|||
|
|
success: false,
|
|||
|
|
error: error.message || '未知错误',
|
|||
|
|
code: error.code || -1,
|
|||
|
|
}))
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 窗体SDK实现
|
|||
|
|
*/
|
|||
|
|
class WindowSDKImpl extends SDKBase implements WindowSDK {
|
|||
|
|
private eventListeners = new Map<keyof WindowEvents, Set<Function>>()
|
|||
|
|
|
|||
|
|
constructor(appId: string) {
|
|||
|
|
super()
|
|||
|
|
this.appId = appId
|
|||
|
|
this.setupEventListeners()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async setTitle(title: string): Promise<APIResponse<boolean>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('window.setTitle', { title }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async resize(width: number, height: number): Promise<APIResponse<boolean>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('window.resize', { width, height }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async move(x: number, y: number): Promise<APIResponse<boolean>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('window.move', { x, y }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async minimize(): Promise<APIResponse<boolean>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('window.minimize'))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async maximize(): Promise<APIResponse<boolean>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('window.maximize'))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async restore(): Promise<APIResponse<boolean>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('window.restore'))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async fullscreen(): Promise<APIResponse<boolean>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('window.fullscreen'))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async close(): Promise<APIResponse<boolean>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('window.close'))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async getState(): Promise<APIResponse<WindowState>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('window.getState'))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async getSize(): Promise<APIResponse<{ width: number; height: number }>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('window.getSize'))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async getPosition(): Promise<APIResponse<{ x: number; y: number }>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('window.getPosition'))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
on<K extends keyof WindowEvents>(event: K, callback: WindowEvents[K]): void {
|
|||
|
|
if (!this.eventListeners.has(event)) {
|
|||
|
|
this.eventListeners.set(event, new Set())
|
|||
|
|
}
|
|||
|
|
this.eventListeners.get(event)!.add(callback)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
off<K extends keyof WindowEvents>(event: K, callback?: WindowEvents[K]): void {
|
|||
|
|
if (callback) {
|
|||
|
|
this.eventListeners.get(event)?.delete(callback)
|
|||
|
|
} else {
|
|||
|
|
this.eventListeners.delete(event)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private setupEventListeners(): void {
|
|||
|
|
window.addEventListener('message', (event) => {
|
|||
|
|
if (event.data?.type?.startsWith('system:window:')) {
|
|||
|
|
const eventType = event.data.type.replace('system:window:', '') as keyof WindowEvents
|
|||
|
|
const listeners = this.eventListeners.get(eventType)
|
|||
|
|
if (listeners) {
|
|||
|
|
listeners.forEach((callback) => {
|
|||
|
|
try {
|
|||
|
|
callback(...(event.data.args || []))
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('窗体事件处理错误:', error)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 存储SDK实现
|
|||
|
|
*/
|
|||
|
|
class StorageSDKImpl extends SDKBase implements StorageSDK {
|
|||
|
|
private eventListeners = new Map<keyof StorageEvents, Set<Function>>()
|
|||
|
|
|
|||
|
|
constructor(appId: string) {
|
|||
|
|
super()
|
|||
|
|
this.appId = appId
|
|||
|
|
this.setupEventListeners()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async set(key: string, value: any): Promise<APIResponse<boolean>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('storage.set', { key, value }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async get<T = any>(key: string): Promise<APIResponse<T | null>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('storage.get', { key }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async remove(key: string): Promise<APIResponse<boolean>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('storage.remove', { key }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async clear(): Promise<APIResponse<boolean>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('storage.clear'))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async keys(): Promise<APIResponse<string[]>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('storage.keys'))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async has(key: string): Promise<APIResponse<boolean>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('storage.has', { key }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async getStats(): Promise<APIResponse<any>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('storage.getStats'))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
on<K extends keyof StorageEvents>(event: K, callback: StorageEvents[K]): void {
|
|||
|
|
if (!this.eventListeners.has(event)) {
|
|||
|
|
this.eventListeners.set(event, new Set())
|
|||
|
|
}
|
|||
|
|
this.eventListeners.get(event)!.add(callback)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
off<K extends keyof StorageEvents>(event: K, callback?: StorageEvents[K]): void {
|
|||
|
|
if (callback) {
|
|||
|
|
this.eventListeners.get(event)?.delete(callback)
|
|||
|
|
} else {
|
|||
|
|
this.eventListeners.delete(event)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private setupEventListeners(): void {
|
|||
|
|
window.addEventListener('message', (event) => {
|
|||
|
|
if (event.data?.type?.startsWith('system:storage:')) {
|
|||
|
|
const eventType = event.data.type.replace('system:storage:', '') as keyof StorageEvents
|
|||
|
|
const listeners = this.eventListeners.get(eventType)
|
|||
|
|
if (listeners) {
|
|||
|
|
listeners.forEach((callback) => {
|
|||
|
|
try {
|
|||
|
|
callback(...(event.data.args || []))
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('存储事件处理错误:', error)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 网络SDK实现
|
|||
|
|
*/
|
|||
|
|
class NetworkSDKImpl extends SDKBase implements NetworkSDK {
|
|||
|
|
constructor(appId: string) {
|
|||
|
|
super()
|
|||
|
|
this.appId = appId
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async request<T = any>(
|
|||
|
|
url: string,
|
|||
|
|
config?: NetworkRequestConfig,
|
|||
|
|
): Promise<APIResponse<NetworkResponse<T>>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('network.request', { url, config }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async get<T = any>(
|
|||
|
|
url: string,
|
|||
|
|
config?: Omit<NetworkRequestConfig, 'method'>,
|
|||
|
|
): Promise<APIResponse<NetworkResponse<T>>> {
|
|||
|
|
return this.request(url, { ...config, method: 'GET' })
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async post<T = any>(
|
|||
|
|
url: string,
|
|||
|
|
data?: any,
|
|||
|
|
config?: Omit<NetworkRequestConfig, 'method' | 'body'>,
|
|||
|
|
): Promise<APIResponse<NetworkResponse<T>>> {
|
|||
|
|
return this.request(url, { ...config, method: 'POST', body: data })
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async put<T = any>(
|
|||
|
|
url: string,
|
|||
|
|
data?: any,
|
|||
|
|
config?: Omit<NetworkRequestConfig, 'method' | 'body'>,
|
|||
|
|
): Promise<APIResponse<NetworkResponse<T>>> {
|
|||
|
|
return this.request(url, { ...config, method: 'PUT', body: data })
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async delete<T = any>(
|
|||
|
|
url: string,
|
|||
|
|
config?: Omit<NetworkRequestConfig, 'method'>,
|
|||
|
|
): Promise<APIResponse<NetworkResponse<T>>> {
|
|||
|
|
return this.request(url, { ...config, method: 'DELETE' })
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async upload(
|
|||
|
|
url: string,
|
|||
|
|
file: File | Blob,
|
|||
|
|
onProgress?: (loaded: number, total: number) => void,
|
|||
|
|
): Promise<APIResponse<NetworkResponse>> {
|
|||
|
|
return this.wrapResponse(
|
|||
|
|
this.sendToSystem('network.upload', { url, file, hasProgressCallback: !!onProgress }),
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async download(
|
|||
|
|
url: string,
|
|||
|
|
filename?: string,
|
|||
|
|
onProgress?: (loaded: number, total: number) => void,
|
|||
|
|
): Promise<APIResponse<Blob>> {
|
|||
|
|
return this.wrapResponse(
|
|||
|
|
this.sendToSystem('network.download', { url, filename, hasProgressCallback: !!onProgress }),
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async isOnline(): Promise<APIResponse<boolean>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('network.isOnline'))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async getStats(): Promise<
|
|||
|
|
APIResponse<{ requestCount: number; failureCount: number; averageTime: number }>
|
|||
|
|
> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('network.getStats'))
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 事件SDK实现
|
|||
|
|
*/
|
|||
|
|
class EventSDKImpl extends SDKBase implements EventSDK {
|
|||
|
|
private subscriptions = new Map<string, Function>()
|
|||
|
|
|
|||
|
|
constructor(appId: string) {
|
|||
|
|
super()
|
|||
|
|
this.appId = appId
|
|||
|
|
this.setupEventListeners()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async emit<T = any>(channel: string, data: T): Promise<APIResponse<string>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('events.emit', { channel, data }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async on<T = any>(
|
|||
|
|
channel: string,
|
|||
|
|
callback: (message: EventMessage<T>) => void,
|
|||
|
|
config?: EventSubscriptionConfig,
|
|||
|
|
): Promise<APIResponse<string>> {
|
|||
|
|
const result = await this.wrapResponse(this.sendToSystem('events.on', { channel, config }))
|
|||
|
|
|
|||
|
|
if (result.success && result.data) {
|
|||
|
|
this.subscriptions.set(result.data, callback)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return result
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async off(subscriptionId: string): Promise<APIResponse<boolean>> {
|
|||
|
|
const result = await this.wrapResponse(this.sendToSystem('events.off', { subscriptionId }))
|
|||
|
|
|
|||
|
|
if (result.success) {
|
|||
|
|
this.subscriptions.delete(subscriptionId)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return result
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async broadcast<T = any>(channel: string, data: T): Promise<APIResponse<string>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('events.broadcast', { channel, data }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async sendTo<T = any>(targetAppId: string, data: T): Promise<APIResponse<string>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('events.sendTo', { targetAppId, data }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async getSubscriberCount(channel: string): Promise<APIResponse<number>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('events.getSubscriberCount', { channel }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async getChannels(): Promise<APIResponse<string[]>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('events.getChannels'))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private setupEventListeners(): void {
|
|||
|
|
window.addEventListener('message', (event) => {
|
|||
|
|
if (event.data?.type === 'system:event' && event.data?.subscriptionId) {
|
|||
|
|
const callback = this.subscriptions.get(event.data.subscriptionId)
|
|||
|
|
if (callback) {
|
|||
|
|
try {
|
|||
|
|
callback(event.data.message)
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('事件回调处理错误:', error)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* UI SDK实现
|
|||
|
|
*/
|
|||
|
|
class UISDKImpl extends SDKBase implements UISDK {
|
|||
|
|
constructor(appId: string) {
|
|||
|
|
super()
|
|||
|
|
this.appId = appId
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async showDialog(
|
|||
|
|
options: DialogOptions,
|
|||
|
|
): Promise<APIResponse<{ buttonIndex: number; inputValue?: string }>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('ui.showDialog', options))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async showNotification(options: NotificationOptions): Promise<APIResponse<string>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('ui.showNotification', options))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async showFilePicker(options?: FilePickerOptions): Promise<APIResponse<FileList | null>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('ui.showFilePicker', options))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async showSaveDialog(defaultName?: string, accept?: string): Promise<APIResponse<string | null>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('ui.showSaveDialog', { defaultName, accept }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async showToast(
|
|||
|
|
message: string,
|
|||
|
|
type?: 'info' | 'success' | 'warning' | 'error',
|
|||
|
|
duration?: number,
|
|||
|
|
): Promise<APIResponse<string>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('ui.showToast', { message, type, duration }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async showLoading(message?: string): Promise<APIResponse<string>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('ui.showLoading', { message }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async hideLoading(id: string): Promise<APIResponse<boolean>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('ui.hideLoading', { id }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async showProgress(options: {
|
|||
|
|
title?: string
|
|||
|
|
message?: string
|
|||
|
|
progress: number
|
|||
|
|
}): Promise<APIResponse<string>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('ui.showProgress', options))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async updateProgress(
|
|||
|
|
id: string,
|
|||
|
|
progress: number,
|
|||
|
|
message?: string,
|
|||
|
|
): Promise<APIResponse<boolean>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('ui.updateProgress', { id, progress, message }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async hideProgress(id: string): Promise<APIResponse<boolean>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('ui.hideProgress', { id }))
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 系统SDK实现
|
|||
|
|
*/
|
|||
|
|
class SystemSDKImpl extends SDKBase implements SystemSDK {
|
|||
|
|
constructor(appId: string) {
|
|||
|
|
super()
|
|||
|
|
this.appId = appId
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async getSystemInfo(): Promise<APIResponse<SystemInfo>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('system.getSystemInfo'))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async getAppInfo(): Promise<APIResponse<AppInfo>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('system.getAppInfo'))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async requestPermission(
|
|||
|
|
permission: string,
|
|||
|
|
reason?: string,
|
|||
|
|
): Promise<APIResponse<PermissionStatus>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('system.requestPermission', { permission, reason }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async checkPermission(permission: string): Promise<APIResponse<PermissionStatus>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('system.checkPermission', { permission }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async getClipboard(): Promise<APIResponse<string>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('system.getClipboard'))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async setClipboard(text: string): Promise<APIResponse<boolean>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('system.setClipboard', { text }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async openExternal(url: string): Promise<APIResponse<boolean>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('system.openExternal', { url }))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async getCurrentTime(): Promise<APIResponse<Date>> {
|
|||
|
|
const result = await this.wrapResponse(this.sendToSystem('system.getCurrentTime'))
|
|||
|
|
if (result.success && result.data) {
|
|||
|
|
result.data = new Date(result.data)
|
|||
|
|
}
|
|||
|
|
return result
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async generateUUID(): Promise<APIResponse<string>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('system.generateUUID'))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async exit(): Promise<APIResponse<boolean>> {
|
|||
|
|
return this.wrapResponse(this.sendToSystem('system.exit'))
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 主SDK实现类
|
|||
|
|
*/
|
|||
|
|
class SystemDesktopSDKImpl implements SystemDesktopSDK {
|
|||
|
|
readonly version: string = '1.0.0'
|
|||
|
|
|
|||
|
|
private _appId: string = ''
|
|||
|
|
private _initialized: boolean = false
|
|||
|
|
|
|||
|
|
private _window!: WindowSDK
|
|||
|
|
private _storage!: StorageSDK
|
|||
|
|
private _network!: NetworkSDK
|
|||
|
|
private _events!: EventSDK
|
|||
|
|
private _ui!: UISDK
|
|||
|
|
private _system!: SystemSDK
|
|||
|
|
|
|||
|
|
get appId(): string {
|
|||
|
|
return this._appId
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
get initialized(): boolean {
|
|||
|
|
return this._initialized
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
get window(): WindowSDK {
|
|||
|
|
this.checkInitialized()
|
|||
|
|
return this._window
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
get storage(): StorageSDK {
|
|||
|
|
this.checkInitialized()
|
|||
|
|
return this._storage
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
get network(): NetworkSDK {
|
|||
|
|
this.checkInitialized()
|
|||
|
|
return this._network
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
get events(): EventSDK {
|
|||
|
|
this.checkInitialized()
|
|||
|
|
return this._events
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
get ui(): UISDK {
|
|||
|
|
this.checkInitialized()
|
|||
|
|
return this._ui
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
get system(): SystemSDK {
|
|||
|
|
this.checkInitialized()
|
|||
|
|
return this._system
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async init(config: SDKConfig): Promise<APIResponse<boolean>> {
|
|||
|
|
try {
|
|||
|
|
if (this._initialized) {
|
|||
|
|
return { success: false, error: 'SDK已初始化' }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this._appId = config.appId
|
|||
|
|
|
|||
|
|
// 初始化各个子模块
|
|||
|
|
this._window = new WindowSDKImpl(this._appId)
|
|||
|
|
this._storage = new StorageSDKImpl(this._appId)
|
|||
|
|
this._network = new NetworkSDKImpl(this._appId)
|
|||
|
|
this._events = new EventSDKImpl(this._appId)
|
|||
|
|
this._ui = new UISDKImpl(this._appId)
|
|||
|
|
this._system = new SystemSDKImpl(this._appId)
|
|||
|
|
|
|||
|
|
// 向系统注册应用
|
|||
|
|
const response = await this.sendToSystem('sdk.init', config)
|
|||
|
|
|
|||
|
|
if (response.success) {
|
|||
|
|
this._initialized = true
|
|||
|
|
console.log(`SDK已初始化,应用ID: ${this._appId}`)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return response
|
|||
|
|
} catch (error) {
|
|||
|
|
return {
|
|||
|
|
success: false,
|
|||
|
|
error: error instanceof Error ? error.message : '初始化失败',
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async destroy(): Promise<APIResponse<boolean>> {
|
|||
|
|
try {
|
|||
|
|
if (!this._initialized) {
|
|||
|
|
return { success: false, error: 'SDK未初始化' }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const response = await this.sendToSystem('sdk.destroy', { appId: this._appId })
|
|||
|
|
|
|||
|
|
if (response.success) {
|
|||
|
|
this._initialized = false
|
|||
|
|
this._appId = ''
|
|||
|
|
console.log('SDK已销毁')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return response
|
|||
|
|
} catch (error) {
|
|||
|
|
return {
|
|||
|
|
success: false,
|
|||
|
|
error: error instanceof Error ? error.message : '销毁失败',
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async getStatus(): Promise<
|
|||
|
|
APIResponse<{ initialized: boolean; connected: boolean; permissions: string[] }>
|
|||
|
|
> {
|
|||
|
|
try {
|
|||
|
|
const response = await this.sendToSystem('sdk.getStatus', { appId: this._appId })
|
|||
|
|
return {
|
|||
|
|
success: true,
|
|||
|
|
data: {
|
|||
|
|
initialized: this._initialized,
|
|||
|
|
connected: response.data.connected || false,
|
|||
|
|
permissions: response.data.permissions || [],
|
|||
|
|
},
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
return {
|
|||
|
|
success: false,
|
|||
|
|
error: error instanceof Error ? error.message : '获取状态失败',
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private checkInitialized(): void {
|
|||
|
|
if (!this._initialized) {
|
|||
|
|
throw new Error('SDK未初始化,请先调用init()方法')
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private sendToSystem<T = any>(
|
|||
|
|
type: string,
|
|||
|
|
data?: any,
|
|||
|
|
): Promise<{ success: boolean; data?: T; error?: string }> {
|
|||
|
|
return new Promise((resolve, reject) => {
|
|||
|
|
const requestId = Date.now().toString() + Math.random().toString(36).substr(2, 9)
|
|||
|
|
|
|||
|
|
const handler = (event: MessageEvent) => {
|
|||
|
|
if (event.data?.type === 'system:response' && event.data?.requestId === requestId) {
|
|||
|
|
window.removeEventListener('message', handler)
|
|||
|
|
resolve(event.data)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
window.addEventListener('message', handler)
|
|||
|
|
|
|||
|
|
window.parent.postMessage(
|
|||
|
|
{
|
|||
|
|
type: 'sdk:call',
|
|||
|
|
requestId,
|
|||
|
|
method: type,
|
|||
|
|
data,
|
|||
|
|
appId: this._appId,
|
|||
|
|
},
|
|||
|
|
'*',
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
setTimeout(() => {
|
|||
|
|
window.removeEventListener('message', handler)
|
|||
|
|
reject(new Error('系统调用超时'))
|
|||
|
|
}, 10000)
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 创建全局SDK实例
|
|||
|
|
const SystemSDK = new SystemDesktopSDKImpl()
|
|||
|
|
|
|||
|
|
// 导出SDK实例
|
|||
|
|
export default SystemSDK
|
|||
|
|
|
|||
|
|
// 在window对象上挂载SDK
|
|||
|
|
if (typeof window !== 'undefined') {
|
|||
|
|
window.SystemSDK = SystemSDK
|
|||
|
|
}
|