“班主任0820考核数据更新”

This commit is contained in:
weizhong committed 2025-08-20 16:04:40 +08:00
1 parent ea739d328b
commit 166c850356
33 files changed
+3999 -127

No files matched your search

@@ -0,0 +1,146 @@
package org.dromara.bzrkh.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
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.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.log.enums.BusinessType;
import org.dromara.bzrkh.domain.vo.AssessmentApprovalVo;
import org.dromara.bzrkh.domain.vo.AssessmentApprovalDetailVo;
import org.dromara.bzrkh.domain.vo.SchemeOptionVo;
import org.dromara.bzrkh.domain.bo.AssessmentApprovalQueryBo;
import org.dromara.bzrkh.domain.bo.AssessmentApprovalSubmitBo;
import org.dromara.bzrkh.domain.bo.BatchApprovalBo;
import org.dromara.bzrkh.service.IAssessmentApprovalService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.excel.utils.ExcelUtil;
import jakarta.servlet.http.HttpServletResponse;
/**
* 班主任考核审核Controller
*
* @author ruoyi
* @date 2025-01-28
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/bzrkh/assessmentApproval")
public class AssessmentApprovalController extends BaseController {
private final IAssessmentApprovalService assessmentApprovalService;
/**
* 查询班主任考核审核列表
*/
@SaCheckPermission("bzrkh:assessmentApproval:list")
@GetMapping("/list")
public TableDataInfo<AssessmentApprovalVo> list(AssessmentApprovalQueryBo bo, PageQuery pageQuery) {
return assessmentApprovalService.queryPageList(bo, pageQuery);
}
/**
* 获取考核审核详情
*/
@SaCheckPermission("bzrkh:assessmentApproval:query")
@GetMapping("/detail")
public R<AssessmentApprovalDetailVo> getApprovalDetail(
@RequestParam @NotNull(message = "计划ID不能为空") Long planId,
@RequestParam @NotNull(message = "班级ID不能为空") Long classId,
@RequestParam @NotNull(message = "被评价用户ID不能为空") Long evaluatedUserId) {
AssessmentApprovalDetailVo detail = assessmentApprovalService.getApprovalDetail(planId, classId, evaluatedUserId);
return R.ok(detail);
}
/**
* 提交考核审核
*/
@SaCheckPermission("bzrkh:assessmentApproval:approve")
@Log(title = "班主任考核审核", businessType = BusinessType.UPDATE)
@PostMapping("/submit")
public R<Void> submitApproval(@RequestBody @Validated AssessmentApprovalSubmitBo bo) {
Long approverUserId = LoginHelper.getUserId();
boolean result = assessmentApprovalService.submitApproval(bo, approverUserId);
return toAjax(result);
}
/**
* 批量审核通过
*/
@SaCheckPermission("bzrkh:assessmentApproval:approve")
@Log(title = "班主任考核审核", businessType = BusinessType.UPDATE)
@PostMapping("/batchApprove")
public R<Void> batchApprove(@RequestBody BatchApprovalBo bo) {
Long approverUserId = LoginHelper.getUserId();
boolean result = assessmentApprovalService.batchApprove(bo.getIds(), approverUserId);
return toAjax(result);
}
/**
* 批量审核拒绝
*/
@SaCheckPermission("bzrkh:assessmentApproval:approve")
@Log(title = "班主任考核审核", businessType = BusinessType.UPDATE)
@PostMapping("/batchReject")
public R<Void> batchReject(@RequestBody BatchRejectBo bo) {
Long approverUserId = LoginHelper.getUserId();
boolean result = assessmentApprovalService.batchReject(bo.getIds(), bo.getRejectReason(), approverUserId);
return toAjax(result);
}
/**
* 获取考核方案下拉选项
*/
@SaCheckPermission("bzrkh:assessmentApproval:list")
@GetMapping("/schemeOptions")
public R<List<SchemeOptionVo>> getSchemeOptions() {
List<SchemeOptionVo> options = assessmentApprovalService.getSchemeOptions();
return R.ok(options);
}
/**
* 导出班主任考核审核数据
*/
@SaCheckPermission("bzrkh:assessmentApproval:export")
@Log(title = "班主任考核审核", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(AssessmentApprovalQueryBo bo, HttpServletResponse response) {
List<AssessmentApprovalVo> list = assessmentApprovalService.queryList(bo);
ExcelUtil.exportExcel(list, "班主任考核审核数据", AssessmentApprovalVo.class, response);
}
/**
* 批量拒绝请求对象
*/
public static class BatchRejectBo {
@NotEmpty(message = "审核ID列表不能为空")
private List<Long> ids;
@NotBlank(message = "拒绝原因不能为空")
private String rejectReason;
public List<Long> getIds() {
return ids;
}
public void setIds(List<Long> ids) {
this.ids = ids;
}
public String getRejectReason() {
return rejectReason;
}
public void setRejectReason(String rejectReason) {
this.rejectReason = rejectReason;
}
}
}
@@ -73,6 +73,18 @@ public class TeacherAssessmentController extends BaseController {
return toAjax(result);
}
/**
* 撤销考核提交
*/
@SaCheckPermission("bzrkh:teacherAssessment:withdraw")
@Log(title = "班主任考核管理", businessType = BusinessType.UPDATE)
@PostMapping("/withdraw")
public R<Void> withdrawAssessment(@RequestBody TeacherAssessmentSubmitRequest request) {
Long teacherId = LoginHelper.getUserId();
boolean result = teacherAssessmentService.withdrawAssessment(request.getPlanId(), request.getClassId(), teacherId);
return toAjax(result);
}
/**
* 查看考核详情
*/
@@ -0,0 +1,35 @@
package org.dromara.bzrkh.domain.bo;
import lombok.Data;
import java.math.BigDecimal;
/**
* 指标审核提交业务对象
*
* @author ruoyi
* @date 2025-01-28
*/
@Data
public class AssessmentApprovalIndicatorSubmitBo {
/**
* 主键ID
*/
private Long id;
/**
* 指标ID
*/
private Long indicatorId;
/**
* 上级评分数
*/
private BigDecimal superiorScore;
/**
* 上级评意见
*/
private String superiorComment;
}
@@ -0,0 +1,56 @@
package org.dromara.bzrkh.domain.bo;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 班主任考核审核查询对象
*
* @author ruoyi
* @date 2025-01-28
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class AssessmentApprovalQueryBo extends BaseEntity {
/**
* 计划名称
*/
private String planName;
/**
* 考核方案名称
*/
private String schemeName;
/**
* 审核状态(0=待审核 1=审核通过 2=审核不通过)
*/
private String auditStatus;
/**
* 班级名称
*/
private String className;
/**
* 班主任姓名
*/
private String teacherName;
/**
* 被评价用户姓名
*/
private String evaluatedUserName;
/**
* 学年
*/
private String academicYear;
/**
* 学期
*/
private String semester;
}
@@ -0,0 +1,35 @@
package org.dromara.bzrkh.domain.bo;
import lombok.Data;
import java.math.BigDecimal;
/**
* 特色工作审核提交业务对象
*
* @author ruoyi
* @date 2025-01-28
*/
@Data
public class AssessmentApprovalSpecialWorkSubmitBo {
/**
* 主键ID
*/
private Long id;
/**
* 指标编码
*/
private String indicatorCode;
/**
* 上级评分数
*/
private BigDecimal superiorScore;
/**
* 上级评意见
*/
private String superiorComment;
}
@@ -0,0 +1,70 @@
package org.dromara.bzrkh.domain.bo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import jakarta.validation.constraints.NotNull;
import java.util.List;
/**
* 考核审核提交业务对象
*
* @author ruoyi
* @date 2025-01-28
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class AssessmentApprovalSubmitBo extends BaseEntity {
/**
* 考核计划ID
*/
@NotNull(message = "考核计划ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long planId;
/**
* 班级ID
*/
@NotNull(message = "班级ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long classId;
/**
* 被评价用户ID
*/
@NotNull(message = "被评价用户ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long evaluatedUserId;
/**
* 班主任常规工作审核数据
*/
private List<AssessmentApprovalIndicatorSubmitBo> routineWorkApproval;
/**
* 班级管理实效审核数据
*/
private AssessmentApprovalIndicatorSubmitBo classDeductionApproval;
/**
* 特色工作审核数据
*/
private List<AssessmentApprovalSpecialWorkSubmitBo> specialWorkApproval;
/**
* 上级总体评价
*/
private String superiorOverallComment;
/**
* 审核状态 0=待审核 1=审核通过 2=审核不通过
*/
@NotNull(message = "审核状态不能为空", groups = { AddGroup.class, EditGroup.class })
private String auditStatus;
/**
* 审核意见
*/
private String auditComment;
}
@@ -0,0 +1,22 @@
package org.dromara.bzrkh.domain.bo;
import lombok.Data;
import jakarta.validation.constraints.NotEmpty;
import java.util.List;
/**
* 批量审核业务对象
*
* @author ruoyi
* @date 2025-01-28
*/
@Data
public class BatchApprovalBo {
/**
* 审核ID列表
*/
@NotEmpty(message = "审核ID列表不能为空")
private List<Long> ids;
}
@@ -0,0 +1,111 @@
package org.dromara.bzrkh.domain.vo;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* 考核审核详情视图对象
*
* @author ruoyi
* @date 2025-01-28
*/
@Data
public class AssessmentApprovalDetailVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Long id;
/**
* 考核计划ID
*/
private Long planId;
/**
* 班级ID
*/
private Long classId;
/**
* 班级详细信息
*/
private ClassDetailVo classDetail;
/**
* 系数信息
*/
private CoefficientVo coefficient;
/**
* 班主任常规工作指标列表 - 包含自评和上级评分
*/
private List<AssessmentApprovalIndicatorVo> routineWorkIndicators;
/**
* 班级扣分指标 - 班级管理实效
*/
private AssessmentApprovalIndicatorVo classDeductionIndicator;
/**
* 特色工作指标列表
*/
private List<AssessmentApprovalSpecialWorkVo> specialWorkIndicators;
/**
* 自我总体评价
*/
private String selfOverallComment;
/**
* 上级总体评价
*/
private String superiorOverallComment;
/**
* 月考核得分
*/
private BigDecimal monthlyScore;
/**
* 审核状态
*/
private String auditStatus;
/**
* 提交时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date submitTime;
/**
* 创建者
*/
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;
}
@@ -0,0 +1,82 @@
package org.dromara.bzrkh.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 审核指标视图对象 - 包含自评和上级评分
*
* @author ruoyi
* @date 2025-01-28
*/
@Data
public class AssessmentApprovalIndicatorVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Long id;
/**
* 指标ID
*/
private Long indicatorId;
/**
* 指标名称
*/
private String indicatorName;
/**
* 指标编码
*/
private String indicatorCode;
/**
* 指标描述
*/
private String description;
/**
* 指标分值
*/
private BigDecimal score;
/**
* 最高分值
*/
private BigDecimal maxScore;
// 自评相关
/**
* 自评分数
*/
private BigDecimal selfScore;
/**
* 自评意见
*/
private String selfComment;
// 上级评相关
/**
* 上级评分数
*/
private BigDecimal superiorScore;
/**
* 上级评意见
*/
private String superiorComment;
/**
* 审核状态
*/
private String auditStatus;
}
@@ -0,0 +1,62 @@
package org.dromara.bzrkh.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 特色工作审核视图对象
*
* @author ruoyi
* @date 2025-01-28
*/
@Data
public class AssessmentApprovalSpecialWorkVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
private Long id;
/**
* 指标编码
*/
private String indicatorCode;
/**
* 指标名称
*/
private String indicatorName;
// 自评相关
/**
* 自评分数
*/
private BigDecimal score;
/**
* 自评意见
*/
private String selfComment;
// 上级评相关
/**
* 上级评分数
*/
private BigDecimal superiorScore;
/**
* 上级评意见
*/
private String superiorComment;
/**
* 审核状态
*/
private String auditStatus;
}
@@ -0,0 +1,163 @@
package org.dromara.bzrkh.domain.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 班主任考核审核视图对象
*
* @author ruoyi
* @date 2025-01-28
*/
@Data
@ExcelIgnoreUnannotated
public class AssessmentApprovalVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long id;
/**
* 考核计划ID
*/
private Long planId;
/**
* 考核计划名称
*/
@ExcelProperty(value = "计划名称")
private String planName;
/**
* 考核计划编码
*/
@ExcelProperty(value = "计划编码")
private String planCode;
/**
* 考核方案ID
*/
private Long schemeId;
/**
* 考核方案名称
*/
@ExcelProperty(value = "考核方案")
private String schemeName;
/**
* 学年
*/
@ExcelProperty(value = "学年")
private String academicYear;
/**
* 学期
*/
@ExcelProperty(value = "学期")
private String semester;
/**
* 班级ID
*/
private Long classId;
/**
* 班级名称
*/
@ExcelProperty(value = "班级名称")
private String className;
/**
* 班主任用户ID
*/
private Long teacherId;
/**
* 班主任姓名
*/
@ExcelProperty(value = "班主任姓名")
private String teacherName;
/**
* 被评价用户ID
*/
private Long evaluatedUserId;
/**
* 被评价用户姓名
*/
@ExcelProperty(value = "被评价用户姓名")
private String evaluatedUserName;
/**
* 提交时间
*/
@ExcelProperty(value = "提交时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date submitTime;
/**
* 审核状态(0=待审核 1=审核通过 2=审核不通过)
*/
@ExcelProperty(value = "审核状态")
private String auditStatus;
/**
* 审核状态文本
*/
private String auditStatusText;
/**
* 自评总分
*/
@ExcelProperty(value = "自评总分")
private BigDecimal selfScore;
/**
* 上级评总分
*/
@ExcelProperty(value = "上级评总分")
private BigDecimal superiorScore;
/**
* 最终得分
*/
@ExcelProperty(value = "最终得分")
private BigDecimal finalScore;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 创建者
*/
private Long createBy;
/**
* 更新时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/**
* 更新者
*/
private Long updateBy;
}
@@ -65,6 +65,11 @@ public class AssessmentIndicatorScoreVo implements Serializable {
*/
private Integer sortOrder;
/**
* 审核状态(0=待审核,1=审核通过,2=审核不通过)
*/
private String auditStatus;
/**
* 创建者
*/
@@ -150,4 +150,21 @@ public class BmzrAssessmentPlanVo implements Serializable {
* 删除标志(0代表存在 1代表删除)
*/
private String deleted;
/**
* 审核状态(null=未提交,0=已提交待审核,1=审核通过,2=审核不通过)
*/
@ExcelProperty(value = "审核状态")
private String auditStatus;
/**
* 提交时间
*/
@ExcelProperty(value = "提交时间")
private Date submitTime;
/**
* 是否已提交(用于前端按钮状态控制)
*/
private Boolean submitted;
}
@@ -0,0 +1,39 @@
package org.dromara.bzrkh.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 考核方案选项视图对象
*
* @author ruoyi
* @date 2025-01-28
*/
@Data
public class SchemeOptionVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 选项值
*/
private String value;
/**
* 选项标签
*/
private String label;
/**
* 方案ID
*/
private Long schemeId;
/**
* 方案编码
*/
private String schemeCode;
}
@@ -0,0 +1,133 @@
package org.dromara.bzrkh.mapper;
import org.dromara.bzrkh.domain.vo.AssessmentApprovalVo;
import org.dromara.bzrkh.domain.vo.AssessmentApprovalDetailVo;
import org.dromara.bzrkh.domain.vo.AssessmentApprovalIndicatorVo;
import org.dromara.bzrkh.domain.vo.AssessmentApprovalSpecialWorkVo;
import org.dromara.bzrkh.domain.vo.SchemeOptionVo;
import org.dromara.bzrkh.domain.bo.AssessmentApprovalQueryBo;
import org.dromara.bzrkh.domain.BmzrAssessmentScore;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 班主任考核审核Mapper接口
*
* @author ruoyi
* @date 2025-01-28
*/
public interface AssessmentApprovalMapper extends BaseMapperPlus<BmzrAssessmentScore, AssessmentApprovalVo> {
/**
* 查询班主任考核审核列表
*
* @param bo 查询条件
* @return 班主任考核审核列表
*/
List<AssessmentApprovalVo> queryList(AssessmentApprovalQueryBo bo);
/**
* 获取考核审核基本信息
*
* @param planId 计划ID
* @param classId 班级ID
* @param evaluatedUserId 被评价用户ID
* @return 审核基本信息
*/
AssessmentApprovalDetailVo getApprovalBasicInfo(@Param("planId") Long planId,
@Param("classId") Long classId,
@Param("evaluatedUserId") Long evaluatedUserId);
/**
* 获取班主任常规工作指标列表
*
* @param planId 计划ID
* @param classId 班级ID
* @param evaluatedUserId 被评价用户ID
* @return 常规工作指标列表
*/
List<AssessmentApprovalIndicatorVo> getRoutineWorkIndicators(@Param("planId") Long planId,
@Param("classId") Long classId,
@Param("evaluatedUserId") Long evaluatedUserId);
/**
* 获取班级扣分指标(班级管理实效)
*
* @param planId 计划ID
* @param classId 班级ID
* @param evaluatedUserId 被评价用户ID
* @return 班级扣分指标
*/
AssessmentApprovalIndicatorVo getClassDeductionIndicator(@Param("planId") Long planId,
@Param("classId") Long classId,
@Param("evaluatedUserId") Long evaluatedUserId);
/**
* 获取特色工作指标列表
*
* @param planId 计划ID
* @param classId 班级ID
* @param evaluatedUserId 被评价用户ID
* @return 特色工作指标列表
*/
List<AssessmentApprovalSpecialWorkVo> getSpecialWorkIndicators(@Param("planId") Long planId,
@Param("classId") Long classId,
@Param("evaluatedUserId") Long evaluatedUserId);
/**
* 更新上级评分和意见
*
* @param id 分数记录ID
* @param superiorScore 上级评分
* @param superiorComment 上级评意见
* @param approverUserId 审核人用户ID
* @return 更新条数
*/
int updateSuperiorScore(@Param("id") Long id,
@Param("superiorScore") String superiorScore,
@Param("superiorComment") String superiorComment,
@Param("approverUserId") Long approverUserId);
/**
* 更新审核状态和意见
*
* @param planId 计划ID
* @param classId 班级ID
* @param evaluatedUserId 被评价用户ID
* @param auditStatus 审核状态
* @param auditComment 审核意见
* @param superiorOverallComment 上级总体评价
* @param approverUserId 审核人用户ID
* @return 更新条数
*/
int updateAuditStatus(@Param("planId") Long planId,
@Param("classId") Long classId,
@Param("evaluatedUserId") Long evaluatedUserId,
@Param("auditStatus") String auditStatus,
@Param("auditComment") String auditComment,
@Param("superiorOverallComment") String superiorOverallComment,
@Param("approverUserId") Long approverUserId);
/**
* 批量更新审核状态
*
* @param ids 审核ID列表
* @param auditStatus 审核状态
* @param auditComment 审核意见
* @param approverUserId 审核人用户ID
* @return 更新条数
*/
int batchUpdateAuditStatus(@Param("ids") List<Long> ids,
@Param("auditStatus") String auditStatus,
@Param("auditComment") String auditComment,
@Param("approverUserId") Long approverUserId);
/**
* 获取考核方案下拉选项
*
* @return 方案选项列表
*/
List<SchemeOptionVo> getSchemeOptions();
}
@@ -0,0 +1,82 @@
package org.dromara.bzrkh.service;
import org.dromara.bzrkh.domain.vo.AssessmentApprovalVo;
import org.dromara.bzrkh.domain.vo.AssessmentApprovalDetailVo;
import org.dromara.bzrkh.domain.vo.SchemeOptionVo;
import org.dromara.bzrkh.domain.bo.AssessmentApprovalQueryBo;
import org.dromara.bzrkh.domain.bo.AssessmentApprovalSubmitBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.List;
/**
* 班主任考核审核Service接口
*
* @author ruoyi
* @date 2025-01-28
*/
public interface IAssessmentApprovalService {
/**
* 查询班主任考核审核列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 班主任考核审核列表
*/
TableDataInfo<AssessmentApprovalVo> queryPageList(AssessmentApprovalQueryBo bo, PageQuery pageQuery);
/**
* 查询班主任考核审核列表
*
* @param bo 查询条件
* @return 班主任考核审核列表
*/
List<AssessmentApprovalVo> queryList(AssessmentApprovalQueryBo bo);
/**
* 获取考核审核详情
*
* @param planId 计划ID
* @param classId 班级ID
* @param evaluatedUserId 被评价用户ID
* @return 审核详情
*/
AssessmentApprovalDetailVo getApprovalDetail(Long planId, Long classId, Long evaluatedUserId);
/**
* 提交考核审核
*
* @param bo 审核数据
* @param approverUserId 审核人用户ID
* @return 是否成功
*/
boolean submitApproval(AssessmentApprovalSubmitBo bo, Long approverUserId);
/**
* 批量审核通过
*
* @param ids 审核ID列表
* @param approverUserId 审核人用户ID
* @return 是否成功
*/
boolean batchApprove(List<Long> ids, Long approverUserId);
/**
* 批量审核拒绝
*
* @param ids 审核ID列表
* @param rejectReason 拒绝原因
* @param approverUserId 审核人用户ID
* @return 是否成功
*/
boolean batchReject(List<Long> ids, String rejectReason, Long approverUserId);
/**
* 获取考核方案下拉选项
*
* @return 方案选项列表
*/
List<SchemeOptionVo> getSchemeOptions();
}
@@ -75,6 +75,16 @@ public interface ITeacherAssessmentService {
*/
boolean submitAssessmentScore(AssessmentSubmitBo bo, Long teacherId);
/**
* 撤销考核提交
*
* @param planId 计划ID
* @param classId 班级ID
* @param teacherId 班主任ID
* @return 是否成功
*/
boolean withdrawAssessment(Long planId, Long classId, Long teacherId);
/**
* 测试人数系数计算(临时调试方法)
* 用于验证特定人数的系数计算是否正确
@@ -0,0 +1,213 @@
package org.dromara.bzrkh.service.impl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
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 org.dromara.common.core.utils.MapstructUtils;
import org.dromara.bzrkh.domain.vo.AssessmentApprovalVo;
import org.dromara.bzrkh.domain.vo.AssessmentApprovalDetailVo;
import org.dromara.bzrkh.domain.vo.AssessmentApprovalIndicatorVo;
import org.dromara.bzrkh.domain.vo.AssessmentApprovalSpecialWorkVo;
import org.dromara.bzrkh.domain.vo.SchemeOptionVo;
import org.dromara.bzrkh.domain.vo.ClassDetailVo;
import org.dromara.bzrkh.domain.vo.CoefficientVo;
import org.dromara.bzrkh.domain.bo.AssessmentApprovalQueryBo;
import org.dromara.bzrkh.domain.bo.AssessmentApprovalSubmitBo;
import org.dromara.bzrkh.domain.bo.AssessmentApprovalIndicatorSubmitBo;
import org.dromara.bzrkh.domain.bo.AssessmentApprovalSpecialWorkSubmitBo;
import org.dromara.bzrkh.mapper.AssessmentApprovalMapper;
import org.dromara.bzrkh.service.IAssessmentApprovalService;
import org.dromara.bzrkh.service.ITeacherAssessmentService;
import java.util.List;
import java.util.Date;
/**
* 班主任考核审核Service业务层处理
*
* @author ruoyi
* @date 2025-01-28
*/
@RequiredArgsConstructor
@Service
public class AssessmentApprovalServiceImpl implements IAssessmentApprovalService {
private final AssessmentApprovalMapper assessmentApprovalMapper;
private final ITeacherAssessmentService teacherAssessmentService;
@Override
public TableDataInfo<AssessmentApprovalVo> queryPageList(AssessmentApprovalQueryBo bo, PageQuery pageQuery) {
Page<AssessmentApprovalVo> page = pageQuery.build();
List<AssessmentApprovalVo> list = assessmentApprovalMapper.queryList(bo);
// 手动分页处理
int total = list.size();
int start = (int) ((page.getCurrent() - 1) * page.getSize());
int end = Math.min(start + (int) page.getSize(), total);
List<AssessmentApprovalVo> pageList = list.subList(start, end);
page.setRecords(pageList);
page.setTotal(total);
return TableDataInfo.build(page);
}
@Override
public List<AssessmentApprovalVo> queryList(AssessmentApprovalQueryBo bo) {
return assessmentApprovalMapper.queryList(bo);
}
@Override
public AssessmentApprovalDetailVo getApprovalDetail(Long planId, Long classId, Long evaluatedUserId) {
// 1. 获取基本信息
AssessmentApprovalDetailVo detail = assessmentApprovalMapper.getApprovalBasicInfo(planId, classId, evaluatedUserId);
if (detail == null) {
throw new RuntimeException("未找到考核审核数据");
}
// 2. 获取班级详细信息和系数信息(复用现有service)
try {
// 使用现有的获取考核详情方法来获取班级信息和系数
var assessmentDetail = teacherAssessmentService.getAssessmentSubmitDetail(planId, classId, evaluatedUserId);
ClassDetailVo classDetail = new ClassDetailVo();
classDetail.setId(assessmentDetail.getClassDetail().getId());
classDetail.setClassName(assessmentDetail.getClassDetail().getClassName());
classDetail.setCollegeName(assessmentDetail.getClassDetail().getCollegeName());
classDetail.setMajorName(assessmentDetail.getClassDetail().getMajorName());
classDetail.setClassType(assessmentDetail.getClassDetail().getClassType());
classDetail.setTotalStudentCount(assessmentDetail.getClassDetail().getTotalStudentCount());
classDetail.setBoardingStudentCount(assessmentDetail.getClassDetail().getBoardingStudentCount());
detail.setClassDetail(classDetail);
CoefficientVo coefficient = new CoefficientVo();
coefficient.setTotalCoefficient(assessmentDetail.getCoefficient().getTotalCoefficient());
coefficient.setLevelCoefficient(assessmentDetail.getCoefficient().getLevelCoefficient());
coefficient.setStudentCountCoefficient(assessmentDetail.getCoefficient().getStudentCountCoefficient());
coefficient.setBoardingCoefficient(assessmentDetail.getCoefficient().getBoardingCoefficient());
detail.setCoefficient(coefficient);
} catch (Exception e) {
// 如果获取失败,使用默认值
detail.setClassDetail(new ClassDetailVo());
detail.setCoefficient(new CoefficientVo());
}
// 3. 获取班主任常规工作指标列表
List<AssessmentApprovalIndicatorVo> routineWorkIndicators =
assessmentApprovalMapper.getRoutineWorkIndicators(planId, classId, evaluatedUserId);
detail.setRoutineWorkIndicators(routineWorkIndicators);
// 4. 获取班级扣分指标(班级管理实效)
AssessmentApprovalIndicatorVo classDeductionIndicator =
assessmentApprovalMapper.getClassDeductionIndicator(planId, classId, evaluatedUserId);
detail.setClassDeductionIndicator(classDeductionIndicator);
// 5. 获取特色工作指标列表
List<AssessmentApprovalSpecialWorkVo> specialWorkIndicators =
assessmentApprovalMapper.getSpecialWorkIndicators(planId, classId, evaluatedUserId);
detail.setSpecialWorkIndicators(specialWorkIndicators);
return detail;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean submitApproval(AssessmentApprovalSubmitBo bo, Long approverUserId) {
try {
// 1. 更新班主任常规工作指标的上级评分和意见
if (bo.getRoutineWorkApproval() != null) {
for (AssessmentApprovalIndicatorSubmitBo indicator : bo.getRoutineWorkApproval()) {
if (indicator.getId() != null) {
assessmentApprovalMapper.updateSuperiorScore(
indicator.getId(),
indicator.getSuperiorScore() != null ? indicator.getSuperiorScore().toString() : null,
indicator.getSuperiorComment(),
approverUserId
);
}
}
}
// 2. 更新班级管理实效的上级评分和意见
if (bo.getClassDeductionApproval() != null && bo.getClassDeductionApproval().getId() != null) {
assessmentApprovalMapper.updateSuperiorScore(
bo.getClassDeductionApproval().getId(),
bo.getClassDeductionApproval().getSuperiorScore() != null ?
bo.getClassDeductionApproval().getSuperiorScore().toString() : null,
bo.getClassDeductionApproval().getSuperiorComment(),
approverUserId
);
}
// 3. 更新特色工作指标的上级评分和意见
if (bo.getSpecialWorkApproval() != null) {
for (AssessmentApprovalSpecialWorkSubmitBo specialWork : bo.getSpecialWorkApproval()) {
if (specialWork.getId() != null) {
assessmentApprovalMapper.updateSuperiorScore(
specialWork.getId(),
specialWork.getSuperiorScore() != null ? specialWork.getSuperiorScore().toString() : null,
specialWork.getSuperiorComment(),
approverUserId
);
}
}
}
// 4. 更新审核状态和总体评价
int result = assessmentApprovalMapper.updateAuditStatus(
bo.getPlanId(),
bo.getClassId(),
bo.getEvaluatedUserId(),
bo.getAuditStatus(),
bo.getAuditComment(),
bo.getSuperiorOverallComment(),
approverUserId
);
return result > 0;
} catch (Exception e) {
throw new RuntimeException("提交审核失败: " + e.getMessage(), e);
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean batchApprove(List<Long> ids, Long approverUserId) {
try {
int result = assessmentApprovalMapper.batchUpdateAuditStatus(
ids,
"1", // 审核通过
"批量审核通过",
approverUserId
);
return result > 0;
} catch (Exception e) {
throw new RuntimeException("批量审核通过失败: " + e.getMessage(), e);
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean batchReject(List<Long> ids, String rejectReason, Long approverUserId) {
try {
int result = assessmentApprovalMapper.batchUpdateAuditStatus(
ids,
"2", // 审核不通过
rejectReason,
approverUserId
);
return result > 0;
} catch (Exception e) {
throw new RuntimeException("批量审核拒绝失败: " + e.getMessage(), e);
}
}
@Override
public List<SchemeOptionVo> getSchemeOptions() {
return assessmentApprovalMapper.getSchemeOptions();
}
}
@@ -379,6 +379,42 @@ public class TeacherAssessmentServiceImpl implements ITeacherAssessmentService {
return result;
}
/**
* 撤销考核提交
*
* @param planId 计划ID
* @param classId 班级ID
* @param teacherId 班主任ID
* @return 是否成功
*/
@Override
public boolean withdrawAssessment(Long planId, Long classId, Long teacherId) {
try {
// 验证是否有权限撤销(只能撤销自己提交的且状态为待审核的考核)
List<AssessmentIndicatorScoreVo> savedScores = teacherAssessmentMapper.selectSavedAssessmentScores(planId, teacherId);
if (savedScores == null || savedScores.isEmpty()) {
log.warn("未找到可撤销的考核提交记录,计划ID: {}, 教师ID: {}", planId, teacherId);
return false;
}
// 检查审核状态,只有待审核状态("0")的才能撤销
boolean canWithdraw = savedScores.stream().anyMatch(score -> "0".equals(score.getAuditStatus()));
if (!canWithdraw) {
log.warn("考核已审核,无法撤销,计划ID: {}, 教师ID: {}", planId, teacherId);
return false;
}
// 逻辑删除该计划下该教师的所有评分数据
teacherAssessmentMapper.deleteAssessmentScoresByPlanAndTeacher(planId, teacherId);
log.info("成功撤销考核提交,计划ID: {}, 教师ID: {}", planId, teacherId);
return true;
} catch (Exception e) {
log.error("撤销考核提交失败,计划ID: {}, 教师ID: {}", planId, teacherId, e);
return false;
}
}
/**
* 测试人数系数计算(临时调试方法)
* 可以通过调用这个方法来验证具体人数的系数计算
@@ -0,0 +1,293 @@
<?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.bzrkh.mapper.AssessmentApprovalMapper">
<!-- 审核列表结果映射 -->
<resultMap type="org.dromara.bzrkh.domain.vo.AssessmentApprovalVo" id="AssessmentApprovalVoResult">
<result property="id" column="id"/>
<result property="planId" column="plan_id"/>
<result property="planName" column="plan_name"/>
<result property="planCode" column="plan_code"/>
<result property="schemeId" column="scheme_id"/>
<result property="schemeName" column="scheme_name"/>
<result property="academicYear" column="academic_year"/>
<result property="semester" column="semester"/>
<result property="classId" column="class_id"/>
<result property="className" column="class_name"/>
<result property="teacherId" column="teacher_id"/>
<result property="teacherName" column="teacher_name"/>
<result property="evaluatedUserId" column="evaluated_user_id"/>
<result property="evaluatedUserName" column="evaluated_user_name"/>
<result property="submitTime" column="submit_time"/>
<result property="auditStatus" column="audit_status"/>
<result property="selfScore" column="self_score"/>
<result property="superiorScore" column="superior_score"/>
<result property="finalScore" column="final_score"/>
<result property="createTime" column="create_time"/>
<result property="createBy" column="create_by"/>
<result property="updateTime" column="update_time"/>
<result property="updateBy" column="update_by"/>
</resultMap>
<!-- 审核详情结果映射 -->
<resultMap type="org.dromara.bzrkh.domain.vo.AssessmentApprovalDetailVo" id="AssessmentApprovalDetailVoResult">
<result property="id" column="id"/>
<result property="planId" column="plan_id"/>
<result property="classId" column="class_id"/>
<result property="selfOverallComment" column="self_overall_comment"/>
<result property="superiorOverallComment" column="superior_overall_comment"/>
<result property="auditStatus" column="audit_status"/>
<result property="submitTime" column="submit_time"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
</resultMap>
<!-- 审核指标结果映射 -->
<resultMap type="org.dromara.bzrkh.domain.vo.AssessmentApprovalIndicatorVo" id="AssessmentApprovalIndicatorVoResult">
<result property="id" column="id"/>
<result property="indicatorId" column="indicator_id"/>
<result property="indicatorName" column="indicator_name"/>
<result property="indicatorCode" column="indicator_code"/>
<result property="description" column="description"/>
<result property="score" column="score"/>
<result property="maxScore" column="max_score"/>
<result property="selfScore" column="self_score"/>
<result property="selfComment" column="self_comment"/>
<result property="superiorScore" column="superior_score"/>
<result property="superiorComment" column="superior_comment"/>
<result property="auditStatus" column="audit_status"/>
</resultMap>
<!-- 特色工作审核结果映射 -->
<resultMap type="org.dromara.bzrkh.domain.vo.AssessmentApprovalSpecialWorkVo" id="AssessmentApprovalSpecialWorkVoResult">
<result property="id" column="id"/>
<result property="indicatorCode" column="indicator_code"/>
<result property="indicatorName" column="indicator_name"/>
<result property="score" column="score"/>
<result property="selfComment" column="self_comment"/>
<result property="superiorScore" column="superior_score"/>
<result property="superiorComment" column="superior_comment"/>
<result property="auditStatus" column="audit_status"/>
</resultMap>
<!-- 方案选项结果映射 -->
<resultMap type="org.dromara.bzrkh.domain.vo.SchemeOptionVo" id="SchemeOptionVoResult">
<result property="value" column="scheme_name"/>
<result property="label" column="scheme_name"/>
<result property="schemeId" column="id"/>
<result property="schemeCode" column="scheme_code"/>
</resultMap>
<!-- 查询班主任考核审核列表 -->
<select id="queryList" parameterType="org.dromara.bzrkh.domain.bo.AssessmentApprovalQueryBo" resultMap="AssessmentApprovalVoResult">
SELECT
MIN(s.id) as id,
s.plan_id,
p.plan_name,
p.plan_code,
s.scheme_id,
sch.scheme_name,
p.academic_year,
p.semester,
s.class_id,
c.class_name,
c.class_teacher_id as teacher_id,
c.class_teacher_name as teacher_name,
s.evaluated_user_id,
s.evaluated_user_name,
MAX(s.submit_time) as submit_time,
MAX(s.audit_status) as audit_status,
SUM(s.self_score) as self_score,
SUM(s.superior_score) as superior_score,
SUM(s.final_score) as final_score,
MAX(s.create_time) as create_time,
MAX(s.create_by) as create_by,
MAX(s.update_time) as update_time,
MAX(s.update_by) as update_by
FROM bmzr_assessment_score s
LEFT JOIN bmzr_assessment_plan p ON s.plan_id = p.id AND p.deleted = 0
LEFT JOIN bmzr_assessment_scheme sch ON s.scheme_id = sch.id AND sch.deleted = 0
LEFT JOIN xg_class_msg c ON s.class_id = c.id AND c.deleted = 0
WHERE s.deleted = 0
AND s.self_submit_time IS NOT NULL
<if test="planName != null and planName != ''">
AND p.plan_name LIKE CONCAT('%', #{planName}, '%')
</if>
<if test="schemeName != null and schemeName != ''">
AND sch.scheme_name LIKE CONCAT('%', #{schemeName}, '%')
</if>
<if test="auditStatus != null and auditStatus != ''">
AND s.audit_status = #{auditStatus}
</if>
<if test="className != null and className != ''">
AND c.class_name LIKE CONCAT('%', #{className}, '%')
</if>
<if test="teacherName != null and teacherName != ''">
AND c.class_teacher_name LIKE CONCAT('%', #{teacherName}, '%')
</if>
<if test="evaluatedUserName != null and evaluatedUserName != ''">
AND s.evaluated_user_name LIKE CONCAT('%', #{evaluatedUserName}, '%')
</if>
<if test="academicYear != null and academicYear != ''">
AND p.academic_year = #{academicYear}
</if>
<if test="semester != null and semester != ''">
AND p.semester = #{semester}
</if>
GROUP BY s.plan_id, s.class_id, s.evaluated_user_id, s.scheme_id, s.audit_status, s.evaluated_user_name,
p.plan_name, p.plan_code, p.academic_year, p.semester,
c.class_name, c.class_teacher_id, c.class_teacher_name,
sch.scheme_name
ORDER BY MAX(s.create_time) DESC
</select>
<!-- 获取考核审核基本信息 -->
<select id="getApprovalBasicInfo" resultMap="AssessmentApprovalDetailVoResult">
SELECT
s.id,
s.plan_id,
s.class_id,
s.self_overall_comment,
s.superior_overall_comment,
s.audit_status,
s.submit_time,
s.create_by,
s.create_time,
s.update_by,
s.update_time
FROM bmzr_assessment_score s
WHERE s.plan_id = #{planId}
AND s.class_id = #{classId}
AND s.evaluated_user_id = #{evaluatedUserId}
AND s.deleted = 0
LIMIT 1
</select>
<!-- 获取班主任常规工作指标列表 -->
<select id="getRoutineWorkIndicators" resultMap="AssessmentApprovalIndicatorVoResult">
SELECT
s.id,
s.indicator_id,
i.indicator_name,
i.indicator_code,
CONCAT(i.indicator_name, '(', i.remark, ')') as description,
i.score,
i.max_score,
s.self_score,
s.self_comment,
s.superior_score,
s.superior_comment,
s.audit_status
FROM bmzr_assessment_score s
LEFT JOIN bmzr_assessment_indicator i ON s.indicator_id = i.id AND i.deleted = 0
WHERE s.plan_id = #{planId}
AND s.class_id = #{classId}
AND s.evaluated_user_id = #{evaluatedUserId}
AND s.deleted = 0
AND i.indicator_type = 'routine_work'
ORDER BY i.sort_order ASC
</select>
<!-- 获取班级扣分指标(班级管理实效) -->
<select id="getClassDeductionIndicator" resultMap="AssessmentApprovalIndicatorVoResult">
SELECT
s.id,
s.indicator_id,
i.indicator_name,
i.indicator_code,
CONCAT(i.indicator_name, '(', i.remark, ')') as description,
i.score,
i.max_score,
s.self_score,
s.self_comment,
s.superior_score,
s.superior_comment,
s.audit_status
FROM bmzr_assessment_score s
LEFT JOIN bmzr_assessment_indicator i ON s.indicator_id = i.id AND i.deleted = 0
WHERE s.plan_id = #{planId}
AND s.class_id = #{classId}
AND s.evaluated_user_id = #{evaluatedUserId}
AND s.deleted = 0
AND i.indicator_type = 'class_deduction'
LIMIT 1
</select>
<!-- 获取特色工作指标列表 -->
<select id="getSpecialWorkIndicators" resultMap="AssessmentApprovalSpecialWorkVoResult">
SELECT
s.id,
i.indicator_code,
i.indicator_name,
s.self_score as score,
s.self_comment,
s.superior_score,
s.superior_comment,
s.audit_status
FROM bmzr_assessment_score s
LEFT JOIN bmzr_assessment_indicator i ON s.indicator_id = i.id AND i.deleted = 0
WHERE s.plan_id = #{planId}
AND s.class_id = #{classId}
AND s.evaluated_user_id = #{evaluatedUserId}
AND s.deleted = 0
AND i.indicator_type = 'special_work'
ORDER BY i.sort_order ASC
</select>
<!-- 更新上级评分和意见 -->
<update id="updateSuperiorScore">
UPDATE bmzr_assessment_score
SET superior_score = #{superiorScore},
superior_comment = #{superiorComment},
superior_evaluator_id = #{approverUserId},
superior_submit_time = NOW(),
update_by = #{approverUserId},
update_time = NOW()
WHERE id = #{id}
AND deleted = 0
</update>
<!-- 更新审核状态和意见 -->
<update id="updateAuditStatus">
UPDATE bmzr_assessment_score
SET audit_status = #{auditStatus},
superior_overall_comment = #{superiorOverallComment},
update_by = #{approverUserId},
update_time = NOW()
WHERE plan_id = #{planId}
AND class_id = #{classId}
AND evaluated_user_id = #{evaluatedUserId}
AND deleted = 0
</update>
<!-- 批量更新审核状态 -->
<update id="batchUpdateAuditStatus">
UPDATE bmzr_assessment_score
SET audit_status = #{auditStatus},
superior_overall_comment = #{auditComment},
update_by = #{approverUserId},
update_time = NOW()
WHERE id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
AND deleted = 0
</update>
<!-- 获取考核方案下拉选项 -->
<select id="getSchemeOptions" resultMap="SchemeOptionVoResult">
SELECT
id,
scheme_code,
scheme_name
FROM bmzr_assessment_scheme
WHERE status = '0'
AND deleted = 0
ORDER BY create_time DESC
</select>
</mapper>
@@ -43,6 +43,9 @@
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="deleted" column="deleted"/>
<result property="auditStatus" column="audit_status"/>
<result property="submitTime" column="submit_time"/>
<result property="submitted" column="submitted"/>
</resultMap>
<!-- 班级详细信息结果映射 -->
@@ -71,6 +74,7 @@
<result property="selfComment" column="self_comment"/>
<result property="selfOverallComment" column="self_overall_comment"/>
<result property="sortOrder" column="sort_order"/>
<result property="auditStatus" column="audit_status"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
@@ -134,9 +138,17 @@
p.create_time,
p.update_by,
p.update_time,
p.deleted
p.deleted,
score.audit_status as audit_status,
score.self_submit_time as submit_time,
CASE WHEN score.plan_id IS NOT NULL THEN 1 ELSE 0 END as submitted
FROM bmzr_assessment_plan p
LEFT JOIN bmzr_assessment_scheme s ON p.scheme_id = s.id AND s.deleted = 0
LEFT JOIN (
SELECT DISTINCT plan_id, audit_status, self_submit_time
FROM bmzr_assessment_score
WHERE evaluated_user_id = #{teacherId} AND deleted = 0
) score ON p.id = score.plan_id
WHERE p.deleted = 0
<if test="planStatus != null and planStatus != ''">
AND p.plan_status = #{planStatus}
@@ -256,6 +268,7 @@
s.self_comment,
s.self_overall_comment,
i.sort_order,
s.audit_status,
s.create_by,
s.create_time,
s.update_by,
@@ -0,0 +1,63 @@
-- ==========================================
-- 班主任考核审核权限配置SQL
-- 版本:V1.0.0
-- 功能:班主任考核审核相关权限配置
-- 作者:系统设计
-- 时间:2025-01-28
-- 模块:学工管理-班主任考核审核权限配置
-- ==========================================
-- 1. 菜单配置
-- 班主任考核审核菜单
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, query_param, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES
('班主任考核审核', (SELECT menu_id FROM sys_menu WHERE menu_name = '班主任考核系统' LIMIT 1), 6, 'assessmentApproval', 'bzrkh/assessmentApproval/index', '', '', 1, 0, 'C', '0', '0', 'bzrkh:assessmentApproval:list', 'edit', 103, 1, now(), 1, now(), '班主任考核审核菜单');
-- 2. 按钮权限配置
-- 获取刚插入的菜单ID
SET @assessment_approval_menu_id = LAST_INSERT_ID();
-- 班主任考核审核按钮权限
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, query_param, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES
('考核审核查询', @assessment_approval_menu_id, 1, '', '', '', '', 1, 0, 'F', '0', '0', 'bzrkh:assessmentApproval:list', '#', 103, 1, now(), 1, now(), ''),
('考核审核详情', @assessment_approval_menu_id, 2, '', '', '', '', 1, 0, 'F', '0', '0', 'bzrkh:assessmentApproval:query', '#', 103, 1, now(), 1, now(), ''),
('考核审核操作', @assessment_approval_menu_id, 3, '', '', '', '', 1, 0, 'F', '0', '0', 'bzrkh:assessmentApproval:approve', '#', 103, 1, now(), 1, now(), ''),
('考核审核导出', @assessment_approval_menu_id, 4, '', '', '', '', 1, 0, 'F', '0', '0', 'bzrkh:assessmentApproval:export', '#', 103, 1, now(), 1, now(), '');
-- 3. 字典配置
-- 审核状态字典
INSERT INTO sys_dict_type (dict_name, dict_type, status, create_dept, create_by, create_time, update_by, update_time, remark) VALUES
('班主任考核审核状态', 'bmzr_audit_status', '0', 103, 1, now(), 1, now(), '班主任考核审核状态字典');
-- 获取字典类型ID
SET @dict_type_id = LAST_INSERT_ID();
-- 审核状态字典数据
INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_dept, create_by, create_time, update_by, update_time, remark) VALUES
(1, '待审核', '0', 'bmzr_audit_status', '', 'warning', 'Y', '0', 103, 1, now(), 1, now(), '待审核状态'),
(2, '审核通过', '1', 'bmzr_audit_status', '', 'success', 'N', '0', 103, 1, now(), 1, now(), '审核通过状态'),
(3, '审核不通过', '2', 'bmzr_audit_status', '', 'danger', 'N', '0', 103, 1, now(), 1, now(), '审核不通过状态');
-- ==========================================
-- 权限字符说明
-- ==========================================
/*
权限字符列表:
1. bzrkh:assessmentApproval:list - 班主任考核审核查询权限(查看审核列表)
2. bzrkh:assessmentApproval:query - 班主任考核审核详情权限(查看审核详情)
3. bzrkh:assessmentApproval:approve - 班主任考核审核操作权限(审批、批量审批、批量拒绝)
4. bzrkh:assessmentApproval:export - 班主任考核审核导出权限(导出审核数据)
API接口与权限字符对应关系:
- GET /bzrkh/assessmentApproval/list → bzrkh:assessmentApproval:list
- GET /bzrkh/assessmentApproval/detail → bzrkh:assessmentApproval:query
- POST /bzrkh/assessmentApproval/submit → bzrkh:assessmentApproval:approve
- POST /bzrkh/assessmentApproval/batchApprove → bzrkh:assessmentApproval:approve
- POST /bzrkh/assessmentApproval/batchReject → bzrkh:assessmentApproval:approve
- GET /bzrkh/assessmentApproval/schemeOptions → bzrkh:assessmentApproval:list
- POST /bzrkh/assessmentApproval/export → bzrkh:assessmentApproval:export
用户角色分配建议:
1. 学工处管理员:拥有所有权限(list、query、approve、export)
2. 学院管理员:拥有查询和审核权限(list、query、approve)
3. 普通审核员:拥有查询权限(list、query)
*/
@@ -0,0 +1,47 @@
-- ==========================================
-- 班主任考核撤销功能权限配置
-- 功能说明:为班主任考核管理新增撤销提交功能的权限配置
-- 创建时间:2025-01-28
-- ==========================================
-- 1. 插入撤销考核权限
INSERT INTO sys_menu (
menu_name, parent_id, order_num, path, component, query_param, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark
) VALUES (
'撤销考核提交',
(SELECT menu_id FROM sys_menu WHERE perms = 'bzrkh:teacherAssessment:list' LIMIT 1),
4,
'',
'',
'',
'',
1,
0,
'F',
'0',
'0',
'bzrkh:teacherAssessment:withdraw',
'#',
103,
1,
NOW(),
1,
NOW(),
'班主任考核撤销提交权限'
);
-- ==========================================
-- 权限字符说明
-- ==========================================
/*
新增权限字符:
- bzrkh:teacherAssessment:withdraw - 班主任考核撤销权限
使用的API接口及对应权限:
- POST /bzrkh/teacherAssessment/withdraw - bzrkh:teacherAssessment:withdraw
说明:
- 撤销功能只对待审核状态(audit_status='0')的考核有效
- 撤销后会逻辑删除评分数据,允许重新提交
- 已审核通过或驳回的考核无法撤销
*/
-14
View File
@@ -17,7 +17,6 @@
- [宿舍管理员授权API](./宿舍管理员授权API.md)
- [学生管理员授权关系API](./学生管理员授权关系API.md)
- [学生销假管理API](./学生销假管理API.md)
- [逆地理编码API](./逆地理编码API.md) - **新增逆地理编码功能**(2025-01-03)
### 1. 用户认证登录
@@ -83,14 +82,11 @@
| 处理预约申请 | POST | /api/xljk/consultation/appointment/process | 预约管理 | xljk:consultation:appointment:process |
| **获取房间床位详细信息** | GET | /dormbed/dormBed/details/room/{roomId} | 宿舍管理 | dormbed:dormBed:query |
| **获取宿舍楼床位详细信息** | GET | /dormbed/dormBed/details/building/{buildingId} | 宿舍管理 | dormbed:dormBed:query |
| 获取当前班主任的班级列表 | GET | /classMsg/classMsg/myClassListAsTeacher | 班级信息 | classMsg:classMsg:list |
| 记录咨询结果 | POST | /api/xljk/consultation/appointment/record | 预约管理 | xljk:consultation:appointment:record |
| 查询未到访记录列表 | GET | /api/xljk/consultation/no-show/list | 预约限制 | xljk:consultation:noshow:list |
| 获取未到访记录详情 | GET | /api/xljk/consultation/no-show/{id} | 预约限制 | xljk:consultation:noshow:query |
| 解除预约限制 | PUT | /api/xljk/consultation/no-show/{id}/release | 预约限制 | xljk:consultation:noshow:release |
| 检查学生是否被限制预约 | GET | /api/xljk/consultation/no-show/check-limitation | 预约限制 | - |
| 逆地理编码 | POST | /system/SysRegion/reverse-geocode | 行政区划 | system:SysRegion:geocode |
| **根据学生ID查询卫生检查信息** | GET | /dormHygieneCheck/dormHygieneCheck/student/{studentId} | 宿舍卫生检查 | dormHygieneCheck:dormHygieneCheck:query |
## 更新历史
@@ -100,8 +96,6 @@
| 2025-07-01 | 1.0 | 初始版本 | 系统管理员 |
| 2025-07-15 | 1.1 | 添加心理健康测评API | 张工 |
| 2025-07-30 | 1.2 | 添加预约限制功能API | Cursor |
| 2025-01-03 | 1.3 | 添加逆地理编码API | zlwu |
| 2025-01-03 | 1.4 | 添加宿舍卫生检查-根据学生ID查询API | zlwu |
**详细文档**: [企业信息管理API.md](./企业信息管理API.md)
@@ -141,13 +135,6 @@
## 🔗 API文档导航
### 🏠 宿舍管理模块
| API文档 | 描述 | 状态 | 更新时间 |
|---------|------|------|----------|
| [宿舍卫生检查API-根据学生ID查询](./宿舍卫生检查API-根据学生ID查询.md) | 根据学生ID查询宿舍卫生检查信息 | ✅ 完成 | 2025-01-03 |
| [宿舍卫生检查API-根据学生ID查询-使用说明](./宿舍卫生检查API-根据学生ID查询-使用说明.md) | 宿舍卫生检查API使用说明 | ✅ 完成 | 2025-01-03 |
### 👥 学工管理模块
| API文档 | 描述 | 状态 | 更新时间 |
@@ -161,5 +148,4 @@
| **[学生考核管理系统API](./学生考核管理系统API.md)** | **学生综合素质测评、违纪处分、奖励加分管理** | **✅ 完成** | **2025-01-27** |
| **[学生考核管理系统修改方案](./学生考核管理系统API修改方案.md)** | **基于标准化违纪处分等级的系统升级方案** | **📋 方案** | **2025-01-27** |
| **[学生考核管理系统数据库修改影响分析](./学生考核管理系统数据库修改影响分析.md)** | **数据库升级脚本执行的详细影响分析** | **📊 分析** | **2025-01-27** |
- 指标体系管理API.md(新增:支持Excel批量导入、导入模板下载;新增字段:具体指标名称)
@@ -0,0 +1,108 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import {
AssessmentApprovalQuery,
AssessmentApprovalVO,
AssessmentApprovalDetailVO,
AssessmentApprovalSubmitBO
} from './types';
/**
* 查询班主任考核审核列表
* @param query
* @returns {*}
*/
export const listAssessmentApproval = (query?: AssessmentApprovalQuery): AxiosPromise<AssessmentApprovalVO[]> => {
return request({
url: '/bzrkh/assessmentApproval/list',
method: 'get',
params: query
});
};
/**
* 获取考核审核详情
* @param planId 计划ID
* @param classId 班级ID
* @param evaluatedUserId 被评价用户ID
* @returns {*}
*/
export const getAssessmentApprovalDetail = (planId: string | number, classId: string | number, evaluatedUserId: string | number): AxiosPromise<AssessmentApprovalDetailVO> => {
return request({
url: '/bzrkh/assessmentApproval/detail',
method: 'get',
params: {
planId,
classId,
evaluatedUserId
}
});
};
/**
* 提交考核审核
* @param data 审核数据
* @returns {*}
*/
export const submitAssessmentApproval = (data: AssessmentApprovalSubmitBO): AxiosPromise<void> => {
return request({
url: '/bzrkh/assessmentApproval/submit',
method: 'post',
data: data
});
};
/**
* 批量审核通过
* @param ids 审核ID列表
* @returns {*}
*/
export const batchApproveAssessment = (ids: (string | number)[]): AxiosPromise<void> => {
return request({
url: '/bzrkh/assessmentApproval/batchApprove',
method: 'post',
data: { ids }
});
};
/**
* 批量审核拒绝
* @param ids 审核ID列表
* @param rejectReason 拒绝原因
* @returns {*}
*/
export const batchRejectAssessment = (ids: (string | number)[], rejectReason: string): AxiosPromise<void> => {
return request({
url: '/bzrkh/assessmentApproval/batchReject',
method: 'post',
data: {
ids,
rejectReason
}
});
};
/**
* 获取考核方案下拉选项
* @returns {*}
*/
export const getAssessmentSchemeOptions = (): AxiosPromise<any[]> => {
return request({
url: '/bzrkh/assessmentApproval/schemeOptions',
method: 'get'
});
};
/**
* 导出考核审核数据
* @param query 查询条件
* @returns {*}
*/
export const exportAssessmentApproval = (query?: AssessmentApprovalQuery): AxiosPromise<void> => {
return request({
url: '/bzrkh/assessmentApproval/export',
method: 'post',
data: query,
responseType: 'blob'
});
};
@@ -0,0 +1,220 @@
/**
* 班主任考核审核相关类型定义
*/
/**
* 审核列表查询参数
*/
export interface AssessmentApprovalQuery {
pageNum?: number;
pageSize?: number;
planName?: string;
schemeName?: string;
auditStatus?: string;
className?: string;
teacherName?: string;
orderByColumn?: string;
isAsc?: string;
}
/**
* 审核列表VO
*/
export interface AssessmentApprovalVO {
id?: string | number;
planId?: string | number;
planName?: string;
planCode?: string;
schemeId?: string | number;
schemeName?: string;
academicYear?: string;
semester?: string;
classId?: string | number;
className?: string;
teacherId?: string | number;
teacherName?: string;
evaluatedUserId?: string | number;
evaluatedUserName?: string;
submitTime?: string;
auditStatus?: string;
auditStatusText?: string;
selfScore?: number;
superiorScore?: number;
finalScore?: number;
createTime?: string;
}
/**
* 审核详情VO - 继承自班主任提交的详情数据
*/
export interface AssessmentApprovalDetailVO {
id?: string | number;
planId?: string | number;
classId?: string | number;
/**
* 班级详细信息
*/
classDetail?: {
id?: string | number;
className?: string;
collegeName?: string;
majorName?: string;
classType?: string;
totalStudentCount?: number;
boardingStudentCount?: number;
};
/**
* 系数信息
*/
coefficient?: {
totalCoefficient?: number;
levelCoefficient?: number;
studentCountCoefficient?: number;
boardingCoefficient?: number;
};
/**
* 班主任常规工作指标列表 - 包含自评和上级评分
*/
routineWorkIndicators?: AssessmentApprovalIndicatorVO[];
/**
* 班级扣分指标 - 班级管理实效
*/
classDeductionIndicator?: AssessmentApprovalIndicatorVO;
/**
* 特色工作指标列表
*/
specialWorkIndicators?: AssessmentApprovalSpecialWorkVO[];
/**
* 自我总体评价
*/
selfOverallComment?: string;
/**
* 上级总体评价
*/
superiorOverallComment?: string;
/**
* 月考核得分
*/
monthlyScore?: number;
/**
* 审核状态
*/
auditStatus?: string;
/**
* 提交时间
*/
submitTime?: string;
}
/**
* 审核指标VO - 包含自评和上级评分
*/
export interface AssessmentApprovalIndicatorVO {
id?: string | number;
indicatorId?: string | number;
indicatorName?: string;
indicatorCode?: string;
description?: string;
score?: number; // 指标分值
maxScore?: number;
// 自评相关
selfScore?: number;
selfComment?: string;
// 上级评相关
superiorScore?: number;
superiorComment?: string;
// 审核状态
auditStatus?: string;
}
/**
* 特色工作审核VO
*/
export interface AssessmentApprovalSpecialWorkVO {
id?: string | number;
indicatorCode?: string;
indicatorName?: string;
// 自评相关
score?: number; // 自评分数
selfComment?: string;
// 上级评相关
superiorScore?: number;
superiorComment?: string;
// 审核状态
auditStatus?: string;
}
/**
* 审核提交BO
*/
export interface AssessmentApprovalSubmitBO {
planId?: string | number;
classId?: string | number;
evaluatedUserId?: string | number;
/**
* 班主任常规工作审核数据
*/
routineWorkApproval?: AssessmentApprovalIndicatorSubmitVO[];
/**
* 班级管理实效审核数据
*/
classDeductionApproval?: AssessmentApprovalIndicatorSubmitVO;
/**
* 特色工作审核数据
*/
specialWorkApproval?: AssessmentApprovalSpecialWorkSubmitVO[];
/**
* 上级总体评价
*/
superiorOverallComment?: string;
/**
* 审核状态 0=待审核 1=审核通过 2=审核不通过
*/
auditStatus?: string;
/**
* 审核意见
*/
auditComment?: string;
}
/**
* 指标审核提交VO
*/
export interface AssessmentApprovalIndicatorSubmitVO {
id?: string | number;
indicatorId?: string | number;
superiorScore?: number;
superiorComment?: string;
}
/**
* 特色工作审核提交VO
*/
export interface AssessmentApprovalSpecialWorkSubmitVO {
id?: string | number;
indicatorCode?: string;
superiorScore?: number;
superiorComment?: string;
}
+17 -1
View File
@@ -29,7 +29,7 @@ export const listTeacherClasses = (query?: TeacherClassQuery): AxiosPromise<Teac
*/
export const listTeacherAssessmentPlans = (query?: TeacherAssessmentPlanQuery): AxiosPromise<TeacherAssessmentPlanVO[]> => {
return request({
url: '/bzrkh/assessmentPlan/list',
url: '/bzrkh/teacherAssessment/plans',
method: 'get',
params: query
});
@@ -93,4 +93,20 @@ export const submitAssessmentScore = (data: AssessmentSubmitVO): AxiosPromise<vo
method: 'post',
data
});
};
/**
* 撤销考核提交
* @param planId 计划ID
* @param classId 班级ID
*/
export const withdrawAssessment = (planId: string | number, classId: string | number): AxiosPromise<void> => {
return request({
url: '/bzrkh/teacherAssessment/withdraw',
method: 'post',
data: {
planId,
classId
}
});
};
@@ -135,6 +135,21 @@ export interface TeacherAssessmentPlanVO {
* 备注
*/
remark?: string;
/**
* 审核状态(null=未提交,0=已提交待审核,1=审核通过,2=审核不通过)
*/
auditStatus?: string;
/**
* 提交时间
*/
submitTime?: string;
/**
* 是否已提交(用于前端按钮状态控制)
*/
submitted?: boolean;
}
export interface TeacherAssessmentPlanQuery {
@@ -0,0 +1,720 @@
<template>
<el-dialog
:title="dialogTitle"
v-model="visible"
width="1200px"
:close-on-click-modal="false"
append-to-body
@close="handleClose"
>
<div v-loading="loading" class="approval-dialog-content">
<!-- 1. 班级信息卡片 -->
<el-card shadow="never" class="info-card">
<template #header>
<div class="card-header">
<span>班级信息</span>
</div>
</template>
<el-descriptions :column="3" border>
<el-descriptions-item label="学院名称">{{ approvalDetail?.classDetail?.collegeName || '-' }}</el-descriptions-item>
<el-descriptions-item label="专业名称">{{ approvalDetail?.classDetail?.majorName || '-' }}</el-descriptions-item>
<el-descriptions-item label="班级名称">{{ approvalDetail?.classDetail?.className || '-' }}</el-descriptions-item>
</el-descriptions>
</el-card>
<!-- 2. 总系数(K)与层次系数(K1)并排 -->
<el-row :gutter="20" class="info-card">
<el-col :span="12">
<el-card shadow="never">
<template #header>
<div class="card-header">
<span>总系数(K)</span>
</div>
</template>
<el-descriptions :column="1" border>
<el-descriptions-item label="总系数">{{ formatNumber(approvalDetail?.coefficient?.totalCoefficient, 3) }}</el-descriptions-item>
</el-descriptions>
</el-card>
</el-col>
<el-col :span="12">
<el-card shadow="never">
<template #header>
<div class="card-header">
<span>层次系数(K1)</span>
</div>
</template>
<el-descriptions :column="2" border>
<el-descriptions-item label="班级学历层级">{{ getClassTypeText(approvalDetail?.classDetail?.classType) }}</el-descriptions-item>
<el-descriptions-item label="层次系数">{{ formatNumber(approvalDetail?.coefficient?.levelCoefficient, 3) }}</el-descriptions-item>
</el-descriptions>
</el-card>
</el-col>
</el-row>
<!-- 3. 人数系数(K2)与住校生系数(K3)并排 -->
<el-row :gutter="20" class="info-card">
<el-col :span="12">
<el-card shadow="never">
<template #header>
<div class="card-header">
<span>人数系数(K2)</span>
</div>
</template>
<el-descriptions :column="2" border>
<el-descriptions-item label="班级总人数">{{ approvalDetail?.classDetail?.totalStudentCount || 0 }}人</el-descriptions-item>
<el-descriptions-item label="人数系数">{{ formatNumber(approvalDetail?.coefficient?.studentCountCoefficient, 3) }}</el-descriptions-item>
</el-descriptions>
</el-card>
</el-col>
<el-col :span="12">
<el-card shadow="never">
<template #header>
<div class="card-header">
<span>住校生系数(K3)</span>
</div>
</template>
<el-descriptions :column="2" border>
<el-descriptions-item label="住校生人数">{{ approvalDetail?.classDetail?.boardingStudentCount || 0 }}人</el-descriptions-item>
<el-descriptions-item label="住校生系数">{{ formatNumber(approvalDetail?.coefficient?.boardingCoefficient, 3) }}</el-descriptions-item>
</el-descriptions>
</el-card>
</el-col>
</el-row>
<!-- 4. 班主任常规工作(50分)卡片 -->
<el-card shadow="never" class="info-card">
<template #header>
<div class="card-header">
<span>班主任常规工作(50分)</span>
</div>
</template>
<el-table border :data="routineWorkScores" style="width: 100%" max-height="400" class="routine-work-table">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="indicatorName" label="指标名称" min-width="150" align="center" :show-overflow-tooltip="true" />
<el-table-column prop="description" label="指标描述" min-width="180" align="center" :show-overflow-tooltip="true" />
<el-table-column prop="score" label="指标分值" width="80" align="center">
<template #default="scope">
<span>{{ scope.row.score || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="自评分数" width="80" align="center">
<template #default="scope">
<span>{{ scope.row.selfScore || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="自评意见" width="180" align="center">
<template #default="scope">
<el-tooltip :content="scope.row.selfComment || '无'" placement="top" :disabled="!scope.row.selfComment">
<span class="text-ellipsis">{{ scope.row.selfComment || '无' }}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column label="上级评分" width="100" align="center">
<template #default="scope">
<el-input-number
v-model="scope.row.superiorScore"
:min="0"
:max="scope.row.score || 100"
:precision="2"
controls-position="right"
style="width: 100%"
placeholder="请输入分数"
size="small"
/>
</template>
</el-table-column>
<el-table-column label="审批意见" width="200" align="center">
<template #default="scope">
<el-input
v-model="scope.row.superiorComment"
type="textarea"
:rows="2"
placeholder="请输入审批意见"
maxlength="200"
show-word-limit
size="small"
/>
</template>
</el-table-column>
</el-table>
</el-card>
<!-- 5. 班级管理实效(50分)卡片 -->
<el-card shadow="never" class="info-card">
<template #header>
<div class="card-header">
<span>班级管理实效(50分)</span>
</div>
</template>
<el-form :model="managementEffectivenessForm" label-width="150px" class="management-effectiveness-form">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="班级扣分">
<el-input
:value="managementEffectivenessForm.classDeduction?.toFixed(2) || '0.00'"
readonly
style="width: 100%; text-align: center;"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="按班级扣分50%计">
<el-input
:value="managementEffectivenessForm.classDeductionHalf?.toFixed(2) || '0.00'"
readonly
style="width: 100%; text-align: center;"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="上级评分">
<el-input-number
v-model="managementEffectivenessForm.superiorScore"
:min="0"
:max="50"
:precision="2"
controls-position="right"
style="width: 100%"
placeholder="请输入分数"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="自评意见">
<el-input
:value="managementEffectivenessForm.selfComment"
type="textarea"
:rows="3"
readonly
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="审批意见">
<el-input
v-model="managementEffectivenessForm.superiorComment"
type="textarea"
:rows="3"
placeholder="请输入审批意见"
maxlength="500"
show-word-limit
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<!-- 6. 特色工作(加20分)卡片 -->
<el-card shadow="never" class="info-card">
<template #header>
<div class="card-header">
<span>特色工作(加20分)</span>
</div>
</template>
<el-table border :data="specialWorkScores" style="width: 100%" class="special-work-table">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="indicatorName" label="特色工作项目" min-width="180" align="center" :show-overflow-tooltip="true" />
<el-table-column label="自评分数" width="80" align="center">
<template #default="scope">
<span>{{ scope.row.score || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="自评意见" width="180" align="center">
<template #default="scope">
<el-tooltip :content="scope.row.selfComment || '无'" placement="top" :disabled="!scope.row.selfComment">
<span class="text-ellipsis">{{ scope.row.selfComment || '无' }}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column label="上级评分" width="100" align="center">
<template #default="scope">
<el-input-number
v-model="scope.row.superiorScore"
:min="0"
:max="20"
:precision="2"
controls-position="right"
style="width: 100%"
placeholder="请输入分数"
size="small"
/>
</template>
</el-table-column>
<el-table-column label="审批意见" width="200" align="center">
<template #default="scope">
<el-input
v-model="scope.row.superiorComment"
type="textarea"
:rows="2"
placeholder="请输入审批意见"
maxlength="200"
show-word-limit
size="small"
/>
</template>
</el-table-column>
</el-table>
</el-card>
<!-- 7. 月考核得分卡片 -->
<el-card shadow="never" class="info-card">
<template #header>
<div class="card-header">
<span>月考核得分</span>
</div>
</template>
<el-form :model="monthlyScoreForm" label-width="100px" class="monthly-score-form">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="月考核得分">
<el-input
:value="calculateMonthlyScore().toFixed(2)"
readonly
style="width: 100%; text-align: center;"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="自我总体评价">
<el-input
:value="monthlyScoreForm.selfOverallComment"
type="textarea"
:rows="4"
readonly
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="上级总体评价">
<el-input
v-model="monthlyScoreForm.superiorOverallComment"
type="textarea"
:rows="4"
placeholder="请输入上级总体评价"
maxlength="500"
show-word-limit
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<!-- 8. 审批结果卡片 -->
<el-card shadow="never" class="info-card">
<template #header>
<div class="card-header">
<span>审批结果</span>
</div>
</template>
<el-form :model="approvalForm" label-width="100px" class="approval-form">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="审批状态" required>
<el-radio-group v-model="approvalForm.auditStatus">
<el-radio value="1">通过</el-radio>
<el-radio value="2">拒绝</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="审批意见">
<el-input
v-model="approvalForm.auditComment"
type="textarea"
:rows="3"
placeholder="请输入审批意见"
maxlength="500"
show-word-limit
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
</div>
<template #footer>
<div class="dialog-footer">
<el-button :loading="submitLoading" type="primary" @click="handleSubmit">保存审批</el-button>
<el-button @click="handleClose">取消</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup name="ApprovalDialog" lang="ts">
import {
getAssessmentApprovalDetail,
submitAssessmentApproval
} from '@/api/bzrkh/assessmentApproval';
import {
AssessmentApprovalVO,
AssessmentApprovalDetailVO,
AssessmentApprovalIndicatorVO,
AssessmentApprovalSpecialWorkVO,
AssessmentApprovalSubmitBO
} from '@/api/bzrkh/assessmentApproval/types';
const emit = defineEmits(['success']);
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const visible = ref(false);
const loading = ref(false);
const submitLoading = ref(false);
const currentRow = ref<AssessmentApprovalVO>();
const approvalDetail = ref<AssessmentApprovalDetailVO>();
const routineWorkScores = ref<AssessmentApprovalIndicatorVO[]>([]);
const specialWorkScores = ref<AssessmentApprovalSpecialWorkVO[]>([]);
// 班级管理实效表单
const managementEffectivenessForm = reactive({
classDeduction: 0,
classDeductionHalf: 0,
selfComment: '',
superiorScore: 0,
superiorComment: ''
});
// 月考核得分表单
const monthlyScoreForm = reactive({
selfOverallComment: '',
superiorOverallComment: ''
});
// 审批表单
const approvalForm = reactive({
auditStatus: '1', // 默认通过
auditComment: ''
});
const dialogTitle = computed(() => {
const className = approvalDetail.value?.classDetail?.className || '';
return `${className} - 班主任考核审批`;
});
/** 获取班级层次文本 */
const getClassTypeText = (classType?: string) => {
const typeMap: Record<string, string> = {
'1': '中级工班',
'2': '高级工班',
'3': '预备技师班',
'4': '技师班',
'5': '中高职一体'
};
return typeMap[classType || ''] || '未知';
};
/** 格式化数字显示 */
const formatNumber = (value?: number | string, precision = 4) => {
if (value === undefined || value === null || value === '') {
return '0.' + '0'.repeat(precision);
}
const numValue = typeof value === 'string' ? parseFloat(value) : value;
if (isNaN(numValue)) {
return '0.' + '0'.repeat(precision);
}
return numValue.toFixed(precision);
};
/** 计算月考核得分 */
const calculateMonthlyScore = () => {
// 总系数(K)
const totalCoefficient = approvalDetail.value?.coefficient?.totalCoefficient || 0;
// 班主任常规工作自评分之和
const routineWorkTotal = routineWorkScores.value.reduce((sum, item) => sum + (item.selfScore || 0), 0);
// 按班级扣分50%计的分值
const deductionHalf = managementEffectivenessForm.classDeductionHalf || 0;
// 特色工作总分值
const specialWorkTotal = specialWorkScores.value.reduce((sum, item) => sum + (item.score || 0), 0);
// 月考核得分 = 总系数(K)* (班主任常规工作自评分之和 - 按班级扣分50%计的分值 + 特色工作总分值)
return totalCoefficient * (routineWorkTotal - deductionHalf + specialWorkTotal);
};
/** 打开弹窗 */
const open = async (row: AssessmentApprovalVO) => {
if (!row.planId || !row.classId || !row.evaluatedUserId) {
proxy?.$modal.msgError('参数错误:缺少必要的ID信息');
return;
}
currentRow.value = row;
visible.value = true;
await loadApprovalDetail();
};
/** 加载审批详情数据 */
const loadApprovalDetail = async () => {
if (!currentRow.value?.planId || !currentRow.value?.classId || !currentRow.value?.evaluatedUserId) {
return;
}
loading.value = true;
try {
const res = await getAssessmentApprovalDetail(
currentRow.value.planId,
currentRow.value.classId,
currentRow.value.evaluatedUserId
);
approvalDetail.value = res.data;
// 初始化班主任常规工作数据
routineWorkScores.value = (approvalDetail.value?.routineWorkIndicators || []).map(item => ({
...item,
superiorScore: item.superiorScore || 0,
superiorComment: item.superiorComment || ''
}));
// 初始化班级管理实效数据
if (approvalDetail.value?.classDeductionIndicator) {
const indicator = approvalDetail.value.classDeductionIndicator;
managementEffectivenessForm.classDeduction = indicator.selfScore || 0;
managementEffectivenessForm.classDeductionHalf = (indicator.selfScore || 0) * 0.5;
managementEffectivenessForm.selfComment = indicator.selfComment || '';
managementEffectivenessForm.superiorScore = indicator.superiorScore || 0;
managementEffectivenessForm.superiorComment = indicator.superiorComment || '';
}
// 初始化特色工作数据
specialWorkScores.value = (approvalDetail.value?.specialWorkIndicators || []).map(item => ({
...item,
superiorScore: item.superiorScore || 0,
superiorComment: item.superiorComment || ''
}));
// 初始化月考核得分数据
monthlyScoreForm.selfOverallComment = approvalDetail.value?.selfOverallComment || '';
monthlyScoreForm.superiorOverallComment = approvalDetail.value?.superiorOverallComment || '';
// 初始化审批状态
approvalForm.auditStatus = approvalDetail.value?.auditStatus || '1';
} catch (error) {
console.error('加载审批详情失败:', error);
proxy?.$modal.msgError('加载审批详情失败');
} finally {
loading.value = false;
}
};
/** 提交审批 */
const handleSubmit = async () => {
try {
// 验证必填项
if (!approvalForm.auditStatus) {
proxy?.$modal.msgWarning('请选择审批状态');
return;
}
if (approvalForm.auditStatus === '2' && !approvalForm.auditComment.trim()) {
proxy?.$modal.msgWarning('拒绝审批时必须填写审批意见');
return;
}
submitLoading.value = true;
// 构造提交数据
const submitData: AssessmentApprovalSubmitBO = {
planId: currentRow.value?.planId,
classId: currentRow.value?.classId,
evaluatedUserId: currentRow.value?.evaluatedUserId,
routineWorkApproval: routineWorkScores.value.map(item => ({
id: item.id,
indicatorId: item.indicatorId,
superiorScore: item.superiorScore,
superiorComment: item.superiorComment
})),
classDeductionApproval: {
id: approvalDetail.value?.classDeductionIndicator?.id,
indicatorId: approvalDetail.value?.classDeductionIndicator?.indicatorId,
superiorScore: managementEffectivenessForm.superiorScore,
superiorComment: managementEffectivenessForm.superiorComment
},
specialWorkApproval: specialWorkScores.value.map(item => ({
id: item.id,
indicatorCode: item.indicatorCode,
superiorScore: item.superiorScore,
superiorComment: item.superiorComment
})),
superiorOverallComment: monthlyScoreForm.superiorOverallComment,
auditStatus: approvalForm.auditStatus,
auditComment: approvalForm.auditComment
};
await submitAssessmentApproval(submitData);
proxy?.$modal.msgSuccess('审批提交成功');
emit('success');
handleClose();
} catch (error) {
console.error('提交审批失败:', error);
proxy?.$modal.msgError('提交审批失败');
} finally {
submitLoading.value = false;
}
};
/** 关闭弹窗 */
const handleClose = () => {
visible.value = false;
// 重置表单数据
routineWorkScores.value = [];
specialWorkScores.value = [];
Object.assign(managementEffectivenessForm, {
classDeduction: 0,
classDeductionHalf: 0,
selfComment: '',
superiorScore: 0,
superiorComment: ''
});
Object.assign(monthlyScoreForm, {
selfOverallComment: '',
superiorOverallComment: ''
});
Object.assign(approvalForm, {
auditStatus: '1',
auditComment: ''
});
};
// 暴露给父组件的方法
defineExpose({
open
});
</script>
<style scoped>
.approval-dialog-content {
max-height: 70vh;
overflow-y: auto;
}
.info-card {
margin-bottom: 16px;
}
.info-card:last-child {
margin-bottom: 0;
}
.card-header {
font-weight: 600;
color: #303133;
text-align: center;
}
/* 表格样式 */
:deep(.el-table) {
border-radius: 4px;
}
:deep(.el-table th) {
background-color: #f5f7fa;
color: #606266;
font-weight: 600;
}
/* 班主任常规工作表格样式优化 */
:deep(.routine-work-table) {
.el-table__body-wrapper {
max-height: 350px;
overflow-y: auto;
}
.el-table__row {
height: auto;
}
.el-table__cell {
padding: 8px 0;
vertical-align: middle;
}
/* 优化输入框在表格中的显示 */
.el-input-number {
width: 100% !important;
}
.el-textarea__inner {
resize: none;
min-height: 60px !important;
}
}
/* 特色工作表格样式优化 */
:deep(.special-work-table) {
.el-table__row {
height: auto;
}
.el-table__cell {
padding: 8px 0;
vertical-align: middle;
}
.el-input-number {
width: 100% !important;
}
.el-textarea__inner {
resize: none;
min-height: 60px !important;
}
}
/* 文本省略样式 */
.text-ellipsis {
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 160px;
}
/* 表单样式优化 */
:deep(.el-form-item__label) {
font-weight: 500;
text-align: center;
}
/* 描述列表居中样式 */
:deep(.el-descriptions) {
.el-descriptions__label {
text-align: center;
font-weight: 500;
}
.el-descriptions__content {
text-align: center;
}
}
/* 只读输入框样式 */
:deep(.el-input.is-disabled .el-input__wrapper) {
background-color: #f5f7fa;
}
/* 审批表单样式 */
.approval-form :deep(.el-radio-group) {
.el-radio {
margin-right: 30px;
}
}
</style>
@@ -0,0 +1,273 @@
<template>
<div class="p-2 page-container">
<!-- 搜索区域 -->
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form :model="queryParams" ref="queryFormRef" label-width="100px">
<el-row :gutter="20">
<el-col :lg="6" :md="12" :sm="24">
<el-form-item label="计划名称" prop="planName">
<el-input v-model="queryParams.planName" placeholder="请输入计划名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
<el-col :lg="6" :md="12" :sm="24">
<el-form-item label="考核方案" prop="schemeName">
<el-select v-model="queryParams.schemeName" placeholder="请选择考核方案" clearable style="width: 100%">
<el-option
v-for="item in schemeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :lg="6" :md="12" :sm="24">
<el-form-item label="审批状态" prop="auditStatus">
<el-select v-model="queryParams.auditStatus" placeholder="请选择审批状态" clearable style="width: 100%">
<el-option label="待审核" value="0" />
<el-option label="审核通过" value="1" />
<el-option label="审核不通过" value="2" />
</el-select>
</el-form-item>
</el-col>
<el-col :lg="6" :md="12" :sm="24">
<el-form-item label="班级名称" prop="className">
<el-input v-model="queryParams.className" placeholder="请输入班级名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
<el-col :lg="6" :md="12" :sm="24">
<el-form-item label="班主任姓名" prop="teacherName">
<el-input v-model="queryParams.teacherName" placeholder="请输入班主任姓名" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
<el-col :lg="6" :md="24" :sm="24" style="text-align: right">
<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" class="button-card table-card">
<template #header>
<el-row :gutter="10" class="mb8">
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<div class="table-container">
<el-table v-loading="loading" border :data="approvalList" @sort-change="sortChange">
<el-table-column label="计划名称" align="center" prop="planName" :show-overflow-tooltip="true" />
<el-table-column label="考核方案" align="center" prop="schemeName" :show-overflow-tooltip="true" />
<el-table-column label="学年学期" align="center" width="120">
<template #default="scope">
<span>{{ scope.row.academicYear }}{{ scope.row.semester === '1' ? '上' : '下' }}学期</span>
</template>
</el-table-column>
<el-table-column label="班级名称" align="center" prop="className" :show-overflow-tooltip="true" />
<el-table-column label="班主任姓名" align="center" prop="evaluatedUserName" :show-overflow-tooltip="true" />
<el-table-column label="申请时间" align="center" width="180" sortable="custom" prop="submitTime">
<template #default="scope">
<span>{{ parseTime(scope.row.submitTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="审批状态" align="center" width="120">
<template #default="scope">
<el-tag v-if="!scope.row.auditStatus || scope.row.auditStatus === '0'" type="warning" effect="plain">待审核</el-tag>
<el-tag v-else-if="scope.row.auditStatus === '1'" type="success" effect="plain">审核通过</el-tag>
<el-tag v-else-if="scope.row.auditStatus === '2'" type="danger" effect="plain">审核不通过</el-tag>
<el-tag v-else type="info" effect="plain">未知状态</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
<template #default="scope">
<el-tooltip content="审批" placement="top">
<el-button
link
type="primary"
icon="Edit"
:disabled="loading || scope.row.auditStatus !== '0'"
@click="handleApproval(scope.row)"
></el-button>
</el-tooltip>
<el-tooltip content="查看" placement="top">
<el-button
link
type="success"
icon="View"
:disabled="loading"
@click="handleView(scope.row)"
></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
</div>
<div class="pagination-container">
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</div>
</el-card>
<!-- 审批弹窗 -->
<ApprovalDialog
ref="approvalDialogRef"
@success="handleApprovalSuccess"
/>
<!-- 查看弹窗 -->
<ViewDialog
ref="viewDialogRef"
/>
</div>
</template>
<script setup name="AssessmentApproval" lang="ts">
import {
listAssessmentApproval,
getAssessmentSchemeOptions
} from '@/api/bzrkh/assessmentApproval';
import {
AssessmentApprovalVO,
AssessmentApprovalQuery
} from '@/api/bzrkh/assessmentApproval/types';
import ApprovalDialog from './approvalDialog.vue';
import ViewDialog from './viewDialog.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const approvalList = ref<AssessmentApprovalVO[]>([]);
const loading = ref(true);
const showSearch = ref(true);
const total = ref(0);
const schemeOptions = ref<any[]>([]);
// 弹窗引用
const approvalDialogRef = ref();
const viewDialogRef = ref();
const queryFormRef = ref<ElFormInstance>();
const data = reactive<PageData<any, AssessmentApprovalQuery>>({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
planName: undefined,
schemeName: undefined,
auditStatus: undefined,
className: undefined,
teacherName: undefined
},
rules: {}
});
const { queryParams } = toRefs(data);
/** 获取考核方案选项 */
const getSchemeOptions = async () => {
try {
const res = await getAssessmentSchemeOptions();
schemeOptions.value = res.data || [];
} catch (error) {
console.error('获取考核方案选项失败:', error);
}
};
/** 查询审核列表 */
const getList = async () => {
loading.value = true;
try {
const res = await listAssessmentApproval(queryParams.value);
approvalList.value = res.rows || [];
total.value = res.total || 0;
} catch (error) {
console.error('获取审核列表失败:', error);
} finally {
loading.value = false;
}
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 排序触发事件 */
const sortChange = (column: any) => {
const { prop, order } = column;
if (prop === 'submitTime') {
queryParams.value.orderByColumn = prop;
queryParams.value.isAsc = order === 'ascending' ? 'asc' : 'desc';
getList();
}
};
/** 审批操作 */
const handleApproval = (row: AssessmentApprovalVO) => {
approvalDialogRef.value?.open(row);
};
/** 查看操作 */
const handleView = (row: AssessmentApprovalVO) => {
viewDialogRef.value?.open(row);
};
/** 审批成功回调 */
const handleApprovalSuccess = () => {
getList();
};
onMounted(() => {
getSchemeOptions();
getList();
});
</script>
<style scoped>
/* 页面容器样式 */
.page-container {
padding: 8px;
}
/* 表格卡片布局 */
.table-card {
margin-top: 0;
}
.table-card :deep(.el-card__body) {
padding: 0px 20px 20px 20px !important;
}
/* 表格主体 */
.table-container {
margin-bottom: 0;
}
/* 移除按钮栏底部边框 */
.button-card :deep(.el-card__header) {
border-bottom: none !important;
}
/* 分页容器样式 */
.pagination-container {
display: flex;
justify-content: flex-end;
padding: 16px 20px 0 0 !important;
background-color: #fff;
margin-top: 0px !important;
}
</style>
@@ -0,0 +1,577 @@
<template>
<el-dialog
:title="dialogTitle"
v-model="visible"
width="1200px"
:close-on-click-modal="false"
append-to-body
@close="handleClose"
>
<div v-loading="loading" class="view-dialog-content">
<!-- 1. 班级信息卡片 -->
<el-card shadow="never" class="info-card">
<template #header>
<div class="card-header">
<span>班级信息</span>
</div>
</template>
<el-descriptions :column="3" border>
<el-descriptions-item label="学院名称">{{ viewDetail?.classDetail?.collegeName || '-' }}</el-descriptions-item>
<el-descriptions-item label="专业名称">{{ viewDetail?.classDetail?.majorName || '-' }}</el-descriptions-item>
<el-descriptions-item label="班级名称">{{ viewDetail?.classDetail?.className || '-' }}</el-descriptions-item>
</el-descriptions>
</el-card>
<!-- 2. 总系数(K)与层次系数(K1)并排 -->
<el-row :gutter="20" class="info-card">
<el-col :span="12">
<el-card shadow="never">
<template #header>
<div class="card-header">
<span>总系数(K)</span>
</div>
</template>
<el-descriptions :column="1" border>
<el-descriptions-item label="总系数">{{ formatNumber(viewDetail?.coefficient?.totalCoefficient, 3) }}</el-descriptions-item>
</el-descriptions>
</el-card>
</el-col>
<el-col :span="12">
<el-card shadow="never">
<template #header>
<div class="card-header">
<span>层次系数(K1)</span>
</div>
</template>
<el-descriptions :column="2" border>
<el-descriptions-item label="班级学历层级">{{ getClassTypeText(viewDetail?.classDetail?.classType) }}</el-descriptions-item>
<el-descriptions-item label="层次系数">{{ formatNumber(viewDetail?.coefficient?.levelCoefficient, 3) }}</el-descriptions-item>
</el-descriptions>
</el-card>
</el-col>
</el-row>
<!-- 3. 人数系数(K2)与住校生系数(K3)并排 -->
<el-row :gutter="20" class="info-card">
<el-col :span="12">
<el-card shadow="never">
<template #header>
<div class="card-header">
<span>人数系数(K2)</span>
</div>
</template>
<el-descriptions :column="2" border>
<el-descriptions-item label="班级总人数">{{ viewDetail?.classDetail?.totalStudentCount || 0 }}人</el-descriptions-item>
<el-descriptions-item label="人数系数">{{ formatNumber(viewDetail?.coefficient?.studentCountCoefficient, 3) }}</el-descriptions-item>
</el-descriptions>
</el-card>
</el-col>
<el-col :span="12">
<el-card shadow="never">
<template #header>
<div class="card-header">
<span>住校生系数(K3)</span>
</div>
</template>
<el-descriptions :column="2" border>
<el-descriptions-item label="住校生人数">{{ viewDetail?.classDetail?.boardingStudentCount || 0 }}人</el-descriptions-item>
<el-descriptions-item label="住校生系数">{{ formatNumber(viewDetail?.coefficient?.boardingCoefficient, 3) }}</el-descriptions-item>
</el-descriptions>
</el-card>
</el-col>
</el-row>
<!-- 4. 班主任常规工作(50分)卡片 -->
<el-card shadow="never" class="info-card">
<template #header>
<div class="card-header">
<span>班主任常规工作(50分)</span>
</div>
</template>
<el-table border :data="routineWorkScores" style="width: 100%" max-height="400" class="routine-work-table">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="indicatorName" label="指标名称" min-width="150" align="center" :show-overflow-tooltip="true" />
<el-table-column prop="description" label="指标描述" min-width="180" align="center" :show-overflow-tooltip="true" />
<el-table-column prop="score" label="指标分值" width="80" align="center">
<template #default="scope">
<span>{{ scope.row.score || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="自评分数" width="80" align="center">
<template #default="scope">
<span>{{ scope.row.selfScore || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="自评意见" width="180" align="center">
<template #default="scope">
<el-tooltip :content="scope.row.selfComment || '无'" placement="top" :disabled="!scope.row.selfComment">
<span class="text-ellipsis">{{ scope.row.selfComment || '无' }}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column label="上级评分" width="80" align="center">
<template #default="scope">
<span>{{ scope.row.superiorScore || '-' }}</span>
</template>
</el-table-column>
<el-table-column label="审批意见" width="180" align="center">
<template #default="scope">
<el-tooltip :content="scope.row.superiorComment || '无'" placement="top" :disabled="!scope.row.superiorComment">
<span class="text-ellipsis">{{ scope.row.superiorComment || '无' }}</span>
</el-tooltip>
</template>
</el-table-column>
</el-table>
</el-card>
<!-- 5. 班级管理实效(50分)卡片 -->
<el-card shadow="never" class="info-card">
<template #header>
<div class="card-header">
<span>班级管理实效(50分)</span>
</div>
</template>
<el-form label-width="150px" class="management-effectiveness-form">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="班级扣分">
<el-input
:value="managementEffectivenessData.classDeduction?.toFixed(2) || '0.00'"
readonly
style="width: 100%; text-align: center;"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="按班级扣分50%计">
<el-input
:value="managementEffectivenessData.classDeductionHalf?.toFixed(2) || '0.00'"
readonly
style="width: 100%; text-align: center;"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="上级评分">
<el-input
:value="managementEffectivenessData.superiorScore?.toFixed(2) || '-'"
readonly
style="width: 100%; text-align: center;"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="自评意见">
<el-input
:value="managementEffectivenessData.selfComment"
type="textarea"
:rows="3"
readonly
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="审批意见">
<el-input
:value="managementEffectivenessData.superiorComment"
type="textarea"
:rows="3"
readonly
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<!-- 6. 特色工作(加20分)卡片 -->
<el-card shadow="never" class="info-card">
<template #header>
<div class="card-header">
<span>特色工作(加20分)</span>
</div>
</template>
<el-table border :data="specialWorkScores" style="width: 100%" class="special-work-table">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="indicatorName" label="特色工作项目" min-width="180" align="center" :show-overflow-tooltip="true" />
<el-table-column label="自评分数" width="80" align="center">
<template #default="scope">
<span>{{ scope.row.score || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="自评意见" width="180" align="center">
<template #default="scope">
<el-tooltip :content="scope.row.selfComment || '无'" placement="top" :disabled="!scope.row.selfComment">
<span class="text-ellipsis">{{ scope.row.selfComment || '无' }}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column label="上级评分" width="80" align="center">
<template #default="scope">
<span>{{ scope.row.superiorScore || '-' }}</span>
</template>
</el-table-column>
<el-table-column label="审批意见" width="180" align="center">
<template #default="scope">
<el-tooltip :content="scope.row.superiorComment || '无'" placement="top" :disabled="!scope.row.superiorComment">
<span class="text-ellipsis">{{ scope.row.superiorComment || '无' }}</span>
</el-tooltip>
</template>
</el-table-column>
</el-table>
</el-card>
<!-- 7. 月考核得分卡片 -->
<el-card shadow="never" class="info-card">
<template #header>
<div class="card-header">
<span>月考核得分</span>
</div>
</template>
<el-form label-width="100px" class="monthly-score-form">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="月考核得分">
<el-input
:value="calculateMonthlyScore().toFixed(2)"
readonly
style="width: 100%; text-align: center;"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="自我总体评价">
<el-input
:value="monthlyScoreData.selfOverallComment"
type="textarea"
:rows="4"
readonly
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="上级总体评价">
<el-input
:value="monthlyScoreData.superiorOverallComment"
type="textarea"
:rows="4"
readonly
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<!-- 8. 审批结果卡片 -->
<el-card shadow="never" class="info-card" v-if="viewDetail?.auditStatus">
<template #header>
<div class="card-header">
<span>审批结果</span>
</div>
</template>
<el-descriptions :column="2" border>
<el-descriptions-item label="审批状态">
<dict-tag :options="bmzr_audit_status" :value="viewDetail?.auditStatus"/>
</el-descriptions-item>
<el-descriptions-item label="审批时间">
{{ parseTime(currentRow?.createTime, '{y}-{m}-{d} {h}:{i}:{s}') || '-' }}
</el-descriptions-item>
</el-descriptions>
<el-form label-width="100px" style="margin-top: 20px;" v-if="approvalData.auditComment">
<el-form-item label="审批意见">
<el-input
:value="approvalData.auditComment"
type="textarea"
:rows="3"
readonly
/>
</el-form-item>
</el-form>
</el-card>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="handleClose">关闭</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup name="ViewDialog" lang="ts">
import {
getAssessmentApprovalDetail
} from '@/api/bzrkh/assessmentApproval';
import {
AssessmentApprovalVO,
AssessmentApprovalDetailVO,
AssessmentApprovalIndicatorVO,
AssessmentApprovalSpecialWorkVO
} from '@/api/bzrkh/assessmentApproval/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { bmzr_audit_status } = proxy?.useDict('bmzr_audit_status');
const visible = ref(false);
const loading = ref(false);
const currentRow = ref<AssessmentApprovalVO>();
const viewDetail = ref<AssessmentApprovalDetailVO>();
const routineWorkScores = ref<AssessmentApprovalIndicatorVO[]>([]);
const specialWorkScores = ref<AssessmentApprovalSpecialWorkVO[]>([]);
// 班级管理实效数据
const managementEffectivenessData = reactive({
classDeduction: 0,
classDeductionHalf: 0,
selfComment: '',
superiorScore: 0,
superiorComment: ''
});
// 月考核得分数据
const monthlyScoreData = reactive({
selfOverallComment: '',
superiorOverallComment: ''
});
// 审批数据
const approvalData = reactive({
auditComment: ''
});
const dialogTitle = computed(() => {
const className = viewDetail.value?.classDetail?.className || '';
return `${className} - 班主任考核查看`;
});
/** 获取班级层次文本 */
const getClassTypeText = (classType?: string) => {
const typeMap: Record<string, string> = {
'1': '中级工班',
'2': '高级工班',
'3': '预备技师班',
'4': '技师班',
'5': '中高职一体'
};
return typeMap[classType || ''] || '未知';
};
/** 格式化数字显示 */
const formatNumber = (value?: number | string, precision = 4) => {
if (value === undefined || value === null || value === '') {
return '0.' + '0'.repeat(precision);
}
const numValue = typeof value === 'string' ? parseFloat(value) : value;
if (isNaN(numValue)) {
return '0.' + '0'.repeat(precision);
}
return numValue.toFixed(precision);
};
/** 计算月考核得分 */
const calculateMonthlyScore = () => {
// 总系数(K)
const totalCoefficient = viewDetail.value?.coefficient?.totalCoefficient || 0;
// 班主任常规工作自评分之和
const routineWorkTotal = routineWorkScores.value.reduce((sum, item) => sum + (item.selfScore || 0), 0);
// 按班级扣分50%计的分值
const deductionHalf = managementEffectivenessData.classDeductionHalf || 0;
// 特色工作总分值
const specialWorkTotal = specialWorkScores.value.reduce((sum, item) => sum + (item.score || 0), 0);
// 月考核得分 = 总系数(K)* (班主任常规工作自评分之和 - 按班级扣分50%计的分值 + 特色工作总分值)
return totalCoefficient * (routineWorkTotal - deductionHalf + specialWorkTotal);
};
/** 打开弹窗 */
const open = async (row: AssessmentApprovalVO) => {
if (!row.planId || !row.classId || !row.evaluatedUserId) {
proxy?.$modal.msgError('参数错误:缺少必要的ID信息');
return;
}
currentRow.value = row;
visible.value = true;
await loadViewDetail();
};
/** 加载查看详情数据 */
const loadViewDetail = async () => {
if (!currentRow.value?.planId || !currentRow.value?.classId || !currentRow.value?.evaluatedUserId) {
return;
}
loading.value = true;
try {
const res = await getAssessmentApprovalDetail(
currentRow.value.planId,
currentRow.value.classId,
currentRow.value.evaluatedUserId
);
viewDetail.value = res.data;
// 初始化班主任常规工作数据
routineWorkScores.value = viewDetail.value?.routineWorkIndicators || [];
// 初始化班级管理实效数据
if (viewDetail.value?.classDeductionIndicator) {
const indicator = viewDetail.value.classDeductionIndicator;
managementEffectivenessData.classDeduction = indicator.selfScore || 0;
managementEffectivenessData.classDeductionHalf = (indicator.selfScore || 0) * 0.5;
managementEffectivenessData.selfComment = indicator.selfComment || '';
managementEffectivenessData.superiorScore = indicator.superiorScore || 0;
managementEffectivenessData.superiorComment = indicator.superiorComment || '';
}
// 初始化特色工作数据
specialWorkScores.value = viewDetail.value?.specialWorkIndicators || [];
// 初始化月考核得分数据
monthlyScoreData.selfOverallComment = viewDetail.value?.selfOverallComment || '';
monthlyScoreData.superiorOverallComment = viewDetail.value?.superiorOverallComment || '';
// 初始化审批数据
// 这里需要根据实际的后端字段调整
approvalData.auditComment = '';
} catch (error) {
console.error('加载查看详情失败:', error);
proxy?.$modal.msgError('加载查看详情失败');
} finally {
loading.value = false;
}
};
/** 关闭弹窗 */
const handleClose = () => {
visible.value = false;
// 重置数据
routineWorkScores.value = [];
specialWorkScores.value = [];
Object.assign(managementEffectivenessData, {
classDeduction: 0,
classDeductionHalf: 0,
selfComment: '',
superiorScore: 0,
superiorComment: ''
});
Object.assign(monthlyScoreData, {
selfOverallComment: '',
superiorOverallComment: ''
});
Object.assign(approvalData, {
auditComment: ''
});
};
// 暴露给父组件的方法
defineExpose({
open
});
</script>
<style scoped>
.view-dialog-content {
max-height: 70vh;
overflow-y: auto;
}
.info-card {
margin-bottom: 16px;
}
.info-card:last-child {
margin-bottom: 0;
}
.card-header {
font-weight: 600;
color: #303133;
text-align: center;
}
/* 表格样式 */
:deep(.el-table) {
border-radius: 4px;
}
:deep(.el-table th) {
background-color: #f5f7fa;
color: #606266;
font-weight: 600;
}
/* 班主任常规工作表格样式优化 */
:deep(.routine-work-table) {
.el-table__body-wrapper {
max-height: 350px;
overflow-y: auto;
}
.el-table__row {
height: auto;
}
.el-table__cell {
padding: 8px 0;
vertical-align: middle;
}
}
/* 特色工作表格样式优化 */
:deep(.special-work-table) {
.el-table__row {
height: auto;
}
.el-table__cell {
padding: 8px 0;
vertical-align: middle;
}
}
/* 文本省略样式 */
.text-ellipsis {
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 160px;
}
/* 表单样式优化 */
:deep(.el-form-item__label) {
font-weight: 500;
text-align: center;
}
/* 描述列表居中样式 */
:deep(.el-descriptions) {
.el-descriptions__label {
text-align: center;
font-weight: 500;
}
.el-descriptions__content {
text-align: center;
}
}
/* 只读输入框样式 */
:deep(.el-input.is-disabled .el-input__wrapper) {
background-color: #f5f7fa;
}
</style>
+91 -40
View File
@@ -35,15 +35,9 @@
<!-- 表格区域 -->
<el-card shadow="never" class="button-card table-card">
<template #header>
<!-- <el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Edit" @click="() => handleSubmitAssessment()" :disabled="!hasSelectedPlan"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="View" @click="() => handleViewAssessment()" :disabled="!hasSelectedPlan"></el-button>
</el-col>
<el-row :gutter="10" class="mb8">
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row> -->
</el-row>
</template>
<div class="table-container">
@@ -70,6 +64,15 @@
<span v-else class="text-gray-400">未设置</span>
</template>
</el-table-column>
<el-table-column label="审核状态" align="center" width="120">
<template #default="scope">
<el-tag v-if="!scope.row.submitted" type="info" effect="plain">未提交</el-tag>
<el-tag v-else-if="scope.row.auditStatus === '0'" type="warning" effect="plain">待审核</el-tag>
<el-tag v-else-if="scope.row.auditStatus === '1'" type="success" effect="plain">审核通过</el-tag>
<el-tag v-else-if="scope.row.auditStatus === '2'" type="danger" effect="plain">审核不通过</el-tag>
<el-tag v-else type="info" effect="plain">未知状态</el-tag>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
@@ -77,15 +80,30 @@
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="提交考核" placement="top">
<el-button
link
type="primary"
icon="Edit"
:disabled="loading || !isDataReady"
@click="handleSubmitAssessment(scope.row)"
></el-button>
</el-tooltip>
<!-- 未提交状态:显示提交考核按钮 -->
<template v-if="!scope.row.submitted">
<el-tooltip content="提交考核" placement="top">
<el-button
link
type="primary"
icon="Edit"
:disabled="loading || !isDataReady"
@click="handleSubmitAssessment(scope.row)"
></el-button>
</el-tooltip>
</template>
<!-- 已提交状态:显示撤销按钮 -->
<template v-else>
<el-tooltip content="撤销提交" placement="top">
<el-button
link
type="warning"
icon="RefreshLeft"
:disabled="loading || !isDataReady || scope.row.auditStatus !== '0'"
@click="handleWithdrawAssessment(scope.row)"
></el-button>
</el-tooltip>
</template>
<el-tooltip content="查看考核" placement="top">
<el-button
link
@@ -129,7 +147,8 @@ import {
listTeacherClasses,
listTeacherAssessmentPlans,
submitAssessment,
getAssessmentDetail
getAssessmentDetail,
withdrawAssessment
} from '@/api/bzrkh/teacherAssessment';
import {
TeacherClassVO,
@@ -147,8 +166,7 @@ const assessmentPlanList = ref<TeacherAssessmentPlanVO[]>([]);
const loading = ref(true);
const showSearch = ref(true);
const activeTab = ref<string>('');
const selectedPlans = ref<TeacherAssessmentPlanVO[]>([]);
const hasSelectedPlan = ref(false);
const total = ref(0);
// 考核提交相关状态
@@ -235,8 +253,7 @@ const resetQuery = () => {
/** 多选框选中数据 */
const handleSelectionChange = (selection: TeacherAssessmentPlanVO[]) => {
selectedPlans.value = selection;
hasSelectedPlan.value = selection.length > 0;
// 不再需要处理批量选择逻辑
};
/** 排序触发事件 */
@@ -250,25 +267,19 @@ const sortChange = (column: any) => {
};
/** 提交考核 */
const handleSubmitAssessment = async (row?: TeacherAssessmentPlanVO) => {
const plans = row ? [row] : selectedPlans.value;
if (plans.length === 0) {
const handleSubmitAssessment = async (row: TeacherAssessmentPlanVO) => {
if (!row) {
proxy?.$modal.msgWarning('请选择要提交考核的计划');
return;
}
if (plans.length > 1) {
proxy?.$modal.msgWarning('每次只能提交一个考核计划');
return;
}
// 验证数据是否已准备就绪
if (!isDataReady.value) {
proxy?.$modal.msgWarning('数据加载中,请稍后再试');
return;
}
const plan = plans[0];
const plan = row;
// 确保计划ID存在
if (!plan.id) {
@@ -295,9 +306,8 @@ const handleSubmitAssessment = async (row?: TeacherAssessmentPlanVO) => {
};
/** 查看考核 */
const handleViewAssessment = async (row?: TeacherAssessmentPlanVO) => {
const plans = row ? [row] : selectedPlans.value;
if (plans.length === 0) {
const handleViewAssessment = async (row: TeacherAssessmentPlanVO) => {
if (!row) {
proxy?.$modal.msgWarning('请选择要查看考核的计划');
return;
}
@@ -307,11 +317,9 @@ const handleViewAssessment = async (row?: TeacherAssessmentPlanVO) => {
proxy?.$modal.msgWarning('数据加载中,请稍后再试');
return;
}
const plan = plans[0];
// 确保计划ID存在
if (!plan.id) {
if (!row.id) {
proxy?.$modal.msgError('考核计划ID无效');
return;
}
@@ -327,13 +335,56 @@ const handleViewAssessment = async (row?: TeacherAssessmentPlanVO) => {
proxy?.$modal.msg('查看考核功能待实现');
};
/** 撤销考核提交 */
const handleWithdrawAssessment = async (row: TeacherAssessmentPlanVO) => {
// 验证数据是否已准备就绪
if (!isDataReady.value) {
proxy?.$modal.msgWarning('数据加载中,请稍后再试');
return;
}
// 确保计划ID存在
if (!row.id) {
proxy?.$modal.msgError('考核计划ID无效');
return;
}
// 检查提交状态,只有待审核状态才能撤销
if (row.auditStatus !== '0') {
proxy?.$modal.msgWarning('只有待审核状态的考核才能撤销');
return;
}
const currentClass = teacherClasses.value.find(c => c.id?.toString() === activeTab.value);
if (!currentClass || !currentClass.id) {
proxy?.$modal.msgError('获取班级信息失败,请刷新页面后重试');
return;
}
try {
// 确认撤销操作
await proxy?.$modal.confirm('确定要撤销该考核提交吗?撤销后可以重新修改和提交。');
// 调用撤销API
await withdrawAssessment(row.id, currentClass.id);
proxy?.$modal.msgSuccess('撤销成功');
// 刷新列表
await getList();
} catch (error) {
if (error !== 'cancel') {
console.error('撤销考核提交失败:', error);
proxy?.$modal.msgError('撤销失败,请重试');
}
}
};
/** 考核提交成功回调 */
const handleSubmitSuccess = () => {
// 刷新考核计划列表
getList();
// 清空选择
selectedPlans.value = [];
hasSelectedPlan.value = false;
};
onMounted(() => {
@@ -22,74 +22,82 @@
</el-descriptions>
</el-card>
<!-- 2. 人数系数卡片 -->
<el-card shadow="never" class="info-card">
<template #header>
<div class="card-header">
<span>人数系数(K2)</span>
</div>
</template>
<el-descriptions :column="2" border>
<el-descriptions-item label="班级总人数">{{ assessmentDetail?.classDetail?.totalStudentCount || 0 }}人</el-descriptions-item>
<el-descriptions-item label="人数系数">{{ formatNumber(assessmentDetail?.coefficient?.studentCountCoefficient, 4) }}</el-descriptions-item>
</el-descriptions>
</el-card>
<!-- 2. 总系数(K)与层次系数(K1)并排 -->
<el-row :gutter="20" class="info-card">
<el-col :span="12">
<el-card shadow="never">
<template #header>
<div class="card-header">
<span>总系数(K)</span>
</div>
</template>
<el-descriptions :column="1" border>
<el-descriptions-item label="总系数">{{ formatNumber(assessmentDetail?.coefficient?.totalCoefficient, 3) }}</el-descriptions-item>
</el-descriptions>
</el-card>
</el-col>
<el-col :span="12">
<el-card shadow="never">
<template #header>
<div class="card-header">
<span>层次系数(K1)</span>
</div>
</template>
<el-descriptions :column="2" border>
<el-descriptions-item label="班级学历层级">{{ getClassTypeText(assessmentDetail?.classDetail?.classType) }}</el-descriptions-item>
<el-descriptions-item label="层次系数">{{ formatNumber(assessmentDetail?.coefficient?.levelCoefficient, 3) }}</el-descriptions-item>
</el-descriptions>
</el-card>
</el-col>
</el-row>
<!-- 3. 住校生系数卡片 -->
<el-card shadow="never" class="info-card">
<template #header>
<div class="card-header">
<span>住校生系数(K3)</span>
</div>
</template>
<el-descriptions :column="2" border>
<el-descriptions-item label="住校生人数">{{ assessmentDetail?.classDetail?.boardingStudentCount || 0 }}人</el-descriptions-item>
<el-descriptions-item label="住校生系数">{{ formatNumber(assessmentDetail?.coefficient?.boardingCoefficient, 4) }}</el-descriptions-item>
</el-descriptions>
</el-card>
<!-- 3. 人数系数(K2)与住校生系数(K3)并排 -->
<el-row :gutter="20" class="info-card">
<el-col :span="12">
<el-card shadow="never">
<template #header>
<div class="card-header">
<span>人数系数(K2)</span>
</div>
</template>
<el-descriptions :column="2" border>
<el-descriptions-item label="班级总人数">{{ assessmentDetail?.classDetail?.totalStudentCount || 0 }}人</el-descriptions-item>
<el-descriptions-item label="人数系数">{{ formatNumber(assessmentDetail?.coefficient?.studentCountCoefficient, 3) }}</el-descriptions-item>
</el-descriptions>
</el-card>
</el-col>
<el-col :span="12">
<el-card shadow="never">
<template #header>
<div class="card-header">
<span>住校生系数(K3)</span>
</div>
</template>
<el-descriptions :column="2" border>
<el-descriptions-item label="住校生人数">{{ assessmentDetail?.classDetail?.boardingStudentCount || 0 }}人</el-descriptions-item>
<el-descriptions-item label="住校生系数">{{ formatNumber(assessmentDetail?.coefficient?.boardingCoefficient, 3) }}</el-descriptions-item>
</el-descriptions>
</el-card>
</el-col>
</el-row>
<!-- 4. 层次系数卡片 -->
<el-card shadow="never" class="info-card">
<template #header>
<div class="card-header">
<span>层次系数(K1)</span>
</div>
</template>
<el-descriptions :column="2" border>
<el-descriptions-item label="班级学历层级">{{ getClassTypeText(assessmentDetail?.classDetail?.classType) }}</el-descriptions-item>
<el-descriptions-item label="层次系数">{{ formatNumber(assessmentDetail?.coefficient?.levelCoefficient, 4) }}</el-descriptions-item>
</el-descriptions>
</el-card>
<!-- 5. 总系数卡片 -->
<el-card shadow="never" class="info-card">
<template #header>
<div class="card-header">
<span>总系数(K)</span>
</div>
</template>
<el-descriptions :column="1" border>
<el-descriptions-item label="总系数">{{ formatNumber(assessmentDetail?.coefficient?.totalCoefficient, 6) }}</el-descriptions-item>
</el-descriptions>
</el-card>
<!-- 6. 班主任常规工作(50分)卡片 -->
<!-- 4. 班主任常规工作(50分)卡片 -->
<el-card shadow="never" class="info-card">
<template #header>
<div class="card-header">
<span>班主任常规工作(50分)</span>
</div>
</template>
<el-table border :data="routineWorkScores" style="width: 100%">
<el-table border :data="routineWorkScores" style="width: 100%" max-height="400" class="routine-work-table">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="indicatorName" label="指标名称" align="center" :show-overflow-tooltip="true" />
<el-table-column prop="description" label="指标描述" align="center" :show-overflow-tooltip="true" />
<el-table-column prop="indicatorName" label="指标名称" min-width="180" align="center" :show-overflow-tooltip="true" />
<el-table-column prop="description" label="指标描述" min-width="200" align="center" :show-overflow-tooltip="true" />
<el-table-column prop="score" label="指标分值" width="100" align="center">
<template #default="scope">
<span>{{ scope.row.score || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="自评分数" width="120" align="center">
<el-table-column label="自评分数" width="130" align="center">
<template #default="scope">
<el-input-number
v-model="scope.row.selfScore"
@@ -99,10 +107,11 @@
controls-position="right"
style="width: 100%"
placeholder="请输入分数"
size="small"
/>
</template>
</el-table-column>
<el-table-column label="自评意见" width="200" align="center">
<el-table-column label="自评意见" width="220" align="center">
<template #default="scope">
<el-input
v-model="scope.row.selfComment"
@@ -111,20 +120,21 @@
placeholder="请输入自评意见"
maxlength="200"
show-word-limit
size="small"
/>
</template>
</el-table-column>
</el-table>
</el-card>
<!-- 7. 班级管理实效(50分)卡片 -->
<!-- 5. 班级管理实效(50分)卡片 -->
<el-card shadow="never" class="info-card">
<template #header>
<div class="card-header">
<span>班级管理实效(50分)</span>
</div>
</template>
<el-form :model="managementEffectivenessForm" label-width="150px">
<el-form :model="managementEffectivenessForm" label-width="150px" class="management-effectiveness-form">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="班级扣分">
@@ -144,7 +154,7 @@
<el-input
:value="managementEffectivenessForm.classDeductionHalf?.toFixed(2) || '0.00'"
readonly
style="width: 100%"
style="width: 100%; text-align: center;"
/>
</el-form-item>
</el-col>
@@ -171,17 +181,17 @@
</el-form>
</el-card>
<!-- 8. 特色工作(加20分)卡片 -->
<!-- 6. 特色工作(加20分)卡片 -->
<el-card shadow="never" class="info-card">
<template #header>
<div class="card-header">
<span>特色工作(加20分)</span>
</div>
</template>
<el-form :model="specialWorkForm" label-width="200px">
<el-form :model="specialWorkForm" label-width="240px" class="special-work-form">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="及时并妥善处理好学生违纪事件">
<el-form-item label="及时并妥善处理好学生违纪事件" class="no-wrap-label">
<el-input-number
v-model="specialWorkForm.score1"
:min="0"
@@ -237,7 +247,7 @@
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="班级宣传工作有特色">
<el-form-item label="班级宣传工作有特色" class="no-wrap-label">
<el-input-number
v-model="specialWorkForm.score3"
:min="0"
@@ -297,7 +307,7 @@
<el-input
:value="specialWorkForm.totalScore?.toFixed(2) || '0.00'"
readonly
style="width: 100%"
style="width: 100%; text-align: center;"
/>
</el-form-item>
</el-col>
@@ -305,21 +315,21 @@
</el-form>
</el-card>
<!-- 9. 月考核得分卡片 -->
<!-- 7. 月考核得分卡片 -->
<el-card shadow="never" class="info-card">
<template #header>
<div class="card-header">
<span>月考核得分</span>
</div>
</template>
<el-form :model="monthlyScoreForm" label-width="100px">
<el-form :model="monthlyScoreForm" label-width="100px" class="monthly-score-form">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="月考核得分">
<el-input
:value="calculateMonthlyScore().toFixed(2)"
readonly
style="width: 100%"
style="width: 100%; text-align: center;"
/>
</el-form-item>
</el-col>
@@ -345,6 +355,7 @@
<template #footer>
<div class="dialog-footer">
<el-button :loading="submitLoading" type="primary" @click="handleSubmit">保存</el-button>
<el-button :loading="submitLoading" type="success" @click="handleSubmitForApproval">提交</el-button>
<el-button @click="handleClose">取消</el-button>
</div>
</template>
@@ -354,7 +365,8 @@
<script setup name="SubmitDialog" lang="ts">
import {
getAssessmentSubmitDetail,
submitAssessmentScore
submitAssessmentScore,
submitAssessment
} from '@/api/bzrkh/teacherAssessment';
import {
AssessmentDetailVO,
@@ -548,7 +560,7 @@ const handleViewStudentViolations = () => {
proxy?.$modal.msg('学生违规处分信息查看功能暂未实现');
};
/** 提交考核 */
/** 保存考核数据 */
const handleSubmit = async () => {
try {
// 验证必填项
@@ -602,13 +614,83 @@ const handleSubmit = async () => {
};
await submitAssessmentScore(submitData);
proxy?.$modal.msgSuccess('考核提交成功');
proxy?.$modal.msgSuccess('考核保存成功');
emit('success');
} catch (error) {
console.error('保存考核失败:', error);
proxy?.$modal.msgError('保存考核失败');
} finally {
submitLoading.value = false;
}
};
/** 提交到审批流程 */
const handleSubmitForApproval = async () => {
try {
// 验证必填项
if (routineWorkScores.value.some(item => item.selfScore === undefined || item.selfScore === null)) {
proxy?.$modal.msgWarning('请完善班主任常规工作的自评分数');
return;
}
// 验证必要参数
if (!props.planId || !props.classId) {
proxy?.$modal.msgError('缺少必要参数:计划ID或班级ID');
return;
}
submitLoading.value = true;
// 构造提交数据
const submitData: AssessmentSubmitVO = {
planId: props.planId,
classId: props.classId,
routineWorkScores: routineWorkScores.value,
classDeduction: managementEffectivenessForm.classDeduction,
classDeductionComment: managementEffectivenessForm.selfComment,
specialWorkScores: [
{
indicatorCode: 'bzrtsgz001',
indicatorName: '及时并妥善处理好学生违纪事件',
score: specialWorkForm.score1,
selfComment: specialWorkForm.comment1
},
{
indicatorCode: 'bzrtsgz002',
indicatorName: '班级活动获奖情况',
score: specialWorkForm.score2,
selfComment: specialWorkForm.comment2
},
{
indicatorCode: 'bzrtsgz003',
indicatorName: '班级宣传工作有特色',
score: specialWorkForm.score3,
selfComment: specialWorkForm.comment3
},
{
indicatorCode: 'bzrtsgz004',
indicatorName: '其他',
score: specialWorkForm.score4,
selfComment: specialWorkForm.comment4
}
],
overallComment: monthlyScoreForm.overallComment
};
// 第一步:保存考核评分数据
await submitAssessmentScore(submitData);
// 第二步:提交到审批流程
await submitAssessment(props.planId, props.classId);
proxy?.$modal.msgSuccess('考核提交成功,已进入审批流程');
emit('success');
handleClose();
} catch (error) {
console.error('提交考核失败:', error);
proxy?.$modal.msgError('提交考核失败');
console.error('提交审批失败:', error);
proxy?.$modal.msgError('提交审批失败');
} finally {
submitLoading.value = false;
}
@@ -617,6 +699,7 @@ const handleSubmit = async () => {
/** 关闭弹窗 */
const handleClose = () => {
visible.value = false;
// 重置表单数据
routineWorkScores.value = [];
Object.assign(managementEffectivenessForm, {
@@ -663,6 +746,7 @@ defineExpose({
.card-header {
font-weight: 600;
color: #303133;
text-align: center;
}
/* 表格样式 */
@@ -676,11 +760,88 @@ defineExpose({
font-weight: 600;
}
/* 班主任常规工作表格样式优化 */
:deep(.routine-work-table) {
.el-table__body-wrapper {
max-height: 350px;
overflow-y: auto;
}
.el-table__row {
height: auto;
}
.el-table__cell {
padding: 8px 0;
vertical-align: middle;
}
/* 优化输入框在表格中的显示 */
.el-input-number {
width: 100% !important;
}
.el-textarea__inner {
resize: none;
min-height: 60px !important;
}
/* 响应式调整 */
@media (max-width: 1400px) {
.el-table__cell {
padding: 6px 4px;
}
}
}
/* 特色工作表单样式优化 */
:deep(.special-work-form) {
.no-wrap-label .el-form-item__label {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1.4;
}
.el-form-item__label {
font-weight: 500;
text-align: center;
}
}
/* 月考核得分表单样式优化 */
:deep(.monthly-score-form) {
.el-form-item__label {
text-align: center;
font-weight: 500;
}
}
/* 班级管理实效表单样式优化 */
:deep(.management-effectiveness-form) {
.el-form-item__label {
text-align: center;
font-weight: 500;
}
}
/* 表单样式 */
:deep(.el-form-item__label) {
font-weight: 500;
}
/* 描述列表居中样式 */
:deep(.el-descriptions) {
.el-descriptions__label {
text-align: center;
font-weight: 500;
}
.el-descriptions__content {
text-align: center;
}
}
/* 只读输入框样式 */
:deep(.el-input.is-disabled .el-input__wrapper) {
background-color: #f5f7fa;