|
@@ -1,6 +1,7 @@
|
|
|
-import { Component, OnInit, ViewChild, ElementRef, AfterViewInit, OnDestroy } from '@angular/core';
|
|
|
+import { Component, OnInit, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
|
|
|
import { CommonModule } from '@angular/common';
|
|
|
import * as echarts from 'echarts';
|
|
|
+import { AiApiService } from '../../../../lib/ai-api.service';
|
|
|
|
|
|
@Component({
|
|
|
selector: 'app-page-interview',
|
|
@@ -9,197 +10,343 @@ import * as echarts from 'echarts';
|
|
|
templateUrl: './page-interview.html',
|
|
|
styleUrl: './page-interview.scss'
|
|
|
})
|
|
|
-export class PageInterview implements OnInit, AfterViewInit, OnDestroy {
|
|
|
- // 倒计时相关属性
|
|
|
- remainingTime: string = '30:00';
|
|
|
- remainingMinutes: number = 30;
|
|
|
- remainingSeconds: number = 0;
|
|
|
- timerInterval: any;
|
|
|
-
|
|
|
- // 其他现有属性保持不变
|
|
|
+export class PageInterview implements OnInit, AfterViewInit {
|
|
|
+ // 计时相关
|
|
|
+ remainingTime = '10:00';
|
|
|
+ progress = 0;
|
|
|
+
|
|
|
+ // 面试状态控制
|
|
|
+ interviewEnded = false;
|
|
|
isAnalyzing = false;
|
|
|
showSubmitButton = false;
|
|
|
- userAnswer = '';
|
|
|
+ showCancelButton = false;
|
|
|
+ isFollowUpQuestion = false;
|
|
|
+ showQuestionCard = true;
|
|
|
+ showRadarChart = false;
|
|
|
|
|
|
- avatarImages = {
|
|
|
- default: 'data:image/svg+xml;base64,...',
|
|
|
- speaking: 'data:image/svg+xml;base64,...',
|
|
|
- };
|
|
|
-
|
|
|
- questions = [
|
|
|
- "欢迎参加本次AI面试,我是您的面试官AI助手。",
|
|
|
+ // 语音相关
|
|
|
+ isListening = false;
|
|
|
+ isSpeaking = false;
|
|
|
+ userAnswer = '';
|
|
|
+ recognition: any;
|
|
|
+ interimTranscript = '';
|
|
|
+ // 问题列表
|
|
|
+ mainQuestions = [
|
|
|
+ "欢迎参加本次AI面试,我是您的面试官AI助手。",
|
|
|
"首先,请简单介绍一下您自己。",
|
|
|
"您在过去工作中遇到的最大技术挑战是什么?您是如何解决的?",
|
|
|
"请描述一个您与团队意见不合时,您是如何处理的案例。"
|
|
|
];
|
|
|
|
|
|
currentQuestionIndex = 0;
|
|
|
- currentQuestion = this.questions[0];
|
|
|
- showQuestionCard = false;
|
|
|
- progress = 30;
|
|
|
+ currentQuestion = this.mainQuestions[0];
|
|
|
|
|
|
+ // 对话记录
|
|
|
messages: {sender: 'ai' | 'user', text: string}[] = [];
|
|
|
|
|
|
- isListening = false;
|
|
|
- isSpeaking = false;
|
|
|
+ // 头像状态
|
|
|
+ avatarImage = "assets/default-avatar.svg";
|
|
|
+ expressionText = "等待开始...";
|
|
|
|
|
|
- avatarImage = "https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/svg/1f913.svg";
|
|
|
- expressionText = "正在聆听您的回答...";
|
|
|
-
|
|
|
- showRadarChart = false;
|
|
|
+ // 评估指标
|
|
|
metrics = {
|
|
|
- expressiveness: 82,
|
|
|
- professionalism: 65,
|
|
|
- relevance: 73
|
|
|
+ expressiveness: 0,
|
|
|
+ professionalism: 0,
|
|
|
+ relevance: 0
|
|
|
};
|
|
|
-
|
|
|
- presetAnswers = [
|
|
|
- "我是张伟,有5年Java开发经验,擅长分布式系统设计。",
|
|
|
- "我们曾遇到高并发下的数据库瓶颈,我通过引入Redis缓存和分库分表解决了问题。",
|
|
|
- "有一次在技术方案选择上,我通过数据对比和原型验证说服了团队采用我的方案。"
|
|
|
- ];
|
|
|
-
|
|
|
+
|
|
|
@ViewChild('dialogContainer') dialogContainer!: ElementRef;
|
|
|
private radarChart: any;
|
|
|
|
|
|
+ constructor(private aiService: AiApiService) {
|
|
|
+ // 初始化语音识别
|
|
|
+ this.initSpeechRecognition();
|
|
|
+ }
|
|
|
+
|
|
|
ngOnInit(): void {
|
|
|
this.initConversation();
|
|
|
- this.startCountdown(); // 启动倒计时
|
|
|
+ this.initProgressTimer();
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
ngAfterViewInit(): void {
|
|
|
this.initRadarChart();
|
|
|
}
|
|
|
-
|
|
|
- ngOnDestroy(): void {
|
|
|
- if (this.timerInterval) {
|
|
|
- clearInterval(this.timerInterval);
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
- // 倒计时相关方法
|
|
|
- private startCountdown() {
|
|
|
- this.updateTimeDisplay();
|
|
|
-
|
|
|
- this.timerInterval = setInterval(() => {
|
|
|
- if (this.remainingSeconds > 0) {
|
|
|
- this.remainingSeconds--;
|
|
|
- } else {
|
|
|
- if (this.remainingMinutes > 0) {
|
|
|
- this.remainingMinutes--;
|
|
|
- this.remainingSeconds = 59;
|
|
|
- } else {
|
|
|
- clearInterval(this.timerInterval);
|
|
|
- this.handleTimeUp();
|
|
|
+
|
|
|
+
|
|
|
+ private initSpeechRecognition() {
|
|
|
+ const SpeechRecognition = (window as any).SpeechRecognition || (window as any).webkitSpeechRecognition;
|
|
|
+ if (SpeechRecognition) {
|
|
|
+ this.recognition = new SpeechRecognition();
|
|
|
+ this.recognition.lang = 'zh-CN';
|
|
|
+ this.recognition.interimResults = true; // 启用临时结果
|
|
|
+ this.recognition.continuous = true;
|
|
|
+
|
|
|
+ this.recognition.onresult = (event: any) => {
|
|
|
+ let finalTranscript = '';
|
|
|
+ let interimTranscript = '';
|
|
|
+
|
|
|
+ for (let i = event.resultIndex; i < event.results.length; i++) {
|
|
|
+ const transcript = event.results[i][0].transcript;
|
|
|
+ if (event.results[i].isFinal) {
|
|
|
+ finalTranscript += transcript;
|
|
|
+ } else {
|
|
|
+ interimTranscript += transcript;
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- this.updateTimeDisplay();
|
|
|
- }, 1000);
|
|
|
- }
|
|
|
|
|
|
- private updateTimeDisplay() {
|
|
|
- const mins = this.remainingMinutes.toString().padStart(2, '0');
|
|
|
- const secs = this.remainingSeconds.toString().padStart(2, '0');
|
|
|
- this.remainingTime = `${mins}:${secs}`;
|
|
|
+ if (finalTranscript) {
|
|
|
+ this.userAnswer = finalTranscript;
|
|
|
+ this.showSubmitButton = true;
|
|
|
+ this.showCancelButton = true;
|
|
|
+ }
|
|
|
+ this.interimTranscript = interimTranscript;
|
|
|
+ };
|
|
|
+
|
|
|
+ this.recognition.onerror = (event: any) => {
|
|
|
+ console.error('语音识别错误:', event.error);
|
|
|
+ this.updateAvatarState('listening');
|
|
|
+ };
|
|
|
+
|
|
|
+ this.recognition.onend = () => {
|
|
|
+ if (this.isListening) {
|
|
|
+ this.stopVoiceInput();
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- private handleTimeUp() {
|
|
|
- this.addAIMessage("面试时间已结束,系统将自动提交您的回答");
|
|
|
- this.submitAnswer();
|
|
|
+ private initProgressTimer(): void {
|
|
|
+ const totalSeconds = 10 * 60; // 10分钟 = 600秒
|
|
|
+ let elapsedSeconds = 0;
|
|
|
+
|
|
|
+ const timer = setInterval(() => {
|
|
|
+ if (this.interviewEnded) {
|
|
|
+ clearInterval(timer);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ elapsedSeconds++;
|
|
|
+ this.progress = Math.min((elapsedSeconds / totalSeconds) * 100, 100);
|
|
|
+
|
|
|
+ // 更新时间显示
|
|
|
+ const remainingSeconds = totalSeconds - elapsedSeconds;
|
|
|
+ const minutes = Math.floor(remainingSeconds / 60);
|
|
|
+ const seconds = remainingSeconds % 60;
|
|
|
+ this.remainingTime = `${minutes}:${seconds < 10 ? '0' + seconds : seconds}`;
|
|
|
+
|
|
|
+ // 时间到自动结束
|
|
|
+ if (elapsedSeconds >= totalSeconds) {
|
|
|
+ clearInterval(timer);
|
|
|
+ this.addAIMessage("时间到,本次面试结束");
|
|
|
+ this.interviewEnded = true;
|
|
|
+ }
|
|
|
+ }, 1000); // 改为每秒更新一次
|
|
|
}
|
|
|
|
|
|
- // 其他现有方法保持不变
|
|
|
initConversation(): void {
|
|
|
- this.addAIMessage(this.questions[0]);
|
|
|
+ this.addAIMessage(this.mainQuestions[0]);
|
|
|
setTimeout(() => {
|
|
|
this.askQuestion(1);
|
|
|
}, 1500);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
askQuestion(index: number): void {
|
|
|
- if (index >= this.questions.length) return;
|
|
|
+ if (index >= this.mainQuestions.length || this.interviewEnded) {
|
|
|
+ this.endInterview();
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
this.currentQuestionIndex = index;
|
|
|
- this.currentQuestion = this.questions[index];
|
|
|
+ this.isFollowUpQuestion = false;
|
|
|
+ this.currentQuestion = this.mainQuestions[index];
|
|
|
+
|
|
|
this.addAIMessage(this.currentQuestion);
|
|
|
- this.avatarImage = "https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/svg/1f4ac.svg";
|
|
|
- this.expressionText = "等待您的回答...";
|
|
|
+ this.updateAvatarState('speaking');
|
|
|
+ this.speakText(this.currentQuestion); // 自动语音播放问题
|
|
|
}
|
|
|
-
|
|
|
- addAIMessage(text: string): void {
|
|
|
- this.messages.push({ sender: 'ai', text: text });
|
|
|
+
|
|
|
+ async askFollowUpQuestion(followUpText: string): Promise<void> {
|
|
|
+ if (this.interviewEnded) return;
|
|
|
+
|
|
|
+ this.isFollowUpQuestion = true;
|
|
|
+ this.currentQuestion = followUpText;
|
|
|
+
|
|
|
+ this.addAIMessage("关于您刚才的回答,我有一个跟进问题...");
|
|
|
setTimeout(() => {
|
|
|
- this.dialogContainer.nativeElement.scrollTop = this.dialogContainer.nativeElement.scrollHeight;
|
|
|
- }, 0);
|
|
|
- this.speakText(text);
|
|
|
+ this.addAIMessage(this.currentQuestion);
|
|
|
+ this.updateAvatarState('speaking');
|
|
|
+ }, 1000);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ endInterview(): void {
|
|
|
+ this.interviewEnded = true;
|
|
|
+ this.addAIMessage("感谢您参与本次面试,祝您有美好的一天!");
|
|
|
+ this.updateAvatarState('default');
|
|
|
+ }
|
|
|
+
|
|
|
+ restartInterview(): void {
|
|
|
+ this.interviewEnded = false;
|
|
|
+ this.currentQuestionIndex = 0;
|
|
|
+ this.currentQuestion = this.mainQuestions[0];
|
|
|
+ this.messages = [];
|
|
|
+ this.metrics = { expressiveness: 0, professionalism: 0, relevance: 0 };
|
|
|
+ this.progress = 0;
|
|
|
+ this.initConversation();
|
|
|
+ }
|
|
|
+
|
|
|
+ addAIMessage(text: string): void {
|
|
|
+ this.messages.push({
|
|
|
+ sender: 'ai',
|
|
|
+ text: text
|
|
|
+ });
|
|
|
+ this.scrollToBottom();
|
|
|
+ }
|
|
|
+
|
|
|
addUserMessage(text: string): void {
|
|
|
- this.messages.push({ sender: 'user', text: text });
|
|
|
+ this.messages.push({
|
|
|
+ sender: 'user',
|
|
|
+ text: text
|
|
|
+ });
|
|
|
+ this.scrollToBottom();
|
|
|
+ }
|
|
|
+
|
|
|
+ private scrollToBottom(): void {
|
|
|
setTimeout(() => {
|
|
|
this.dialogContainer.nativeElement.scrollTop = this.dialogContainer.nativeElement.scrollHeight;
|
|
|
}, 0);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
speakText(text: string): void {
|
|
|
- if (this.isSpeaking) return;
|
|
|
+ if (this.isSpeaking || !text) return;
|
|
|
|
|
|
this.isSpeaking = true;
|
|
|
- this.avatarImage = "https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/svg/1f5e3.svg";
|
|
|
- this.expressionText = "正在播报问题...";
|
|
|
-
|
|
|
+ this.updateAvatarState('speaking');
|
|
|
+
|
|
|
const utterance = new SpeechSynthesisUtterance(text);
|
|
|
utterance.lang = 'zh-CN';
|
|
|
utterance.rate = 0.9;
|
|
|
utterance.pitch = 1;
|
|
|
-
|
|
|
+
|
|
|
utterance.onend = () => {
|
|
|
this.isSpeaking = false;
|
|
|
- this.avatarImage = "https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/svg/1f4ac.svg";
|
|
|
- this.expressionText = "等待您的回答...";
|
|
|
+ if (!this.interviewEnded) {
|
|
|
+ this.updateAvatarState('listening');
|
|
|
+ }
|
|
|
};
|
|
|
-
|
|
|
+
|
|
|
speechSynthesis.speak(utterance);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
startVoiceInput(): void {
|
|
|
+ if (!this.recognition || this.isSpeaking || this.isAnalyzing) return;
|
|
|
+
|
|
|
this.isListening = true;
|
|
|
- this.expressionText = "正在聆听您的回答...";
|
|
|
+ this.userAnswer = '';
|
|
|
+ this.updateAvatarState('listening');
|
|
|
+ this.recognition.start();
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
stopVoiceInput(): void {
|
|
|
this.isListening = false;
|
|
|
- this.userAnswer = this.presetAnswers[this.currentQuestionIndex - 1] || "这是我的回答...";
|
|
|
- this.showSubmitButton = true;
|
|
|
- this.avatarImage = this.avatarImages.default;
|
|
|
- this.expressionText = "请确认您的回答";
|
|
|
+ if (this.recognition) {
|
|
|
+ this.recognition.stop();
|
|
|
+ }
|
|
|
+ this.updateAvatarState('waiting');
|
|
|
}
|
|
|
-
|
|
|
- submitAnswer(): void {
|
|
|
+
|
|
|
+ async submitAnswer(): Promise<void> {
|
|
|
+ if (!this.userAnswer || this.isAnalyzing) return;
|
|
|
+
|
|
|
this.showSubmitButton = false;
|
|
|
+ this.showCancelButton = false;
|
|
|
this.addUserMessage(this.userAnswer);
|
|
|
- this.isAnalyzing = true;
|
|
|
- this.avatarImage = this.avatarImages.default;
|
|
|
- this.expressionText = "正在分析您的回答...";
|
|
|
|
|
|
- setTimeout(() => {
|
|
|
- this.isAnalyzing = false;
|
|
|
- if (this.currentQuestionIndex < this.questions.length - 1) {
|
|
|
- this.askQuestion(this.currentQuestionIndex + 1);
|
|
|
+ this.isAnalyzing = true;
|
|
|
+ this.updateAvatarState('analyzing');
|
|
|
+
|
|
|
+ try {
|
|
|
+ const evaluation = await this.aiService.evaluateInterviewAnswer(
|
|
|
+ this.currentQuestion,
|
|
|
+ this.userAnswer
|
|
|
+ );
|
|
|
+
|
|
|
+ // 更新评估指标
|
|
|
+ this.metrics = {
|
|
|
+ expressiveness: evaluation.metrics.expressiveness,
|
|
|
+ professionalism: evaluation.metrics.professionalism,
|
|
|
+ relevance: evaluation.metrics.relevance
|
|
|
+ };
|
|
|
+
|
|
|
+ // 添加AI反馈
|
|
|
+ this.addAIMessage(evaluation.feedback);
|
|
|
+
|
|
|
+ // 检查回答相关性
|
|
|
+ if (evaluation.metrics.relevance < 30) {
|
|
|
+ this.addAIMessage("您的回答与问题相关性较低,本次面试结束。");
|
|
|
+ this.interviewEnded = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理问题流程
|
|
|
+ if (!this.isFollowUpQuestion && this.currentQuestionIndex !== 1) {
|
|
|
+ // 主问题(非自我介绍)需要追问
|
|
|
+ setTimeout(() => {
|
|
|
+ this.askFollowUpQuestion(evaluation.followUpQuestion);
|
|
|
+ }, 1500);
|
|
|
} else {
|
|
|
- this.addAIMessage("感谢您的回答,面试即将结束,正在生成最终报告...");
|
|
|
- this.avatarImage = this.avatarImages.speaking;
|
|
|
- this.expressionText = "生成最终评估中...";
|
|
|
+ // 进入下一个问题
|
|
|
+ setTimeout(() => {
|
|
|
+ this.askQuestion(this.currentQuestionIndex + 1);
|
|
|
+ }, 1500);
|
|
|
}
|
|
|
- }, 2000);
|
|
|
+ } catch (error) {
|
|
|
+ console.error('评估失败:', error);
|
|
|
+ this.addAIMessage("分析完成,让我们继续下一个问题");
|
|
|
+ this.askQuestion(this.currentQuestionIndex + 1);
|
|
|
+ } finally {
|
|
|
+ this.isAnalyzing = false;
|
|
|
+ this.userAnswer = '';
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ cancelAnswer(): void {
|
|
|
+ this.showSubmitButton = false;
|
|
|
+ this.showCancelButton = false;
|
|
|
+ this.userAnswer = '';
|
|
|
+ this.updateAvatarState('listening');
|
|
|
+ }
|
|
|
+
|
|
|
playQuestion(): void {
|
|
|
- if (!this.isSpeaking) {
|
|
|
- this.speakText(this.questions[this.currentQuestionIndex]);
|
|
|
+ if (!this.isListening && !this.isSpeaking) {
|
|
|
+ this.speakText(this.currentQuestion);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ updateAvatarState(state: 'speaking' | 'listening' | 'waiting' | 'analyzing' | 'default'): void {
|
|
|
+ switch(state) {
|
|
|
+ case 'speaking':
|
|
|
+ this.avatarImage = "assets/ai-speaking.svg";
|
|
|
+ this.expressionText = "正在提问...";
|
|
|
+ break;
|
|
|
+ case 'listening':
|
|
|
+ this.avatarImage = "assets/ai-listening.svg";
|
|
|
+ this.expressionText = "正在聆听...";
|
|
|
+ break;
|
|
|
+ case 'waiting':
|
|
|
+ this.avatarImage = "assets/ai-waiting.svg";
|
|
|
+ this.expressionText = "等待确认...";
|
|
|
+ break;
|
|
|
+ case 'analyzing':
|
|
|
+ this.avatarImage = "assets/ai-analyzing.svg";
|
|
|
+ this.expressionText = "分析回答中...";
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ this.avatarImage = "assets/default-avatar.svg";
|
|
|
+ this.expressionText = "AI面试官";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
toggleRadarChart(): void {
|
|
|
this.showRadarChart = !this.showRadarChart;
|
|
|
if (this.showRadarChart) {
|
|
@@ -208,9 +355,9 @@ export class PageInterview implements OnInit, AfterViewInit, OnDestroy {
|
|
|
}, 0);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- initRadarChart(): void {
|
|
|
- if (!this.showRadarChart) return;
|
|
|
+
|
|
|
+ private initRadarChart(): void {
|
|
|
+ if (!this.showRadarChart || this.interviewEnded) return;
|
|
|
|
|
|
const chartDom = document.getElementById('radarChart');
|
|
|
if (!chartDom) return;
|
|
@@ -235,55 +382,34 @@ export class PageInterview implements OnInit, AfterViewInit, OnDestroy {
|
|
|
{ name: '知识广度', max: 100 }
|
|
|
],
|
|
|
radius: '65%',
|
|
|
- axisName: {
|
|
|
- color: '#4A5568'
|
|
|
- },
|
|
|
- splitArea: {
|
|
|
- areaStyle: {
|
|
|
- color: ['rgba(42, 92, 170, 0.1)']
|
|
|
- }
|
|
|
- },
|
|
|
- axisLine: {
|
|
|
- lineStyle: {
|
|
|
- color: 'rgba(42, 92, 170, 0.3)'
|
|
|
- }
|
|
|
- },
|
|
|
- splitLine: {
|
|
|
- lineStyle: {
|
|
|
- color: 'rgba(42, 92, 170, 0.3)'
|
|
|
- }
|
|
|
- }
|
|
|
+ axisName: { color: '#4A5568' },
|
|
|
+ splitArea: { areaStyle: { color: ['rgba(42, 92, 170, 0.1)'] } },
|
|
|
+ axisLine: { lineStyle: { color: 'rgba(42, 92, 170, 0.3)' } },
|
|
|
+ splitLine: { lineStyle: { color: 'rgba(42, 92, 170, 0.3)' } }
|
|
|
},
|
|
|
series: [{
|
|
|
type: 'radar',
|
|
|
data: [
|
|
|
{
|
|
|
- value: [82, 65, 73, 68, 75, 60],
|
|
|
+ value: [
|
|
|
+ this.metrics.expressiveness,
|
|
|
+ this.metrics.professionalism,
|
|
|
+ this.metrics.relevance,
|
|
|
+ (this.metrics.expressiveness + this.metrics.professionalism) / 2,
|
|
|
+ this.metrics.expressiveness,
|
|
|
+ this.metrics.professionalism
|
|
|
+ ],
|
|
|
name: '当前表现',
|
|
|
- areaStyle: {
|
|
|
- color: 'rgba(42, 92, 170, 0.4)'
|
|
|
- },
|
|
|
- lineStyle: {
|
|
|
- width: 2,
|
|
|
- color: 'rgba(42, 92, 170, 0.8)'
|
|
|
- },
|
|
|
- itemStyle: {
|
|
|
- color: '#2A5CAA'
|
|
|
- }
|
|
|
+ areaStyle: { color: 'rgba(42, 92, 170, 0.4)' },
|
|
|
+ lineStyle: { width: 2, color: 'rgba(42, 92, 170, 0.8)' },
|
|
|
+ itemStyle: { color: '#2A5CAA' }
|
|
|
},
|
|
|
{
|
|
|
value: [70, 80, 85, 75, 65, 70],
|
|
|
name: '岗位要求',
|
|
|
- areaStyle: {
|
|
|
- color: 'rgba(255, 107, 53, 0.2)'
|
|
|
- },
|
|
|
- lineStyle: {
|
|
|
- width: 2,
|
|
|
- color: 'rgba(255, 107, 53, 0.8)'
|
|
|
- },
|
|
|
- itemStyle: {
|
|
|
- color: '#FF6B35'
|
|
|
- }
|
|
|
+ areaStyle: { color: 'rgba(255, 107, 53, 0.2)' },
|
|
|
+ lineStyle: { width: 2, color: 'rgba(255, 107, 53, 0.8)' },
|
|
|
+ itemStyle: { color: '#FF6B35' }
|
|
|
}
|
|
|
]
|
|
|
}]
|
|
@@ -295,4 +421,6 @@ export class PageInterview implements OnInit, AfterViewInit, OnDestroy {
|
|
|
this.radarChart?.resize();
|
|
|
});
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
}
|