import { useUserStore } from '@/store/userStore' //超时时间 const TIMEOUT_MS = 1000 * 6 // 声明外部依赖(由运行环境提供) declare function videoAjax(): VideoAjax interface UserDefineParam { lessonId: string key?: string | number order?: string | number content?: string } interface VideoAjaxResponseItem { content?: string } interface VideoAjaxResponse { code: number msg?: string data: { value?: VideoAjaxResponseItem[] | string } } export type UserDefineFetchStatus = 'success' | 'empty' | 'unauthenticated' | 'error' export interface UserDefineFetchResult { status: UserDefineFetchStatus content: string code?: number message?: string } interface VideoAjax { setHost(host: string): void addUserDefine(param: UserDefineParam): void getUserDefineInfoByUser( param: UserDefineParam, callback: (data: VideoAjaxResponse | undefined) => void ): void getUserDefineInfo( param: UserDefineParam, callback: (data: VideoAjaxResponse | undefined) => void ): void finishCourse(param: { order: number; co: string; process: number }): void } const LESSON_PREFIX = 'hsgrl' export type StorageBackend = 'auto' | 'yiban' | 'session' export interface StorageOptions { backend?: StorageBackend } const getStorageKey = (lessonId: string | number, key: string | number) => `${LESSON_PREFIX}_${lessonId}_${key}` const resolveStorageBackend = (backend: StorageBackend = 'auto'): 'yiban' | 'session' => { if (backend === 'yiban' || backend === 'session') return backend return useUserStore.getState().yibanConnectionStatus === 'connected' ? 'yiban' : 'session' } const videoajax: VideoAjax = videoAjax() videoajax.setHost('/') // lessonId(课时唯一ID) export function setUserDefine( lessonId: string | number, key: string | number, value: string, options: StorageOptions = {} ): void { const backend = resolveStorageBackend(options.backend) if (backend === 'session') { sessionStorage.setItem(getStorageKey(lessonId, key), value) return } const param: UserDefineParam = { lessonId: `${LESSON_PREFIX}_${lessonId}`, key, content: value, } videoajax.addUserDefine(param) } // 内部:将回调形式封装为 Promise function getUserDefineResultAsyncInternal( lessonId: string | number, key: string | number, options: StorageOptions = {} ): Promise { const backend = resolveStorageBackend(options.backend) if (backend === 'session') { const itemValue = sessionStorage.getItem(getStorageKey(lessonId, key)) return Promise.resolve( itemValue === undefined || itemValue === null || itemValue === 'null' || itemValue === '' ? { status: 'empty', content: '' } : { status: 'success', content: itemValue } ) } const param: UserDefineParam = { lessonId: `${LESSON_PREFIX}_${lessonId}`, order: key, } return new Promise((resolve) => { let settled = false const timeout = setTimeout(() => { console.warn(`getUserDefine timeout: lessonId=${lessonId}, key=${key}`) done({ status: 'error', content: '', message: '学习进度获取超时' }) }, TIMEOUT_MS) const done = (result: UserDefineFetchResult) => { if (settled) return settled = true clearTimeout(timeout) resolve(result) } try { videoajax.getUserDefineInfoByUser(param, (res) => { try { console.log(res) if (res === undefined || res === null || res === ('null' as unknown)) { done({ status: 'empty', content: '' }) return } if (res.code === 202) { done({ status: 'unauthenticated', content: '', code: res.code, message: res.msg }) return } if (res.code !== 200) { done({ status: 'error', content: '', code: res.code, message: res.msg || '学习进度获取失败', }) return } const value = res.data?.value if (value === undefined || value === null || value === 'null' || value === '') { done({ status: 'empty', content: '' }) return } const json = Array.isArray(value) ? value : [] const content = json[0]?.content || '' done( content === '' || content === 'null' ? { status: 'empty', content: '' } : { status: 'success', content } ) } catch (error) { console.error('Failed to handle getUserDefine response', error) done({ status: 'error', content: '', message: '学习进度解析失败' }) } }) } catch (error) { console.error('Failed to call getUserDefine', error) done({ status: 'error', content: '', message: '学习进度获取失败' }) } }) } // Promise 版本:获取用户自定义数据 export async function getUserDefineResult( lessonId: string | number, key: string | number, options: StorageOptions = {} ): Promise { return getUserDefineResultAsyncInternal(lessonId, key, options) } export function parseUserDefineContent(content: string): T { const raw = JSON.parse(content) if (useUserStore.getState().yibanConnectionStatus === 'connected') { return raw as T } if (raw && typeof raw === 'object' && 'state' in raw) { return (raw as { state: T }).state } return raw as T } // 根据课时顺序号(所处课程的第几课时)更新对应易班平台上的每个环节进度(异步) export async function setCourseTimeProgress(order: number): Promise { if (useUserStore.getState().yibanConnectionStatus !== 'connected') { console.info(`[yiban] skip finishCourse: disconnected, order=${order}`) return false } const courseid = useUserStore.getState().courseId // var courseid = getCookie(lesson+"_course_id");//获取url链接的课程ID // const courseid = await getLtDefine('10000') if (courseid === undefined || courseid === null || courseid === '') { console.info(`[yiban] skip finishCourse: missing courseId, order=${order}`) return false } if (order <= 0) { console.info(`[yiban] skip finishCourse: invalid order=${order}`) return false } const param2 = { order, co: courseid, process: 100 } console.info('[yiban] finishCourse', param2) videoajax.finishCourse(param2) return true }