소스 검색

提交代码

zlwu 1 년 전
부모
커밋
62c953ab72
17개의 변경된 파일과 674개의 추가작업 그리고 141개의 파일을 삭제
  1. 23 0
      backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/controller/XskhDisciplineRecordController.java
  2. 13 0
      backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/controller/XskhRewardRecordController.java
  3. 24 0
      backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/domain/vo/XskhAssessmentApplicationApprovalVo.java
  4. 23 0
      backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/mapper/XskhDisciplineRecordMapper.java
  5. 14 0
      backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/mapper/XskhRewardRecordMapper.java
  6. 21 0
      backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/service/IXskhDisciplineRecordService.java
  7. 14 2
      backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/service/IXskhRewardRecordService.java
  8. 6 4
      backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/service/impl/XskhAssessmentApplicationApprovalServiceImpl.java
  9. 34 0
      backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/service/impl/XskhDisciplineRecordServiceImpl.java
  10. 26 0
      backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/service/impl/XskhRewardRecordServiceImpl.java
  11. 33 7
      backend/ruoyi-modules/ruoyi-xskh/src/main/resources/mapper/XskhDisciplineRecordMapper.xml
  12. 20 0
      backend/ruoyi-modules/ruoyi-xskh/src/main/resources/mapper/xskh/XskhRewardRecordMapper.xml
  13. 12 0
      web/src/api/xskh/assessmentApplication/types.ts
  14. 1 61
      web/src/api/xskh/disciplineRecord/disciplineRecord/types.ts
  15. 1 61
      web/src/api/xskh/xsDisciplineRecord/xsDisciplineRecord/types.ts
  16. 140 6
      web/src/views/xskh/assessmentApplication/AssessmentApplicationForm.vue
  17. 269 0
      web/src/views/xskh/assessmentApplication/IndicatorDataDialog.vue

+ 23 - 0
backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/controller/XskhDisciplineRecordController.java

@@ -1,6 +1,7 @@
 package org.dromara.xskh.controller;
 
 import java.util.List;
+import java.util.Map;
 
 import lombok.RequiredArgsConstructor;
 import jakarta.servlet.http.HttpServletResponse;
@@ -130,4 +131,26 @@ public class XskhDisciplineRecordController extends BaseController {
             PageQuery pageQuery) {
         return xskhDisciplineRecordService.queryClassTeacherPageList(bo, pageQuery);
     }
+
+    /**
+     * 获取指标关联的违纪处分类型和奖励类型
+     */
+    @SaCheckPermission("disciplineRecord:disciplineRecord:query")
+    @GetMapping("/getIndicatorTypes/{indicatorId}")
+    public R<Map<String, String>> getIndicatorTypes(@NotNull(message = "指标ID不能为空") @PathVariable Long indicatorId) {
+        return R.ok(xskhDisciplineRecordService.getIndicatorTypes(indicatorId));
+    }
+
+    /**
+     * 获取学生在指定时间范围内的违纪处分记录
+     */
+    @SaCheckPermission("disciplineRecord:disciplineRecord:query")
+    @GetMapping("/getStudentDisciplineRecords")
+    public R<List<XskhDisciplineRecordVo>> getStudentDisciplineRecords(
+            @RequestParam Long studentId,
+            @RequestParam String disciplineTypeIds,
+            @RequestParam String startTime,
+            @RequestParam String endTime) {
+        return R.ok(xskhDisciplineRecordService.getStudentDisciplineRecords(studentId, disciplineTypeIds, startTime, endTime));
+    }
 }

+ 13 - 0
backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/controller/XskhRewardRecordController.java

@@ -130,4 +130,17 @@ public class XskhRewardRecordController extends BaseController {
             PageQuery pageQuery) {
         return xskhRewardRecordService.queryClassTeacherPageList(bo, pageQuery);
     }
+
+    /**
+     * 获取学生在指定时间范围内的奖励记录
+     */
+    @SaCheckPermission("rewardRecord:rewardRecord:query")
+    @GetMapping("/getStudentRewardRecords")
+    public R<List<XskhRewardRecordVo>> getStudentRewardRecords(
+            @RequestParam Long studentId,
+            @RequestParam String rewardTypeIds,
+            @RequestParam String startTime,
+            @RequestParam String endTime) {
+        return R.ok(xskhRewardRecordService.getStudentRewardRecords(studentId, rewardTypeIds, startTime, endTime));
+    }
 }

+ 24 - 0
backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/domain/vo/XskhAssessmentApplicationApprovalVo.java

@@ -39,6 +39,30 @@ public class XskhAssessmentApplicationApprovalVo implements Serializable {
      */
     private String scheduleName;
 
+    /**
+     * 考核开始时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date startTime;
+
+    /**
+     * 考核结束时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date endTime;
+
+    /**
+     * 数据统计开始时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date dataStartTime;
+
+    /**
+     * 数据统计结束时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date dataEndTime;
+
     /**
      * 学生ID
      */

+ 23 - 0
backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/mapper/XskhDisciplineRecordMapper.java

@@ -9,6 +9,7 @@ import org.dromara.xskh.domain.vo.XskhDisciplineRecordVo;
 import org.dromara.xskh.domain.vo.XskhStudentOptionVo;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * 学生违纪处分记录Mapper接口
@@ -38,4 +39,26 @@ public interface XskhDisciplineRecordMapper extends BaseMapperPlus<XskhDisciplin
             @Param("bo") XskhDisciplineRecordBo bo,
             @Param("classTeacherId") Long classTeacherId);
 
