提交请假销假代码

This commit is contained in:
zlwu committed 2025-08-06 01:32:11 +08:00
1 parent 4e8b6d77b6
commit 86f65df783
22 files changed
+4583 -191

No files matched your search

@@ -0,0 +1,128 @@
package org.dromara.workflow.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.workflow.domain.vo.XgStudentCancelLeaveVo;
import org.dromara.workflow.domain.bo.XgStudentCancelLeaveBo;
import org.dromara.workflow.service.IXgStudentCancelLeaveService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
* 学生销假
*
* @author zlwu
* @date 2025-08-05
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/studentCancelLeave/studentCancelLeave")
public class XgStudentCancelLeaveController extends BaseController {
private final IXgStudentCancelLeaveService xgStudentCancelLeaveService;
/**
* 查询学生销假列表
*/
@SaCheckPermission("studentCancelLeave:studentCancelLeave:list")
@GetMapping("/list")
public TableDataInfo<XgStudentCancelLeaveVo> list(XgStudentCancelLeaveBo bo, PageQuery pageQuery) {
return xgStudentCancelLeaveService.queryPageList(bo, pageQuery);
}
/**
* 导出学生销假列表
*/
@SaCheckPermission("studentCancelLeave:studentCancelLeave:export")
@Log(title = "学生销假", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(XgStudentCancelLeaveBo bo, HttpServletResponse response) {
List<XgStudentCancelLeaveVo> list = xgStudentCancelLeaveService.queryList(bo);
ExcelUtil.exportExcel(list, "学生销假", XgStudentCancelLeaveVo.class, response);
}
/**
* 获取学生销假详细信息
*
* @param id 主键
*/
@SaCheckPermission("studentCancelLeave:studentCancelLeave:query")
@GetMapping("/{id}")
public R<XgStudentCancelLeaveVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
return R.ok(xgStudentCancelLeaveService.queryById(id));
}
/**
* 新增学生销假
*/
@SaCheckPermission("studentCancelLeave:studentCancelLeave:add")
@Log(title = "学生销假", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<XgStudentCancelLeaveVo> add(@Validated(AddGroup.class) @RequestBody XgStudentCancelLeaveBo bo) {
XgStudentCancelLeaveVo result = xgStudentCancelLeaveService.insertByBo(bo);
return R.ok(result);
}
/**
* 修改学生销假
*/
@SaCheckPermission("studentCancelLeave:studentCancelLeave:edit")
@Log(title = "学生销假", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody XgStudentCancelLeaveBo bo) {
return toAjax(xgStudentCancelLeaveService.updateByBo(bo));
}
/**
* 删除学生销假
*
* @param ids 主键串
*/
@SaCheckPermission("studentCancelLeave:studentCancelLeave:remove")
@Log(title = "学生销假", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
return toAjax(xgStudentCancelLeaveService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 根据请假ID获取销假ID
*
* @param leaveId 请假ID
*/
@SaCheckPermission("studentCancelLeave:studentCancelLeave:query")
@GetMapping("/getCancelLeaveId/{leaveId}")
public R<Long> getCancelLeaveIdByLeaveId(@NotNull(message = "请假ID不能为空") @PathVariable Long leaveId) {
Long cancelLeaveId = xgStudentCancelLeaveService.getCancelLeaveIdByLeaveId(leaveId);
return R.ok(cancelLeaveId);
}
/**
* 根据销假ID获取请假ID
*
* @param cancelLeaveId 销假ID
*/
@SaCheckPermission("studentCancelLeave:studentCancelLeave:query")
@GetMapping("/getLeaveId/{cancelLeaveId}")
public R<Long> getLeaveIdByCancelLeaveId(@NotNull(message = "销假ID不能为空") @PathVariable Long cancelLeaveId) {
Long leaveId = xgStudentCancelLeaveService.getLeaveIdByCancelLeaveId(cancelLeaveId);
return R.ok(leaveId);
}
}
@@ -0,0 +1,200 @@
package org.dromara.workflow.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
/**
* 学生销假对象 xg_student_cancel_leave
*
* @author zlwu
* @date 2025-08-05
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("xg_student_cancel_leave")
public class XgStudentCancelLeave extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID(雪花ID)
*/
@TableId(value = "id")
private Long id;
/**
* 删除标志(0代表存在 1代表删除)
*/
@TableLogic(value = "0", delval = "1")
private Long deleted;
/**
* 学生ID
*/
private Long studentId;
/**
* 学生姓名
*/
private String studentName;
/**
* 学号
*/
private String studentNo;
/**
* 班级ID
*/
private Long classId;
/**
* 班级名称
*/
private String className;
/**
* 专业ID
*/
private Long majorId;
/**
* 专业名称
*/
private String majorName;
/**
* 学院ID
*/
private Long collegeId;
/**
* 学院名称
*/
private String collegeName;
/**
* 请假类型编码
*/
private String leaveTypeCode;
/**
* 请假类型名称
*/
private String leaveTypeName;
/**
* 开始时间(年月日时分秒)
*/
private Date startTime;
/**
* 结束时间(年月日时分秒)
*/
private Date endTime;
/**
* 请假时长(天)
*/
private Double leaveDuration;
/**
* 是否离校:0-否,1-是
*/
private String isLeaveSchool;
/**
* 是否需要销假:0-否,1-是
*/
private String needCancel;
/**
* 紧急联系人
*/
private String emergencyContact;
/**
* 紧急联系电话
*/
private String emergencyPhone;
/**
* 请假原因
*/
private String leaveReason;
/**
* 请假时地理位置
*/
private String leaveLocation;
/**
* 附件OSS文件ID(逗号分隔)
*/
private String attachmentOssIds;
/**
* 审批状态:"cancel", "已撤销" "draft", "草稿" "waiting", "待审核" "finish", "已完成"
* "invalid", "已作废" "back", "已退回" "termination", "已终止"
*/
private String approvalStatus;
/**
* 审批意见
*/
private String approvalOpinion;
/**
* 审批时间
*/
private Date approvalTime;
/**
* 审批人ID
*/
private Long approvalBy;
/**
* 审批人姓名
*/
private String approvalByName;
/**
* 销假状态:0-未销假,1-已销假,2-逾期未销假 3 - 无需销假 "cancel", "已撤销" "draft", "草稿" "waiting",
* "待审核" "finish", "已完成" "invalid", "已作废" "back", "已退回" "termination", "已终止"
*/
private String cancelStatus;
/**
* 销假时间
*/
private Date cancelTime;
/**
* 销假地理位置
*/
private String cancelLocation;
/**
* 销假照片OSS文件ID(逗号分隔)
*/
private String cancelPhotoOssIds;
/**
* 销假备注
*/
private String cancelRemark;
/**
* 学生请假表id
*/
private Long leaveId;
}
@@ -0,0 +1,212 @@
package org.dromara.workflow.domain.bo;
import org.dromara.workflow.domain.XgStudentCancelLeave;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* 学生销假业务对象 xg_student_cancel_leave
*
* @author zlwu
* @date 2025-08-05
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = XgStudentCancelLeave.class, reverseConvertGenerate = false)
public class XgStudentCancelLeaveBo extends BaseEntity {
/**
* 主键ID(雪花ID)
*/
@NotNull(message = "主键ID(雪花ID)不能为空", groups = { EditGroup.class })
private Long id;
/**
* 删除标志(0代表存在 1代表删除)
*/
private Long deleted;
/**
* 学生ID
*/
@NotNull(message = "学生ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long studentId;
/**
* 学生姓名
*/
@NotBlank(message = "学生姓名不能为空", groups = { AddGroup.class, EditGroup.class })
private String studentName;
/**
* 学号
*/
@NotBlank(message = "学号不能为空", groups = { AddGroup.class, EditGroup.class })
private String studentNo;
/**
* 班级ID
*/
private Long classId;
/**
* 班级名称
*/
private String className;
/**
* 专业ID
*/
private Long majorId;
/**
* 专业名称
*/
private String majorName;
/**
* 学院ID
*/
private Long collegeId;
/**
* 学院名称
*/
private String collegeName;
/**
* 请假类型编码
*/
@NotBlank(message = "请假类型编码不能为空", groups = { AddGroup.class, EditGroup.class })
private String leaveTypeCode;
/**
* 请假类型名称
*/
@NotBlank(message = "请假类型名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String leaveTypeName;
/**
* 开始时间(年月日时分秒)
*/
@NotNull(message = "开始时间(年月日时分秒)不能为空", groups = { AddGroup.class, EditGroup.class })
private Date startTime;
/**
* 结束时间(年月日时分秒)
*/
@NotNull(message = "结束时间(年月日时分秒)不能为空", groups = { AddGroup.class, EditGroup.class })
private Date endTime;
/**
* 请假时长(天)
*/
@NotNull(message = "请假时长(天)不能为空", groups = { AddGroup.class, EditGroup.class })
private Double leaveDuration;
/**
* 是否离校:0-否,1-是
*/
@NotBlank(message = "是否离校:0-否,1-是不能为空", groups = { AddGroup.class, EditGroup.class })
private String isLeaveSchool;
/**
* 是否需要销假:0-否,1-是
*/
@NotBlank(message = "是否需要销假:0-否,1-是不能为空", groups = { AddGroup.class, EditGroup.class })
private String needCancel;
/**
* 紧急联系人
*/
private String emergencyContact;
/**
* 紧急联系电话
*/
private String emergencyPhone;
/**
* 请假原因
*/
@NotBlank(message = "请假原因不能为空", groups = { AddGroup.class, EditGroup.class })
private String leaveReason;
/**
* 请假时地理位置
*/
private String leaveLocation;
/**
* 附件OSS文件ID(逗号分隔)
*/
private String attachmentOssIds;
/**
* 审批状态:"cancel", "已撤销" "draft", "草稿" "waiting", "待审核" "finish", "已完成"
* "invalid", "已作废" "back", "已退回" "termination", "已终止"
*/
@NotBlank(message = "审批状态:cancel-已撤销 draft-草稿 waiting-待审核 finish-已完成 invalid-已作废 back-已退回 termination-已终止 不能为空", groups = {
AddGroup.class, EditGroup.class })
private String approvalStatus;
/**
* 审批意见
*/
private String approvalOpinion;
/**
* 审批时间
*/
private Date approvalTime;
/**
* 审批人ID
*/
private Long approvalBy;
/**
* 审批人姓名
*/
private String approvalByName;
/**
* 销假状态:0-未销假,1-已销假,2-逾期未销假 3 - 无需销假 "cancel", "已撤销" "draft", "草稿" "waiting",
* "待审核" "finish", "已完成" "invalid", "已作废" "back", "已退回" "termination", "已终止"
*/
private String cancelStatus;
/**
* 销假时间
*/
private Date cancelTime;
/**
* 销假地理位置
*/
private String cancelLocation;
/**
* 销假照片OSS文件ID(逗号分隔)
*/
private String cancelPhotoOssIds;
/**
* 销假备注
*/
private String cancelRemark;
/**
* 学生请假表id
*/
@NotNull(message = "学生请假表id不能为空", groups = { AddGroup.class, EditGroup.class })
private Long leaveId;
}
@@ -0,0 +1,244 @@
package org.dromara.workflow.domain.vo;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.dromara.workflow.domain.XgStudentCancelLeave;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 学生销假视图对象 xg_student_cancel_leave
*
* @author zlwu
* @date 2025-08-05
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = XgStudentCancelLeave.class)
public class XgStudentCancelLeaveVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID(雪花ID)
*/
@ExcelProperty(value = "主键ID", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "雪=花ID")
private Long id;
/**
* 删除标志(0代表存在 1代表删除)
*/
@ExcelProperty(value = "删除标志", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=代表存在,1=代表删除")
private Long deleted;
/**
* 学生ID
*/
@ExcelProperty(value = "学生ID")
private Long studentId;
/**
* 学生姓名
*/
@ExcelProperty(value = "学生姓名")
private String studentName;
/**
* 学号
*/
@ExcelProperty(value = "学号")
private String studentNo;
/**
* 班级ID
*/
@ExcelProperty(value = "班级ID")
private Long classId;
/**
* 班级名称
*/
@ExcelProperty(value = "班级名称")
private String className;
/**
* 专业ID
*/
@ExcelProperty(value = "专业ID")
private Long majorId;
/**
* 专业名称
*/
@ExcelProperty(value = "专业名称")
private String majorName;
/**
* 学院ID
*/
@ExcelProperty(value = "学院ID")
private Long collegeId;
/**
* 学院名称
*/
@ExcelProperty(value = "学院名称")
private String collegeName;
/**
* 请假类型编码
*/
@ExcelProperty(value = "请假类型编码")
private String leaveTypeCode;
/**
* 请假类型名称
*/
@ExcelProperty(value = "请假类型名称")
private String leaveTypeName;
/**
* 开始时间(年月日时分秒)
*/
@ExcelProperty(value = "开始时间", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "年=月日时分秒")
private Date startTime;
/**
* 结束时间(年月日时分秒)
*/
@ExcelProperty(value = "结束时间", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "年=月日时分秒")
private Date endTime;
/**
* 请假时长(天)
*/
@ExcelProperty(value = "请假时长", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "天=")
private Double leaveDuration;
/**
* 是否离校:0-否,1-是
*/
@ExcelProperty(value = "是否离校:0-否,1-是")
private String isLeaveSchool;
/**
* 是否需要销假:0-否,1-是
*/
@ExcelProperty(value = "是否需要销假:0-否,1-是")
private String needCancel;
/**
* 紧急联系人
*/
@ExcelProperty(value = "紧急联系人")
private String emergencyContact;
/**
* 紧急联系电话
*/
@ExcelProperty(value = "紧急联系电话")
private String emergencyPhone;
/**
* 请假原因
*/
@ExcelProperty(value = "请假原因")
private String leaveReason;
/**
* 请假时地理位置
*/
@ExcelProperty(value = "请假时地理位置")
private String leaveLocation;
/**
* 附件OSS文件ID(逗号分隔)
*/
@ExcelProperty(value = "附件OSS文件ID", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "逗=号分隔")
private String attachmentOssIds;
/**
* 审批状态:"cancel", "已撤销" "draft", "草稿" "waiting", "待审核" "finish", "已完成"
* "invalid", "已作废" "back", "已退回" "termination", "已终止"
*/
@ExcelProperty(value = "审批状态:cancel-已撤销 draft-草稿 waiting-待审核 finish-已完成 invalid-已作废 back-已退回 termination-已终止")
private String approvalStatus;
/**
* 审批意见
*/
@ExcelProperty(value = "审批意见")
private String approvalOpinion;
/**
* 审批时间
*/
@ExcelProperty(value = "审批时间")
private Date approvalTime;
/**
* 审批人ID
*/
@ExcelProperty(value = "审批人ID")
private Long approvalBy;
/**
* 审批人姓名
*/
@ExcelProperty(value = "审批人姓名")
private String approvalByName;
/**
* 销假状态:0-未销假,1-已销假,2-逾期未销假 3 - 无需销假 "cancel", "已撤销" "draft", "草稿" "waiting",
* "待审核" "finish", "已完成" "invalid", "已作废" "back", "已退回" "termination", "已终止"
*/
@ExcelProperty(value = "销假状态:0-未销假,1-已销假,2-逾期未销假 3 - 无需销假 cancel-已撤销 draft-草稿 waiting-待审核 finish-已完成 invalid-已作废 back-已退回 termination-已终止 ")
private String cancelStatus;
/**
* 销假时间
*/
@ExcelProperty(value = "销假时间")
private Date cancelTime;
/**
* 销假地理位置
*/
@ExcelProperty(value = "销假地理位置")
private String cancelLocation;
/**
* 销假照片OSS文件ID(逗号分隔)
*/
@ExcelProperty(value = "销假照片OSS文件ID", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "逗=号分隔")
private String cancelPhotoOssIds;
/**
* 销假备注
*/
@ExcelProperty(value = "销假备注")
private String cancelRemark;
/**
* 学生请假表id
*/
@ExcelProperty(value = "学生请假表id")
private Long leaveId;
}
@@ -0,0 +1,15 @@
package org.dromara.workflow.mapper;
import org.dromara.workflow.domain.XgStudentCancelLeave;
import org.dromara.workflow.domain.vo.XgStudentCancelLeaveVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 学生销假Mapper接口
*
* @author zlwu
* @date 2025-08-05
*/
public interface XgStudentCancelLeaveMapper extends BaseMapperPlus<XgStudentCancelLeave, XgStudentCancelLeaveVo> {
}
@@ -0,0 +1,84 @@
package org.dromara.workflow.service;
import org.dromara.workflow.domain.vo.XgStudentCancelLeaveVo;
import org.dromara.workflow.domain.bo.XgStudentCancelLeaveBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 学生销假Service接口
*
* @author zlwu
* @date 2025-08-05
*/
public interface IXgStudentCancelLeaveService {
/**
* 查询学生销假
*
* @param id 主键
* @return 学生销假
*/
XgStudentCancelLeaveVo queryById(Long id);
/**
* 分页查询学生销假列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 学生销假分页列表
*/
TableDataInfo<XgStudentCancelLeaveVo> queryPageList(XgStudentCancelLeaveBo bo, PageQuery pageQuery);
/**
* 查询符合条件的学生销假列表
*
* @param bo 查询条件
* @return 学生销假列表
*/
List<XgStudentCancelLeaveVo> queryList(XgStudentCancelLeaveBo bo);
/**
* 新增学生销假
*
* @param bo 学生销假
* @return 新增成功的学生销假信息
*/
XgStudentCancelLeaveVo insertByBo(XgStudentCancelLeaveBo bo);
/**
* 修改学生销假
*
* @param bo 学生销假
* @return 是否修改成功
*/
Boolean updateByBo(XgStudentCancelLeaveBo bo);
/**
* 校验并批量删除学生销假信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 根据请假ID获取销假ID
*
* @param leaveId 请假ID
* @return 销假ID,如果不存在则返回null
*/
Long getCancelLeaveIdByLeaveId(Long leaveId);
/**
* 根据销假ID获取请假ID
*
* @param cancelLeaveId 销假ID
* @return 请假ID,如果不存在则返回null
*/
Long getLeaveIdByCancelLeaveId(Long cancelLeaveId);
}
@@ -0,0 +1,256 @@
package org.dromara.workflow.service.impl;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.dromara.workflow.domain.bo.XgStudentCancelLeaveBo;
import org.dromara.workflow.domain.vo.XgStudentCancelLeaveVo;
import org.dromara.workflow.domain.XgStudentCancelLeave;
import org.dromara.workflow.mapper.XgStudentCancelLeaveMapper;
import org.dromara.workflow.service.IXgStudentCancelLeaveService;
import org.dromara.workflow.service.IXgStudentLeaveService;
import org.dromara.workflow.domain.bo.XgStudentLeaveBo;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 学生销假Service业务层处理
*
* @author zlwu
* @date 2025-08-05
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class XgStudentCancelLeaveServiceImpl implements IXgStudentCancelLeaveService {
private final XgStudentCancelLeaveMapper baseMapper;
private final IXgStudentLeaveService xgStudentLeaveService;
/**
* 查询学生销假
*
* @param id 主键
* @return 学生销假
*/
@Override
public XgStudentCancelLeaveVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
/**
* 分页查询学生销假列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 学生销假分页列表
*/
@Override
public TableDataInfo<XgStudentCancelLeaveVo> queryPageList(XgStudentCancelLeaveBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<XgStudentCancelLeave> lqw = buildQueryWrapper(bo);
Page<XgStudentCancelLeaveVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的学生销假列表
*
* @param bo 查询条件
* @return 学生销假列表
*/
@Override
public List<XgStudentCancelLeaveVo> queryList(XgStudentCancelLeaveBo bo) {
LambdaQueryWrapper<XgStudentCancelLeave> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<XgStudentCancelLeave> buildQueryWrapper(XgStudentCancelLeaveBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<XgStudentCancelLeave> lqw = Wrappers.lambdaQuery();
lqw.orderByAsc(XgStudentCancelLeave::getId);
lqw.eq(bo.getDeleted() != null, XgStudentCancelLeave::getDeleted, bo.getDeleted());
lqw.eq(bo.getStudentId() != null, XgStudentCancelLeave::getStudentId, bo.getStudentId());
lqw.like(StringUtils.isNotBlank(bo.getStudentName()), XgStudentCancelLeave::getStudentName,
bo.getStudentName());
lqw.eq(StringUtils.isNotBlank(bo.getStudentNo()), XgStudentCancelLeave::getStudentNo,
bo.getStudentNo());
lqw.eq(bo.getClassId() != null, XgStudentCancelLeave::getClassId, bo.getClassId());
lqw.like(StringUtils.isNotBlank(bo.getClassName()), XgStudentCancelLeave::getClassName,
bo.getClassName());
lqw.eq(bo.getMajorId() != null, XgStudentCancelLeave::getMajorId, bo.getMajorId());
lqw.like(StringUtils.isNotBlank(bo.getMajorName()), XgStudentCancelLeave::getMajorName,
bo.getMajorName());
lqw.eq(bo.getCollegeId() != null, XgStudentCancelLeave::getCollegeId, bo.getCollegeId());
lqw.like(StringUtils.isNotBlank(bo.getCollegeName()), XgStudentCancelLeave::getCollegeName,
bo.getCollegeName());
lqw.eq(StringUtils.isNotBlank(bo.getLeaveTypeCode()), XgStudentCancelLeave::getLeaveTypeCode,
bo.getLeaveTypeCode());
lqw.like(StringUtils.isNotBlank(bo.getLeaveTypeName()), XgStudentCancelLeave::getLeaveTypeName,
bo.getLeaveTypeName());
lqw.eq(bo.getStartTime() != null, XgStudentCancelLeave::getStartTime, bo.getStartTime());
lqw.eq(bo.getEndTime() != null, XgStudentCancelLeave::getEndTime, bo.getEndTime());
lqw.eq(bo.getLeaveDuration() != null, XgStudentCancelLeave::getLeaveDuration, bo.getLeaveDuration());
lqw.eq(StringUtils.isNotBlank(bo.getIsLeaveSchool()), XgStudentCancelLeave::getIsLeaveSchool,
bo.getIsLeaveSchool());
lqw.eq(StringUtils.isNotBlank(bo.getNeedCancel()), XgStudentCancelLeave::getNeedCancel,
bo.getNeedCancel());
lqw.eq(StringUtils.isNotBlank(bo.getEmergencyContact()), XgStudentCancelLeave::getEmergencyContact,
bo.getEmergencyContact());
lqw.eq(StringUtils.isNotBlank(bo.getEmergencyPhone()), XgStudentCancelLeave::getEmergencyPhone,
bo.getEmergencyPhone());
lqw.eq(StringUtils.isNotBlank(bo.getLeaveReason()), XgStudentCancelLeave::getLeaveReason,
bo.getLeaveReason());
lqw.eq(StringUtils.isNotBlank(bo.getLeaveLocation()), XgStudentCancelLeave::getLeaveLocation,
bo.getLeaveLocation());
lqw.eq(StringUtils.isNotBlank(bo.getAttachmentOssIds()), XgStudentCancelLeave::getAttachmentOssIds,
bo.getAttachmentOssIds());
lqw.eq(StringUtils.isNotBlank(bo.getApprovalStatus()), XgStudentCancelLeave::getApprovalStatus,
bo.getApprovalStatus());
lqw.eq(StringUtils.isNotBlank(bo.getApprovalOpinion()), XgStudentCancelLeave::getApprovalOpinion,
bo.getApprovalOpinion());
lqw.eq(bo.getApprovalTime() != null, XgStudentCancelLeave::getApprovalTime, bo.getApprovalTime());
lqw.eq(bo.getApprovalBy() != null, XgStudentCancelLeave::getApprovalBy, bo.getApprovalBy());
lqw.like(StringUtils.isNotBlank(bo.getApprovalByName()), XgStudentCancelLeave::getApprovalByName,
bo.getApprovalByName());
lqw.eq(StringUtils.isNotBlank(bo.getCancelStatus()), XgStudentCancelLeave::getCancelStatus,
bo.getCancelStatus());
lqw.eq(bo.getCancelTime() != null, XgStudentCancelLeave::getCancelTime, bo.getCancelTime());
lqw.eq(StringUtils.isNotBlank(bo.getCancelLocation()), XgStudentCancelLeave::getCancelLocation,
bo.getCancelLocation());
lqw.eq(StringUtils.isNotBlank(bo.getCancelPhotoOssIds()), XgStudentCancelLeave::getCancelPhotoOssIds,
bo.getCancelPhotoOssIds());
lqw.eq(StringUtils.isNotBlank(bo.getCancelRemark()), XgStudentCancelLeave::getCancelRemark,
bo.getCancelRemark());
lqw.eq(bo.getLeaveId() != null, XgStudentCancelLeave::getLeaveId, bo.getLeaveId());
return lqw;
}
/**
* 新增学生销假
*
* @param bo 学生销假
* @return 新增成功的学生销假信息
*/
@Override
@Transactional(rollbackFor = Exception.class)
public XgStudentCancelLeaveVo insertByBo(XgStudentCancelLeaveBo bo) {
XgStudentCancelLeave add = MapstructUtils.convert(bo, XgStudentCancelLeave.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
// 更新学生请假表中的销假相关字段
if (bo.getLeaveId() != null) {
XgStudentLeaveBo leaveBo = new XgStudentLeaveBo();
leaveBo.setId(bo.getLeaveId());
leaveBo.setCancelStatus(bo.getCancelStatus());
leaveBo.setCancelTime(bo.getCancelTime());
leaveBo.setCancelLocation(bo.getCancelLocation());
leaveBo.setCancelPhotoOssIds(bo.getCancelPhotoOssIds());
leaveBo.setCancelRemark(bo.getCancelRemark());
xgStudentLeaveService.updateByBo(leaveBo);
}
// 返回新增成功的记录信息
return MapstructUtils.convert(add, XgStudentCancelLeaveVo.class);
}
return null;
}
/**
* 修改学生销假
*
* @param bo 学生销假
* @return 是否修改成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean updateByBo(XgStudentCancelLeaveBo bo) {
XgStudentCancelLeave update = MapstructUtils.convert(bo, XgStudentCancelLeave.class);
validEntityBeforeSave(update);
boolean flag = baseMapper.updateById(update) > 0;
if (flag) {
// 同步更新学生请假表中的销假相关字段
if (bo.getLeaveId() != null) {
XgStudentLeaveBo leaveBo = new XgStudentLeaveBo();
leaveBo.setId(bo.getLeaveId());
leaveBo.setCancelStatus(bo.getCancelStatus());
leaveBo.setCancelTime(bo.getCancelTime());
leaveBo.setCancelLocation(bo.getCancelLocation());
leaveBo.setCancelPhotoOssIds(bo.getCancelPhotoOssIds());
leaveBo.setCancelRemark(bo.getCancelRemark());
xgStudentLeaveService.updateByBo(leaveBo);
}
}
return flag;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(XgStudentCancelLeave entity) {
// TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除学生销假信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
// TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 根据请假ID获取销假ID
*
* @param leaveId 请假ID
* @return 销假ID,如果不存在则返回null
*/
@Override
public Long getCancelLeaveIdByLeaveId(Long leaveId) {
LambdaQueryWrapper<XgStudentCancelLeave> lqw = Wrappers.lambdaQuery();
lqw.eq(XgStudentCancelLeave::getLeaveId, leaveId);
lqw.eq(XgStudentCancelLeave::getDeleted, 0L); // 只查询未删除的记录
lqw.select(XgStudentCancelLeave::getId);
XgStudentCancelLeave cancelLeave = baseMapper.selectOne(lqw);
return cancelLeave != null ? cancelLeave.getId() : null;
}
/**
* 根据销假ID获取请假ID
*
* @param cancelLeaveId 销假ID
* @return 请假ID,如果不存在则返回null
*/
@Override
public Long getLeaveIdByCancelLeaveId(Long cancelLeaveId) {
LambdaQueryWrapper<XgStudentCancelLeave> lqw = Wrappers.lambdaQuery();
lqw.eq(XgStudentCancelLeave::getId, cancelLeaveId);
lqw.eq(XgStudentCancelLeave::getDeleted, 0L); // 只查询未删除的记录
lqw.select(XgStudentCancelLeave::getLeaveId);
XgStudentCancelLeave cancelLeave = baseMapper.selectOne(lqw);
return cancelLeave != null ? cancelLeave.getLeaveId() : null;
}
}
@@ -17,10 +17,13 @@ import org.dromara.workflow.mapper.XgStudentLeaveMapper;
import org.dromara.workflow.service.IXgStudentLeaveService;
import org.dromara.workflow.common.ConditionalOnEnable;
import org.dromara.workflow.domain.TestLeave;
import org.dromara.workflow.domain.XgStudentCancelLeave;
import org.dromara.workflow.domain.bo.TestLeaveBo;
import org.dromara.workflow.domain.vo.TestLeaveVo;
import org.dromara.workflow.mapper.TestLeaveMapper;
import org.dromara.workflow.mapper.XgStudentCancelLeaveMapper;
import org.dromara.workflow.service.ITestLeaveService;
import org.dromara.workflow.service.IXgStudentCancelLeaveService;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -57,6 +60,7 @@ public class XgStudentLeaveServiceImpl implements IXgStudentLeaveService {
private final XgStudentLeaveMapper baseMapper;
private final WorkflowService workflowService;
private final XgStudentCancelLeaveMapper xgStudentCancelLeaveMapper;
/**
* 查询学生请假 - 记录学生的请假申请、审批和销假信息
@@ -226,6 +230,43 @@ public class XgStudentLeaveServiceImpl implements IXgStudentLeaveService {
baseMapper.updateById(xgStudentLeave);
}
/**
* 销假流程
* 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)
* 正常使用只需#processEvent.flowCode=='leave1'
* 示例为了方便则使用startsWith匹配了全部示例key
*
* @param processEvent 参数
*/
@Transactional(rollbackFor = Exception.class)
@EventListener(condition = "#processEvent.flowCode.startsWith('hzdyjs-xj')")
public void processHandl_xj(ProcessEvent processEvent) {
// 更新了销假表
log.info("当前任务执行了{}", processEvent.toString());
XgStudentCancelLeave xgStudentCancelLeave = xgStudentCancelLeaveMapper
.selectById(Long.valueOf(processEvent.getBusinessId()));
// 更新了请假表
XgStudentLeave xgStudentLeave = baseMapper.selectById(xgStudentCancelLeave.getLeaveId());
xgStudentCancelLeave.setCancelStatus(processEvent.getStatus());
xgStudentLeave.setCancelStatus(processEvent.getStatus());
// 用于例如审批附件 审批意见等 存储到业务表内 自行根据业务实现存储流程
Map<String, Object> params = processEvent.getParams();
if (MapUtil.isNotEmpty(params)) {
// 历史任务扩展(通常为附件)
String hisTaskExt = Convert.toStr(params.get("hisTaskExt"));
// 办理人
String handler = Convert.toStr(params.get("handler"));
// 办理意见
String message = Convert.toStr(params.get("message"));
}
if (processEvent.getSubmit()) {
xgStudentCancelLeave.setCancelStatus(BusinessStatusEnum.WAITING.getStatus());
xgStudentLeave.setCancelStatus(BusinessStatusEnum.WAITING.getStatus());
}
xgStudentCancelLeaveMapper.updateById(xgStudentCancelLeave);
baseMapper.updateById(xgStudentLeave);
}
/**
* 执行任务创建监听
* 示例:也可通过 @EventListener(condition =
@@ -242,6 +283,23 @@ public class XgStudentLeaveServiceImpl implements IXgStudentLeaveService {
log.info("当前任务创建了{}", processTaskEvent.toString());
}
/**
* 销假
* 执行任务创建监听
* 示例:也可通过 @EventListener(condition =
* "#processTaskEvent.flowCode=='leave1'")进行判断
* 在方法中判断流程节点key
* if ("xxx".equals(processTaskEvent.getNodeCode())) {
* //执行业务逻辑
* }
*
* @param processTaskEvent 参数
*/
@EventListener(condition = "#processTaskEvent.flowCode.startsWith('hzdyjs-xj')")
public void processTaskHandler_xj(ProcessTaskEvent processTaskEvent) {
log.info("当前任务创建了{}", processTaskEvent.toString());
}
/**
* 监听删除流程事件
* 正常使用只需#processDeleteEvent.flowCode=='leave1'
@@ -259,4 +317,33 @@ public class XgStudentLeaveServiceImpl implements IXgStudentLeaveService {
baseMapper.deleteById(xgStudentLeave.getId());
}
/**
* 销假
* 监听删除流程事件
* 正常使用只需#processDeleteEvent.flowCode=='leave1'
* 示例为了方便则使用startsWith匹配了全部示例key
*
* @param processDeleteEvent 参数
*/
@Transactional(rollbackFor = Exception.class)
@EventListener(condition = "#processDeleteEvent.flowCode.startsWith('hzdyjs-xj')")
public void processDeleteHandler_xj(ProcessDeleteEvent processDeleteEvent) {
log.info("监听删除流程事件,当前任务执行了{}", processDeleteEvent.toString());
// 删除销假表数据
XgStudentCancelLeave xgStudentCancelLeave = xgStudentCancelLeaveMapper
.selectById(Long.valueOf(processDeleteEvent.getBusinessId()));
if (ObjectUtil.isNull(xgStudentCancelLeave)) {
return;
}
xgStudentCancelLeaveMapper.deleteById(xgStudentCancelLeave.getId());
// 更新了请假表
XgStudentLeave xgStudentLeave = baseMapper.selectById(xgStudentCancelLeave.getLeaveId());
xgStudentLeave.setCancelStatus("0");
xgStudentLeave.setCancelTime(null);
xgStudentLeave.setCancelLocation(null);
xgStudentLeave.setCancelPhotoOssIds(null);
xgStudentLeave.setCancelRemark(null);
baseMapper.updateById(xgStudentLeave);
}
}
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.workflow.mapper.XgStudentCancelLeaveMapper">
</mapper>
@@ -0,0 +1,153 @@
# 销假表单附件上传区域优化变更记录
**变更时间**: 2025-01-27 14:30:00
**变更人员**: Cursor AI
**变更文件**: `web/src/views/xg/xsjcxx/xsqj/xjdialog.vue`
**变更类型**: 功能优化
## 🎯 变更目标
解决销假表单中附件上传区域当上传很多附件时,附件区域信息显示不完整的问题。
## 🔧 具体变更内容
### 1. 附件容器高度优化
- **原高度**: `max-height: 600px`
- **新高度**: `max-height: 800px`
- **优化效果**: 增加200px高度,支持更多附件显示
### 2. 滚动条样式优化
```css
/* 新增滚动条样式 */
.attachment-upload-container::-webkit-scrollbar {
width: 8px;
}
.attachment-upload-container::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 4px;
}
.attachment-upload-container::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 4px;
}
.attachment-upload-container::-webkit-scrollbar-thumb:hover {
background: #a8a8a8;
}
```
**优化效果**: 滚动条更明显,用户体验更好
### 3. 响应式布局优化
```css
/* 支持响应式布局 */
.attachment-upload-container :deep(.el-upload-list--picture-card) {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
gap: 12px;
margin-top: 12px;
padding-bottom: 20px;
min-height: 200px;
}
/* 大屏幕:5列布局 */
@media (min-width: 1200px) {
grid-template-columns: repeat(5, 1fr);
}
/* 中等屏幕:4列布局 */
@media (min-width: 768px) and (max-width: 1199px) {
grid-template-columns: repeat(4, 1fr);
}
/* 小屏幕:3列布局 */
@media (max-width: 767px) {
grid-template-columns: repeat(3, 1fr);
}
```
**优化效果**: 不同屏幕尺寸下都有最佳显示效果
### 4. 附件数量提示功能
```vue
<!-- 新增附件数量提示 -->
<div v-if="cancelAttachmentList.length > 0" class="attachment-count-tip">
<el-icon><Document /></el-icon>
<span>已上传 {{ cancelAttachmentList.length }} 个附件</span>
<span v-if="cancelAttachmentList.length >= 8" class="scroll-tip">(可滚动查看更多)</span>
</div>
```
**优化效果**: 用户清楚知道已上传的附件数量,当附件较多时提示可滚动
### 5. 附件卡片布局优化
- **卡片高度**: 从 `180px` 增加到 `200px`
- **文件名区域**: 从 `32px` 增加到 `40px`
- **字体大小**: 从 `11px` 增加到 `12px`
- **字体粗细**: 增加 `font-weight: 500`
**优化效果**: 附件信息显示更清晰,可读性更好
### 6. 附件数量提示样式
```css
.attachment-count-tip {
display: flex;
align-items: center;
gap: 6px;
padding: 8px 12px;
background: #e6f7ff;
border: 1px solid #91d5ff;
border-radius: 4px;
margin-bottom: 8px;
font-size: 13px;
color: #1890ff;
}
.scroll-tip {
color: #52c41a;
font-weight: 500;
}
```
**优化效果**: 美观的提示样式,用户友好
## 📊 优化效果对比
### 优化前
- ❌ 附件容器高度限制600px,附件多时显示不全
- ❌ 滚动条不明显,用户可能不知道可以滚动
- ❌ 固定5列布局,小屏幕显示效果差
- ❌ 没有附件数量提示
- ❌ 附件卡片信息显示空间有限
### 优化后
- ✅ 附件容器高度增加到800px,支持更多附件
- ✅ 滚动条样式优化,更明显易用
- ✅ 响应式布局,适配不同屏幕尺寸
- ✅ 附件数量提示,用户清楚了解状态
- ✅ 附件卡片布局优化,信息显示更清晰
## 🎯 用户体验提升
1. **信息完整性**: 附件多时也能完整显示所有信息
2. **操作便利性**: 明显的滚动条和提示信息
3. **视觉友好性**: 响应式布局和优化的卡片设计
4. **状态清晰性**: 附件数量提示让用户了解当前状态
## 📝 技术要点
1. **CSS Grid布局**: 使用 `grid-template-columns: repeat(auto-fit, minmax(160px, 1fr))` 实现响应式
2. **媒体查询**: 针对不同屏幕尺寸优化列数
3. **滚动条定制**: 使用 `::-webkit-scrollbar` 伪元素定制滚动条样式
4. **Vue响应式**: 利用 `cancelAttachmentList.length` 动态显示提示信息
## 🔄 后续建议
1. **性能优化**: 当附件数量特别多时,可考虑虚拟滚动
2. **交互优化**: 可添加附件预览功能
3. **批量操作**: 可添加批量删除、批量下载功能
4. **拖拽排序**: 可添加附件拖拽排序功能
---
**变更状态**: ✅ 已完成
**测试状态**: 🔄 待测试
**文档状态**: ✅ 已更新
@@ -1,5 +1,204 @@
# 代码调整记录 - 2025-01-27 - cursor
## 🔧 前端销假API调用优化 (2025-01-27 14:30:00)
### 功能概述
修改前端销假对话框(`xjdialog.vue`)中的`submitForm`方法,将`addStudentCancelLeave` API调用改为调用后端`XgStudentCancelLeaveController.java`中的`add`方法,主要针对出参处理进行了优化。
### 详细变更
#### 1. 前端API类型定义优化
**文件**: `web/src/api/workflow/studentCancelLeave/studentCancelLeave/index.ts`
**修改内容**:
- 为`addStudentCancelLeave`方法添加了返回类型定义:`AxiosPromise<StudentCancelLeaveVO>`
- 为`getCancelLeaveIdByLeaveId`方法添加了返回类型定义:`AxiosPromise<number>`
**修改前**:
```typescript
export const addStudentCancelLeave = (data: StudentCancelLeaveForm) => {
return request({
url: '/studentCancelLeave/studentCancelLeave',
method: 'post',
data: data
});
};
```
**修改后**:
```typescript
export const addStudentCancelLeave = (data: StudentCancelLeaveForm): AxiosPromise<StudentCancelLeaveVO> => {
return request({
url: '/studentCancelLeave/studentCancelLeave',
method: 'post',
data: data
});
};
```
#### 2. 前端业务逻辑优化
**文件**: `web/src/views/xg/xsjcxx/xsqj/xjdialog.vue`
**修改内容**:
1. **新增销假记录处理优化**:
```javascript
// 调用后端 XgStudentCancelLeaveController 的 add 方法
res = await addStudentCancelLeave(updateData).finally(() => (buttonLoading.value = false));
// 从返回结果中获取新创建的销假记录ID
if (res && res.data && res.data.id) {
cancelLeaveId = res.data.id;
}
```
2. **销假信息获取优化**:
```javascript
// 根据id 获取销假的信息 传给流程启动的函数
const cancelInfoResponse = await getStudentCancelLeave(cancelLeaveId);
const cancelInfo = cancelInfoResponse?.data;
```
### 修改原因
1. **API返回类型统一**: 确保前端API调用与后端控制器返回类型一致
2. **数据处理优化**: 正确处理后端`R<XgStudentCancelLeaveVo>`类型的返回数据
3. **业务逻辑完善**: 确保新增销假记录后能正确获取新创建的记录ID
### 影响范围
- 前端销假功能的新增操作
- 工作流启动时的数据传递
- API类型定义的完整性
### 测试建议
1. 测试新增销假记录功能
2. 验证工作流启动时数据传递的正确性
3. 检查API返回数据的处理是否正确
### 相关文件
- `web/src/views/xg/xsjcxx/xsqj/xjdialog.vue`
- `web/src/api/workflow/studentCancelLeave/studentCancelLeave/index.ts`
- `backend/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/XgStudentCancelLeaveController.java`
---
## 🔧 学生销假控制器新增根据请假ID获取销假ID功能 (2025-01-27 17:00:00)
### 功能概述
在 `XgStudentCancelLeaveController.java` 中新增了根据请假ID获取销假ID的功能,支持通过请假记录快速查找对应的销假记录。
### 详细变更
#### 1. Service接口扩展
**文件**: `backend/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IXgStudentCancelLeaveService.java`
**新增方法**:
```java
/**
* 根据请假ID获取销假ID
*
* @param leaveId 请假ID
* @return 销假ID,如果不存在则返回null
*/
Long getCancelLeaveIdByLeaveId(Long leaveId);
```
#### 2. Service实现类
**文件**: `backend/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/XgStudentCancelLeaveServiceImpl.java`
**新增实现方法**:
```java
/**
* 根据请假ID获取销假ID
*
* @param leaveId 请假ID
* @return 销假ID,如果不存在则返回null
*/
@Override
public Long getCancelLeaveIdByLeaveId(Long leaveId) {
LambdaQueryWrapper<XgStudentCancelLeave> lqw = Wrappers.lambdaQuery();
lqw.eq(XgStudentCancelLeave::getLeaveId, leaveId);
lqw.eq(XgStudentCancelLeave::getDeleted, 0L); // 只查询未删除的记录
lqw.select(XgStudentCancelLeave::getId);
XgStudentCancelLeave cancelLeave = baseMapper.selectOne(lqw);
return cancelLeave != null ? cancelLeave.getId() : null;
}
```
#### 3. Controller接口
**文件**: `backend/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/XgStudentCancelLeaveController.java`
**新增接口方法**:
```java
/**
* 根据请假ID获取销假ID
*
* @param leaveId 请假ID
*/
@SaCheckPermission("studentCancelLeave:studentCancelLeave:query")
@GetMapping("/getCancelLeaveId/{leaveId}")
public R<Long> getCancelLeaveIdByLeaveId(@NotNull(message = "请假ID不能为空")
@PathVariable Long leaveId) {
Long cancelLeaveId = xgStudentCancelLeaveService.getCancelLeaveIdByLeaveId(leaveId);
return R.ok(cancelLeaveId);
}
```
### 技术实现要点
#### 1. 数据库查询优化
- 使用 `LambdaQueryWrapper` 构建查询条件
- 通过 `leaveId` 字段进行精确匹配
- 使用 `select()` 方法只查询需要的 `id` 字段,提高查询效率
#### 2. 权限控制
- 使用 `@SaCheckPermission("studentCancelLeave:studentCancelLeave:query")` 注解
- 复用现有的查询权限,无需额外配置
#### 3. 参数验证
- 使用 `@NotNull` 注解确保请假ID不为空
- 提供清晰的错误提示信息
#### 4. 返回值处理
- 返回 `R<Long>` 类型,符合项目统一响应格式
- 如果不存在对应的销假记录,返回 `null`
### API接口信息
**接口路径**: `GET /studentCancelLeave/studentCancelLeave/getCancelLeaveId/{leaveId}`
**请求参数**:
- `leaveId` (Long, 必填): 请假ID
**响应格式**:
```json
{
"code": 200,
"msg": "操作成功",
"data": 123456
}
```
**权限要求**: `studentCancelLeave:studentCancelLeave:query`
### 变更时间
2025-01-27 17:00:00
### 变更人员
Cursor AI
### 备注
此功能为请假管理模块的重要补充,支持根据请假记录快速查找对应的销假记录,提升系统查询效率。
### 🔧 重要修复 (2025-01-27 17:15:00)
**问题**: 查询条件缺少 `deleted = 0` 过滤条件,可能导致查询到已删除的记录
**修复**: 在 `getCancelLeaveIdByLeaveId` 方法中添加 `lqw.eq(XgStudentCancelLeave::getDeleted, 0L)` 条件
**影响**: 确保只查询未删除的有效销假记录,避免数据污染
---
## 🔧 前端金额格式化函数修复 (2025-01-27 16:30:00)
### 问题描述
@@ -9301,5 +9500,102 @@ public XgStudentLeaveVo insertByBo(XgStudentLeaveBo bo) {
**记录人**: cursor
**记录时间**: 2025-01-27 14:30:00
=======
---
# 代码调整记录 - 2025-01-27 (续)
## 修改时间
2025-01-27 15:30:00
## 修改内容
### 销假界面getStudentLeaveInfo方法优化
**修改原因**: 用户需求 - 在销假界面中根据销假ID获取请假ID,以便正确显示请假信息
#### 涉及文件
1. `web/src/api/workflow/studentCancelLeave/studentCancelLeave/index.ts`
2. `web/src/views/xg/xsjcxx/xsqj/xjdialog.vue`
#### 具体修改
**1. 前端API接口新增**
- 文件: `web/src/api/workflow/studentCancelLeave/studentCancelLeave/index.ts`
- 新增方法: `getLeaveIdByCancelLeaveId`
- 功能: 根据销假ID获取请假ID
- 调用后端接口: `XgStudentCancelLeaveController.getLeaveIdByCancelLeaveId`
```typescript
/**
* 根据销假ID获取请假ID
* @param cancelLeaveId
*/
export const getLeaveIdByCancelLeaveId = (cancelLeaveId: string | number): AxiosPromise<number> => {
return request({
url: `/studentCancelLeave/studentCancelLeave/getLeaveId/${cancelLeaveId}`,
method: 'get'
});
};
```
**2. 销假界面方法修改**
- 文件: `web/src/views/xg/xsjcxx/xsqj/xjdialog.vue`
- 修改方法: `getStudentLeaveInfo`
- 修改内容:
- 导入新增的API方法
- 修改逻辑,使用 `getLeaveIdByCancelLeaveId` 替代 `getCancelLeaveIdByLeaveId`
```typescript
// 导入语句修改
import {
getStudentCancelLeave,
updateStudentCancelLeave,
getCancelLeaveIdByLeaveId,
getLeaveIdByCancelLeaveId, // 新增
addStudentCancelLeave
} from '@/api/workflow/studentCancelLeave/studentCancelLeave';
// getStudentLeaveInfo方法修改
const getStudentLeaveInfo = async (id: string | number) => {
try {
//通过销假id获取请假id
const leaveIdResp = await getLeaveIdByCancelLeaveId(id); // 修改:使用新的API方法
let leaveId = leaveIdResp?.data;
console.log('通过销假ID获取到的请假ID:', leaveId);
id = leaveId || id;
// ... 后续逻辑保持不变
} catch (error) {
// ... 错误处理
}
};
```
#### 修改效果
**修改前**:
- 销假界面使用 `getCancelLeaveIdByLeaveId` 方法(根据请假ID获取销假ID)
- 逻辑错误,无法正确获取请假信息
**修改后**:
- 销假界面使用 `getLeaveIdByCancelLeaveId` 方法(根据销假ID获取请假ID)
- 逻辑正确,能够根据销假ID正确获取对应的请假信息
#### 涉及的后端接口
- `XgStudentCancelLeaveController.getLeaveIdByCancelLeaveId` - 根据销假ID获取请假ID
#### 测试建议
1. 在销假界面中打开一个销假记录
2. 验证是否正确获取到对应的请假信息
3. 检查控制台日志,确认API调用正常
#### 影响范围
- 销假界面 (`xjdialog.vue`) 的数据获取逻辑
- 前端API接口层新增方法
- 不影响请假界面 (`dialog.vue`) 的功能
---
**记录人**: cursor
**记录时间**: 2025-01-27 15:30:00
@@ -1,171 +1,82 @@
# 文件下载缓存机制实现 - 变更记录
# 代码调整记录 - 2025-01-27
**变更时间**: 2025-01-27 15:30:00
**变更人员**: wuzilong
**变更类型**: 功能增强
**影响范围**: 文件下载服务
## 学生销假编辑功能同步更新学生请假信息
## 📋 变更概述
### 修改时间
2025-01-27 10:30:00
为提升文件下载性能,减少对MinIO存储的重复请求,在 `SysOssServiceImpl` 中实现了基于内存的文件缓存机制。
### 修改内容
## 🔧 技术实现
#### 1. 修改学生销假服务实现类
**文件**: `backend/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/XgStudentCancelLeaveServiceImpl.java`
### 1. 核心组件
**修改内容**:
- 在 `updateByBo` 方法中添加了 `@Transactional(rollbackFor = Exception.class)` 事务注解
- 添加了同步更新学生请假表中销假相关字段的逻辑
- 当销假信息更新成功后,根据 `leaveId` 关联更新学生请假表中的以下字段:
- `cancelStatus` - 销假状态
- `cancelTime` - 销假时间
- `cancelLocation` - 销假地理位置
- `cancelPhotoOssIds` - 销假照片OSS文件ID
- `cancelRemark` - 销假备注
#### 缓存条目类 (CacheEntry)
- 位置: `SysOssServiceImpl.java` (第67-120行)
- 功能: 存储文件数据、大小、创建时间、访问时间、内容类型
- 特性: 支持过期时间检查
**修改原因**:
- 确保学生销假信息的修改能够同步更新到学生请假表中
- 保持两个表之间销假信息的一致性
- 避免数据不一致的问题
#### LRU缓存实现
- 存储: `ConcurrentHashMap<Long, CacheEntry>`
- 并发安全: `ReentrantReadWriteLock`
- 统计: `AtomicLong` 计数器
### 技术实现
### 2. 配置管理
#### 事务管理
- 使用 `@Transactional(rollbackFor = Exception.class)` 确保数据一致性
- 如果销假表更新失败或请假表更新失败,都会回滚整个事务
#### 配置类
- 文件: `FileCacheConfig.java`
- 功能: 管理所有缓存参数
- 配置前缀: `system.file-cache`
#### 同步逻辑
```java
if (flag) {
// 同步更新学生请假表中的销假相关字段
if (bo.getLeaveId() != null) {
XgStudentLeaveBo leaveBo = new XgStudentLeaveBo();
leaveBo.setId(bo.getLeaveId());
leaveBo.setCancelStatus(bo.getCancelStatus());
leaveBo.setCancelTime(bo.getCancelTime());
leaveBo.setCancelLocation(bo.getCancelLocation());
leaveBo.setCancelPhotoOssIds(bo.getCancelPhotoOssIds());
leaveBo.setCancelRemark(bo.getCancelRemark());
#### 配置参数
```yaml
system:
file-cache:
enabled: true # 是否启用缓存
max-cache-size: 100 # 最大文件数量
max-cache-size-bytes: 524288000 # 最大缓存大小(500MB)
expire-time-ms: 1800000 # 过期时间(30分钟)
max-single-file-size: 52428800 # 单文件最大大小(50MB)
evict-ratio: 20 # LRU淘汰比例(20%)
enable-stats: true # 启用统计
cleanup-interval-ms: 300000 # 清理间隔(5分钟)
xgStudentLeaveService.updateByBo(leaveBo);
}
}
```
### 3. API接口
### 影响范围
- **学生销假管理**: 编辑销假信息时会同步更新请假表
- **数据一致性**: 确保销假信息在两个表中保持一致
- **业务流程**: 不影响现有的销假业务流程
#### 新增接口
1. **获取缓存统计**: `GET /resource/oss/cache/stats`
2. **清空缓存**: `DELETE /resource/oss/cache/clear`
3. **移除指定缓存**: `DELETE /resource/oss/cache/{ossId}`
### 测试建议
1. 测试编辑学生销假信息功能
2. 验证学生请假表中的销假字段是否正确更新
3. 测试事务回滚功能(模拟更新失败场景)
#### 权限配置
- `system:oss:cache:stats` - 查看缓存统计
- `system:oss:cache:clear` - 清空缓存
- `system:oss:cache:remove` - 移除指定缓存
### 相关文件
- `backend/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/XgStudentCancelLeaveController.java`
- `backend/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IXgStudentCancelLeaveService.java`
- `backend/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/XgStudentCancelLeaveBo.java`
## 📁 修改文件清单
#### 2. 创建学生销假管理API文档
**文件**: `docs/开发文档/API/学生销假管理API.md`
### 1. 核心实现文件
- `backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java`
- 新增缓存相关字段和方法
- 修改 `secureDownload` 方法支持缓存
- 新增缓存管理方法
**创建内容**:
- 完整的学生销假管理API接口文档
- 包含7个主要接口的详细说明
- 重点说明修改销假接口的同步更新功能
- 提供技术实现说明和使用示例
- 包含数据字典和注意事项
### 2. 接口定义文件
- `backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java`
- 新增缓存管理接口方法
#### 3. 更新API文档总览
**文件**: `docs/开发文档/API/API文档总览.md`
### 3. 控制器文件
- `backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java`
- 新增缓存管理API接口
### 4. 配置类文件
- `backend/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/config/FileCacheConfig.java`
- 新增文件缓存配置类
### 5. 配置文件
- `backend/ruoyi-modules/ruoyi-system/src/main/resources/application-file-cache.yml`
- 新增配置示例文件
### 6. 文档文件
- `docs/开发文档/文件下载缓存机制说明.md`
- 新增详细的功能说明文档
## 🚀 功能特性
### 1. 智能缓存策略
- **大小控制**: 只缓存小于50MB的文件
- **LRU淘汰**: 空间不足时淘汰最久未访问的文件
- **过期管理**: 30分钟自动过期
- **并发安全**: 读写锁保证数据一致性
### 2. 性能优化
- **缓存命中**: 直接从内存返回,响应时间减少80-90%
- **流式传输**: 支持大文件分块下载
- **统计监控**: 实时监控缓存命中率和大小
### 3. 管理功能
- **统计信息**: 缓存大小、命中率、访问次数
- **手动管理**: 支持清空和移除指定缓存
- **配置化**: 所有参数可通过配置文件调整
## 📊 性能提升
### 预期效果
- **响应时间**: 缓存命中时减少80-90%
- **MinIO压力**: 显著减少重复请求
- **并发性能**: 支持多用户同时访问
- **整体性能**: 平均下载速度提升60-80%
### 监控指标
- 缓存命中率 > 70%
- 内存使用率合理控制
- 响应时间显著提升
## ⚠️ 注意事项
### 1. 内存管理
- 缓存占用JVM堆内存,需要合理配置大小
- 建议监控应用内存使用情况
- 大文件不会被缓存,避免内存溢出
### 2. 数据一致性
- 缓存数据可能与MinIO不同步
- 文件更新后建议清除相关缓存
- 可通过API手动管理缓存
### 3. 配置建议
- 根据服务器内存调整缓存大小
- 根据访问模式优化过期时间
- 定期监控缓存统计信息
## 🔧 测试建议
### 1. 功能测试
- 测试文件下载缓存机制
- 验证LRU淘汰策略
- 检查过期时间管理
### 2. 性能测试
- 对比缓存命中前后的响应时间
- 测试并发下载性能
- 监控内存使用情况
### 3. 压力测试
- 模拟大量文件下载请求
- 测试缓存满时的淘汰机制
- 验证系统稳定性
## 📝 后续优化
### 1. 功能增强
- 支持缓存预热
- 添加缓存压缩
- 实现分布式缓存
### 2. 监控完善
- 集成Prometheus监控
- 添加缓存告警
- 完善日志记录
### 3. 性能优化
- 优化LRU算法
- 支持缓存分片
- 添加缓存预热
---
**📋 变更确认**: 本次变更已完成代码实现、文档编写和配置管理,建议在测试环境验证后部署到生产环境。
**更新内容**:
- 在API模块列表中添加学生销假管理API的链接
- 保持文档结构的一致性
+1
View File
@@ -15,6 +15,7 @@
- [宿舍管理员信息API](./宿舍管理员信息API.md)
- [宿舍管理员授权API](./宿舍管理员授权API.md)
- [学生管理员授权关系API](./学生管理员授权关系API.md)
- [学生销假管理API](./学生销假管理API.md)
### 1. 用户认证登录
@@ -0,0 +1,579 @@
# 学生销假管理 API 接口文档
## 模块概述
**模块名称**:Student Cancel Leave / 学生销假管理
**基础路径**:`/studentCancelLeave/studentCancelLeave`
**版本**:v1.0
**负责人**:zlwu
**更新时间**:2025-01-27
### 模块功能
学生销假管理模块负责处理学生的销假申请和审批流程,包括销假信息的录入、修改、查询和删除。该模块与学生请假管理模块紧密关联,确保销假信息在两个表之间保持同步。
**核心特性**:
- 销假信息的完整生命周期管理
- 与学生请假表的自动同步更新
- 支持销假状态跟踪和地理位置记录
- 提供照片上传和备注功能
### 权限说明
- **权限前缀**:`studentCancelLeave:studentCancelLeave:`
- **权限列表**:
- `studentCancelLeave:studentCancelLeave:list` - 查询销假列表
- `studentCancelLeave:studentCancelLeave:query` - 查询销假详情
- `studentCancelLeave:studentCancelLeave:add` - 新增销假
- `studentCancelLeave:studentCancelLeave:edit` - 编辑销假
- `studentCancelLeave:studentCancelLeave:remove` - 删除销假
- `studentCancelLeave:studentCancelLeave:export` - 导出销假数据
---
## 📊 接口概览
### 接口分类
#### 基础 CRUD 接口
| 接口名称 | HTTP 方法 | 路径 | 权限要求 | 功能描述 |
| -------------- | --------- | --------------------------------------- | ------------------------------------------- | ---------------------- |
| 查询销假列表 | GET | `/studentCancelLeave/studentCancelLeave/list` | `studentCancelLeave:studentCancelLeave:list` | 分页查询销假列表 |
| 查询销假详情 | GET | `/studentCancelLeave/studentCancelLeave/{id}` | `studentCancelLeave:studentCancelLeave:query` | 根据 ID 查询销假详情 |
| 新增销假 | POST | `/studentCancelLeave/studentCancelLeave` | `studentCancelLeave:studentCancelLeave:add` | 创建新的销假记录 |
| 修改销假 | PUT | `/studentCancelLeave/studentCancelLeave` | `studentCancelLeave:studentCancelLeave:edit` | 更新销假信息 |
| 删除销假 | DELETE | `/studentCancelLeave/studentCancelLeave/{ids}` | `studentCancelLeave:studentCancelLeave:remove` | 批量删除销假记录 |
#### 业务逻辑接口
| 接口名称 | HTTP 方法 | 路径 | 权限要求 | 功能描述 |
| ------------------ | --------- | ------------------------------------------------------- | ------------------------------------------- | ---------------------- |
| 导出销假数据 | POST | `/studentCancelLeave/studentCancelLeave/export` | `studentCancelLeave:studentCancelLeave:export` | 导出销假数据到Excel |
| 根据请假ID获取销假ID | GET | `/studentCancelLeave/studentCancelLeave/getCancelLeaveId/{leaveId}` | `studentCancelLeave:studentCancelLeave:query` | 根据请假ID查询对应的销假ID |
### 通用响应格式
#### 成功响应
```json
{
"code": 200,
"msg": "操作成功",
"data": {
// 响应数据
}
}
```
#### 分页响应
```json
{
"code": 200,
"msg": "查询成功",
"rows": [
// 数据列表
],
"total": 100
}
```
#### 错误响应
```json
{
"code": 400001,
"msg": "参数错误",
"data": null
}
```
---
## 🔌 详细接口说明
### 1. 查询销假列表
- **接口路径**:`GET /studentCancelLeave/studentCancelLeave/list`
- **权限标识**:`studentCancelLeave:studentCancelLeave:list`
- **功能描述**:分页查询学生销假列表,支持多条件筛选
#### 请求参数
| 参数名 | 类型 | 必填 | 说明 |
| ---------------- | ------ | ---- | ------------------------ |
| pageNum | int | 否 | 页码,默认1 |
| pageSize | int | 否 | 每页大小,默认10 |
| studentName | string | 否 | 学生姓名(模糊查询) |
| studentNo | string | 否 | 学号 |
| className | string | 否 | 班级名称(模糊查询) |
| collegeName | string | 否 | 学院名称(模糊查询) |
| leaveTypeCode | string | 否 | 请假类型编码 |
| approvalStatus | string | 否 | 审批状态 |
| cancelStatus | string | 否 | 销假状态 |
| startTime | date | 否 | 开始时间 |
| endTime | date | 否 | 结束时间 |
#### 响应数据
```json
{
"code": 200,
"msg": "查询成功",
"rows": [
{
"id": 1,
"studentId": 1001,
"studentName": "张三",
"studentNo": "2023001001",
"className": "计算机2023-1班",
"collegeName": "计算机学院",
"leaveTypeName": "事假",
"startTime": "2025-01-20 08:00:00",
"endTime": "2025-01-22 18:00:00",
"leaveDuration": 3.0,
"approvalStatus": "finish",
"cancelStatus": "1",
"cancelTime": "2025-01-22 16:30:00",
"cancelLocation": "北京市朝阳区",
"cancelRemark": "已按时返校",
"leaveId": 2001
}
],
"total": 1
}
```
### 2. 查询销假详情
- **接口路径**:`GET /studentCancelLeave/studentCancelLeave/{id}`
- **权限标识**:`studentCancelLeave:studentCancelLeave:query`
- **功能描述**:根据ID查询销假详细信息
#### 请求参数
| 参数名 | 类型 | 必填 | 说明 |
| ------ | ---- | ---- | ------ |
| id | long | 是 | 销假ID |
#### 响应数据
```json
{
"code": 200,
"msg": "查询成功",
"data": {
"id": 1,
"studentId": 1001,
"studentName": "张三",
"studentNo": "2023001001",
"classId": 101,
"className": "计算机2023-1班",
"majorId": 1,
"majorName": "计算机科学与技术",
"collegeId": 1,
"collegeName": "计算机学院",
"leaveTypeCode": "SJ",
"leaveTypeName": "事假",
"startTime": "2025-01-20 08:00:00",
"endTime": "2025-01-22 18:00:00",
"leaveDuration": 3.0,
"isLeaveSchool": "1",
"needCancel": "1",
"emergencyContact": "张父",
"emergencyPhone": "13900139000",
"leaveReason": "家中有事需要处理",
"leaveLocation": "北京市朝阳区",
"attachmentOssIds": "123,456",
"approvalStatus": "finish",
"approvalOpinion": "同意请假",
"approvalTime": "2025-01-19 14:30:00",
"approvalBy": 1001,
"approvalByName": "李老师",
"cancelStatus": "1",
"cancelTime": "2025-01-22 16:30:00",
"cancelLocation": "北京市朝阳区",
"cancelPhotoOssIds": "789,101",
"cancelRemark": "已按时返校",
"leaveId": 2001
}
}
```
### 3. 新增销假
- **接口路径**:`POST /studentCancelLeave/studentCancelLeave`
- **权限标识**:`studentCancelLeave:studentCancelLeave:add`
- **功能描述**:新增学生销假记录,并同步更新学生请假表的销假信息
#### 请求参数
```json
{
"studentId": 1001,
"studentName": "张三",
"studentNo": "2023001001",
"classId": 101,
"className": "计算机2023-1班",
"majorId": 1,
"majorName": "计算机科学与技术",
"collegeId": 1,
"collegeName": "计算机学院",
"leaveTypeCode": "SJ",
"leaveTypeName": "事假",
"startTime": "2025-01-20 08:00:00",
"endTime": "2025-01-22 18:00:00",
"leaveDuration": 3.0,
"isLeaveSchool": "1",
"needCancel": "1",
"emergencyContact": "张父",
"emergencyPhone": "13900139000",
"leaveReason": "家中有事需要处理",
"leaveLocation": "北京市朝阳区",
"attachmentOssIds": "123,456",
"approvalStatus": "finish",
"approvalOpinion": "同意请假",
"approvalTime": "2025-01-19 14:30:00",
"approvalBy": 1001,
"approvalByName": "李老师",
"cancelStatus": "1",
"cancelTime": "2025-01-22 16:30:00",
"cancelLocation": "北京市朝阳区",
"cancelPhotoOssIds": "789,101",
"cancelRemark": "已按时返校",
"leaveId": 2001
}
```
#### 响应数据
```json
{
"code": 200,
"msg": "新增成功",
"data": {
"id": 1,
"studentName": "张三",
"studentNo": "2023001001",
"cancelStatus": "1",
"cancelTime": "2025-01-22 16:30:00"
}
}
```
### 4. 修改销假 ⭐
- **接口路径**:`PUT /studentCancelLeave/studentCancelLeave`
- **权限标识**:`studentCancelLeave:studentCancelLeave:edit`
- **功能描述**:修改学生销假信息,并同步更新学生请假表中的销假相关字段
**⚠️ 重要说明**:此接口会自动同步更新学生请假表中的销假信息,确保数据一致性。
#### 请求参数
```json
{
"id": 1,
"cancelStatus": "1",
"cancelTime": "2025-01-22 16:30:00",
"cancelLocation": "北京市朝阳区",
"cancelPhotoOssIds": "789,101",
"cancelRemark": "已按时返校,状态良好",
"leaveId": 2001
}
```
#### 响应数据
```json
{
"code": 200,
"msg": "修改成功"
}
```
#### 同步更新说明
当修改销假信息时,系统会自动同步更新学生请假表中的以下字段:
| 字段名 | 说明 | 来源 |
| ------------------- | ------------ | ----------------------- |
| `cancel_status` | 销假状态 | 销假表的 `cancelStatus` |
| `cancel_time` | 销假时间 | 销假表的 `cancelTime` |
| `cancel_location` | 销假地理位置 | 销假表的 `cancelLocation` |
| `cancel_photo_oss_ids` | 销假照片 | 销假表的 `cancelPhotoOssIds` |
| `cancel_remark` | 销假备注 | 销假表的 `cancelRemark` |
**事务保证**:使用 `@Transactional` 注解确保两个表的更新操作要么全部成功,要么全部回滚。
### 5. 删除销假
- **接口路径**:`DELETE /studentCancelLeave/studentCancelLeave/{ids}`
- **权限标识**:`studentCancelLeave:studentCancelLeave:remove`
- **功能描述**:批量删除销假记录
#### 请求参数
| 参数名 | 类型 | 必填 | 说明 |
| ------ | ------ | ---- | ------------------------ |
| ids | string | 是 | 销假ID列表,多个用逗号分隔 |
#### 响应数据
```json
{
"code": 200,
"msg": "删除成功"
}
```
### 6. 导出销假数据
- **接口路径**:`POST /studentCancelLeave/studentCancelLeave/export`
- **权限标识**:`studentCancelLeave:studentCancelLeave:export`
- **功能描述**:导出销假数据到Excel文件
#### 请求参数
| 参数名 | 类型 | 必填 | 说明 |
| ---------------- | ------ | ---- | ------------------------ |
| studentName | string | 否 | 学生姓名(模糊查询) |
| studentNo | string | 否 | 学号 |
| className | string | 否 | 班级名称(模糊查询) |
| collegeName | string | 否 | 学院名称(模糊查询) |
| leaveTypeCode | string | 否 | 请假类型编码 |
| approvalStatus | string | 否 | 审批状态 |
| cancelStatus | string | 否 | 销假状态 |
| startTime | date | 否 | 开始时间 |
| endTime | date | 否 | 结束时间 |
#### 响应数据
返回Excel文件流,文件名格式:`学生销假_yyyyMMddHHmmss.xlsx`
### 7. 根据请假ID获取销假ID
- **接口路径**:`GET /studentCancelLeave/studentCancelLeave/getCancelLeaveId/{leaveId}`
- **权限标识**:`studentCancelLeave:studentCancelLeave:query`
- **功能描述**:根据请假ID查询对应的销假ID
#### 请求参数
| 参数名 | 类型 | 必填 | 说明 |
| ------- | ---- | ---- | ------ |
| leaveId | long | 是 | 请假ID |
#### 响应数据
```json
{
"code": 200,
"msg": "查询成功",
"data": 1
}
```
---
## 📋 数据字典
### 销假状态 (cancelStatus)
| 值 | 说明 |
| --- | -------- |
| 0 | 未销假 |
| 1 | 已销假 |
| 2 | 逾期未销假 |
| 3 | 无需销假 |
### 审批状态 (approvalStatus)
| 值 | 说明 |
| --------- | -------- |
| draft | 草稿 |
| waiting | 待审核 |
| finish | 已完成 |
| cancel | 已撤销 |
| invalid | 已作废 |
| back | 已退回 |
| termination | 已终止 |
### 是否离校 (isLeaveSchool)
| 值 | 说明 |
| --- | ---- |
| 0 | 否 |
| 1 | 是 |
### 是否需要销假 (needCancel)
| 值 | 说明 |
| --- | ---- |
| 0 | 否 |
| 1 | 是 |
---
## 🔧 技术实现
### 数据同步机制
#### 1. 新增销假同步
在 `insertByBo` 方法中,新增销假记录成功后,会自动更新学生请假表的销假字段:
```java
@Transactional(rollbackFor = Exception.class)
public XgStudentCancelLeaveVo insertByBo(XgStudentCancelLeaveBo bo) {
// 新增销假记录
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
// 同步更新学生请假表中的销假相关字段
if (bo.getLeaveId() != null) {
XgStudentLeaveBo leaveBo = new XgStudentLeaveBo();
leaveBo.setId(bo.getLeaveId());
leaveBo.setCancelStatus(bo.getCancelStatus());
leaveBo.setCancelTime(bo.getCancelTime());
leaveBo.setCancelLocation(bo.getCancelLocation());
leaveBo.setCancelPhotoOssIds(bo.getCancelPhotoOssIds());
leaveBo.setCancelRemark(bo.getCancelRemark());
xgStudentLeaveService.updateByBo(leaveBo);
}
}
}
```
#### 2. 修改销假同步
在 `updateByBo` 方法中,修改销假记录成功后,也会同步更新学生请假表:
```java
@Transactional(rollbackFor = Exception.class)
public Boolean updateByBo(XgStudentCancelLeaveBo bo) {
// 修改销假记录
boolean flag = baseMapper.updateById(update) > 0;
if (flag) {
// 同步更新学生请假表中的销假相关字段
if (bo.getLeaveId() != null) {
XgStudentLeaveBo leaveBo = new XgStudentLeaveBo();
leaveBo.setId(bo.getLeaveId());
leaveBo.setCancelStatus(bo.getCancelStatus());
leaveBo.setCancelTime(bo.getCancelTime());
leaveBo.setCancelLocation(bo.getCancelLocation());
leaveBo.setCancelPhotoOssIds(bo.getCancelPhotoOssIds());
leaveBo.setCancelRemark(bo.getCancelRemark());
xgStudentLeaveService.updateByBo(leaveBo);
}
}
return flag;
}
```
### 事务管理
- 使用 `@Transactional(rollbackFor = Exception.class)` 确保数据一致性
- 如果销假表更新失败或请假表更新失败,都会回滚整个事务
- 保证两个表的数据始终保持同步
### 关联关系
- 销假表通过 `leave_id` 字段关联学生请假表
- 一个请假记录只能对应一个销假记录
- 销假记录必须关联到有效的请假记录
---
## 🚀 使用示例
### 前端调用示例
```javascript
// 修改销假信息
const updateCancelLeave = async (data) => {
try {
const response = await request({
url: '/studentCancelLeave/studentCancelLeave',
method: 'put',
data: {
id: 1,
cancelStatus: '1',
cancelTime: '2025-01-22 16:30:00',
cancelLocation: '北京市朝阳区',
cancelPhotoOssIds: '789,101',
cancelRemark: '已按时返校',
leaveId: 2001
}
});
if (response.code === 200) {
console.log('销假信息修改成功,已同步更新请假表');
}
} catch (error) {
console.error('修改失败:', error);
}
};
```
### 后端调用示例
```java
// 修改销假信息
XgStudentCancelLeaveBo bo = new XgStudentCancelLeaveBo();
bo.setId(1L);
bo.setCancelStatus("1");
bo.setCancelTime(new Date());
bo.setCancelLocation("北京市朝阳区");
bo.setCancelRemark("已按时返校");
bo.setLeaveId(2001L);
boolean result = xgStudentCancelLeaveService.updateByBo(bo);
if (result) {
log.info("销假信息修改成功,已同步更新请假表");
}
```
---
## ⚠️ 注意事项
### 1. 数据一致性
- 销假信息修改时会自动同步更新学生请假表
- 确保 `leaveId` 字段正确关联到有效的请假记录
- 使用事务保证数据一致性
### 2. 权限控制
- 所有接口都需要相应的权限标识
- 建议在业务层面进行权限验证
- 注意数据访问范围的控制
### 3. 性能考虑
- 大量数据查询时建议使用分页
- 导出功能可能耗时较长,建议异步处理
- 注意缓存策略的使用
### 4. 错误处理
- 接口调用失败时会返回相应的错误码和错误信息
- 建议在前端进行适当的错误处理
- 记录详细的错误日志便于问题排查
---
## 📝 更新日志
| 版本 | 日期 | 更新内容 | 更新人 |
| ------ | ---------- | ---------------------------------- | ------ |
| v1.0 | 2025-01-27 | 初始版本,包含完整的CRUD接口 | zlwu |
| v1.1 | 2025-01-27 | 新增同步更新学生请假表功能 | zlwu |
---
**📋 文档维护**:本文档会随着接口的更新而持续维护,如有疑问请联系开发团队。
@@ -0,0 +1,85 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { StudentCancelLeaveVO, StudentCancelLeaveForm, StudentCancelLeaveQuery } from '@/api/workflow/studentCancelLeave/studentCancelLeave/types';
/**
* 查询学生销假列表
* @param query
* @returns {*}
*/
export const listStudentCancelLeave = (query?: StudentCancelLeaveQuery): AxiosPromise<StudentCancelLeaveVO[]> => {
return request({
url: '/studentCancelLeave/studentCancelLeave/list',
method: 'get',
params: query
});
};
/**
* 查询学生销假详细
* @param id
*/
export const getStudentCancelLeave = (id: string | number): AxiosPromise<StudentCancelLeaveVO> => {
return request({
url: '/studentCancelLeave/studentCancelLeave/' + id,
method: 'get'
});
};
/**
* 新增学生销假
* @param data
*/
export const addStudentCancelLeave = (data: StudentCancelLeaveForm): AxiosPromise<StudentCancelLeaveVO> => {
return request({
url: '/studentCancelLeave/studentCancelLeave',
method: 'post',
data: data
});
};
/**
* 修改学生销假
* @param data
*/
export const updateStudentCancelLeave = (data: StudentCancelLeaveForm) => {
return request({
url: '/studentCancelLeave/studentCancelLeave',
method: 'put',
data: data
});
};
/**
* 删除学生销假
* @param id
*/
export const delStudentCancelLeave = (id: string | number | Array<string | number>) => {
return request({
url: '/studentCancelLeave/studentCancelLeave/' + id,
method: 'delete'
});
};
/**
* 根据请假ID获取销假ID
* @param leaveId
*/
export const getCancelLeaveIdByLeaveId = (leaveId: string | number): AxiosPromise<number> => {
return request({
url: `/studentCancelLeave/studentCancelLeave/getCancelLeaveId/${leaveId}`,
method: 'get'
});
};
/**
* 根据销假ID获取请假ID
* @param cancelLeaveId
*/
export const getLeaveIdByCancelLeaveId = (cancelLeaveId: string | number): AxiosPromise<number> => {
return request({
url: `/studentCancelLeave/studentCancelLeave/getLeaveId/${cancelLeaveId}`,
method: 'get'
});
};
@@ -0,0 +1,521 @@
export interface StudentCancelLeaveVO {
/**
* 主键ID(雪花ID)
*/
id: string | number;
/**
* 删除标志(0代表存在 1代表删除)
*/
deleted: number;
/**
* 学生ID
*/
studentId: string | number;
/**
* 学生姓名
*/
studentName: string;
/**
* 学号
*/
studentNo: string;
/**
* 班级ID
*/
classId: string | number;
/**
* 班级名称
*/
className: string;
/**
* 专业ID
*/
majorId: string | number;
/**
* 专业名称
*/
majorName: string;
/**
* 学院ID
*/
collegeId: string | number;
/**
* 学院名称
*/
collegeName: string;
/**
* 请假类型编码
*/
leaveTypeCode: string;
/**
* 请假类型名称
*/
leaveTypeName: string;
/**
* 开始时间(年月日时分秒)
*/
startTime: string;
/**
* 结束时间(年月日时分秒)
*/
endTime: string;
/**
* 请假时长(天)
*/
leaveDuration: number;
/**
* 是否离校:0-否,1-是
*/
isLeaveSchool: string;
/**
* 是否需要销假:0-否,1-是
*/
needCancel: string;
/**
* 紧急联系人
*/
emergencyContact: string;
/**
* 紧急联系电话
*/
emergencyPhone: string;
/**
* 请假原因
*/
leaveReason: string;
/**
* 请假时地理位置
*/
leaveLocation: string;
/**
* 附件OSS文件ID(逗号分隔)
*/
attachmentOssIds: string | number;
/**
* 审批状态:"cancel", "已撤销" "draft", "草稿" "waiting", "待审核" "finish", "已完成" "invalid", "已作废" "back", "已退回" "termination", "已终止"
*/
approvalStatus: string;
/**
* 审批意见
*/
approvalOpinion: string;
/**
* 审批时间
*/
approvalTime: string;
/**
* 审批人ID
*/
approvalBy: number;
/**
* 审批人姓名
*/
approvalByName: string;
/**
* 销假状态:0-未销假,1-已销假,2-逾期未销假 3 - 无需销假 "cancel", "已撤销" "draft", "草稿" "waiting", "待审核" "finish", "已完成" "invalid", "已作废" "back", "已退回" "termination", "已终止"
*/
cancelStatus: string;
/**
* 销假时间
*/
cancelTime: string;
/**
* 销假地理位置
*/
cancelLocation: string;
/**
* 销假照片OSS文件ID(逗号分隔)
*/
cancelPhotoOssIds: string | number;
/**
* 销假备注
*/
cancelRemark: string;
/**
* 学生请假表id
*/
leaveId: string | number;
}
export interface StudentCancelLeaveForm extends BaseEntity {
/**
* 主键ID(雪花ID)
*/
id?: string | number;
/**
* 删除标志(0代表存在 1代表删除)
*/
deleted?: number;
/**
* 学生ID
*/
studentId?: string | number;
/**
* 学生姓名
*/
studentName?: string;
/**
* 学号
*/
studentNo?: string;
/**
* 班级ID
*/
classId?: string | number;
/**
* 班级名称
*/
className?: string;
/**
* 专业ID
*/
majorId?: string | number;
/**
* 专业名称
*/
majorName?: string;
/**
* 学院ID
*/
collegeId?: string | number;
/**
* 学院名称
*/
collegeName?: string;
/**
* 请假类型编码
*/
leaveTypeCode?: string;
/**
* 请假类型名称
*/
leaveTypeName?: string;
/**
* 开始时间(年月日时分秒)
*/
startTime?: string;
/**
* 结束时间(年月日时分秒)
*/
endTime?: string;
/**
* 请假时长(天)
*/
leaveDuration?: number;
/**
* 是否离校:0-否,1-是
*/
isLeaveSchool?: string;
/**
* 是否需要销假:0-否,1-是
*/
needCancel?: string;
/**
* 紧急联系人
*/
emergencyContact?: string;
/**
* 紧急联系电话
*/
emergencyPhone?: string;
/**
* 请假原因
*/
leaveReason?: string;
/**
* 请假时地理位置
*/
leaveLocation?: string;
/**
* 附件OSS文件ID(逗号分隔)
*/
attachmentOssIds?: string | number;
/**
* 审批状态:"cancel", "已撤销" "draft", "草稿" "waiting", "待审核" "finish", "已完成" "invalid", "已作废" "back", "已退回" "termination", "已终止"
*/
approvalStatus?: string;
/**
* 审批意见
*/
approvalOpinion?: string;
/**
* 审批时间
*/
approvalTime?: string;
/**
* 审批人ID
*/
approvalBy?: number;
/**
* 审批人姓名
*/
approvalByName?: string;
/**
* 销假状态:0-未销假,1-已销假,2-逾期未销假 3 - 无需销假 "cancel", "已撤销" "draft", "草稿" "waiting", "待审核" "finish", "已完成" "invalid", "已作废" "back", "已退回" "termination", "已终止"
*/
cancelStatus?: string;
/**
* 销假时间
*/
cancelTime?: string;
/**
* 销假地理位置
*/
cancelLocation?: string;
/**
* 销假照片OSS文件ID(逗号分隔)
*/
cancelPhotoOssIds?: string | number;
/**
* 销假备注
*/
cancelRemark?: string;
/**
* 学生请假表id
*/
leaveId?: string | number;
}
export interface StudentCancelLeaveQuery extends PageQuery {
/**
* 删除标志(0代表存在 1代表删除)
*/
deleted?: number;
/**
* 学生ID
*/
studentId?: string | number;
/**
* 学生姓名
*/
studentName?: string;
/**
* 学号
*/
studentNo?: string;
/**
* 班级ID
*/
classId?: string | number;
/**
* 班级名称
*/
className?: string;
/**
* 专业ID
*/
majorId?: string | number;
/**
* 专业名称
*/
majorName?: string;
/**
* 学院ID
*/
collegeId?: string | number;
/**
* 学院名称
*/
collegeName?: string;
/**
* 请假类型编码
*/
leaveTypeCode?: string;
/**
* 请假类型名称
*/
leaveTypeName?: string;
/**
* 开始时间(年月日时分秒)
*/
startTime?: string;
/**
* 结束时间(年月日时分秒)
*/
endTime?: string;
/**
* 请假时长(天)
*/
leaveDuration?: number;
/**
* 是否离校:0-否,1-是
*/
isLeaveSchool?: string;
/**
* 是否需要销假:0-否,1-是
*/
needCancel?: string;
/**
* 紧急联系人
*/
emergencyContact?: string;
/**
* 紧急联系电话
*/
emergencyPhone?: string;
/**
* 请假原因
*/
leaveReason?: string;
/**
* 请假时地理位置
*/
leaveLocation?: string;
/**
* 附件OSS文件ID(逗号分隔)
*/
attachmentOssIds?: string | number;
/**
* 审批状态:"cancel", "已撤销" "draft", "草稿" "waiting", "待审核" "finish", "已完成" "invalid", "已作废" "back", "已退回" "termination", "已终止"
*/
approvalStatus?: string;
/**
* 审批意见
*/
approvalOpinion?: string;
/**
* 审批时间
*/
approvalTime?: string;
/**
* 审批人ID
*/
approvalBy?: number;
/**
* 审批人姓名
*/
approvalByName?: string;
/**
* 销假状态:0-未销假,1-已销假,2-逾期未销假 3 - 无需销假 "cancel", "已撤销" "draft", "草稿" "waiting", "待审核" "finish", "已完成" "invalid", "已作废" "back", "已退回" "termination", "已终止"
*/
cancelStatus?: string;
/**
* 销假时间
*/
cancelTime?: string;
/**
* 销假地理位置
*/
cancelLocation?: string;
/**
* 销假照片OSS文件ID(逗号分隔)
*/
cancelPhotoOssIds?: string | number;
/**
* 销假备注
*/
cancelRemark?: string;
/**
* 学生请假表id
*/
leaveId?: string | number;
/**
* 日期范围参数
*/
params?: any;
}
+27 -26
View File
@@ -386,31 +386,31 @@ const flowCodeOptions = [
{
value: 'hzdyjs-qj',
label: '学生请假流程-杭州第一技师'
},
{
value: 'leave1',
label: '请假申请-普通'
},
{
value: 'leave2',
label: '请假申请-排他网关'
},
{
value: 'leave3',
label: '请假申请-并行网关'
},
{
value: 'leave4',
label: '请假申请-会签'
},
{
value: 'leave5',
label: '请假申请-并行会签网关'
},
{
value: 'leave6',
label: '请假申请-排他并行会签'
}
// {
// value: 'leave1',
// label: '请假申请-普通'
// },
// {
// value: 'leave2',
// label: '请假申请-排他网关'
// },
// {
// value: 'leave3',
// label: '请假申请-并行网关'
// },
// {
// value: 'leave4',
// label: '请假申请-会签'
// },
// {
// value: 'leave5',
// label: '请假申请-并行会签网关'
// },
// {
// value: 'leave6',
// label: '请假申请-排他并行会签'
// }
];
// 上传相关配置
@@ -1418,7 +1418,8 @@ onMounted(() => {
/* 附件上传容器样式 */
.attachment-upload-container {
width: 100%;
max-height: 300px;
max-height: calc(100vh - 650px);
min-height: 200px;
overflow-y: auto;
padding-right: 8px;
border: 1px solid #e4e7ed;
@@ -1429,7 +1430,7 @@ onMounted(() => {
/* 附件上传区域内容样式 */
.attachment-upload-container .upload-demo {
padding: 12px;
min-height: 150px;
min-height: 180px;
}
.attachment-upload-container .upload-demo .el-upload {
+64 -11
View File
@@ -172,17 +172,17 @@
<el-table v-loading="loading" border :data="studentLeaveList" @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="id" v-if="false" />
<!-- <el-table-column label="删除标志" align="center" prop="deleted" /> -->
<!-- <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="classId" /> -->
<el-table-column label="班级名称" align="center" prop="className" />
<!-- <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="collegeId" /> -->
<el-table-column label="学院名称" align="center" prop="collegeName" />
<!-- <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="班级名称" align="center" prop="className" />
<el-table-column label="学生姓名" align="center" prop="studentName" />
<el-table-column label="学号" align="center" prop="studentNo" />
<!-- <el-table-column label="请假类型编码" align="center" prop="leaveTypeCode" /> -->
<el-table-column label="请假类型名称" align="center" prop="leaveTypeName" />
<el-table-column label="开始时间" align="center" prop="startTime" width="180">
@@ -210,12 +210,17 @@
<el-table-column label="紧急联系电话" align="center" prop="emergencyPhone" />
<el-table-column label="请假原因" align="center" prop="leaveReason" />
<!-- <el-table-column label="请假时地理位置" align="center" prop="leaveLocation" /> -->
<el-table-column label="附件OSS文件ID" align="center" prop="attachmentOssIds" width="280" />
<!-- <el-table-column label="附件OSS文件ID" align="center" prop="attachmentOssIds" width="280" /> -->
<el-table-column label="审批状态" align="center" prop="approvalStatus">
<template #default="scope">
<dict-tag :options="student_leave_approval_status" :value="scope.row.approvalStatus" />
</template>
</el-table-column>
<el-table-column label="销假状态" align="center" prop="cancelStatus">
<template #default="scope">
<dict-tag :options="xg_xsqj_cancel_status" :value="scope.row.cancelStatus" />
</template>
</el-table-column>
<!--<el-table-column label="审批意见" align="center" prop="approvalOpinion" />
<el-table-column label="审批时间" align="center" prop="approvalTime" width="180">
<template #default="scope">
@@ -233,12 +238,13 @@
<el-table-column label="销假地理位置" align="center" prop="cancelLocation" />
<el-table-column label="销假照片OSS文件ID" align="center" prop="cancelPhotoOssIds" />
<el-table-column label="销假备注" align="center" prop="cancelRemark" /> -->
<el-table-column label="操作" align="center" width="100px" class-name="small-padding fixed-width" fixed="right">
<el-table-column label="操作" align="center" width="150px" class-name="small-padding fixed-width" fixed="right">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['studentLeave:studentLeave:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<!-- 删除按钮:仅草稿状态可见 -->
<el-tooltip content="删除" placement="top" v-if="scope.row.approvalStatus === 'draft'">
<el-button
link
type="danger"
@@ -247,6 +253,16 @@
v-hasPermi="['studentLeave:studentLeave:remove']"
></el-button>
</el-tooltip>
<!-- 销假按钮:仅已完成状态且需要销假时可见 -->
<el-tooltip content="销假" placement="top" v-if="scope.row.approvalStatus === 'finish' && scope.row.needCancel === '1'">
<el-button
link
type="success"
icon="CircleCheck"
@click="handleCancelLeave(scope.row)"
v-hasPermi="['studentLeave:studentLeave:cancel']"
></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
@@ -282,7 +298,9 @@ interface PageData<T, Q> {
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// 加载字典数据
const { sys_yesno, student_leave_approval_status } = toRefs<any>(proxy?.useDict('sys_yesno', 'student_leave_approval_status'));
const { sys_yesno, student_leave_approval_status, xg_xsqj_cancel_status } = toRefs<any>(
proxy?.useDict('sys_yesno', 'student_leave_approval_status', 'xg_xsqj_cancel_status')
);
const studentLeaveList = ref<StudentLeaveVO[]>([]);
const buttonLoading = ref(false);
@@ -500,6 +518,41 @@ const handleDelete = async (row?: StudentLeaveVO) => {
await getList();
};
/** 销假按钮操作 */
const handleCancelLeave = async (row: StudentLeaveVO) => {
await proxy?.$modal.confirm('是否确认销假学生请假申请?').finally(() => (loading.value = false));
// TODO: 调用销假API
// await cancelStudentLeave(row.id);
// reset();
const _id = row?.id || ids.value[0];
// 根据销假状态设置type参数
// 当销假状态cancel_status = '0' 或者 '3'时,type = 'add',其他都是 'update'
const type = row.cancelStatus === '0' || row.cancelStatus === '3' ? 'add' : 'update';
// const res = await getStudentLeave(_id);
// Object.assign(form.value, res.data);
// // 传递type参数,标识为修改操作
// form.value.type = 'update';
// form.value.id = _id;
// dialog.visible = true;
// dialog.title = '修改学生请假';
// proxy.$tab.closePage(proxy.$route);
console.log('type:', type);
proxy.$router.push({
path: `/xg/xsjcxx/xsqj/cancelLeaveEdit/index`,
query: {
id: _id,
type: type
}
});
// proxy?.$modal.msgSuccess('销假成功');
// await getList();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
File diff suppressed because it is too large. Load diff