新增报到机:实现终端扫码报到核验与受控课堂打卡模拟

This commit is contained in:
wangzhibiao committed 2026-10-09 20:04:52 +08:00
1 parent b1d5a999ca
commit cecf11790e
16 files changed
+2571 -7

No files matched your search

@@ -85,6 +85,9 @@ public class AttendanceController extends BaseController
return success(checkin);
}
@Autowired(required = false)
private com.ruoyi.train.service.ReportTerminalService reportTerminalService;
/**
* 查询课次学员考勤名册 (纯只读,供培训管理员点名签到)。
*/
@@ -94,4 +97,19 @@ public class AttendanceController extends BaseController
{
return success(attendanceAppService.getLessonRoster(lessonId));
}
/**
* 模拟电子设备课堂打卡 (P1 Mock 考勤接入)。
*/
@PreAuthorize("@ss.hasPermi('train:attendance:checkin')")
@Log(title = "模拟设备课堂打卡", businessType = BusinessType.INSERT)
@PostMapping("/mock-swipe")
public AjaxResult mockSwipe(@Validated @RequestBody com.ruoyi.train.domain.dto.MockAttendanceDTO dto)
{
if (reportTerminalService == null)
{
throw new com.ruoyi.common.exception.ServiceException("模拟考勤服务不可用");
}
return success(reportTerminalService.mockDeviceAttendance(dto, SecurityUtils.getUsername()));
}
}
@@ -0,0 +1,77 @@
package com.ruoyi.web.controller.train;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.train.domain.dto.MockAttendanceDTO;
import com.ruoyi.train.domain.dto.ReportTerminalConfirmDTO;
import com.ruoyi.train.domain.vo.MockAttendanceResultVO;
import com.ruoyi.train.domain.vo.ReportTerminalPreviewVO;
import com.ruoyi.train.service.ReportTerminalService;
/**
* 模拟报到机与设备考勤接入 Controller (P0/P1 MVP v3)。
* <p>
* 仅供内部授权测试与模拟环境使用,严格要求登录鉴权 (@ss.hasPermi)。
*
* @author ruoyi
*/
@RestController
@RequestMapping("/train/report-terminal")
public class TrainReportTerminalController extends BaseController
{
private final ReportTerminalService reportTerminalService;
@Autowired
public TrainReportTerminalController(ReportTerminalService reportTerminalService)
{
this.reportTerminalService = reportTerminalService;
}
/**
* 报到机扫码查询学员报到信息 (P0)。
*/
@PreAuthorize("@ss.hasPermi('train:report:confirm')")
@GetMapping("/lookup")
public AjaxResult lookup(@RequestParam("studentId") String studentId,
@RequestParam(value = "planId", required = false) String planId)
{
ReportTerminalPreviewVO preview = reportTerminalService.lookupTerminalReport(studentId, planId);
return success(preview);
}
/**
* 报到机核对后一键确认报到 (P0)。
*/
@PreAuthorize("@ss.hasPermi('train:report:confirm')")
@Log(title = "报到机确认报到", businessType = BusinessType.UPDATE)
@PostMapping("/confirm")
public AjaxResult confirm(@RequestBody ReportTerminalConfirmDTO dto)
{
ReportTerminalPreviewVO result = reportTerminalService.confirmTerminalReport(dto, SecurityUtils.getUsername());
return success(result);
}
/**
* 模拟课堂设备打卡 (P1 Mock 考勤接入)。
*/
@PreAuthorize("@ss.hasPermi('train:attendance:checkin')")
@Log(title = "模拟设备课堂打卡", businessType = BusinessType.INSERT)
@PostMapping("/mock-attendance")
public AjaxResult mockAttendance(@Validated @RequestBody MockAttendanceDTO dto)
{
MockAttendanceResultVO result = reportTerminalService.mockDeviceAttendance(dto, SecurityUtils.getUsername());
return success(result);
}
}
@@ -141,3 +141,11 @@ xss:
excludes: /system/notice
# 匹配链接
urlPatterns: /system/*,/monitor/*,/tool/*
# 培训业务配置
train:
mock:
device:
# 模拟设备打卡接口开关 (仅在测试/沙箱环境开启)
enabled: true
@@ -0,0 +1,67 @@
package com.ruoyi.web.controller.train;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.lang.reflect.Method;
import org.junit.Test;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import com.ruoyi.train.domain.dto.MockAttendanceDTO;
import com.ruoyi.train.domain.dto.ReportTerminalConfirmDTO;
/**
* 报到机与设备考勤 Controller 契约与权限注解测试。
*
* @author ruoyi
*/
public class ReportTerminalControllerTest
{
@Test
public void testTerminalControllerContract() throws Exception
{
// 1. 报到机查询接口契约
Method lookupMethod = TrainReportTerminalController.class.getMethod("lookup", String.class, String.class);
assertNotNull(lookupMethod);
GetMapping getMapping = lookupMethod.getAnnotation(GetMapping.class);
assertNotNull(getMapping);
assertEquals("/lookup", getMapping.value()[0]);
PreAuthorize lookupAuth = lookupMethod.getAnnotation(PreAuthorize.class);
assertNotNull(lookupAuth);
assertEquals("@ss.hasPermi('train:report:confirm')", lookupAuth.value());
// 2. 报到机确认接口契约
Method confirmMethod = TrainReportTerminalController.class.getMethod("confirm", ReportTerminalConfirmDTO.class);
assertNotNull(confirmMethod);
PostMapping postMapping = confirmMethod.getAnnotation(PostMapping.class);
assertNotNull(postMapping);
assertEquals("/confirm", postMapping.value()[0]);
PreAuthorize confirmAuth = confirmMethod.getAnnotation(PreAuthorize.class);
assertNotNull(confirmAuth);
assertEquals("@ss.hasPermi('train:report:confirm')", confirmAuth.value());
// 3. 模拟打卡接口契约
Method mockAttendanceMethod = TrainReportTerminalController.class.getMethod("mockAttendance", MockAttendanceDTO.class);
assertNotNull(mockAttendanceMethod);
PostMapping postMock = mockAttendanceMethod.getAnnotation(PostMapping.class);
assertNotNull(postMock);
assertEquals("/mock-attendance", postMock.value()[0]);
PreAuthorize mockAuth = mockAttendanceMethod.getAnnotation(PreAuthorize.class);
assertNotNull(mockAuth);
assertEquals("@ss.hasPermi('train:attendance:checkin')", mockAuth.value());
}
@Test
public void testAttendanceControllerMockSwipeContract() throws Exception
{
Method mockSwipeMethod = AttendanceController.class.getMethod("mockSwipe", MockAttendanceDTO.class);
assertNotNull(mockSwipeMethod);
PostMapping postMapping = mockSwipeMethod.getAnnotation(PostMapping.class);
assertNotNull(postMapping);
assertEquals("/mock-swipe", postMapping.value()[0]);
PreAuthorize swipeAuth = mockSwipeMethod.getAnnotation(PreAuthorize.class);
assertNotNull(swipeAuth);
assertEquals("@ss.hasPermi('train:attendance:checkin')", swipeAuth.value());
}
}