+    /**
+     * 获取指标关联的违纪处分类型和奖励类型
+     *
+     * @param indicatorId 指标ID
+     * @return 包含disciplineTypeIds和rewardTypeIds的Map
+     */
+    Map<String, String> selectIndicatorTypes(@Param("indicatorId") Long indicatorId);
+
+    /**
+     * 获取学生在指定时间范围内的违纪处分记录
+     *
+     * @param studentId         学生ID
+     * @param disciplineTypeIds 违纪处分类型ID列表
+     * @param startTime         开始时间
+     * @param endTime           结束时间
+     * @return 违纪处分记录列表
+     */
+    List<XskhDisciplineRecordVo> selectStudentDisciplineRecords(@Param("studentId") Long studentId,
+            @Param("disciplineTypeIds") List<Long> disciplineTypeIds,
+            @Param("startTime") String startTime,
+            @Param("endTime") String endTime);
+
 }

+ 14 - 0
backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/mapper/XskhRewardRecordMapper.java

@@ -37,4 +37,18 @@ public interface XskhRewardRecordMapper extends BaseMapperPlus<XskhRewardRecord,
     Page<XskhRewardRecordVo> selectClassTeacherVoPage(@Param("page") Page<XskhRewardRecordVo> page,
             @Param("bo") XskhRewardRecordBo bo,
             @Param("classTeacherId") Long classTeacherId);
+
+    /**
+     * 获取学生在指定时间范围内的奖励记录
+     *
+     * @param studentId     学生ID
+     * @param rewardTypeIds 奖励类型ID列表
+     * @param startTime     开始时间
+     * @param endTime       结束时间
+     * @return 奖励记录列表
+     */
+    List<XskhRewardRecordVo> selectStudentRewardRecords(@Param("studentId") Long studentId,
+            @Param("rewardTypeIds") List<Long> rewardTypeIds,
+            @Param("startTime") String startTime,
+            @Param("endTime") String endTime);
 }

+ 21 - 0
backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/service/IXskhDisciplineRecordService.java

@@ -8,6 +8,7 @@ import org.dromara.xskh.domain.vo.XskhStudentOptionVo;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 学生违纪处分记录Service接口
@@ -70,4 +71,24 @@ public interface IXskhDisciplineRecordService {
      * @return 更新结果
      */
     Boolean updateDisciplineRecordStatus(Long id, String status);
+
+    /**
+     * 获取指标关联的违纪处分类型和奖励类型
+     *
+     * @param indicatorId 指标ID
+     * @return 包含disciplineTypeIds和rewardTypeIds的Map
+     */
+    Map<String, String> getIndicatorTypes(Long indicatorId);
+
+    /**
+     * 获取学生在指定时间范围内的违纪处分记录
+     *
+     * @param studentId         学生ID
+     * @param disciplineTypeIds 违纪处分类型ID,逗号分隔
+     * @param startTime         开始时间
+     * @param endTime           结束时间
+     * @return 违纪处分记录列表
+     */
+    List<XskhDisciplineRecordVo> getStudentDisciplineRecords(Long studentId, String disciplineTypeIds, String startTime,
+            String endTime);
 }

+ 14 - 2
backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/service/IXskhRewardRecordService.java

@@ -78,7 +78,7 @@ public interface IXskhRewardRecordService {
     /**
      * 查询当前登录学生的奖励记录列表
      *
-     * @param bo 查询条件
+     * @param bo        查询条件
      * @param pageQuery 分页参数
      * @return 分页结果
      */
@@ -87,9 +87,21 @@ public interface IXskhRewardRecordService {
     /**
      * 查询班主任班级的奖励记录列表(班主任专用)
      *
-     * @param bo 查询条件
+     * @param bo        查询条件
      * @param pageQuery 分页参数
      * @return 分页结果
      */
     TableDataInfo<XskhRewardRecordVo> queryClassTeacherPageList(XskhRewardRecordBo bo, PageQuery pageQuery);
+
+    /**
+     * 获取学生在指定时间范围内的奖励记录
+     *
+     * @param studentId     学生ID
+     * @param rewardTypeIds 奖励类型ID,逗号分隔
+     * @param startTime     开始时间
+     * @param endTime       结束时间
+     * @return 奖励记录列表
+     */
+    List<XskhRewardRecordVo> getStudentRewardRecords(Long studentId, String rewardTypeIds, String startTime,
+            String endTime);
 }

+ 6 - 4
backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/service/impl/XskhAssessmentApplicationApprovalServiceImpl.java

@@ -261,10 +261,12 @@ public class XskhAssessmentApplicationApprovalServiceImpl implements IXskhAssess
             vo.setScheduleName(schedule.getScheduleName());
             // 设置考核计划的状态信息
             vo.setStatus(schedule.getStatus());
-            // 设置时间信息到备注字段(前端会解析)
-            String timeInfo = String.format("开始时间:%s,结束时间:%s",
-                    schedule.getStartTime(), schedule.getEndTime());
-            vo.setTeacherApprovalRemark(timeInfo); // 临时使用这个字段存储时间信息
+            // 设置考核计划的时间信息
+            vo.setStartTime(schedule.getStartTime());
+            vo.setEndTime(schedule.getEndTime());
+            // 设置数据统计时间范围(用于指标数据查询)
+            vo.setDataStartTime(schedule.getDataStartTime());
+            vo.setDataEndTime(schedule.getDataEndTime());
             result.add(vo);
         }
 

+ 34 - 0
backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/service/impl/XskhDisciplineRecordServiceImpl.java

