feat(心理评估): 新增心理评估数据获取和展示功能

添加获取心理评估数据的API接口,并实现前端表格展示和详情查看功能。主要包含:
1. 新增获取心理评估数据的API方法
2. 创建心理评估列表页面,展示学生最新评估等级
3. 实现查看详情功能,显示学生信息和历史评估记录
4. 添加评估等级标签样式和颜色区分
This commit is contained in:
2025-08-16 19:40:41 +08:00
parent 9b4d11ae5e
commit a3d0345a7b
3 changed files with 367 additions and 43 deletions

View File

@@ -8,3 +8,12 @@ export function getMessagesToAdmin(params) {
params: params params: params
}) })
} }
// 获取心理评估数据
export function getPsychologicalRatings(query) {
return request({
url: '/api/wechat/rating/all',
method: 'get',
params: query
})
}

View File

@@ -293,17 +293,69 @@
<el-table-column prop="label" label="项目" align="center" /> <el-table-column prop="label" label="项目" align="center" />
<el-table-column prop="value" label="数量" align="center"> <el-table-column prop="value" label="数量" align="center">
<template v-slot="scope"> <template v-slot="scope">
<div <div class="project-name-bold">
class="quantity-cell" {{ scope.row.label }}
:class="{ 'zero-quantity': scope.row.value == 0 }"
>
{{ scope.row.value }}
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="controller" align="center" label="操作"> <el-table-column prop="value" align="center">
<template v-slot:header>
<div class="table-header">
<svg
class="header-icon"
viewBox="0 0 1024 1024"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M896 123.712C808.704 49.92 704.768 0 512 0 319.168 0 215.296 49.92 128 123.712c-40.768 34.56-64 74.112-64 116.288v365.952c0 0.704 0 1.408 0.128 1.984L64 784C64 916.48 229.184 1024 512 1024c282.816 0 448-107.52 448-240V608 240c0-42.24-23.232-81.792-64-116.288zM512 480.064c192.768 0 296.704-49.92 384-123.712v79.168c-17.92 11.52-37.504 22.208-58.816 32.256C732.224 516.928 657.984 544 512 544c-145.984 0-220.16-27.136-325.184-76.416A508.288 508.288 0 0 1 128 435.456V356.352C215.296 430.08 319.168 480 512 480z m0 181.312c192.768 0 296.704-49.92 384-123.712v79.168c-17.92 11.456-37.504 22.208-58.816 32.256-104.96 49.152-179.264 76.288-325.184 76.288-145.92 0-220.16-27.136-325.184-76.288A508.288 508.288 0 0 1 128 616.832V537.664c87.296 73.792 191.168 123.712 384 123.712z m325.184 168.96c-104.96 49.28-179.264 76.352-325.184 76.352-145.92 0-220.16-27.072-325.184-76.288a533.504 533.504 0 0 1-56.384-30.592A53.952 53.952 0 0 1 128 784v-65.024c87.296 73.856 191.168 123.712 384 123.712 192.768 0 296.704-49.92 384-123.712v65.024c0 5.12-0.768 10.432-2.368 15.744-17.28 10.88-36.16 21.12-56.448 30.592z"
fill="#00AAFB"
></path>
</svg>
<span>数量</span>
</div>
</template>
<template v-slot="scope"> <template v-slot="scope">
<div class="going" @click="going(scope.row.url)">查看更多</div> <div class="quantity-container">
<div
class="quantity-circle"
:class="{
'zero-quantity': scope.row.value == 0,
'has-quantity': scope.row.value > 0,
}"
>
{{ scope.row.value }}
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="controller" align="center">
<template v-slot:header>
<div class="table-header">
<svg
class="header-icon"
viewBox="0 0 1024 1024"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M52.5056 240.64v740.6848H971.52V42.6752H284.5696V0H1024v1024H0V240.64h52.5056z"
fill="#1B7AFF"
></path>
<path
d="M57.6 187.2384l172.8512-140.4416L288.8192 0v234.6752H0z"
fill="#1B7AFF"
></path>
<path
d="M758.7584 373.888c-8.3968 9.8048-24.4992 23.808-45.4912 43.392a52.5056 52.5056 0 0 1-77.7216 0 51.072 51.072 0 0 1 0-77.6704c19.6096-20.992 42.7008-46.848 42.0096-46.848a163.84 163.84 0 0 0-186.1888 33.536 165.76 165.76 0 0 0-39.9104 170.0352l-193.8944 193.1008a73.7024 73.7024 0 0 0 0.6912 104.2688 73.7792 73.7792 0 0 0 104.2944-0.7168l193.92-193.1008a164.5568 164.5568 0 0 0 175.1808-45.6448 164.352 164.352 0 0 0 27.1104-178.944v-1.408zM301.1584 789.3248a37.9904 37.9904 0 0 1-27.7248-10.9056c-15.36-15.7952-15.36-40.9088 0-56.704l218.8032-218.112-7.296-21.0944a137.088 137.088 0 0 1 32.8192-139.5968 133.6832 133.6832 0 0 1 94.8224-39.9872h5.8368l-3.6352 3.6352a89.2928 89.2928 0 0 0-27.7248 63.2576 91.4688 91.4688 0 0 0 28.4416 67.6096c17.152 18.432 41.1648 28.9536 66.3808 29.0816a94.208 94.208 0 0 0 66.3552-29.0816 132.096 132.096 0 0 1-37.9136 96.6912 135.168 135.168 0 0 1-96.256 39.2704 131.6608 131.6608 0 0 1-43.776-7.2704l-21.1456-7.2704-218.8032 218.112c-7.7056 7.808-18.2016 12.2368-29.184 12.3648z"
fill="#1B7AFF"
></path>
</svg>
<span>操作</span>
</div>
</template>
<template v-slot="scope">
<button class="action-button" @click="going(scope.row.url)">
查看更多
</button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@@ -380,7 +432,7 @@
<div class="message-dialog-content"> <div class="message-dialog-content">
<el-table :data="msg_list" style="width: 100%" max-height="400"> <el-table :data="msg_list" style="width: 100%" max-height="400">
<el-table-column prop="content" label="消息内容" min-width="200"> <el-table-column prop="content" label="消息内容" min-width="200">
<template slot-scope="scope"> <template v-slot="scope">
<div <div
class="message-content clickable-row" class="message-content clickable-row"
@click="viewMessageDetail(scope.row)" @click="viewMessageDetail(scope.row)"
@@ -395,7 +447,7 @@
width="180" width="180"
align="center" align="center"
> >
<template slot-scope="scope"> <template v-slot="scope">
{{ formatTime(scope.row.createTime) }} {{ formatTime(scope.row.createTime) }}
</template> </template>
</el-table-column> </el-table-column>
@@ -425,7 +477,7 @@
align="center" align="center"
/> />
<el-table-column prop="projectName" label="项目名称" min-width="200"> <el-table-column prop="projectName" label="项目名称" min-width="200">
<template slot-scope="scope"> <template v-slot="scope">
<div <div
class="project-name clickable-row" class="project-name clickable-row"
@click="viewAnnouncementDetail(scope.row)" @click="viewAnnouncementDetail(scope.row)"
@@ -435,7 +487,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="状态" width="100" align="center"> <el-table-column label="状态" width="100" align="center">
<template slot-scope="scope"> <template>
<el-tag type="success" size="small">审核通过</el-tag> <el-tag type="success" size="small">审核通过</el-tag>
</template> </template>
</el-table-column> </el-table-column>
@@ -445,7 +497,7 @@
width="180" width="180"
align="center" align="center"
> >
<template slot-scope="scope"> <template v-slot="scope">
{{ formatTime(scope.row.createTime) }} {{ formatTime(scope.row.createTime) }}
</template> </template>
</el-table-column> </el-table-column>
@@ -760,40 +812,88 @@
text-decoration: underline; text-decoration: underline;
} }
/* 数量列样式 */ /* 表头样式 */
.quantity-cell { .table-header {
background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%); display: flex;
color: #1565c0; align-items: center;
justify-content: center;
gap: 6px;
font-weight: 600;
color: #333;
}
.header-icon {
width: 16px;
height: 16px;
}
/* 数量容器样式 */
.quantity-container {
display: flex;
justify-content: center;
align-items: center;
padding: 6px;
min-height: 44px;
}
/* 圆形数量样式 */
.quantity-circle {
width: 32px;
height: 32px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold; font-weight: bold;
font-size: 16px; font-size: 14px;
padding: 8px 12px; transition: transform 0.2s ease, box-shadow 0.2s ease;
border-radius: 8px;
border: 2px solid #2196f3;
box-shadow: 0 2px 8px rgba(33, 150, 243, 0.2);
display: inline-block;
min-width: 40px;
text-align: center;
transition: all 0.3s ease;
position: relative;
} }
.quantity-cell:hover { .quantity-circle.zero-quantity {
transform: translateY(-2px); background-color: rgba(115, 209, 61, 0.8);
box-shadow: 0 4px 12px rgba(33, 150, 243, 0.3); box-shadow: 0 2px 4px rgba(115, 209, 61, 0.25);
background: linear-gradient(135deg, #bbdefb 0%, #90caf9 100%);
} }
/* 为数量为0的情况添加绿色样式 */ .quantity-circle.has-quantity {
.quantity-cell.zero-quantity { background-color: rgba(255, 197, 61, 0.8);
background: linear-gradient(135deg, #e8f5e8 0%, #c8e6c9 100%); box-shadow: 0 2px 4px rgba(255, 197, 61, 0.25);
color: #2e7d32;
border-color: #4caf50;
box-shadow: 0 2px 8px rgba(76, 175, 80, 0.2);
} }
.quantity-cell.zero-quantity:hover { .quantity-circle:hover {
background: linear-gradient(135deg, #c8e6c9 0%, #a5d6a7 100%); transform: scale(1.05);
box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
/* 蓝色按钮样式 */
.action-button {
background: linear-gradient(135deg, rgba(64, 169, 255, 0.85) 0%, rgba(24, 144, 255, 0.85) 100%);
color: white;
border: none;
padding: 8px 16px;
border-radius: 6px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
font-size: 13px;
}
.action-button:hover {
background: linear-gradient(135deg, rgba(105, 192, 255, 0.9) 0%, rgba(64, 169, 255, 0.9) 100%);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(64, 169, 255, 0.25);
}
.action-button:active {
transform: translateY(0);
box-shadow: 0 2px 6px rgba(64, 169, 255, 0.15);
}
/* 项目名称加粗样式 */
.project-name-bold {
font-weight: bold;
color: #333;
font-size: 14px;
} }
/* 对话框样式 */ /* 对话框样式 */

View File

@@ -1,8 +1,223 @@
<template> <template>
<div class="cmd">你好 <div class="app-container">
<el-table v-loading="loading" :data="psychologicalList" style="width: 100%">
<el-table-column label="学号" align="center" prop="studentId" min-width="120" />
<el-table-column label="最新评估等级" align="center" prop="rating" min-width="120">
<template slot-scope="scope">
<el-tag :type="getRatingTagType(scope.row.rating)" effect="dark">
{{ scope.row.rating }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" min-width="120">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-view" @click="viewDetails(scope.row)">查看详情</el-button>
</template>
</el-table-column>
</el-table>
<!-- 心理评估详情弹出对话框 -->
<el-dialog
title="心理评估详情"
:visible.sync="dialogVisible"
width="80%"
:before-close="closeRatingHistory"
class="rating-dialog"
>
<div v-if="selectedStudent">
<h3>学生信息</h3>
<p><strong>学号</strong>{{ selectedStudent.studentId }}</p>
<p><strong>姓名</strong>{{ selectedStudent.studentName }}</p>
<p><strong>班级</strong>{{ selectedStudent.className }}</p>
<p><strong>辅导员</strong>{{ selectedStudent.counselor }}</p>
<h3>历史评估记录</h3>
<el-table :data="studentHistoryList" style="width: 100%">
<el-table-column label="评估等级" align="center" prop="rating" min-width="120">
<template slot-scope="scope">
<el-tag :type="getRatingTagType(scope.row.rating)" effect="dark">
{{ scope.row.rating }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="评估时间" align="center" prop="createdTime" min-width="150">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createdTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
</el-table>
</div>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
export default {}; import { getPsychologicalRatings } from "@/api/aitutor/chat";
import { listStudent } from "@/api/stuCQS/basedata/student";
export default {
name: "ChatWarning",
data() {
return {
// 遮罩层
loading: true,
// 心理评估表格数据
psychologicalList: [],
// 对话框显示状态
dialogVisible: false,
// 选中的学生信息
selectedStudent: null,
// 学生历史评估记录
studentHistoryList: [],
// 原始数据(用于详情查看)
originalData: []
};
},
created() {
this.getList();
},
methods: {
/** 查询心理评估列表 */
getList() {
this.loading = true;
getPsychologicalRatings().then(response => {
// 处理数据按学生ID分组只保留最新的评估记录
this.originalData = response.data || [];
const studentMap = new Map();
this.originalData.forEach(item => {
const studentId = item.studentId;
if (!studentMap.has(studentId) ||
new Date(item.createdTime) > new Date(studentMap.get(studentId).createdTime)) {
studentMap.set(studentId, item);
}
});
this.psychologicalList = Array.from(studentMap.values());
this.loading = false;
}).catch(error => {
console.error('获取心理评估数据失败:', error);
this.loading = false;
this.$modal.msgError('获取数据失败');
});
},
/** 查看详情 */
viewDetails(row) {
// 查询学生基本信息
this.getStudentInfo(row.studentId);
// 获取该学生的所有历史记录
this.studentHistoryList = this.originalData
.filter(item => item.studentId === row.studentId)
.sort((a, b) => new Date(b.createdTime) - new Date(a.createdTime));
this.dialogVisible = true;
},
/** 查询学生基本信息 */
getStudentInfo(studentId) {
// 使用现有的学生查询API
const queryParams = {
pageNum: 1,
pageSize: 1,
stuNo: studentId
};
this.getList2(queryParams).then(response => {
if (response.rows && response.rows.length > 0) {
const student = response.rows[0];
this.selectedStudent = {
studentId: student.stuNo,
studentName: student.name,
className: student.srsMajors ? student.srsMajors.majorName : '未知班级',
counselor: student.cphName
};
} else {
this.selectedStudent = {
studentId: studentId,
studentName: '未找到',
className: '未找到',
counselor: '未找到'
};
}
}).catch(error => {
console.error('获取学生信息失败:', error);
this.selectedStudent = {
studentId: studentId,
studentName: '查询失败',
className: '查询失败',
counselor: '查询失败'
};
});
},
/** 查询学生列表 */
getList2(queryParams) {
this.loading = true;
return listStudent(queryParams).then(response => {
this.loading = false;
return response;
}).catch(error => {
this.loading = false;
throw error;
});
},
/** 获取评估等级标签类型 */
getRatingTagType(rating) {
if (!rating) return 'info';
const ratingStr = rating.toString().toLowerCase();
if (ratingStr.includes('高') || ratingStr.includes('严重') || ratingStr.includes('high')) {
return 'danger';
} else if (ratingStr.includes('中') || ratingStr.includes('medium')) {
return 'warning';
} else if (ratingStr.includes('低') || ratingStr.includes('轻') || ratingStr.includes('low')) {
return 'success';
}
return 'info';
}
}
};
</script> </script>
<style></style>
<style scoped>
.app-container {
padding: 20px;
}
.mb8 {
margin-bottom: 8px;
}
.el-table .cell {
word-break: break-word;
}
/* 对话框样式 */
.rating-dialog .el-dialog__body {
padding: 0;
}
.dialog-header {
background: #f8f9fa;
padding: 16px 20px;
border-bottom: 1px solid #e9ecef;
margin-bottom: 0;
}
.student-info {
font-size: 16px;
font-weight: 500;
color: #303133;
}
.rating-content {
padding: 20px;
min-height: 200px;
}
.no-rating {
text-align: center;
padding: 40px 0;
}
</style>