“0823会议问题修改”

This commit is contained in:
weizhong committed 2025-08-24 23:37:48 +08:00
1 parent ff261194e3
commit 8311111c29
33 files changed
+1029 -1096

No files matched your search

@@ -11,7 +11,6 @@ import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.rs.domain.RsTrainingApplication;
import org.dromara.rs.domain.RsTrainingCourse;
import org.dromara.rs.service.IRsTrainingApplicationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
@@ -42,7 +41,7 @@ public class RsTrainingApplicationController extends BaseController {
/**
* 查询培训申请列表
*/
@SaCheckPermission("rs:training:application:list")
@SaCheckPermission("rs:trainingapplication:list")
@GetMapping("/list")
public TableDataInfo<RsTrainingApplication> list(RsTrainingApplication application, PageQuery pageQuery) {
return trainingApplicationService.selectPageRsTrainingApplicationList(application, pageQuery);
@@ -51,7 +50,7 @@ public class RsTrainingApplicationController extends BaseController {
/**
* 导出培训申请列表
*/
@SaCheckPermission("rs:training:application:export")
@SaCheckPermission("rs:trainingapplication:export")
@Log(title = "培训申请", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, RsTrainingApplication application) {
@@ -62,7 +61,7 @@ public class RsTrainingApplicationController extends BaseController {
/**
* 获取培训申请详细信息
*/
@SaCheckPermission("rs:training:application:query")
@SaCheckPermission("rs:trainingapplication:query")
@GetMapping("/{applicationId}")
public R<RsTrainingApplication> getInfo(@PathVariable("applicationId") Long applicationId) {
return R.ok(trainingApplicationService.selectRsTrainingApplicationById(applicationId));
@@ -71,7 +70,7 @@ public class RsTrainingApplicationController extends BaseController {
/**
* 新增培训申请
*/
@SaCheckPermission("rs:training:application:add")
@SaCheckPermission("rs:trainingapplication:add")
@Log(title = "培训申请", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping
@@ -124,7 +123,7 @@ public class RsTrainingApplicationController extends BaseController {
/**
* 修改培训申请
*/
@SaCheckPermission("rs:training:application:edit")
@SaCheckPermission("rs:trainingapplication:edit")
@Log(title = "培训申请", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping
@@ -135,7 +134,7 @@ public class RsTrainingApplicationController extends BaseController {
/**
* 删除培训申请
*/
@SaCheckPermission("rs:training:application:remove")
@SaCheckPermission("rs:trainingapplication:remove")
@Log(title = "培训申请", businessType = BusinessType.DELETE)
@DeleteMapping("/{applicationIds}")
public R<Void> remove(@PathVariable Long[] applicationIds) {
@@ -145,7 +144,7 @@ public class RsTrainingApplicationController extends BaseController {
/**
* 取消培训申请
*/
@SaCheckPermission("rs:training:application:edit")
@SaCheckPermission("rs:trainingapplication:edit")
@Log(title = "培训申请", businessType = BusinessType.UPDATE)
@PutMapping("/cancel/{applicationId}")
public R<Void> cancel(@PathVariable("applicationId") Long applicationId) {
@@ -155,7 +154,7 @@ public class RsTrainingApplicationController extends BaseController {
/**
* 查询我的培训申请列表
*/
@SaCheckPermission("rs:training:application:query")
@SaCheckPermission("rs:trainingapplication:query")
@GetMapping("/my")
public TableDataInfo<RsTrainingApplication> listMyApplications(RsTrainingApplication application, PageQuery pageQuery) {
return trainingApplicationService.selectPageMyApplications(StpUtil.getLoginIdAsLong(), application, pageQuery);
@@ -164,7 +163,7 @@ public class RsTrainingApplicationController extends BaseController {
/**
* 查询指定课程的申请列表
*/
@SaCheckPermission("rs:training:application:list")
@SaCheckPermission("rs:trainingapplication:list")
@GetMapping("/list/{courseId}")
public TableDataInfo<RsTrainingApplication> listByCourse(@PathVariable("courseId") Long courseId, RsTrainingApplication application, PageQuery pageQuery) {
return trainingApplicationService.selectPageApplicationsByCourse(courseId, application, pageQuery);
@@ -227,7 +226,7 @@ public class RsTrainingApplicationController extends BaseController {
/**
* 更新培训申请状态
*/
@SaCheckPermission("rs:training:application:edit")
@SaCheckPermission("rs:trainingapplication:edit")
@Log(title = "培训申请状态", businessType = BusinessType.UPDATE)
@PutMapping("/status/{applicationId}/{status}")
public R<Void> updateStatus(
@@ -240,7 +239,7 @@ public class RsTrainingApplicationController extends BaseController {
/**
* 重新提交被拒绝的培训申请
*/
@SaCheckPermission("rs:training:application:edit")
@SaCheckPermission("rs:trainingapplication:edit")
@Log(title = "重新提交培训申请", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/resubmit/{applicationId}")
@@ -38,7 +38,7 @@ public class RsTrainingApprovalController extends BaseController {
/**
* 查询培训审批列表
*/
@SaCheckPermission("rs:training:approval:list")
@SaCheckPermission("rs:trainingapproval:list")
@GetMapping("/list")
public TableDataInfo<RsTrainingApproval> list(RsTrainingApproval approval, PageQuery pageQuery) {
// 使用带详细信息的查询方法,返回申请人姓名和课程名称
@@ -48,7 +48,7 @@ public class RsTrainingApprovalController extends BaseController {
/**
* 获取培训审批详细信息
*/
@SaCheckPermission("rs:training:approval:query")
@SaCheckPermission("rs:trainingapproval:query")
@GetMapping("/{approvalId}")
public R<RsTrainingApproval> getInfo(@PathVariable("approvalId") Long approvalId) {
return R.ok(trainingApprovalService.selectRsTrainingApprovalById(approvalId));
@@ -57,7 +57,7 @@ public class RsTrainingApprovalController extends BaseController {
/**
* 新增培训审批
*/
@SaCheckPermission("rs:training:approval:add")
@SaCheckPermission("rs:trainingapproval:add")
@Log(title = "培训审批", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping
@@ -68,7 +68,7 @@ public class RsTrainingApprovalController extends BaseController {
/**
* 修改培训审批
*/
@SaCheckPermission("rs:training:approval:edit")
@SaCheckPermission("rs:trainingapproval:edit")
@Log(title = "培训审批", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping
@@ -79,7 +79,7 @@ public class RsTrainingApprovalController extends BaseController {
/**
* 删除培训审批
*/
@SaCheckPermission("rs:training:approval:remove")
@SaCheckPermission("rs:trainingapproval:remove")
@Log(title = "培训审批", businessType = BusinessType.DELETE)
@DeleteMapping("/{approvalIds}")
public R<Void> remove(@PathVariable Long[] approvalIds) {
@@ -89,7 +89,7 @@ public class RsTrainingApprovalController extends BaseController {
/**
* 查询待我审批的列表
*/
@SaCheckPermission("rs:training:approval:process")
@SaCheckPermission("rs:trainingapproval:process")
@GetMapping("/pending")
public TableDataInfo<RsTrainingApproval> listPendingApprovals(RsTrainingApproval approval, PageQuery pageQuery) {
return trainingApprovalService.selectPagePendingApprovals(StpUtil.getLoginIdAsLong(), approval, pageQuery);
@@ -98,7 +98,7 @@ public class RsTrainingApprovalController extends BaseController {
/**
* 处理审批
*/
@SaCheckPermission("rs:training:approval:process")
@SaCheckPermission("rs:trainingapproval:process")
@Log(title = "培训审批", businessType = BusinessType.UPDATE)
@PutMapping("/process/{applicationId}/{status}")
public R<Void> processApproval(@PathVariable("applicationId") Long applicationId, @PathVariable("status") String status, @RequestBody(required = false) Map<String, String> params) {
@@ -109,7 +109,7 @@ public class RsTrainingApprovalController extends BaseController {
/**
* 查询申请审批历史
*/
@SaCheckPermission("rs:training:approval:query")
@SaCheckPermission("rs:trainingapproval:query")
@GetMapping("/history/{applicationId}")
public R<List<RsTrainingApproval>> getApprovalHistory(@PathVariable("applicationId") Long applicationId) {
System.out.println("查询审批历史记录 - applicationId: " + applicationId);
@@ -1,124 +0,0 @@
package org.dromara.rs.controller;
import java.util.List;
import org.dromara.common.core.domain.R;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.rs.domain.RsTrainingCourse;
import org.dromara.rs.service.IRsTrainingCourseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaIgnore;
import jakarta.servlet.http.HttpServletResponse;
/**
* 培训课程控制器
*
* @author weizzzz
* @date 2025-07-16
*/
@RestController
@RequestMapping("/rs/training/course")
public class RsTrainingCourseController extends BaseController {
@Autowired
private IRsTrainingCourseService trainingCourseService;
/**
* 查询培训课程列表
*/
@SaCheckPermission("rs:training:course:list")
@GetMapping("/list")
public TableDataInfo<RsTrainingCourse> list(RsTrainingCourse course, PageQuery pageQuery) {
return trainingCourseService.selectPageRsTrainingCourseList(course, pageQuery);
}
/**
* 导出培训课程列表
*/
@SaCheckPermission("rs:training:course:export")
@Log(title = "培训课程", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, RsTrainingCourse course) {
List<RsTrainingCourse> list = trainingCourseService.selectRsTrainingCourseList(course);
ExcelUtil.exportExcel(list, "培训课程", RsTrainingCourse.class, response);
}
/**
* 获取培训课程详细信息
*/
@SaCheckPermission("rs:training:course:query")
@GetMapping("/{courseId}")
public R<RsTrainingCourse> getInfo(@PathVariable("courseId") Long courseId) {
return R.ok(trainingCourseService.selectRsTrainingCourseById(courseId));
}
/**
* 新增培训课程
*/
@SaCheckPermission("rs:training:course:add")
@Log(title = "培训课程", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping
public R<Void> add(@Validated @RequestBody RsTrainingCourse course) {
return toAjax(trainingCourseService.insertRsTrainingCourse(course));
}
/**
* 修改培训课程
*/
@SaCheckPermission("rs:training:course:edit")
@Log(title = "培训课程", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping
public R<Void> edit(@Validated @RequestBody RsTrainingCourse course) {
return toAjax(trainingCourseService.updateRsTrainingCourse(course));
}
/**
* 删除培训课程
*/
@SaCheckPermission("rs:training:course:remove")
@Log(title = "培训课程", businessType = BusinessType.DELETE)
@DeleteMapping("/{courseIds}")
public R<Void> remove(@PathVariable Long[] courseIds) {
return toAjax(trainingCourseService.deleteRsTrainingCourseByIds(courseIds));
}
/**
* 切换培训课程状态
*/
@SaCheckPermission("rs:training:course:edit")
@Log(title = "培训课程", businessType = BusinessType.UPDATE)
@PutMapping("/toggle/{courseId}")
public R<Void> toggleStatus(@PathVariable("courseId") Long courseId) {
return toAjax(trainingCourseService.toggleCourseStatus(courseId));
}
/**
* 获取可用培训课程列表(不分页)
*/
@SaIgnore
@GetMapping("/available")
public R<List<RsTrainingCourse>> getAvailableCourses() {
RsTrainingCourse course = new RsTrainingCourse();
course.setStatus("0"); // 只查询状态为正常的课程
return R.ok(trainingCourseService.selectRsTrainingCourseList(course));
}
}
@@ -7,6 +7,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
@@ -26,7 +27,7 @@ public class RsTrainingApplication extends BaseEntity {
/**
* 申请ID
*/
@TableId(value = "application_id")
@TableId(value = "application_id", type = IdType.ASSIGN_ID)
private Long applicationId;
/**
@@ -34,6 +35,11 @@ public class RsTrainingApplication extends BaseEntity {
*/
private Long courseId;
/**
* 培训名称
*/
private String courseName;
/**
* 申请人ID
*/
@@ -107,11 +113,6 @@ public class RsTrainingApplication extends BaseEntity {
*/
private Long createDept;
/**
* 自定义课程名称
*/
private String courseName;
/**
* 拒绝时间
*/
@@ -1,92 +0,0 @@
package org.dromara.rs.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;
/**
* 培训课程对象 rs_training_course
*
* @author weizzzz
* @date 2025-07-16
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("rs_training_course")
public class RsTrainingCourse extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 课程ID
*/
@TableId(value = "course_id")
private Long courseId;
/**
* 课程名称
*/
private String title;
/**
* 课程类别
*/
private String category;
/**
* 课程描述
*/
private String description;
/**
* 开始时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
/**
* 结束时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
/**
* 学时数
*/
private Integer duration;
/**
* 培训地点
*/
private String location;
/**
* 最大参与人数
*/
private Integer maxParticipants;
/**
* 当前报名人数
*/
private Integer currentParticipants;
/**
* 状态(0正常 1结束)
*/
private String status;
/**
* 租户ID
*/
private String tenantId;
/** 非数据库字段 **/
@TableField(exist = false)
private Integer applicationCount;
}
@@ -7,6 +7,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import java.math.BigDecimal;
import java.util.Date;
@@ -27,7 +28,7 @@ public class RsTrainingRecord extends BaseEntity {
/**
* 记录ID
*/
@TableId(value = "record_id")
@TableId(value = "record_id", type = IdType.ASSIGN_ID)
private Long recordId;
private Long applicationId;
@@ -117,6 +118,11 @@ public class RsTrainingRecord extends BaseEntity {
private String tenantId;
private Long createDept;
/**
* 部门ID
*/
private Long deptId;
// 数据库字段 - 直接存储在培训记录表中
private String courseName;
private Integer duration;
@@ -1,14 +0,0 @@
package org.dromara.rs.mapper;
import org.dromara.rs.domain.RsTrainingCourse;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 培训课程Mapper接口
*
* @author weizzzz
* @date 2025-07-16
*/
public interface RsTrainingCourseMapper extends BaseMapperPlus<RsTrainingCourse, RsTrainingCourse> {
}
@@ -1,80 +0,0 @@
package org.dromara.rs.service;
import java.util.List;
import org.dromara.rs.domain.RsTrainingCourse;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
* 培训课程服务接口
*
* @author weizzzz
* @date 2025-07-16
*/
public interface IRsTrainingCourseService {
/**
* 查询培训课程列表
*
* @param course 培训课程
* @param pageQuery 分页参数
* @return 培训课程分页列表
*/
TableDataInfo<RsTrainingCourse> selectPageRsTrainingCourseList(RsTrainingCourse course, PageQuery pageQuery);
/**
* 查询培训课程列表
*
* @param course 培训课程
* @return 培训课程列表
*/
List<RsTrainingCourse> selectRsTrainingCourseList(RsTrainingCourse course);
/**
* 查询培训课程详细信息
*
* @param courseId 培训课程ID
* @return 培训课程
*/
RsTrainingCourse selectRsTrainingCourseById(Long courseId);
/**
* 新增培训课程
*
* @param course 培训课程
* @return 结果
*/
int insertRsTrainingCourse(RsTrainingCourse course);
/**
* 修改培训课程
*
* @param course 培训课程
* @return 结果
*/
int updateRsTrainingCourse(RsTrainingCourse course);
/**
* 批量删除培训课程
*
* @param courseIds 需要删除的培训课程ID数组
* @return 结果
*/
int deleteRsTrainingCourseByIds(Long[] courseIds);
/**
* 删除培训课程信息
*
* @param courseId 培训课程ID
* @return 结果
*/
int deleteRsTrainingCourseById(Long courseId);
/**
* 切换培训课程状态
*
* @param courseId 培训课程ID
* @return 结果
*/
int toggleCourseStatus(Long courseId);
}
@@ -1,30 +1,32 @@
package org.dromara.rs.service.impl;
import java.util.Arrays;
import java.util.List;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.dromara.rs.mapper.RsTrainingApplicationMapper;
import org.dromara.rs.mapper.RsTrainingCourseMapper;
import org.dromara.rs.domain.RsTrainingApplication;
import org.dromara.rs.domain.RsTrainingCourse;
import org.dromara.rs.domain.RsTrainingRecord;
import org.dromara.rs.domain.bo.RsTrainingApplicationBo;
import java.util.Arrays;
import org.dromara.rs.mapper.RsTrainingApplicationMapper;
import org.dromara.rs.service.IRsTrainingApplicationService;
import org.dromara.rs.service.IRsTrainingRecordService;
import org.dromara.rs.domain.RsTrainingRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.dromara.common.core.utils.DateUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import java.util.Collection;
import java.util.Date;
import java.util.List;
/**
* 培训申请服务实现类
@@ -33,29 +35,15 @@ import org.springframework.context.ApplicationContextAware;
* @date 2025-07-16
*/
@Service
public class RsTrainingApplicationServiceImpl implements IRsTrainingApplicationService, ApplicationContextAware {
@RequiredArgsConstructor
public class RsTrainingApplicationServiceImpl implements IRsTrainingApplicationService {
private static final Logger log = LoggerFactory.getLogger(RsTrainingApplicationServiceImpl.class);
@Autowired
private RsTrainingApplicationMapper trainingApplicationMapper;
private final RsTrainingApplicationMapper trainingApplicationMapper;
@Autowired
private RsTrainingCourseMapper trainingCourseMapper;
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
/**
* 获取培训记录服务(延迟获取以避免循环依赖)
*/
private IRsTrainingRecordService getRecordService() {
return applicationContext.getBean(IRsTrainingRecordService.class);
}
private IRsTrainingRecordService trainingRecordService;
/**
* 查询培训申请列表
@@ -85,9 +73,9 @@ public class RsTrainingApplicationServiceImpl implements IRsTrainingApplicationS
// 使用自定义分页查询获取列表数据
List<RsTrainingApplication> list = trainingApplicationMapper.selectRsTrainingApplicationListPage(application, offset, size);
// 处理自定义培训课程(courseId=0)的情况
// 处理自定义培训课程的情况
for (RsTrainingApplication app : list) {
if (app.getCourseId() != null && app.getCourseId() == 0 && (app.getCourseName() == null || app.getCourseName().isEmpty())) {
if (app.getCourseName() == null || app.getCourseName().isEmpty()) {
app.setCourseName("自定义培训");
}
}
@@ -194,7 +182,6 @@ public class RsTrainingApplicationServiceImpl implements IRsTrainingApplicationS
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int insertRsTrainingApplication(RsTrainingApplication application) {
try {
// 确保applicationId不为空
@@ -212,41 +199,18 @@ public class RsTrainingApplicationServiceImpl implements IRsTrainingApplicationS
}
// 处理自定义培训课程的情况(courseId = 0 或 null)
if (application.getCourseId() == null || application.getCourseId() == 0) {
// 对于自定义培训课程,不需要验证课程和更新课程报名人数
application.setCourseId(0L); // 确保courseId为0L而不是null
// 确保courseName不为空
if (application.getCourseName() == null || application.getCourseName().isEmpty()) {
application.setCourseName("自定义培训");
}
application.setCreateTime(DateUtils.getNowDate());
application.setApplyTime(DateUtils.getNowDate());
application.setStatus("0"); // 待审核状态
application.setTenantId("000000"); // 设置默认租户ID
return trainingApplicationMapper.insert(application);
// 确保courseName不为空
if (application.getCourseName() == null || application.getCourseName().isEmpty()) {
application.setCourseName("自定义培训");
}
// 1. 验证课程是否存在并可申请
RsTrainingCourse course = trainingCourseMapper.selectById(application.getCourseId());
if (course == null) {
return 0;
}
// 2. 检查是否已达到最大参与人数
if (course.getCurrentParticipants() >= course.getMaxParticipants()) {
return 0;
}
// 3. 更新课程当前报名人数
course.setCurrentParticipants(course.getCurrentParticipants() + 1);
trainingCourseMapper.updateById(course);
// 4. 保存申请信息
application.setCreateTime(DateUtils.getNowDate());
application.setApplyTime(DateUtils.getNowDate());
Date now = DateUtils.getNowDate();
application.setCreateTime(now);
application.setApplyTime(now);
application.setStatus("0"); // 待审核状态
application.setTenantId("000000"); // 设置默认租户ID
return trainingApplicationMapper.insert(application);
// 以上代码已处理所有情况
} catch (Exception e) {
e.printStackTrace();
throw e;
@@ -272,18 +236,13 @@ public class RsTrainingApplicationServiceImpl implements IRsTrainingApplicationS
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int deleteRsTrainingApplicationByIds(Long[] applicationIds) {
// 查询所有要删除的申请
List<RsTrainingApplication> applications = trainingApplicationMapper.selectBatchIds(Arrays.asList(applicationIds));
// 对每个申请,减少对应课程的当前报名人数
for (RsTrainingApplication app : applications) {
RsTrainingCourse course = trainingCourseMapper.selectById(app.getCourseId());
if (course != null && course.getCurrentParticipants() > 0) {
course.setCurrentParticipants(course.getCurrentParticipants() - 1);
trainingCourseMapper.updateById(course);
}
// 培训课程功能已移除,无需更新课程报名人数
}
return trainingApplicationMapper.deleteBatchIds(Arrays.asList(applicationIds));
@@ -296,17 +255,11 @@ public class RsTrainingApplicationServiceImpl implements IRsTrainingApplicationS
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int deleteRsTrainingApplicationById(Long applicationId) {
// 查询申请
RsTrainingApplication application = trainingApplicationMapper.selectById(applicationId);
if (application != null) {
// 减少课程的当前报名人数
RsTrainingCourse course = trainingCourseMapper.selectById(application.getCourseId());
if (course != null && course.getCurrentParticipants() > 0) {
course.setCurrentParticipants(course.getCurrentParticipants() - 1);
trainingCourseMapper.updateById(course);
}
// 培训课程功能已移除,无需更新课程报名人数
}
return trainingApplicationMapper.deleteById(applicationId);
@@ -319,23 +272,17 @@ public class RsTrainingApplicationServiceImpl implements IRsTrainingApplicationS
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int cancelApplication(Long applicationId) {
// 查询申请
RsTrainingApplication application = trainingApplicationMapper.selectById(applicationId);
if (application != null) {
// 只有待审核状态的申请才能取消
if ("0".equals(application.getStatus())) {
// 更新状态为已取消
application.setStatus("3");
application.setUpdateTime(DateUtils.getNowDate());
// 更新状态为已取消
application.setStatus("3");
application.setUpdateTime(DateUtils.getNowDate());
// 减少课程的当前报名人数
RsTrainingCourse course = trainingCourseMapper.selectById(application.getCourseId());
if (course != null && course.getCurrentParticipants() > 0) {
course.setCurrentParticipants(course.getCurrentParticipants() - 1);
trainingCourseMapper.updateById(course);
}
// 培训课程功能已移除,无需更新课程报名人数
return trainingApplicationMapper.updateById(application);
}
@@ -353,51 +300,28 @@ public class RsTrainingApplicationServiceImpl implements IRsTrainingApplicationS
@Override
public int updateApplicationStatus(Long applicationId, String status) {
RsTrainingApplication application = trainingApplicationMapper.selectById(applicationId);
if (application != null) {
application.setStatus(status);
application.setUpdateTime(DateUtils.getNowDate());
// 如果是拒绝,记录被拒绝时间
if ("2".equals(status)) {
application.setRejectTime(DateUtils.getNowDate());
}
if (application != null) {
application.setStatus(status);
Date now = DateUtils.getNowDate();
application.setUpdateTime(now);
// 如果是拒绝,记录被拒绝时间
if ("2".equals(status)) {
application.setRejectTime(now);
}
int result = trainingApplicationMapper.updateById(application);
// 同步到培训记录表:状态为"1已通过""3进行中""4已完成"时自动写入
if ("1".equals(status) || "3".equals(status) || "4".equals(status)) {
log.info("【同步培训记录】触发,applicationId={}, status={}", applicationId, status);
RsTrainingRecord exist = getRecordService().selectByApplicationId(applicationId);
if (exist == null) {
log.info("【同步培训记录】插入新记录,userId={}, courseId={}", application.getUserId(), application.getCourseId());
RsTrainingRecord record = new RsTrainingRecord();
// 设置记录ID(使用时间戳)
record.setRecordId(System.currentTimeMillis());
record.setApplicationId(application.getApplicationId());
record.setCourseId(application.getCourseId());
record.setUserId(application.getUserId());
record.setUserName(application.getUserName());
record.setDepartment(application.getDepartment());
record.setPosition(application.getPosition());
record.setReason(application.getReason());
record.setStatus(application.getStatus());
record.setApplyTime(application.getApplyTime());
record.setCurrentApprover(application.getCurrentApprover());
record.setLocation(application.getLocation());
record.setDuration(application.getDuration());
record.setStartTime(application.getStartTime());
record.setEndTime(application.getEndTime());
record.setCourseName(application.getCourseName());
record.setTenantId(application.getTenantId());
record.setCreateDept(application.getCreateDept());
record.setCreateBy(1L); // 默认系统用户
record.setCreateTime(DateUtils.getNowDate());
// 默认完成状态为进行中
record.setCompletionStatus("0");
getRecordService().insertRsTrainingRecord(record);
} else {
log.info("【同步培训记录】已存在,不重复插入,applicationId={}", applicationId);
// 如果申请通过,自动创建培训记录
if ("1".equals(status)) {
try {
createTrainingRecordFromApplication(application);
} catch (Exception e) {
log.error("创建培训记录失败: applicationId={}, error={}", applicationId, e.getMessage(), e);
// 不影响申请状态更新的结果
}
}
return result;
}
return 0;
@@ -411,7 +335,6 @@ public class RsTrainingApplicationServiceImpl implements IRsTrainingApplicationS
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int resubmitApplication(Long applicationId, RsTrainingApplication applicationData) {
// 查询原申请
RsTrainingApplication existingApp = trainingApplicationMapper.selectById(applicationId);
@@ -424,7 +347,7 @@ public class RsTrainingApplicationServiceImpl implements IRsTrainingApplicationS
return 0;
}
log.info("【重新提交申请】原申请状态: {}, 申请ID: {}", existingApp.getStatus(), applicationId);
// 更新申请数据
if (applicationData.getReason() != null) {
@@ -446,13 +369,74 @@ public class RsTrainingApplicationServiceImpl implements IRsTrainingApplicationS
existingApp.setCourseName(applicationData.getCourseName());
}
// 重置为待审核状态
existingApp.setStatus("0");
existingApp.setUpdateTime(DateUtils.getNowDate());
existingApp.setApplyTime(DateUtils.getNowDate()); // 更新申请时间
// 重置为待审核状态
existingApp.setStatus("0");
Date now = DateUtils.getNowDate();
existingApp.setUpdateTime(now);
existingApp.setApplyTime(now); // 更新申请时间
log.info("【重新提交申请】更新为待审核状态");
return trainingApplicationMapper.updateById(existingApp);
}
/**
* 根据培训申请创建培训记录
*
* @param application 培训申请
*/
private void createTrainingRecordFromApplication(RsTrainingApplication application) {
try {
// 检查是否已存在培训记录
RsTrainingRecord existingRecord = trainingRecordService.selectByApplicationId(application.getApplicationId());
if (existingRecord != null) {
log.info("培训记录已存在,不重复创建: applicationId={}, recordId={}",
application.getApplicationId(), existingRecord.getRecordId());
return;
}
// 创建新的培训记录
RsTrainingRecord record = new RsTrainingRecord();
record.setApplicationId(application.getApplicationId());
record.setCourseId(application.getCourseId());
record.setUserId(application.getUserId());
record.setUserName(application.getUserName());
record.setDepartment(application.getDepartment());
record.setPosition(application.getPosition());
record.setReason(application.getReason());
// 添加缺失的字段设置
record.setCourseName(application.getCourseName());
record.setDuration(application.getDuration());
record.setLocation(application.getLocation());
record.setStatus("3"); // 3=进行中
record.setApplyTime(application.getApplyTime());
record.setStartTime(application.getStartTime());
record.setEndTime(application.getEndTime());
record.setCompletionStatus("0"); // 0=进行中
// 设置基础字段 - 修复字段缺失问题
Date now = DateUtils.getNowDate();
record.setCreateTime(now);
record.setUpdateTime(now);
// 设置租户和用户信息
record.setTenantId(application.getTenantId() != null ? application.getTenantId() : "000000");
record.setCreateBy(application.getUserId()); // 创建者设为申请人
record.setUpdateBy(application.getUserId()); // 更新者设为申请人
record.setCreateDept(application.getCreateDept() != null ? application.getCreateDept() : 1L); // 使用createDept,如果没有则设为默认值
record.setDeptId(application.getCreateDept() != null ? application.getCreateDept() : 1L); // 设置部门ID
int result = trainingRecordService.insertRsTrainingRecord(record);
if (result > 0) {
log.info("培训记录创建成功: applicationId={}, recordId={}",
application.getApplicationId(), record.getRecordId());
} else {
log.error("培训记录创建失败: applicationId={}", application.getApplicationId());
}
} catch (Exception e) {
log.error("创建培训记录时发生异常: applicationId={}, error={}",
application.getApplicationId(), e.getMessage(), e);
throw e;
}
}
}
@@ -1,138 +0,0 @@
package org.dromara.rs.service.impl;
import java.util.Arrays;
import java.util.List;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.dromara.rs.mapper.RsTrainingCourseMapper;
import org.dromara.rs.domain.RsTrainingCourse;
import org.dromara.rs.service.IRsTrainingCourseService;
/**
* 培训课程服务实现类
*
* @author weizzzz
* @date 2025-07-16
*/
@Service
public class RsTrainingCourseServiceImpl implements IRsTrainingCourseService {
@Autowired
private RsTrainingCourseMapper trainingCourseMapper;
/**
* 查询培训课程列表
*
* @param course 培训课程
* @param pageQuery 分页参数
* @return 培训课程分页列表
*/
@Override
public TableDataInfo<RsTrainingCourse> selectPageRsTrainingCourseList(RsTrainingCourse course, PageQuery pageQuery) {
com.baomidou.mybatisplus.extension.plugins.pagination.Page<RsTrainingCourse> page = trainingCourseMapper.selectPage(pageQuery.build(), buildQueryWrapper(course));
return TableDataInfo.build(page);
}
/**
* 查询培训课程列表
*
* @param course 培训课程
* @return 培训课程列表
*/
@Override
public List<RsTrainingCourse> selectRsTrainingCourseList(RsTrainingCourse course) {
return trainingCourseMapper.selectList(buildQueryWrapper(course));
}
/**
* 查询培训课程详细信息
*
* @param courseId 培训课程ID
* @return 培训课程
*/
@Override
public RsTrainingCourse selectRsTrainingCourseById(Long courseId) {
return trainingCourseMapper.selectById(courseId);
}
/**
* 新增培训课程
*
* @param course 培训课程
* @return 结果
*/
@Override
public int insertRsTrainingCourse(RsTrainingCourse course) {
course.setCreateTime(DateUtils.getNowDate());
return trainingCourseMapper.insert(course);
}
/**
* 修改培训课程
*
* @param course 培训课程
* @return 结果
*/
@Override
public int updateRsTrainingCourse(RsTrainingCourse course) {
course.setUpdateTime(DateUtils.getNowDate());
return trainingCourseMapper.updateById(course);
}
/**
* 批量删除培训课程
*
* @param courseIds 需要删除的培训课程ID数组
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int deleteRsTrainingCourseByIds(Long[] courseIds) {
return trainingCourseMapper.deleteBatchIds(Arrays.asList(courseIds));
}
/**
* 删除培训课程信息
*
* @param courseId 培训课程ID
* @return 结果
*/
@Override
public int deleteRsTrainingCourseById(Long courseId) {
return trainingCourseMapper.deleteById(courseId);
}
/**
* 切换培训课程状态
*
* @param courseId 培训课程ID
* @return 结果
*/
@Override
public int toggleCourseStatus(Long courseId) {
RsTrainingCourse course = trainingCourseMapper.selectById(courseId);
if (course != null) {
// 切换状态:0正常 -> 1停用,或 1停用 -> 0正常
course.setStatus("0".equals(course.getStatus()) ? "1" : "0");
course.setUpdateTime(DateUtils.getNowDate());
return trainingCourseMapper.updateById(course);
}
return 0;
}
/**
* 构建查询条件
*/
private com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<RsTrainingCourse> buildQueryWrapper(RsTrainingCourse course) {
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<RsTrainingCourse> lqw = new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>();
lqw.like(course.getTitle() != null, RsTrainingCourse::getTitle, course.getTitle());
lqw.eq(course.getCategory() != null, RsTrainingCourse::getCategory, course.getCategory());
lqw.eq(course.getStatus() != null, RsTrainingCourse::getStatus, course.getStatus());
return lqw;
}
}
@@ -15,8 +15,7 @@ import org.dromara.rs.domain.RsTrainingRecord;
import org.dromara.rs.service.IRsTrainingRecordService;
import org.dromara.rs.domain.RsTrainingApplication;
import org.dromara.rs.service.IRsTrainingApplicationService;
import org.dromara.rs.domain.RsTrainingCourse;
import org.dromara.rs.service.IRsTrainingCourseService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.commons.lang3.StringUtils;
@@ -37,8 +36,7 @@ public class RsTrainingRecordServiceImpl implements IRsTrainingRecordService, Ap
@Autowired
private RsTrainingRecordMapper trainingRecordMapper;
@Autowired
private IRsTrainingCourseService courseService;
private ApplicationContext applicationContext;
@@ -303,25 +301,11 @@ public class RsTrainingRecordServiceImpl implements IRsTrainingRecordService, Ap
}
}
// 如果申请表中也没有,尝试从课程表获取
if ((StringUtils.isEmpty(record.getCourseName()) || StringUtils.isEmpty(record.getLocation()) || record.getDuration() == null)
&& record.getCourseId() != null) {
RsTrainingCourse course = courseService.selectRsTrainingCourseById(record.getCourseId());
if (course != null) {
if (StringUtils.isEmpty(record.getCourseName())) {
record.setCourseName(course.getTitle());
needUpdate = true;
}
if (StringUtils.isEmpty(record.getLocation())) {
record.setLocation(course.getLocation());
needUpdate = true;
}
if (record.getDuration() == null) {
record.setDuration(course.getDuration());
needUpdate = true;
}
}
// 培训课程功能已移除,不再从课程表获取信息
// 如果记录中仍然缺少信息,设置默认值
if (StringUtils.isEmpty(record.getCourseName())) {
record.setCourseName("自定义培训");
needUpdate = true;
}
// 更新记录
@@ -1,62 +0,0 @@
<?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.rs.mapper.RsTrainingCourseMapper">
<resultMap type="RsTrainingCourse" id="RsTrainingCourseResult">
<id property="courseId" column="course_id"/>
<result property="title" column="title"/>
<result property="category" column="category"/>
<result property="description" column="description"/>
<result property="startTime" column="start_time"/>
<result property="endTime" column="end_time"/>
<result property="duration" column="duration"/>
<result property="location" column="location"/>
<result property="maxParticipants" column="max_participants"/>
<result property="currentParticipants" column="current_participants"/>
<result property="status" column="status"/>
<result property="tenantId" column="tenant_id"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="remark" column="remark"/>
<result property="applicationCount" column="application_count"/>
</resultMap>
<sql id="selectRsTrainingCourseVo">
select c.course_id, c.title, c.category, c.description, c.start_time, c.end_time, c.duration,
c.location, c.max_participants, c.current_participants, c.status, c.tenant_id, c.create_by,
c.create_time, c.update_by, c.update_time, c.remark,
(select count(1) from rs_training_application a where a.course_id = c.course_id and a.deleted = '0' and a.tenant_id = c.tenant_id) as application_count
from rs_training_course c
</sql>
<select id="selectRsTrainingCourseList" parameterType="RsTrainingCourse" resultMap="RsTrainingCourseResult">
<include refid="selectRsTrainingCourseVo"/>
<where>
c.deleted = '0'
<if test="title != null and title != ''">
AND c.title like concat('%', #{title}, '%')
</if>
<if test="category != null and category != ''">
AND c.category = #{category}
</if>
<if test="startTime != null">
AND c.start_time = #{startTime}
</if>
<if test="endTime != null">
AND c.end_time = #{endTime}
</if>
<if test="status != null and status != ''">
AND c.status = #{status}
</if>
<if test="tenantId != null and tenantId != ''">
AND c.tenant_id = #{tenantId}
</if>
</where>
order by c.create_time desc
</select>
</mapper>
@@ -36,6 +36,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="courseName" column="course_name"/>
<result property="duration" column="duration"/>
<result property="location" column="location"/>
<result property="deptId" column="dept_id"/>
</resultMap>
<sql id="selectRsTrainingRecordVo">
@@ -43,7 +44,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
r.completion_status, r.completion_time, r.score, r.certificate_path, r.certificate_number, r.attachment_ids,
r.feedback, r.tenant_id, r.create_dept, r.create_by, r.create_time, r.update_by, r.update_time,
r.department, r.position, r.reason, r.status, r.apply_time, r.current_approver, r.start_time, r.end_time,
r.course_name, r.duration, r.location
r.course_name, r.duration, r.location, r.dept_id
from rs_training_record r
</sql>
@@ -51,6 +52,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="selectRsTrainingRecordVo"/>
<where>
r.deleted = '0'
<if test="applicationId != null">and r.application_id = #{applicationId}</if>
<if test="courseId != null">and r.course_id = #{courseId}</if>
<if test="courseName != null and courseName != ''">and r.course_name like concat('%', #{courseName}, '%')</if>
<if test="userId != null">and r.user_id = #{userId}</if>
@@ -74,12 +76,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
record_id, application_id, course_id, user_id, user_name, completion_status, completion_time, score,
certificate_path, certificate_number, attachment_ids, feedback, location, duration, apply_time,
status, course_name, department, position, reason, current_approver, start_time, end_time,
tenant_id, create_dept, create_by, create_time, deleted
tenant_id, create_dept, create_by, create_time, deleted, dept_id
) VALUES (
#{recordId}, #{applicationId}, #{courseId}, #{userId}, #{userName}, #{completionStatus}, #{completionTime}, #{score},
#{certificatePath}, #{certificateNumber}, #{attachmentIds}, #{feedback}, #{location}, #{duration}, #{applyTime},
#{status}, #{courseName}, #{department}, #{position}, #{reason}, #{currentApprover}, #{startTime}, #{endTime},
#{tenantId}, #{createDept}, #{createBy}, #{createTime}, '0'
#{tenantId}, #{createDept}, #{createBy}, #{createTime}, '0', #{deptId}
)
</insert>
@@ -109,7 +111,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="startTime != null">start_time = #{startTime},</if>
<if test="endTime != null">end_time = #{endTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime}</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="deptId != null">dept_id = #{deptId},</if>
</set>
where record_id = #{recordId}
</update>
@@ -34,7 +34,7 @@ create table rs_training_course (
drop table if exists rs_training_application;
create table rs_training_application (
application_id bigint(20) not null comment '申请ID',
course_id bigint(20) not null comment '课程ID',
course_name varchar(100) not null comment '培训名称',
user_id bigint(20) not null comment '申请人ID',
user_name varchar(50) not null comment '申请人姓名',
department varchar(50) not null comment '所属部门',
@@ -43,7 +43,13 @@ create table rs_training_application (
status char(1) default '0' comment '状态(0待审核 1已通过 2已拒绝 3进行中 4已完成)',
apply_time datetime comment '申请时间',
current_approver varchar(50) comment '当前审批人',
location varchar(200) comment '培训地点',
duration int(11) comment '学时',
start_time datetime comment '开始时间',
end_time datetime comment '结束时间',
tenant_id varchar(20) default '000000' comment '租户编号',
create_dept bigint(20) comment '创建部门',
reject_time datetime comment '拒绝时间',
create_by bigint(20) comment '创建者',
create_time datetime comment '创建时间',
update_by bigint(20) comment '更新者',
+3
View File
@@ -107,6 +107,8 @@ export interface RecordQuery {
courseName?: string;
userId?: number | string;
userName?: string;
location?: string;
department?: string;
completionStatus?: string;
params?: Record<string, any>;
}
@@ -119,6 +121,7 @@ export interface RecordVO {
courseName: string;
userId: number | string;
userName: string;
location?: string;
department?: string;
completionStatus: string;
score?: string;
@@ -87,24 +87,24 @@
<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">
<el-table-column prop="score" label="指标分值" min-width="100" align="center">
<template #default="scope">
<span>{{ scope.row.score || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="自评分数" width="80" align="center">
<el-table-column label="自评分数" min-width="100" align="center">
<template #default="scope">
<span>{{ scope.row.selfScore || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="自评意见" width="180" align="center">
<el-table-column label="自评意见" min-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">
<el-table-column label="上级评分" min-width="120" align="center">
<template #default="scope">
<el-input-number
v-model="scope.row.superiorScore"
@@ -118,7 +118,7 @@
/>
</template>
</el-table-column>
<el-table-column label="审批意见" width="200" align="center">
<el-table-column label="审批意见" min-width="200" align="center">
<template #default="scope">
<el-input
v-model="scope.row.superiorComment"
@@ -204,27 +204,27 @@
<span>特色工作(加20分)</span>
</div>
</template>
<el-table border :data="specialWorkScores" style="width: 100%" class="special-work-table">
<el-table border :data="specialWorkScores" style="width: 100%" max-height="200" 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">
<el-table-column label="自评分数" min-width="100" align="center">
<template #default="scope">
<span>{{ scope.row.score || scope.row.selfScore || 0 }}</span>
<span>{{ scope.row.selfScore || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="自评意见" width="180" align="center">
<el-table-column label="自评意见" min-width="200" 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">
<el-table-column label="上级评分" min-width="120" align="center">
<template #default="scope">
<el-input-number
v-model="scope.row.superiorScore"
:min="0"
:max="20"
:max="scope.row.score || 20"
:precision="2"
controls-position="right"
style="width: 100%"
@@ -233,7 +233,7 @@
/>
</template>
</el-table-column>
<el-table-column label="审批意见" width="200" align="center">
<el-table-column label="审批意见" min-width="200" align="center">
<template #default="scope">
<el-input
v-model="scope.row.superiorComment"
@@ -6,19 +6,19 @@
<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-col :span="8">
<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-col :span="8">
<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-col :span="8">
<el-form-item label="审批状态" prop="auditStatus">
<el-select v-model="queryParams.auditStatus" placeholder="请选择审批状态" clearable style="width: 100%">
<el-option label="待审核" value="0" />
@@ -27,17 +27,21 @@
</el-select>
</el-form-item>
</el-col>
<el-col :lg="6" :md="12" :sm="24">
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<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-col :span="8">
<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-row>
<el-row>
<el-col :span="24" class="search-btn-container">
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
@@ -59,21 +63,21 @@
<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">
<el-table-column label="计划名称" align="center" prop="planName" min-width="180" :show-overflow-tooltip="true" />
<el-table-column label="考核方案" align="center" prop="schemeName" min-width="180" :show-overflow-tooltip="true" />
<el-table-column label="学年学期" align="center" min-width="140">
<template #default="scope">
<span>{{ scope.row.academicYear }}{{ scope.row.semester === '1' ? '上' : '下' }}学期</span>
<span>{{ scope.row.academicYear }}{{ getSemesterLabel(scope.row.semester) }}</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">
<el-table-column label="班级名称" align="center" prop="className" min-width="120" :show-overflow-tooltip="true" />
<el-table-column label="班主任姓名" align="center" prop="evaluatedUserName" min-width="120" :show-overflow-tooltip="true" />
<el-table-column label="申请时间" align="center" min-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">
<el-table-column label="审批状态" align="center" min-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>
@@ -120,6 +124,13 @@ import ApprovalDialog from './approvalDialog.vue';
import ViewDialog from './viewDialog.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { student_semester } = toRefs<any>(proxy?.useDict('student_semester'));
// 获取学期标签
const getSemesterLabel = (semester: string) => {
const semesterDict = student_semester.value?.find((item: any) => item.value === semester);
return semesterDict ? semesterDict.label : '';
};
const approvalList = ref<AssessmentApprovalVO[]>([]);
const loading = ref(true);
@@ -248,4 +259,15 @@ onMounted(() => {
background-color: #fff;
margin-top: 0px !important;
}
/* 搜索按钮容器样式 */
.search-btn-container {
display: flex;
justify-content: flex-end;
margin-top: 10px;
}
.search-btn-container .el-form-item {
margin-bottom: 0 !important;
}
</style>
@@ -85,29 +85,29 @@
<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">
<el-table-column prop="score" label="指标分值" min-width="100" align="center">
<template #default="scope">
<span>{{ scope.row.score || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="自评分数" width="80" align="center">
<el-table-column label="自评分数" min-width="100" align="center">
<template #default="scope">
<span>{{ scope.row.selfScore || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="自评意见" width="180" align="center">
<el-table-column label="自评意见" min-width="200" 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">
<el-table-column label="上级评分" min-width="100" align="center">
<template #default="scope">
<span>{{ scope.row.superiorScore || '-' }}</span>
<span>{{ scope.row.superiorScore || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="审批意见" width="180" align="center">
<el-table-column label="审批意见" min-width="200" 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>
@@ -175,24 +175,24 @@
<el-table border :data="specialWorkScores" style="width: 100%" max-height="200" 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">
<el-table-column label="自评分数" min-width="100" align="center">
<template #default="scope">
<span>{{ scope.row.selfScore || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="自评意见" width="180" align="center">
<el-table-column label="自评意见" min-width="200" 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">
<el-table-column label="上级评分" min-width="100" align="center">
<template #default="scope">
<span>{{ scope.row.superiorScore || '-' }}</span>
<span>{{ scope.row.superiorScore || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="审批意见" width="180" align="center">
<el-table-column label="审批意见" min-width="200" 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>
@@ -5,24 +5,26 @@
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" label-width="100px">
<el-row :gutter="20">
<el-col :lg="6" :md="12" :sm="24">
<el-col :span="8">
<el-form-item label="指标名称" prop="indicatorName">
<el-input v-model="queryParams.indicatorName" placeholder="请输入指标名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
<el-col :lg="6" :md="12" :sm="24">
<el-col :span="8">
<el-form-item label="指标编码" prop="indicatorCode">
<el-input v-model="queryParams.indicatorCode" placeholder="请输入指标编码" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
<el-col :lg="6" :md="12" :sm="24">
<el-col :span="8">
<el-form-item label="指标类型" prop="indicatorType">
<el-select v-model="queryParams.indicatorType" placeholder="请选择指标类型" clearable style="width: 100%">
<el-option v-for="item in indicatorTypeOptions" :key="item.id" :label="item.indicatorTypeName" :value="item.indicatorTypeCode" />
</el-select>
</el-form-item>
</el-col>
<el-col :lg="6" :md="24" :sm="24">
</el-row>
<el-row>
<el-col :span="24" class="search-btn-container">
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
@@ -54,17 +56,17 @@
<div class="table-container">
<el-table v-loading="loading" border :data="assessmentIndicatorList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="指标编码" align="center" prop="indicatorCode" width="140" show-overflow-tooltip />
<el-table-column label="指标编码" align="center" prop="indicatorCode" min-width="140" show-overflow-tooltip />
<el-table-column label="指标名称" align="center" prop="indicatorName" min-width="180" show-overflow-tooltip />
<el-table-column label="指标类型" align="center" prop="indicatorType" width="120">
<el-table-column label="指标类型" align="center" prop="indicatorType" min-width="150" show-overflow-tooltip>
<template #default="scope">
{{ getIndicatorTypeName(scope.row.indicatorType) }}
</template>
</el-table-column>
<el-table-column label="最高分值" align="center" prop="maxScore" width="100" />
<el-table-column label="分值" align="center" prop="score" width="80" />
<el-table-column label="排序" align="center" prop="sortOrder" width="80" />
<el-table-column label="状态" align="center" prop="status" width="80">
<el-table-column label="最高分值" align="center" prop="maxScore" min-width="100" />
<el-table-column label="分值" align="center" prop="score" min-width="80" />
<el-table-column label="排序" align="center" prop="sortOrder" min-width="80" />
<el-table-column label="状态" align="center" prop="status" min-width="80">
<template #default="scope">
<dict-tag :options="sys_item_enable" :value="scope.row.status" />
</template>
@@ -404,4 +406,15 @@ onMounted(() => {
background-color: #fff;
margin-top: 0px !important;
}
/* 搜索按钮容器样式 */
.search-btn-container {
display: flex;
justify-content: flex-end;
margin-top: 10px;
}
.search-btn-container .el-form-item {
margin-bottom: 0 !important;
}
</style>
@@ -5,24 +5,26 @@
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" label-width="100px">
<el-row :gutter="20">
<el-col :lg="6" :md="12" :sm="24">
<el-col :span="8">
<el-form-item label="指标类型编码" prop="indicatorTypeCode">
<el-input v-model="queryParams.indicatorTypeCode" placeholder="请输入指标类型编码" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
<el-col :lg="6" :md="12" :sm="24">
<el-col :span="8">
<el-form-item label="指标类型名称" prop="indicatorTypeName">
<el-input v-model="queryParams.indicatorTypeName" placeholder="请输入指标类型名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
<el-col :lg="6" :md="12" :sm="24">
<el-col :span="8">
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable style="width: 100%">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
<el-option v-for="dict in sys_item_enable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :lg="6" :md="24" :sm="24">
</el-row>
<el-row>
<el-col :span="24" class="search-btn-container">
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
@@ -55,20 +57,20 @@
<div class="table-container">
<el-table v-loading="loading" border :data="assessmentIndicatorTypeList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="指标类型编码" align="center" prop="indicatorTypeCode" />
<el-table-column label="指标类型名称" align="center" prop="indicatorTypeName" />
<el-table-column label="状态" align="center" prop="status">
<el-table-column label="指标类型编码" align="center" prop="indicatorTypeCode" min-width="150" show-overflow-tooltip />
<el-table-column label="指标类型名称" align="center" prop="indicatorTypeName" min-width="180" show-overflow-tooltip />
<el-table-column label="状态" align="center" prop="status" min-width="100">
<template #default="scope">
<dict-tag :options="sys_item_enable" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<el-table-column label="备注" align="center" prop="remark" min-width="200" show-overflow-tooltip />
<el-table-column label="创建时间" align="center" prop="createTime" min-width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<el-table-column label="操作" align="center" width="120" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button
@@ -293,6 +295,17 @@ onMounted(() => {
padding: 8px;
}
/* 搜索按钮容器样式 */
.search-btn-container {
display: flex;
justify-content: flex-end;
margin-top: 10px;
.el-form-item {
margin-bottom: 0 !important;
}
}
/* 表格卡片布局 */
.table-card {
margin-top: 0;
+45 -23
View File
@@ -5,44 +5,47 @@
<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-col :span="8">
<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-col :span="8">
<el-form-item label="计划编码" prop="planCode">
<el-input v-model="queryParams.planCode" placeholder="请输入计划编码" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
<el-col :lg="6" :md="12" :sm="24">
<el-col :span="8">
<el-form-item label="考核方案" prop="schemeId">
<el-select v-model="queryParams.schemeId" placeholder="请选择考核方案" clearable style="width: 100%">
<el-option v-for="item in schemeOptions" :key="item.id" :label="item.schemeName" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :lg="6" :md="12" :sm="24">
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="学年" prop="academicYear">
<el-input v-model="queryParams.academicYear" placeholder="请输入学年" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
<el-col :lg="6" :md="12" :sm="24">
<el-col :span="8">
<el-form-item label="学期" prop="semester">
<el-select v-model="queryParams.semester" placeholder="请选择学期" clearable style="width: 100%">
<el-option label="上学期" value="1" />
<el-option label="下学期" value="2" />
<el-option v-for="dict in student_semester" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :lg="6" :md="12" :sm="24">
<el-col :span="8">
<el-form-item label="计划状态" prop="planStatus">
<el-select v-model="queryParams.planStatus" placeholder="请选择计划状态" clearable style="width: 100%">
<el-option v-for="option in planStatusOptions" :key="option.value" :label="option.label" :value="option.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :lg="12" :md="24" :sm="24">
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="创建时间">
<el-date-picker
v-model="dateRange"
@@ -56,7 +59,9 @@
></el-date-picker>
</el-form-item>
</el-col>
<el-col :lg="6" :md="24" :sm="24">
</el-row>
<el-row>
<el-col :span="24" class="search-btn-container">
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
@@ -87,24 +92,24 @@
<div class="table-container">
<el-table v-loading="loading" border :data="assessmentPlanList" @selection-change="handleSelectionChange" @sort-change="sortChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="计划名称" align="center" prop="planName" :show-overflow-tooltip="true" />
<el-table-column label="计划编码" align="center" prop="planCode" :show-overflow-tooltip="true" />
<el-table-column label="考核方案" align="center" :show-overflow-tooltip="true">
<el-table-column label="计划名称" align="center" prop="planName" min-width="180" :show-overflow-tooltip="true" />
<el-table-column label="计划编码" align="center" prop="planCode" min-width="150" :show-overflow-tooltip="true" />
<el-table-column label="考核方案" align="center" min-width="180" :show-overflow-tooltip="true">
<template #default="scope">
<span>{{ schemeOptions.find((item) => item.id === scope.row.schemeId)?.schemeName || '' }}</span>
</template>
</el-table-column>
<el-table-column label="学年学期" align="center" width="120">
<el-table-column label="学年学期" align="center" min-width="160">
<template #default="scope">
<span>{{ scope.row.academicYear }}{{ scope.row.semester === '1' ? '上' : '下' }}学期</span>
<span>{{ scope.row.academicYear }}{{ getSemesterLabel(scope.row.semester) }}</span>
</template>
</el-table-column>
<el-table-column label="计划时间" align="center" width="180">
<el-table-column label="计划时间" align="center" min-width="200">
<template #default="scope">
<span>{{ parseTime(scope.row.planStartTime, '{y}-{m}-{d}') }} 至 {{ parseTime(scope.row.planEndTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="数据提取时间" align="center" width="180">
<el-table-column label="数据提取时间" align="center" min-width="200">
<template #default="scope">
<span v-if="scope.row.dataExtractStartTime && scope.row.dataExtractEndTime">
{{ parseTime(scope.row.dataExtractStartTime, '{y}-{m}-{d}') }} 至 {{ parseTime(scope.row.dataExtractEndTime, '{y}-{m}-{d}') }}
@@ -112,7 +117,7 @@
<span v-else class="text-gray-400">未设置</span>
</template>
</el-table-column>
<el-table-column label="计划状态" align="center" width="100">
<el-table-column label="计划状态" align="center" min-width="100">
<template #default="scope">
<el-switch
v-model="scope.row.planStatus"
@@ -123,12 +128,12 @@
></el-switch>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<el-table-column label="创建时间" align="center" prop="createTime" min-width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="120">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['bzrkh:assessmentPlan:edit']"></el-button>
@@ -168,7 +173,7 @@
<el-option
v-for="item in schemeOptions"
:key="item.id"
:label="`${item.schemeName}(${item.academicYear}${item.semester === '1' ? '上' : '下'}学期)`"
:label="`${item.schemeName}(${item.academicYear}${getSemesterLabel(item.semester)})`"
:value="item.id"
/>
</el-select>
@@ -184,8 +189,7 @@
<el-col :span="12">
<el-form-item label="学期" prop="semester">
<el-select v-model="form.semester" placeholder="请选择学期" style="width: 100%">
<el-option label="上学期" value="1" />
<el-option label="下学期" value="2" />
<el-option v-for="dict in student_semester" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
@@ -286,6 +290,13 @@ import { AssessmentPlanVO, AssessmentPlanQuery, AssessmentPlanForm } from '@/api
import { BmzrAssessmentSchemeVO } from '@/api/bzrkh/assessmentScheme/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { student_semester } = toRefs<any>(proxy?.useDict('student_semester'));
// 获取学期标签
const getSemesterLabel = (semester: string) => {
const semesterDict = student_semester.value?.find((item: any) => item.value === semester);
return semesterDict ? semesterDict.label : '';
};
// 自定义计划状态选项(符合数据库设计:0=禁用 1=启用)
const planStatusOptions = ref([
@@ -534,4 +545,15 @@ onMounted(() => {
background-color: #fff;
margin-top: 0px !important;
}
/* 搜索按钮容器样式 */
.search-btn-container {
display: flex;
justify-content: flex-end;
margin-top: 10px;
}
.search-btn-container .el-form-item {
margin-bottom: 0 !important;
}
</style>
+25 -15
View File
@@ -5,39 +5,40 @@
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" label-width="100px">
<el-row :gutter="20">
<el-col :lg="6" :md="12" :sm="24">
<el-col :span="8">
<el-form-item label="方案名称" prop="schemeName">
<el-input v-model="queryParams.schemeName" placeholder="请输入方案名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
<el-col :lg="6" :md="12" :sm="24">
<el-col :span="8">
<el-form-item label="方案编码" prop="schemeCode">
<el-input v-model="queryParams.schemeCode" placeholder="请输入方案编码" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
<el-col :lg="6" :md="12" :sm="24">
<el-col :span="8">
<el-form-item label="学年" prop="academicYear">
<el-input v-model="queryParams.academicYear" placeholder="请输入学年" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
<el-col :lg="6" :md="12" :sm="24">
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="学期" prop="semester">
<el-select v-model="queryParams.semester" placeholder="请选择学期" clearable style="width: 100%">
<el-option label="上学期" value="1" />
<el-option label="下学期" value="2" />
<el-option v-for="dict in student_semester" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :lg="6" :md="12" :sm="24">
<el-col :span="8">
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable style="width: 100%">
<el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :lg="18" :md="12" :sm="24">
</el-row>
<el-row>
<el-col :span="24" class="search-btn-container">
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
@@ -81,8 +82,7 @@
<el-table-column label="学年" align="center" prop="academicYear" width="100" />
<el-table-column label="学期" align="center" prop="semester" width="80">
<template #default="scope">
<el-tag v-if="scope.row.semester === '1'" type="primary">上学期</el-tag>
<el-tag v-else-if="scope.row.semester === '2'" type="success">下学期</el-tag>
<dict-tag :options="student_semester" :value="scope.row.semester" />
</template>
</el-table-column>
<el-table-column label="自评" align="center" prop="selfEvaluationRequired" width="70">
@@ -164,8 +164,7 @@
<el-col :span="12">
<el-form-item label="学期" prop="semester">
<el-select v-model="form.semester" placeholder="请选择学期" style="width: 100%">
<el-option label="上学期" value="1" />
<el-option label="下学期" value="2" />
<el-option v-for="dict in student_semester" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
@@ -234,7 +233,7 @@ import { BmzrAssessmentSchemeVO, BmzrAssessmentSchemeQuery, BmzrAssessmentScheme
import IndicatorManagement from './IndicatorManagement.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { sys_normal_disable, sys_yesno } = toRefs<any>(proxy?.useDict('sys_normal_disable', 'sys_yesno'));
const { sys_normal_disable, sys_yesno, student_semester } = toRefs<any>(proxy?.useDict('sys_normal_disable', 'sys_yesno', 'student_semester'));
const schemeList = ref<BmzrAssessmentSchemeVO[]>([]);
const buttonLoading = ref(false);
@@ -517,4 +516,15 @@ onMounted(() => {
justify-content: flex-end;
gap: 12px;
}
/* 搜索按钮容器样式 */
.search-btn-container {
display: flex;
justify-content: flex-end;
margin-top: 10px;
}
.search-btn-container .el-form-item {
margin-bottom: 0 !important;
}
</style>
+38 -26
View File
@@ -10,12 +10,14 @@
<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-col :span="8">
<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="24" :sm="24">
</el-row>
<el-row>
<el-col :span="24" class="search-btn-container">
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
@@ -37,20 +39,20 @@
<div class="table-container">
<el-table v-loading="loading" border :data="assessmentPlanList" @sort-change="sortChange">
<el-table-column label="计划名称" align="center" prop="planName" :show-overflow-tooltip="true" />
<el-table-column label="计划编码" align="center" prop="planCode" :show-overflow-tooltip="true" />
<el-table-column label="考核方案" align="center" prop="schemeName" :show-overflow-tooltip="true" />
<el-table-column label="学年学期" align="center" width="120">
<el-table-column label="计划名称" align="center" prop="planName" min-width="180" :show-overflow-tooltip="true" />
<el-table-column label="计划编码" align="center" prop="planCode" min-width="150" :show-overflow-tooltip="true" />
<el-table-column label="考核方案" align="center" prop="schemeName" min-width="180" :show-overflow-tooltip="true" />
<el-table-column label="学年学期" align="center" min-width="160">
<template #default="scope">
<span>{{ scope.row.academicYear }}{{ scope.row.semester === '1' ? '上' : '下' }}学期</span>
<span>{{ scope.row.academicYear }}{{ getSemesterLabel(scope.row.semester) }}</span>
</template>
</el-table-column>
<el-table-column label="计划时间" align="center" width="180">
<el-table-column label="计划时间" align="center" min-width="200">
<template #default="scope">
<span>{{ parseTime(scope.row.planStartTime, '{y}-{m}-{d}') }} 至 {{ parseTime(scope.row.planEndTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="数据提取时间" align="center" width="180">
<el-table-column label="数据提取时间" align="center" min-width="200">
<template #default="scope">
<span v-if="scope.row.dataExtractStartTime && scope.row.dataExtractEndTime">
{{ parseTime(scope.row.dataExtractStartTime, '{y}-{m}-{d}') }} 至 {{ parseTime(scope.row.dataExtractEndTime, '{y}-{m}-{d}') }}
@@ -58,7 +60,7 @@
<span v-else class="text-gray-400">未设置</span>
</template>
</el-table-column>
<el-table-column label="审核状态" align="center" width="120">
<el-table-column label="审核状态" align="center" min-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 === '9'" type="primary" effect="plain">草稿</el-tag>
@@ -68,12 +70,12 @@
<el-tag v-else type="info" effect="plain">未知状态</el-tag>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<el-table-column label="创建时间" align="center" prop="createTime" min-width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
<template #default="scope">
<!-- 审核通过状态:只显示查看考核按钮 -->
<template v-if="scope.row.auditStatus === '1'">
@@ -101,27 +103,18 @@
></el-button>
</el-tooltip>
</template>
<!-- 已提交状态(待审核):显示撤销按钮 -->
<!-- 待审核状态:显示查看考核按钮 -->
<template v-else-if="scope.row.auditStatus === '0'">
<el-tooltip content="撤销提交" placement="top">
<el-tooltip content="查看考核" placement="top">
<el-button
link
type="warning"
icon="RefreshLeft"
type="success"
icon="View"
:disabled="loading || !isDataReady"
@click="handleWithdrawAssessment(scope.row)"
@click="handleViewAssessment(scope.row)"
></el-button>
</el-tooltip>
</template>
<el-tooltip content="查看考核" placement="top">
<el-button
link
type="success"
icon="View"
:disabled="loading || !isDataReady"
@click="handleViewAssessment(scope.row)"
></el-button>
</el-tooltip>
</template>
</template>
</el-table-column>
@@ -170,6 +163,14 @@ import SubmitDialog from './submitDialog.vue';
import ViewDialog from './viewDialog.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { student_semester } = toRefs<any>(proxy?.useDict('student_semester'));
// 获取学期标签
const getSemesterLabel = (semester: string) => {
const semesterDict = student_semester.value?.find((item: any) => item.value === semester);
return semesterDict ? semesterDict.label : '';
};
const userStore = useUserStore();
const teacherClasses = ref<TeacherClassVO[]>([]);
@@ -496,6 +497,17 @@ onMounted(() => {
margin-top: 0px !important;
}
/* 搜索按钮容器样式 */
.search-btn-container {
display: flex;
justify-content: flex-end;
margin-top: 10px;
}
.search-btn-container .el-form-item {
margin-bottom: 0 !important;
}
/* 标签页样式优化 */
:deep(.el-tabs__header) {
margin-bottom: 20px;
@@ -89,12 +89,12 @@
<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 prop="description" label="指标描述" min-width="200" align="center" :show-overflow-tooltip="true" />
<el-table-column prop="score" label="指标分值" width="80" align="center">
<el-table-column prop="score" label="指标分值" min-width="100" align="center">
<template #default="scope">
<span>{{ scope.row.score || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="自评分数" width="130" align="center">
<el-table-column label="自评分数" min-width="130" align="center">
<template #default="scope">
<el-input-number
v-model="scope.row.selfScore"
@@ -105,21 +105,19 @@
style="width: 100%"
placeholder="请输入分数"
size="small"
class="score-input"
/>
</template>
</el-table-column>
<el-table-column label="自评意见" width="220" align="center">
<el-table-column label="自评意见" min-width="220" align="center">
<template #default="scope">
<el-input
v-model="scope.row.selfComment"
type="textarea"
:rows="1"
:rows="2"
placeholder="请输入自评意见"
maxlength="200"
show-word-limit
size="small"
class="comment-input"
/>
</template>
</el-table-column>
@@ -344,22 +342,22 @@
<el-tab-pane label="违纪记录" name="discipline">
<el-table :data="studentRecordsData?.disciplineRecords || []" border style="width: 100%" max-height="400" empty-text="暂无违纪记录">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="studentNo" label="学号" width="120" align="center" />
<el-table-column prop="studentName" label="学生姓名" width="100" align="center" />
<el-table-column prop="disciplineTypeName" label="违纪类型" width="120" align="center" />
<el-table-column prop="disciplineDate" label="违纪日期" width="110" align="center">
<el-table-column prop="studentNo" label="学号" min-width="120" align="center" />
<el-table-column prop="studentName" label="学生姓名" min-width="100" align="center" />
<el-table-column prop="disciplineTypeName" label="违纪类型" min-width="120" align="center" />
<el-table-column prop="disciplineDate" label="违纪日期" min-width="110" align="center">
<template #default="scope">
<span>{{ scope.row.disciplineDate?.split(' ')[0] || '-' }}</span>
</template>
</el-table-column>
<el-table-column prop="disciplineReason" label="违纪原因" min-width="200" :show-overflow-tooltip="true" />
<el-table-column prop="disciplineContent" label="处分内容" min-width="200" :show-overflow-tooltip="true" />
<el-table-column prop="scoreDeduction" label="扣分" width="80" align="center">
<el-table-column prop="scoreDeduction" label="扣分" min-width="80" align="center">
<template #default="scope">
<el-tag type="danger" size="small">{{ scope.row.scoreDeduction || 0 }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="80" align="center">
<el-table-column prop="status" label="状态" min-width="80" align="center">
<template #default="scope">
<el-tag :type="scope.row.status === '1' ? 'danger' : 'info'" size="small">
{{ scope.row.status === '1' ? '生效' : '已撤销' }}
@@ -373,21 +371,21 @@
<el-tab-pane label="奖励记录" name="reward">
<el-table :data="studentRecordsData?.rewardRecords || []" border style="width: 100%" max-height="400" empty-text="暂无奖励记录">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="studentNo" label="学号" width="120" align="center" />
<el-table-column prop="studentName" label="学生姓名" width="100" align="center" />
<el-table-column prop="rewardTypeName" label="奖励类型" width="120" align="center" />
<el-table-column prop="rewardDate" label="奖励日期" width="110" align="center">
<el-table-column prop="studentNo" label="学号" min-width="120" align="center" />
<el-table-column prop="studentName" label="学生姓名" min-width="100" align="center" />
<el-table-column prop="rewardTypeName" label="奖励类型" min-width="120" align="center" />
<el-table-column prop="rewardDate" label="奖励日期" min-width="110" align="center">
<template #default="scope">
<span>{{ scope.row.rewardDate || '-' }}</span>
</template>
</el-table-column>
<el-table-column prop="rewardContent" label="奖励内容" min-width="300" :show-overflow-tooltip="true" />
<el-table-column prop="scoreAddition" label="加分" width="80" align="center">
<el-table-column prop="scoreAddition" label="加分" min-width="80" align="center">
<template #default="scope">
<el-tag type="success" size="small">{{ scope.row.scoreAddition || 0 }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="80" align="center">
<el-table-column prop="status" label="状态" min-width="80" align="center">
<template #default="scope">
<el-tag :type="scope.row.status === '1' ? 'success' : 'info'" size="small">
{{ scope.row.status === '1' ? '生效' : '撤销' }}
@@ -89,37 +89,35 @@
<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 prop="description" label="指标描述" min-width="200" align="center" :show-overflow-tooltip="true" />
<el-table-column prop="score" label="指标分值" width="80" align="center">
<el-table-column prop="score" label="指标分值" min-width="100" align="center">
<template #default="scope">
<span>{{ scope.row.score || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="自评分数" width="80" align="center">
<el-table-column label="自评分数" min-width="100" align="center">
<template #default="scope">
<div class="readonly-field">
{{ formatNumber(scope.row.selfScore, 2) }}
</div>
<span>{{ scope.row.selfScore || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="自评意见" width="180" align="center">
<el-table-column label="自评意见" min-width="200" align="center">
<template #default="scope">
<div class="readonly-field comment-field">
{{ scope.row.selfComment || '-' }}
</div>
<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>
<!-- 审批模式下显示上级评分和审批意见 -->
<template v-if="viewMode === 'approval'">
<el-table-column label="上级评分" width="80" align="center">
<el-table-column label="上级评分" min-width="100" align="center">
<template #default="scope">
<span>{{ scope.row.superiorScore || '-' }}</span>
<span>{{ scope.row.superiorScore || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="审批意见" width="180" align="center">
<el-table-column label="审批意见" min-width="200" align="center">
<template #default="scope">
<div class="readonly-field comment-field">
{{ scope.row.superiorComment || '-' }}
</div>
<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>
</template>
@@ -230,28 +228,28 @@
<el-table border :data="approvalSpecialWorkScores" 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">
<el-table-column label="自评分数" min-width="100" align="center">
<template #default="scope">
<span>{{ scope.row.selfScore || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="自评意见" width="180" align="center">
<el-table-column label="自评意见" min-width="200" align="center">
<template #default="scope">
<div class="readonly-field comment-field">
{{ scope.row.selfComment || '-' }}
</div>
<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">
<el-table-column label="上级评分" min-width="100" align="center">
<template #default="scope">
<span>{{ scope.row.superiorScore || '-' }}</span>
<span>{{ scope.row.superiorScore || 0 }}</span>
</template>
</el-table-column>
<el-table-column label="审批意见" width="180" align="center">
<el-table-column label="审批意见" min-width="200" align="center">
<template #default="scope">
<div class="readonly-field comment-field">
{{ scope.row.superiorComment || '-' }}
</div>
<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>
@@ -369,22 +367,22 @@
<el-tab-pane label="违纪记录" name="discipline">
<el-table :data="studentRecordsData?.disciplineRecords || []" border style="width: 100%" max-height="400" empty-text="暂无违纪记录">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="studentNo" label="学号" width="120" align="center" />
<el-table-column prop="studentName" label="学生姓名" width="100" align="center" />
<el-table-column prop="disciplineTypeName" label="违纪类型" width="120" align="center" />
<el-table-column prop="disciplineDate" label="违纪日期" width="110" align="center">
<el-table-column prop="studentNo" label="学号" min-width="120" align="center" />
<el-table-column prop="studentName" label="学生姓名" min-width="100" align="center" />
<el-table-column prop="disciplineTypeName" label="违纪类型" min-width="120" align="center" />
<el-table-column prop="disciplineDate" label="违纪日期" min-width="110" align="center">
<template #default="scope">
<span>{{ scope.row.disciplineDate?.split(' ')[0] || '-' }}</span>
</template>
</el-table-column>
<el-table-column prop="disciplineReason" label="违纪原因" min-width="200" :show-overflow-tooltip="true" />
<el-table-column prop="disciplineContent" label="处分内容" min-width="200" :show-overflow-tooltip="true" />
<el-table-column prop="scoreDeduction" label="扣分" width="80" align="center">
<el-table-column prop="scoreDeduction" label="扣分" min-width="80" align="center">
<template #default="scope">
<el-tag type="danger" size="small">{{ scope.row.scoreDeduction || 0 }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="80" align="center">
<el-table-column prop="status" label="状态" min-width="80" align="center">
<template #default="scope">
<el-tag :type="scope.row.status === '1' ? 'danger' : 'info'" size="small">
{{ scope.row.status === '1' ? '生效' : '已撤销' }}
@@ -398,21 +396,21 @@
<el-tab-pane label="奖励记录" name="reward">
<el-table :data="studentRecordsData?.rewardRecords || []" border style="width: 100%" max-height="400" empty-text="暂无奖励记录">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="studentNo" label="学号" width="120" align="center" />
<el-table-column prop="studentName" label="学生姓名" width="100" align="center" />
<el-table-column prop="rewardTypeName" label="奖励类型" width="120" align="center" />
<el-table-column prop="rewardDate" label="奖励日期" width="110" align="center">
<el-table-column prop="studentNo" label="学号" min-width="120" align="center" />
<el-table-column prop="studentName" label="学生姓名" min-width="100" align="center" />
<el-table-column prop="rewardTypeName" label="奖励类型" min-width="120" align="center" />
<el-table-column prop="rewardDate" label="奖励日期" min-width="110" align="center">
<template #default="scope">
<span>{{ scope.row.rewardDate || '-' }}</span>
</template>
</el-table-column>
<el-table-column prop="rewardContent" label="奖励内容" min-width="300" :show-overflow-tooltip="true" />
<el-table-column prop="scoreAddition" label="加分" width="80" align="center">
<el-table-column prop="scoreAddition" label="加分" min-width="80" align="center">
<template #default="scope">
<el-tag type="success" size="small">{{ scope.row.scoreAddition || 0 }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="80" align="center">
<el-table-column prop="status" label="状态" min-width="80" align="center">
<template #default="scope">
<el-tag :type="scope.row.status === '1' ? 'success' : 'info'" size="small">
{{ scope.row.status === '1' ? '生效' : '撤销' }}
+14 -8
View File
@@ -60,7 +60,7 @@
<el-button icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['rs:job:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button icon="Download" @click="handleExport" v-hasPermi="['rs:job:export']">导出</el-button>
<el-button icon="Download" @click="handleExport" v-hasPermi="['rs:job:export']" style="display: none">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
@@ -91,7 +91,7 @@
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="240">
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="280">
<template #default="scope">
<el-tooltip content="查看" placement="top">
<el-button
@@ -113,6 +113,17 @@
@click="handleUpdate(scope.row)"
></el-button>
</el-tooltip>
<el-tooltip content="查看简历记录" placement="top">
<el-button
link
type="info"
icon="Document"
size="default"
style="font-size: 16px; margin-right: 8px"
@click="handleApplications(scope.row)"
v-if="scope.row.jobId"
></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button
link
@@ -216,7 +227,7 @@
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button icon="Download" @click="handleExportApplications" v-hasPermi="['rs:application:export']">导出</el-button>
<el-button icon="Download" @click="handleExportApplications" v-hasPermi="['rs:application:export']" style="display: none">导出</el-button>
</el-col>
<el-col :span="1.5">
<el-button icon="Printer" @click="handlePrintApplications">打印</el-button>
@@ -386,7 +397,6 @@
</el-descriptions>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="handleApplications(viewForm)" v-if="viewForm.jobId">查看简历记录</el-button>
<el-button @click="viewOpen = false">关 闭</el-button>
</div>
</template>
@@ -1686,10 +1696,6 @@ function handleExportResume() {
<p><strong>应聘职位:</strong>${selectedRecord.jobTitle || '未提供'}</p>
<p><strong>联系电话:</strong>${selectedRecord.contactPhone || '未提供'}</p>
<p><strong>联系邮箱:</strong>${selectedRecord.contactEmail || '未提供'}</p>
<p><strong>申请状态:</strong>${
selectedRecord.status === '0' ? '待处理' : selectedRecord.status === '1' ? '已通过' : selectedRecord.status === '2' ? '已拒绝' : '未知'
}</p>
<p><strong>申请时间:</strong>${parseTime(selectedRecord.applyTime)}</p>
</div>
<div style="margin-bottom: 30px;">
+9 -3
View File
@@ -76,7 +76,7 @@
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button icon="Download" @click="handleExportPending" v-hasPermi="['rs:overseas:export']">导出</el-button>
<el-button icon="Download" @click="handleExportPending" v-hasPermi="['rs:overseas:export']" style="display: none">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showPendingSearch" @queryTable="getPendingList"></right-toolbar>
</el-row>
@@ -219,7 +219,7 @@
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button icon="Download" @click="handleExportRecord" v-hasPermi="['rs:overseas:export']">导出</el-button>
<el-button icon="Download" @click="handleExportRecord" v-hasPermi="['rs:overseas:export']" style="display: none">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showRecordSearch" @queryTable="getRecordList"></right-toolbar>
</el-row>
@@ -854,7 +854,13 @@ const handleRecordDateRangeChange = (dates: [string, string] | null) => {
<style scoped>
.search-btn-container {
text-align: center;
display: flex;
justify-content: flex-end;
margin-top: 10px;
}
.search-btn-container :deep(.el-form-item) {
margin-bottom: 0 !important;
}
.button-card {
+8 -2
View File
@@ -67,7 +67,7 @@
<el-button type="primary" plain icon="Plus" @click="handleAddApplication" v-hasPermi="['rs:overseas:add']">新增申请</el-button>
</el-col>
<el-col :span="1.5">
<el-button icon="Download" @click="handleExportApplication" v-hasPermi="['rs:overseas:export']">导出</el-button>
<el-button icon="Download" @click="handleExportApplication" v-hasPermi="['rs:overseas:export']" style="display: none">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showApplicationSearch" @queryTable="getApplicationList"></right-toolbar>
</el-row>
@@ -1055,7 +1055,13 @@ const handleViewRecord = (row: OverseasRecordVO) => {
<style scoped>
.search-btn-container {
text-align: center;
display: flex;
justify-content: flex-end;
margin-top: 10px;
}
.search-btn-container :deep(.el-form-item) {
margin-bottom: 0 !important;
}
.button-card {
+8 -3
View File
@@ -64,7 +64,7 @@
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['rs:overseas:export']">导出</el-button>
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['rs:overseas:export']" style="display: none">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
@@ -678,8 +678,13 @@ onMounted(() => {
/* 搜索按钮容器 */
.search-btn-container {
text-align: left;
padding-top: 10px;
display: flex;
justify-content: flex-end;
margin-top: 10px;
}
.search-btn-container :deep(.el-form-item) {
margin-bottom: 0 !important;
}
/* 表格卡片样式 */
+12 -6
View File
@@ -344,9 +344,9 @@ onMounted(() => {
min-height: 100vh;
.header-banner {
background-color: #409eff;
background: #004e48;
color: white;
padding: 40px 0;
padding: 50px 0;
text-align: center;
.banner-content {
@@ -355,14 +355,20 @@ onMounted(() => {
padding: 0 20px;
.apply-title {
font-size: 2rem;
margin-bottom: 10px;
font-size: 2.5rem;
color: #ffffff;
margin-bottom: 15px;
font-weight: 600;
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.4);
}
.apply-subtitle {
font-size: 1rem;
opacity: 0.8;
font-size: 1.3rem;
color: #ffffff;
opacity: 0.92;
margin: 0;
font-weight: 300;
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.4);
}
}
}
+230 -96
View File
@@ -375,50 +375,71 @@ onMounted(() => {
<style scoped lang="scss">
.recruitment-portal {
min-height: 100vh;
background: #f8f9fa;
background: #f5f5f5;
.header-banner {
background: linear-gradient(135deg, #2c3e50 0%, #34495e 100%);
// 纯色背景,不要图案
background: #004e48;
position: relative;
color: white;
padding: 60px 0;
padding: 50px 0;
text-align: center;
.banner-content {
margin: 0 auto;
padding: 0 30px;
position: relative;
z-index: 1;
.portal-title {
font-size: 3.5rem;
font-weight: 700;
margin-bottom: 20px;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
font-size: 3.2rem;
font-weight: 600;
margin-bottom: 15px;
text-shadow: 2px 2px 6px rgba(0, 0, 0, 0.5);
color: #ffffff;
letter-spacing: 3px;
}
.portal-subtitle {
font-size: 1.5rem;
opacity: 0.9;
font-size: 1.3rem;
color: #ffffff;
opacity: 0.92;
margin: 0;
font-weight: 300;
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.4);
}
}
}
.breadcrumb-container {
background: white;
padding: 15px 0;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
border-bottom: 1px solid #e8ecf0;
padding: 12px 0;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
border-bottom: 1px solid #e0e0e0;
.el-breadcrumb {
margin: 0 auto;
padding: 0 30px;
:deep(.el-breadcrumb__item) {
.el-breadcrumb__inner {
color: #666;
font-weight: 400;
}
&:last-child .el-breadcrumb__inner {
color: #2d5a3d;
font-weight: 500;
}
}
}
}
.portal-container {
margin: 0;
padding: 30px;
padding: 25px;
display: flex;
gap: 25px;
gap: 20px;
min-height: calc(100vh - 200px);
}
@@ -427,51 +448,101 @@ onMounted(() => {
flex-shrink: 0;
.nav-section {
background: white;
border-radius: 12px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
border: 1px solid #e8ecf0;
// 参考官网左侧导航的样式 - 整体深绿色背景
background: #004e48;
border-radius: 0;
padding: 0;
margin-bottom: 15px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
border: none;
overflow: visible;
.nav-title {
font-size: 1.2rem;
font-weight: 600;
margin-bottom: 20px;
color: #2c3e50;
border-bottom: 2px solid #e3f2fd;
padding-bottom: 10px;
margin: 0;
color: #ffffff;
// 参考官网"学工在线"的深绿色背景
background: #004e48;
padding: 18px 20px;
text-align: center;
position: relative;
letter-spacing: 1px;
}
.nav-list {
list-style: none;
padding: 0;
margin: 0;
background: #004e48;
.nav-item {
display: flex;
align-items: center;
padding: 12px 15px;
margin-bottom: 8px;
border-radius: 8px;
padding: 15px 20px;
margin: 0;
cursor: pointer;
transition: all 0.3s ease;
color: #555;
color: #ffffff;
font-weight: 500;
font-size: 1rem;
position: relative;
border: none;
// 默认状态 - 普通导航项
background: #004e48;
&:hover {
background: #f8f9fa;
color: #667eea;
background: #006157;
}
&.active {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
// 参考官网"学生活动"的样式 - 更深的绿色和箭头形状
background: #003a37;
position: relative;
z-index: 2;
// 创建右箭头效果
&::after {
content: '';
position: absolute;
right: -15px;
top: 50%;
transform: translateY(-50%);
width: 0;
height: 0;
border-left: 15px solid #003a37;
border-top: 15px solid transparent;
border-bottom: 15px solid transparent;
z-index: 3;
}
// 箭头阴影效果
&::before {
content: '';
position: absolute;
right: -17px;
top: 50%;
transform: translateY(-50%);
width: 0;
height: 0;
border-left: 17px solid rgba(0, 0, 0, 0.15);
border-top: 17px solid transparent;
border-bottom: 17px solid transparent;
z-index: 1;
}
}
.el-icon {
margin-right: 10px;
font-size: 1.1rem;
color: #ffffff;
transition: color 0.2s ease;
}
span {
font-size: 1rem;
letter-spacing: 0.5px;
}
}
}
@@ -480,11 +551,25 @@ onMounted(() => {
.main-content {
flex: 1;
min-width: 0; // 确保flex子项能够收缩
/* 搜索区域样式已删除 */
min-width: 0;
.job-list-section {
.el-card {
border-radius: 8px;
border: 1px solid #e8e8e8;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
:deep(.el-card__header) {
background: #fafafa;
border-bottom: 1px solid #e8e8e8;
padding: 16px 20px;
}
:deep(.el-card__body) {
padding: 20px;
}
}
.list-header {
display: flex;
justify-content: space-between;
@@ -497,96 +582,106 @@ onMounted(() => {
h3 {
margin: 0;
color: #2c3e50;
color: #2d5a3d;
font-weight: 600;
font-size: 1.2rem;
}
.job-count {
color: #666;
font-size: 0.9rem;
background: #e8f5e8;
padding: 4px 8px;
border-radius: 12px;
font-weight: 500;
}
}
.view-options {
:deep(.el-radio-group) {
.el-radio-button__inner {
background: #fff;
border-color: #2d5a3d;
color: #2d5a3d;
&:hover {
color: #2d5a3d;
}
}
.el-radio-button__original-radio:checked + .el-radio-button__inner {
background: #2d5a3d;
border-color: #2d5a3d;
color: #fff;
}
}
}
}
.list-view {
:deep(.el-table) {
.el-table__header {
background: #fafafa;
th {
background: #fafafa !important;
color: #333;
font-weight: 500;
}
}
.el-table__row {
&:hover {
background: #f8f9fa;
}
}
}
.job-title-link {
font-weight: 600;
font-weight: 500;
color: #2d5a3d;
text-decoration: none;
&:hover {
color: #4a7c59;
text-decoration: underline;
}
}
.deadline-passed {
color: #f56c6c;
font-weight: 600;
}
.deadline-warning {
color: #e6a23c;
font-weight: 600;
}
}
.card-view {
.job-card-col {
margin-bottom: 15px;
}
.job-card {
height: 100%;
cursor: pointer;
border: 1px solid #e8e8e8;
border-radius: 8px;
transition: all 0.3s ease;
display: flex;
flex-direction: column;
&:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
transform: translateY(-3px);
box-shadow: 0 6px 20px rgba(45, 90, 61, 0.15);
border-color: #2d5a3d;
}
.job-card-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 15px;
.job-card-title {
margin: 0;
font-size: 1.1rem;
color: #2d5a3d;
font-weight: 600;
color: #2c3e50;
flex: 1;
margin-right: 10px;
}
}
.job-card-info {
margin-bottom: 15px;
flex: 1;
.info-item {
display: flex;
align-items: center;
margin-bottom: 8px;
color: #666;
font-size: 0.9rem;
.el-icon {
margin-right: 8px;
color: #999;
}
}
}
.job-card-footer {
display: flex;
justify-content: space-between;
align-items: center;
.publish-time {
font-size: 0.8rem;
color: #999;
.el-button {
background: #2d5a3d;
border-color: #2d5a3d;
&:hover {
background: #4a7c59;
border-color: #4a7c59;
}
&:disabled {
background: #ccc;
border-color: #ccc;
}
}
}
}
@@ -594,12 +689,28 @@ onMounted(() => {
}
}
// 对话框样式优化
:deep(.el-dialog) {
border-radius: 8px;
.el-dialog__header {
background: #fafafa;
border-bottom: 1px solid #e8e8e8;
.el-dialog__title {
color: #2d5a3d;
font-weight: 600;
}
}
}
.job-detail {
.detail-header {
.job-basic-info {
h3 {
margin-bottom: 15px;
color: #2c3e50;
color: #2d5a3d;
font-weight: 600;
}
.job-meta {
@@ -612,6 +723,14 @@ onMounted(() => {
color: #666;
font-size: 0.9rem;
}
.el-tag {
&.el-tag--success {
background: #e8f5e8;
color: #2d5a3d;
border-color: #2d5a3d;
}
}
}
}
}
@@ -621,9 +740,12 @@ onMounted(() => {
margin-bottom: 25px;
h4 {
color: #2c3e50;
color: #2d5a3d;
margin-bottom: 15px;
font-size: 1.1rem;
font-weight: 600;
border-left: 4px solid #2d5a3d;
padding-left: 12px;
}
.content-text {
@@ -644,9 +766,21 @@ onMounted(() => {
.dialog-footer {
text-align: right;
padding-top: 15px;
border-top: 1px solid #e8e8e8;
.el-button {
margin-left: 10px;
&.el-button--primary {
background: #2d5a3d;
border-color: #2d5a3d;
&:hover {
background: #4a7c59;
border-color: #4a7c59;
}
}
}
}
}
+268 -86
View File
@@ -57,12 +57,12 @@
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAddApplication" v-hasPermi="['rs:training:application:add']"
<el-button type="primary" plain icon="Plus" @click="handleAddApplication" v-hasPermi="['rs:trainingapplication:add']"
>申请培训</el-button
>
</el-col>
<el-col :span="1.5">
<el-button icon="Download" @click="handleExportTrainingApplication" v-hasPermi="['rs:training:application:export']">导出</el-button>
<el-button icon="Download" @click="handleExportTrainingApplication" v-hasPermi="['rs:trainingapplication:export']" style="display: none">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showApplicationSearch" @queryTable="getApplicationList"></right-toolbar>
</el-row>
@@ -95,7 +95,7 @@
type="primary"
icon="View"
@click="handleViewApplicant(scope.row)"
v-hasPermi="['rs:training:application:query']"
v-hasPermi="['rs:trainingapplication:query']"
></el-button>
</el-tooltip>
<!-- 待审核状态:显示撤回按钮 -->
@@ -105,7 +105,7 @@
type="warning"
icon="RefreshLeft"
@click="handleCancelApplication(scope.row)"
v-hasPermi="['rs:training:application:cancel']"
v-hasPermi="['rs:trainingapplication:cancel']"
></el-button>
</el-tooltip>
<!-- 已拒绝状态:显示重新提交按钮(需要修改并重新提交权限) -->
@@ -115,7 +115,7 @@
type="success"
icon="RefreshRight"
@click="handleUpdateAndResubmitApplication(scope.row)"
v-hasPermi="['rs:training:application:edit', 'rs:training:application:submit']"
v-hasPermi="['rs:trainingapplication:edit', 'rs:trainingapplication:submit']"
></el-button>
</el-tooltip>
<!-- 已通过和已拒绝状态:显示审批历史 -->
@@ -128,8 +128,8 @@
link
type="danger"
icon="Delete"
@click="handleDeleteApplication(scope.row)"
v-hasPermi="['rs:training:application:remove']"
@click="handleDeleteApplication(scope.row)"
v-hasPermi="['rs:trainingapplication:remove']"
></el-button>
</el-tooltip>
</template>
@@ -161,16 +161,13 @@
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="学员姓名" prop="userName">
<el-input v-model="recordQueryParams.userName" placeholder="请输入学员姓名" clearable @keyup.enter="handleRecordQuery" />
<el-form-item label="培训地点" prop="location">
<el-input v-model="recordQueryParams.location" placeholder="请输入培训地点" clearable @keyup.enter="handleRecordQuery" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="完成状态" prop="completionStatus">
<el-select v-model="recordQueryParams.completionStatus" placeholder="请选择完成状态" clearable style="width: 100%">
<el-option label="未完成" value="0" />
<el-option label="已完成" value="1" />
</el-select>
<el-form-item label="部门" prop="department">
<el-input v-model="recordQueryParams.department" placeholder="请输入部门" clearable style="width: 100%" />
</el-form-item>
</el-col>
</el-row>
@@ -193,7 +190,7 @@
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button icon="Download" @click="handleExportRecord" v-hasPermi="['rs:training:record:export']">导出</el-button>
<el-button icon="Download" @click="handleExportRecord" v-hasPermi="['rs:training:record:export']" style="display: none">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showRecordSearch" @queryTable="getRecordList"></right-toolbar>
</el-row>
@@ -210,21 +207,17 @@
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="课程名称" align="center" prop="courseName" min-width="150" :show-overflow-tooltip="true" />
<el-table-column label="培训地点" align="center" prop="location" min-width="110" :show-overflow-tooltip="true" />
<el-table-column label="学时" align="center" prop="duration" width="80" />
<el-table-column label="申请时间" align="center" prop="applyTime" width="160">
<template #default="scope">
<span>{{ parseTime(scope.row.applyTime) }}</span>
</template>
</el-table-column>
<el-table-column label="申请状态" align="center" prop="status" width="100">
<el-table-column label="部门" align="center" prop="department" min-width="110" :show-overflow-tooltip="true" />
<el-table-column label="完成状态" align="center" prop="completionStatus" width="100">
<template #default="scope">
<el-tag
:type="scope.row.status === '0' ? 'warning' : scope.row.status === '1' ? 'success' : scope.row.status === '2' ? 'danger' : 'info'"
:type="scope.row.completionStatus === '0' ? 'warning' : scope.row.completionStatus === '1' ? 'success' : 'info'"
>
{{ getStatusLabel(scope.row.status) }}
{{ scope.row.completionStatus === '0' ? '未完成' : scope.row.completionStatus === '1' ? '已完成' : '未知' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="学时" align="center" prop="duration" width="80" />
<el-table-column label="完成时间" align="center" prop="completionTime" width="160">
<template #default="scope">
<span>{{ parseTime(scope.row.completionTime) || '未完成' }}</span>
@@ -355,7 +348,7 @@
type="primary"
@click="handleViewApplications(courseDetail)"
v-if="courseDetail.courseId"
v-hasPermi="['rs:training:application:list']"
v-hasPermi="['rs:trainingapplication:list']"
>查看申请记录</el-button
>
<el-button @click="courseDetailDialogVisible = false">关 闭</el-button>
@@ -456,7 +449,12 @@
<el-input-number v-model="applicationForm.duration" :min="0" :max="1000" :step="0.5" style="width: 200px" />
</el-form-item>
<el-form-item label="所属部门" prop="department">
<el-input v-model="applicationForm.department" placeholder="请输入所属部门" :disabled="true" />
<el-input
v-model="applicationForm.department"
placeholder="请输入所属部门"
readonly
class="readonly-input"
/>
</el-form-item>
<el-form-item label="培训时间" required>
<el-col :span="11">
@@ -771,7 +769,8 @@ import {
deleteTrainingApplication,
getTrainingApprovalHistory,
resubmitTrainingApplication,
updateRecordAttachments
updateRecordAttachments,
listAllApprovalRecords
} from '@/api/rs/training';
import { parseTime } from '@/utils/ruoyi';
import request from '@/utils/request';
@@ -787,12 +786,15 @@ import type {
ApplicationVO,
ApplicationForm
} from '@/api/rs/training';
import { listDept } from '@/api/system/dept';
import { listDept, getDept } from '@/api/system/dept';
import type { DeptVO } from '@/api/system/dept/types';
import { getFilePreviewUrl } from '@/api/system/file';
import { getToken } from '@/utils/auth';
import { getInfo as getUserInfo } from '@/api/login';
import { useUserStore } from '@/store/modules/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const userStore = useUserStore();
// 环境变量
const baseApi = import.meta.env.VITE_APP_BASE_API;
@@ -976,17 +978,19 @@ const applicationDetail = reactive<any>({
const approvalHistoryOpen = ref(false);
const approvalHistoryList = ref<any[]>([]);
// 培训记录相关
// 培训记录相关
const recordLoading = ref(false);
const recordList = ref<RecordVO[]>([]);
const recordList = ref<RecordVO[]>([]);
const recordTotal = ref(0);
const showRecordSearch = ref(true);
const recordQueryParams = reactive<RecordQuery>({
const recordQueryParams = reactive<RecordQuery>({
pageNum: 1,
pageSize: 10,
pageSize: 20,
courseId: undefined as string | number | undefined,
courseName: '',
userId: undefined as string | number | undefined,
userName: '',
department: '',
completionStatus: '',
params: {}
});
@@ -1325,17 +1329,72 @@ function getApplicationList() {
}
/** 新增培训申请 */
function handleAddApplication() {
async function handleAddApplication() {
resetApplicationForm();
applicationDialogVisible.value = true;
applicationDialogTitle.value = '申请培训';
// 加载课程选项
if (courseOptions.value.length === 0) {
if (courseOptions.value && courseOptions.value.length === 0) {
loadCourseOptions();
}
// 模拟用户部门信息
applicationForm.department = '计算机科学学院';
// 自动获取登录用户的部门信息
try {
// 确保用户信息已加载
if (!userStore.userId) {
await userStore.getInfo();
}
console.log('开始自动填充用户部门信息:', {
userId: userStore.userId,
cachedDeptName: userStore.deptName
});
// 重新获取用户信息以确保获取到deptId
await userStore.getInfo();
const userInfo = await getUserInfo();
const userDeptId = userInfo.data.user.deptId;
console.log('用户信息详情:', {
userId: userStore.userId,
deptId: userDeptId,
cachedDeptName: userStore.deptName
});
// 如果有deptId,从数据库sys_dept表实时获取部门名称
if (userDeptId) {
console.log('开始从数据库sys_dept表获取部门信息 - deptId:', userDeptId);
try {
const deptResponse = await getDept(userDeptId);
if (deptResponse.code === 200 && deptResponse.data) {
const realDeptName = deptResponse.data.deptName;
applicationForm.department = realDeptName;
console.log('培训申请部门自动匹配成功:', {
userId: userStore.userId,
userDeptId: userDeptId,
deptNameFromDatabase: realDeptName,
关联逻辑: 'sys_user.dept_id -> sys_dept.dept_name'
});
} else {
console.warn('从数据库获取部门信息失败,使用缓存的部门名称');
applicationForm.department = userStore.deptName || '';
}
} catch (deptError) {
console.error('查询部门信息API调用失败:', deptError);
applicationForm.department = userStore.deptName || '';
}
} else {
console.warn('用户deptId不存在,使用缓存的部门名称');
applicationForm.department = userStore.deptName || '';
}
} catch (error) {
console.error('获取用户信息失败:', error);
// 如果获取失败,使用空字符串,用户可以手动输入
applicationForm.department = '';
}
}
/** 重置培训申请表单 */
@@ -1722,8 +1781,12 @@ function handleTrainingSubTabClick() {
// 加载课程选项
function loadCourseOptions() {
return listTrainingCourse({ pageNum: 1, pageSize: 100, status: '0' }).then((response) => {
courseOptions.value = response.rows;
return response.rows;
courseOptions.value = response.rows || [];
return courseOptions.value;
}).catch((error) => {
console.error('加载课程选项失败:', error);
courseOptions.value = [];
throw error;
});
}
@@ -1755,10 +1818,19 @@ function remoteSearchUser(query: string) {
/** 获取培训记录列表 */
function getRecordList() {
recordLoading.value = true;
listTrainingRecord(recordQueryParams).then(response => {
// 设置当前用户ID,只查询当前用户的培训记录
const queryParams = {
...recordQueryParams,
userId: userStore.userId // 设置当前用户ID
};
// 调用培训记录接口,获取培训记录数据
listTrainingRecord(queryParams).then(response => {
recordList.value = response.rows;
recordTotal.value = response.total;
recordLoading.value = false;
}).catch(() => {
recordLoading.value = false;
});
}
@@ -1768,13 +1840,14 @@ function handleAddRecord() {
recordDialogVisible.value = true;
recordDialogTitle.value = '添加培训记录';
// 加载课程选项
if (courseOptions.value.length === 0) {
if (!courseOptions.value || courseOptions.value.length === 0) {
loadCourseOptions();
}
}
/** 重置培训记录表单 */
function resetRecordForm() {
console.log('resetRecordForm 开始执行');
recordForm.recordId = undefined;
recordForm.courseId = '';
recordForm.userId = '';
@@ -1787,8 +1860,18 @@ function resetRecordForm() {
recordForm.attachmentIds = '';
recordForm.feedback = '';
recordForm.remark = '';
recordCertificateFileList.value = [];
console.log('开始重置附件列表,当前 recordCertificateFileList.value:', recordCertificateFileList.value);
if (recordCertificateFileList.value) {
recordCertificateFileList.value = [];
} else {
console.warn('recordCertificateFileList.value 是 undefined,创建新数组');
recordCertificateFileList.value = [];
}
console.log('开始重置表单字段');
recordFormRef.value?.resetFields();
console.log('resetRecordForm 执行完成');
}
/** 取消培训记录对话框 */
@@ -1808,6 +1891,10 @@ function submitRecordForm() {
console.log('证书路径:', recordForm.certificatePath);
console.log('证书文件名:', recordForm.certificateFileName);
// 在提交前确保attachmentIds字段是最新的
updateRecordFormAttachmentIds();
console.log('提交前的attachmentIds:', recordForm.attachmentIds);
if (recordForm.recordId) {
// 修改记录时,保存证书信息到本地存储
if (recordForm.certificatePath) {
@@ -1873,51 +1960,108 @@ async function handleUpdateRecord(row: RecordVO) {
console.log('=== 修改培训记录开始 ===');
console.log('row数据:', row);
resetRecordForm();
// 加载课程选项
if (courseOptions.value.length === 0) {
loadCourseOptions();
}
try {
const response = await getTrainingRecord(row.recordId);
const data = response.data || row;
Object.assign(recordForm, data);
// 确保课程名称正确显示
if (!recordForm.courseName && recordForm.courseId) {
const course = courseOptions.value.find((c) => c.courseId === recordForm.courseId);
if (course) {
recordForm.courseName = course.title;
}
// 立即显示对话框,避免用户等待
recordDialogVisible.value = true;
recordDialogTitle.value = '修改培训记录';
// 重置表单
try {
console.log('开始重置表单...');
resetRecordForm();
console.log('表单重置完成');
} catch (error) {
console.error('重置表单时出错:', error);
throw error;
}
} catch (error) {
console.log('使用模拟数据,原因:', error);
// 模拟数据,实际应使用API返回的数据
Object.assign(recordForm, {
recordId: row.recordId,
courseId: row.courseId,
courseName: row.courseName,
userId: row.userId,
completionStatus: row.completionStatus,
score: row.score,
duration: row.duration,
completionTime: row.completionTime,
certificatePath: row.certificatePath,
certificateFileName: row.certificateFileName,
remark: row.remark
// 先设置基础数据,确保对话框内容可见
try {
console.log('开始设置基础数据...');
Object.assign(recordForm, {
recordId: row.recordId,
courseId: row.courseId,
courseName: row.courseName,
userId: row.userId,
userName: row.userName,
completionStatus: row.completionStatus || '0',
score: row.score || '',
duration: row.duration || '',
completionTime: row.completionTime || '',
certificatePath: row.certificatePath || '',
certificateNumber: row.certificateNumber || '',
certificateFileName: row.certificateFileName || '',
attachmentIds: (row as any).attachmentIds || '',
feedback: row.feedback || '',
remark: row.remark || ''
});
console.log('基础数据设置完成,attachmentIds:', recordForm.attachmentIds);
} catch (error) {
console.error('设置基础数据时出错:', error);
throw error;
}
console.log('设置基础数据后的recordForm:', recordForm);
console.log('当前courseOptions.value:', courseOptions.value);
// 异步加载课程选项(如果还没有加载)
try {
console.log('开始处理课程选项,当前courseOptions:', courseOptions.value);
if (!courseOptions.value || courseOptions.value.length === 0) {
console.log('需要加载课程选项');
loadCourseOptions().then(() => {
console.log('课程选项加载完成,开始匹配课程名称');
// 确保课程名称正确显示
if (!recordForm.courseName && recordForm.courseId && courseOptions.value) {
const course = courseOptions.value.find((c) => c.courseId === recordForm.courseId);
if (course) {
recordForm.courseName = course.title;
}
}
}).catch(error => {
console.warn('加载课程选项失败:', error);
});
} else {
console.log('使用现有课程选项');
// 确保课程名称正确显示
if (!recordForm.courseName && recordForm.courseId && courseOptions.value) {
const course = courseOptions.value.find((c) => c.courseId === recordForm.courseId);
if (course) {
recordForm.courseName = course.title;
}
}
}
console.log('课程选项处理完成');
} catch (error) {
console.error('处理课程选项时出错:', error);
throw error;
}
// 异步获取详细数据(可选)
try {
const response = await getTrainingRecord(row.recordId);
if (response.data) {
// 合并API返回的数据,保留已设置的基础数据
Object.assign(recordForm, response.data);
console.log('API返回的详细数据:', response.data);
}
} catch (error) {
console.log('获取详细数据失败,使用基础数据:', error);
// 使用基础数据继续,不影响对话框显示
}
// 异步处理证书附件数据
handleRecordAttachmentData().catch(error => {
console.warn('处理附件数据失败:', error);
// 不影响对话框显示
});
console.log('=== 修改培训记录完成 ===');
} catch (error) {
console.error('修改培训记录过程中发生错误:', error);
// 即使出错也要显示对话框,让用户看到基础数据
proxy?.$modal.msgError('加载培训记录数据时发生错误,请重试');
}
console.log('设置后的recordForm:', recordForm);
// 处理证书附件数据
await handleRecordAttachmentData();
recordDialogVisible.value = true;
recordDialogTitle.value = '修改培训记录';
console.log('=== 修改培训记录完成 ===');
}
/** 查看培训记录详情 */
@@ -1960,7 +2104,7 @@ function handleDeleteRecord(row?: RecordVO) {
if (row) {
confirmMessage = `是否确认删除学员"${row.userName}"的培训记录?`;
} else {
const selectedItems = recordList.value.filter((item) => recordIds.value.includes(item.recordId as number | string));
const selectedItems = recordList.value.filter((item) => recordIds.value.includes(item.applicationId as number | string));
if (selectedItems.length === 1) {
confirmMessage = `是否确认删除学员"${selectedItems[0].userName}"的培训记录?`;
} else {
@@ -2090,7 +2234,7 @@ function handleRecordCertificateSuccess(response: any, file: any) {
file.url = response.data.url;
file.ossId = response.data.ossId;
proxy?.$modal.msgSuccess('证书上传成功!');
proxy?.$modal.msgSuccess('证书上传成功!');
console.log('证书上传成功:', response.data);
// 更新文件状态为成功
@@ -2099,6 +2243,9 @@ function handleRecordCertificateSuccess(response: any, file: any) {
// 自动保存附件ID到后端
saveRecordAttachments();
// 同时更新recordForm中的attachmentIds字段,确保提交时包含附件信息
updateRecordFormAttachmentIds();
}
}
@@ -2147,6 +2294,25 @@ async function saveRecordAttachments() {
}
}
/** 更新recordForm中的attachmentIds字段 */
function updateRecordFormAttachmentIds() {
if (!recordForm.recordId) {
console.warn('记录ID为空,无法更新附件ID');
return;
}
// 提取所有成功上传的ossId
const attachmentOssIds = recordCertificateFileList.value
.filter(file => file.status === 'success' && file.ossId)
.map(file => file.ossId);
// 转换为逗号分隔的字符串并更新recordForm
const attachmentIds = attachmentOssIds.join(',');
recordForm.attachmentIds = attachmentIds;
console.log('更新recordForm.attachmentIds:', attachmentIds);
}
/** 处理培训记录附件数据 */
async function handleRecordAttachmentData() {
try {
@@ -2761,6 +2927,9 @@ function handleRemoveCertificate(file: any) {
// 自动保存附件ID到后端
saveRecordAttachments();
// 同时更新recordForm中的attachmentIds字段
updateRecordFormAttachmentIds();
proxy?.$modal.msgSuccess('证书文件已删除');
}
@@ -2774,8 +2943,8 @@ function handleRecordQuery() {
function resetRecordQuery() {
recordQueryForm.value?.resetFields();
recordQueryParams.courseName = '';
recordQueryParams.userName = '';
recordQueryParams.completionStatus = '';
recordQueryParams.location = '';
recordQueryParams.department = '';
handleRecordQuery();
}
@@ -3115,6 +3284,19 @@ onMounted(() => {
color: #909399 !important;
line-height: 1.4 !important;
}
/* 只读输入框样式 */
.readonly-input :deep(.el-input__inner) {
background-color: #f5f7fa !important;
color: #606266 !important;
border-color: #dcdfe6 !important;
cursor: not-allowed !important;
}
.readonly-input :deep(.el-input__inner:focus) {
border-color: #dcdfe6 !important;
box-shadow: none !important;
}
</style>
<style scoped>
+32 -8
View File
@@ -57,7 +57,7 @@
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button icon="Download" @click="handleExportTrainingApplication" v-hasPermi="['rs:trainingApproval:export']">导出</el-button>
<el-button icon="Download" @click="handleExportTrainingApplication" v-hasPermi="['rs:trainingapproval:export']" style="display: none">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showApplicationSearch" @queryTable="getApplicationList"></right-toolbar>
</el-row>
@@ -120,7 +120,7 @@
</el-tab-pane>
<!-- 审批记录选项卡 -->
<el-tab-pane label="审批记录" name="approvalRecord" v-hasPermi="['rs:trainingApproval:query']">
<el-tab-pane label="审批记录" name="approvalRecord" v-hasPermi="['rs:trainingapproval:query']">
<!-- 搜索区域 -->
<transition :enter-active-class="animate.searchAnimate.enter" :leave-active-class="animate.searchAnimate.leave">
<div v-show="showApprovalRecordSearch" class="mb-[10px]">
@@ -175,7 +175,7 @@
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button icon="Download" @click="handleExportApprovalRecord" v-hasPermi="['rs:trainingApproval:export']">导出</el-button>
<el-button icon="Download" @click="handleExportApprovalRecord" v-hasPermi="['rs:trainingapproval:export']">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showApprovalRecordSearch" @queryTable="getApprovalRecordList"></right-toolbar>
</el-row>
@@ -351,12 +351,12 @@
<el-row>
<el-col :span="12">
<el-form-item label="申请时间">
<el-input v-model="approvalRecordDetail.applyTime" readonly />
<el-input :value="parseTime(approvalRecordDetail.applyTime)" readonly />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="审批时间">
<el-input v-model="approvalRecordDetail.approvalTime" readonly />
<el-input :value="parseTime(approvalRecordDetail.approvalTime)" readonly />
</el-form-item>
</el-col>
</el-row>
@@ -822,8 +822,26 @@ const handleApprovalRecordSelectionChange = (selection: any[]) => {
// 查看审批记录详情
const handleViewApprovalRecord = async (row: any) => {
try {
const response = await getTrainingApplication(row.applicationId);
Object.assign(approvalRecordDetail, response.data);
// 获取原始申请数据,以获取完整的申请信息(申请时间、部门、申请理由等)
const applicationResponse = await getTrainingApplication(row.applicationId);
const applicationData = applicationResponse.data;
// 合并申请数据和审批数据
Object.assign(approvalRecordDetail, {
applicationId: row.applicationId,
courseId: applicationData.courseId,
courseName: applicationData.courseName,
userId: applicationData.userId,
userName: applicationData.userName,
department: applicationData.department, // 从申请数据获取部门
status: row.status, // 使用审批记录的状态
applyTime: applicationData.applyTime, // 从申请数据获取申请时间
approvalTime: row.approvalTime, // 从审批记录获取审批时间
reason: applicationData.reason, // 从申请数据获取申请理由
remark: applicationData.remark,
adminRemark: row.opinion, // 从审批记录获取审批意见
certificatePath: applicationData.certificatePath
});
// 获取审批历史记录
const historyResponse = await getTrainingApprovalHistory(row.applicationId);
@@ -1007,7 +1025,13 @@ onMounted(() => {
}
.search-btn-container {
text-align: right;
display: flex;
justify-content: flex-end;
margin-top: 10px;
}
.search-btn-container :deep(.el-form-item) {
margin-bottom: 0 !important;
}
.button-card {