Files
hzdyjs/web/src/views/xg/xsjcxx/classmsg/classMsg/index.vue
T

1410 lines
52 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="p-2 page-container">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" label-width="100px">
<el-row :gutter="20">
<el-col :span="6">
<el-form-item label="学院代码" prop="collegeId">
<el-select v-model="queryParams.collegeId" placeholder="请选择学院" clearable @change="handleCollegeChange">
<el-option v-for="item in collegeOptions" :key="item.deptId" :label="item.deptName" :value="item.deptId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="专业代码" prop="majorId">
<el-select v-model="queryParams.majorId" placeholder="请选择专业" clearable>
<el-option v-for="item in majorOptions" :key="item.deptId" :label="item.deptName" :value="item.deptId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="班级名称" prop="className">
<el-input v-model="queryParams.className" placeholder="请输入班级名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="年级" prop="grade">
<el-input v-model="queryParams.grade" placeholder="请输入年级" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="6">
<el-form-item label="所在校区" prop="campusId">
<el-select v-model="queryParams.campusId" placeholder="请选择校区" clearable filterable>
<el-option v-for="item in campusOptions" :key="item.id" :label="item.campusName" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24" class="search-btn-container">
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['classMsg:classMsg:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-dropdown v-hasPermi="['classMsg:classMsg:add']" split-button type="info" plain @click="handleImport">
导入
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item icon="Download" @click="importTemplate">下载模板</el-dropdown-item>
<el-dropdown-item icon="Upload" @click="handleImport">导入数据</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['classMsg:classMsg:edit']"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['classMsg:classMsg:remove']"
>删除</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="CircleCheck"
:disabled="multiple"
@click="handleBatchGraduate"
v-hasPermi="['classMsg:classMsg:edit']"
>毕业</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="VideoPause" :disabled="multiple" @click="handleBatchPause" v-hasPermi="['classMsg:classMsg:edit']"
>暂停</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="CloseBold" :disabled="multiple" @click="handleBatchDissolve" v-hasPermi="['classMsg:classMsg:edit']"
>解散</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="OfficeBuilding"
:disabled="multiple"
@click="handleBatchSetCampus"
v-hasPermi="['classMsg:classMsg:edit']"
>批量设置校区</el-button
>
</el-col>
<!-- <el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['classMsg:classMsg:export']">导出</el-button>
</el-col> -->
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" border :data="classMsgList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="主键ID" align="center" prop="id" v-if="true" />
<el-table-column label="学院代码" align="center" prop="collegeId" v-if="false" />
<el-table-column label="专业代码" align="center" prop="majorId" v-if="false" />
<el-table-column label="学院名称" align="center" prop="collegeName" />
<el-table-column label="专业名称" align="center" prop="majorName" />
<el-table-column label="所在校区" align="center" prop="campusName" min-width="110" />
<el-table-column label="班级名称" align="center" prop="className" />
<el-table-column label="学历层次" align="center" prop="classType">
<template #default="scope">
<!-- <el-tag :type="getClassTypeTag(scope.row.classType)">{{ formatClassType(scope.row.classType) }}</el-tag> -->
<dict-tag :options="zsjy_education_level" :value="scope.row.classType" />
</template>
</el-table-column>
<el-table-column label="班主任" align="center" prop="classTeacherName" />
<el-table-column label="辅导员" align="center" prop="counselorName" />
<el-table-column label="年级" align="center" prop="grade" />
<el-table-column label="入学年份" align="center" prop="enrollmentYear" />
<el-table-column label="学制(年)" align="center" prop="schoolSystem" />
<el-table-column label="毕业年份" align="center" prop="graduationYear" />
<el-table-column label="班级状态" align="center" prop="classStatus">
<template #default="scope">
<!-- <el-tag :type="getClassStatusTag(scope.row.classStatus)">{{ formatClassStatus(scope.row.classStatus) }}</el-tag> -->
<dict-tag :options="xg_class_status" :value="scope.row.classStatus" />
</template>
</el-table-column>
<el-table-column label="备注信息" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="255" fixed="right">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" plain icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['classMsg:classMsg:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button
link
type="danger"
plain
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['classMsg:classMsg:remove']"
></el-button>
</el-tooltip>
<el-tooltip content="设置班主任" placement="top">
<el-button
link
type="success"
plain
icon="User"
@click="handleSetClassTeacher(scope.row)"
v-hasPermi="['classMsg:classMsg:edit']"
></el-button>
</el-tooltip>
<el-tooltip content="设置辅导员" placement="top">
<el-button
link
type="info"
plain
icon="UserFilled"
@click="handleSetCounselor(scope.row)"
v-hasPermi="['classMsg:classMsg:edit']"
></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 添加或修改班级信息-新版对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="classMsgFormRef" :model="form" :rules="rules" label-width="100px">
<el-form-item label="学院代码" prop="collegeId">
<el-select v-model="form.collegeId" placeholder="请选择学院" style="width: 100%" @change="handleFormCollegeChange">
<el-option v-for="item in collegeOptions" :key="item.deptId" :label="item.deptName" :value="item.deptId" />
</el-select>
</el-form-item>
<el-form-item label="学院名称" prop="collegeName" v-if="false">
<el-input v-model="form.collegeName" placeholder="请输入学院名称" readonly />
</el-form-item>
<el-form-item label="专业代码" prop="majorId">
<el-select v-model="form.majorId" placeholder="请选择专业" style="width: 100%" @change="handleFormMajorChange">
<el-option v-for="item in formMajorOptions" :key="item.deptId" :label="item.deptName" :value="item.deptId" />
</el-select>
</el-form-item>
<el-form-item label="专业名称" prop="majorName" v-if="false">
<el-input v-model="form.majorName" placeholder="请输入专业名称" readonly />
</el-form-item>
<el-form-item label="所在校区" prop="campusId">
<el-select v-model="form.campusId" placeholder="请选择校区(选填)" clearable filterable style="width: 100%" @change="handleFormCampusChange">
<el-option v-for="item in campusOptions" :key="item.id" :label="item.campusName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="班级代码" prop="classCode" v-if="false">
<el-input v-model="form.classCode" placeholder="请输入班级代码" />
</el-form-item>
<el-form-item label="班级名称" prop="className">
<el-input v-model="form.className" placeholder="请输入班级名称" />
</el-form-item>
<el-form-item label="学历层级" prop="classType">
<el-select v-model="form.classType" placeholder="请选择学历层级" style="width: 100%">
<el-option v-for="dict in zsjy_education_level" :key="dict.value" :label="dict.label" :value="dict.value" />
<!-- <el-option label="中级工" :value="1" />
<el-option label="高级工" :value="2" />
<el-option label="预备技师" :value="3" />
<el-option label="技师" :value="4" />
<el-option label="中高职一体" :value="5" /> -->
</el-select>
</el-form-item>
<el-form-item label="年级" prop="grade">
<el-input v-model="form.grade" placeholder="请输入年级" />
</el-form-item>
<el-form-item label="入学年份" prop="enrollmentYear">
<el-input v-model="form.enrollmentYear" placeholder="请输入入学年份" @input="syncGraduationYear" />
</el-form-item>
<el-form-item label="学制(年)" prop="schoolSystem">
<el-input v-model="form.schoolSystem" placeholder="请输入学制(年)" @input="syncGraduationYear" />
</el-form-item>
<el-form-item label="毕业年份" prop="graduationYear">
<el-input v-model="form.graduationYear" placeholder="入学年份+学制自动计算,可修改" />
</el-form-item>
<el-form-item label="辅导员ID" prop="counselorId" v-if="false">
<el-input v-model="form.counselorId" placeholder="请输入辅导员ID" />
</el-form-item>
<el-form-item label="辅导员姓名" prop="counselorName" v-if="false">
<el-input v-model="form.counselorName" placeholder="请输入辅导员姓名" />
</el-form-item>
<el-form-item label="班主任ID" prop="classTeacherId" v-if="false">
<el-input v-model="form.classTeacherId" placeholder="请输入班主任ID" />
</el-form-item>
<el-form-item label="班主任姓名" prop="classTeacherName" v-if="false">
<el-input v-model="form.classTeacherName" placeholder="请输入班主任姓名" />
</el-form-item>
<el-form-item label="班级导师ID" prop="classAdvisorId" v-if="false">
<el-input v-model="form.classAdvisorId" placeholder="请输入班级导师ID" />
</el-form-item>
<el-form-item label="班级导师姓名" prop="classAdvisorName" v-if="false">
<el-input v-model="form.classAdvisorName" placeholder="请输入班级导师姓名" />
</el-form-item>
<el-form-item label="班长ID" prop="classMonitorId" v-if="false">
<el-input v-model="form.classMonitorId" placeholder="请输入班长ID" />
</el-form-item>
<el-form-item label="班长姓名" prop="classMonitorName" v-if="false">
<el-input v-model="form.classMonitorName" placeholder="请输入班长姓名" />
</el-form-item>
<el-form-item label="副班长ID" prop="deputyMonitorId" v-if="false">
<el-input v-model="form.deputyMonitorId" placeholder="请输入副班长ID" />
</el-form-item>
<el-form-item label="副班长姓名" prop="deputyMonitorName" v-if="false">
<el-input v-model="form.deputyMonitorName" placeholder="请输入副班长姓名" />
</el-form-item>
<el-form-item label="是否已毕业" prop="isGraduation">
<el-select v-model="form.isGraduation" placeholder="请选择是否已毕业" style="width: 100%">
<!-- <el-option label="未毕业" :value="0" />
<el-option label="已毕业" :value="1" /> -->
<el-option v-for="dict in is_graduation" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="毕业日期" prop="graduationDate" v-if="false">
<el-date-picker
clearable
v-model="form.graduationDate"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择毕业日期"
style="width: 100%"
>
</el-date-picker>
</el-form-item>
<el-form-item label="计划容量" prop="plannedCapacity" v-if="false">
<el-input v-model="form.plannedCapacity" placeholder="请输入计划容量" />
</el-form-item>
<el-form-item label="当前学生人数" prop="currentStudentCount" v-if="false">
<el-input v-model="form.currentStudentCount" placeholder="请输入当前学生人数" />
</el-form-item>
<el-form-item label="最大学生人数" prop="maxStudentCount" v-if="false">
<el-input v-model="form.maxStudentCount" placeholder="请输入最大学生人数" />
</el-form-item>
<el-form-item label="男生人数" prop="maleCount" v-if="false">
<el-input v-model="form.maleCount" placeholder="请输入男生人数" />
</el-form-item>
<el-form-item label="女生人数" prop="femaleCount" v-if="false">
<el-input v-model="form.femaleCount" placeholder="请输入女生人数" />
</el-form-item>
<el-form-item label="在籍人数" prop="activeCount" v-if="false">
<el-input v-model="form.activeCount" placeholder="请输入在籍人数" />
</el-form-item>
<el-form-item label="转入人数" prop="transferInCount" v-if="false">
<el-input v-model="form.transferInCount" placeholder="请输入转入人数" />
</el-form-item>
<el-form-item label="转出人数" prop="transferOutCount" v-if="false">
<el-input v-model="form.transferOutCount" placeholder="请输入转出人数" />
</el-form-item>
<el-form-item label="退学人数" prop="dropoutCount" v-if="false">
<el-input v-model="form.dropoutCount" placeholder="请输入退学人数" />
</el-form-item>
<el-form-item label="毕业人数" prop="graduateCount" v-if="false">
<el-input v-model="form.graduateCount" placeholder="请输入毕业人数" />
</el-form-item>
<el-form-item label="班级办公室位置" prop="officeLocation" v-if="false">
<el-input v-model="form.officeLocation" placeholder="请输入班级办公室位置" />
</el-form-item>
<el-form-item label="班级教室位置" prop="classLocation">
<el-input v-model="form.classLocation" placeholder="请输入班级教室位置" />
</el-form-item>
<el-form-item label="联系电话" prop="contactPhone" v-if="false">
<el-input v-model="form.contactPhone" placeholder="请输入联系电话" />
</el-form-item>
<el-form-item label="QQ群号" prop="qqGroup" v-if="false">
<el-input v-model="form.qqGroup" placeholder="请输入QQ群号" />
</el-form-item>
<el-form-item label="微信群" prop="wechatGroup" v-if="false">
<el-input v-model="form.wechatGroup" placeholder="请输入微信群" />
</el-form-item>
<el-form-item label="班级邮箱" prop="email" v-if="false">
<el-input v-model="form.email" placeholder="请输入班级邮箱" />
</el-form-item>
<el-form-item label="课程安排" prop="classSchedule" v-if="false">
<el-input v-model="form.classSchedule" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="班级文化建设" prop="classCulture" v-if="false">
<el-input v-model="form.classCulture" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="班级规章制度" prop="classRules" v-if="false">
<el-input v-model="form.classRules" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="班级状态" prop="classStatus">
<el-select v-model="form.classStatus" placeholder="请选择班级状态" style="width: 100%">
<!-- <el-option label="正常" :value="1" />
<el-option label="暂停" :value="2" />
<el-option label="毕业" :value="3" />
<el-option label="解散" :value="4" /> -->
<el-option v-for="dict in xg_class_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="班级描述" prop="classDescription">
<el-input v-model="form.classDescription" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="最后统计更新时间" prop="lastCountUpdate" v-if="false">
<el-date-picker
clearable
v-model="form.lastCountUpdate"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择最后统计更新时间"
>
</el-date-picker>
</el-form-item>
<el-form-item label="备注信息" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</template>
</el-dialog>
<!-- 设置班主任对话框 -->
<el-dialog title="设置班主任" v-model="classTeacherDialog.visible" width="500px" append-to-body>
<el-descriptions title="班级信息" :column="1" border>
<el-descriptions-item label="学院名称">{{ classTeacherDialog.classInfo.collegeName }}</el-descriptions-item>
<el-descriptions-item label="专业名称">{{ classTeacherDialog.classInfo.majorName }}</el-descriptions-item>
<el-descriptions-item label="班级名称">{{ classTeacherDialog.classInfo.className }}</el-descriptions-item>
<el-descriptions-item label="年级">{{ classTeacherDialog.classInfo.grade }}</el-descriptions-item>
</el-descriptions>
<div class="mt-4">
<el-form ref="classTeacherFormRef" :model="classTeacherDialog.form" label-width="100px">
<el-form-item label="班主任" prop="classTeacherId">
<el-select
v-model="classTeacherDialog.form.classTeacherId"
placeholder="请选择班主任"
filterable
remote
clearable
:remote-method="handleTeacherSearch"
:loading="classTeacherDialog.loading"
style="width: 100%"
>
<el-option
v-for="item in classTeacherDialog.teachers"
:key="item.id"
:label="`${item.nickName}(${item.userId})(${item.phonenumber || '-'})`"
:value="item.id"
>
<div class="flex items-center">
<span>{{ item.nickName }}</span>
<span class="text-gray-400 ml-2">({{ item.userId }})</span>
<span class="text-gray-400 ml-2">({{ item.phonenumber || '-' }})</span>
</div>
</el-option>
</el-select>
</el-form-item>
</el-form>
</div>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitClassTeacher">确 定</el-button>
<el-button @click="classTeacherDialog.visible = false">取 消</el-button>
</div>
</template>
</el-dialog>
<!-- 班级信息导入对话框 -->
<el-dialog v-model="upload.open" :title="upload.title" width="420px" append-to-body>
<el-upload
ref="uploadRef"
:limit="1"
accept=".xlsx, .xls"
:headers="upload.headers"
:action="upload.url"
:disabled="upload.isUploading"
:on-progress="handleFileUploadProgress"
:on-success="handleFileSuccess"
:on-error="handleFileError"
:auto-upload="false"
drag
>
<el-icon class="el-icon--upload"><i-ep-upload-filled /></el-icon>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<template #tip>
<div class="el-upload__tip text-center">
<div>请先下载模板,通过下拉框选择学院、专业及字典项后上传。</div>
<span>仅允许导入 xls、xlsx 格式文件。</span>
<el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">
下载模板
</el-link>
</div>
</template>
</el-upload>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" :loading="upload.isUploading" @click="submitFileForm">确 定</el-button>
<el-button @click="upload.open = false">取 消</el-button>
</div>
</template>
</el-dialog>
<!-- 设置辅导员对话框 -->
<el-dialog title="设置辅导员" v-model="counselorDialog.visible" width="500px" append-to-body>
<el-descriptions title="班级信息" :column="1" border>
<el-descriptions-item label="学院名称">{{ counselorDialog.classInfo.collegeName }}</el-descriptions-item>
<el-descriptions-item label="专业名称">{{ counselorDialog.classInfo.majorName }}</el-descriptions-item>
<el-descriptions-item label="班级名称">{{ counselorDialog.classInfo.className }}</el-descriptions-item>
<el-descriptions-item label="年级">{{ counselorDialog.classInfo.grade }}</el-descriptions-item>
</el-descriptions>
<div class="mt-4">
<el-form ref="counselorFormRef" :model="counselorDialog.form" label-width="100px">
<el-form-item label="辅导员" prop="counselorId">
<el-select
v-model="counselorDialog.form.counselorId"
placeholder="请选择辅导员"
filterable
remote
clearable
:remote-method="handleCounselorSearch"
:loading="counselorDialog.loading"
style="width: 100%"
>
<el-option
v-for="item in counselorDialog.counselors"
:key="item.id"
:label="`${item.nickName}(${item.userId})(${item.phonenumber || '-'})`"
:value="item.id"
>
<div class="flex items-center">
<span>{{ item.nickName }}</span>
<span class="text-gray-400 ml-2">({{ item.userId }})</span>
<span class="text-gray-400 ml-2">({{ item.phonenumber || '-' }})</span>
</div>
</el-option>
</el-select>
</el-form-item>
</el-form>
</div>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitCounselor">确 定</el-button>
<el-button @click="counselorDialog.visible = false">取 消</el-button>
</div>
</template>
</el-dialog>
<!-- 批量设置所在校区 -->
<el-dialog title="批量设置校区" v-model="campusBatchDialog.visible" width="420px" append-to-body>
<el-form label-width="90px">
<el-form-item label="所在校区" required>
<el-select v-model="campusBatchDialog.campusId" placeholder="请选择校区" filterable style="width: 100%">
<el-option v-for="item in campusOptions" :key="item.id" :label="item.campusName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="已选班级">
<span>{{ ids.length }} 个</span>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitBatchSetCampus">确 定</el-button>
<el-button @click="campusBatchDialog.visible = false">取 消</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="ClassMsg" lang="ts">
import {
listClassMsg,
getClassMsg,
delClassMsg,
addClassMsg,
updateClassMsg,
updateClassStatus,
updateClassStatusBatch,
updateClassCampusBatch
} from '@/api/xg/xsjcxx/classMsg/classMsg';
import { listColleges, collegeTree, listMajorsByCollegeId } from '@/api/xg/xsjcxx/classMsg/college';
import { ClassMsgVO, ClassMsgQuery, ClassMsgForm, SysDeptVo } from '@/api/xg/xsjcxx/classMsg/types';
import { listDormCampus } from '@/api/xg/xgss/xqxx/dormCampus';
import type { DormCampusVO } from '@/api/xg/xgss/xqxx/dormCampus/types';
import { ComponentInternalInstance, ref, reactive, toRefs, onMounted, getCurrentInstance, watch } from 'vue';
import type { FormInstance as ElFormInstance, UploadFile, UploadInstance } from 'element-plus';
import { ElMessageBox } from 'element-plus';
import { globalHeaders } from '@/utils/request';
import { getActiveUserList } from '@/api/xg/sysUser'; // 添加用户API导入
import { addClassTeacherCounselorRel, updateClassTeacherCounselorRel } from '@/api/xg/classTeacherCounselorRel'; // 添加班级辅导员关联API导入
interface DialogOption {
visible: boolean;
title: string;
}
interface PageData<T, Q> {
form: T;
queryParams: Q;
rules: Record<string, any[]>;
}
interface ComponentInternalInstance {
proxy?: any;
}
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const {
xg_class_status,
is_graduation,
wenhuachengdu,
xg_political_status,
sys_user_sex,
xg_nation,
sys_question_category,
sys_item_enable,
sys_item_required,
sys_item_delete,
house_hold_register_type,
marital_status,
sys_yesno,
xg_family_economic,
xg_blood_type,
disability_type,
zsjy_education_level,
xg_training_mode,
admission_category,
student_status
} = toRefs<any>(
proxy?.useDict(
'xg_class_status',
'is_graduation',
'wenhuachengdu',
'xg_political_status',
'sys_user_sex',
'xg_nation',
'sys_question_category',
'sys_item_enable',
'sys_item_required',
'sys_item_delete',
'house_hold_register_type',
'marital_status',
'sys_yesno',
'xg_family_economic',
'xg_blood_type',
'disability_type',
'zsjy_education_level',
'xg_training_mode',
'admission_category',
'student_status'
)
);
const classMsgList = ref<ClassMsgVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const collegeOptions = ref<SysDeptVo[]>([]); // 学院选项
const majorOptions = ref<SysDeptVo[]>([]); // 检索时的专业选项
const formMajorOptions = ref<SysDeptVo[]>([]); // 表单中的专业选项
const collegeTreeData = ref<SysDeptVo[]>([]); // 学院专业树形数据
const campusOptions = ref<DormCampusVO[]>([]); // 校区选项
const queryFormRef = ref<ElFormInstance>();
const classMsgFormRef = ref<ElFormInstance>();
const uploadRef = ref<UploadInstance>();
/** 班级导入参数 */
const upload = reactive({
open: false,
title: '',
isUploading: false,
headers: globalHeaders(),
url: import.meta.env.VITE_APP_BASE_API + '/classMsg/classMsg/importData'
});
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const campusBatchDialog = reactive<{ visible: boolean; campusId?: string | number }>({
visible: false,
campusId: undefined
});
const initFormData: ClassMsgForm = {
id: undefined,
collegeId: undefined,
collegeName: undefined,
majorId: undefined,
majorName: undefined,
campusId: undefined,
campusName: undefined,
classCode: undefined,
className: undefined,
classType: '4',
grade: undefined,
enrollmentYear: undefined,
schoolSystem: undefined,
graduationYear: undefined,
trainingType: undefined,
degreeType: undefined,
counselorId: undefined,
counselorName: undefined,
classTeacherId: undefined,
classTeacherName: undefined,
classAdvisorId: undefined,
classAdvisorName: undefined,
classMonitorId: undefined,
classMonitorName: undefined,
deputyMonitorId: undefined,
deputyMonitorName: undefined,
classStatus: '1',
isGraduation: '0',
graduationDate: undefined,
plannedCapacity: undefined,
currentStudentCount: undefined,
maxStudentCount: undefined,
maleCount: undefined,
femaleCount: undefined,
activeCount: undefined,
transferInCount: undefined,
transferOutCount: undefined,
dropoutCount: undefined,
graduateCount: undefined,
officeLocation: undefined,
classLocation: undefined,
contactPhone: undefined,
qqGroup: undefined,
wechatGroup: undefined,
email: undefined,
classSchedule: undefined,
classCulture: undefined,
classRules: undefined,
classDescription: undefined,
lastCountUpdate: undefined,
remark: undefined
};
const data = reactive<PageData<ClassMsgForm, ClassMsgQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
collegeId: undefined,
majorId: undefined,
campusId: undefined,
className: undefined,
classType: undefined,
grade: undefined,
classStatus: undefined,
params: {}
},
rules: {
id: [{ required: true, message: '主键ID不能为空', trigger: 'blur' }],
classCode: [{ required: true, message: '班级代码不能为空', trigger: 'blur' }],
className: [{ required: true, message: '班级名称不能为空', trigger: 'blur' }],
grade: [{ required: true, message: '年级不能为空', trigger: 'blur' }],
enrollmentYear: [{ required: true, message: '入学年份不能为空', trigger: 'blur' }],
majorId: [{ required: true, message: '专业不能为空', trigger: 'blur' }],
classType: [{ required: true, message: '学历层级不能为空', trigger: 'blur' }],
classStatus: [{ required: true, message: '班级状态不能为空', trigger: 'change' }],
schoolSystem: [{ required: true, message: '学制(年)不能为空', trigger: 'blur' }],
graduationYear: [{ required: true, message: '毕业年份不能为空', trigger: 'blur' }],
collegeId: [{ required: true, message: '学院不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询班级信息-新版列表 */
const getList = async () => {
loading.value = true;
const res = await listClassMsg(queryParams.value);
classMsgList.value = res.rows || [];
total.value = res.total;
loading.value = false;
};
/** 查询学院列表 */
const getCollegeList = async () => {
const res = await listColleges();
collegeOptions.value = res.data;
};
/** 查询校区列表 */
const getCampusList = async () => {
try {
const res = await listDormCampus({ pageNum: 1, pageSize: 1000 });
campusOptions.value = (res as any).rows || res.data || [];
} catch (e) {
campusOptions.value = [];
}
};
/** 查询学院专业树形结构 */
const getCollegeTree = async () => {
const res = await collegeTree();
collegeTreeData.value = res.data;
};
/** 查询专业列表 */
const getMajorList = async (collegeId: number) => {
if (!collegeId) {
majorOptions.value = [];
return;
}
const res = await listMajorsByCollegeId(collegeId);
majorOptions.value = res.data;
};
/** 查询表单中的专业列表 */
const getFormMajorList = async (collegeId: number) => {
if (!collegeId) {
formMajorOptions.value = [];
return;
}
const res = await listMajorsByCollegeId(collegeId);
formMajorOptions.value = res.data;
};
/** 学院选择框变化事件 */
const handleCollegeChange = (value: number) => {
queryParams.value.majorId = undefined;
if (value) {
getMajorList(value);
} else {
majorOptions.value = [];
}
};
/** 表单学院选择框变化事件 */
const handleFormCollegeChange = (value: number) => {
form.value.majorId = undefined;
form.value.majorName = undefined;
if (value) {
// 设置学院名称
const college = collegeOptions.value.find((item) => item.deptId === value);
if (college) {
form.value.collegeName = college.deptName;
}
getFormMajorList(value);
} else {
form.value.collegeName = undefined;
formMajorOptions.value = [];
}
};
/** 表单专业选择框变化事件 */
const handleFormMajorChange = (value: number) => {
if (value) {
// 设置专业名称
const major = formMajorOptions.value.find((item) => item.deptId === value);
if (major) {
form.value.majorName = major.deptName;
}
} else {
form.value.majorName = undefined;
}
};
/** 表单校区变更:同步名称 */
const handleFormCampusChange = (campusId?: string | number | null) => {
if (campusId === undefined || campusId === null || campusId === '') {
form.value.campusId = undefined;
form.value.campusName = undefined;
return;
}
const campus = campusOptions.value.find((item) => String(item.id) === String(campusId));
form.value.campusName = campus?.campusName;
};
// 监听班级名称变化,自动同步到班级代码
watch(
() => form.value.className,
(newVal) => {
// 只在新增模式下同步班级代码(即id未定义时)
if (!form.value.id && newVal) {
form.value.classCode = newVal;
}
}
);
/** 根据入学年份 + 学制自动计算毕业年份 */
const syncGraduationYear = () => {
const enrollmentYear = Number(form.value.enrollmentYear);
const schoolSystem = Number(form.value.schoolSystem);
if (Number.isFinite(enrollmentYear) && Number.isFinite(schoolSystem) && schoolSystem > 0) {
form.value.graduationYear = enrollmentYear + schoolSystem;
}
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
classMsgFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
majorOptions.value = [];
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: ClassMsgVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
dialog.title = '添加班级信息';
};
/** 导入按钮操作 */
const handleImport = () => {
upload.title = '班级信息导入';
upload.open = true;
};
/** 下载导入模板 */
const importTemplate = () => {
proxy?.download('classMsg/classMsg/importTemplate', {}, `班级信息导入模板_${new Date().getTime()}.xlsx`);
};
/** 文件上传中处理 */
const handleFileUploadProgress = () => {
upload.isUploading = true;
};
/** 文件上传成功处理 */
const handleFileSuccess = (response: any, file: UploadFile) => {
upload.open = false;
upload.isUploading = false;
uploadRef.value?.handleRemove(file);
ElMessageBox.alert(
"<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + (response.msg || '导入完成') + '</div>',
'导入结果',
{ dangerouslyUseHTMLString: true }
);
getList();
};
/** 文件上传失败处理 */
const handleFileError = () => {
upload.isUploading = false;
proxy?.$modal.msgError('导入失败,请检查文件格式或网络连接');
};
/** 提交上传文件 */
const submitFileForm = () => {
uploadRef.value?.submit();
};
/** 修改按钮操作 */
const handleUpdate = async (row?: ClassMsgVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getClassMsg(_id);
console.log(res);
Object.assign(form.value, res.data);
// 确保classType是字符串类型,null时设置为undefined
if (form.value.classType !== undefined && form.value.classType !== null) {
form.value.classType = String(form.value.classType);
} else {
form.value.classType = undefined;
}
// 确保isGraduation是字符串类型,null时设置为undefined
if (form.value.isGraduation !== undefined && form.value.isGraduation !== null) {
form.value.isGraduation = String(form.value.isGraduation);
} else {
form.value.isGraduation = undefined;
}
// 确保classStatus是字符串类型,null时设置为undefined
if (form.value.classStatus !== undefined && form.value.classStatus !== null) {
form.value.classStatus = String(form.value.classStatus);
} else {
form.value.classStatus = undefined;
}
// 获取该学院下的专业列表
if (form.value.collegeId) {
await getFormMajorList(form.value.collegeId as number);
}
dialog.visible = true;
dialog.title = '修改班级信息';
};
/** 提交按钮 */
const submitForm = () => {
classMsgFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateClassMsg(form.value).finally(() => (buttonLoading.value = false));
} else {
await addClassMsg(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: ClassMsgVO) => {
const _ids = row?.id || ids.value;
// 获取要删除的班级名称
let classNames = '';
if (row) {
// 单个删除时直接使用行数据中的班级名称
classNames = row.className;
} else {
// 批量删除时,根据ids查找对应的班级名称并拼接
classNames = classMsgList.value
.filter((item) => ids.value.includes(item.id))
.map((item) => item.className)
.join('、');
}
await proxy?.$modal.confirm('是否确认删除班级"' + classNames + '"?').finally(() => (loading.value = false));
await delClassMsg(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 批量状态更新通用方法 */
const handleBatchChangeStatus = async (status: '2' | '3' | '4', actionLabel: string) => {
// 选中名称用于确认提示
const classNames =
classMsgList.value
.filter((item) => ids.value.includes(item.id))
.map((item) => item.className)
.join('、') || '';
await proxy?.$modal.confirm(`是否将班级「${classNames}」批量设置为【${actionLabel}】?`).finally(() => (loading.value = false));
buttonLoading.value = true;
try {
// 批量更新所选班级状态(后端单次处理)
await updateClassStatusBatch({ ids: ids.value, classStatus: status });
proxy?.$modal.msgSuccess(`${actionLabel}操作成功`);
await getList();
} finally {
buttonLoading.value = false;
}
};
/** 批量设置为毕业 */
const handleBatchGraduate = async () => {
if (!ids.value || ids.value.length === 0) {
proxy?.$modal.msgWarning('请先勾选需要操作的班级');
return;
}
await handleBatchChangeStatus('3', '毕业');
};
/** 批量设置为暂停 */
const handleBatchPause = async () => {
if (!ids.value || ids.value.length === 0) {
proxy?.$modal.msgWarning('请先勾选需要操作的班级');
return;
}
await handleBatchChangeStatus('2', '暂停');
};
/** 批量设置为解散 */
const handleBatchDissolve = async () => {
if (!ids.value || ids.value.length === 0) {
proxy?.$modal.msgWarning('请先勾选需要操作的班级');
return;
}
await handleBatchChangeStatus('4', '解散');
};
/** 打开批量设置校区弹窗 */
const handleBatchSetCampus = () => {
if (!ids.value || ids.value.length === 0) {
proxy?.$modal.msgWarning('请先勾选需要操作的班级');
return;
}
campusBatchDialog.campusId = undefined;
campusBatchDialog.visible = true;
};
/** 提交批量设置校区 */
const submitBatchSetCampus = async () => {
if (campusBatchDialog.campusId === undefined || campusBatchDialog.campusId === null || campusBatchDialog.campusId === '') {
proxy?.$modal.msgWarning('请选择校区');
return;
}
buttonLoading.value = true;
try {
await updateClassCampusBatch({ ids: ids.value, campusId: campusBatchDialog.campusId });
proxy?.$modal.msgSuccess('批量设置校区成功');
campusBatchDialog.visible = false;
await getList();
} finally {
buttonLoading.value = false;
}
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'classMsg/classMsg/export',
{
...queryParams.value
},
`classMsg_${new Date().getTime()}.xlsx`
);
};
/** 格式化班级类型 */
const formatClassType = (value: number | string) => {
const map = {
'1': '中级工',
'2': '高级工',
'3': '预备技师',
'4': '技师',
'5': '中高职一体'
};
return map[value] || value;
};
/** 格式化班级状态 */
const formatClassStatus = (value: number | string) => {
const map = {
'1': '正常',
'2': '暂停',
'3': '毕业',
'4': '解散'
};
return map[value] || value;
};
/** 获取班级类型标签类型 */
const getClassTypeTag = (value: number | string) => {
const map = {
'1': 'success', // 中级工
'2': 'warning', // 高级工
'3': 'primary', // 预备技师
'4': 'danger', // 技师
'5': 'primary' // 中高职一体
};
return map[value] || 'primary';
};
/** 获取班级状态标签类型 */
const getClassStatusTag = (value: number | string) => {
const map = {
'1': 'success', // 正常
'2': 'info', // 暂停
'3': 'danger', // 毕业
'4': 'warning' // 解散
};
return map[value] || 'primary';
};
// 班主任对话框数据
const classTeacherDialog = reactive({
visible: false,
loading: false,
classInfo: {
id: undefined,
collegeName: '',
majorName: '',
className: '',
grade: ''
},
form: {
classId: undefined,
classTeacherId: undefined,
classTeacherName: ''
},
teachers: [] as Array<{ id: number; userId: string; nickName: string; phonenumber: string }>
});
// 辅导员对话框数据
const counselorDialog = reactive({
visible: false,
loading: false,
classInfo: {
id: undefined,
collegeName: '',
majorName: '',
className: '',
grade: ''
},
form: {
classId: undefined,
counselorId: undefined,
counselorName: ''
},
counselors: [] as Array<{ id: number; userId: string; nickName: string; phonenumber: string }>
});
// 获取有效用户列表
const fetchActiveUsers = async () => {
try {
const res = await getActiveUserList();
if (res && res.data) {
// 转换为需要的格式
const users = res.data.map((user) => ({
id: user.userId,
userId: user.userId,
nickName: user.nickName,
phonenumber: user.phonenumber || ''
}));
return users;
}
return [];
} catch (error) {
console.error('获取用户列表失败', error);
return [];
}
};
/** 处理班主任检索 */
const handleTeacherSearch = async (query: string) => {
classTeacherDialog.loading = true;
try {
const users = await fetchActiveUsers();
if (query) {
classTeacherDialog.teachers = users.filter(
(item) => item.nickName.includes(query) || item.userId.toString().includes(query) || (item.phonenumber && item.phonenumber.includes(query))
);
} else {
classTeacherDialog.teachers = users;
}
} catch (error) {
console.error('搜索用户失败', error);
} finally {
classTeacherDialog.loading = false;
}
};
/** 处理辅导员检索 */
const handleCounselorSearch = async (query: string) => {
counselorDialog.loading = true;
try {
const users = await fetchActiveUsers();
if (query) {
counselorDialog.counselors = users.filter(
(item) => item.nickName.includes(query) || item.userId.toString().includes(query) || (item.phonenumber && item.phonenumber.includes(query))
);
} else {
counselorDialog.counselors = users;
}
} catch (error) {
console.error('搜索用户失败', error);
} finally {
counselorDialog.loading = false;
}
};
/** 设置班主任按钮操作 */
const handleSetClassTeacher = async (row: ClassMsgVO) => {
classTeacherDialog.classInfo = {
id: row.id,
collegeName: row.collegeName,
majorName: row.majorName,
className: row.className,
grade: row.grade
};
classTeacherDialog.form = {
classId: row.id,
classTeacherId: row.classTeacherId,
classTeacherName: row.classTeacherName
};
classTeacherDialog.loading = true;
try {
const users = await fetchActiveUsers();
classTeacherDialog.teachers = users;
} catch (error) {
console.error('获取用户数据失败', error);
} finally {
classTeacherDialog.loading = false;
}
classTeacherDialog.visible = true;
};
/** 设置辅导员按钮操作 */
const handleSetCounselor = async (row: ClassMsgVO) => {
counselorDialog.classInfo = {
id: row.id,
collegeName: row.collegeName,
majorName: row.majorName,
className: row.className,
grade: row.grade
};
counselorDialog.form = {
classId: row.id,
counselorId: row.counselorId,
counselorName: row.counselorName
};
counselorDialog.loading = true;
try {
const users = await fetchActiveUsers();
counselorDialog.counselors = users;
} catch (error) {
console.error('获取用户数据失败', error);
} finally {
counselorDialog.loading = false;
}
counselorDialog.visible = true;
};
/** 提交班主任设置 */
const submitClassTeacher = async () => {
buttonLoading.value = true;
try {
// 构建关联数据
const teacherRelData: any = {
classId: classTeacherDialog.classInfo.id,
teacherType: 'class_teacher' // 教师类型:class_teacher-班主任,counselor-辅导员,advisor-导师'
};
// 判断是否选择了班主任
if (classTeacherDialog.form.classTeacherId) {
// 获取选中的班主任信息
const selectedTeacher = classTeacherDialog.teachers.find((item) => item.id === classTeacherDialog.form.classTeacherId);
if (selectedTeacher) {
// 添加班主任信息
teacherRelData.teacherId = selectedTeacher.id;
teacherRelData.teacherName = selectedTeacher.nickName;
teacherRelData.startDate = new Date().toISOString();
teacherRelData.endDate = null;
}
} else {
// 清空班主任信息
teacherRelData.teacherId = 123;
teacherRelData.teacherName = 'none123';
teacherRelData.startDate = new Date().toISOString();
teacherRelData.endDate = new Date().toISOString();
teacherRelData.isDeleted = true; // 标记为删除
}
// 调用API - 无论是新增还是更新,都使用相同的API
// 后端API会根据是否已存在班主任自动处理逻辑删除和新增
await addClassTeacherCounselorRel(teacherRelData);
proxy?.$modal.msgSuccess('班主任设置成功');
classTeacherDialog.visible = false;
await getList(); // 刷新列表
} catch (error) {
console.error('设置班主任失败', error);
proxy?.$modal.msgError('设置失败,请重试');
} finally {
buttonLoading.value = false;
}
};
/** 提交辅导员设置 */
const submitCounselor = async () => {
buttonLoading.value = true;
try {
// 构建关联数据
const counselorRelData: any = {
classId: counselorDialog.classInfo.id,
teacherType: 'counselor' // 教师类型:class_teacher-班主任,counselor-辅导员,advisor-导师'
};
// 判断是否选择了辅导员
if (counselorDialog.form.counselorId) {
// 获取选中的辅导员信息
const selectedCounselor = counselorDialog.counselors.find((item) => item.id === counselorDialog.form.counselorId);
if (selectedCounselor) {
// 添加辅导员信息
counselorRelData.teacherId = selectedCounselor.id;
counselorRelData.teacherName = selectedCounselor.nickName;
counselorRelData.startDate = new Date().toISOString();
counselorRelData.endDate = null;
}
} else {
// 清空辅导员信息
counselorRelData.teacherId = 123;
counselorRelData.teacherName = 'none123';
counselorRelData.startDate = new Date().toISOString();
counselorRelData.endDate = new Date().toISOString();
counselorRelData.isDeleted = true; // 标记为删除
}
// 调用API - 无论是新增还是更新,都使用相同的API
// 后端API会根据是否已存在辅导员自动处理逻辑删除和新增
await addClassTeacherCounselorRel(counselorRelData);
proxy?.$modal.msgSuccess('辅导员设置成功');
counselorDialog.visible = false;
await getList(); // 刷新列表
} catch (error) {
console.error('设置辅导员失败', error);
proxy?.$modal.msgError('设置失败,请重试');
} finally {
buttonLoading.value = false;
}
};
onMounted(() => {
getList();
getCollegeList();
getCollegeTree();
getCampusList();
});
</script>
<style scoped>
/* 页面容器样式 */
.page-container {
padding: 8px;
}
/* 搜索按钮容器样式 */
.search-btn-container {
display: flex;
justify-content: flex-end;
margin-top: 10px;
.el-form-item {
margin-bottom: 0 !important;
}
}
</style>