You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dianshang-qianduan/src/views/analysis-of-students/analysis.vue

211 lines
7.7 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!--
* @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>