lsc 3 dní pred
rodič
commit
08cb83a758
1 zmenil súbory, kde vykonal 103 pridanie a 51 odobranie
  1. 103 51
      src/views/Student/index.vue

+ 103 - 51
src/views/Student/index.vue

@@ -1103,7 +1103,7 @@ const handleHomeworkSubmit = async () => {
           const screenSlides = document.querySelectorAll('.viewer-canvas .screen-slide')
           let iframeElement: HTMLIFrameElement | null = null
 
-          // 直接获取iframe元素本身,而不是其内部文档
+          // 直接获取iframe元素本身
           if (
             screenSlides &&
             screenSlides[slideIndex.value] &&
@@ -1116,7 +1116,7 @@ const handleHomeworkSubmit = async () => {
           }
 
           try {
-            // 直接对iframe元素进行截图,而不是其内部文档
+            // 方案1:使用html2canvas的iframe特殊处理
             const html2canvas = await import('html2canvas')
             const canvas = await html2canvas.default(iframeElement, {
               useCORS: true,
@@ -1124,87 +1124,139 @@ const handleHomeworkSubmit = async () => {
               scale: 1,
               backgroundColor: '#ffffff',
               logging: false,
-              // 对iframe元素进行截图
+              // 关键配置:处理iframe内容
               foreignObjectRendering: true,
               removeContainer: true,
-              // 添加iframe特定的配置
-              ignoreElements: (element) => {
-                // 忽略可能引起问题的元素
-                return element.tagName === 'SCRIPT' || element.tagName === 'STYLE'
+              // 特殊处理iframe
+              onclone: (clonedDoc, element) => {
+                // 在克隆的文档中处理iframe
+                const clonedIframes = clonedDoc.querySelectorAll('iframe')
+                clonedIframes.forEach((iframe) => {
+                  const src = iframe.getAttribute('src')
+                  if (src) {
+                    // 创建一个包含iframe信息的占位符
+                    const placeholder = clonedDoc.createElement('div')
+                    placeholder.style.width = iframe.style.width || iframe.getAttribute('width') || '100%'
+                    placeholder.style.height = iframe.style.height || iframe.getAttribute('height') || '300px'
+                    placeholder.style.backgroundColor = '#f8f9fa'
+                    placeholder.style.border = '2px solid #dee2e6'
+                    placeholder.style.borderRadius = '8px'
+                    placeholder.style.display = 'flex'
+                    placeholder.style.flexDirection = 'column'
+                    placeholder.style.alignItems = 'center'
+                    placeholder.style.justifyContent = 'center'
+                    placeholder.style.padding = '20px'
+                    placeholder.style.fontFamily = 'Arial, sans-serif'
+                    
+                    // 创建iframe占位符内容
+                    placeholder.innerHTML = `
+                      <div style="font-size: 24px; margin-bottom: 10px;">🌐</div>
+                      <div style="font-size: 16px; font-weight: bold; color: #495057; margin-bottom: 8px;">iframe内容</div>
+                      <div style="font-size: 12px; color: #6c757d; text-align: center; word-break: break-all; max-width: 100%;">
+                        ${src.length > 60 ? src.substring(0, 60) + '...' : src}
+                      </div>
+                      <div style="font-size: 10px; color: #adb5bd; margin-top: 8px;">
+                        (跨域限制,无法截图内部内容)
+                      </div>
+                    `
+                    
+                    // 替换iframe
+                    iframe.parentNode?.replaceChild(placeholder, iframe)
+                  }
+                })
               }
             })
             imageData = canvas.toDataURL('image/png', 0.95)
-            console.log('使用html2canvas截图成功')
+            console.log('使用html2canvas iframe特殊处理截图成功')
           }
           catch (html2canvasError) {
-            console.log('html2canvas截图失败,回退到html-to-image:', html2canvasError)
+            console.log('html2canvas iframe处理失败,尝试html-to-image:', html2canvasError)
             
             try {
-              // 回退到html-to-image
+              // 方案2:使用html-to-image
               const { toPng } = await import('html-to-image')
               imageData = await toPng(iframeElement, {
                 quality: 0.95,
-                backgroundColor: '#ffffff'
+                backgroundColor: '#ffffff',
+                // html-to-image的iframe处理
+                filter: (node) => {
+                  // 过滤掉可能引起问题的元素
+                  if (node.tagName === 'SCRIPT' || node.tagName === 'STYLE') {
+                    return false
+                  }
+                  return true
+                }
               })
               console.log('使用html-to-image截图成功')
             }
             catch (htmlToImageError) {
-              console.log('html-to-image也失败了,尝试备用方案:', htmlToImageError)
+              console.log('html-to-image也失败了,使用canvas绘制方案:', htmlToImageError)
               
-              // 最后的备用方案:使用canvas直接绘制iframe
+              // 方案3:使用canvas直接绘制iframe占位符
               const canvas = document.createElement('canvas')
               const ctx = canvas.getContext('2d')
               if (ctx) {
-                canvas.width = iframeElement.offsetWidth
-                canvas.height = iframeElement.offsetHeight
+                // 设置canvas尺寸
+                canvas.width = iframeElement.offsetWidth || 800
+                canvas.height = iframeElement.offsetHeight || 600
                 
-                // 绘制iframe的可见区域
-                ctx.fillStyle = '#ffffff'
+                // 绘制背景
+                const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height)
+                gradient.addColorStop(0, '#f8f9fa')
+                gradient.addColorStop(1, '#e9ecef')
+                ctx.fillStyle = gradient
                 ctx.fillRect(0, 0, canvas.width, canvas.height)
                 
-                // 添加一个提示文本
-                ctx.fillStyle = '#666666'
-                ctx.font = '16px Arial'
+                // 绘制边框
+                ctx.strokeStyle = '#dee2e6'
+                ctx.lineWidth = 3
+                ctx.strokeRect(2, 2, canvas.width - 4, canvas.height - 4)
+                
+                // 绘制内边框
+                ctx.strokeStyle = '#ffffff'
+                ctx.lineWidth = 1
+                ctx.strokeRect(5, 5, canvas.width - 10, canvas.height - 10)
+                
+                // 绘制iframe图标
+                ctx.fillStyle = '#6c757d'
+                ctx.font = 'bold 48px Arial'
                 ctx.textAlign = 'center'
-                ctx.fillText('无法截图iframe内容', canvas.width / 2, canvas.height / 2)
-                ctx.fillText('(跨域限制)', canvas.width / 2, canvas.height / 2 + 20)
+                ctx.fillText('', canvas.width / 2, canvas.height / 2 - 40)
+                
+                // 绘制标题
+                ctx.font = 'bold 20px Arial'
+                ctx.fillStyle = '#495057'
+                ctx.fillText('iframe内容', canvas.width / 2, canvas.height / 2 + 20)
+                
+                // 绘制URL
+                const src = iframeElement.src
+                if (src) {
+                  ctx.font = '14px Arial'
+                  ctx.fillStyle = '#6c757d'
+                  const url = src.length > 80 ? src.substring(0, 80) + '...' : src
+                  ctx.fillText(url, canvas.width / 2, canvas.height / 2 + 50)
+                }
+                
+                // 绘制提示信息
+                ctx.font = '12px Arial'
+                ctx.fillStyle = '#adb5bd'
+                ctx.fillText('(跨域限制,无法截图内部内容)', canvas.width / 2, canvas.height / 2 + 80)
+                
+                // 绘制装饰性元素
+                ctx.strokeStyle = '#dee2e6'
+                ctx.lineWidth = 1
+                ctx.setLineDash([5, 5])
+                ctx.strokeRect(20, 20, canvas.width - 40, canvas.height - 40)
+                ctx.setLineDash([])
                 
                 imageData = canvas.toDataURL('image/png', 0.95)
-                console.log('使用备用方案截图成功')
+                console.log('使用canvas绘制方案截图成功')
               }
               else {
                 throw new Error('无法创建canvas上下文')
               }
             }
           }
-          
-          // 将base64字符串转换为File对象
-          const base64ToFile = (base64String: string, filename: string): File => {
-            const arr = base64String.split(',')
-            const mime = arr[0].match(/:(.*?);/)?.[1] || 'image/png'
-            const bstr = atob(arr[1])
-            let n = bstr.length
-            const u8arr = new Uint8Array(n)
-            while (n--) {
-              u8arr[n] = bstr.charCodeAt(n)
-            }
-            return new File([u8arr], filename, { type: mime })
-          }
-          
-          const imageFile = base64ToFile(imageData, `screenshot_${Date.now()}.png`)
-          const imageUrl = await uploadFile(imageFile)
-          // 提交截图
-          await submitWork(slideIndex.value, '73', imageUrl, '1') // 73表示截图工具,21表示图片类型
-          message.success('页面截图提交成功')
-          hasSubmitWork = true
-          
-          // 发送作业提交成功的socket消息
-          sendMessage({
-            type: 'homework_submitted',
-            courseid: props.courseid,
-            slideIndex: slideIndex.value,
-            userid: props.userid
-          })
         }
         catch (error) {
           console.error('截图提交失败:', error)