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

4 months ago
<!--
* @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">
4 months ago
<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({
4 months ago
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;
4 months ago
}
};
// 分析
const analysis = (val) => {
if (!scoreLoaded.value) {
return proxy.$message.warning("成绩数据正在加载,请稍候");
}
if (!hasScoreData.value) {
return proxy.$message.warning("暂无成绩数据,暂时无法进行AI学情分析");
}
4 months ago
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;
}
}
4 months ago
.brief-introduction {
display: flex;
justify-content: center;
gap: 4rem;
margin-top: 10rem;
.brief-introduction-item {
width: 30rem;
}
}
}
}
</style>