fix: 修复开发/测试包模拟进度被易班同步覆盖的问题

进度模拟面板写入 puzzleStore 后,App 启动时易班同步会将其覆盖;
现在在同步完成后按 sessionStorage 中保存的模式重放模拟进度,
确保测试包的"到达某故居/全流程完成"调试入口生效。

同时纳入近期未提交的页面、组件、资源与环境变量改动。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
zhongyidianandClaude Opus 4.7 committed 2026-05-23 10:19:36 +08:00
1 parent 6d40e19346
commit 49ecabbf3a
155 files changed
+1956 -724

No files matched your search

+110 -55
View File
@@ -1,5 +1,8 @@
import { useUserStore } from '@/store/userStore'
//超时时间
const TIMEOUT_MS = 1000 * 10
// 声明外部依赖(由运行环境提供)
declare const $: any
declare const iscallyb: boolean
@@ -9,11 +12,6 @@ declare function getFutureDa(days: number): string
declare function getCurrentDa(str: string): void
declare function formatDateFromMilliseconds(date: Date): string
// 本地或非易班环境下,外部全局变量可能未注入;统一用安全访问
const isYibanRuntime = (): boolean => {
return typeof iscallyb !== 'undefined' && iscallyb === true
}
interface UserDefineParam {
lessonId: string
key?: string | number
@@ -27,11 +25,21 @@ interface VideoAjaxResponseItem {
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
@@ -77,17 +85,12 @@ $.extend({
const LESSON_PREFIX = 'hsgrl'
const videoajax: VideoAjax | null = typeof videoAjax !== 'undefined' ? videoAjax() : null
videoajax?.setHost('/')
function normalizeLessonId(lessonId: string | number): string {
const raw = String(lessonId)
return raw.startsWith(`${LESSON_PREFIX}_`) ? raw : `${LESSON_PREFIX}_${raw}`
}
const videoajax: VideoAjax = videoAjax()
videoajax.setHost('/')
// 设置我的自定义数据(所有的自定义数据都设置在第一个课时ID上,以key来区分不同的类型)
function setLtDefine(key: string | number, value: string): void {
if (isYibanRuntime()) {
if (iscallyb) {
setUserDefine(1, key, value)
} else {
sessionStorage.setItem(`${LESSON_PREFIX}_${key}`, value)
@@ -98,7 +101,7 @@ let mycstr9 = ''
// 获取定义数据(由于底层是异步接口,这里返回 Promise)
async function getLtDefine(key: string | number): Promise<string> {
if (isYibanRuntime()) {
if (iscallyb) {
if (mycstr9 === '') {
const all = await getUsersDefine(1, emykey)
if (all === undefined || all === null || all === 'null' || all === '') {
@@ -142,53 +145,105 @@ export function setUserDefine(
key: string | number,
value: string
): void {
if (!isYibanRuntime() || !videoajax) {
sessionStorage.setItem(`${normalizeLessonId(lessonId)}_${key}`, value)
return
}
const param: UserDefineParam = {
lessonId: normalizeLessonId(lessonId),
lessonId: `${LESSON_PREFIX}_${lessonId}`,
key,
content: value,
}
console.log(param)
videoajax.addUserDefine(param)
}
// 内部:将回调形式封装为 Promise
function getUserDefineAsyncInternal(
function getUserDefineResultAsyncInternal(
lessonId: string | number,
key: string | number
): Promise<string> {
if (!isYibanRuntime() || !videoajax) {
const value = sessionStorage.getItem(`${normalizeLessonId(lessonId)}_${key}`)
return Promise.resolve(value === null || value === 'null' ? '' : value)
): Promise<UserDefineFetchResult> {
if (!iscallyb) {
const itemValue = sessionStorage.getItem(`${LESSON_PREFIX}_${lessonId}_${key}`)
return Promise.resolve(
itemValue === undefined || itemValue === null || itemValue === 'null' || itemValue === ''
? { status: 'empty', content: '' }
: { status: 'success', content: itemValue }
)
}
const param: UserDefineParam = {
lessonId: normalizeLessonId(lessonId),
lessonId: `${LESSON_PREFIX}_${lessonId}`,
order: key,
}
const ajax = videoajax
return new Promise((resolve) => {
let content = ''
ajax.getUserDefineInfoByUser(param, (res) => {
// 保留原有 console 行为
let settled = false
const done = (result: UserDefineFetchResult) => {
if (settled) return
settled = true
resolve(result)
}
const timeout = setTimeout(() => {
console.warn(`getUserDefine timeout: lessonId=${lessonId}, key=${key}`)
done({ status: 'error', content: '', message: '学习进度获取超时' })
}, TIMEOUT_MS)
videoajax.getUserDefineInfoByUser(param, (res) => {
clearTimeout(timeout)
console.log(res)
if (res && res.code === 200) {
const json = (res.data.value || []) as VideoAjaxResponseItem[]
const contents = json[0]?.content || ''
content = contents
} else {
content = ''
if (res === undefined || res === null || res === ('null' as unknown)) {
done({ status: 'empty', content: '' })
return
}
resolve(content)
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 }
)
})
})
}
function getUserDefineAsyncInternal(
lessonId: string | number,
key: string | number
): Promise<string> {
return getUserDefineResultAsyncInternal(lessonId, key).then((result) =>
result.status === 'success' ? result.content : ''
)
}
// Promise 版本:获取用户自定义数据
export async function getUserDefineResult(
lessonId: string | number,
key: string | number
): Promise<UserDefineFetchResult> {
return getUserDefineResultAsyncInternal(lessonId, key)
}
export async function getUserDefine(
lessonId: string | number,
key: string | number
@@ -201,19 +256,27 @@ function getUsersDefineAsyncInternal(
lessonId: string | number,
key: string | number
): Promise<string | VideoAjaxResponseItem[]> {
if (!isYibanRuntime() || !videoajax) {
return Promise.resolve('')
}
const param: UserDefineParam = {
lessonId: normalizeLessonId(lessonId),
lessonId: `${LESSON_PREFIX}_${lessonId}`,
order: key,
}
const ajax = videoajax
return new Promise((resolve) => {
let content: string | VideoAjaxResponseItem[] = ''
ajax.getUserDefineInfo(param, (data) => {
let settled = false
const done = (content: string | VideoAjaxResponseItem[]) => {
if (settled) return
settled = true
resolve(content)
}
const timeout = setTimeout(() => {
console.warn(`getUsersDefine timeout: lessonId=${lessonId}, key=${key}`)
done('')
}, TIMEOUT_MS)
videoajax.getUserDefineInfo(param, (data) => {
clearTimeout(timeout)
let content: string | VideoAjaxResponseItem[] = ''
if (data && data.code === 200) {
const json = (data.data.value || []) as VideoAjaxResponseItem[]
if (json.length > 1) {
@@ -231,10 +294,8 @@ function getUsersDefineAsyncInternal(
} else {
content = json[0]?.content || ''
}
} else {
content = ''
}
resolve(content)
done(content)
})
})
}
@@ -253,13 +314,7 @@ export async function setCourseTimeProgress(order: number): Promise<void> {
// var courseid = getCookie(lesson+"_course_id");//获取url链接的课程ID
// const courseid = await getLtDefine('10000')
console.info(`courseid:${courseid} order:${order}`)
if (
isYibanRuntime() &&
videoajax &&
courseid !== undefined &&
courseid !== null &&
courseid !== ''
) {
if (iscallyb && courseid !== undefined && courseid !== null && courseid !== '') {
if (order > 0) {
const param2 = { order, co: courseid, process: 100 }
videoajax.finishCourse(param2)