You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular组件嵌入Classmarker测试脚本遇未授权错误求助

解决Angular嵌入Classmarker测试的未授权错误问题

问题根源

Classmarker的嵌入脚本会校验挂载上下文,当直接追加到组件元素时,脚本执行上下文与预期的全局(body层级)不匹配,触发权限验证失败;另外Angular的视图封装(ViewEncapsulation)也会干扰脚本的正常加载逻辑。

可行解决方案

方案1:容器+手动初始化iframe(最稳定)

直接绕开第三方脚本的上下文限制,手动创建iframe嵌入测试页面:

  1. 组件模板定义容器:
<div #quizContainer></div>
  1. 组件类中实现加载逻辑:
import { Component, ViewChild, ElementRef, OnInit } from '@angular/core';

@Component({
  selector: 'app-classmarker-quiz',
  template: '<div #quizContainer></div>',
  styleUrls: ['./classmarker-quiz.component.css']
})
export class ClassmarkerQuizComponent implements OnInit {
  @ViewChild('quizContainer') quizContainer!: ElementRef;

  ngOnInit(): void {
    this.initQuizIframe();
  }

  private initQuizIframe(): void {
    const iframe = document.createElement('iframe');
    iframe.src = 'https://www.classmarker.com/online-test/start/?quiz=4p365d69cbe3a608';
    iframe.width = '700';
    iframe.height = '800';
    iframe.frameBorder = '0';
    // 可选:添加 sandbox 属性增强安全性
    // iframe.sandbox = 'allow-forms allow-scripts allow-same-origin';
    this.quizContainer.nativeElement.appendChild(iframe);
  }
}

方案2:关闭组件视图封装

关闭Angular的视图隔离,让脚本的全局逻辑正常生效:

  1. 修改组件装饰器:
import { Component, ViewChild, ElementRef, OnInit, Renderer2 } from '@angular/core';
import { ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'app-classmarker-quiz',
  template: '<div #quizContainer></div>',
  styleUrls: ['./classmarker-quiz.component.css'],
  encapsulation: ViewEncapsulation.None // 关闭视图封装
})
export class ClassmarkerQuizComponent implements OnInit {
  @ViewChild('quizContainer') quizContainer!: ElementRef;

  constructor(private renderer: Renderer2) {}

  ngOnInit(): void {
    const script = this.renderer.createElement('script');
    this.renderer.setAttribute(script, 'src', 'https://www.classmarker.com/public/js/embed-classmarker-1.0.0.js?quiz=4p365d69cbe3a608');
    this.renderer.setAttribute(script, 'data-quiz', '4p365d69cbe3a608');
    this.renderer.setAttribute(script, 'data-width', '700');
    this.renderer.setAttribute(script, 'data-height', '800');
    this.renderer.appendChild(this.quizContainer.nativeElement, script);
  }
}

方案3:全局加载脚本+组件内初始化

先把脚本加载到全局上下文,再在组件容器内初始化:

import { Component, ViewChild, ElementRef, OnInit } from '@angular/core';

@Component({
  selector: 'app-classmarker-quiz',
  template: '<div #quizContainer></div>'
})
export class ClassmarkerQuizComponent implements OnInit {
  @ViewChild('quizContainer') quizContainer!: ElementRef;

  ngOnInit(): void {
    this.loadScriptThenInit();
  }

  private loadScriptThenInit(): void {
    // 避免重复加载脚本
    if (document.querySelector('script[src*="embed-classmarker-1.0.0.js"]')) {
      this.initQuizInContainer();
      return;
    }

    const script = document.createElement('script');
    script.src = 'https://www.classmarker.com/public/js/embed-classmarker-1.0.0.js?quiz=4p365d69cbe3a608';
    script.onload = () => this.initQuizInContainer();
    document.head.appendChild(script);
  }

  private initQuizInContainer(): void {
    // 手动创建带data属性的脚本节点插入容器
    const initScript = document.createElement('script');
    initScript.setAttribute('data-quiz', '4p365d69cbe3a608');
    initScript.setAttribute('data-width', '700');
    initScript.setAttribute('data-height', '800');
    this.quizContainer.nativeElement.appendChild(initScript);
  }
}

注意事项

  • 优先选择方案1,直接嵌入iframe不依赖第三方脚本的加载逻辑,稳定性和兼容性最好
  • 所有方案都要避免重复加载脚本,否则会引发页面异常

内容的提问来源于stack exchange,提问作者Kenath Perera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 17:25:28