|
@@ -165,6 +165,7 @@
|
|
|
<tr>
|
|
<tr>
|
|
|
<th class="th-num">#</th>
|
|
<th class="th-num">#</th>
|
|
|
<th>任务与工具</th>
|
|
<th>任务与工具</th>
|
|
|
|
|
+ <th class="th-center">所在页码</th>
|
|
|
<th class="th-center">提交率</th>
|
|
<th class="th-center">提交率</th>
|
|
|
<th class="th-center">正确率</th>
|
|
<th class="th-center">正确率</th>
|
|
|
<th class="th-center">互动次数</th>
|
|
<th class="th-center">互动次数</th>
|
|
@@ -173,31 +174,16 @@
|
|
|
</tr>
|
|
</tr>
|
|
|
</thead>
|
|
</thead>
|
|
|
<tbody>
|
|
<tbody>
|
|
|
- <tr v-for="task in tasks" :key="task.id" class="table-row">
|
|
|
|
|
- <td class="td-num">{{ task.id }}</td>
|
|
|
|
|
|
|
+ <tr v-for="(task, idx) in tasks" :key="task.id" class="table-row">
|
|
|
|
|
+ <td class="td-num">{{ idx + 1 }}</td>
|
|
|
<td>
|
|
<td>
|
|
|
<div class="task-name">{{ task.name }}</div>
|
|
<div class="task-name">{{ task.name }}</div>
|
|
|
<div class="task-type">
|
|
<div class="task-type">
|
|
|
- <svg
|
|
|
|
|
- class="task-type-icon"
|
|
|
|
|
- :style="{ color: task.typeIconColor }"
|
|
|
|
|
- width="14"
|
|
|
|
|
- height="14"
|
|
|
|
|
- viewBox="0 0 24 24"
|
|
|
|
|
- fill="currentColor"
|
|
|
|
|
- >
|
|
|
|
|
- <path :d="task.typeIconPath" />
|
|
|
|
|
- </svg>
|
|
|
|
|
{{ task.type }}
|
|
{{ task.type }}
|
|
|
- <!-- <span v-if="task.aiRounds" class="ai-rounds-badge">
|
|
|
|
|
- <svg width="10" height="10" viewBox="0 0 24 24" fill="currentColor">
|
|
|
|
|
- <path d="M12 2l1.8 6L20 9.8l-6 1.8L12 18l-1.8-6.4L4 9.8l6.2-1.8z" />
|
|
|
|
|
- </svg>
|
|
|
|
|
- {{ task.aiRounds }}
|
|
|
|
|
- </span> -->
|
|
|
|
|
</div>
|
|
</div>
|
|
|
</td>
|
|
</td>
|
|
|
- <td class="td-center td-extrabold">{{ task.submitRate }}</td>
|
|
|
|
|
|
|
+ <td class="td-center">{{ task.task + 1 }}</td>
|
|
|
|
|
+ <td class="td-center td-extrabold">{{ task.submitRate }}%</td>
|
|
|
<td class="td-center">
|
|
<td class="td-center">
|
|
|
<span
|
|
<span
|
|
|
v-if="task.accuracy !== '—'"
|
|
v-if="task.accuracy !== '—'"
|
|
@@ -205,11 +191,11 @@
|
|
|
>{{ task.accuracy }}</span>
|
|
>{{ task.accuracy }}</span>
|
|
|
<span v-else class="accuracy-dash">{{ task.accuracy }}</span>
|
|
<span v-else class="accuracy-dash">{{ task.accuracy }}</span>
|
|
|
</td>
|
|
</td>
|
|
|
- <td class="td-center td-bold-700">{{ task.interactions }}</td>
|
|
|
|
|
|
|
+ <td class="td-center td-bold-700">{{ task.interactions }}次</td>
|
|
|
<!-- <td class="td-center td-medium">{{ task.avgTime }}</td> -->
|
|
<!-- <td class="td-center td-medium">{{ task.avgTime }}</td> -->
|
|
|
<td class="td-insight">
|
|
<td class="td-insight">
|
|
|
<div class="insight-text">
|
|
<div class="insight-text">
|
|
|
- {{ task.insightPrefix }}<strong v-if="task.insightStrong" class="insight-strong">{{ task.insightStrong }}</strong>{{ task.insightSuffix }}
|
|
|
|
|
|
|
+ {{ task.aiExplanation }}
|
|
|
</div>
|
|
</div>
|
|
|
</td>
|
|
</td>
|
|
|
</tr>
|
|
</tr>
|
|
@@ -355,11 +341,11 @@ export default {
|
|
|
searchKeyword: '',
|
|
searchKeyword: '',
|
|
|
chartInstance: null,
|
|
chartInstance: null,
|
|
|
kpis: [
|
|
kpis: [
|
|
|
- { value: '90%', suffix: '', label: '出勤率', sub: '(45/50人)', color: '#F97316' },
|
|
|
|
|
- { value: '89%', suffix: '', label: '平均提交率', sub: '(313次提交)', color: '#10B981' },
|
|
|
|
|
|
|
+ { value: '0', suffix: '', label: '出勤率', sub: '(0/0人)', color: '#F97316' },
|
|
|
|
|
+ { value: '0', suffix: '', label: '平均提交率', sub: '(0次提交)', color: '#10B981' },
|
|
|
// { value: '64%', suffix: '', label: '平均正确率', sub: '(最高94%·最低25%)', color: '#10B981' },
|
|
// { value: '64%', suffix: '', label: '平均正确率', sub: '(最高94%·最低25%)', color: '#10B981' },
|
|
|
- { value: '4', suffix: '轮', label: 'AI 轮次', sub: '(最多7·最少0)', color: '#3B82F6' },
|
|
|
|
|
- { value: '47', suffix: '', label: '总互动量', sub: '(总点赞数)', color: '#EC4899' }
|
|
|
|
|
|
|
+ { value: '0', suffix: '轮', label: 'AI 轮次', sub: '(最多7·最少0)', color: '#3B82F6' },
|
|
|
|
|
+ { value: '0', suffix: '', label: '总互动量', sub: '(总点赞数)', color: '#EC4899' }
|
|
|
],
|
|
],
|
|
|
courseSummary: {
|
|
courseSummary: {
|
|
|
theme: '探索人工智能的起源、核心技术与未来趋势,建立对AI基础概念的准确认知。',
|
|
theme: '探索人工智能的起源、核心技术与未来趋势,建立对AI基础概念的准确认知。',
|
|
@@ -391,54 +377,39 @@ export default {
|
|
|
}
|
|
}
|
|
|
],
|
|
],
|
|
|
tasks: [
|
|
tasks: [
|
|
|
- {
|
|
|
|
|
- id: 1,
|
|
|
|
|
- name: '以下哪项不属于 AI 应用领域',
|
|
|
|
|
- type: '单选题',
|
|
|
|
|
- typeIconPath: 'M12 2a10 10 0 100 20 10 10 0 000-20zm-3 14l-5-5 1.4-1.4L9 13.2l7.6-7.6L18 7l-9 9z',
|
|
|
|
|
- typeIconColor: '#60A5FA',
|
|
|
|
|
- aiRounds: null,
|
|
|
|
|
- submitRate: '86%',
|
|
|
|
|
- accuracy: '60%',
|
|
|
|
|
- accuracyTone: 'tone-orange',
|
|
|
|
|
- interactions: '43 次',
|
|
|
|
|
- avgTime: '1:14',
|
|
|
|
|
- insightPrefix: '概念边界混淆,',
|
|
|
|
|
- insightStrong: '13人错误',
|
|
|
|
|
- insightSuffix: ',建议优先复讲。'
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- id: 2,
|
|
|
|
|
- name: 'AI 应用场景排序',
|
|
|
|
|
- type: '排序题',
|
|
|
|
|
- typeIconPath: 'M3 4h2v2H3V4zm4 0h14v2H7V4zM3 11h2v2H3v-2zm4 0h14v2H7v-2zM3 18h2v2H3v-2zm4 0h14v2H7v-2z',
|
|
|
|
|
- typeIconColor: '#A78BFA',
|
|
|
|
|
- aiRounds: null,
|
|
|
|
|
- submitRate: '90%',
|
|
|
|
|
- accuracy: '70%',
|
|
|
|
|
- accuracyTone: 'tone-emerald',
|
|
|
|
|
- interactions: '45 次',
|
|
|
|
|
- avgTime: '3:43',
|
|
|
|
|
- insightPrefix: '弱AI与强AI基本分清,',
|
|
|
|
|
- insightStrong: '35人完全正确',
|
|
|
|
|
- insightSuffix: '。'
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- id: 3,
|
|
|
|
|
- name: '什么是神经网络?',
|
|
|
|
|
- type: '开放问答',
|
|
|
|
|
- typeIconPath: 'M21 11.5a8.38 8.38 0 01-.9 3.8 8.5 8.5 0 01-7.6 4.7 8.38 8.38 0 01-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 01-.9-3.8 8.5 8.5 0 014.7-7.6 8.38 8.38 0 013.8-.9h.5a8.48 8.48 0 018 8v.5z',
|
|
|
|
|
- typeIconColor: '#818CF8',
|
|
|
|
|
- aiRounds: '4.0轮',
|
|
|
|
|
- submitRate: '90%',
|
|
|
|
|
- accuracy: '—',
|
|
|
|
|
- accuracyTone: '',
|
|
|
|
|
- interactions: '45 次',
|
|
|
|
|
- avgTime: '6:14',
|
|
|
|
|
- insightPrefix: '优秀回答有类比能力,待提升者多停留在表层定义。',
|
|
|
|
|
- insightStrong: '',
|
|
|
|
|
- insightSuffix: ''
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // {
|
|
|
|
|
+ // id: 1,
|
|
|
|
|
+ // name: '以下哪项不属于 AI 应用领域',
|
|
|
|
|
+ // type: '单选题',
|
|
|
|
|
+ // submitRate: '86%',
|
|
|
|
|
+ // accuracy: '60%',
|
|
|
|
|
+ // accuracyTone: 'tone-orange',
|
|
|
|
|
+ // interactions: '43 次',
|
|
|
|
|
+ // avgTime: '1:14',
|
|
|
|
|
+ // aiExplanation: '概念边界混淆,',
|
|
|
|
|
+ // },
|
|
|
|
|
+ // {
|
|
|
|
|
+ // id: 2,
|
|
|
|
|
+ // name: 'AI 应用场景排序',
|
|
|
|
|
+ // type: '排序题',
|
|
|
|
|
+ // submitRate: '90%',
|
|
|
|
|
+ // accuracy: '70%',
|
|
|
|
|
+ // accuracyTone: 'tone-emerald',
|
|
|
|
|
+ // interactions: '45 次',
|
|
|
|
|
+ // avgTime: '3:43',
|
|
|
|
|
+ // aiExplanation: '弱AI与强AI基本分清,',
|
|
|
|
|
+ // },
|
|
|
|
|
+ // {
|
|
|
|
|
+ // id: 3,
|
|
|
|
|
+ // name: '什么是神经网络?',
|
|
|
|
|
+ // type: '开放问答',
|
|
|
|
|
+ // submitRate: '90%',
|
|
|
|
|
+ // accuracy: '—',
|
|
|
|
|
+ // accuracyTone: '',
|
|
|
|
|
+ // interactions: '45 次',
|
|
|
|
|
+ // avgTime: '6:14',
|
|
|
|
|
+ // aiExplanation: '优秀回答有类比能力,待提升者多停留在表层定义。',
|
|
|
|
|
+ // }
|
|
|
],
|
|
],
|
|
|
students: [
|
|
students: [
|
|
|
// { id: 1, name: '张伟', attention: false, tasksDone: 7, tasksTotal: 7, correctRate: '87%', aiRounds: 6, likes: '5/3' },
|
|
// { id: 1, name: '张伟', attention: false, tasksDone: 7, tasksTotal: 7, correctRate: '87%', aiRounds: 6, likes: '5/3' },
|
|
@@ -458,7 +429,19 @@ export default {
|
|
|
grade: '',
|
|
grade: '',
|
|
|
subject: '',
|
|
subject: '',
|
|
|
works: [],
|
|
works: [],
|
|
|
- likesArray: []
|
|
|
|
|
|
|
+ likesArray: [],
|
|
|
|
|
+ taskTool: {
|
|
|
|
|
+ 45: '选择题',
|
|
|
|
|
+ 15: '问答题',
|
|
|
|
|
+ 73: 'h5网页',
|
|
|
|
|
+ 72: '应用中心',
|
|
|
|
|
+ 78: '投票',
|
|
|
|
|
+ 79: '拍照',
|
|
|
|
|
+ 831: 'Kwl表格',
|
|
|
|
|
+ 832: '六顶思考帽',
|
|
|
|
|
+ 84: '文件上传'
|
|
|
|
|
+ },
|
|
|
|
|
+ isAi: [45, 15, 72, 831, 832]
|
|
|
};
|
|
};
|
|
|
},
|
|
},
|
|
|
computed: {
|
|
computed: {
|
|
@@ -468,8 +451,8 @@ export default {
|
|
|
return this.students.filter(s => s.name.toLowerCase().includes(kw));
|
|
return this.students.filter(s => s.name.toLowerCase().includes(kw));
|
|
|
},
|
|
},
|
|
|
getClassClassName() {
|
|
getClassClassName() {
|
|
|
- let name = this.classList.length ? this.classList.filter(item => item.id == this.selectedClass)[0].name || '' : '';
|
|
|
|
|
- return name;
|
|
|
|
|
|
|
+ const cls = this.classList.find(item => item.id === this.selectedClass);
|
|
|
|
|
+ return cls ? cls.name : '';
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
mounted() {
|
|
mounted() {
|
|
@@ -577,7 +560,7 @@ export default {
|
|
|
cid: this.courseDetail.courseId,
|
|
cid: this.courseDetail.courseId,
|
|
|
classid: this.selectedClass
|
|
classid: this.selectedClass
|
|
|
}
|
|
}
|
|
|
- this.ajax.get(this.$store.state.api + "getPPTDataBoard", params).then(res => {
|
|
|
|
|
|
|
+ this.ajax.get(this.$store.state.api + "getPPTDataBoard", params).then(async res => {
|
|
|
this.classstime = res.data[0][0].time;
|
|
this.classstime = res.data[0][0].time;
|
|
|
this.grade = res.data[1].map(item => item.name).join('、');
|
|
this.grade = res.data[1].map(item => item.name).join('、');
|
|
|
this.subject = res.data[2].map(item => item.name).join('、');
|
|
this.subject = res.data[2].map(item => item.name).join('、');
|
|
@@ -592,16 +575,49 @@ export default {
|
|
|
const attendanceRate = attendanceCount / totalStudents;
|
|
const attendanceRate = attendanceCount / totalStudents;
|
|
|
this.kpis[0].value = Math.round(attendanceRate * 100) + '%';
|
|
this.kpis[0].value = Math.round(attendanceRate * 100) + '%';
|
|
|
this.kpis[0].sub = `(${attendanceCount}/${this.students.length}人)`;
|
|
this.kpis[0].sub = `(${attendanceCount}/${this.students.length}人)`;
|
|
|
-
|
|
|
|
|
|
|
+ let tasks = []
|
|
|
// 平均提交率
|
|
// 平均提交率
|
|
|
let pptSlides = this.pptJSON.slides || [];
|
|
let pptSlides = this.pptJSON.slides || [];
|
|
|
let tools = 0;
|
|
let tools = 0;
|
|
|
- const notTool = [74, 75, 76, 82];
|
|
|
|
|
|
|
+ let toolNum = Object.keys(this.taskTool);
|
|
|
for (let i = 0; i < pptSlides.length; i++) {
|
|
for (let i = 0; i < pptSlides.length; i++) {
|
|
|
- const hasSubmissionTool = pptSlides[i].elements.some((element) => {
|
|
|
|
|
- return element.type === 'frame' && !notTool.includes(element.toolType);
|
|
|
|
|
|
|
+ const hasSubmissionTool = pptSlides[i].elements.filter((element) => {
|
|
|
|
|
+ return element.type === 'frame' && toolNum.includes(element.toolType.toString());
|
|
|
});
|
|
});
|
|
|
- if (hasSubmissionTool) {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if (hasSubmissionTool.length > 0) {
|
|
|
|
|
+ const match = hasSubmissionTool[0].url.match(/[?&]id=([^&]+)/)
|
|
|
|
|
+ let id = match[1];
|
|
|
|
|
+ let content = '';
|
|
|
|
|
+ if(hasSubmissionTool[0].toolType == 72){
|
|
|
|
|
+ id = hasSubmissionTool[0].id;
|
|
|
|
|
+ }else {
|
|
|
|
|
+ let work = await this.getWork(id);
|
|
|
|
|
+ try {
|
|
|
|
|
+ let workContent = JSON.parse(work.data[0][0].json);
|
|
|
|
|
+ content = workContent;
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ content = '';
|
|
|
|
|
+ }
|
|
|
|
|
+ console.log(work);
|
|
|
|
|
+ }
|
|
|
|
|
+ tasks.push(
|
|
|
|
|
+ {
|
|
|
|
|
+ id: id,
|
|
|
|
|
+ content: content,
|
|
|
|
|
+ name: this.taskTool[hasSubmissionTool[0].toolType],
|
|
|
|
|
+ type: this.taskTool[hasSubmissionTool[0].toolType],
|
|
|
|
|
+ value: hasSubmissionTool.length,
|
|
|
|
|
+ url: hasSubmissionTool[0].url,
|
|
|
|
|
+ toolType: hasSubmissionTool[0].toolType,
|
|
|
|
|
+ task: i,
|
|
|
|
|
+ students: [],
|
|
|
|
|
+ work: [],
|
|
|
|
|
+ interactions: 0,
|
|
|
|
|
+ accuracy: '—'
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+ console.log(hasSubmissionTool);
|
|
|
tools++;
|
|
tools++;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -619,10 +635,38 @@ export default {
|
|
|
this.kpis[3].value = totalLikes;
|
|
this.kpis[3].value = totalLikes;
|
|
|
this.kpis[3].sub = `(${totalLikes}人点赞)`;
|
|
this.kpis[3].sub = `(${totalLikes}人点赞)`;
|
|
|
|
|
|
|
|
|
|
+ // 任务概况统计
|
|
|
|
|
+ console.log(tasks);
|
|
|
|
|
+ console.log(this.works);
|
|
|
|
|
+ for(let work = 0; work < this.works.length; work++){
|
|
|
|
|
+ for(let task = 0; task < tasks.length; task++){
|
|
|
|
|
+ if(this.works[work].task == tasks[task].task && this.works[work].atool == tasks[task].toolType){
|
|
|
|
|
+ tasks[task].students.push(this.works[work].userid);
|
|
|
|
|
+ tasks[task].work.push(this.works[work].id);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ for (let like = 0; like < this.likesArray.length; like++){
|
|
|
|
|
+ for(let task = 0; task < tasks.length; task++){
|
|
|
|
|
+ if(tasks[task].work.includes(this.likesArray[like].workId)){
|
|
|
|
|
+ tasks[task].interactions++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ for(let task = 0; task < tasks.length; task++){
|
|
|
|
|
+ tasks[task].submitRate = Math.round((tasks[task].students.length / totalStudents) * 100);
|
|
|
|
|
+ }
|
|
|
|
|
+ this.tasks = tasks;
|
|
|
|
|
+
|
|
|
this.loading = false;
|
|
this.loading = false;
|
|
|
}).catch(() => {
|
|
}).catch(() => {
|
|
|
this.loading = false;
|
|
this.loading = false;
|
|
|
})
|
|
})
|
|
|
|
|
+ },
|
|
|
|
|
+ getWork(id) {
|
|
|
|
|
+ return this.ajax.get(this.$store.state.api + "select_workPageById", {
|
|
|
|
|
+ id: id,
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|