fix: include current training data in AI analysis

bugfix/ai-assessment-evidence-rescore
陈沅 1 month ago
parent 0128953288
commit 4721ac77a7

@ -9,7 +9,7 @@
<template>
<div class="stu-analysis-of-students">
<div class="handren-title">
<h3>此处为AI根据学情数据进行的智能分析,从个人成绩和实训时长角度给出分析结果,仅供参考</h3>
<h3>此处为AI根据学情数据进行的智能分析,从个人实训成绩和实训学习数据角度给出分析结果,仅供参考</h3>
</div>
<div class="content">
<el-empty v-if="scoreLoaded && !hasScoreData" class="empty-score" description="暂无成绩数据,暂时无法进行AI学情分析" />
@ -63,16 +63,72 @@ 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 studyTimeFields = [
{ projectName: "市场需求挖掘", field: "marketResearchTime" },
{ projectName: "产品规划", field: "productPlanningTime" },
{ projectName: "产品投放测试", field: "productLaunchTestTime" },
{ projectName: "供应渠道管理", field: "supplyChannelTime" },
{ projectName: "产品评估与考核", field: "productEvaluationTime" },
];
const toNumber = (value) => Number(value) || 0;
const hasStudentTrainingData = (report, studyTime, visitRows) =>
(report?.modules || []).some((module) => toNumber(module.score) > 0 || toNumber(module.completedTaskCount) > 0)
|| (report?.tasks || []).some((task) => task.progressStatus && task.progressStatus !== "NOT_STARTED")
|| studyTimeFields.some(({ field }) => toNumber(studyTime?.[field]) > 0)
|| (visitRows || []).some((item) => toNumber(item.visitCount) > 0);
const buildStudentAnalysisData = (report, studyTime, visitRows) => ({
trainingScores: {
totalScore: toNumber(report?.totalScore),
rank: report?.rank ?? null,
modules: (report?.modules || []).map((module) => ({
moduleName: module.moduleName,
score: toNumber(module.score),
weight: toNumber(module.weight),
completedTaskCount: toNumber(module.completedTaskCount),
totalTaskCount: toNumber(module.totalTaskCount),
participating: Boolean(module.participating),
})),
},
learningData: {
studyTimeMinutes: studyTimeFields.map(({ projectName, field }) => ({
projectName,
minutes: toNumber(studyTime?.[field]),
})),
projectVisits: (visitRows || []).map((item) => ({
projectName: item.project,
visitCount: toNumber(item.visitCount),
})),
taskProgress: (report?.tasks || []).map((task) => ({
taskName: task.taskName,
moduleName: task.moduleName,
progressStatus: task.progressStatus || "NOT_STARTED",
submitted: Boolean(task.submitted),
aiAssessmentScore: task.aiAssessmentScore ?? null,
})),
},
});
const getScoreList = async () => {
scoreLoaded.value = false;
scoreList.value = [];
hasScoreData.value = false;
proxy.$cache.session.remove("scoreList");
proxy.$cache.session.remove("learningAnalysisData");
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;
const [reportResult, studyTimeResult, visitCountResult] = await Promise.allSettled([
indexApi.getCurrentExperimentReport(),
indexApi.getStudyTime({ userId: userStore.userInfo.userId }),
indexApi.getUserVisitCount({ userId: userStore.userInfo.userId, schoolId: userStore.userInfo.schoolId }),
]);
if (reportResult.status !== "fulfilled") {
throw reportResult.reason;
}
const report = reportResult.value?.data || {};
const studyTime = studyTimeResult.status === "fulfilled" ? (studyTimeResult.value?.data || {}) : {};
const visitRows = visitCountResult.status === "fulfilled" && Array.isArray(visitCountResult.value?.data)
? visitCountResult.value.data
: [];
scoreList.value = buildStudentAnalysisData(report, studyTime, visitRows);
hasScoreData.value = hasStudentTrainingData(report, studyTime, visitRows);
} else {
const res = await scoreApi.getScoreList({
index: 1,
@ -96,7 +152,7 @@ const getScoreList = async () => {
}));
}
if (hasScoreData.value) {
proxy.$cache.session.setJSON("scoreList", scoreList.value);
proxy.$cache.session.setJSON("learningAnalysisData", scoreList.value);
} else {
proxy.$message.warning("暂无成绩数据,暂时无法进行AI学情分析");
}
@ -114,7 +170,7 @@ const analysis = (val) => {
if (!hasScoreData.value) {
return proxy.$message.warning("暂无成绩数据,暂时无法进行AI学情分析");
}
proxy.$cache.session.setJSON("msg", val.msg);
proxy.$cache.session.setJSON("msg", `${val.msg}\n请严格基于传入的实训成绩(trainingScores)和实训学习数据(learningData)分析,不要补造数据。`);
router.push("/ai/learning-situation-dialogue");
};
onMounted(() => {

@ -162,7 +162,7 @@ const gInterrupt = () => {
const getAnalysis = async () => {
loading.value = true;
try {
const res = await AI.getLearningAnalysis({ stuNeed: proxy.$cache.session.getJSON("msg"), stuData: proxy.$cache.session.getJSON("scoreList") });
const res = await AI.getLearningAnalysis({ stuNeed: proxy.$cache.session.getJSON("msg"), stuData: proxy.$cache.session.getJSON("learningAnalysisData") });
messages.value.push({
id: Date.now(),
role: "assistant",
@ -205,7 +205,7 @@ const exportData = () => {
XLSX.writeFile(workbook, "export.xlsx");
};
onMounted(() => {
if (proxy.$cache.session.getJSON("msg") && proxy.$cache.session.getJSON("scoreList")) {
if (proxy.$cache.session.getJSON("msg") && proxy.$cache.session.getJSON("learningAnalysisData")) {
getAnalysis();
} else {
if (proxy.$cache.session.getJSON("teachingPlan")) {

@ -14,16 +14,22 @@ test("learning analysis request does not send the commerce login token", () => {
assert.match(requestBlock, /params:\s*\{\s*stuNeed\s*}/);
});
test("learning analysis page handles empty and failed score data", () => {
test("learning analysis page sends current training scores and learning activity data", () => {
assert.match(analysisSource, /暂无成绩数据,暂时无法进行AI学情分析/);
assert.match(analysisSource, /proxy\.\$cache\.session\.remove\("scoreList"\)/);
assert.match(analysisSource, /rows\.some\(hasTeacherScoreData\)/);
assert.match(analysisSource, /getCurrentExperimentReport/);
assert.match(analysisSource, /getStudyTime/);
assert.match(analysisSource, /getUserVisitCount/);
assert.match(analysisSource, /trainingScores/);
assert.match(analysisSource, /learningData/);
assert.match(analysisSource, /learningAnalysisData/);
assert.doesNotMatch(analysisSource, /getStuModuleDetail/);
assert.match(analysisSource, /completedTaskCount/);
assert.match(analysisSource, /if \(!hasScoreData\.value\)/);
assert.match(analysisSource, /finally\s*\{\s*scoreLoaded\.value = true/);
});
test("AI analysis failure always closes the loading overlay", () => {
assert.match(dialogueSource, /learningAnalysisData/);
assert.match(dialogueSource, /AI学情分析暂时不可用,请稍后重试/);
assert.match(dialogueSource, /finally\s*\{\s*loading\.value = false/);
});

Loading…
Cancel
Save