|
@@ -1852,7 +1852,13 @@ const elementDone = async (element: any, slideIndex: number) => {
|
|
|
try {
|
|
try {
|
|
|
// 创建一个临时的iframe来测试是否能获取contentWindow
|
|
// 创建一个临时的iframe来测试是否能获取contentWindow
|
|
|
const tempIframe = document.createElement('iframe')
|
|
const tempIframe = document.createElement('iframe')
|
|
|
- tempIframe.style.display = 'none'
|
|
|
|
|
|
|
+ // 不用 display:none:iPad Safari/WKWebView 会对隐藏 iframe 资源节流,
|
|
|
|
|
+ // onload 迟迟不触发导致超时误判为"禁止嵌入",误入抓 HTML 路径(跨站 Cookie 被 ITP 拦截必然失败)
|
|
|
|
|
+ tempIframe.style.position = 'absolute'
|
|
|
|
|
+ tempIframe.style.left = '-9999px'
|
|
|
|
|
+ tempIframe.style.top = '-9999px'
|
|
|
|
|
+ tempIframe.style.width = '1px'
|
|
|
|
|
+ tempIframe.style.height = '1px'
|
|
|
tempIframe.src = iframeSrc
|
|
tempIframe.src = iframeSrc
|
|
|
|
|
|
|
|
// 先将临时iframe添加到body,否则onload事件不会触发
|
|
// 先将临时iframe添加到body,否则onload事件不会触发
|
|
@@ -1861,12 +1867,13 @@ const elementDone = async (element: any, slideIndex: number) => {
|
|
|
await new Promise((resolve, reject) => {
|
|
await new Promise((resolve, reject) => {
|
|
|
tempIframe.onload = resolve
|
|
tempIframe.onload = resolve
|
|
|
tempIframe.onerror = reject
|
|
tempIframe.onerror = reject
|
|
|
- // 可选:设置超时时间,避免长时间无响应
|
|
|
|
|
- setTimeout(() => reject(new Error('Timeout')), 5000)
|
|
|
|
|
|
|
+ // iPad 网络/渲染较慢,超时放宽到 12 秒
|
|
|
|
|
+ setTimeout(() => reject(new Error('Timeout')), 12000)
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- // 尝试获取contentWindow
|
|
|
|
|
- if (tempIframe.contentWindow && tempIframe.contentWindow.document) {
|
|
|
|
|
|
|
+ // 尝试获取contentDocument(标准属性:跨域返回 null 不抛异常;
|
|
|
|
|
+ // 不能用 contentWindow.document,iPad Safari 跨域访问会直接抛 SecurityError,又会误入抓 HTML 路径)
|
|
|
|
|
+ if (tempIframe.contentDocument) {
|
|
|
console.log(`iframe ${iframeSrc} 可以获取contentWindow,使用直接加载方式`)
|
|
console.log(`iframe ${iframeSrc} 可以获取contentWindow,使用直接加载方式`)
|
|
|
// 移除临时iframe
|
|
// 移除临时iframe
|
|
|
document.body.removeChild(tempIframe)
|
|
document.body.removeChild(tempIframe)
|
|
@@ -1918,11 +1925,23 @@ const elementDone = async (element: any, slideIndex: number) => {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
console.log(`处理幻灯片 ${slideIndex + 1} 中的iframe链接:`, iframeSrc)
|
|
console.log(`处理幻灯片 ${slideIndex + 1} 中的iframe链接:`, iframeSrc)
|
|
|
- _element = {
|
|
|
|
|
- ...element,
|
|
|
|
|
- isHTML: true,
|
|
|
|
|
- url: html,
|
|
|
|
|
- curl: iframeSrc
|
|
|
|
|
|
|
+ if (html) {
|
|
|
|
|
+ _element = {
|
|
|
|
|
+ ...element,
|
|
|
|
|
+ isHTML: true,
|
|
|
|
|
+ url: html,
|
|
|
|
|
+ curl: iframeSrc
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ // getHTML/getFile/getFile2 全失败:不能置空 url 硬切 srcdoc(会白屏),
|
|
|
|
|
+ // 回退为直接加载原始链接,至少保持与进页面时一致的显示效果
|
|
|
|
|
+ console.warn(`幻灯片 ${slideIndex + 1} 未获取到HTML内容,回退为直接加载:`, iframeSrc)
|
|
|
|
|
+ _element = {
|
|
|
|
|
+ ...element,
|
|
|
|
|
+ isHTML: false,
|
|
|
|
|
+ url: iframeSrc
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -3968,8 +3987,10 @@ const openChoiceQuestionDetail3 = (index:number) => {
|
|
|
|
|
|
|
|
const handlePageUnload = () => {
|
|
const handlePageUnload = () => {
|
|
|
if (isCreator.value && timerIndicator.value.visible && props.type === '1') {
|
|
if (isCreator.value && timerIndicator.value.visible && props.type === '1') {
|
|
|
- sendMessage({ type: 'timer_stop', courseid: props.courseid, isCreator: isCreator.value ? 'T' : 'F' })
|
|
|
|
|
|
|
+ // sendMessage({ type: 'timer_stop', courseid: props.courseid, isCreator: isCreator.value ? 'T' : 'F' })
|
|
|
|
|
+ onTimerStop()
|
|
|
}
|
|
}
|
|
|
|
|
+ // sad
|
|
|
// 创建老师刷新/关闭页面时,清空所有同步状态
|
|
// 创建老师刷新/关闭页面时,清空所有同步状态
|
|
|
if (isCreator.value && props.type === '1') {
|
|
if (isCreator.value && props.type === '1') {
|
|
|
clearAllSyncStates()
|
|
clearAllSyncStates()
|
|
@@ -4180,7 +4201,7 @@ onMounted(() => {
|
|
|
'11. ws.readyState': providerSocket.value?.ws?.readyState,
|
|
'11. ws.readyState': providerSocket.value?.ws?.readyState,
|
|
|
'12. messageV3?.get("slideIndex")': msgV3Type?.get?.('slideIndex'),
|
|
'12. messageV3?.get("slideIndex")': msgV3Type?.get?.('slideIndex'),
|
|
|
'13. yTimerMesssage': doc.getArray('timerMessages'),
|
|
'13. yTimerMesssage': doc.getArray('timerMessages'),
|
|
|
- '14. timerState':docSocket.value.getMap('timerState')
|
|
|
|
|
|
|
+ '14. timerState': docSocket.value.getMap('timerState')
|
|
|
}
|
|
}
|
|
|
console.log('════════ Yjs 诊断 ════════')
|
|
console.log('════════ Yjs 诊断 ════════')
|
|
|
for (const [k, v] of Object.entries(report)) {
|
|
for (const [k, v] of Object.entries(report)) {
|