| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485 |
- <template>
- <div class="mt-4 flex-1 min-h-1 relative" :class="{ 'card-table-in-dialog': inDialog }">
- <div class="absolute top-0 left-0 w-full h-full" :class="{ 'card-table-in-dialog-inner': inDialog }">
- <el-table
- :data="data"
- class="w-full"
- :height="inDialog ? undefined : '100%'"
- :max-height="inDialog ? '60vh' : undefined"
- @selection-change="handleSelectionChange"
- v-loading="loading"
- >
- <el-table-column label="" type="selection" min-width="60" fixed="left"></el-table-column>
- <el-table-column label="卡号" prop="cardNo" align="center" min-width="100" fixed="left"></el-table-column>
- <el-table-column label="密码" prop="password" align="center" min-width="100"></el-table-column>
- <el-table-column label="姓名—手机" prop="studentInfo" align="center" min-width="150">
- <template #default="scope">
- <div class="text-[13px]">{{ scope.row.nickName || '-' }}</div>
- <div v-if="scope.row.phonenumber" class="text-[12px] text-gray-600">{{ scope.row.phonenumber }}</div>
- </template>
- </el-table-column>
- <el-table-column label="机构" prop="deptName" align="center" min-width="120">
- <template #default="scope">
- <div>{{ scope.row.deptName || '-' }}</div>
- </template>
- </el-table-column>
- <el-table-column label="省份" prop="location" align="center" min-width="120">
- <template #default="scope">
- <div>{{ scope.row.location || '-' }}</div>
- </template>
- </el-table-column>
- <el-table-column label="代理商" prop="agentName" align="center" min-width="120">
- <template #default="scope">
- <div>{{ scope.row.agentName || '-' }}</div>
- </template>
- </el-table-column>
- <el-table-column label="单招年份" prop="endYear" align="center" min-width="120">
- <template #default="scope">
- <div>{{ scope.row.endYear || '-' }}</div>
- </template>
- </el-table-column>
- <el-table-column label="注册学校" prop="schoolName" align="center" min-width="120" >
- <template #default="scope">
- <div class="text-[13px] ellipsis-2">{{ scope.row.schoolName || '-' }}</div>
- </template>
- </el-table-column>
- <el-table-column label="注册班级" prop="className" align="center" min-width="110">
- <template #default="scope">
- <div class="text-[13px] ellipsis-2">{{ scope.row.className || '-' }}</div>
- </template>
- </el-table-column>
- <el-table-column label="培训学校" prop="campusName" align="center" min-width="100">
- <template #default="scope">
- <div class="text-[13px] ellipsis-2">{{ scope.row.campusName || '-' }}</div>
- </template>
- </el-table-column>
- <el-table-column label="培训班级" prop="campusClassName" align="center" min-width="120">
- <template #default="scope">
- <div class="text-[13px] ellipsis-2">{{ scope.row.campusClassName || '-' }}</div>
- </template>
- </el-table-column>
- <el-table-column label="考生类型(注册)" prop="examType" align="center" min-width="140">
- <template #default="scope">
- <div v-if="scope.row && scope.row.examType && exam_type">
- <dict-tag :options="exam_type" :value="scope.row.examType" />
- <div v-if="scope.row.examMajorName || scope.row.examMajor" class="text-[12px] text-gray-600 mt-1">
- <span v-if="scope.row.examMajor">{{ scope.row.examMajor }}</span>
- <span v-if="scope.row.examMajor && scope.row.examMajorName"> - </span>
- <span v-if="scope.row.examMajorName">{{ scope.row.examMajorName }}</span>
- </div>
- </div>
- <span v-else>-</span>
- </template>
- </el-table-column>
- <el-table-column label="定向" prop="directedStudy" align="center" width="140">
- <template #default="scope">
- <div v-if="getFirstDirectedStudyInfo(scope.row)" class="cursor-pointer text-blue-500 hover:text-blue-700" @click="handleShowDirectedStudy(scope.row)">
- <el-tooltip :content="getFirstDirectedStudy(scope.row)" placement="top" :disabled="!getFirstDirectedStudy(scope.row)">
- <div class="directed-study-cell">
- <div v-if="getFirstDirectedStudyInfo(scope.row).universityName" class="directed-study-line">
- {{ getFirstDirectedStudyInfo(scope.row).universityName }}
- </div>
- <div v-if="getFirstDirectedStudyInfo(scope.row).majorName" class="directed-study-line">
- {{ getFirstDirectedStudyInfo(scope.row).majorName }}
- </div>
- </div>
- </el-tooltip>
- </div>
- <span v-else>-</span>
- </template>
- </el-table-column>
- <el-table-column label="卡类型" prop="type" align="center" min-width="120">
- <template #default="scope">
- <dict-tag :options="card_type" :value="scope.row.type" />
- </template>
- </el-table-column>
- <el-table-column label="分配状态" prop="distributeStatus" align="center" min-width="100">
- <template #default="scope">
- <dict-tag :options="card_distribute_status" :value="scope.row.distributeStatus" />
- </template>
- </el-table-column>
- <el-table-column label="使用状态" prop="status" align="center" min-width="100">
- <template #default="scope">
- <dict-tag :options="card_status" :value="scope.row.status" />
- </template>
- </el-table-column>
- <el-table-column label="过期状态" prop="timeStatus" align="center" min-width="100">
- <template #default="scope">
- <dict-tag :options="card_time_status" :value="scope.row.timeStatus" />
- </template>
- </el-table-column>
- <el-table-column label="缴费状态" prop="payStatus" align="center" min-width="100">
- <template #default="scope">
- <dict-tag :options="card_pay_status" :value="scope.row.payStatus" />
- </template>
- </el-table-column>
- <el-table-column label="结算状态" prop="isSettlement" align="center" min-width="100">
- <template #default="scope">
- <dict-tag :options="card_settlement_status" :value="scope.row.isSettlement" />
- </template>
- </el-table-column>
- <el-table-column label="分配时间" prop="distributeTime" align="center" min-width="120">
- <template #default="scope">
- <span>{{ scope.row.distributeTime ? parseTime(scope.row.distributeTime, '{y}-{m}-{d}') : '-' }}</span>
- </template>
- </el-table-column>
- <el-table-column label="激活时间" prop="activeTime" align="center" min-width="120">
- <template #default="scope">
- <span>{{ scope.row.activeTime ? parseTime(scope.row.activeTime, '{y}-{m}-{d}') : '-' }}</span>
- </template>
- </el-table-column>
- <el-table-column label="到期时间" prop="outDate" align="center" min-width="120">
- <template #default="scope">
- <span>{{ scope.row.outDate ? parseTime(scope.row.outDate, '{y}-{m}-{d}') : '-' }}</span>
- </template>
- </el-table-column>
- <el-table-column label="缴费时间" prop="payTime" align="center" min-width="120" :fixed="hideActions ? 'right' : undefined">
- <template #default="scope">
- <span>{{ scope.row.payTime ? parseTime(scope.row.payTime, '{y}-{m}-{d}') : '-' }}</span>
- </template>
- </el-table-column>
- <el-table-column label="模考次数" prop="simulate" align="center" min-width="100" :fixed="hideActions ? 'right' : undefined">
- <template #default="scope">
- <el-button type="primary" link @click="handleShowSimulate(scope.row.cardId)">查看</el-button>
- <el-button type="warning" link @click="handleClearDirectedStudy(scope.row)" v-if="scope.row.userId && scope.row.directedStudy">清空定向</el-button>
- </template>
- </el-table-column>
- <el-table-column v-if="!hideActions" label="操作" min-width="110" fixed="right" align="center">
- <template #default="scope">
- <el-button type="danger" text icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
- </template>
- </el-table-column>
- </el-table>
- </div>
-
- <!-- 定向信息弹窗 -->
- <el-dialog v-model="directedStudyDialogVisible" title="定向信息" width="900px">
- <el-table :data="directedStudyList" 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 v-model="simulateDialogVisible" title="模考次数" width="600px">
- <el-table :data="simulateList" class="w-full" style="width: 100%" v-loading="simulateLoading">
- <el-table-column label="科目ID" prop="subjectId" width="100" align="center"></el-table-column>
- <el-table-column label="科目名称" prop="subjectName" min-width="150" align="center"></el-table-column>
- <el-table-column label="次数" prop="count" width="100" align="center"></el-table-column>
- <el-table-column label="操作" width="100" align="center">
- <template #default="scope">
- <el-button type="primary" link @click="handleEditSimulateCount(scope.row)">修改</el-button>
- </template>
- </el-table-column>
- </el-table>
- <div v-if="!simulateLoading && simulateList.length === 0" style="text-align: center; color: #909399; padding: 20px;">
- 暂无模拟考试记录
- </div>
- </el-dialog>
-
- <!-- 修改次数弹窗 -->
- <el-dialog v-model="editCountDialogVisible" title="修改次数" width="400px">
- <el-form :model="editCountForm" label-width="100px">
- <el-form-item label="科目">
- <el-input v-model="editCountForm.subjectName" readonly></el-input>
- </el-form-item>
- <el-form-item label="次数" prop="count">
- <el-input-number v-model="editCountForm.count" :min="0" :precision="0" style="width: 100%"></el-input-number>
- </el-form-item>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button @click="editCountDialogVisible = false">取 消</el-button>
- <el-button type="primary" @click="handleSaveCount" :loading="savingCount">保 存</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
- </template>
- <script setup>
- import DictTag from '@/components/DictTag/index.vue';
- import { getCurrentInstance, ref } from 'vue';
- import { getUserSimulateList, updateUserEvalCounts, clearUserDirectedStudy } from '@/api/dz/cards';
- import { ElMessage, ElMessageBox } from 'element-plus';
- const { proxy } = getCurrentInstance();
- const { card_type, exam_type, card_distribute_status, card_status, card_settlement_status, card_time_status, card_pay_status } =
- proxy.useDict("card_type", "exam_type", "card_distribute_status", "card_status", "card_settlement_status", "card_time_status", "card_pay_status");
- const props = defineProps({
- data: {
- type: Array,
- default: () => [],
- },
- loading: {
- type: Boolean,
- default: false,
- },
- inDialog: {
- type: Boolean,
- default: false,
- },
- hideActions: {
- type: Boolean,
- default: false,
- },
- });
- const emit = defineEmits(['selectionChange', 'delete', 'refresh']);
- const handleSelectionChange = (selection) => {
- emit('selectionChange', selection);
- };
- const handleDelete = (row) => {
- emit('delete', row);
- };
- // 安全获取 assignExamType
- const getAssignExamType = (row) => {
- return row && row.assignExamType ? row.assignExamType : null;
- };
- // 解析directedStudy JSON并获取第一个的显示文本(用于tooltip)
- const getFirstDirectedStudy = (row) => {
- if (!row || !row.directedStudy) {
- return null;
- }
- try {
- const directedStudy = typeof row.directedStudy === 'string'
- ? JSON.parse(row.directedStudy)
- : row.directedStudy;
-
- 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 = (row) => {
- if (!row || !row.directedStudy) {
- return null;
- }
- try {
- const directedStudy = typeof row.directedStudy === 'string'
- ? JSON.parse(row.directedStudy)
- : row.directedStudy;
-
- 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 = (row) => {
- if (!row || !row.directedStudy) {
- return [];
- }
- try {
- const directedStudy = typeof row.directedStudy === 'string'
- ? JSON.parse(row.directedStudy)
- : row.directedStudy;
-
- 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 directedStudyDialogVisible = ref(false);
- const directedStudyList = ref([]);
- // 显示定向信息弹窗
- const handleShowDirectedStudy = (row) => {
- directedStudyList.value = getDirectedStudyList(row);
- directedStudyDialogVisible.value = true;
- };
- // 模拟考试弹窗相关
- const simulateDialogVisible = ref(false);
- const simulateList = ref([]);
- const simulateLoading = ref(false);
- const currentCardId = ref(null);
- // 修改次数弹窗相关
- const editCountDialogVisible = ref(false);
- const editCountForm = ref({
- userId: null,
- subjectId: null,
- subjectName: '',
- count: 0
- });
- const savingCount = ref(false);
- // 显示模拟考试弹窗
- const handleShowSimulate = async (cardId) => {
- if (!cardId) {
- ElMessage.warning('卡号不存在')
- return
- }
-
- currentCardId.value = cardId
- simulateDialogVisible.value = true
- simulateLoading.value = true
- simulateList.value = []
-
- try {
- const response = await getUserSimulateList({ cardId })
- if (response && response.data) {
- simulateList.value = response.data
- } else {
- simulateList.value = []
- }
- } catch (error) {
- console.error('获取模拟考试数据失败:', error)
- ElMessage.error('获取模拟考试数据失败')
- simulateList.value = []
- } finally {
- simulateLoading.value = false
- }
- };
- // 显示修改次数弹窗
- const handleEditSimulateCount = (row) => {
- editCountForm.value = {
- userId: row.userId,
- subjectId: row.subjectId,
- subjectName: row.subjectName,
- count: row.count || 0
- };
- editCountDialogVisible.value = true;
- };
- // 保存次数
- const handleSaveCount = async () => {
- if (editCountForm.value.count < 0) {
- ElMessage.warning('次数不能为负数')
- return
- }
-
- savingCount.value = true
- try {
- await updateUserEvalCounts({
- userId: editCountForm.value.userId,
- subjectId: editCountForm.value.subjectId,
- count: editCountForm.value.count
- })
- ElMessage.success('修改成功')
- editCountDialogVisible.value = false
-
- // 更新本地列表数据
- const item = simulateList.value.find(item => item.subjectId === editCountForm.value.subjectId)
- if (item) {
- item.count = editCountForm.value.count
- }
- } catch (error) {
- console.error('修改次数失败:', error)
- ElMessage.error('修改次数失败')
- } finally {
- savingCount.value = false
- }
- };
- // 清空定向
- const handleClearDirectedStudy = async (row) => {
- if (!row || !row.userId) {
- ElMessage.warning('用户ID不存在')
- return
- }
-
- try {
- await ElMessageBox.confirm('确定要清空该用户的定向信息吗?', '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning'
- })
-
- await clearUserDirectedStudy(row.userId)
- ElMessage.success('清空定向成功')
-
- // 更新本地数据,将 directedStudy 设置为 null
- if (row) {
- row.directedStudy = null
- }
-
- // 触发刷新,通知父组件更新数据
- emit('refresh')
- } catch (error) {
- if (error !== 'cancel') {
- console.error('清空定向失败:', error)
- ElMessage.error('清空定向失败')
- }
- }
- };
- </script>
- <style lang="scss" scoped>
- /* 在弹窗中使用时的样式 */
- .card-table-in-dialog {
- position: relative !important;
- height: auto !important;
- min-height: 400px;
- max-height: 60vh;
- margin-top: 0 !important;
- }
- .card-table-in-dialog-inner {
- position: relative !important;
- height: auto !important;
- width: 100% !important;
- top: 0 !important;
- left: 0 !important;
- }
- .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>
|