|
|
@@ -64,7 +64,7 @@
|
|
|
<!-- 延迟加载iframe:只有在可见且不是缩略图时才加载 -->
|
|
|
<iframe
|
|
|
:key="`html-${iframeKey}`"
|
|
|
- :srcdoc="processedSrcdoc"
|
|
|
+ :srcdoc="elementInfo.url"
|
|
|
v-else-if="elementInfo.isHTML && !isThumbnail && isVisible"
|
|
|
:width="width"
|
|
|
:height="height"
|
|
|
@@ -121,10 +121,6 @@ import {
|
|
|
} from '@/configs/englishSpeakingTools'
|
|
|
import { ref, watch, nextTick } from 'vue'
|
|
|
import { computed } from 'vue'
|
|
|
-import jqueryRaw from './jquery-3.6.0.min.js?raw'
|
|
|
-import awsSdkRaw from './aws-sdk-2.235.1.min.js?raw'
|
|
|
-import jietuRaw from './jietu.js?raw'
|
|
|
-import html2canvasRaw from 'html2canvas/dist/html2canvas.min.js?raw'
|
|
|
|
|
|
const props = defineProps({
|
|
|
elementInfo: {
|
|
|
@@ -148,65 +144,6 @@ const props = defineProps({
|
|
|
// 用于强制刷新iframe的key
|
|
|
const iframeKey = ref(0)
|
|
|
|
|
|
-// 处理 srcdoc:将页面自定义的 $ 改名为 _$,注入 jQuery 等脚本
|
|
|
-const processedSrcdoc = computed(() => {
|
|
|
- if (!props.elementInfo.isHTML) return props.elementInfo.url
|
|
|
-
|
|
|
- const html = props.elementInfo.url
|
|
|
- try {
|
|
|
- const parser = new DOMParser()
|
|
|
- const doc = parser.parseFromString(html, 'text/html')
|
|
|
-
|
|
|
- // 1. 重命名页面已有的 $ 变量为 _$,避免与 jQuery 冲突
|
|
|
- // 支持 var/let/const 声明,以及 $(...) 调用和 $.xxx 属性访问
|
|
|
- const scripts = doc.querySelectorAll('script:not([src])')
|
|
|
- scripts.forEach(script => {
|
|
|
- const content = script.textContent || ''
|
|
|
- if (!content) return
|
|
|
- const modified = content
|
|
|
- // 重命名声明:var $ = / let $ = / const $ =
|
|
|
- .replace(/\b(var|let|const)\s+\$\s*=/g, '$1 _$ =')
|
|
|
- // 重命名调用:$('id') → _$('id')
|
|
|
- .replace(/(^|[^a-zA-Z0-9_$])\$\s*\(/g, '$1_$(')
|
|
|
- // 重命名属性访问:$.ajax → _$.ajax
|
|
|
- .replace(/(^|[^a-zA-Z0-9_$])\$\./g, '$1_$.')
|
|
|
- script.textContent = modified
|
|
|
- })
|
|
|
-
|
|
|
- // 2. 在 head 开头注入 jQuery、html2canvas、aws-sdk
|
|
|
- const head = doc.head || doc.getElementsByTagName('head')[0] || doc.createElement('head')
|
|
|
- if (!head.parentNode) {
|
|
|
- doc.documentElement.insertBefore(head, doc.body || null)
|
|
|
- }
|
|
|
-
|
|
|
- const injectScript = (content: string, prepend = false) => {
|
|
|
- const s = doc.createElement('script')
|
|
|
- s.textContent = content
|
|
|
- if (prepend) head.insertBefore(s, head.firstChild)
|
|
|
- else head.appendChild(s)
|
|
|
- }
|
|
|
-
|
|
|
- // 按顺序注入:jQuery → html2canvas → aws-sdk
|
|
|
- injectScript(jqueryRaw, true)
|
|
|
- injectScript(html2canvasRaw)
|
|
|
- injectScript(awsSdkRaw)
|
|
|
-
|
|
|
- // 3. 在 body 末尾追加 jietu.js(此时 $ 是 jQuery)
|
|
|
- const body = doc.body || doc.getElementsByTagName('body')[0]
|
|
|
- if (body) {
|
|
|
- const jietuScript = doc.createElement('script')
|
|
|
- jietuScript.textContent = jietuRaw
|
|
|
- body.appendChild(jietuScript)
|
|
|
- }
|
|
|
-
|
|
|
- return '<!DOCTYPE html>' + doc.documentElement.outerHTML
|
|
|
- }
|
|
|
- catch (e) {
|
|
|
- console.error('处理 srcdoc 失败:', e)
|
|
|
- return html
|
|
|
- }
|
|
|
-})
|
|
|
-
|
|
|
// 监听elementInfo.url的变化
|
|
|
watch(
|
|
|
() => props.elementInfo.url,
|
|
|
@@ -261,13 +198,78 @@ const getTypeLabel = (type: number): string => {
|
|
|
|
|
|
const frameloading = ref(false)
|
|
|
|
|
|
-// 处理iframe加载完成事件(脚本已在 srcdoc 中内联注入,这里只需隐藏 loading)
|
|
|
-const handleIframeLoad = async () => {
|
|
|
+// 处理iframe加载完成事件
|
|
|
+const handleIframeLoad = async (event: Event) => {
|
|
|
+ const iframe = event.target as HTMLIFrameElement
|
|
|
frameloading.value = true
|
|
|
- await nextTick()
|
|
|
- setTimeout(() => {
|
|
|
+ try {
|
|
|
+ // 等待iframe完全加载
|
|
|
+ await nextTick()
|
|
|
+ setTimeout(async () => {
|
|
|
+ // 检查iframe是否可访问(同源检查)
|
|
|
+ if (iframe.contentWindow && iframe.contentDocument) {
|
|
|
+ const iframeDoc = iframe.contentDocument
|
|
|
+ const iframeHead =
|
|
|
+ iframeDoc.head || iframeDoc.getElementsByTagName('head')[0]
|
|
|
+
|
|
|
+ if (iframeHead) {
|
|
|
+ // 使用动态导入获取JS文件内容
|
|
|
+ const jsFiles = [
|
|
|
+ {
|
|
|
+ id: 'aws-sdk',
|
|
|
+ importPath: () => import('./aws-sdk-2.235.1.min.js?raw'),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 'jquery',
|
|
|
+ importPath: () => import('./jquery-3.6.0.min.js?raw'),
|
|
|
+ },
|
|
|
+ { id: 'jietu', importPath: () => import('./jietu.js?raw') },
|
|
|
+ ]
|
|
|
+
|
|
|
+ for (const jsFile of jsFiles) {
|
|
|
+ try {
|
|
|
+ // 检查是否已经注入过
|
|
|
+ if (!iframeDoc.getElementById(jsFile.id)) {
|
|
|
+ const jsModule = await jsFile.importPath()
|
|
|
+ const jsContent = jsModule.default || jsModule
|
|
|
+
|
|
|
+ const scriptElement = iframeDoc.createElement('script')
|
|
|
+ scriptElement.id = jsFile.id
|
|
|
+ scriptElement.textContent = jsContent
|
|
|
+ iframeHead.appendChild(scriptElement)
|
|
|
+
|
|
|
+ console.log(`已注入 ${jsFile.id} 到iframe中`)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (fetchError) {
|
|
|
+ console.error(`获取 ${jsFile.id} 失败:`, fetchError)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ frameloading.value = false
|
|
|
+
|
|
|
+ // 可选:在iframe中执行一些初始化代码
|
|
|
+ try {
|
|
|
+ iframe.contentWindow.eval(`
|
|
|
+ console.log('iframe中的JS环境已准备就绪');
|
|
|
+ // 这里可以添加一些初始化代码
|
|
|
+ `)
|
|
|
+ }
|
|
|
+ catch (evalError) {
|
|
|
+ frameloading.value = false
|
|
|
+ console.warn('无法在iframe中执行代码:', evalError)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ frameloading.value = false
|
|
|
+ console.warn('无法访问iframe内容,可能是跨域限制')
|
|
|
+ }
|
|
|
+ }, 1000)
|
|
|
+ }
|
|
|
+ catch (error) {
|
|
|
frameloading.value = false
|
|
|
- }, 500)
|
|
|
+ console.error('注入JS到iframe失败:', error)
|
|
|
+ }
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
@@ -432,4 +434,4 @@ const handleIframeLoad = async () => {
|
|
|
transform: rotate(360deg);
|
|
|
}
|
|
|
}
|
|
|
-</style>
|
|
|
+</style>
|