|
|
@@ -121,55 +121,43 @@
|
|
|
<!-- 发送试卷弹窗 -->
|
|
|
<el-dialog v-model="sendPaperDialogVisible" title="发送试卷" width="60%" destroy-on-close>
|
|
|
<el-form :model="sendPaperForm" label-width="100px">
|
|
|
- <el-form-item label="学校">
|
|
|
- <el-select
|
|
|
- v-model="sendPaperForm.schoolId"
|
|
|
- placeholder="请选择学校"
|
|
|
- clearable
|
|
|
- filterable
|
|
|
- style="width: 100%"
|
|
|
- @change="handleSchoolChange"
|
|
|
- >
|
|
|
- <el-option
|
|
|
- v-for="school in schoolList"
|
|
|
- :key="school.id"
|
|
|
- :label="school.name"
|
|
|
- :value="school.id"
|
|
|
- />
|
|
|
- </el-select>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="班级">
|
|
|
- <el-select
|
|
|
- v-model="sendPaperForm.classId"
|
|
|
- placeholder="请先选择学校"
|
|
|
- clearable
|
|
|
- filterable
|
|
|
- style="width: 100%"
|
|
|
- :disabled="!sendPaperForm.schoolId"
|
|
|
- @change="handleClassChange"
|
|
|
- >
|
|
|
- <el-option
|
|
|
- v-for="cls in classList"
|
|
|
- :key="cls.classId"
|
|
|
- :label="cls.name"
|
|
|
- :value="cls.classId"
|
|
|
- />
|
|
|
- </el-select>
|
|
|
- </el-form-item>
|
|
|
+ <SchoolClassSelect
|
|
|
+ ref="schoolClassSelectRef"
|
|
|
+ v-model="sendPaperForm"
|
|
|
+ :enable-campus="true"
|
|
|
+ :multiple-class="true"
|
|
|
+ :auto-load="false"
|
|
|
+ school-label="所在学校"
|
|
|
+ school-class-label="学校班级"
|
|
|
+ campus-label="培训校区"
|
|
|
+ campus-class-label="校区班级"
|
|
|
+ school-placeholder="请选择所在学校"
|
|
|
+ school-class-placeholder="请选择学校班级"
|
|
|
+ campus-placeholder="请选择培训校区"
|
|
|
+ campus-class-placeholder="请选择校区班级"
|
|
|
+ @change="handleSchoolClassChange"
|
|
|
+ />
|
|
|
<el-form-item label="学生列表">
|
|
|
<div style="max-height: 400px; overflow-y: auto; border: 1px solid #dcdfe6; border-radius: 4px; padding: 10px;">
|
|
|
<el-checkbox-group v-model="selectedStudentIds" v-loading="studentListLoading">
|
|
|
- <el-checkbox
|
|
|
- v-for="student in studentList"
|
|
|
- :key="student.studentId"
|
|
|
- :label="student.studentId"
|
|
|
- style="display: block; margin-bottom: 8px;"
|
|
|
- >
|
|
|
- {{ student.studentName || `学生ID: ${student.studentId}` }}
|
|
|
- </el-checkbox>
|
|
|
+ <div class="student-checkbox-container">
|
|
|
+ <el-checkbox
|
|
|
+ v-for="student in studentList"
|
|
|
+ :key="student.cardId"
|
|
|
+ :label="student.userId || student.cardId"
|
|
|
+ :disabled="student.isSend === true"
|
|
|
+ :class="{ 'is-sent': student.isSend === true }"
|
|
|
+ class="student-checkbox-item"
|
|
|
+ >
|
|
|
+ <span :class="{ 'text-gray': student.isSend === true }">
|
|
|
+ {{ student.nickName || student.userName || `卡片${student.cardNo || student.cardId}` }}
|
|
|
+ <span v-if="student.isSend === true" class="sent-tag">(已发送)</span>
|
|
|
+ </span>
|
|
|
+ </el-checkbox>
|
|
|
+ </div>
|
|
|
</el-checkbox-group>
|
|
|
<div v-if="!studentListLoading && studentList.length === 0" style="text-align: center; color: #909399; padding: 20px;">
|
|
|
- 请先选择学校和班级
|
|
|
+ 请先选择学校和班级或校区和校区班级
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-form-item>
|
|
|
@@ -184,13 +172,12 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup name="ListPaperRecords">
|
|
|
-import { ref, computed, getCurrentInstance, onMounted, markRaw } from 'vue'
|
|
|
+import { ref, computed, getCurrentInstance, onMounted, markRaw, nextTick } from 'vue'
|
|
|
import { useInjectGlobalLoading } from "@/views/hooks/useGlobalLoading.js"
|
|
|
-import { getPapers, getFrontPaperDetail } from "@/api/dz/papers.js"
|
|
|
+import { getPapers, getFrontPaperDetail, sendPaper } from "@/api/dz/papers.js"
|
|
|
import { listPaper_question } from "@/api/learn/paper_question.js"
|
|
|
-import { getAllSchool } from "@/api/dz/school.js"
|
|
|
-import { getClassesBySchoolId } from "@/api/dz/classes.js"
|
|
|
-import { listStudent } from "@/api/learn/student.js"
|
|
|
+import { listCards2 } from "@/api/dz/cards.js"
|
|
|
+import SchoolClassSelect from '@/views/dz/components/SchoolClassSelect.vue'
|
|
|
import { ElMessage } from 'element-plus'
|
|
|
import Table from '@/components/Table/index.vue'
|
|
|
import DictTag from '@/components/DictTag/index.vue'
|
|
|
@@ -252,10 +239,11 @@ const currentPaperId = ref(null)
|
|
|
const sendPaperDialogVisible = ref(false)
|
|
|
const sendPaperForm = ref({
|
|
|
schoolId: null,
|
|
|
- classId: null
|
|
|
+ schoolClassIds: null,
|
|
|
+ campusId: null,
|
|
|
+ campusClassIds: null,
|
|
|
+ classId: null // 用于兼容原有逻辑
|
|
|
})
|
|
|
-const schoolList = ref([])
|
|
|
-const classList = ref([])
|
|
|
const studentList = ref([])
|
|
|
const selectedStudentIds = ref([])
|
|
|
const studentListLoading = ref(false)
|
|
|
@@ -371,8 +359,11 @@ const handleShowPaperQuestion = (paperId) => {
|
|
|
paperQuestionDialogVisible.value = true
|
|
|
}
|
|
|
|
|
|
+// 学校班级选择组件的引用
|
|
|
+const schoolClassSelectRef = ref(null)
|
|
|
+
|
|
|
// 显示发送试卷弹窗
|
|
|
-const handleSendPaper = (row) => {
|
|
|
+const handleSendPaper = async (row) => {
|
|
|
if (!row || !row.paperId) {
|
|
|
ElMessage.warning('试卷信息不存在')
|
|
|
return
|
|
|
@@ -381,77 +372,111 @@ const handleSendPaper = (row) => {
|
|
|
currentPaperRow.value = row
|
|
|
sendPaperForm.value = {
|
|
|
schoolId: null,
|
|
|
+ schoolClassIds: null,
|
|
|
+ campusId: null,
|
|
|
+ campusClassIds: null,
|
|
|
classId: null
|
|
|
}
|
|
|
- classList.value = []
|
|
|
studentList.value = []
|
|
|
selectedStudentIds.value = []
|
|
|
sendPaperDialogVisible.value = true
|
|
|
|
|
|
- // 加载学校列表
|
|
|
- loadSchoolList()
|
|
|
-}
|
|
|
-
|
|
|
-// 加载学校列表
|
|
|
-const loadSchoolList = async () => {
|
|
|
- try {
|
|
|
- const response = await getAllSchool()
|
|
|
- if (response && response.data) {
|
|
|
- schoolList.value = response.data
|
|
|
- } else {
|
|
|
- schoolList.value = []
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error('加载学校列表失败:', error)
|
|
|
- ElMessage.error('加载学校列表失败')
|
|
|
- schoolList.value = []
|
|
|
+ // 等待弹窗打开后,再加载学校列表和校区列表
|
|
|
+ await nextTick()
|
|
|
+ if (schoolClassSelectRef.value) {
|
|
|
+ await Promise.all([
|
|
|
+ schoolClassSelectRef.value.loadSchoolList(true),
|
|
|
+ schoolClassSelectRef.value.loadCampusList()
|
|
|
+ ])
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 学校变化时加载班级列表
|
|
|
-const handleSchoolChange = async (schoolId) => {
|
|
|
- sendPaperForm.value.classId = null
|
|
|
- classList.value = []
|
|
|
- studentList.value = []
|
|
|
- selectedStudentIds.value = []
|
|
|
+// 学校班级变化处理
|
|
|
+const handleSchoolClassChange = async (data) => {
|
|
|
+ // 更新表单数据
|
|
|
+ sendPaperForm.value.schoolId = data.schoolId
|
|
|
+ sendPaperForm.value.schoolClassIds = data.schoolClassIds
|
|
|
+ sendPaperForm.value.campusId = data.campusId
|
|
|
+ sendPaperForm.value.campusClassIds = data.campusClassIds
|
|
|
|
|
|
- if (!schoolId) {
|
|
|
- return
|
|
|
- }
|
|
|
+ // 判断是否有学校班级或校区班级
|
|
|
+ const hasSchoolClass = data.schoolClassIds && (
|
|
|
+ (Array.isArray(data.schoolClassIds) && data.schoolClassIds.length > 0) ||
|
|
|
+ (!Array.isArray(data.schoolClassIds) && data.schoolClassIds)
|
|
|
+ )
|
|
|
+ const hasCampusClass = data.campusClassIds && (
|
|
|
+ (Array.isArray(data.campusClassIds) && data.campusClassIds.length > 0) ||
|
|
|
+ (!Array.isArray(data.campusClassIds) && data.campusClassIds)
|
|
|
+ )
|
|
|
|
|
|
- try {
|
|
|
- const response = await getClassesBySchoolId({ schoolId })
|
|
|
- if (response && response.data) {
|
|
|
- classList.value = response.data
|
|
|
- } else {
|
|
|
- classList.value = []
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error('加载班级列表失败:', error)
|
|
|
- ElMessage.error('加载班级列表失败')
|
|
|
- classList.value = []
|
|
|
+ // 如果选择了班级,加载学生列表
|
|
|
+ if ((hasSchoolClass && data.schoolId) || (hasCampusClass && data.campusId)) {
|
|
|
+ await loadStudentList()
|
|
|
+ } else {
|
|
|
+ studentList.value = []
|
|
|
+ selectedStudentIds.value = []
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 班级变化时加载学生列表
|
|
|
-const handleClassChange = async (classId) => {
|
|
|
- studentList.value = []
|
|
|
- selectedStudentIds.value = []
|
|
|
-
|
|
|
- if (!classId || !sendPaperForm.value.schoolId) {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
+// 加载学生列表
|
|
|
+const loadStudentList = async () => {
|
|
|
studentListLoading.value = true
|
|
|
try {
|
|
|
- const response = await listStudent({
|
|
|
- schoolId: sendPaperForm.value.schoolId,
|
|
|
- classId: classId,
|
|
|
+ const params = {
|
|
|
pageNum: 1,
|
|
|
- pageSize: 1000
|
|
|
- })
|
|
|
+ pageSize: 10000 // 获取所有学生
|
|
|
+ }
|
|
|
+
|
|
|
+ // 传递 paperId,用于判断学生是否已发送
|
|
|
+ // 从表格数据看,row 中有 paperId 字段(对应 learn_paper.id)
|
|
|
+ if (currentPaperRow.value) {
|
|
|
+ if (currentPaperRow.value.paperId) {
|
|
|
+ params.paperId = currentPaperRow.value.paperId
|
|
|
+ } else {
|
|
|
+ console.warn('paperId 不存在,无法判断学生是否已发送', currentPaperRow.value)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 优先使用学校班级,如果没有则使用校区班级
|
|
|
+ if (sendPaperForm.value.schoolId && sendPaperForm.value.schoolClassIds) {
|
|
|
+ // 使用学校班级
|
|
|
+ const classIds = Array.isArray(sendPaperForm.value.schoolClassIds)
|
|
|
+ ? sendPaperForm.value.schoolClassIds
|
|
|
+ : [sendPaperForm.value.schoolClassIds]
|
|
|
+
|
|
|
+ // 如果有多个班级,需要分别查询或使用第一个班级
|
|
|
+ // 这里先使用第一个班级,如果需要支持多班级,可以循环查询
|
|
|
+ params.schoolId = sendPaperForm.value.schoolId
|
|
|
+ params.classId = classIds[0]
|
|
|
+ } else if (sendPaperForm.value.campusId && sendPaperForm.value.campusClassIds) {
|
|
|
+ // 使用校区班级
|
|
|
+ const classIds = Array.isArray(sendPaperForm.value.campusClassIds)
|
|
|
+ ? sendPaperForm.value.campusClassIds
|
|
|
+ : [sendPaperForm.value.campusClassIds]
|
|
|
+
|
|
|
+ params.campusId = sendPaperForm.value.campusId
|
|
|
+ params.campusClassId = classIds[0]
|
|
|
+ } else {
|
|
|
+ studentList.value = []
|
|
|
+ selectedStudentIds.value = []
|
|
|
+ studentListLoading.value = false
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const response = await listCards2(params)
|
|
|
if (response && response.rows) {
|
|
|
+ // 从卡片数据中提取学生信息
|
|
|
+ // 只保留已关联用户的卡片(有nickName表示已关联用户)
|
|
|
studentList.value = response.rows
|
|
|
+ .filter(card => card.nickName || card.cardId) // 保留有昵称或卡片ID的记录
|
|
|
+ .map(card => ({
|
|
|
+ userId: card.userId || null, // userId可能不存在,使用cardId作为标识
|
|
|
+ cardId: card.cardId,
|
|
|
+ nickName: card.nickName || card.cardNo || `卡片${card.cardId}`,
|
|
|
+ userName: card.userName || null,
|
|
|
+ cardNo: card.cardNo,
|
|
|
+ isSend: card.isSend || false // 保留 isSend 字段
|
|
|
+ }))
|
|
|
} else {
|
|
|
studentList.value = []
|
|
|
}
|
|
|
@@ -471,13 +496,18 @@ const handleConfirmSend = async () => {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- if (!sendPaperForm.value.schoolId) {
|
|
|
- ElMessage.warning('请选择学校')
|
|
|
- return
|
|
|
- }
|
|
|
+ // 检查学校班级或校区班级(至少选择一组)
|
|
|
+ const hasSchoolClass = sendPaperForm.value.schoolId && sendPaperForm.value.schoolClassIds && (
|
|
|
+ (Array.isArray(sendPaperForm.value.schoolClassIds) && sendPaperForm.value.schoolClassIds.length > 0) ||
|
|
|
+ (!Array.isArray(sendPaperForm.value.schoolClassIds) && sendPaperForm.value.schoolClassIds)
|
|
|
+ )
|
|
|
+ const hasCampusClass = sendPaperForm.value.campusId && sendPaperForm.value.campusClassIds && (
|
|
|
+ (Array.isArray(sendPaperForm.value.campusClassIds) && sendPaperForm.value.campusClassIds.length > 0) ||
|
|
|
+ (!Array.isArray(sendPaperForm.value.campusClassIds) && sendPaperForm.value.campusClassIds)
|
|
|
+ )
|
|
|
|
|
|
- if (!sendPaperForm.value.classId) {
|
|
|
- ElMessage.warning('请选择班级')
|
|
|
+ if (!hasSchoolClass && !hasCampusClass) {
|
|
|
+ ElMessage.warning('请选择学校班级或校区班级')
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -488,13 +518,39 @@ const handleConfirmSend = async () => {
|
|
|
|
|
|
sending.value = true
|
|
|
try {
|
|
|
- // TODO: 调用发送试卷的API
|
|
|
- // 这里需要根据实际的API接口来实现
|
|
|
- ElMessage.success(`试卷已发送给 ${selectedStudentIds.value.length} 个学生`)
|
|
|
+ // 获取 testPaperId(表格中的 id 字段,对应 learn_test_paper.id)
|
|
|
+ // 从 SQL 查询看,返回的字段是 t1.id,应该就是 id
|
|
|
+ // 如果 id 不存在,打印调试信息
|
|
|
+ const testPaperId = currentPaperRow.value.id
|
|
|
+
|
|
|
+ if (!testPaperId) {
|
|
|
+ // 打印完整的数据结构,帮助调试
|
|
|
+ console.error('当前行数据:', JSON.stringify(currentPaperRow.value, null, 2))
|
|
|
+ console.error('可用的字段:', Object.keys(currentPaperRow.value))
|
|
|
+ ElMessage.error('试卷ID不存在,请检查数据。已打印调试信息到控制台')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取选中的学生的 cardId 列表
|
|
|
+ const selectedCardIds = studentList.value
|
|
|
+ .filter(student => selectedStudentIds.value.includes(student.userId || student.cardId))
|
|
|
+ .map(student => student.cardId)
|
|
|
+ .filter(cardId => cardId != null)
|
|
|
+
|
|
|
+ if (selectedCardIds.length === 0) {
|
|
|
+ ElMessage.warning('请至少选择一个有效的学生')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 调用发送试卷的API
|
|
|
+ await sendPaper(testPaperId, selectedCardIds)
|
|
|
+ ElMessage.success(`试卷已发送给 ${selectedCardIds.length} 个学生`)
|
|
|
sendPaperDialogVisible.value = false
|
|
|
+ // 刷新列表
|
|
|
+ await getList()
|
|
|
} catch (error) {
|
|
|
console.error('发送试卷失败:', error)
|
|
|
- ElMessage.error('发送试卷失败')
|
|
|
+ ElMessage.error(error?.msg || error?.message || '发送试卷失败')
|
|
|
} finally {
|
|
|
sending.value = false
|
|
|
}
|
|
|
@@ -727,5 +783,34 @@ onMounted(() => {
|
|
|
color: #303133;
|
|
|
flex: 1;
|
|
|
}
|
|
|
+
|
|
|
+/* 学生复选框容器 */
|
|
|
+.student-checkbox-container {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 学生复选框项 - 一行显示3个 */
|
|
|
+.student-checkbox-item {
|
|
|
+ flex: 0 0 calc(33.333% - 8px);
|
|
|
+ min-width: 200px;
|
|
|
+ max-width: calc(33.333% - 8px);
|
|
|
+}
|
|
|
+
|
|
|
+/* 已发送的学生样式 */
|
|
|
+.is-sent {
|
|
|
+ opacity: 0.6;
|
|
|
+}
|
|
|
+
|
|
|
+.text-gray {
|
|
|
+ color: #909399;
|
|
|
+}
|
|
|
+
|
|
|
+.sent-tag {
|
|
|
+ color: #909399;
|
|
|
+ font-size: 12px;
|
|
|
+ margin-left: 4px;
|
|
|
+}
|
|
|
</style>
|
|
|
|