UNPKG

@plasosdk/client-sdk

Version:

Plaso教育平台的客户端SDK

195 lines (173 loc) 4.98 kB
import React from 'react'; import { createRoot, Root } from 'react-dom/client'; import { PlasoViewer } from './components/PlasoViewer'; import { Environment } from './config/environment'; import { PlasoContentType,getUrlConfigMap } from './config/url'; export interface PlasoClientOptions { token: string; container: HTMLElement; env?: Environment; onError?: (error: Error) => void; onLoading?: (isLoading: boolean) => void; // 是否打开开发者工具 devTools?: boolean platform?: string; } // 定义URL映射配置 interface UrlConfig { baseUrl: string; } export class PlasoClient { private platform: string; private token: string; private container: HTMLElement; private onError?: (error: Error) => void; private onLoading?: (isLoading: boolean) => void; private root: Root | null = null; private env: Environment; private URL_CONFIG_MAP: Record<PlasoContentType, UrlConfig> | null = null; private devTools: boolean; constructor(options: PlasoClientOptions) { this.platform = options.platform || 'plaso'; this.token = options.token; this.container = options.container; this.onError = options.onError; this.onLoading = options.onLoading; this.root = createRoot(this.container); this.env = options.env || Environment.PROD; this.URL_CONFIG_MAP = getUrlConfigMap(this.env, this.platform); this.devTools = options.devTools || false; this.checkParams(); } private checkParams = () => { if(!(this.token && this.container)){ this.onError?.(new Error('传入参数有误')); } } private handleError(error: Error): void { console.error('Plaso客户端错误:', error); if (this.onError) { this.onError(error); } } /** * 构建完整URL * @param type 内容类型 * @returns 完整的URL */ private buildUrl(type: PlasoContentType): string { const config = this.URL_CONFIG_MAP?.[type]; if (!config) { throw new Error(`不支持的内容类型: ${type}`); } const { baseUrl } = config; // 检查baseUrl是否已包含参数 const hasParams = baseUrl.includes('?'); const separator = hasParams ? '&' : '?'; return `${baseUrl}${separator}token=${encodeURIComponent(this.token)}`; } /** * 渲染内容 * @param type 内容类型 */ private async renderContent(type: PlasoContentType): Promise<void> { if (!this.root) { throw new Error('Plaso客户端未正确初始化'); } if (this.onLoading) { this.onLoading(true); } try { const url = this.buildUrl(type); this.root.render( React.createElement(PlasoViewer, { url, token: this.token, type, devTools: this.devTools, onError: this.handleError.bind(this) }) ); } catch (error) { this.handleError(error as Error); throw error; } finally { if (this.onLoading) { this.onLoading(false); } } } /** * 创建指定类型的模块 * @param module 模块类型 */ public async createModule(module: PlasoContentType): Promise<void> { try { await this.renderContent(module); } catch (error) { this.handleError(error as Error); throw error; } } /** * 创建作业 */ public async createAssignment(): Promise<void> { try { await this.createModule(PlasoContentType.NHOMEWORK); } catch (error) { this.handleError(error as Error); throw error; } } /** * 创建课堂 */ public async createClassroom(): Promise<void> { try { await this.createModule(PlasoContentType.LIVECLASS); } catch (error) { this.handleError(error as Error); throw error; } } /** * 创建资源 */ public async createResource(): Promise<void> { try { await this.createModule(PlasoContentType.RESOURCES); } catch (error) { this.handleError(error as Error); throw error; } } /** * 渲染自定义内容 * @param type 内容类型 */ public async renderCustomContent(type: PlasoContentType): Promise<void> { try { await this.createModule(type); } catch (error) { this.handleError(error as Error); throw error; } } /** * 销毁客户端实例 */ public destroy(): HTMLElement | void { console.log('销毁客户端实例'); if (this.root) { this.root.unmount(); this.root = null; } if (this.container.parentNode) { const newContainer = this.container.cloneNode(false) as HTMLElement; this.container.parentNode.replaceChild(newContainer, this.container); this.container = newContainer; return newContainer; // 返回新节点 } } }