@@ -21,6 +21,8 @@ import org.springframework.stereotype.Service;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.Arrays;
+import java.util.stream.Collectors;
 
 /**
  * 学生违纪处分记录Service业务层处理
@@ -212,4 +214,36 @@ public class XskhDisciplineRecordServiceImpl implements IXskhDisciplineRecordSer
         record.setStatus(status);
         return baseMapper.updateById(record) > 0;
     }
+
+    /**
+     * 获取指标关联的违纪处分类型和奖励类型
+     */
+    @Override
+    public Map<String, String> getIndicatorTypes(Long indicatorId) {
+        return baseMapper.selectIndicatorTypes(indicatorId);
+    }
+
+    /**
+     * 获取学生在指定时间范围内的违纪处分记录
+     */
+    @Override
+    public List<XskhDisciplineRecordVo> getStudentDisciplineRecords(Long studentId, String disciplineTypeIds,
+            String startTime, String endTime) {
+        if (StringUtils.isBlank(disciplineTypeIds)) {
+            return List.of();
+        }
+
+        // 将逗号分隔的字符串转换为List<Long>
+        List<Long> typeIds = Arrays.stream(disciplineTypeIds.split(","))
+                .map(String::trim)
+                .filter(StringUtils::isNotBlank)
+                .map(Long::valueOf)
+                .collect(Collectors.toList());
+
+        if (typeIds.isEmpty()) {
+            return List.of();
+        }
+
+        return baseMapper.selectStudentDisciplineRecords(studentId, typeIds, startTime, endTime);
+    }
 }

+ 26 - 0
backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/service/impl/XskhRewardRecordServiceImpl.java

@@ -21,6 +21,8 @@ import org.dromara.xskh.service.IXskhRewardRecordService;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Arrays;
+import java.util.stream.Collectors;
 import java.util.Map;
 
 /**
@@ -223,4 +225,28 @@ public class XskhRewardRecordServiceImpl implements IXskhRewardRecordService {
         Page<XskhRewardRecordVo> result = baseMapper.selectClassTeacherVoPage(pageQuery.build(), bo, currentUserId);
         return TableDataInfo.build(result);
     }
+
+    /**
+     * 获取学生在指定时间范围内的奖励记录
+     */
+    @Override
+    public List<XskhRewardRecordVo> getStudentRewardRecords(Long studentId, String rewardTypeIds, String startTime,
+            String endTime) {
+        if (StringUtils.isBlank(rewardTypeIds)) {
+            return List.of();
+        }
+
+        // 将逗号分隔的字符串转换为List<Long>
+        List<Long> typeIds = Arrays.stream(rewardTypeIds.split(","))
+                .map(String::trim)
+                .filter(StringUtils::isNotBlank)
+                .map(Long::valueOf)
+                .collect(Collectors.toList());
+
+        if (typeIds.isEmpty()) {
+            return List.of();
+        }
+
+        return baseMapper.selectStudentRewardRecords(studentId, typeIds, startTime, endTime);
+    }
 }

+ 33 - 7
backend/ruoyi-modules/ruoyi-xskh/src/main/resources/mapper/XskhDisciplineRecordMapper.xml

@@ -22,10 +22,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="disciplineContent" column="discipline_content" />
         <result property="scoreDeduction" column="score_deduction" />
         <result property="status" column="status" />
-        <result property="approvalStatus" column="approval_status" />
-        <result property="approvalBy" column="approval_by" />
-        <result property="approvalTime" column="approval_time" />
-        <result property="approvalRemark" column="approval_remark" />
         <result property="attachmentOssIds" column="attachment_oss_ids" />
         <result property="createBy" column="create_by" />
         <result property="createTime" column="create_time" />
@@ -49,7 +45,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </resultMap>
 
     <sql id="selectXskhDisciplineRecordVo">
-        select id, student_id, student_no, student_name, college_id, college_name, major_id, major_name, class_id, class_name, discipline_type_id, discipline_type_name, discipline_date, discipline_reason, discipline_content, score_deduction, status, approval_status, approval_by, approval_time, approval_remark, attachment_oss_ids, create_by, create_time, create_dept, update_by, update_time, deleted, tenant_id from xskh_discipline_record
+        select id, student_id, student_no, student_name, college_id, college_name, major_id, major_name, class_id, class_name, discipline_type_id, discipline_type_name, discipline_date, discipline_reason, discipline_content, score_deduction, status, attachment_oss_ids, create_by, create_time, create_dept, update_by, update_time, deleted, tenant_id from xskh_discipline_record
     </sql>
 
     <select id="selectStudentOptions" parameterType="String" resultMap="StudentOptionResult">
@@ -71,8 +67,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         select dr.id, dr.student_id, dr.student_no, dr.student_name, dr.college_id, dr.college_name,
                dr.major_id, dr.major_name, dr.class_id, dr.class_name, dr.discipline_type_id,
                dr.discipline_type_name, dr.discipline_date, dr.discipline_reason, dr.discipline_content,
-               dr.score_deduction, dr.status, dr.approval_status, dr.approval_by, dr.approval_time,
-               dr.approval_remark, dr.attachment_oss_ids, dr.create_by, dr.create_time, dr.create_dept,
+               dr.score_deduction, dr.status, dr.attachment_oss_ids, dr.create_by, dr.create_time, dr.create_dept,
                dr.update_by, dr.update_time, dr.deleted, dr.tenant_id
         from xskh_discipline_record dr
         where dr.deleted = 0
