提交代码
This commit is contained in:
1 parent
bee68f318d
commit
a884f695ea
8 files changed
+847
-107
No files matched your search
+24
-4
@@ -19,6 +19,8 @@ import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.xg.domain.vo.XgDormViolationVo;
|
||||
import org.dromara.xg.domain.bo.XgDormViolationBo;
|
||||
import org.dromara.xg.domain.vo.StudentOptionVo;
|
||||
import org.dromara.xg.domain.bo.StudentOptionBo;
|
||||
import org.dromara.xg.service.IXgDormViolationService;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
@@ -63,8 +65,7 @@ public class XgDormViolationController extends BaseController {
|
||||
*/
|
||||
@SaCheckPermission("dormViolation:dormViolation:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<XgDormViolationVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
public R<XgDormViolationVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
|
||||
return R.ok(xgDormViolationService.queryById(id));
|
||||
}
|
||||
|
||||
@@ -98,8 +99,27 @@ public class XgDormViolationController extends BaseController {
|
||||
@SaCheckPermission("dormViolation:dormViolation:remove")
|
||||
@Log(title = "宿舍违纪记录", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] ids) {
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
|
||||
return toAjax(xgDormViolationService.deleteWithValidByIds(List.of(ids), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取学生选择器选项列表(支持按学号、姓名检索)
|
||||
*/
|
||||
@SaCheckPermission("dormViolation:dormViolation:list")
|
||||
@GetMapping("/studentOptions")
|
||||
public TableDataInfo<StudentOptionVo> getStudentOptions(StudentOptionBo bo, PageQuery pageQuery) {
|
||||
return xgDormViolationService.getStudentOptions(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据学生ID获取学生详细信息
|
||||
*
|
||||
* @param studentId 学生ID
|
||||
*/
|
||||
@SaCheckPermission("dormViolation:dormViolation:list")
|
||||
@GetMapping("/student/{studentId}")
|
||||
public R<StudentOptionVo> getStudentById(@NotNull(message = "学生ID不能为空") @PathVariable Long studentId) {
|
||||
return R.ok(xgDormViolationService.getStudentById(studentId));
|
||||
}
|
||||
}
|
||||
+21
@@ -2,7 +2,12 @@ package org.dromara.xg.mapper;
|
||||
|
||||
import org.dromara.xg.domain.XgDormViolation;
|
||||
import org.dromara.xg.domain.vo.XgDormViolationVo;
|
||||
import org.dromara.xg.domain.vo.StudentOptionVo;
|
||||
import org.dromara.xg.domain.bo.StudentOptionBo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* 宿舍违纪记录Mapper接口
|
||||
@@ -12,4 +17,20 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
*/
|
||||
public interface XgDormViolationMapper extends BaseMapperPlus<XgDormViolation, XgDormViolationVo> {
|
||||
|
||||
/**
|
||||
* 查询学生选择器选项列表(支持按学号、姓名检索)
|
||||
*
|
||||
* @param page 分页参数
|
||||
* @param bo 查询条件
|
||||
* @return 学生选项列表
|
||||
*/
|
||||
Page<StudentOptionVo> selectStudentOptions(IPage<?> page, @Param("bo") StudentOptionBo bo);
|
||||
|
||||
/**
|
||||
* 根据学生ID获取学生详细信息
|
||||
*
|
||||
* @param studentId 学生ID
|
||||
* @return 学生详细信息
|
||||
*/
|
||||
StudentOptionVo selectStudentById(@Param("studentId") Long studentId);
|
||||
}
|
||||
+19
@@ -2,6 +2,8 @@ package org.dromara.xg.service;
|
||||
|
||||
import org.dromara.xg.domain.vo.XgDormViolationVo;
|
||||
import org.dromara.xg.domain.bo.XgDormViolationBo;
|
||||
import org.dromara.xg.domain.vo.StudentOptionVo;
|
||||
import org.dromara.xg.domain.bo.StudentOptionBo;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
|
||||
@@ -65,4 +67,21 @@ public interface IXgDormViolationService {
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
/**
|
||||
* 获取学生选择器选项列表(支持按学号、姓名检索)
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 学生选项分页列表
|
||||
*/
|
||||
TableDataInfo<StudentOptionVo> getStudentOptions(StudentOptionBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 根据学生ID获取学生详细信息
|
||||
*
|
||||
* @param studentId 学生ID
|
||||
* @return 学生详细信息
|
||||
*/
|
||||
StudentOptionVo getStudentById(Long studentId);
|
||||
}
|
||||
+39
-9
@@ -12,6 +12,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.dromara.xg.domain.bo.XgDormViolationBo;
|
||||
import org.dromara.xg.domain.vo.XgDormViolationVo;
|
||||
import org.dromara.xg.domain.bo.StudentOptionBo;
|
||||
import org.dromara.xg.domain.vo.StudentOptionVo;
|
||||
import org.dromara.xg.domain.XgDormViolation;
|
||||
import org.dromara.xg.mapper.XgDormViolationMapper;
|
||||
import org.dromara.xg.service.IXgDormViolationService;
|
||||
@@ -40,7 +42,7 @@ public class XgDormViolationServiceImpl implements IXgDormViolationService {
|
||||
* @return 宿舍违纪记录
|
||||
*/
|
||||
@Override
|
||||
public XgDormViolationVo queryById(Long id){
|
||||
public XgDormViolationVo queryById(Long id) {
|
||||
return baseMapper.selectVoById(id);
|
||||
}
|
||||
|
||||
@@ -94,11 +96,15 @@ public class XgDormViolationServiceImpl implements IXgDormViolationService {
|
||||
lqw.eq(bo.getBedId() != null, XgDormViolation::getBedId, bo.getBedId());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getBedName()), XgDormViolation::getBedName, bo.getBedName());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getViolationType()), XgDormViolation::getViolationType, bo.getViolationType());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getViolationLevel()), XgDormViolation::getViolationLevel, bo.getViolationLevel());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getViolationLevel()), XgDormViolation::getViolationLevel,
|
||||
bo.getViolationLevel());
|
||||
lqw.eq(bo.getViolationTime() != null, XgDormViolation::getViolationTime, bo.getViolationTime());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getViolationDescription()), XgDormViolation::getViolationDescription, bo.getViolationDescription());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getInvolvedStudents()), XgDormViolation::getInvolvedStudents, bo.getInvolvedStudents());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getAttachmentOssIds()), XgDormViolation::getAttachmentOssIds, bo.getAttachmentOssIds());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getViolationDescription()), XgDormViolation::getViolationDescription,
|
||||
bo.getViolationDescription());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getInvolvedStudents()), XgDormViolation::getInvolvedStudents,
|
||||
bo.getInvolvedStudents());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getAttachmentOssIds()), XgDormViolation::getAttachmentOssIds,
|
||||
bo.getAttachmentOssIds());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getDeleted()), XgDormViolation::getDeleted, bo.getDeleted());
|
||||
return lqw;
|
||||
}
|
||||
@@ -136,8 +142,8 @@ public class XgDormViolationServiceImpl implements IXgDormViolationService {
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(XgDormViolation entity){
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
private void validEntityBeforeSave(XgDormViolation entity) {
|
||||
// TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,9 +155,33 @@ public class XgDormViolationServiceImpl implements IXgDormViolationService {
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if(isValid){
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
if (isValid) {
|
||||
// TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取学生选择器选项列表(支持按学号、姓名检索)
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 学生选项分页列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<StudentOptionVo> getStudentOptions(StudentOptionBo bo, PageQuery pageQuery) {
|
||||
Page<StudentOptionVo> result = baseMapper.selectStudentOptions(pageQuery.build(), bo);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据学生ID获取学生详细信息
|
||||
*
|
||||
* @param studentId 学生ID
|
||||
* @return 学生详细信息
|
||||
*/
|
||||
@Override
|
||||
public StudentOptionVo getStudentById(Long studentId) {
|
||||
return baseMapper.selectStudentById(studentId);
|
||||
}
|
||||
}
|
||||
+114
@@ -4,4 +4,118 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.dromara.xg.mapper.XgDormViolationMapper">
|
||||
|
||||
<!-- 学生选项查询结果映射 -->
|
||||
<resultMap id="StudentOptionResult" type="org.dromara.xg.domain.vo.StudentOptionVo">
|
||||
<id property="id" column="id"/>
|
||||
<result property="studentNo" column="student_no"/>
|
||||
<result property="name" column="name"/>
|
||||
<result property="gender" column="gender"/>
|
||||
<result property="collegeId" column="college_id"/>
|
||||
<result property="collegeName" column="college_name"/>
|
||||
<result property="majorId" column="major_id"/>
|
||||
<result property="majorName" column="major_name"/>
|
||||
<result property="classId" column="class_id"/>
|
||||
<result property="className" column="class_name"/>
|
||||
<result property="phone" column="phone"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<association property="dormInfo" javaType="org.dromara.xg.domain.vo.StudentOptionVo$DormInfo">
|
||||
<result property="campusId" column="campus_id"/>
|
||||
<result property="campusName" column="campus_name"/>
|
||||
<result property="areaId" column="area_id"/>
|
||||
<result property="areaName" column="area_name"/>
|
||||
<result property="buildingId" column="building_id"/>
|
||||
<result property="buildingName" column="building_name"/>
|
||||
<result property="roomId" column="room_id"/>
|
||||
<result property="roomName" column="room_name"/>
|
||||
<result property="bedId" column="bed_id"/>
|
||||
<result property="bedName" column="bed_name"/>
|
||||
</association>
|
||||
</resultMap>
|
||||
|
||||
<!-- 查询学生选择器选项列表 -->
|
||||
<select id="selectStudentOptions" resultMap="StudentOptionResult">
|
||||
SELECT
|
||||
s.id,
|
||||
s.student_no,
|
||||
s.name,
|
||||
s.gender,
|
||||
s.college_id,
|
||||
s.college_name,
|
||||
s.major_id,
|
||||
s.major_name,
|
||||
s.class_id,
|
||||
s.class_name,
|
||||
s.phone,
|
||||
s.create_by,
|
||||
s.create_time,
|
||||
s.update_by,
|
||||
s.update_time,
|
||||
COALESCE(dc.id, NULL) as campus_id,
|
||||
COALESCE(dc.campus_name, NULL) as campus_name,
|
||||
COALESCE(da.id, NULL) as area_id,
|
||||
COALESCE(da.area_name, NULL) as area_name,
|
||||
COALESCE(db.id, NULL) as building_id,
|
||||
COALESCE(db.building_name, NULL) as building_name,
|
||||
COALESCE(dr.id, NULL) as room_id,
|
||||
COALESCE(dr.room_name, NULL) as room_name,
|
||||
COALESCE(bed.id, NULL) as bed_id,
|
||||
COALESCE(bed.bed_name, NULL) as bed_name
|
||||
FROM xg_student_msg s
|
||||
LEFT JOIN xg_dorm_bed_student dbs ON s.id = dbs.student_id AND dbs.deleted = 0
|
||||
LEFT JOIN xg_dorm_bed bed ON dbs.bed_id = bed.id AND bed.deleted = 0
|
||||
LEFT JOIN xg_dorm_room dr ON bed.room_id = dr.id AND dr.deleted = 0
|
||||
LEFT JOIN xg_dorm_building db ON dr.building_id = db.id AND db.deleted = 0
|
||||
LEFT JOIN xg_dorm_area da ON db.area_id = da.id AND da.deleted = 0
|
||||
LEFT JOIN xg_dorm_campus dc ON da.campus_id = dc.id AND dc.deleted = 0
|
||||
WHERE s.deleted = 0
|
||||
AND s.student_status = '1'
|
||||
<if test="bo.keyword != null and bo.keyword != ''">
|
||||
AND (s.student_no LIKE CONCAT('%', #{bo.keyword}, '%')
|
||||
OR s.name LIKE CONCAT('%', #{bo.keyword}, '%'))
|
||||
</if>
|
||||
ORDER BY s.student_no ASC
|
||||
</select>
|
||||
|
||||
<!-- 根据学生ID获取学生详细信息 -->
|
||||
<select id="selectStudentById" resultMap="StudentOptionResult">
|
||||
SELECT
|
||||
s.id,
|
||||
s.student_no,
|
||||
s.name,
|
||||
s.gender,
|
||||
s.college_id,
|
||||
s.college_name,
|
||||
s.major_id,
|
||||
s.major_name,
|
||||
s.class_id,
|
||||
s.class_name,
|
||||
s.phone,
|
||||
s.create_by,
|
||||
s.create_time,
|
||||
s.update_by,
|
||||
s.update_time,
|
||||
COALESCE(dc.id, NULL) as campus_id,
|
||||
COALESCE(dc.campus_name, NULL) as campus_name,
|
||||
COALESCE(da.id, NULL) as area_id,
|
||||
COALESCE(da.area_name, NULL) as area_name,
|
||||
COALESCE(db.id, NULL) as building_id,
|
||||
COALESCE(db.building_name, NULL) as building_name,
|
||||
COALESCE(dr.id, NULL) as room_id,
|
||||
COALESCE(dr.room_name, NULL) as room_name,
|
||||
COALESCE(bed.id, NULL) as bed_id,
|
||||
COALESCE(bed.bed_name, NULL) as bed_name
|
||||
FROM xg_student_msg s
|
||||
LEFT JOIN xg_dorm_bed_student dbs ON s.id = dbs.student_id AND dbs.deleted = 0
|
||||
LEFT JOIN xg_dorm_bed bed ON dbs.bed_id = bed.id AND bed.deleted = 0
|
||||
LEFT JOIN xg_dorm_room dr ON bed.room_id = dr.id AND dr.deleted = 0
|
||||
LEFT JOIN xg_dorm_building db ON dr.building_id = db.id AND db.deleted = 0
|
||||
LEFT JOIN xg_dorm_area da ON db.area_id = da.id AND da.deleted = 0
|
||||
LEFT JOIN xg_dorm_campus dc ON da.campus_id = dc.id AND dc.deleted = 0
|
||||
WHERE s.deleted = 0
|
||||
AND s.id = #{studentId}
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -78,12 +78,14 @@ export const delDormViolation = (id: string | number | Array<string | number>) =
|
||||
* @param query 查询参数
|
||||
* @returns 学生选项列表
|
||||
*/
|
||||
export const getStudentOptions = (query?: StudentOptionQuery): AxiosPromise<{
|
||||
export const getStudentOptions = (
|
||||
query?: StudentOptionQuery
|
||||
): AxiosPromise<{
|
||||
total: number;
|
||||
rows: StudentOptionVO[];
|
||||
}> => {
|
||||
return request({
|
||||
url: '/holidayStay/holidayStay/studentOptions',
|
||||
url: '/dormViolation/dormViolation/studentOptions',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
@@ -151,3 +153,15 @@ export const getBedOptions = (roomId?: string | number): AxiosPromise<any[]> =>
|
||||
params: roomId ? { roomId } : undefined
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据学生ID获取学生详细信息
|
||||
* @param studentId 学生ID
|
||||
* @returns 学生详细信息
|
||||
*/
|
||||
export const getStudentById = (studentId: string | number): AxiosPromise<StudentOptionVO> => {
|
||||
return request({
|
||||
url: `/dormViolation/dormViolation/student/${studentId}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
@@ -263,9 +263,9 @@ export interface DormViolationForm extends BaseEntity {
|
||||
violationDescription?: string;
|
||||
|
||||
/**
|
||||
* 涉及其他学生id(逗号分隔)
|
||||
* 涉及其他学生id(逗号分隔)或数组
|
||||
*/
|
||||
involvedStudents?: string;
|
||||
involvedStudents?: string | (string | number)[];
|
||||
|
||||
/**
|
||||
* 附件OSS ID列表(逗号分隔)
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
>修改</el-button
|
||||
>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<!-- <el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
@@ -116,7 +116,7 @@
|
||||
v-hasPermi="['dormViolation:dormViolation:remove']"
|
||||
>删除</el-button
|
||||
>
|
||||
</el-col>
|
||||
</el-col> -->
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['dormViolation:dormViolation:export']">导出</el-button>
|
||||
</el-col>
|
||||
@@ -126,47 +126,47 @@
|
||||
|
||||
<el-table v-loading="loading" border :data="dormViolationList" @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="学生ID" align="center" prop="studentId" />
|
||||
<!-- <el-table-column label="违纪记录ID" align="center" prop="id" v-if="true" />
|
||||
<el-table-column label="学生ID" align="center" prop="studentId" /> -->
|
||||
<el-table-column label="学生姓名" align="center" prop="studentName" />
|
||||
<el-table-column label="学号" align="center" prop="studentNo" />
|
||||
<el-table-column label="学院ID" align="center" prop="collegeId" />
|
||||
<!-- <el-table-column label="学院ID" align="center" prop="collegeId" /> -->
|
||||
<el-table-column label="学院名称" align="center" prop="collegeName" />
|
||||
<el-table-column label="专业ID" align="center" prop="majorId" />
|
||||
<!-- <el-table-column label="专业ID" align="center" prop="majorId" /> -->
|
||||
<el-table-column label="专业名称" align="center" prop="majorName" />
|
||||
<el-table-column label="班级ID" align="center" prop="classId" />
|
||||
<!-- <el-table-column label="班级ID" align="center" prop="classId" /> -->
|
||||
<el-table-column label="班级名称" align="center" prop="className" />
|
||||
<el-table-column label="校区ID" align="center" prop="campusId" />
|
||||
<!-- <el-table-column label="校区ID" align="center" prop="campusId" /> -->
|
||||
<el-table-column label="校区名称" align="center" prop="campusName" />
|
||||
<el-table-column label="宿舍区域ID" align="center" prop="areaId" />
|
||||
<!-- <el-table-column label="宿舍区域ID" align="center" prop="areaId" /> -->
|
||||
<el-table-column label="宿舍区域名称" align="center" prop="areaName" />
|
||||
<el-table-column label="宿舍楼ID" align="center" prop="buildingId" />
|
||||
<!-- <el-table-column label="宿舍楼ID" align="center" prop="buildingId" /> -->
|
||||
<el-table-column label="宿舍楼名称" align="center" prop="buildingName" />
|
||||
<el-table-column label="宿舍房间ID" align="center" prop="roomId" />
|
||||
<!-- <el-table-column label="宿舍房间ID" align="center" prop="roomId" /> -->
|
||||
<el-table-column label="房间名称" align="center" prop="roomName" />
|
||||
<el-table-column label="床位ID" align="center" prop="bedId" />
|
||||
<!-- <el-table-column label="床位ID" align="center" prop="bedId" /> -->
|
||||
<el-table-column label="床位名称" align="center" prop="bedName" />
|
||||
<el-table-column label="违纪类型" align="center" prop="violationType">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="dorm_violation_type" :value="scope.row.violationType" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="违纪等级:1轻微 2一般 3严重 4特别严重" align="center" prop="violationLevel">
|
||||
<el-table-column label="违纪等级" align="center" prop="violationLevel">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="dorm_violation_level" :value="scope.row.violationLevel" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="违纪发生时间" align="center" prop="violationTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.violationTime, '{y}-{m}-{d}') }}</span>
|
||||
<span>{{ parseTime(scope.row.violationTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="违纪行为描述" align="center" prop="violationDescription" />
|
||||
<el-table-column label="涉及其他学生id" align="center" prop="involvedStudents" />
|
||||
<el-table-column label="附件OSS ID列表" align="center" prop="attachmentOssIds" />
|
||||
<el-table-column label="删除标志" align="center" prop="deleted" />
|
||||
<!-- <el-table-column label="涉及其他学生id" align="center" prop="involvedStudents" /> -->
|
||||
<!-- <el-table-column label="附件OSS ID列表" align="center" prop="attachmentOssIds" /> -->
|
||||
<!-- <el-table-column label="删除标志" align="center" prop="deleted" /> -->
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="120">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="修改" placement="top">
|
||||
<el-button
|
||||
@@ -180,7 +180,7 @@
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
type="danger"
|
||||
icon="Delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
v-hasPermi="['dormViolation:dormViolation:remove']"
|
||||
@@ -377,13 +377,89 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="涉及其他学生" prop="involvedStudents">
|
||||
<el-input v-model="form.involvedStudents" placeholder="请输入涉及其他学生ID" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 涉及其他学生 - 单独一行 -->
|
||||
<el-form-item label="涉及其他学生" prop="involvedStudents">
|
||||
<el-select
|
||||
v-model="form.involvedStudents"
|
||||
placeholder="请选择涉及的其他学生"
|
||||
filterable
|
||||
remote
|
||||
:remote-method="remoteSearchInvolvedStudents"
|
||||
:loading="involvedStudentLoading"
|
||||
clearable
|
||||
multiple
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
style="width: 100%"
|
||||
@visible-change="handleInvolvedStudentSelectVisibleChange"
|
||||
@change="handleInvolvedStudentsChange"
|
||||
popper-class="involved-student-select-dropdown"
|
||||
>
|
||||
<el-option
|
||||
v-for="student in involvedStudentOptions.filter((s) => s.id !== form.studentId)"
|
||||
:key="student.id"
|
||||
:label="`${student.name} (${student.studentNo})`"
|
||||
:value="student.id"
|
||||
>
|
||||
<div class="student-option">
|
||||
<div class="student-main">
|
||||
<span class="student-name">{{ student.name }}</span>
|
||||
<span class="student-no">{{ student.studentNo }}</span>
|
||||
<span class="student-gender">{{ student.gender === '0' ? '男' : '女' }}</span>
|
||||
</div>
|
||||
<div class="student-info" v-if="student.collegeName || student.majorName || student.className">
|
||||
<span v-if="student.collegeName && student.collegeName.trim()" class="info-item">{{ student.collegeName }}</span>
|
||||
<span v-if="student.majorName && student.majorName.trim()" class="info-item">{{ student.majorName }}</span>
|
||||
<span v-if="student.className && student.className.trim()" class="info-item">{{ student.className }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<div class="form-tip">
|
||||
<el-icon><InfoFilled /></el-icon>
|
||||
<span>支持多选,可搜索学号或姓名,最多选择10名学生</span>
|
||||
</div>
|
||||
|
||||
<!-- 涉及其他学生信息展示表格 -->
|
||||
<div v-if="selectedInvolvedStudents.length > 0" class="involved-students-table-container">
|
||||
<div class="table-header">
|
||||
<span class="table-title">已选择的涉及学生信息</span>
|
||||
<span class="table-count">(共 {{ selectedInvolvedStudents.length }} 人)</span>
|
||||
</div>
|
||||
<el-table :data="selectedInvolvedStudents" size="small" border stripe class="involved-students-table" max-height="300">
|
||||
<el-table-column label="序号" type="index" width="50" align="center" />
|
||||
<el-table-column label="姓名" prop="name" width="120" align="center" />
|
||||
<el-table-column label="学号" prop="studentNo" width="120" align="center" />
|
||||
<el-table-column label="性别" prop="gender" width="60" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.gender === '0' ? 'primary' : 'danger'" size="small">
|
||||
{{ scope.row.gender === '0' ? '男' : '女' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="学院" prop="collegeName" min-width="120" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="专业" prop="majorName" min-width="120" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="班级" prop="className" min-width="120" align="center" show-overflow-tooltip />
|
||||
<!-- <el-table-column label="宿舍信息" min-width="150" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<div v-if="scope.row.dormInfo" class="dorm-info">
|
||||
<div>{{ scope.row.dormInfo.campusName }}</div>
|
||||
<div>{{ scope.row.dormInfo.buildingName }} - {{ scope.row.dormInfo.roomName }}</div>
|
||||
</div>
|
||||
<span v-else class="no-dorm">暂无宿舍信息</span>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column label="操作" width="80" align="center" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button type="danger" size="small" link @click="removeInvolvedStudent(scope.row.id)"> 移除 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 完整宽度的字段 -->
|
||||
<el-form-item label="违纪行为描述" prop="violationDescription">
|
||||
<el-input v-model="form.violationDescription" type="textarea" placeholder="请输入违纪行为描述" :rows="3" />
|
||||
@@ -483,7 +559,7 @@ import { ref, reactive, toRefs, onMounted, getCurrentInstance, ComponentInternal
|
||||
import ElMessage from 'element-plus/es/components/message/index';
|
||||
import ElMessageBox from 'element-plus/es/components/message-box/index';
|
||||
import ElLoading from 'element-plus/es/components/loading/index';
|
||||
import { UploadFilled, Document, Loading, Download, Delete } from '@element-plus/icons-vue';
|
||||
import { UploadFilled, Document, Loading, Download, Delete, InfoFilled } from '@element-plus/icons-vue';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import ImagePreview from '@/components/ImagePreview/index.vue';
|
||||
import request from '@/utils/request';
|
||||
@@ -494,6 +570,7 @@ import {
|
||||
addDormViolation,
|
||||
updateDormViolation,
|
||||
getStudentOptions,
|
||||
getStudentById,
|
||||
getCampusOptions,
|
||||
getAreaOptions,
|
||||
getBuildingOptions,
|
||||
@@ -530,6 +607,76 @@ const studentOptions = ref<StudentOptionVO[]>([]);
|
||||
const studentLoading = ref(false);
|
||||
const studentSelectVisible = ref(false);
|
||||
|
||||
// 涉及其他学生选择器相关状态
|
||||
const involvedStudentOptions = ref<StudentOptionVO[]>([]);
|
||||
const involvedStudentLoading = ref(false);
|
||||
const involvedStudentSelectVisible = ref(false);
|
||||
|
||||
// 存储已选择的涉及学生完整信息
|
||||
const selectedInvolvedStudentsMap = ref<Map<string | number, StudentOptionVO>>(new Map());
|
||||
|
||||
// 计算属性:获取已选择的涉及学生详细信息
|
||||
const selectedInvolvedStudents = computed(() => {
|
||||
if (!form.value.involvedStudents || !Array.isArray(form.value.involvedStudents)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
console.log('计算涉及学生信息 - 当前ID列表:', form.value.involvedStudents);
|
||||
console.log('当前Map大小:', selectedInvolvedStudentsMap.value.size);
|
||||
console.log('当前涉及学生选项数量:', involvedStudentOptions.value.length);
|
||||
|
||||
const result = form.value.involvedStudents
|
||||
.map((id) => {
|
||||
console.log(`处理学生ID: ${id}`);
|
||||
|
||||
// 优先从已保存的完整信息中获取(包括预加载的占位符)
|
||||
const savedStudent = selectedInvolvedStudentsMap.value.get(id);
|
||||
if (savedStudent) {
|
||||
console.log(`从Map中找到学生: ${savedStudent.name}`);
|
||||
return savedStudent;
|
||||
}
|
||||
|
||||
// 从涉及学生选项中查找详细信息
|
||||
const student = involvedStudentOptions.value.find((s) => s.id === id);
|
||||
if (student) {
|
||||
console.log(`从涉及学生选项中找到: ${student.name}`);
|
||||
// 保存到Map中,避免后续丢失
|
||||
selectedInvolvedStudentsMap.value.set(id, student);
|
||||
return student;
|
||||
}
|
||||
|
||||
// 如果涉及学生选项中没有,从主学生选项中查找
|
||||
const mainStudent = studentOptions.value.find((s) => s.id === id);
|
||||
if (mainStudent) {
|
||||
console.log(`从主学生选项中找到: ${mainStudent.name}`);
|
||||
// 保存到Map中,避免后续丢失
|
||||
selectedInvolvedStudentsMap.value.set(id, mainStudent);
|
||||
return mainStudent;
|
||||
}
|
||||
|
||||
console.log(`未找到学生 ${id} 的详细信息,创建临时占位符`);
|
||||
// 如果都没有找到,创建一个临时的占位符信息
|
||||
const tempPlaceholder = {
|
||||
id: id,
|
||||
name: `学生${id.toString().slice(-4)}`, // 使用ID后4位作为显示名称
|
||||
studentNo: id.toString(),
|
||||
gender: '',
|
||||
collegeName: '信息加载中...',
|
||||
majorName: '信息加载中...',
|
||||
className: '信息加载中...',
|
||||
dormInfo: null
|
||||
};
|
||||
|
||||
// 将临时占位符也保存到Map中,避免重复创建
|
||||
selectedInvolvedStudentsMap.value.set(id, tempPlaceholder);
|
||||
return tempPlaceholder;
|
||||
})
|
||||
.filter((student) => student); // 过滤掉无效数据
|
||||
|
||||
console.log('最终涉及学生列表:', result);
|
||||
return result;
|
||||
});
|
||||
|
||||
// 宿舍级联选择器相关状态
|
||||
const campusOptions = ref<CampusOptionVO[]>([]);
|
||||
const areaOptions = ref<AreaOptionVO[]>([]);
|
||||
@@ -538,6 +685,25 @@ const roomOptions = ref<RoomOptionVO[]>([]);
|
||||
const bedOptions = ref<BedOptionVO[]>([]);
|
||||
const dormLoading = ref(false);
|
||||
|
||||
// 缓存机制,避免重复请求
|
||||
const dormCache = ref<Map<string, any[]>>(new Map());
|
||||
const cacheExpireTime = 5 * 60 * 1000; // 5分钟缓存过期
|
||||
const cacheTimestamps = ref<Map<string, number>>(new Map());
|
||||
|
||||
// 缓存工具函数
|
||||
const getCachedData = (key: string) => {
|
||||
const timestamp = cacheTimestamps.value.get(key);
|
||||
if (timestamp && Date.now() - timestamp < cacheExpireTime) {
|
||||
return dormCache.value.get(key);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const setCachedData = (key: string, data: any[]) => {
|
||||
dormCache.value.set(key, data);
|
||||
cacheTimestamps.value.set(key, Date.now());
|
||||
};
|
||||
|
||||
// 附件上传相关状态
|
||||
const attachmentList = ref<any[]>([]);
|
||||
|
||||
@@ -574,7 +740,7 @@ const initFormData: DormViolationForm = {
|
||||
violationLevel: undefined,
|
||||
violationTime: undefined,
|
||||
violationDescription: undefined,
|
||||
involvedStudents: undefined,
|
||||
involvedStudents: [] as (string | number)[], // 初始化为空数组
|
||||
attachmentOssIds: undefined,
|
||||
deleted: undefined,
|
||||
remark: undefined
|
||||
@@ -624,7 +790,19 @@ const data = reactive<PageData<DormViolationForm, DormViolationQuery>>({
|
||||
violationType: [{ required: true, message: '违纪类型不能为空', trigger: 'change' }],
|
||||
violationLevel: [{ required: true, message: '违纪等级:1轻微 2一般 3严重 4特别严重不能为空', trigger: 'change' }],
|
||||
violationTime: [{ required: true, message: '违纪发生时间不能为空', trigger: 'blur' }],
|
||||
violationDescription: [{ required: true, message: '违纪行为描述不能为空', trigger: 'blur' }]
|
||||
violationDescription: [{ required: true, message: '违纪行为描述不能为空', trigger: 'blur' }],
|
||||
involvedStudents: [
|
||||
{
|
||||
validator: (rule: any, value: any, callback: any) => {
|
||||
if (Array.isArray(value) && value.length > 10) {
|
||||
callback(new Error('最多只能选择10名学生'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
trigger: 'change'
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
@@ -676,6 +854,9 @@ const reset = () => {
|
||||
|
||||
// 清空附件列表
|
||||
attachmentList.value = [];
|
||||
|
||||
// 清空已选择的涉及学生信息Map
|
||||
selectedInvolvedStudentsMap.value.clear();
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
@@ -706,19 +887,67 @@ const handleAdd = () => {
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: DormViolationVO) => {
|
||||
reset();
|
||||
const _id = row?.id || ids.value[0];
|
||||
const res = await getDormViolation(_id);
|
||||
Object.assign(form.value, res.data);
|
||||
|
||||
// 根据已有数据级联加载宿舍选项
|
||||
await loadCascadeOptionsForUpdate(form.value);
|
||||
|
||||
// 处理附件数据
|
||||
await handleAttachmentData();
|
||||
|
||||
// 先显示弹窗,提升用户体验
|
||||
dialog.visible = true;
|
||||
dialog.title = '修改宿舍违纪记录';
|
||||
|
||||
// 显示加载状态
|
||||
const loadingInstance = ElLoading.service({
|
||||
target: '.el-dialog__body',
|
||||
text: '正在加载数据...',
|
||||
background: 'rgba(255, 255, 255, 0.8)'
|
||||
});
|
||||
|
||||
try {
|
||||
reset();
|
||||
const _id = row?.id || ids.value[0];
|
||||
|
||||
// 并行执行数据加载,提升性能
|
||||
const [violationRes, campusRes] = await Promise.all([
|
||||
getDormViolation(_id),
|
||||
getCampusOptions() // 预加载校区选项
|
||||
]);
|
||||
|
||||
Object.assign(form.value, violationRes.data);
|
||||
campusOptions.value = campusRes.rows || [];
|
||||
|
||||
console.log('编辑违纪记录,使用原始数据:', violationRes.data);
|
||||
|
||||
// 处理涉及其他学生数据 - 将逗号分隔的字符串转换为数组
|
||||
if (form.value.involvedStudents && typeof form.value.involvedStudents === 'string') {
|
||||
form.value.involvedStudents = form.value.involvedStudents
|
||||
.split(',')
|
||||
.map((id) => id.trim())
|
||||
.filter((id) => id) as (string | number)[];
|
||||
|
||||
console.log('编辑时的涉及学生ID列表:', form.value.involvedStudents);
|
||||
}
|
||||
|
||||
// 并行执行其他数据加载任务
|
||||
const loadTasks = [];
|
||||
|
||||
// 如果有涉及学生,异步加载学生信息
|
||||
if (form.value.involvedStudents && form.value.involvedStudents.length > 0) {
|
||||
loadTasks.push(
|
||||
Promise.all([loadInvolvedStudentsInfo(form.value.involvedStudents), loadInvolvedStudentsForSelect(form.value.involvedStudents)])
|
||||
);
|
||||
}
|
||||
|
||||
// 异步加载宿舍级联选项
|
||||
loadTasks.push(loadCascadeOptionsForUpdate(form.value));
|
||||
|
||||
// 异步处理附件数据
|
||||
loadTasks.push(handleAttachmentData());
|
||||
|
||||
// 等待所有异步任务完成
|
||||
await Promise.all(loadTasks);
|
||||
} catch (error) {
|
||||
console.error('加载编辑数据失败:', error);
|
||||
ElMessage.error('加载数据失败,请重试');
|
||||
dialog.visible = false;
|
||||
} finally {
|
||||
loadingInstance.close();
|
||||
}
|
||||
};
|
||||
|
||||
/** 提交按钮 */
|
||||
@@ -733,6 +962,11 @@ const submitForm = () => {
|
||||
// 将附件ID添加到表单数据中,处理成逗号分隔的字符串
|
||||
form.value.attachmentOssIds = attachmentOssIds.join(',');
|
||||
|
||||
// 处理涉及其他学生数据 - 将数组转换为逗号分隔的字符串
|
||||
if (Array.isArray(form.value.involvedStudents)) {
|
||||
form.value.involvedStudents = form.value.involvedStudents.join(',');
|
||||
}
|
||||
|
||||
if (form.value.id) {
|
||||
await updateDormViolation(form.value).finally(() => (buttonLoading.value = false));
|
||||
} else {
|
||||
@@ -776,7 +1010,8 @@ const remoteSearchStudents = async (query: string) => {
|
||||
};
|
||||
const res = await getStudentOptions(params);
|
||||
console.log('学生搜索响应:', res);
|
||||
studentOptions.value = res.rows || [];
|
||||
// 修复:正确处理API返回的数据结构
|
||||
studentOptions.value = res.data?.rows || res.rows || [];
|
||||
|
||||
// 调试:检查第一个学生的数据
|
||||
if (studentOptions.value.length > 0) {
|
||||
@@ -818,7 +1053,8 @@ const loadInitialStudents = async () => {
|
||||
};
|
||||
const res = await getStudentOptions(params);
|
||||
console.log('初始学生数据响应:', res);
|
||||
studentOptions.value = res.rows || [];
|
||||
// 修复:正确处理API返回的数据结构
|
||||
studentOptions.value = res.data?.rows || res.rows || [];
|
||||
|
||||
// 调试:检查第一个学生的数据
|
||||
if (studentOptions.value.length > 0) {
|
||||
@@ -839,6 +1075,171 @@ const loadInitialStudents = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
/** 远程搜索涉及其他学生 */
|
||||
const remoteSearchInvolvedStudents = async (query: string) => {
|
||||
involvedStudentLoading.value = true;
|
||||
try {
|
||||
const params: StudentOptionQuery = {
|
||||
keyword: query.trim(),
|
||||
pageNum: 1,
|
||||
pageSize: 20
|
||||
};
|
||||
const res = await getStudentOptions(params);
|
||||
console.log('涉及学生搜索响应:', res);
|
||||
// 修复:正确处理API返回的数据结构
|
||||
involvedStudentOptions.value = res.data?.rows || res.rows || [];
|
||||
} catch (error) {
|
||||
console.error('搜索涉及学生失败:', error);
|
||||
involvedStudentOptions.value = [];
|
||||
} finally {
|
||||
involvedStudentLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
/** 涉及其他学生选择器可见性变化处理 */
|
||||
const handleInvolvedStudentSelectVisibleChange = async (visible: boolean) => {
|
||||
involvedStudentSelectVisible.value = visible;
|
||||
|
||||
// 当下拉框打开且没有数据时,加载初始数据
|
||||
if (visible && involvedStudentOptions.value.length === 0) {
|
||||
await loadInitialInvolvedStudents();
|
||||
}
|
||||
};
|
||||
|
||||
/** 加载初始涉及其他学生数据 */
|
||||
const loadInitialInvolvedStudents = async () => {
|
||||
involvedStudentLoading.value = true;
|
||||
try {
|
||||
const params: StudentOptionQuery = {
|
||||
keyword: '', // 空关键词获取初始数据
|
||||
pageNum: 1,
|
||||
pageSize: 20
|
||||
};
|
||||
const res = await getStudentOptions(params);
|
||||
console.log('初始涉及学生数据响应:', res);
|
||||
// 修复:正确处理API返回的数据结构
|
||||
involvedStudentOptions.value = res.data?.rows || res.rows || [];
|
||||
} catch (error) {
|
||||
console.error('加载初始涉及学生数据失败:', error);
|
||||
involvedStudentOptions.value = [];
|
||||
} finally {
|
||||
involvedStudentLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
/** 预加载涉及学生的完整信息 */
|
||||
const loadInvolvedStudentsInfo = async (studentIds: (string | number)[]) => {
|
||||
// 批量获取学生信息,减少接口调用次数
|
||||
try {
|
||||
const studentPromises = studentIds.map(async (studentId) => {
|
||||
try {
|
||||
const studentRes = await getStudentById(studentId);
|
||||
const studentInfo = studentRes.data;
|
||||
selectedInvolvedStudentsMap.value.set(studentId, studentInfo);
|
||||
console.log(`预加载学生 ${studentId} 信息:`, studentInfo);
|
||||
return { studentId, success: true, data: studentInfo };
|
||||
} catch (error) {
|
||||
console.error(`预加载学生 ${studentId} 信息失败:`, error);
|
||||
// 创建临时占位符
|
||||
const tempPlaceholder = {
|
||||
id: studentId,
|
||||
name: `学生${studentId.toString().slice(-4)}`,
|
||||
studentNo: studentId.toString(),
|
||||
gender: '',
|
||||
collegeName: '信息加载失败',
|
||||
majorName: '信息加载失败',
|
||||
className: '信息加载失败',
|
||||
dormInfo: null
|
||||
};
|
||||
selectedInvolvedStudentsMap.value.set(studentId, tempPlaceholder);
|
||||
return { studentId, success: false, data: tempPlaceholder };
|
||||
}
|
||||
});
|
||||
|
||||
// 并行执行所有学生信息获取
|
||||
await Promise.all(studentPromises);
|
||||
} catch (error) {
|
||||
console.error('批量加载涉及学生信息失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
/** 为选择框加载涉及学生信息 */
|
||||
const loadInvolvedStudentsForSelect = async (studentIds: (string | number)[]) => {
|
||||
try {
|
||||
// 获取涉及学生的完整信息
|
||||
const studentsInfo: StudentOptionVO[] = [];
|
||||
|
||||
for (const studentId of studentIds) {
|
||||
try {
|
||||
const studentRes = await getStudentById(studentId);
|
||||
const studentInfo = studentRes.data;
|
||||
studentsInfo.push(studentInfo);
|
||||
console.log(`为选择框加载学生 ${studentId} 信息:`, studentInfo);
|
||||
} catch (error) {
|
||||
console.error(`为选择框加载学生 ${studentId} 信息失败:`, error);
|
||||
// 创建临时占位符
|
||||
const tempPlaceholder = {
|
||||
id: studentId,
|
||||
name: `学生${studentId.toString().slice(-4)}`,
|
||||
studentNo: studentId.toString(),
|
||||
gender: '',
|
||||
collegeName: '信息加载失败',
|
||||
majorName: '信息加载失败',
|
||||
className: '信息加载失败',
|
||||
dormInfo: null
|
||||
};
|
||||
studentsInfo.push(tempPlaceholder);
|
||||
}
|
||||
}
|
||||
|
||||
// 将学生信息添加到涉及学生选项中,确保选择框能正确显示
|
||||
involvedStudentOptions.value = [...studentsInfo];
|
||||
console.log('涉及学生选择框选项已更新:', involvedStudentOptions.value);
|
||||
} catch (error) {
|
||||
console.error('为选择框加载涉及学生信息失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
/** 涉及其他学生选择变化处理 */
|
||||
const handleInvolvedStudentsChange = (selectedIds: (string | number)[]) => {
|
||||
// 确保不会选择主学生
|
||||
if (form.value.studentId && selectedIds.includes(form.value.studentId)) {
|
||||
ElMessage.warning('不能选择主学生作为涉及其他学生');
|
||||
// 移除主学生ID
|
||||
form.value.involvedStudents = selectedIds.filter((id) => id !== form.value.studentId) as (string | number)[];
|
||||
} else {
|
||||
// 直接更新选择的学生列表
|
||||
form.value.involvedStudents = selectedIds as (string | number)[];
|
||||
}
|
||||
|
||||
// 确保新选择的学生信息被保存
|
||||
selectedIds.forEach((id) => {
|
||||
if (!selectedInvolvedStudentsMap.value.has(id)) {
|
||||
// 从当前选项中查找并保存学生信息
|
||||
const student = involvedStudentOptions.value.find((s) => s.id === id);
|
||||
if (student) {
|
||||
selectedInvolvedStudentsMap.value.set(id, student);
|
||||
} else {
|
||||
// 从主学生选项中查找
|
||||
const mainStudent = studentOptions.value.find((s) => s.id === id);
|
||||
if (mainStudent) {
|
||||
selectedInvolvedStudentsMap.value.set(id, mainStudent);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/** 移除涉及学生 */
|
||||
const removeInvolvedStudent = (studentId: string | number) => {
|
||||
if (Array.isArray(form.value.involvedStudents)) {
|
||||
form.value.involvedStudents = form.value.involvedStudents.filter((id) => id !== studentId) as (string | number)[];
|
||||
// 从Map中也移除该学生信息
|
||||
selectedInvolvedStudentsMap.value.delete(studentId);
|
||||
ElMessage.success('已移除该学生');
|
||||
}
|
||||
};
|
||||
|
||||
/** 学生选择处理 */
|
||||
const handleStudentChange = async (studentId: string | number) => {
|
||||
if (!studentId) {
|
||||
@@ -868,6 +1269,11 @@ const handleStudentChange = async (studentId: string | number) => {
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果主学生ID在涉及其他学生列表中,则移除
|
||||
if (Array.isArray(form.value.involvedStudents)) {
|
||||
form.value.involvedStudents = form.value.involvedStudents.filter((id) => id !== studentId) as (string | number)[];
|
||||
}
|
||||
|
||||
const selectedStudent = studentOptions.value.find((student) => student.id === studentId);
|
||||
if (selectedStudent) {
|
||||
// 填充学生基本信息
|
||||
@@ -989,9 +1395,19 @@ const handleCampusChange = async (campusId: string | number) => {
|
||||
/** 加载宿舍区选项 */
|
||||
const loadAreaOptions = async (campusId: string | number) => {
|
||||
try {
|
||||
const cacheKey = `area_${campusId}`;
|
||||
const cachedData = getCachedData(cacheKey);
|
||||
|
||||
if (cachedData) {
|
||||
areaOptions.value = cachedData;
|
||||
return;
|
||||
}
|
||||
|
||||
dormLoading.value = true;
|
||||
const res = await getAreaOptions(campusId);
|
||||
areaOptions.value = res.rows || [];
|
||||
const data = res.rows || [];
|
||||
areaOptions.value = data;
|
||||
setCachedData(cacheKey, data);
|
||||
} catch (error) {
|
||||
console.error('加载宿舍区选项失败:', error);
|
||||
areaOptions.value = [];
|
||||
@@ -1141,25 +1557,33 @@ const handleBedChange = (bedId: string | number) => {
|
||||
/** 修改时级联加载宿舍选项数据 */
|
||||
const loadCascadeOptionsForUpdate = async (formData: DormViolationForm) => {
|
||||
try {
|
||||
// 并行加载所有需要的宿舍选项,提升性能
|
||||
const loadTasks = [];
|
||||
|
||||
// 如果有校区ID,加载宿舍区选项
|
||||
if (formData.campusId) {
|
||||
await loadAreaOptions(formData.campusId);
|
||||
loadTasks.push(loadAreaOptions(formData.campusId));
|
||||
|
||||
// 如果有宿舍区ID,加载宿舍楼选项
|
||||
if (formData.areaId) {
|
||||
await loadBuildingOptions(formData.areaId);
|
||||
loadTasks.push(loadBuildingOptions(formData.areaId));
|
||||
|
||||
// 如果有宿舍楼ID,加载房间选项
|
||||
if (formData.buildingId) {
|
||||
await loadRoomOptions(formData.buildingId);
|
||||
loadTasks.push(loadRoomOptions(formData.buildingId));
|
||||
|
||||
// 如果有房间ID,加载床位选项
|
||||
if (formData.roomId) {
|
||||
await loadBedOptions(formData.roomId);
|
||||
loadTasks.push(loadBedOptions(formData.roomId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 并行执行所有加载任务
|
||||
if (loadTasks.length > 0) {
|
||||
await Promise.all(loadTasks);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('修改时级联加载宿舍选项失败:', error);
|
||||
}
|
||||
@@ -1364,56 +1788,63 @@ const handleDownloadAttachment = async (file: any) => {
|
||||
// 处理附件数据
|
||||
const handleAttachmentData = async () => {
|
||||
try {
|
||||
// 如果有附件ID,则获取附件信息
|
||||
if (form.value.attachmentOssIds && form.value.attachmentOssIds.toString().trim()) {
|
||||
console.log('开始处理附件数据:', form.value.attachmentOssIds);
|
||||
|
||||
// 将逗号分隔的字符串转换为数组
|
||||
const ossIdsArray = form.value.attachmentOssIds
|
||||
.toString()
|
||||
.split(',')
|
||||
.map((id) => id.trim())
|
||||
.filter((id) => id);
|
||||
|
||||
// 调用接口获取附件信息
|
||||
const response = await request({
|
||||
url: `/resource/oss/listByIds/${ossIdsArray.join(',')}`,
|
||||
method: 'get'
|
||||
});
|
||||
|
||||
if (response.code === 200 && response.data) {
|
||||
console.log('获取到的附件信息:', response.data);
|
||||
|
||||
// 将附件信息转换为上传组件需要的格式
|
||||
const attachmentFiles = response.data.map((item: any, index: number) => ({
|
||||
uid: `existing_${index}_${Date.now()}`,
|
||||
name: item.originalName || `附件${index + 1}`,
|
||||
url: item.url,
|
||||
ossId: item.ossId,
|
||||
status: 'success', // 标记为已上传成功
|
||||
response: {
|
||||
code: 200,
|
||||
data: {
|
||||
url: item.url,
|
||||
ossId: item.ossId
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
// 设置附件列表
|
||||
attachmentList.value = attachmentFiles;
|
||||
console.log('设置附件列表成功:', attachmentList.value);
|
||||
} else {
|
||||
console.warn('获取附件信息失败:', response.msg);
|
||||
attachmentList.value = [];
|
||||
}
|
||||
} else {
|
||||
// 如果没有附件ID,直接返回,避免不必要的请求
|
||||
if (!form.value.attachmentOssIds || !form.value.attachmentOssIds.toString().trim()) {
|
||||
console.log('没有附件数据,清空附件列表');
|
||||
attachmentList.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('开始处理附件数据:', form.value.attachmentOssIds);
|
||||
|
||||
// 将逗号分隔的字符串转换为数组
|
||||
const ossIdsArray = form.value.attachmentOssIds
|
||||
.toString()
|
||||
.split(',')
|
||||
.map((id) => id.trim())
|
||||
.filter((id) => id);
|
||||
|
||||
// 如果附件ID数组为空,直接返回
|
||||
if (ossIdsArray.length === 0) {
|
||||
attachmentList.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
// 调用接口获取附件信息
|
||||
const response = await request({
|
||||
url: `/resource/oss/listByIds/${ossIdsArray.join(',')}`,
|
||||
method: 'get'
|
||||
});
|
||||
|
||||
if (response.code === 200 && response.data) {
|
||||
console.log('获取到的附件信息:', response.data);
|
||||
|
||||
// 将附件信息转换为上传组件需要的格式
|
||||
const attachmentFiles = response.data.map((item: any, index: number) => ({
|
||||
uid: `existing_${index}_${Date.now()}`,
|
||||
name: item.originalName || `附件${index + 1}`,
|
||||
url: item.url,
|
||||
ossId: item.ossId,
|
||||
status: 'success', // 标记为已上传成功
|
||||
response: {
|
||||
code: 200,
|
||||
data: {
|
||||
url: item.url,
|
||||
ossId: item.ossId
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
// 设置附件列表
|
||||
attachmentList.value = attachmentFiles;
|
||||
console.log('设置附件列表成功:', attachmentList.value);
|
||||
} else {
|
||||
console.warn('获取附件信息失败:', response.msg);
|
||||
attachmentList.value = [];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('处理附件数据失败:', error);
|
||||
ElMessage.error('获取附件信息失败,请稍后重试');
|
||||
// 不显示错误提示,避免影响用户体验
|
||||
attachmentList.value = [];
|
||||
}
|
||||
};
|
||||
@@ -1483,6 +1914,27 @@ onMounted(() => {
|
||||
padding: 4px 12px !important;
|
||||
}
|
||||
|
||||
:global(.involved-student-select-dropdown .el-select-dropdown__item) {
|
||||
height: auto !important;
|
||||
min-height: 32px !important;
|
||||
padding: 4px 12px !important;
|
||||
}
|
||||
|
||||
/* 表单提示样式 */
|
||||
.form-tip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
margin-top: 4px;
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.form-tip .el-icon {
|
||||
font-size: 14px;
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
/* 附件上传容器样式 */
|
||||
.attachment-upload-container {
|
||||
width: 100%;
|
||||
@@ -1692,4 +2144,74 @@ onMounted(() => {
|
||||
cursor: not-allowed;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 涉及其他学生表格样式 */
|
||||
.involved-students-table-container {
|
||||
margin-top: 12px;
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 6px;
|
||||
background: #fafafa;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.table-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 8px 12px;
|
||||
background: #f5f7fa;
|
||||
border-bottom: 1px solid #e4e7ed;
|
||||
}
|
||||
|
||||
.table-title {
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.table-count {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.involved-students-table {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.involved-students-table :deep(.el-table__header) {
|
||||
background: #f5f7fa;
|
||||
}
|
||||
|
||||
.involved-students-table :deep(.el-table__header th) {
|
||||
background: #f5f7fa;
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.involved-students-table :deep(.el-table__body td) {
|
||||
font-size: 12px;
|
||||
padding: 6px 0;
|
||||
}
|
||||
|
||||
.dorm-info {
|
||||
font-size: 11px;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.dorm-info div:first-child {
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.dorm-info div:last-child {
|
||||
color: #606266;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.no-dorm {
|
||||
color: #c0c4cc;
|
||||
font-size: 11px;
|
||||
font-style: italic;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user