提交审核

This commit is contained in:
zlwu committed 2025-09-07 23:04:08 +08:00
1 parent a3d3fccd33
commit 0a96ebf80c
14 files changed
+1832 -175

No files matched your search

@@ -134,17 +134,6 @@ public class XskhDisciplineRevokeController extends BaseController {
return toAjax(xskhDisciplineRevokeService.applyRevoke(bo));
}
/**
* 审核撤销申请
*/
@SaCheckPermission("disciplineRevoke:disciplineRevoke:approve")
@Log(title = "审核撤销申请", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/approve")
public R<Void> approveRevoke(@Validated(EditGroup.class) @RequestBody XskhDisciplineRevokeBo bo) {
return toAjax(xskhDisciplineRevokeService.approveRevoke(bo));
}
/**
* 查询班主任班级的违纪撤销申请列表(班主任专用)
*/
@@ -155,15 +144,56 @@ public class XskhDisciplineRevokeController extends BaseController {
return xskhDisciplineRevokeService.queryClassTeacherPageList(bo, pageQuery);
}
/**
* 查询班主任已审核的违纪撤销申请列表(根据审核人查询历史记录)
*/
@SaCheckPermission("disciplineRevoke:classTeacher:list")
@GetMapping("/classTeacherReviewedList")
public TableDataInfo<XskhDisciplineRevokeVo> getClassTeacherReviewedRevokeApplications(XskhDisciplineRevokeBo bo,
PageQuery pageQuery) {
return xskhDisciplineRevokeService.queryClassTeacherReviewedPageList(bo, pageQuery);
}
/**
* 班主任审核撤销申请
*/
@SaCheckPermission("disciplineRevoke:classTeacher:approve")
@Log(title = "班主任审核撤销申请", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/classTeacherApprove")
public R<Void> classTeacherApproveRevoke(@Validated(EditGroup.class) @RequestBody XskhDisciplineRevokeBo bo) {
return toAjax(xskhDisciplineRevokeService.classTeacherApproveRevoke(bo));
@PutMapping("/teacherApprove")
public R<Void> teacherApproveRevoke(@Validated(EditGroup.class) @RequestBody XskhDisciplineRevokeBo bo) {
return toAjax(xskhDisciplineRevokeService.teacherApproveRevoke(bo));
}
/**
* 查询学工处待审核的撤销申请列表(学工处专用)
*/
@SaCheckPermission("disciplineRevoke:studentAffairs:list")
@GetMapping("/studentAffairsList")
public TableDataInfo<XskhDisciplineRevokeVo> getStudentAffairsRevokeApplications(XskhDisciplineRevokeBo bo,
PageQuery pageQuery) {
return xskhDisciplineRevokeService.queryStudentAffairsPageList(bo, pageQuery);
}
/**
* 学工处审核撤销申请
*/
@SaCheckPermission("disciplineRevoke:studentAffairs:approve")
@Log(title = "学工处审核撤销申请", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/studentAffairsApprove")
public R<Void> studentAffairsApproveRevoke(@Validated(EditGroup.class) @RequestBody XskhDisciplineRevokeBo bo) {
return toAjax(xskhDisciplineRevokeService.studentAffairsApproveRevoke(bo));
}
/**
* 查询学工处已审核的撤销申请列表(学工处专用)
*/
@SaCheckPermission("disciplineRevoke:studentAffairs:list")
@GetMapping("/studentAffairsReviewedList")
public TableDataInfo<XskhDisciplineRevokeVo> getStudentAffairsReviewedRevokeApplications(XskhDisciplineRevokeBo bo,
PageQuery pageQuery) {
return xskhDisciplineRevokeService.queryStudentAffairsReviewedPageList(bo, pageQuery);
}
}
@@ -59,22 +59,37 @@ public class XskhDisciplineRevoke extends TenantEntity {
private Date applyTime;
/**
* 状态(1-待审核 2-审核通过 3-审核拒绝)
* 状态(1-待班主任审核 2-待学工处审核 3-审核通过 4-班主任审核拒绝 5-学工处审核拒绝)
*/
private String status;
/**
* 审核人ID
* 班主任审核人ID
*/
private Long teacherApprovalBy;
/**
* 班主任审核时间
*/
private Date teacherApprovalTime;
/**
* 班主任审核备注
*/
private String teacherApprovalRemark;
/**
* 学工处审核人ID
*/
private Long approvalBy;
/**
* 审核时间
* 学工处审核时间
*/
private Date approvalTime;
/**
* 审核备注
* 学工处审核备注
*/
private String approvalRemark;
@@ -68,24 +68,48 @@ public class XskhDisciplineRevokeBo extends BaseEntity {
private Date applyTime;
/**
* 状态(1-待审核 2-审核通过 3-审核拒绝)
* 状态(1-待班主任审核 2-待学工处审核 3-审核通过 4-班主任审核拒绝 5-学工处审核拒绝)
*/
private String status;
/**
* 审核人ID
* 班主任审核人ID
*/
private Long teacherApprovalBy;
/**
* 班主任审核时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date teacherApprovalTime;
/**
* 班主任审核备注
*/
private String teacherApprovalRemark;
/**
* 学工处审核人ID
*/
private Long approvalBy;
/**
* 审核时间
* 学工处审核时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date approvalTime;
/**
* 审核备注
* 学工处审核备注
*/
private String approvalRemark;
// VO类基础字段规范(避免MyBatis映射错误)
private Long createBy; // 创建者
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime; // 创建时间
private Long updateBy; // 更新者
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime; // 更新时间
}
@@ -90,35 +90,60 @@ public class XskhDisciplineRevokeVo implements Serializable {
private Date applyTime;
/**
* 状态(1-待审核 2-审核通过 3-审核拒绝)
* 状态(1-待班主任审核 2-待学工处审核 3-审核通过 4-班主任审核拒绝 5-学工处审核拒绝)
*/
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "student_revoke_status")
private String status;
/**
* 审核人ID
* 班主任审核人ID
*/
@ExcelProperty(value = "审核人ID")
@ExcelProperty(value = "班主任审核人ID")
private Long teacherApprovalBy;
/**
* 班主任审核人姓名(关联查询)
*/
@ExcelProperty(value = "班主任审核人姓名")
private String teacherApprovalByName;
/**
* 班主任审核时间
*/
@ExcelProperty(value = "班主任审核时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date teacherApprovalTime;
/**
* 班主任审核备注
*/
@ExcelProperty(value = "班主任审核备注")
private String teacherApprovalRemark;
/**
* 学工处审核人ID
*/
@ExcelProperty(value = "学工处审核人ID")
private Long approvalBy;
/**
* 审核人姓名(关联查询)
* 学工处审核人姓名(关联查询)
*/
@ExcelProperty(value = "审核人姓名")
@ExcelProperty(value = "学工处审核人姓名")
private String approvalByName;
/**
* 审核时间
* 学工处审核时间
*/
@ExcelProperty(value = "审核时间")
@ExcelProperty(value = "学工处审核时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date approvalTime;
/**
* 审核备注
* 学工处审核备注
*/
@ExcelProperty(value = "审核备注")
@ExcelProperty(value = "学工处审核备注")
private String approvalRemark;
/**
@@ -15,24 +15,58 @@ import org.dromara.xskh.domain.vo.XskhDisciplineRevokeVo;
*/
public interface XskhDisciplineRevokeMapper extends BaseMapperPlus<XskhDisciplineRevoke, XskhDisciplineRevokeVo> {
/**
* 根据违纪记录ID查询撤销申请记录
*
* @param disciplineRecordId 违纪记录ID
* @return 撤销申请记录
*/
XskhDisciplineRevokeVo selectByDisciplineRecordId(Long disciplineRecordId);
/**
* 根据违纪记录ID查询撤销申请记录
*
* @param disciplineRecordId 违纪记录ID
* @return 撤销申请记录
*/
XskhDisciplineRevokeVo selectByDisciplineRecordId(Long disciplineRecordId);
/**
* 查询班主任班级的违纪撤销申请列表(班主任专用)
*
* @param page 分页参数
* @param bo 查询条件
* @param classTeacherId 班主任ID
* @return 分页查询结果
*/
Page<XskhDisciplineRevokeVo> selectClassTeacherVoPage(@Param("page") Page<XskhDisciplineRevokeVo> page,
@Param("bo") XskhDisciplineRevokeBo bo,
@Param("classTeacherId") Long classTeacherId);
/**
* 查询班主任班级的违纪撤销申请列表(班主任专用)
*
* @param page 分页参数
* @param bo 查询条件
* @param classTeacherId 班主任ID
* @return 分页查询结果
*/
Page<XskhDisciplineRevokeVo> selectClassTeacherVoPage(@Param("page") Page<XskhDisciplineRevokeVo> page,
@Param("bo") XskhDisciplineRevokeBo bo,
@Param("classTeacherId") Long classTeacherId);
/**
* 查询学工处待审核的违纪撤销申请列表(学工处专用)
*
* @param page 分页参数
* @param bo 查询条件
* @return 分页查询结果
*/
Page<XskhDisciplineRevokeVo> selectStudentAffairsVoPage(@Param("page") Page<XskhDisciplineRevokeVo> page,
@Param("bo") XskhDisciplineRevokeBo bo);
/**
* 查询学工处已审核的违纪撤销申请列表(学工处专用)
*
* @param page 分页参数
* @param bo 查询条件
* @return 分页查询结果
*/
Page<XskhDisciplineRevokeVo> selectStudentAffairsReviewedVoPage(
@Param("page") Page<XskhDisciplineRevokeVo> page,
@Param("bo") XskhDisciplineRevokeBo bo);
/**
* 查询班主任已审核的违纪撤销申请列表(根据审核人查询历史记录)
*
* @param page 分页参数
* @param bo 查询条件
* @param classTeacherId 班主任ID
* @return 分页查询结果
*/
Page<XskhDisciplineRevokeVo> selectClassTeacherReviewedVoPage(
@Param("page") Page<XskhDisciplineRevokeVo> page,
@Param("bo") XskhDisciplineRevokeBo bo,
@Param("classTeacherId") Long classTeacherId);
}
@@ -61,19 +61,36 @@ public interface IXskhDisciplineRevokeService {
*/
Boolean applyRevoke(XskhDisciplineRevokeBo bo);
/**
* 审核撤销申请
*/
Boolean approveRevoke(XskhDisciplineRevokeBo bo);
/**
* 查询班主任班级的违纪撤销申请列表(班主任专用)
*/
TableDataInfo<XskhDisciplineRevokeVo> queryClassTeacherPageList(XskhDisciplineRevokeBo bo, PageQuery pageQuery);
/**
* 查询班主任已审核的违纪撤销申请列表(根据审核人查询历史记录)
*/
TableDataInfo<XskhDisciplineRevokeVo> queryClassTeacherReviewedPageList(XskhDisciplineRevokeBo bo,
PageQuery pageQuery);
/**
* 班主任审核撤销申请
*/
Boolean classTeacherApproveRevoke(XskhDisciplineRevokeBo bo);
Boolean teacherApproveRevoke(XskhDisciplineRevokeBo bo);
/**
* 查询学工处待审核的撤销申请列表(学工处专用)
*/
TableDataInfo<XskhDisciplineRevokeVo> queryStudentAffairsPageList(XskhDisciplineRevokeBo bo, PageQuery pageQuery);
/**
* 学工处审核撤销申请
*/
Boolean studentAffairsApproveRevoke(XskhDisciplineRevokeBo bo);
/**
* 查询学工处已审核的撤销申请列表(学工处专用)
*/
TableDataInfo<XskhDisciplineRevokeVo> queryStudentAffairsReviewedPageList(XskhDisciplineRevokeBo bo,
PageQuery pageQuery);
}
@@ -21,6 +21,7 @@ import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -197,46 +198,53 @@ public class XskhDisciplineRevokeServiceImpl implements IXskhDisciplineRevokeSer
bo.setStudentId(currentUserId);
bo.setStudentName(disciplineRecord.getStudentName());
bo.setDisciplineRecordId(bo.getDisciplineRecordId());
bo.setStatus("1"); // 待审核
bo.setStatus("1"); // 待班主任审核
bo.setApplyTime(new Date());
return insertByBo(bo);
}
/**
* 审核撤销申请
* 班主任审核撤销申请
*/
@Override
public Boolean approveRevoke(XskhDisciplineRevokeBo bo) {
// 获取当前登录用户ID作为审核人
public Boolean teacherApproveRevoke(XskhDisciplineRevokeBo bo) {
// 获取当前登录用户ID作为班主任审核人
Long currentUserId = LoginHelper.getUserId();
bo.setApprovalBy(currentUserId);
bo.setApprovalTime(new Date());
bo.setTeacherApprovalBy(currentUserId);
bo.setTeacherApprovalTime(new Date());
// 根据审核结果更新状态
if ("2".equals(bo.getStatus())) {
// 班主任审核通过,状态改为待学工处审核
} else if ("4".equals(bo.getStatus())) {
// 班主任审核拒绝,流程结束
}
return updateByBo(bo);
}
/**
* 查询班主任班级的违纪撤销申请列表(班主任专用)
* 查询学工处待审核的撤销申请列表(学工处专用)
*/
@Override
public TableDataInfo<XskhDisciplineRevokeVo> queryClassTeacherPageList(XskhDisciplineRevokeBo bo,
public TableDataInfo<XskhDisciplineRevokeVo> queryStudentAffairsPageList(XskhDisciplineRevokeBo bo,
PageQuery pageQuery) {
// 获取当前登录用户ID(班主任ID)
Long currentUserId = LoginHelper.getUserId();
// 只查询状态为2(待学工处审核)的申请
bo.setStatus("2");
// 调用mapper中的专用查询方法
Page<XskhDisciplineRevokeVo> result = baseMapper.selectClassTeacherVoPage(pageQuery.build(), bo, currentUserId);
// 调用mapper中的学工处专用查询方法
Page<XskhDisciplineRevokeVo> result = baseMapper.selectStudentAffairsVoPage(pageQuery.build(), bo);
return TableDataInfo.build(result);
}
/**
* 班主任审核撤销申请
* 学工处审核撤销申请
*/
@Override
public Boolean classTeacherApproveRevoke(XskhDisciplineRevokeBo bo) {
// 获取当前登录用户ID作为审核人
public Boolean studentAffairsApproveRevoke(XskhDisciplineRevokeBo bo) {
// 获取当前登录用户ID作为学工处审核人
Long currentUserId = LoginHelper.getUserId();
bo.setApprovalBy(currentUserId);
@@ -245,8 +253,8 @@ public class XskhDisciplineRevokeServiceImpl implements IXskhDisciplineRevokeSer
// 更新撤销申请状态
Boolean updateResult = updateByBo(bo);
// 如果撤销申请审批通过(状态为2),则同步更新违纪记录状态为已撤销
if (updateResult && "2".equals(bo.getStatus())) {
// 如果学工处审核通过(状态为3),则同步更新违纪记录状态为已撤销
if (updateResult && "3".equals(bo.getStatus())) {
// 根据撤销申请ID查询完整信息以获取违纪记录ID
XskhDisciplineRevokeVo revokeInfo = queryById(bo.getId());
if (revokeInfo != null && revokeInfo.getDisciplineRecordId() != null) {
@@ -258,4 +266,58 @@ public class XskhDisciplineRevokeServiceImpl implements IXskhDisciplineRevokeSer
return updateResult;
}
/**
* 查询班主任班级的违纪撤销申请列表(班主任专用)
*/
@Override
public TableDataInfo<XskhDisciplineRevokeVo> queryClassTeacherPageList(XskhDisciplineRevokeBo bo,
PageQuery pageQuery) {
// 获取当前登录用户ID(班主任ID)
Long currentUserId = LoginHelper.getUserId();
// 只查询状态为1(待班主任审核)的申请
bo.setStatus("1");
// 调用mapper中的专用查询方法
Page<XskhDisciplineRevokeVo> result = baseMapper.selectClassTeacherVoPage(pageQuery.build(), bo, currentUserId);
return TableDataInfo.build(result);
}
/**
* 查询班主任已审核的违纪撤销申请列表(根据审核人查询历史记录)
*/
@Override
public TableDataInfo<XskhDisciplineRevokeVo> queryClassTeacherReviewedPageList(XskhDisciplineRevokeBo bo,
PageQuery pageQuery) {
// 获取当前登录用户ID(班主任ID)
Long currentUserId = LoginHelper.getUserId();
// 调用mapper中的专用查询方法,通过teacherApprovalBy字段查询历史记录
Page<XskhDisciplineRevokeVo> result = baseMapper.selectClassTeacherReviewedVoPage(pageQuery.build(), bo,
currentUserId);
return TableDataInfo.build(result);
}
/**
* 查询学工处已审核的撤销申请列表(学工处专用)
*/
@Override
public TableDataInfo<XskhDisciplineRevokeVo> queryStudentAffairsReviewedPageList(XskhDisciplineRevokeBo bo,
PageQuery pageQuery) {
// 如果没有指定状态,则查询所有已审核状态(3-审核通过,5-审核拒绝)
if (StringUtils.isBlank(bo.getStatus())) {
// 通过params传递状态列表
if (bo.getParams() == null) {
bo.setParams(new HashMap<>());
}
if (!bo.getParams().containsKey("statusList")) {
bo.getParams().put("statusList", "3,5");
}
}
// 调用mapper中的学工处已审核查询方法
Page<XskhDisciplineRevokeVo> result = baseMapper.selectStudentAffairsReviewedVoPage(pageQuery.build(), bo);
return TableDataInfo.build(result);
}
}
@@ -13,6 +13,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="revokeEvidence" column="revoke_evidence" />
<result property="applyTime" column="apply_time" />
<result property="status" column="status" />
<result property="teacherApprovalBy" column="teacher_approval_by" />
<result property="teacherApprovalTime" column="teacher_approval_time" />
<result property="teacherApprovalRemark" column="teacher_approval_remark" />
<result property="approvalBy" column="approval_by" />
<result property="approvalTime" column="approval_time" />
<result property="approvalRemark" column="approval_remark" />
@@ -26,17 +29,25 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap>
<sql id="selectXskhDisciplineRevokeVo">
select id, discipline_record_id, student_id, student_name, revoke_reason, revoke_evidence, apply_time, status, approval_by, approval_time, approval_remark, create_by, create_time, create_dept, update_by, update_time, deleted, tenant_id from xskh_discipline_revoke
select id, discipline_record_id, student_id, student_name, revoke_reason, revoke_evidence, apply_time, status,
teacher_approval_by, teacher_approval_time, teacher_approval_remark,
approval_by, approval_time, approval_remark,
create_by, create_time, create_dept, update_by, update_time, deleted, tenant_id
from xskh_discipline_revoke
</sql>
<select id="selectByDisciplineRecordId" parameterType="Long" resultType="XskhDisciplineRevokeVo">
select dr.id, dr.discipline_record_id, dr.student_id, dr.student_name, dr.revoke_reason,
dr.revoke_evidence, dr.apply_time, dr.status, dr.approval_by, dr.approval_time,
dr.approval_remark, dr.create_by, dr.create_time, dr.create_dept,
dr.revoke_evidence, dr.apply_time, dr.status,
dr.teacher_approval_by, dr.teacher_approval_time, dr.teacher_approval_remark,
dr.approval_by, dr.approval_time, dr.approval_remark,
dr.create_by, dr.create_time, dr.create_dept,
dr.update_by, dr.update_time, dr.deleted, dr.tenant_id,
u.nick_name as approval_by_name
tu.nick_name as teacher_approval_by_name,
au.nick_name as approval_by_name
from xskh_discipline_revoke dr
left join sys_user u on dr.approval_by = u.user_id and u.del_flag = '0' and u.tenant_id = '000000'
left join sys_user tu on dr.teacher_approval_by = tu.user_id and tu.del_flag = '0' and tu.tenant_id = '000000'
left join sys_user au on dr.approval_by = au.user_id and au.del_flag = '0' and au.tenant_id = '000000'
where dr.discipline_record_id = #{disciplineRecordId}
and dr.deleted = 0
limit 1
@@ -44,14 +55,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectClassTeacherVoPage" resultType="XskhDisciplineRevokeVo">
select dr.id, dr.discipline_record_id, dr.student_id, dr.student_name, dr.revoke_reason,
dr.revoke_evidence, dr.apply_time, dr.status, dr.approval_by, dr.approval_time,
dr.approval_remark, dr.create_by, dr.create_time, dr.create_dept,
dr.revoke_evidence, dr.apply_time, dr.status,
dr.teacher_approval_by, dr.teacher_approval_time, dr.teacher_approval_remark,
dr.approval_by, dr.approval_time, dr.approval_remark,
dr.create_by, dr.create_time, dr.create_dept,
dr.update_by, dr.update_time, dr.deleted, dr.tenant_id,
xdr.student_no, xdr.discipline_type_name, xdr.discipline_date,
u.nick_name as approval_by_name
tu.nick_name as teacher_approval_by_name,
au.nick_name as approval_by_name
from xskh_discipline_revoke dr
inner join xskh_discipline_record xdr on dr.discipline_record_id = xdr.id
left join sys_user u on dr.approval_by = u.user_id and u.del_flag = '0' and u.tenant_id = '000000'
left join sys_user tu on dr.teacher_approval_by = tu.user_id and tu.del_flag = '0' and tu.tenant_id = '000000'
left join sys_user au on dr.approval_by = au.user_id and au.del_flag = '0' and au.tenant_id = '000000'
where dr.deleted = 0
and dr.student_id in (
select sm.id
@@ -75,4 +90,93 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
order by dr.apply_time desc
</select>
<select id="selectStudentAffairsVoPage" resultType="XskhDisciplineRevokeVo">
select dr.id, dr.discipline_record_id, dr.student_id, dr.student_name, dr.revoke_reason,
dr.revoke_evidence, dr.apply_time, dr.status,
dr.teacher_approval_by, dr.teacher_approval_time, dr.teacher_approval_remark,
dr.approval_by, dr.approval_time, dr.approval_remark,
dr.create_by, dr.create_time, dr.create_dept,
dr.update_by, dr.update_time, dr.deleted, dr.tenant_id,
xdr.student_no, xdr.discipline_type_name, xdr.discipline_date,
tu.nick_name as teacher_approval_by_name,
au.nick_name as approval_by_name
from xskh_discipline_revoke dr
inner join xskh_discipline_record xdr on dr.discipline_record_id = xdr.id
left join sys_user tu on dr.teacher_approval_by = tu.user_id and tu.del_flag = '0' and tu.tenant_id = '000000'
left join sys_user au on dr.approval_by = au.user_id and au.del_flag = '0' and au.tenant_id = '000000'
where dr.deleted = 0
<if test="bo.studentNo != null and bo.studentNo != ''">
and xdr.student_no like concat('%', #{bo.studentNo}, '%')
</if>
<if test="bo.studentName != null and bo.studentName != ''">
and dr.student_name like concat('%', #{bo.studentName}, '%')
</if>
<if test="bo.status != null and bo.status != ''">
and dr.status = #{bo.status}
</if>
order by dr.apply_time desc
</select>
<select id="selectStudentAffairsReviewedVoPage" resultType="XskhDisciplineRevokeVo">
select dr.id, dr.discipline_record_id, dr.student_id, dr.student_name, dr.revoke_reason,
dr.revoke_evidence, dr.apply_time, dr.status,
dr.teacher_approval_by, dr.teacher_approval_time, dr.teacher_approval_remark,
dr.approval_by, dr.approval_time, dr.approval_remark,
dr.create_by, dr.create_time, dr.create_dept,
dr.update_by, dr.update_time, dr.deleted, dr.tenant_id,
xdr.student_no, xdr.discipline_type_name, xdr.discipline_date,
tu.nick_name as teacher_approval_by_name,
au.nick_name as approval_by_name
from xskh_discipline_revoke dr
inner join xskh_discipline_record xdr on dr.discipline_record_id = xdr.id
left join sys_user tu on dr.teacher_approval_by = tu.user_id and tu.del_flag = '0' and tu.tenant_id = '000000'
left join sys_user au on dr.approval_by = au.user_id and au.del_flag = '0' and au.tenant_id = '000000'
where dr.deleted = 0
<if test="bo.studentNo != null and bo.studentNo != ''">
and xdr.student_no like concat('%', #{bo.studentNo}, '%')
</if>
<if test="bo.studentName != null and bo.studentName != ''">
and dr.student_name like concat('%', #{bo.studentName}, '%')
</if>
<if test="bo.status != null and bo.status != ''">
and dr.status = #{bo.status}
</if>
<if test="bo.params.statusList != null and bo.params.statusList != ''">
and dr.status in
<foreach collection="bo.params.statusList.split(',')" item="status" open="(" close=")" separator=",">
#{status}
</foreach>
</if>
order by dr.approval_time desc, dr.apply_time desc
</select>
<select id="selectClassTeacherReviewedVoPage" resultType="XskhDisciplineRevokeVo">
select dr.id, dr.discipline_record_id, dr.student_id, dr.student_name, dr.revoke_reason,
dr.revoke_evidence, dr.apply_time, dr.status,
dr.teacher_approval_by, dr.teacher_approval_time, dr.teacher_approval_remark,
dr.approval_by, dr.approval_time, dr.approval_remark,
dr.create_by, dr.create_time, dr.create_dept,
dr.update_by, dr.update_time, dr.deleted, dr.tenant_id,
xdr.student_no, xdr.discipline_type_name, xdr.discipline_date,
tu.nick_name as teacher_approval_by_name,
au.nick_name as approval_by_name
from xskh_discipline_revoke dr
inner join xskh_discipline_record xdr on dr.discipline_record_id = xdr.id
left join sys_user tu on dr.teacher_approval_by = tu.user_id and tu.del_flag = '0' and tu.tenant_id = '000000'
left join sys_user au on dr.approval_by = au.user_id and au.del_flag = '0' and au.tenant_id = '000000'
where dr.deleted = 0
and dr.teacher_approval_by = #{classTeacherId}
and dr.teacher_approval_time is not null
<if test="bo.studentNo != null and bo.studentNo != ''">
and xdr.student_no like concat('%', #{bo.studentNo}, '%')
</if>
<if test="bo.studentName != null and bo.studentName != ''">
and dr.student_name like concat('%', #{bo.studentName}, '%')
</if>
<if test="bo.status != null and bo.status != ''">
and dr.status = #{bo.status}
</if>
order by dr.teacher_approval_time desc, dr.apply_time desc
</select>
</mapper>
@@ -112,10 +112,15 @@ CREATE TABLE `xskh_discipline_revoke` (
`revoke_reason` varchar(500) NOT NULL COMMENT '撤销申请原因',
`revoke_evidence` varchar(500) DEFAULT NULL COMMENT '撤销证明材料,附件的oss_id,多个用逗号分隔',
`apply_time` datetime NOT NULL COMMENT '申请时间',
`status` char(1) DEFAULT '1' COMMENT '状态(1-待审核 2-审核通过 3-审核拒绝)',
`approval_by` bigint(20) DEFAULT NULL COMMENT '审核人ID',
`approval_time` datetime DEFAULT NULL COMMENT '审核时间',
`approval_remark` varchar(500) DEFAULT NULL COMMENT '审核备注',
`status` char(1) DEFAULT '1' COMMENT '状态(1-待班主任审核 2-待学工处审核 3-审核通过 4-班主任审核拒绝 5-学工处审核拒绝)',
-- 班主任审核信息
`teacher_approval_by` bigint(20) DEFAULT NULL COMMENT '班主任审核人ID',
`teacher_approval_time` datetime DEFAULT NULL COMMENT '班主任审核时间',
`teacher_approval_remark` varchar(500) DEFAULT NULL COMMENT '班主任审核备注',
-- 学工处审核信息(保留原有字段名,语义调整为学工处审核)
`approval_by` bigint(20) DEFAULT NULL COMMENT '学工处审核人ID',
`approval_time` datetime DEFAULT NULL COMMENT '学工处审核时间',
`approval_remark` varchar(500) DEFAULT NULL COMMENT '学工处审核备注',
`create_by` bigint(20) DEFAULT NULL COMMENT '创建者',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`create_dept` bigint(20) DEFAULT NULL COMMENT '创建部门',
@@ -126,7 +131,9 @@ CREATE TABLE `xskh_discipline_revoke` (
PRIMARY KEY (`id`),
KEY `idx_discipline_record_id` (`discipline_record_id`),
KEY `idx_student_id` (`student_id`),
KEY `idx_status` (`status`)
KEY `idx_status` (`status`),
KEY `idx_teacher_approval_by` (`teacher_approval_by`),
KEY `idx_approval_by` (`approval_by`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='违纪处分撤销申请审批表';
-- 4. 奖励类型表
@@ -98,12 +98,50 @@ export const applyDisciplineRevoke = (data: DisciplineRevokeForm) => {
};
/**
* 审核撤销申请
* 查询班主任待审核的撤销申请列表
* @param query
* @returns {*}
*/
export const listClassTeacherDisciplineRevoke = (query?: DisciplineRevokeQuery): AxiosPromise<DisciplineRevokeVO[]> => {
return request({
url: '/disciplineRevoke/disciplineRevoke/classTeacherList',
method: 'get',
params: query
});
};
/**
* 班主任审核撤销申请
* @param data
*/
export const approveDisciplineRevoke = (data: DisciplineRevokeForm) => {
export const teacherApproveDisciplineRevoke = (data: DisciplineRevokeForm) => {
return request({
url: '/disciplineRevoke/disciplineRevoke/approve',
url: '/disciplineRevoke/disciplineRevoke/teacherApprove',
method: 'put',
data: data
});
};
/**
* 查询学工处待审核的撤销申请列表
* @param query
* @returns {*}
*/
export const listStudentAffairsDisciplineRevoke = (query?: DisciplineRevokeQuery): AxiosPromise<DisciplineRevokeVO[]> => {
return request({
url: '/disciplineRevoke/disciplineRevoke/studentAffairsList',
method: 'get',
params: query
});
};
/**
* 学工处审核撤销申请
* @param data
*/
export const studentAffairsApproveDisciplineRevoke = (data: DisciplineRevokeForm) => {
return request({
url: '/disciplineRevoke/disciplineRevoke/studentAffairsApprove',
method: 'put',
data: data
});
+78 -17
View File
@@ -37,27 +37,47 @@ export interface DisciplineRevokeVO {
applyTime: string;
/**
* 状态(1-待审核 2-审核通过 3-审核拒绝)
* 状态(1-待班主任审核 2-待学工处审核 3-审核通过 4-班主任审核拒绝 5-学工处审核拒绝)
*/
status: string;
/**
* 审核人ID
* 班主任审核人ID
*/
teacherApprovalBy: string | number;
/**
* 班主任审核人姓名
*/
teacherApprovalByName: string;
/**
* 班主任审核时间
*/
teacherApprovalTime: string;
/**
* 班主任审核备注
*/
teacherApprovalRemark: string;
/**
* 学工处审核人ID
*/
approvalBy: string | number;
/**
* 审核人姓名
* 学工处审核人姓名
*/
approvalByName: string;
/**
* 审核时间
* 学工处审核时间
*/
approvalTime: string;
/**
* 审核备注
* 学工处审核备注
*/
approvalRemark: string;
@@ -80,6 +100,22 @@ export interface DisciplineRevokeVO {
* 更新时间
*/
updateTime: string;
// 扩展字段(用于关联查询显示)
/**
* 学号
*/
studentNo?: string;
/**
* 违纪类型名称
*/
disciplineTypeName?: string;
/**
* 违纪日期
*/
disciplineDate?: string;
}
export interface DisciplineRevokeForm {
@@ -119,22 +155,37 @@ export interface DisciplineRevokeForm {
applyTime?: string;
/**
* 状态(1-待审核 2-审核通过 3-审核拒绝)
* 状态(1-待班主任审核 2-待学工处审核 3-审核通过 4-班主任审核拒绝 5-学工处审核拒绝)
*/
status?: string;
/**
* 审核人ID
* 班主任审核人ID
*/
teacherApprovalBy?: string | number;
/**
* 班主任审核时间
*/
teacherApprovalTime?: string;
/**
* 班主任审核备注
*/
teacherApprovalRemark?: string;
/**
* 学工处审核人ID
*/
approvalBy?: string | number;
/**
* 审核时间
* 学工处审核时间
*/
approvalTime?: string;
/**
* 审核备注
* 学工处审核备注
*/
approvalRemark?: string;
}
@@ -155,6 +206,11 @@ export interface DisciplineRevokeQuery extends PageQuery {
*/
studentName?: string;
/**
* 学号
*/
studentNo?: string;
/**
* 撤销申请原因
*/
@@ -166,25 +222,30 @@ export interface DisciplineRevokeQuery extends PageQuery {
applyTime?: string;
/**
* 状态(1-待审核 2-审核通过 3-审核拒绝)
* 状态(1-待班主任审核 2-待学工处审核 3-审核通过 4-班主任审核拒绝 5-学工处审核拒绝)
*/
status?: string;
/**
* 审核人ID
* 班主任审核人ID
*/
teacherApprovalBy?: string | number;
/**
* 班主任审核时间
*/
teacherApprovalTime?: string;
/**
* 学工处审核人ID
*/
approvalBy?: string | number;
/**
* 审核时间
* 学工处审核时间
*/
approvalTime?: string;
/**
* 审核备注
*/
approvalRemark?: string;
/**
* 其他参数
*/
@@ -33,56 +33,94 @@
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<span class="text-lg font-medium">违纪撤销申请审核列表</span>
<span class="text-lg font-medium">违纪撤销申请管理</span>
</el-col>
<right-toolbar :showSearch="showSearch" @update:showSearch="showSearch = $event" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" border :data="revokeApplicationList" class="full-width-table">
<el-table-column label="学号" align="center" prop="studentNo" min-width="120" />
<el-table-column label="学生姓名" align="center" prop="studentName" min-width="100" />
<el-table-column label="违纪类型" align="center" prop="disciplineTypeName" min-width="140" show-overflow-tooltip />
<el-table-column label="违纪日期" align="center" prop="disciplineDate" min-width="130" />
<el-table-column label="撤销原因" align="center" prop="revokeReason" min-width="200" show-overflow-tooltip />
<el-table-column label="申请时间" align="center" prop="applyTime" min-width="160" />
<el-table-column label="状态" align="center" prop="status" min-width="100">
<template #default="scope">
<dict-tag :options="student_revoke_status" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
<template #default="scope">
<el-tooltip content="查看" placement="top">
<el-button
link
type="primary"
icon="View"
@click="handleView(scope.row)"
v-hasPermi="['disciplineRevoke:classTeacher:query']"
></el-button>
</el-tooltip>
<el-tooltip content="审核通过" placement="top" v-if="scope.row.status === '1'">
<el-button
link
type="success"
icon="CircleCheck"
@click="handleApprove(scope.row, '2')"
v-hasPermi="['disciplineRevoke:classTeacher:approve']"
></el-button>
</el-tooltip>
<el-tooltip content="审核驳回" placement="top" v-if="scope.row.status === '1'">
<el-button
link
type="danger"
icon="CircleClose"
@click="handleApprove(scope.row, '3')"
v-hasPermi="['disciplineRevoke:classTeacher:approve']"
></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<!-- Tab标签页 -->
<el-tabs v-model="activeTab" @tab-change="handleTabChange" class="demo-tabs">
<!-- 待审核Tab -->
<el-tab-pane label="待审核申请" name="pending">
<el-table v-loading="loading" border :data="revokeApplicationList" class="full-width-table">
<el-table-column label="学号" align="center" prop="studentNo" min-width="120" />
<el-table-column label="学生姓名" align="center" prop="studentName" min-width="100" />
<el-table-column label="违纪类型" align="center" prop="disciplineTypeName" min-width="140" show-overflow-tooltip />
<el-table-column label="违纪日期" align="center" prop="disciplineDate" min-width="130" />
<el-table-column label="撤销原因" align="center" prop="revokeReason" min-width="200" show-overflow-tooltip />
<el-table-column label="申请时间" align="center" prop="applyTime" min-width="160" />
<el-table-column label="状态" align="center" prop="status" min-width="100">
<template #default="scope">
<dict-tag :options="student_revoke_status" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
<template #default="scope">
<el-tooltip content="查看" placement="top">
<el-button
link
type="primary"
icon="View"
@click="handleView(scope.row)"
v-hasPermi="['disciplineRevoke:classTeacher:query']"
></el-button>
</el-tooltip>
<el-tooltip content="审核通过" placement="top">
<el-button
link
type="success"
icon="CircleCheck"
@click="handleApprove(scope.row, '2')"
v-hasPermi="['disciplineRevoke:classTeacher:approve']"
></el-button>
</el-tooltip>
<el-tooltip content="审核驳回" placement="top">
<el-button
link
type="danger"
icon="CircleClose"
@click="handleApprove(scope.row, '4')"
v-hasPermi="['disciplineRevoke:classTeacher:approve']"
></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<!-- 已审核Tab -->
<el-tab-pane label="已审核记录" name="reviewed">
<el-table v-loading="loading" border :data="revokeApplicationList" class="full-width-table">
<el-table-column label="学号" align="center" prop="studentNo" min-width="120" />
<el-table-column label="学生姓名" align="center" prop="studentName" min-width="100" />
<el-table-column label="违纪类型" align="center" prop="disciplineTypeName" min-width="140" show-overflow-tooltip />
<el-table-column label="违纪日期" align="center" prop="disciplineDate" min-width="130" />
<el-table-column label="撤销原因" align="center" prop="revokeReason" min-width="200" show-overflow-tooltip />
<el-table-column label="申请时间" align="center" prop="applyTime" min-width="160" />
<el-table-column label="审核时间" align="center" prop="teacherApprovalTime" min-width="160" />
<el-table-column label="班主任审核备注" align="center" prop="teacherApprovalRemark" min-width="200" show-overflow-tooltip />
<el-table-column label="状态" align="center" prop="status" min-width="100">
<template #default="scope">
<dict-tag :options="student_revoke_status" :value="scope.row.status" />
</template>
</el-table-column>
<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
link
type="primary"
icon="View"
@click="handleView(scope.row)"
v-hasPermi="['disciplineRevoke:classTeacher:query']"
></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
<pagination v-show="total > 0" :total="total" :page="queryParams.pageNum" :limit="queryParams.pageSize" @pagination="getList" />
</el-card>
@@ -105,6 +143,32 @@
<el-form-item label="撤销申请原因">
<el-input v-model="approvalForm.revokeReason" type="textarea" :rows="3" disabled />
</el-form-item>
<!-- 撤销证明材料展示 -->
<el-form-item label="撤销证明材料" v-if="revokeAttachmentList && revokeAttachmentList.length > 0">
<div class="attachment-view-container">
<div class="attachment-view-grid">
<div v-for="file in revokeAttachmentList" :key="file.uid" class="upload-file-card">
<div class="upload-file-thumb">
<image-preview v-if="isImageFile(file) && file.url" :src="getFileOssId(file)" class="upload-thumb-image" :isOssId="true" />
<div v-else class="upload-file-placeholder">
<el-icon><Document /></el-icon>
<span class="file-ext">{{ getFileExt(file.name) }}</span>
</div>
</div>
<div class="upload-file-name" :title="file.name">
{{ getShortFileName(file.name) }}
</div>
<div class="upload-file-card-actions">
<el-button type="success" size="small" @click.stop="handleDownloadAttachment(file)" title="下载">
<el-icon><Download /></el-icon>
</el-button>
</div>
</div>
</div>
</div>
</el-form-item>
<el-form-item label="审核备注" prop="approvalRemark">
<el-input v-model="approvalForm.approvalRemark" type="textarea" placeholder="请输入审核备注" :rows="4" />
</el-form-item>
@@ -120,11 +184,15 @@
</template>
<script setup name="RevokeApplicationApproval" lang="ts">
import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue';
import { ref, reactive, toRefs, onMounted, getCurrentInstance, ComponentInternalInstance } from 'vue';
import { Document, Download } from '@element-plus/icons-vue';
import ElMessage from 'element-plus/es/components/message/index';
import { ElLoading } from 'element-plus/es/components/loading/index';
import ImagePreview from '@/components/ImagePreview/index.vue';
import request from '@/utils/request';
import RevokeApplicationView from '../xsDisciplineRecord/RevokeApplicationView.vue';
const { proxy } = getCurrentInstance();
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { student_revoke_status } = toRefs<any>(proxy?.useDict('student_revoke_status'));
const revokeApplicationList = ref<any[]>([]);
@@ -132,16 +200,21 @@ const loading = ref(true);
const showSearch = ref(true);
const total = ref(0);
const buttonLoading = ref(false);
const activeTab = ref('pending'); // 默认显示待审核Tab
const queryFormRef = ref();
const revokeApplicationViewRef = ref();
const approvalFormRef = ref();
// 撤销申请附件数据
const revokeAttachmentList = ref<any[]>([]);
interface QueryParams {
pageNum: number;
pageSize: number;
studentNo?: string;
studentName?: string;
status?: string;
params: Record<string, any>;
}
@@ -155,6 +228,7 @@ const data = reactive<{
pageSize: 10,
studentNo: undefined,
studentName: undefined,
status: '1', // 默认查询待审核状态
params: {}
}
});
@@ -186,9 +260,15 @@ const approvalRules = reactive({
const getList = async () => {
loading.value = true;
try {
// 后续需要调用班主任专用的API
// 根据当前Tab决定使用哪个API
let apiUrl = '/disciplineRevoke/disciplineRevoke/classTeacherList';
if (activeTab.value === 'reviewed') {
// 已审核Tab使用新的API,通过审核人查询历史记录
apiUrl = '/disciplineRevoke/disciplineRevoke/classTeacherReviewedList';
}
const res = await request({
url: '/disciplineRevoke/disciplineRevoke/classTeacherList',
url: apiUrl,
method: 'get',
params: queryParams.value
});
@@ -215,27 +295,209 @@ const resetQuery = () => {
handleQuery();
};
/** Tab切换操作 */
const handleTabChange = (tabName: string) => {
// 重置页码
queryParams.value.pageNum = 1;
// 根据Tab设置状态筛选条件
if (tabName === 'pending') {
// 待审核:状态为'1'
queryParams.value.status = '1';
} else if (tabName === 'reviewed') {
// 已审核:清除状态筛选,通过API切换查询已审核记录
queryParams.value.status = undefined;
}
// 重新查询数据
getList();
};
/** 查看按钮操作 */
const handleView = (row: any) => {
revokeApplicationViewRef.value?.openDialog(row.disciplineRecordId, '查看');
};
/** 审核按钮操作 */
const handleApprove = (row: any, status: string) => {
const handleApprove = async (row: any, status: string) => {
approvalForm.value = {
id: row.id,
disciplineRecordId: row.disciplineRecordId, // 添加违纪记录ID
studentName: row.studentName,
status: status,
statusText: status === '2' ? '审核通过' : '审核驳回',
statusText: status === '2' ? '班主任审核通过' : '班主任审核拒绝',
approvalTime: new Date().toLocaleString(),
revokeReason: row.revokeReason || '', // 添加撤销申请原因
approvalRemark: ''
};
approvalDialog.title = status === '2' ? '审核通过' : '审核驳回';
approvalDialog.title = status === '2' ? '班主任审核通过' : '班主任审核拒绝';
// 加载撤销申请附件数据
await loadRevokeAttachments(row.id);
approvalDialog.visible = true;
};
/** 加载撤销申请附件数据 */
const loadRevokeAttachments = async (revokeId: string | number) => {
try {
// 获取撤销申请详情
const response = await request({
url: `/disciplineRevoke/disciplineRevoke/${revokeId}`,
method: 'get'
});
if (response.code === 200 && response.data && response.data.revokeEvidence) {
await handleRevokeAttachmentData(response.data.revokeEvidence);
} else {
revokeAttachmentList.value = [];
}
} catch (error) {
console.error('加载撤销申请附件失败:', error);
revokeAttachmentList.value = [];
}
};
/** 处理撤销申请附件数据 */
const handleRevokeAttachmentData = async (revokeEvidence: string) => {
try {
if (!revokeEvidence || !revokeEvidence.toString().trim()) {
revokeAttachmentList.value = [];
return;
}
const ossIdsArray = revokeEvidence
.toString()
.split(',')
.map((id: string) => id.trim())
.filter((id: string) => id);
if (ossIdsArray.length === 0) {
revokeAttachmentList.value = [];
return;
}
const response = await request({
url: `/resource/oss/listByIds/${ossIdsArray.join(',')}`,
method: 'get'
});
if (response.code === 200 && response.data) {
const attachmentFiles = response.data.map((item: any, index: number) => ({
uid: `revoke_${index}_${Date.now()}`,
name: item.originalName || `撤销证明${index + 1}`,
url: item.url,
ossId: item.ossId,
status: 'success'
}));
revokeAttachmentList.value = attachmentFiles;
} else {
revokeAttachmentList.value = [];
}
} catch (error) {
console.error('处理撤销申请附件数据失败:', error);
revokeAttachmentList.value = [];
}
};
// 文件处理方法
const isImageFile = (file: any) => {
const imageTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/bmp', 'image/webp'];
return imageTypes.includes(file.raw?.type) || (file.url && /\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(file.name));
};
const getFileOssId = (file: any) => {
return file.ossId || '';
};
const getFileExt = (fileName: string) => {
const ext = fileName.split('.').pop()?.toUpperCase();
return ext || 'FILE';
};
const getShortFileName = (fileName: string) => {
if (!fileName) return '';
const lastDotIndex = fileName.lastIndexOf('.');
if (lastDotIndex === -1) {
return fileName.length > 12 ? fileName.substring(0, 12) + '...' : fileName;
}
const name = fileName.substring(0, lastDotIndex);
const ext = fileName.substring(lastDotIndex);
if (name.length <= 8) {
return fileName;
}
return name.substring(0, 8) + '...' + ext;
};
const handleDownloadAttachment = async (file: any) => {
let downloadUrl = '';
let fileName = file.name || 'attachment';
if (file.response && file.response.data && file.response.data.filePath) {
downloadUrl = file.response.data.filePath;
fileName = file.response.data.fileName || fileName;
} else if (file.ossId) {
downloadUrl = file.ossId;
} else if (file.raw) {
const link = document.createElement('a');
link.href = URL.createObjectURL(file.raw);
link.download = fileName;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(link.href);
return;
}
if (!downloadUrl) {
ElMessage.error('无法获取文件下载地址');
return;
}
try {
const loading = ElLoading.service({
text: '正在下载文件...',
target: document.body
});
const response = await request({
url: '/resource/oss/download/' + downloadUrl,
method: 'get',
responseType: 'blob',
timeout: 300000
});
if (!response) {
throw new Error('响应数据为空');
}
let blobData: Blob;
if (response instanceof Blob) {
blobData = response;
} else if (response.data instanceof Blob) {
blobData = response.data;
} else {
throw new Error('无效的响应数据格式');
}
const url = window.URL.createObjectURL(blobData);
const link = document.createElement('a');
link.href = url;
link.download = fileName;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
loading?.close();
} catch (error) {
console.error('下载文件失败:', error);
ElMessage.error('下载文件失败,请稍后重试');
}
};
/** 提交审核 */
const submitApproval = () => {
approvalFormRef.value?.validate(async (valid: boolean) => {
@@ -243,14 +505,14 @@ const submitApproval = () => {
buttonLoading.value = true;
try {
await request({
url: '/disciplineRevoke/disciplineRevoke/classTeacherApprove',
url: '/disciplineRevoke/disciplineRevoke/teacherApprove',
method: 'put',
data: {
id: approvalForm.value.id,
disciplineRecordId: approvalForm.value.disciplineRecordId, // 添加违纪记录ID
status: approvalForm.value.status,
revokeReason: approvalForm.value.revokeReason, // 添加撤销申请原因
approvalRemark: approvalForm.value.approvalRemark
teacherApprovalRemark: approvalForm.value.approvalRemark // 使用班主任审核备注字段
}
});
proxy?.$modal.msgSuccess('审核成功');
@@ -279,6 +541,8 @@ const cancelApproval = () => {
revokeReason: '', // 添加撤销申请原因字段
approvalRemark: ''
};
// 重置附件数据
revokeAttachmentList.value = [];
};
onMounted(() => {
@@ -312,4 +576,137 @@ onMounted(() => {
:deep(.el-table__body-wrapper) {
width: 100%;
}
/* 文件卡片样式 */
.upload-file-card {
position: relative;
width: 100%;
height: 100%;
border-radius: 6px;
overflow: hidden;
background: #fff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
transition: all 0.3s;
}
.upload-file-card:hover {
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}
.upload-file-thumb {
position: relative;
width: 100%;
height: 110px;
background: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.upload-thumb-image {
width: 100%;
height: 100%;
object-fit: cover;
}
.upload-file-placeholder {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #909399;
font-size: 14px;
}
.upload-file-placeholder .el-icon {
font-size: 28px;
margin-bottom: 4px;
}
.file-ext {
font-size: 12px;
text-transform: uppercase;
text-align: center;
}
.upload-file-name {
padding: 6px 8px;
font-size: 11px;
color: #303133;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
background: #fafafa;
border-top: 1px solid #f0f0f0;
line-height: 1.2;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
word-break: break-all;
max-width: 100%;
}
.upload-file-card-actions {
display: flex;
justify-content: center;
align-items: center;
padding: 6px 8px;
background: #fafafa;
border-top: 1px solid #f0f0f0;
transition: all 0.3s;
height: 38px;
}
.upload-file-card-actions .el-button {
padding: 4px 8px;
border: 1px solid #e0e0e0;
background: #fff;
font-size: 12px;
border-radius: 3px;
transition: all 0.3s;
}
.upload-file-card-actions .el-button:hover {
background: #f5f5f5;
border-color: #409eff;
}
/* 查看模式下的附件网格展示 */
.attachment-view-container {
width: 100%;
max-height: 300px;
min-height: 150px;
overflow-y: auto;
padding-right: 8px;
border: 1px solid #e4e7ed;
border-radius: 6px;
background: #fafafa;
}
.attachment-view-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 9px;
margin: 12px;
padding-bottom: 16px;
}
/* Tab标签页样式 */
.demo-tabs {
margin-bottom: 20px;
}
.demo-tabs .el-tabs__header {
margin-bottom: 20px;
}
/* Tab内容区域样式 */
.el-tab-pane {
margin-top: 10px;
}
</style>
@@ -0,0 +1,790 @@
<template>
<div class="revoke-application-approval">
<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">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="学号" prop="studentNo">
<el-input v-model="queryParams.studentNo" placeholder="请输入学号" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="学生姓名" prop="studentName">
<el-input v-model="queryParams.studentName" placeholder="请输入学生姓名" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
<el-col :span="8" v-if="activeTab === 'reviewed'">
<el-form-item label="审核结果" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择审核结果" clearable>
<el-option label="审核通过" value="3" />
<el-option label="审核拒绝" value="5" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8" v-else>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
<el-option v-for="dict in student_revoke_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</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">
<span class="text-lg font-medium">学工处违纪撤销申请审核管理</span>
</el-col>
<right-toolbar :showSearch="showSearch" @update:showSearch="showSearch = $event" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-tabs v-model="activeTab" @tab-change="handleTabChange" class="tab-container">
<!-- 待审核申请 Tab -->
<el-tab-pane label="待审核申请" name="pending">
<el-table v-loading="loading" border :data="revokeApplicationList" class="full-width-table">
<el-table-column label="学号" align="center" prop="studentNo" min-width="120" />
<el-table-column label="学生姓名" align="center" prop="studentName" min-width="100" />
<el-table-column label="违纪类型" align="center" prop="disciplineTypeName" min-width="140" show-overflow-tooltip />
<el-table-column label="违纪日期" align="center" prop="disciplineDate" min-width="130" />
<el-table-column label="撤销原因" align="center" prop="revokeReason" min-width="200" show-overflow-tooltip />
<el-table-column label="申请时间" align="center" prop="applyTime" min-width="160" />
<el-table-column label="班主任审核" align="center" min-width="120">
<template #default="scope">
<div v-if="scope.row.teacherApprovalTime">
<div>{{ scope.row.teacherApprovalByName }}</div>
<div class="text-xs text-gray-500">{{ scope.row.teacherApprovalTime }}</div>
</div>
<span v-else class="text-gray-400">-</span>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="status" min-width="100">
<template #default="scope">
<dict-tag :options="student_revoke_status" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
<template #default="scope">
<el-tooltip content="查看" placement="top">
<el-button
link
type="primary"
icon="View"
@click="handleView(scope.row)"
v-hasPermi="['disciplineRevoke:studentAffairs:query']"
></el-button>
</el-tooltip>
<el-tooltip content="审核通过" placement="top" v-if="scope.row.status === '2'">
<el-button
link
type="success"
icon="CircleCheck"
@click="handleApprove(scope.row, '3')"
v-hasPermi="['disciplineRevoke:studentAffairs:approve']"
></el-button>
</el-tooltip>
<el-tooltip content="审核驳回" placement="top" v-if="scope.row.status === '2'">
<el-button
link
type="danger"
icon="CircleClose"
@click="handleApprove(scope.row, '5')"
v-hasPermi="['disciplineRevoke:studentAffairs:approve']"
></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" :page="queryParams.pageNum" :limit="queryParams.pageSize" @pagination="getList" />
</el-tab-pane>
<!-- 已审核记录 Tab -->
<el-tab-pane label="已审核记录" name="reviewed">
<el-table v-loading="loading" border :data="reviewedApplicationList" class="full-width-table">
<el-table-column label="学号" align="center" prop="studentNo" min-width="120" />
<el-table-column label="学生姓名" align="center" prop="studentName" min-width="100" />
<el-table-column label="违纪类型" align="center" prop="disciplineTypeName" min-width="140" show-overflow-tooltip />
<el-table-column label="违纪日期" align="center" prop="disciplineDate" min-width="130" />
<el-table-column label="撤销原因" align="center" prop="revokeReason" min-width="200" show-overflow-tooltip />
<el-table-column label="申请时间" align="center" prop="applyTime" min-width="160" />
<el-table-column label="班主任审核" align="center" min-width="120">
<template #default="scope">
<div v-if="scope.row.teacherApprovalTime">
<div>{{ scope.row.teacherApprovalByName }}</div>
<div class="text-xs text-gray-500">{{ scope.row.teacherApprovalTime }}</div>
</div>
<span v-else class="text-gray-400">-</span>
</template>
</el-table-column>
<el-table-column label="学工处审核" align="center" min-width="150">
<template #default="scope">
<div v-if="scope.row.approvalTime">
<div>{{ scope.row.approvalByName || '学工处' }}</div>
<div class="text-xs text-gray-500">{{ scope.row.approvalTime }}</div>
</div>
<span v-else class="text-gray-400">-</span>
</template>
</el-table-column>
<el-table-column label="审核结果" align="center" prop="status" min-width="100">
<template #default="scope">
<el-tag :type="scope.row.status === '3' ? 'success' : 'danger'">
{{ scope.row.status === '3' ? '审核通过' : '审核拒绝' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="审核备注" align="center" prop="approvalRemark" min-width="200" show-overflow-tooltip />
<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
link
type="primary"
icon="View"
@click="handleView(scope.row)"
v-hasPermi="['disciplineRevoke:studentAffairs:query']"
></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination
v-show="reviewedTotal > 0"
:total="reviewedTotal"
:page="queryParams.pageNum"
:limit="queryParams.pageSize"
@pagination="getList"
/>
</el-tab-pane>
</el-tabs>
</el-card>
<!-- 查看撤销申请对话框 -->
<RevokeApplicationView ref="revokeApplicationViewRef" />
<!-- 审核对话框 -->
<el-dialog :title="approvalDialog.title" v-model="approvalDialog.visible" width="600px" append-to-body destroy-on-close>
<el-form ref="approvalFormRef" :model="approvalForm" :rules="approvalRules" label-width="120px">
<el-form-item label="学生姓名">
<el-input v-model="approvalForm.studentName" disabled />
</el-form-item>
<el-form-item label="审核结果">
<el-input v-model="approvalForm.statusText" disabled />
</el-form-item>
<el-form-item label="审核时间">
<el-input v-model="approvalForm.approvalTime" disabled />
</el-form-item>
<el-form-item label="撤销申请原因">
<el-input v-model="approvalForm.revokeReason" type="textarea" :rows="3" disabled />
</el-form-item>
<!-- 撤销证明材料展示(只读) -->
<el-form-item label="撤销证明材料" v-if="revokeAttachmentList && revokeAttachmentList.length > 0">
<div class="attachment-view-container">
<div class="attachment-view-grid">
<div v-for="file in revokeAttachmentList" :key="file.uid" class="upload-file-card">
<div class="upload-file-thumb">
<image-preview v-if="isImageFile(file) && file.url" :src="getFileOssId(file)" class="upload-thumb-image" :isOssId="true" />
<div v-else class="upload-file-placeholder">
<el-icon><Document /></el-icon>
<span class="file-ext">{{ getFileExt(file.name) }}</span>
</div>
</div>
<div class="upload-file-name" :title="file.name">
{{ getShortFileName(file.name) }}
</div>
<div class="upload-file-card-actions">
<el-button type="success" size="small" @click.stop="handleDownloadAttachment(file)" title="下载">
<el-icon><Download /></el-icon>
</el-button>
</div>
</div>
</div>
</div>
</el-form-item>
<el-form-item label="班主任审核意见" v-if="approvalForm.teacherApprovalRemark">
<el-input v-model="approvalForm.teacherApprovalRemark" type="textarea" :rows="2" disabled />
</el-form-item>
<el-form-item label="学工处审核备注" prop="approvalRemark">
<el-input v-model="approvalForm.approvalRemark" type="textarea" placeholder="请输入学工处审核备注" :rows="4" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitApproval">确 定</el-button>
<el-button @click="cancelApproval">取 消</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="StudentAffairsRevokeApproval" lang="ts">
import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue';
import { Document, Download } from '@element-plus/icons-vue';
import { ElMessage, ElLoading } from 'element-plus';
import ImagePreview from '@/components/ImagePreview/index.vue';
import request from '@/utils/request';
import RevokeApplicationView from '../xsDisciplineRecord/RevokeApplicationView.vue';
const { proxy } = getCurrentInstance();
const { student_revoke_status } = toRefs<any>(proxy?.useDict('student_revoke_status'));
const revokeApplicationList = ref<any[]>([]);
const reviewedApplicationList = ref<any[]>([]);
const loading = ref(true);
const showSearch = ref(true);
const total = ref(0);
const reviewedTotal = ref(0);
const buttonLoading = ref(false);
const activeTab = ref('pending');
// 撤销申请附件数据
const revokeAttachmentList = ref<any[]>([]);
const queryFormRef = ref();
const revokeApplicationViewRef = ref();
const approvalFormRef = ref();
interface QueryParams {
pageNum: number;
pageSize: number;
studentNo?: string;
studentName?: string;
status?: string;
params: Record<string, any>;
}
const data = reactive<{
form: Record<string, any>;
queryParams: QueryParams;
}>({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
studentNo: undefined,
studentName: undefined,
status: undefined,
params: {}
}
});
const { queryParams } = toRefs(data);
// 审核对话框
const approvalDialog = reactive({
visible: false,
title: ''
});
const approvalForm = ref({
id: undefined,
disciplineRecordId: undefined,
studentName: '',
status: '',
statusText: '',
approvalTime: '',
revokeReason: '',
teacherApprovalRemark: '',
approvalRemark: ''
});
const approvalRules = reactive({
approvalRemark: [{ required: true, message: '审核备注不能为空', trigger: 'blur' }]
});
/** 查询学工处待审核的撤销申请列表 */
const getList = async () => {
if (activeTab.value === 'pending') {
await getPendingList();
} else {
await getReviewedList();
}
};
/** 获取待审核申请列表 */
const getPendingList = async () => {
loading.value = true;
try {
// 待审核状态,只查询班主任已审核通过的记录(状态为2)
const params = { ...queryParams.value };
if (!params.status) {
params.status = '2'; // 默认查询待学工处审核的记录
}
const res = await request({
url: '/disciplineRevoke/disciplineRevoke/studentAffairsList',
method: 'get',
params: params
});
revokeApplicationList.value = res.rows || [];
total.value = res.total || 0;
} catch (error) {
console.error('获取学工处待审核撤销申请列表失败:', error);
revokeApplicationList.value = [];
total.value = 0;
} finally {
loading.value = false;
}
};
/** 获取已审核记录列表 */
const getReviewedList = async () => {
loading.value = true;
try {
// 已审核状态,查询状态为3(通过)或5(拒绝)的记录
const params = { ...queryParams.value };
if (!params.status) {
// 如果没有指定状态,查询所有已审核的记录
params.params.statusList = '3,5';
}
const res = await request({
url: '/disciplineRevoke/disciplineRevoke/studentAffairsReviewedList',
method: 'get',
params: params
});
reviewedApplicationList.value = res.rows || [];
reviewedTotal.value = res.total || 0;
} catch (error) {
console.error('获取学工处已审核撤销申请列表失败:', error);
reviewedApplicationList.value = [];
reviewedTotal.value = 0;
} finally {
loading.value = false;
}
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** Tab切换处理 */
const handleTabChange = (tabName: string) => {
activeTab.value = tabName;
// 重置查询参数
queryParams.value.pageNum = 1;
queryParams.value.status = undefined;
// 重新加载数据
getList();
};
/** 查看按钮操作 */
const handleView = (row: any) => {
revokeApplicationViewRef.value?.openDialog(row.disciplineRecordId, '查看');
};
/** 审核按钮操作 */
const handleApprove = async (row: any, status: string) => {
approvalForm.value = {
id: row.id,
disciplineRecordId: row.disciplineRecordId,
studentName: row.studentName,
status: status,
statusText: status === '3' ? '学工处审核通过' : '学工处审核拒绝',
approvalTime: new Date().toLocaleString(),
revokeReason: row.revokeReason || '',
teacherApprovalRemark: row.teacherApprovalRemark || '',
approvalRemark: ''
};
// 加载撤销申请的证明材料
if (row.revokeEvidence) {
await handleRevokeAttachmentData(row.revokeEvidence);
} else {
revokeAttachmentList.value = [];
}
approvalDialog.title = status === '3' ? '学工处审核通过' : '学工处审核拒绝';
approvalDialog.visible = true;
};
/** 提交审核 */
const submitApproval = () => {
approvalFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
try {
await request({
url: '/disciplineRevoke/disciplineRevoke/studentAffairsApprove',
method: 'put',
data: {
id: approvalForm.value.id,
disciplineRecordId: approvalForm.value.disciplineRecordId,
status: approvalForm.value.status,
revokeReason: approvalForm.value.revokeReason,
approvalRemark: approvalForm.value.approvalRemark
}
});
proxy?.$modal.msgSuccess('审核成功');
approvalDialog.visible = false;
getList();
} catch (error) {
console.error('审核失败:', error);
proxy?.$modal.msgError('审核失败');
} finally {
buttonLoading.value = false;
}
}
});
};
/** 取消审核 */
const cancelApproval = () => {
approvalDialog.visible = false;
approvalForm.value = {
id: undefined,
disciplineRecordId: undefined,
studentName: '',
status: '',
statusText: '',
approvalTime: '',
revokeReason: '',
teacherApprovalRemark: '',
approvalRemark: ''
};
// 重置附件数据
revokeAttachmentList.value = [];
};
// 文件处理方法
const isImageFile = (file: any) => {
const imageTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/bmp', 'image/webp'];
return imageTypes.includes(file.raw?.type) || (file.url && /\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(file.name));
};
const getFileOssId = (file: any) => {
return file.ossId || '';
};
const getFileExt = (fileName: string) => {
const ext = fileName.split('.').pop()?.toUpperCase();
return ext || 'FILE';
};
const getShortFileName = (fileName: string) => {
if (!fileName) return '';
const lastDotIndex = fileName.lastIndexOf('.');
if (lastDotIndex === -1) {
return fileName.length > 12 ? fileName.substring(0, 12) + '...' : fileName;
}
const name = fileName.substring(0, lastDotIndex);
const ext = fileName.substring(lastDotIndex);
if (name.length <= 8) {
return fileName;
}
return name.substring(0, 8) + '...' + ext;
};
const handleDownloadAttachment = async (file: any) => {
let downloadUrl = '';
let fileName = file.name || 'attachment';
if (file.response && file.response.data && file.response.data.filePath) {
downloadUrl = file.response.data.filePath;
fileName = file.response.data.fileName || fileName;
} else if (file.ossId) {
downloadUrl = file.ossId;
} else if (file.raw) {
const link = document.createElement('a');
link.href = URL.createObjectURL(file.raw);
link.download = fileName;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(link.href);
return;
}
if (!downloadUrl) {
ElMessage.error('无法获取文件下载地址');
return;
}
try {
const loading = ElLoading.service({
text: '正在下载文件...',
target: document.body
});
const response = await request({
url: '/resource/oss/download/' + downloadUrl,
method: 'get',
responseType: 'blob',
timeout: 300000
});
if (!response) {
throw new Error('响应数据为空');
}
let blobData: Blob;
if (response instanceof Blob) {
blobData = response;
} else if (response.data instanceof Blob) {
blobData = response.data;
} else {
throw new Error('无效的响应数据格式');
}
const url = window.URL.createObjectURL(blobData);
const link = document.createElement('a');
link.href = url;
link.download = fileName;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
loading?.close();
} catch (error) {
console.error('下载文件失败:', error);
ElMessage.error('下载文件失败,请稍后重试');
}
};
const handleRevokeAttachmentData = async (revokeEvidence: string) => {
try {
if (!revokeEvidence || !revokeEvidence.toString().trim()) {
revokeAttachmentList.value = [];
return;
}
const ossIdsArray = revokeEvidence
.toString()
.split(',')
.map((id: string) => id.trim())
.filter((id: string) => id);
if (ossIdsArray.length === 0) {
revokeAttachmentList.value = [];
return;
}
const response = await request({
url: `/resource/oss/listByIds/${ossIdsArray.join(',')}`,
method: 'get'
});
if (response.code === 200 && response.data) {
const attachmentFiles = response.data.map((item: any, index: number) => ({
uid: `revoke_${index}_${Date.now()}`,
name: item.originalName || `撤销证明${index + 1}`,
url: item.url,
ossId: item.ossId,
status: 'success'
}));
revokeAttachmentList.value = attachmentFiles;
} else {
revokeAttachmentList.value = [];
}
} catch (error) {
console.error('处理撤销申请附件数据失败:', error);
revokeAttachmentList.value = [];
}
};
onMounted(() => {
getList();
});
</script>
<style scoped>
/* 搜索按钮容器样式 */
.search-btn-container {
display: flex;
justify-content: flex-end;
margin-top: 10px;
}
.search-btn-container .el-form-item {
margin-bottom: 0 !important;
}
/* 表格全宽样式 */
.full-width-table {
width: 100%;
}
/* 确保表格容器充满宽度 */
:deep(.el-table) {
width: 100%;
}
/* 表格内容区域充满宽度 */
:deep(.el-table__body-wrapper) {
width: 100%;
}
/* 文件卡片样式 */
.upload-file-card {
position: relative;
width: 100%;
height: 100%;
border-radius: 6px;
overflow: hidden;
background: #fff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
transition: all 0.3s;
}
.upload-file-card:hover {
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}
.upload-file-thumb {
position: relative;
width: 100%;
height: 110px;
background: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.upload-thumb-image {
width: 100%;
height: 100%;
object-fit: cover;
}
.upload-file-placeholder {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #909399;
font-size: 14px;
}
.upload-file-placeholder .el-icon {
font-size: 28px;
margin-bottom: 4px;
}
.file-ext {
font-size: 12px;
text-transform: uppercase;
text-align: center;
}
.upload-file-name {
padding: 6px 8px;
font-size: 11px;
color: #303133;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
background: #fafafa;
border-top: 1px solid #f0f0f0;
line-height: 1.2;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
word-break: break-all;
max-width: 100%;
}
.upload-file-card-actions {
display: flex;
justify-content: center;
align-items: center;
padding: 6px 8px;
background: #fafafa;
border-top: 1px solid #f0f0f0;
transition: all 0.3s;
height: 38px;
}
.upload-file-card-actions .el-button {
padding: 4px 8px;
border: 1px solid #e0e0e0;
background: #fff;
font-size: 12px;
border-radius: 3px;
transition: all 0.3s;
}
.upload-file-card-actions .el-button:hover {
background: #f5f5f5;
border-color: #409eff;
}
/* 查看模式下的附件网格展示 */
.attachment-view-container {
width: 100%;
max-height: 300px;
min-height: 150px;
overflow-y: auto;
padding-right: 8px;
border: 1px solid #e4e7ed;
border-radius: 6px;
background: #fafafa;
}
.attachment-view-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 9px;
margin: 12px;
padding-bottom: 16px;
}
/* Tab 容器样式 */
.tab-container {
margin-top: 16px;
}
.tab-container :deep(.el-tabs__header) {
margin-bottom: 20px;
}
.tab-container :deep(.el-tabs__nav-wrap) {
padding-left: 0;
}
.tab-container :deep(.el-tabs__item) {
font-size: 14px;
font-weight: 500;
padding: 0 20px;
}
.tab-container :deep(.el-tabs__item.is-active) {
/* color: #409eff; */
}
.tab-container :deep(.el-tabs__content) {
padding-top: 0;
}
</style>
@@ -111,14 +111,9 @@
</el-form-item>
</el-col>
<!-- 右列:审批信息 -->
<!-- 右列:预留空间 -->
<el-col :span="12">
<el-form-item label="审核时间" v-if="revokeData?.approvalTime">
<div class="form-field-value">{{ revokeData.approvalTime }}</div>
</el-form-item>
<el-form-item label="审核人" v-if="revokeData?.approvalByName">
<div class="form-field-value">{{ revokeData.approvalByName }}</div>
</el-form-item>
<!-- 占位 -->
</el-col>
</el-row>
@@ -130,14 +125,6 @@
</el-col>
</el-row>
<el-row v-if="revokeData?.approvalRemark">
<el-col :span="24">
<el-form-item label="审核备注">
<div class="form-field-value textarea-value">{{ revokeData.approvalRemark }}</div>
</el-form-item>
</el-col>
</el-row>
<!-- 撤销证明材料展示(只读) -->
<el-row v-if="revokeAttachmentList && revokeAttachmentList.length > 0">
<el-col :span="24">
@@ -166,6 +153,57 @@
</el-form-item>
</el-col>
</el-row>
<!-- 班主任审核信息 -->
<div
v-if="revokeData?.teacherApprovalTime || (revokeData?.status && ['2', '3', '4', '5'].includes(revokeData.status))"
class="approval-section"
>
<h4 class="section-subtitle">班主任审核</h4>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="班主任审核时间" v-if="revokeData?.teacherApprovalTime">
<div class="form-field-value">{{ revokeData.teacherApprovalTime }}</div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="班主任审核人" v-if="revokeData?.teacherApprovalByName">
<div class="form-field-value">{{ revokeData.teacherApprovalByName }}</div>
</el-form-item>
</el-col>
</el-row>
<el-row v-if="revokeData?.teacherApprovalRemark">
<el-col :span="24">
<el-form-item label="班主任审核备注">
<div class="form-field-value textarea-value">{{ revokeData.teacherApprovalRemark }}</div>
</el-form-item>
</el-col>
</el-row>
</div>
<!-- 学工处审核信息 -->
<div v-if="revokeData?.approvalTime || (revokeData?.status && ['3', '5'].includes(revokeData.status))" class="approval-section">
<h4 class="section-subtitle">学工处审核</h4>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="学工处审核时间" v-if="revokeData?.approvalTime">
<div class="form-field-value">{{ revokeData.approvalTime }}</div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="学工处审核人" v-if="revokeData?.approvalByName">
<div class="form-field-value">{{ revokeData.approvalByName }}</div>
</el-form-item>
</el-col>
</el-row>
<el-row v-if="revokeData?.approvalRemark">
<el-col :span="24">
<el-form-item label="学工处审核备注">
<div class="form-field-value textarea-value">{{ revokeData.approvalRemark }}</div>
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
</div>
@@ -446,6 +484,21 @@ defineExpose({
border-bottom: 1px solid #ebeef5;
}
.section-subtitle {
font-size: 14px;
font-weight: 600;
color: #606266;
margin-bottom: 10px;
padding-bottom: 5px;
border-bottom: 1px dashed #ebeef5;
}
.approval-section {
margin-top: 20px;
padding-top: 15px;
border-top: 1px dashed #ebeef5;
}
.discipline-record-section {
margin-bottom: 20px;
}