import { genId, isStudyMachine, isWebEvn } from '@/utils' // web页面 export const sys_type_web = 1 // 学习机 export const sys_type_study_machine = 2 // 普通移动端 export const sys_type_native_universal = 3 // 原生api的调用对象。App WebView 里桥可能晚于业务脚本注入,调用时需要重新读取。 export const getNativeApi = () => window.$xxl || window.$xxl_universal export const native_api = getNativeApi() // 系统类型 export const sys_type = window.$xxl ? sys_type_study_machine : window.$xxl_universal ? sys_type_native_universal : sys_type_web // 获取SN码 export const getSN = () => { if (isStudyMachine) { const { data: { SN }, } = JSON.parse(native_api.getDeviceInfo()) return SN } return isWebEvn ? 'web' : 'universal' } // 获取厂家 export const getManufacturer = () => { if (native_api?.getDeviceInfo) { const { data: { model }, } = JSON.parse(native_api.getDeviceInfo()) return model } return 'web' } // 获取版本号 export const getVersion = (type = 0) => { if (type === 1) { // web版本(.env 里 `KEY = value` 等号旁空格可能让值带前导空格,compare-versions 会报非法 semver) const v = import.meta.env.VITE_XXL_VERSION return String(v ?? '') .trim() .replace(/^\uFEFF/, '') } if (native_api?.getVersionCode) { const data = JSON.parse(native_api.getVersionCode()).data return String(data ?? '') .trim() .replace(/^\uFEFF/, '') } return '' } // 打开操作 export const openBridge = (type: string, ...args: any[]) => { if (!native_api) return try { switch (type) { case 'wifi': native_api.openWiFi?.() break case 'setting': native_api.openSetting?.() break case 'app': native_api.openApp?.(...args) break case 'lock': native_api.lockScreen?.() break } } catch (err) { console.error(err) } } export const $XXL = { getDefaultPwd: () => packSync('getDefaultPwd'), getAppsInfo: (...args: any[]) => pack('getAppsInfo', ...args), loadResources: (config?: anyObj, cb?: anyFuc) => pack('loadResources', config, cb), clearResources: (config: { ext: string }) => pack('clearResources', config), downloadFile: (config: { url: string; rewrite: 0 | 1 }, cb?: anyFuc) => pack('downloadFile', config, cb), uploadFile: (config: anyObj) => pack('uploadFile', config), showDoodle: (config?: anyObj, cb?: anyFuc) => pack('showDoodle', config, cb), setScreenOn: (...args: any[]) => packSync('setScreenOn', ...args), closeLoading: () => packSync('closeLoading'), reboot: () => packSync('reboot'), restartApp: () => packSync('restartApp'), killMyself: () => packSync('killMyself'), forceRefresh: () => packSync('forceRefresh'), installApk: (path: string) => packSync('installApk', path), getScreenshot: () => packSync('getScreenshot'), showDebugPanel: () => packSync('showDebugPanel'), hideDebugPanel: () => packSync('hideDebugPanel'), clearWebViewCache: () => packSync('clearWebViewCache'), writeError: (error: string) => packSync('writeError', error), uninstallApp: (pkgName: string) => packSync('uninstallApp', pkgName), openExternalURL: (url: string) => packSync('openExternalURL', url), /** 老师投屏开始:参数为 JSON 字符串,与原生 `startTeacherShareScreen` 约定一致 */ startTeacherShareScreen: (config: { host: string; port: number; name: string; id: string }) => packSync('startTeacherShareScreen', JSON.stringify(config)), /** 老师投屏结束 */ stopTeacherShareScreen: () => packSync('stopTeacherShareScreen'), /** 学生课堂监控投屏开始:参数与 `startTeacherShareScreen` 一致 */ startStudentShareScreen: (config: { host: string; port: number; name: string; id: string }) => packSync('startStudentShareScreen', JSON.stringify(config)), /** 学生课堂监控投屏结束 */ stopStudentShareScreen: () => packSync('stopStudentShareScreen'), // openApp: (config: anyObj) => pack('openApp', config), } const pack = (method: string, config: anyObj = {}, cb?: anyFuc): any => { return new Promise((resolve, reject) => { const api = getNativeApi() if (!api) { reject(new Error('暂不支持')) return } // 超时拦截 let timer: any = setTimeout(() => { reject(new Error(`${method} method running timeout`)) }, 1000 * 60) // 注册回调 const cbName = genId(`${method}_`) if (!window.xxl_cb) window.xxl_cb = {} if (cb) { window.xxl_cb[cbName] = (...args: any[]) => cb(...args, () => resolve(true)) } else { window.xxl_cb[cbName] = res => { clearTimeout(timer) timer = null if (res.code === 200) { resolve(res.data) } else { reject(new Error(res.message || `${method} failed: ${JSON.stringify(res)}`)) } } } api[method]?.(JSON.stringify({ ...config, cb: `xxl_cb.${cbName}` })) }) } const packSync = (method: string, ...args: any[]) => { try { const api = getNativeApi() if (!api) return const res = api[method]?.(...args) return res && JSON.parse(res) } catch (err) { console.log(err) } }