chore: 更新素材和组件优化
- 更新展品图片(鲁迅/毛泽东/孙中山/黄炎培/聂耳/张乐平故居) - 新增点击查看图标、报纸素材 - 优化视频组件、拼图组件、展品组件 - 更新陈云音频资源 - 新增输入验证文档和工具函数 - 组件布局和动画优化 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
73d02eb62d
commit
73f6df92ce
130 files changed
+2345
-759
No files matched your search
+101
-212
@@ -1,16 +1,10 @@
|
||||
import { useUserStore } from '@/store/userStore'
|
||||
|
||||
//超时时间
|
||||
const TIMEOUT_MS = 1000 * 10
|
||||
const TIMEOUT_MS = 1000 * 6
|
||||
|
||||
// 声明外部依赖(由运行环境提供)
|
||||
declare const $: any
|
||||
declare const iscallyb: boolean
|
||||
declare const emykey: string
|
||||
declare function videoAjax(): VideoAjax
|
||||
declare function getFutureDa(days: number): string
|
||||
declare function getCurrentDa(str: string): void
|
||||
declare function formatDateFromMilliseconds(date: Date): string
|
||||
|
||||
interface UserDefineParam {
|
||||
lessonId: string
|
||||
@@ -54,113 +48,57 @@ interface VideoAjax {
|
||||
finishCourse(param: { order: number; co: string; process: number }): void
|
||||
}
|
||||
|
||||
// 扩展 jQuery,获取 URL 参数
|
||||
$.extend({
|
||||
getUrlVars(): string[] & Record<string, string | undefined> {
|
||||
const vars: any[] & Record<string, string | undefined> = [] as any
|
||||
let hash: string[]
|
||||
const queryIndex = window.location.href.indexOf('?')
|
||||
if (queryIndex === -1) return vars
|
||||
const hashes = window.location.href
|
||||
.slice(queryIndex + 1)
|
||||
.split('&')
|
||||
.filter(Boolean)
|
||||
for (let i = 0; i < hashes.length; i++) {
|
||||
const item = hashes[i]
|
||||
if (!item) continue
|
||||
hash = item.split('=')
|
||||
const keyRaw = hash[0] ?? ''
|
||||
const valueRaw = hash[1] ?? ''
|
||||
const key = decodeURIComponent(keyRaw)
|
||||
const value = decodeURIComponent(valueRaw)
|
||||
vars.push(key)
|
||||
vars[key] = value
|
||||
}
|
||||
return vars
|
||||
},
|
||||
getUrlVar(name: string): string | undefined {
|
||||
return ($ as any).getUrlVars()[name]
|
||||
},
|
||||
})
|
||||
|
||||
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('/')
|
||||
|
||||
// 设置我的自定义数据(所有的自定义数据都设置在第一个课时ID上,以key来区分不同的类型)
|
||||
function setLtDefine(key: string | number, value: string): void {
|
||||
if (iscallyb) {
|
||||
setUserDefine(1, key, value)
|
||||
} else {
|
||||
sessionStorage.setItem(`${LESSON_PREFIX}_${key}`, value)
|
||||
}
|
||||
}
|
||||
|
||||
let mycstr9 = ''
|
||||
|
||||
// 获取定义数据(由于底层是异步接口,这里返回 Promise)
|
||||
async function getLtDefine(key: string | number): Promise<string> {
|
||||
if (iscallyb) {
|
||||
if (mycstr9 === '') {
|
||||
const all = await getUsersDefine(1, emykey)
|
||||
if (all === undefined || all === null || all === 'null' || all === '') {
|
||||
mycstr9 = getFutureDa(10)
|
||||
setLtDefine(emykey, mycstr9)
|
||||
} else {
|
||||
mycstr9 = all as string // 这里是 emykey,对应上面 getUsersDefine 的 string 分支
|
||||
}
|
||||
}
|
||||
const str = mycstr9 === undefined || mycstr9 === null || mycstr9 === 'null' ? '' : mycstr9
|
||||
getCurrentDa(str)
|
||||
const objitem = await getUserDefine(1, key)
|
||||
return objitem === undefined || objitem === null || objitem === 'null' ? '' : objitem
|
||||
} else {
|
||||
const itemvalue = sessionStorage.getItem(`${LESSON_PREFIX}_${key}`)
|
||||
return itemvalue === undefined || itemvalue === null || itemvalue === 'null' ? '' : itemvalue
|
||||
}
|
||||
}
|
||||
|
||||
// 设置课程笔记10002
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
function setCourseNotepad(collect: string[]): void {
|
||||
// 保持和原逻辑一致:序列化为 JSON 存储
|
||||
setLtDefine(10002, $.toJSON(collect))
|
||||
}
|
||||
|
||||
// 获取课程笔记10002(异步)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async function getCourseNotepad(): Promise<string[]> {
|
||||
const raw = await getLtDefine(10002)
|
||||
if (raw === undefined || raw === null || raw === '') {
|
||||
// 原逻辑:返回长度为 9 的空字符串数组
|
||||
return ['', '', '', '', '', '', '', '', '']
|
||||
}
|
||||
return $.parseJSON(raw) as string[]
|
||||
}
|
||||
|
||||
// lessonId(课时唯一ID)
|
||||
export function setUserDefine(
|
||||
lessonId: string | number,
|
||||
key: string | number,
|
||||
value: string
|
||||
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,
|
||||
}
|
||||
console.log(param)
|
||||
videoajax.addUserDefine(param)
|
||||
}
|
||||
|
||||
// 内部:将回调形式封装为 Promise
|
||||
function getUserDefineResultAsyncInternal(
|
||||
lessonId: string | number,
|
||||
key: string | number
|
||||
key: string | number,
|
||||
options: StorageOptions = {}
|
||||
): Promise<UserDefineFetchResult> {
|
||||
if (!iscallyb) {
|
||||
const itemValue = sessionStorage.getItem(`${LESSON_PREFIX}_${lessonId}_${key}`)
|
||||
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: '' }
|
||||
@@ -175,149 +113,100 @@ function getUserDefineResultAsyncInternal(
|
||||
|
||||
return new Promise((resolve) => {
|
||||
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) => {
|
||||
const done = (result: UserDefineFetchResult) => {
|
||||
if (settled) return
|
||||
settled = true
|
||||
clearTimeout(timeout)
|
||||
console.log(res)
|
||||
resolve(result)
|
||||
}
|
||||
|
||||
if (res === undefined || res === null || res === ('null' as unknown)) {
|
||||
done({ status: 'empty', content: '' })
|
||||
return
|
||||
}
|
||||
try {
|
||||
videoajax.getUserDefineInfoByUser(param, (res) => {
|
||||
try {
|
||||
console.log(res)
|
||||
|
||||
if (res.code === 202) {
|
||||
done({ status: 'unauthenticated', content: '', code: res.code, message: res.msg })
|
||||
return
|
||||
}
|
||||
if (res === undefined || res === null || res === ('null' as unknown)) {
|
||||
done({ status: 'empty', content: '' })
|
||||
return
|
||||
}
|
||||
|
||||
if (res.code !== 200) {
|
||||
done({
|
||||
status: 'error',
|
||||
content: '',
|
||||
code: res.code,
|
||||
message: res.msg || '学习进度获取失败',
|
||||
})
|
||||
return
|
||||
}
|
||||
if (res.code === 202) {
|
||||
done({ status: 'unauthenticated', 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
|
||||
}
|
||||
if (res.code !== 200) {
|
||||
done({
|
||||
status: 'error',
|
||||
content: '',
|
||||
code: res.code,
|
||||
message: res.msg || '学习进度获取失败',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const json = Array.isArray(value) ? value : []
|
||||
const content = json[0]?.content || ''
|
||||
done(
|
||||
content === '' || content === 'null'
|
||||
? { status: 'empty', content: '' }
|
||||
: { status: 'success', content }
|
||||
)
|
||||
})
|
||||
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: '学习进度获取失败' })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
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
|
||||
key: string | number,
|
||||
options: StorageOptions = {}
|
||||
): Promise<UserDefineFetchResult> {
|
||||
return getUserDefineResultAsyncInternal(lessonId, key)
|
||||
}
|
||||
|
||||
export async function getUserDefine(
|
||||
lessonId: string | number,
|
||||
key: string | number
|
||||
): Promise<string> {
|
||||
return getUserDefineAsyncInternal(lessonId, key)
|
||||
}
|
||||
|
||||
// 内部:获取【所有】用户自定义数据(Promise 封装)
|
||||
function getUsersDefineAsyncInternal(
|
||||
lessonId: string | number,
|
||||
key: string | number
|
||||
): Promise<string | VideoAjaxResponseItem[]> {
|
||||
const param: UserDefineParam = {
|
||||
lessonId: `${LESSON_PREFIX}_${lessonId}`,
|
||||
order: key,
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
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) {
|
||||
if (key === emykey) {
|
||||
const mdate = new Date(
|
||||
Math.max.apply(
|
||||
null,
|
||||
json.map((item) => new Date(item.content || '').getTime())
|
||||
)
|
||||
)
|
||||
content = formatDateFromMilliseconds(mdate)
|
||||
} else {
|
||||
content = json
|
||||
}
|
||||
} else {
|
||||
content = json[0]?.content || ''
|
||||
}
|
||||
}
|
||||
done(content)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Promise 版本:获取【所有】用户自定义数据
|
||||
export async function getUsersDefine(
|
||||
lessonId: string | number,
|
||||
key: string | number
|
||||
): Promise<string | VideoAjaxResponseItem[]> {
|
||||
return getUsersDefineAsyncInternal(lessonId, key)
|
||||
return getUserDefineResultAsyncInternal(lessonId, key, options)
|
||||
}
|
||||
|
||||
// 根据课时顺序号(所处课程的第几课时)更新对应易班平台上的每个环节进度(异步)
|
||||
export async function setCourseTimeProgress(order: number): Promise<void> {
|
||||
export async function setCourseTimeProgress(order: number): Promise<boolean> {
|
||||
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')
|
||||
console.info(`courseid:${courseid} order:${order}`)
|
||||
if (iscallyb && courseid !== undefined && courseid !== null && courseid !== '') {
|
||||
if (order > 0) {
|
||||
const param2 = { order, co: courseid, process: 100 }
|
||||
videoajax.finishCourse(param2)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
Reference in new issue
Block a user