| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- <template>
- <!-- 学生列表弹窗 -->
- <el-dialog v-model="dialogVisible" :title="dialogTitle" width="1200px" destroy-on-close>
- <div class="student-table-container">
- <el-table
- v-loading="loading"
- :data="studentList"
- stripe
- height="calc(100vh - 350px)"
- style="width: 100%"
- >
- <el-table-column label="姓名-手机" prop="namePhone" min-width="180" align="center"/>
- <el-table-column label="卡号" prop="cardNo" min-width="120" align="center"/>
- <el-table-column label="注册学校" prop="registerSchool" min-width="120" align="center" show-overflow-tooltip/>
- <el-table-column label="学校班级" prop="registerClass" min-width="80" align="center" show-overflow-tooltip/>
- <el-table-column label="培训校区" prop="trainSchool" min-width="120" align="center" show-overflow-tooltip/>
- <el-table-column label="校区班级" prop="trainClass" min-width="80" align="center" show-overflow-tooltip/>
- <el-table-column label="考生类型" prop="examType" min-width="150" align="center">
- <template #default="scope">
- <template v-if="scope.row && scope.row.examType && exam_type">
- <dict-tag :options="exam_type" :value="scope.row.examType" />
- </template>
- <span v-else>-</span>
- </template>
- </el-table-column>
- <el-table-column label="定向" prop="direct" min-width="150" align="center">
- <template #default="{row}">
- <div v-if="getFirstDirectedStudyInfo(row.direct)" class="cursor-pointer text-blue-500 hover:text-blue-700" @click.stop="handleShowDirectedStudy(row.direct)">
- <el-tooltip :content="getFirstDirectedStudyTooltip(row.direct)" placement="top" :disabled="!getFirstDirectedStudyInfo(row.direct)">
- <div class="directed-study-cell">
- <div v-if="getFirstDirectedStudyInfo(row.direct).universityName" class="directed-study-line">
- {{ getFirstDirectedStudyInfo(row.direct).universityName }}
- </div>
- <div v-if="getFirstDirectedStudyInfo(row.direct).majorName" class="directed-study-line">
- {{ getFirstDirectedStudyInfo(row.direct).majorName }}
- </div>
- </div>
- </el-tooltip>
- </div>
- <span v-else>-</span>
- </template>
- </el-table-column>
- <el-table-column label="代理商" prop="agent" min-width="120" align="center" show-overflow-tooltip/>
- <el-table-column label="单招年份" prop="year" min-width="80" align="center"/>
- <el-table-column label="省份" prop="province" min-width="80" align="center"/>
- <el-table-column label="机构" prop="institution" min-width="150" align="center" show-overflow-tooltip/>
- </el-table>
-
- <!-- 前端分页 -->
- <div class="student-pagination">
- <el-pagination
- v-model:current-page="pageNum"
- v-model:page-size="pageSize"
- :page-sizes="[10, 20, 50, 100]"
- :total="total"
- layout="total, sizes, prev, pager, next, jumper"
- @size-change="handlePageSizeChange"
- @current-change="handlePageChange"
- />
- </div>
- </div>
-
- <!-- 定向信息弹窗 -->
- <el-dialog v-model="directDetailVisible" title="定向信息" width="900px" destroy-on-close>
- <el-table :data="directDetailData" class="w-full" style="width: 100%">
- <el-table-column label="序号" type="index" width="60" align="center"></el-table-column>
- <el-table-column label="编码" prop="code" min-width="120" align="center"></el-table-column>
- <el-table-column label="学校" prop="universityName" min-width="200" align="center">
- <template #default="scope">
- <span>{{ scope.row.universityName }}{{ scope.row.universityId ? `(${scope.row.universityId})` : '' }}</span>
- </template>
- </el-table-column>
- <el-table-column label="专业" prop="majorName" min-width="200" align="center">
- <template #default="scope">
- <span>{{ scope.row.majorName }}{{ scope.row.majorId ? `(${scope.row.majorId})` : '' }}</span>
- </template>
- </el-table-column>
- <el-table-column label="专业类" prop="majorAncestors" min-width="200" align="center"></el-table-column>
- </el-table>
- </el-dialog>
- </el-dialog>
- </template>
- <script setup name="StudentListDialog">
- import { ref, getCurrentInstance } from 'vue'
- import { ElMessage } from 'element-plus'
- import { getClassesBuildStatsDetail } from '@/api/dz/papers.js'
- import DictTag from '@/components/DictTag/index.vue'
- const { proxy } = getCurrentInstance()
- const { exam_type } = proxy.useDict("exam_type")
- // Props
- const props = defineProps({
- // 统计类型映射,用于显示标题
- statTypeMap: {
- type: Object,
- default: () => ({
- 'send': '组卷已完成',
- 'total': '班级人数',
- 'unexact': '未定向未组卷',
- 'unfinish': '组卷未完成',
- 'unsend': '定向未组卷'
- })
- }
- })
- // 弹窗状态
- const dialogVisible = ref(false)
- const dialogTitle = ref('')
- const loading = ref(false)
- // 学生列表数据
- const studentList = ref([])
- const pageNum = ref(1)
- const pageSize = ref(10)
- const total = ref(0)
- // 当前查询参数
- const currentParams = ref(null)
- // 定向详情弹窗相关
- const directDetailVisible = ref(false)
- const directDetailData = ref([])
- // 解析directedStudy JSON并获取第一个的显示文本(用于tooltip)
- const getFirstDirectedStudyTooltip = (direct) => {
- if (!direct) {
- return null
- }
- try {
- const directedStudy = typeof direct === 'string'
- ? JSON.parse(direct)
- : direct
-
- if (Array.isArray(directedStudy) && directedStudy.length > 0) {
- const first = directedStudy[0]
- const universityName = first?.universityName || ''
- const majorName = first?.majorName || ''
- if (universityName || majorName) {
- const parts = []
- if (universityName) parts.push(universityName)
- if (majorName) parts.push(majorName)
- return parts.join(' - ')
- }
- }
- } catch (e) {
- console.error('解析directedStudy失败:', e)
- }
- return null
- }
- // 解析directedStudy JSON并获取第一个的信息对象
- const getFirstDirectedStudyInfo = (direct) => {
- if (!direct) {
- return null
- }
- try {
- const directedStudy = typeof direct === 'string'
- ? JSON.parse(direct)
- : direct
-
- if (Array.isArray(directedStudy) && directedStudy.length > 0) {
- const first = directedStudy[0]
- const universityName = first?.universityName || ''
- const majorName = first?.majorName || ''
- if (universityName || majorName) {
- return {
- universityName: universityName,
- majorName: majorName
- }
- }
- }
- } catch (e) {
- console.error('解析directedStudy失败:', e)
- }
- return null
- }
- // 获取完整的directedStudy列表
- const getDirectedStudyList = (direct) => {
- if (!direct) {
- return []
- }
- try {
- const directedStudy = typeof direct === 'string'
- ? JSON.parse(direct)
- : direct
-
- if (Array.isArray(directedStudy)) {
- return directedStudy.map(item => ({
- code: item?.code || '-',
- majorName: item?.majorName || '-',
- majorId: item?.majorId || null,
- universityName: item?.universityName || '-',
- universityId: item?.universityId || null,
- majorAncestors: item?.majorAncestors || '-'
- }))
- }
- } catch (e) {
- console.error('解析directedStudy失败:', e)
- }
- return []
- }
- // 显示定向信息弹窗
- const handleShowDirectedStudy = (direct) => {
- directDetailData.value = getDirectedStudyList(direct)
- directDetailVisible.value = true
- }
- // 加载学生列表
- const loadStudentList = async () => {
- if (!currentParams.value) {
- console.error('参数不完整')
- return
- }
-
- loading.value = true
- try {
- const res = await getClassesBuildStatsDetail(currentParams.value)
-
- const allStudents = res.data || []
- total.value = allStudents.length
-
- // 前端分页
- const start = (pageNum.value - 1) * pageSize.value
- const end = start + pageSize.value
- studentList.value = allStudents.slice(start, end)
- } catch (error) {
- console.error('加载学生列表失败:', error)
- ElMessage.error('加载学生列表失败: ' + (error.message || '未知错误'))
- } finally {
- loading.value = false
- }
- }
- // 分页大小改变
- const handlePageSizeChange = (size) => {
- pageSize.value = size
- pageNum.value = 1
- loadStudentList()
- }
- // 页码改变
- const handlePageChange = (page) => {
- pageNum.value = page
- loadStudentList()
- }
- // 打开弹窗
- const open = (row, statType, buildType, batchId, queryParams = {}) => {
- if (!row || !statType || !buildType || !batchId) {
- console.error('参数错误:', { row, statType, buildType, batchId })
- return
- }
-
- // 构建查询参数
- const params = {
- buildType,
- batchId,
- classId: row.classId,
- statType
- }
-
- // 添加额外的查询条件
- if (queryParams.examType) params.examType = queryParams.examType
- if (queryParams.subjectId) params.subjectId = queryParams.subjectId
- if (queryParams.universityId) params.universityId = queryParams.universityId
- if (queryParams.majorGroup) params.majorGroup = queryParams.majorGroup
- if (queryParams.majorPlanId) params.majorPlanId = queryParams.majorPlanId
-
- currentParams.value = params
-
- // 设置标题
- dialogTitle.value = `${row.className || ''} - ${props.statTypeMap[statType] || statType}`
-
- // 重置分页
- pageNum.value = 1
- pageSize.value = 10
-
- // 显示弹窗并加载数据
- dialogVisible.value = true
- loadStudentList()
- }
- // 暴露方法给父组件
- defineExpose({
- open
- })
- </script>
- <style scoped>
- .student-table-container {
- display: flex;
- flex-direction: column;
- height: calc(100vh - 300px);
- min-height: 500px;
- max-height: calc(100vh - 300px);
- }
- .student-pagination {
- margin-top: 20px;
- text-align: right;
- flex-shrink: 0;
- padding: 10px 0;
- background-color: #fff;
- }
- .directed-study-cell {
- text-align: center;
- line-height: 1.5;
- }
- .directed-study-line {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- font-size: 12px;
- }
- </style>
|