@@ -98,4 +93,35 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         order by dr.create_time desc
     </select>
 
+    <!-- 获取指标关联的违纪处分类型和奖励类型 -->
+    <select id="selectIndicatorTypes" parameterType="Long" resultType="java.util.Map">
+        select
+            discipline_type_ids,
+            reward_type_ids
+        from xskh_assessment_indicator_discipline_type
+        where indicator_id = #{indicatorId}
+          and deleted = 0
+        limit 1
+    </select>
+
+    <!-- 获取学生在指定时间范围内的违纪处分记录 -->
+    <select id="selectStudentDisciplineRecords" resultType="XskhDisciplineRecordVo">
+        select
+            id, student_id, student_no, student_name, college_id, college_name,
+            major_id, major_name, class_id, class_name, discipline_type_id,
+            discipline_type_name, discipline_date, discipline_reason, discipline_content,
+            score_deduction, status, attachment_oss_ids, create_by, create_time, create_dept,
+            update_by, update_time, deleted, tenant_id
+        from xskh_discipline_record
+        where deleted = 0
+          and status = '1'
+          and student_id = #{studentId}
+          and discipline_type_id in
+        <foreach collection="disciplineTypeIds" item="typeId" open="(" separator="," close=")">
+            #{typeId}
+        </foreach>
+          and discipline_date between #{startTime} and #{endTime}
+        order by create_time desc
+    </select>
+
 </mapper>

+ 20 - 0
backend/ruoyi-modules/ruoyi-xskh/src/main/resources/mapper/xskh/XskhRewardRecordMapper.xml

@@ -131,4 +131,24 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         order by rr.create_time desc
     </select>
 
+    <!-- 获取学生在指定时间范围内的奖励记录 -->
+    <select id="selectStudentRewardRecords" resultType="XskhRewardRecordVo">
+        select
+            id, student_id, student_no, student_name, college_id, college_name,
+            major_id, major_name, class_id, class_name, reward_type_id,
+            reward_type_name, reward_date, reward_content, score_addition,
+            attachment_oss_ids, status, create_by, create_time, create_dept,
+            update_by, update_time, deleted, tenant_id
+        from xskh_reward_record
+        where deleted = 0
+          and status = '1'
+          and student_id = #{studentId}
+          and reward_type_id in
+        <foreach collection="rewardTypeIds" item="typeId" open="(" separator="," close=")">
+            #{typeId}
+        </foreach>
+          and reward_date between #{startTime} and #{endTime}
+        order by create_time desc
+    </select>
+
 </mapper>

+ 12 - 0
web/src/api/xskh/assessmentApplication/types.ts

