|
|
<!--
|
|
|
* @Author: qinzhenpen qzp1807@126.com
|
|
|
* @Date: 2025-03-27 13:40:09
|
|
|
* @LastEditors: qinzhenpen qzp1807@126.com
|
|
|
* @LastEditTime: 2025-05-20 10:47:44
|
|
|
* @FilePath: \corporate-finance\src\components\AI\stu-analysis-of-students.vue
|
|
|
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
|
|
-->
|
|
|
<template>
|
|
|
<div class="stu-analysis-of-students">
|
|
|
<div class="handren-title">
|
|
|
<h3>此处为AI根据学情数据进行的智能分析,从个人成绩和实训时长角度给出分析结果,仅供参考</h3>
|
|
|
</div>
|
|
|
<div class="content">
|
|
|
<el-empty v-if="scoreLoaded && !hasScoreData" class="empty-score" description="暂无成绩数据,暂时无法进行AI学情分析" />
|
|
|
<div v-else class="analysis">
|
|
|
<template v-for="item in dialogue" :key="item.role">
|
|
|
<template v-for="chid in item.child" :key="chid" v-if="item.role == roleId">
|
|
|
<div class="analysis-item" @click="analysis(chid)">{{ chid.name }}</div>
|
|
|
</template>
|
|
|
</template>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
<script setup>
|
|
|
import * as scoreApi from "@/api/teacher.js";
|
|
|
import useUserStore from "@/store/modules/user";
|
|
|
import * as indexApi from "@/api/index";
|
|
|
|
|
|
const userStore = useUserStore();
|
|
|
const { proxy } = getCurrentInstance();
|
|
|
const router = useRouter();
|
|
|
const roleId = computed(() => {
|
|
|
return userStore.userInfo.roleId;
|
|
|
});
|
|
|
const moduleMap = [
|
|
|
{ key: "cppgkh", name: "产品评估与考核" },
|
|
|
{ key: "qdgygl", name: "供应渠道管理" },
|
|
|
{ key: "scqxwj", name: "市场需求挖掘" },
|
|
|
{ key: "cptfcs", name: "产品投放测试" },
|
|
|
{ key: "cpgh", name: "产品规划" },
|
|
|
];
|
|
|
const dialogue = ref([
|
|
|
{
|
|
|
role: "4",
|
|
|
child: [
|
|
|
{ name: "个人实训成绩分析", msg: "先给出个人实训总成绩及各个模块成绩,给出班级排名,及得分最高 的模块和得分最低的模块,对比历史成绩数据,分析成绩走势,给出学习建议" },
|
|
|
{ name: "实训学习数据分析", msg: " 从实训学习的角度,分析各模块学习时长或者操作次数(即点进该模 块的次数),分析模块得分与实训时长匹配情沉,找出不匹配的模 块,即用时长的模块反而得分低的情况。给出学习建议" },
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
role: "3",
|
|
|
child: [
|
|
|
{ name: "班级学生学情分析", msg: "如果有多个班级进行了实训,先对比各班级分数情况,再具体分析某个班的最高分最低分平均分,找出哪些学生没有进行实训操作,哪个学生实训时间最长,哪个最短,找出哪些学生的成绩与实训时长不匹配,即实训旧时长很长但是分数较低或者实训时长较短但是分数较高。给出教学建议。点击上述图标后开始进行分析,分段输出上述相关内容。支特内容复制及导出,保留A对话框,教刻师可继续向A提问" },
|
|
|
{ name: "实训模块学情分析", msg: "从实模块的角度,分析哪个实训模块得分率最高,即多数学生都得分较高的,哪个实训模块得分率较低,即多数学生在该模块得分都较低。哪个模块实训时长最长,哪个最短。分析得分率和实训时长不匹配的模块。给出教学建议。点击上述图标后开始进行分析,分段输出上述相关内容。支持内容复制及导出,保留A对话框,教划师可继续向A提问" },
|
|
|
],
|
|
|
},
|
|
|
]);
|
|
|
const scoreList = ref([]);
|
|
|
const scoreLoaded = ref(false);
|
|
|
const hasScoreData = ref(false);
|
|
|
const hasTeacherScoreData = (row) => {
|
|
|
return Number(row.completedTaskCount || 0) > 0 || moduleMap.some(({ key }) => row[`${key}Score`] !== null && row[`${key}Score`] !== undefined);
|
|
|
};
|
|
|
const getScoreList = async () => {
|
|
|
scoreLoaded.value = false;
|
|
|
scoreList.value = [];
|
|
|
hasScoreData.value = false;
|
|
|
proxy.$cache.session.remove("scoreList");
|
|
|
try {
|
|
|
if (roleId.value == 4) {
|
|
|
const res = await indexApi.getStuModuleDetail({ userId: userStore.userInfo.userId });
|
|
|
scoreList.value = Array.isArray(res?.data) ? res.data : [];
|
|
|
hasScoreData.value = scoreList.value.length > 0;
|
|
|
} else {
|
|
|
const res = await scoreApi.getScoreList({
|
|
|
index: 1,
|
|
|
size: 1000,
|
|
|
schoolId: userStore.userInfo.schoolId,
|
|
|
});
|
|
|
const rows = Array.isArray(res?.data?.list) ? res.data.list : [];
|
|
|
hasScoreData.value = rows.some(hasTeacherScoreData);
|
|
|
scoreList.value = rows.map((item) => ({
|
|
|
name: item.name,
|
|
|
className: item.className,
|
|
|
schoolId: item.schoolId,
|
|
|
scores: moduleMap.map(({ key, name }) => ({
|
|
|
moduleName: name,
|
|
|
score: item[`${key}Score`] || 0,
|
|
|
// 总成绩
|
|
|
totalScore: item.score || 0,
|
|
|
// 总排名
|
|
|
totalRank: item.stuRank || null,
|
|
|
})),
|
|
|
}));
|
|
|
}
|
|
|
if (hasScoreData.value) {
|
|
|
proxy.$cache.session.setJSON("scoreList", scoreList.value);
|
|
|
} else {
|
|
|
proxy.$message.warning("暂无成绩数据,暂时无法进行AI学情分析");
|
|
|
}
|
|
|
} catch (error) {
|
|
|
proxy.$message.error("成绩数据加载失败,请稍后重试");
|
|
|
} finally {
|
|
|
scoreLoaded.value = true;
|
|
|
}
|
|
|
};
|
|
|
// 分析
|
|
|
const analysis = (val) => {
|
|
|
if (!scoreLoaded.value) {
|
|
|
return proxy.$message.warning("成绩数据正在加载,请稍候");
|
|
|
}
|
|
|
if (!hasScoreData.value) {
|
|
|
return proxy.$message.warning("暂无成绩数据,暂时无法进行AI学情分析");
|
|
|
}
|
|
|
proxy.$cache.session.setJSON("msg", val.msg);
|
|
|
router.push("/ai/learning-situation-dialogue");
|
|
|
};
|
|
|
onMounted(() => {
|
|
|
getScoreList();
|
|
|
});
|
|
|
</script>
|
|
|
<style lang='scss' scoped>
|
|
|
.stu-analysis-of-students {
|
|
|
padding: 20px 40px;
|
|
|
height: calc(100vh - 2.5rem);
|
|
|
position: relative;
|
|
|
background: url("@/assets/images/背景.webp") no-repeat;
|
|
|
background-size: 100% 100%;
|
|
|
.handren-title {
|
|
|
text-align: center;
|
|
|
h3 {
|
|
|
font-size: 1.5rem;
|
|
|
line-height: 2.5rem;
|
|
|
margin-top: 0px;
|
|
|
color: #ffffff;
|
|
|
font-weight: 600;
|
|
|
}
|
|
|
}
|
|
|
.content {
|
|
|
color: #ffffff;
|
|
|
height: calc(100vh - 200px);
|
|
|
position: relative;
|
|
|
.analysis {
|
|
|
position: absolute;
|
|
|
top: 50%;
|
|
|
left: 50%;
|
|
|
transform: translate(-50%, -50%);
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
align-items: center;
|
|
|
color: #ffffff;
|
|
|
gap: 11rem;
|
|
|
.analysis-item {
|
|
|
width: 20rem;
|
|
|
height: 15rem;
|
|
|
line-height: 15rem;
|
|
|
text-align: center;
|
|
|
border-radius: 10px;
|
|
|
// 鼠标小手
|
|
|
cursor: pointer;
|
|
|
background: linear-gradient(90deg, #ff6a6a 0%, #ff9d9d 100%);
|
|
|
box-shadow: 0px 0px 10px 0px rgba(255, 106, 106, 0.5);
|
|
|
border-radius: 10px;
|
|
|
font-size: 1.5rem;
|
|
|
font-weight: 600;
|
|
|
position: relative;
|
|
|
overflow: hidden;
|
|
|
&::after {
|
|
|
content: "";
|
|
|
position: absolute;
|
|
|
top: 50%;
|
|
|
left: 50%;
|
|
|
width: 0;
|
|
|
height: 0;
|
|
|
background: rgba(255, 255, 255, 0.2);
|
|
|
border-radius: 50%;
|
|
|
transform: translate(-50%, -50%);
|
|
|
transition: width 0.6s ease-out, height 0.6s ease-out;
|
|
|
}
|
|
|
&:hover::after {
|
|
|
width: 22rem;
|
|
|
height: 18rem;
|
|
|
}
|
|
|
}
|
|
|
// 选中第二个
|
|
|
.analysis-item:nth-child(2) {
|
|
|
background: linear-gradient(-90deg, #1160ff 0%, #1994ff 100%);
|
|
|
}
|
|
|
}
|
|
|
.empty-score {
|
|
|
height: 100%;
|
|
|
--el-empty-description-margin-top: 16px;
|
|
|
:deep(.el-empty__description p) {
|
|
|
color: #ffffff;
|
|
|
}
|
|
|
}
|
|
|
.brief-introduction {
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
gap: 4rem;
|
|
|
margin-top: 10rem;
|
|
|
.brief-introduction-item {
|
|
|
width: 30rem;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</style>
|