@@ -84,6 +84,14 @@ export interface XskhAssessmentApplicationApprovalVo extends BaseEntity {
   scheduleId?: string | number;
   /** 考核计划名称 */
   scheduleName?: string;
+  /** 考核开始时间 */
+  startTime?: string;
+  /** 考核结束时间 */
+  endTime?: string;
+  /** 数据统计开始时间 */
+  dataStartTime?: string;
+  /** 数据统计结束时间 */
+  dataEndTime?: string;
   /** 自评得分 */
   selfScore?: number;
   /** 自评备注 */
@@ -400,6 +408,10 @@ export interface AssessmentScheduleOption {
   startTime: string;
   /** 结束时间 */
   endTime: string;
+  /** 数据统计开始时间 */
+  dataStartTime: string;
+  /** 数据统计结束时间 */
+  dataEndTime: string;
   /** 状态 */
   status: string;
   /** 状态名称 */

+ 1 - 61
web/src/api/xskh/disciplineRecord/disciplineRecord/types.ts

@@ -86,26 +86,6 @@ export interface DisciplineRecordVO {
    */
   status: string;
 
-  /**
-   * 审批状态(1-已审批 2-审批中)
-   */
-  approvalStatus: string;
-
-  /**
-   * 审批人ID
-   */
-  approvalBy: string | number;
-
-  /**
-   * 审批时间
-   */
-  approvalTime: string;
-
-  /**
-   * 审批备注
-   */
-  approvalRemark: string;
-
   /**
    * 附件OSS ID列表,逗号分隔
    */
@@ -218,26 +198,6 @@ export interface DisciplineRecordForm {
    */
   status?: string;
 
-  /**
-   * 审批状态(1-已审批 2-审批中)
-   */
-  approvalStatus?: string;
-
-  /**
-   * 审批人ID
-   */
-  approvalBy?: string | number;
-
-  /**
-   * 审批时间
-   */
-  approvalTime?: string;
-
-  /**
-   * 审批备注
-   */
-  approvalRemark?: string;
-
   /**
    * 附件OSS ID列表,逗号分隔
    */
@@ -325,30 +285,10 @@ export interface DisciplineRecordQuery extends PageQuery {
    */
   status?: string;
 
-  /**
-   * 审批状态(1-已审批 2-审批中)
-   */
-  approvalStatus?: string;
-
-  /**
-   * 审批人ID
-   */
-  approvalBy?: string | number;
-
-  /**
-   * 审批时间
-   */
-  approvalTime?: string;
-
-  /**
-   * 审批备注
-   */
-  approvalRemark?: string;
-
   /**
    * 日期范围参数
    */
-  params?: any;
+  dateRange?: string[];
 }
 
 /**

+ 1 - 61
web/src/api/xskh/xsDisciplineRecord/xsDisciplineRecord/types.ts

@@ -86,26 +86,6 @@ export interface DisciplineRecordVO {
    */
   status: string;
 
-  /**
-   * 审批状态(1-已审批 2-审批中)
-   */
-  approvalStatus: string;
-
-  /**
-   * 审批人ID
-   */
-  approvalBy: string | number;
-
-  /**
-   * 审批时间
-   */
-  approvalTime: string;
-
-  /**
-   * 审批备注
-   */
-  approvalRemark: string;
-
   /**
    * 附件OSS ID列表,逗号分隔
    */
@@ -218,26 +198,6 @@ export interface DisciplineRecordForm {
    */
   status?: string;
 
-  /**
-   * 审批状态(1-已审批 2-审批中)
-   */
-  approvalStatus?: string;
-
-  /**
-   * 审批人ID
-   */
-  approvalBy?: string | number;
-
-  /**
-   * 审批时间
-   */
-  approvalTime?: string;
-
-  /**
-   * 审批备注
-   */
-  approvalRemark?: string;
-
   /**
    * 附件OSS ID列表,逗号分隔
    */
@@ -325,30 +285,10 @@ export interface DisciplineRecordQuery extends PageQuery {
    */
   status?: string;
 
-  /**
-   * 审批状态(1-已审批 2-审批中)
-   */
-  approvalStatus?: string;
-
-  /**
-   * 审批人ID
-   */
-  approvalBy?: string | number;
-
-  /**
-   * 审批时间
-   */
-  approvalTime?: string;
-
-  /**
-   * 审批备注
-   */
-  approvalRemark?: string;
-
   /**
    * 日期范围参数
    */
-  params?: any;
+  dateRange?: string[];
 }
 
 /**

+ 140 - 6
web/src/views/xskh/assessmentApplication/AssessmentApplicationForm.vue

@@ -65,11 +65,26 @@
             <el-card shadow="never">
               <template #header>
                 <div class="card-header">
-                  <span>指标模块</span>
+                  <span>指标模块 </span>
                 </div>
               </template>
               <el-table :data="form.selfScoreList" border style="width: 100%">
-                <el-table-column label="指标名称" prop="indicatorName" min-width="120" />
+                <el-table-column label="指标名称" prop="indicatorName" min-width="120">
+                  <template #default="scope">
+                    <div class="indicator-name-cell">
+                      <span>{{ scope.row.indicatorName }}</span>
+                      <el-button
+                        type="info"
+                        size="small"
+                        :icon="View"
+                        circle
+                        @click="handleViewIndicatorData(scope.row)"
+                        title="查看学生数据"
+                        class="indicator-data-btn"
+                      />
+                    </div>
+                  </template>
+                </el-table-column>
                 <el-table-column label="指标编码" prop="indicatorCode" min-width="100" />
                 <el-table-column label="指标说明" prop="indicatorDescription" min-width="150" show-overflow-tooltip />
                 <el-table-column label="最高分值" prop="planMaxScore" min-width="80" />
@@ -351,17 +366,29 @@
       </div>
     </template>
   </el-dialog>
+
+  <!-- 指标数据详情弹窗 -->
+  <IndicatorDataDialog
+    ref="indicatorDataDialogRef"
+    :indicator-id="currentIndicatorData.indicatorId"
+    :indicator-name="currentIndicatorData.indicatorName"
+    :student-id="form.studentId"
+    :schedule-id="form.scheduleId"
+    :data-start-time="form.dataStartTime"
+    :data-end-time="form.dataEndTime"
+  />
 </template>
 
 <script setup name="AssessmentApplicationForm" lang="ts">
-import { ref, reactive, toRefs, getCurrentInstance, ComponentInternalInstance, computed } from 'vue';
+import { ref, reactive, toRefs, getCurrentInstance, ComponentInternalInstance, computed, nextTick } from 'vue';
 import ElMessage from 'element-plus/es/components/message/index';
 import ElMessageBox from 'element-plus/es/components/message-box/index';
 import ElLoading from 'element-plus/es/components/loading/index';
-import { UploadFilled, Document, Loading, Download, Delete, QuestionFilled } from '@element-plus/icons-vue';
+import { UploadFilled, Document, Loading, Download, Delete, QuestionFilled, View } from '@element-plus/icons-vue';
 import { getToken } from '@/utils/auth';
 import ImagePreview from '@/components/ImagePreview/index.vue';
 import request from '@/utils/request';
+import IndicatorDataDialog from './IndicatorDataDialog.vue';
 import {
   addAssessmentApplication,
   updateAssessmentApplication,
@@ -397,6 +424,8 @@ interface XskhAssessmentApplicationApprovalForm {
   selfScoreList?: XskhAssessmentSelfScoreForm[];
   bonusApprovalList?: XskhAssessmentBonusApprovalForm[];
   teacherApprovalRemark?: string; // 新增:班主任审核备注
+  dataStartTime?: string;
+  dataEndTime?: string;
 }
 
 interface XskhAssessmentSelfScoreForm {
@@ -438,6 +467,8 @@ interface AssessmentScheduleOption {
   scheduleDescription: string;
   startTime: string;
   endTime: string;
+  dataStartTime: string;
+  dataEndTime: string;
   status: string;
   statusName: string;
 }
@@ -455,10 +486,17 @@ declare global {
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 
 const assessmentApplicationFormRef = ref();
+const indicatorDataDialogRef = ref();
 
 // 添加页面加载状态
 const pageLoading = ref(false);
 
+// 当前指标数据
+const currentIndicatorData = reactive({
+  indicatorId: undefined as string | number | undefined,
+  indicatorName: ''
+});
+
 const dialog = reactive({
   visible: false,
   title: ''
@@ -506,7 +544,9 @@ const initFormData: XskhAssessmentApplicationApprovalForm = {
   selfRemark: undefined,
   selfScoreList: [],
   bonusApprovalList: [],
-  teacherApprovalRemark: undefined // 初始化班主任审核备注
+  teacherApprovalRemark: undefined, // 初始化班主任审核备注
+  dataStartTime: undefined,
+  dataEndTime: undefined
 };
 
 const data = reactive({
@@ -999,6 +1039,7 @@ const openDialog = async (id?: string | number, title?: string, schedule?: Asses
   dialog.visible = true;
   dialog.title = title || '提交考核申请';
 
+  console.log('schedule:', schedule.dataStartTime, schedule.dataEndTime);
   // 重置表单
   resetFormData();
 
@@ -1008,6 +1049,12 @@ const openDialog = async (id?: string | number, title?: string, schedule?: Asses
     form.value.scheduleName = schedule.scheduleName;
     form.value.startTime = schedule.startTime;
     form.value.endTime = schedule.endTime;
+    // 设置数据统计时间范围(用于指标数据查询)
+    form.value.dataStartTime = schedule.dataStartTime;
+    form.value.dataEndTime = schedule.dataEndTime;
+
+    console.log('form.value.dataStartTime:', form.value.dataStartTime);
+    console.log('form.value.dataEndTime:', form.value.dataEndTime);
 
     // 获取当前登录用户的学生信息
     await getCurrentUserStudentInfo();
@@ -1025,6 +1072,14 @@ const openDialog = async (id?: string | number, title?: string, schedule?: Asses
         // 完整回显申请数据
         Object.assign(form.value, res.data);
 
+        // 重新设置时间字段,确保指标数据查询的时间范围正确
+        if (schedule) {
+          form.value.dataStartTime = schedule.dataStartTime;
+          form.value.dataEndTime = schedule.dataEndTime;
+          console.log('重新设置时间字段 - dataStartTime:', form.value.dataStartTime);
+          console.log('重新设置时间字段 - dataEndTime:', form.value.dataEndTime);
+        }
+
         // 确保自评得分列表正确回显
         if (res.data.selfScoreList && res.data.selfScoreList.length > 0) {
           form.value.selfScoreList = res.data.selfScoreList.map((item: any) => ({
@@ -1082,6 +1137,14 @@ const openDialog = async (id?: string | number, title?: string, schedule?: Asses
           // 完整回显申请数据
           Object.assign(form.value, existingApplication.data);
 
+          // 重新设置时间字段,确保指标数据查询的时间范围正确
+          if (schedule) {
+            form.value.dataStartTime = schedule.dataStartTime;
+            form.value.dataEndTime = schedule.dataEndTime;
+            console.log('重新设置时间字段 - dataStartTime:', form.value.dataStartTime);
+            console.log('重新设置时间字段 - dataEndTime:', form.value.dataEndTime);
+          }
+
           // 确保自评得分列表正确回显
           if (existingApplication.data.selfScoreList && existingApplication.data.selfScoreList.length > 0) {
             form.value.selfScoreList = existingApplication.data.selfScoreList.map((item: any) => ({
@@ -1135,6 +1198,9 @@ const openDialog = async (id?: string | number, title?: string, schedule?: Asses
             form.value.scheduleName = schedule.scheduleName;
             form.value.startTime = schedule.startTime;
             form.value.endTime = schedule.endTime;
+            // 重新设置数据统计时间范围(用于指标数据查询)
+            form.value.dataStartTime = schedule.dataStartTime;
+            form.value.dataEndTime = schedule.dataEndTime;
             // 重新获取学生信息
             await getCurrentUserStudentInfo();
           }
@@ -1344,6 +1410,40 @@ const getStatusText = (status: string) => {
   return '未知状态';
 };
 
+/** 查看指标数据 */
+const handleViewIndicatorData = (row: XskhAssessmentSelfScoreForm) => {
+  console.log('点击查看指标数据:', {
+    indicatorId: row.indicatorId,
+    indicatorName: row.indicatorName,
+    currentIndicatorId: currentIndicatorData.indicatorId,
+    dataStartTime: form.value.dataStartTime,
+    dataEndTime: form.value.dataEndTime
+  });
+
+  // 直接设置新的指标数据
+  currentIndicatorData.indicatorId = row.indicatorId;
+  currentIndicatorData.indicatorName = row.indicatorName || '';
+
+  console.log('设置新的指标数据:', {
+    indicatorId: currentIndicatorData.indicatorId,
+    indicatorName: currentIndicatorData.indicatorName,
+    dataStartTime: form.value.dataStartTime,
+    dataEndTime: form.value.dataEndTime
+  });
+
+  // 使用nextTick确保DOM更新后再打开弹窗
+  nextTick(() => {
+    // 再次确认数据已更新
+    console.log('准备打开弹窗,当前指标数据:', {
+      indicatorId: currentIndicatorData.indicatorId,
+      indicatorName: currentIndicatorData.indicatorName,
+      dataStartTime: form.value.dataStartTime,
+      dataEndTime: form.value.dataEndTime
+    });
+    indicatorDataDialogRef.value?.openDialog();
+  });
+};
+
 defineExpose({
   openDialog
 });
@@ -1731,7 +1831,7 @@ defineExpose({
   color: #adb5bd !important;
 }
 
-/* 查看模式下禁用表单内的按钮,但保留下载按钮和取消按钮 */
+/* 查看模式下禁用表单内的按钮,但保留下载按钮、取消按钮和指标数据查看按钮 */
 .view-mode .el-form .el-button {
   pointer-events: none;
   opacity: 0.6;
@@ -1743,6 +1843,15 @@ defineExpose({
   opacity: 1;
 }
 
+/* 查看模式下保留指标数据查看按钮的点击功能 */
+.view-mode .el-form .el-button.indicator-data-btn {
+  pointer-events: auto !important;
+  opacity: 1 !important;
+  cursor: pointer !important;
+  z-index: 10 !important;
+  position: relative !important;
+}
+
 /* 查看模式下禁用表格中的操作 */
 .view-mode .el-table .el-input,
 .view-mode .el-table .el-textarea {
@@ -1932,4 +2041,29 @@ defineExpose({
 .header-icon:hover {
   color: #409eff;
 }
+
+/* 指标名称单元格样式 */
+.indicator-name-cell {
+  display: flex;
+  align-items: center;
+  gap: 6px;
+}
+
+.indicator-name-cell span {
+  flex: 1;
+  font-size: inherit;
+}
+
+.indicator-data-btn {
+  flex-shrink: 0;
+  margin-left: 4px;
+  transform: scale(0.7);
+  opacity: 0.7;
+}
+
+.indicator-data-btn:hover {
+  transform: scale(0.8);
+  opacity: 1;
+  transition: all 0.2s ease;
+}
 </style>

+ 269 - 0
web/src/views/xskh/assessmentApplication/IndicatorDataDialog.vue

@@ -0,0 +1,269 @@
+<template>
+  <el-dialog :title="`${indicatorName} - 学生数据详情`" v-model="dialogVisible" width="1000px" append-to-body destroy-on-close>
+    <div v-loading="loading" element-loading-text="正在加载数据...">
+      <!-- 违纪处分记录区域 -->
+      <el-card class="mb-4" shadow="never">
+        <template #header>
+          <div class="card-header">
+            <span>违纪处分记录</span>
+            <el-tag type="danger" size="small">{{ disciplineRecords.length }} 条记录</el-tag>
+          </div>
+        </template>
+        <el-table :data="disciplineRecords" border style="width: 100%" v-if="disciplineRecords.length > 0">
+          <el-table-column label="违纪日期" prop="disciplineDate" width="120">
+            <template #default="scope">
+              {{ formatDate(scope.row.disciplineDate) }}
+            </template>
+          </el-table-column>
+          <el-table-column label="违纪类型" prop="disciplineTypeName" width="120" />
+          <el-table-column label="违纪原因" prop="disciplineReason" min-width="200" show-overflow-tooltip />
+          <el-table-column label="违纪内容" prop="disciplineContent" min-width="200" show-overflow-tooltip />
+          <el-table-column label="扣分分值" prop="scoreDeduction" width="100">
+            <template #default="scope">
+              <el-tag type="danger" size="small">-{{ scope.row.scoreDeduction || 0 }}</el-tag>
+            </template>
+          </el-table-column>
+        </el-table>
+        <el-empty v-else description="暂无违纪处分记录" />
+      </el-card>
+
+      <!-- 奖励记录区域 -->
+      <el-card shadow="never">
+        <template #header>
+          <div class="card-header">
+            <span>奖励记录</span>
+            <el-tag type="success" size="small">{{ rewardRecords.length }} 条记录</el-tag>
+          </div>
+        </template>
+        <el-table :data="rewardRecords" border style="width: 100%" v-if="rewardRecords.length > 0">
+          <el-table-column label="奖励日期" prop="rewardDate" width="120">
+            <template #default="scope">
+              {{ formatDate(scope.row.rewardDate) }}
+            </template>
+          </el-table-column>
+          <el-table-column label="奖励类型" prop="rewardTypeName" width="120" />
+          <el-table-column label="奖励内容" prop="rewardContent" min-width="200" show-overflow-tooltip />
+          <el-table-column label="加分分值" prop="scoreAddition" width="100">
+            <template #default="scope">
+              <el-tag type="success" size="small">+{{ scope.row.scoreAddition || 0 }}</el-tag>
+            </template>
+          </el-table-column>
+        </el-table>
+        <el-empty v-else description="暂无奖励记录" />
+      </el-card>
+    </div>
+  </el-dialog>
+</template>
+
+<script setup name="IndicatorDataDialog" lang="ts">
+import { ref, reactive, toRefs, watch } from 'vue';
+import ElMessage from 'element-plus/es/components/message/index';
+import request from '@/utils/request';
+
+// 类型定义
+interface DisciplineRecord {
+  id: string | number;
+  disciplineDate: string;
+  disciplineTypeName: string;
+  disciplineReason: string;
+  disciplineContent: string;
+  scoreDeduction: number;
+}
+
+interface RewardRecord {
+  id: string | number;
+  rewardDate: string;
+  rewardTypeName: string;
+  rewardContent: string;
+  scoreAddition: number;
+}
+
+interface IndicatorDataDialogProps {
+  indicatorId: string | number;
+  indicatorName: string;
+  studentId: string | number;
+  scheduleId: string | number;
+  dataStartTime: string; // 数据统计开始时间
+  dataEndTime: string; // 数据统计结束时间
+}
+
+const props = defineProps<IndicatorDataDialogProps>();
+
+const dialogVisible = ref(false);
+const loading = ref(false);
+
+const data = reactive({
+  disciplineRecords: [] as DisciplineRecord[],
+  rewardRecords: [] as RewardRecord[]
+});
+
+const { disciplineRecords, rewardRecords } = toRefs(data);
+
+// 监听props变化,当indicatorId变化时重新加载数据
+watch(
+  () => props.indicatorId,
+  (newIndicatorId, oldIndicatorId) => {
+    // 只有当弹窗可见且indicatorId真正发生变化时才重新加载
+    if (dialogVisible.value && newIndicatorId !== oldIndicatorId && newIndicatorId) {
+      console.log('indicatorId变化,重新加载数据:', { old: oldIndicatorId, new: newIndicatorId });
+      loadData();
+    }
+  },
+  { immediate: false }
+);
+
+// 格式化日期
+const formatDate = (dateStr: string) => {
+  if (!dateStr) return '-';
+  return new Date(dateStr).toLocaleDateString('zh-CN');
+};
+
+// 打开弹窗
+const openDialog = async () => {
+  dialogVisible.value = true;
+  // 强制刷新数据,确保使用最新的props值
+  await forceRefreshData();
+};
+
+// 强制刷新数据
+const forceRefreshData = async () => {
+  // 清空之前的数据
+  data.disciplineRecords = [];
+  data.rewardRecords = [];
+
+  // 确保使用最新的props值
+  await loadData();
+};
+
+// 加载数据
+const loadData = async () => {
+  // 如果弹窗未显示或没有indicatorId,则不加载数据
+  if (!dialogVisible.value || !props.indicatorId) {
+    console.log('弹窗未显示或无indicatorId,跳过数据加载');
+    return;
+  }
+
+  loading.value = true;
+  try {
+    console.log('开始加载指标数据,indicatorId:', props.indicatorId);
+
+    // 获取指标关联的违纪处分类型和奖励类型
+    const indicatorTypesResponse = await request({
+      url: `/disciplineRecord/disciplineRecord/getIndicatorTypes/${props.indicatorId}`,
+      method: 'get'
+    });
+
+    if (indicatorTypesResponse.code === 200 && indicatorTypesResponse.data) {
+      // 修复字段名映射:后端返回下划线格式,前端使用驼峰格式
+      const disciplineTypeIds = indicatorTypesResponse.data.discipline_type_ids || indicatorTypesResponse.data.disciplineTypeIds;
+      const rewardTypeIds = indicatorTypesResponse.data.reward_type_ids || indicatorTypesResponse.data.rewardTypeIds;
+
+      // 并行加载违纪处分记录和奖励记录
+      await Promise.all([loadDisciplineRecords(disciplineTypeIds), loadRewardRecords(rewardTypeIds)]);
+    } else {
+      ElMessage.warning('获取指标类型信息失败');
+    }
+  } catch (error) {
+    console.error('加载数据失败:', error);
+    ElMessage.error('加载数据失败,请稍后重试');
+  } finally {
+    loading.value = false;
+  }
+};
+
+// 加载违纪处分记录
+const loadDisciplineRecords = async (disciplineTypeIds: string) => {
+  if (!disciplineTypeIds) {
+    data.disciplineRecords = [];
+    return;
+  }
+
+  console.log('加载违纪处分记录,props:', props);
+  console.log('加载违纪处分记录,disciplineTypeIds:', disciplineTypeIds);
+  console.log('加载违纪处分记录,dataStartTime:', props.dataStartTime);
+  console.log('加载违纪处分记录,dataEndTime:', props.dataEndTime);
+  console.log('加载违纪处分记录,studentId:', props.studentId);
+
+  try {
+    const response = await request({
+      url: '/disciplineRecord/disciplineRecord/getStudentDisciplineRecords',
+      method: 'get',
+      params: {
+        studentId: props.studentId,
+        disciplineTypeIds: disciplineTypeIds,
+        startTime: props.dataStartTime,
+        endTime: props.dataEndTime,
+        status: 1 // 只查询状态为1的记录
+      }
+    });
+
+    if (response.code === 200) {
+      data.disciplineRecords = response.data || [];
+    } else {
+      ElMessage.warning('获取违纪处分记录失败');
+      data.disciplineRecords = [];
+    }
+  } catch (error) {
+    console.error('获取违纪处分记录失败:', error);
+    data.disciplineRecords = [];
+  }
+};
+
+// 加载奖励记录
+const loadRewardRecords = async (rewardTypeIds: string) => {
+  if (!rewardTypeIds) {
+    data.rewardRecords = [];
+    return;
+  }
+
+  try {
+    const response = await request({
+      url: '/rewardRecord/rewardRecord/getStudentRewardRecords',
+      method: 'get',
+      params: {
+        studentId: props.studentId,
+        rewardTypeIds: rewardTypeIds,
+        startTime: props.dataStartTime,
+        endTime: props.dataEndTime,
+        status: 1 // 只查询状态为1的记录
+      }
+    });
+
+    if (response.code === 200) {
+      data.rewardRecords = response.data || [];
+    } else {
+      ElMessage.warning('获取奖励记录失败');
+      data.rewardRecords = [];
+    }
+  } catch (error) {
+    console.error('获取奖励记录失败:', error);
+    data.rewardRecords = [];
+  }
+};
+
+// 关闭弹窗
+const closeDialog = () => {
+  dialogVisible.value = false;
+  // 清空数据
+  data.disciplineRecords = [];
+  data.rewardRecords = [];
+};
+
+defineExpose({
+  openDialog,
+  closeDialog,
+  forceRefreshData
+});
+</script>
+
+<style scoped>
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.mb-4 {
+  margin-bottom: 16px;
+}
+</style>