diff --git a/RuoYi-Vue/ruoyi-admin/src/main/java/com/ruoyi/web/controller/train/TrainElectronicBoardController.java b/RuoYi-Vue/ruoyi-admin/src/main/java/com/ruoyi/web/controller/train/TrainElectronicBoardController.java
index 4bdb27b01..91ef523a6 100644
--- a/RuoYi-Vue/ruoyi-admin/src/main/java/com/ruoyi/web/controller/train/TrainElectronicBoardController.java
+++ b/RuoYi-Vue/ruoyi-admin/src/main/java/com/ruoyi/web/controller/train/TrainElectronicBoardController.java
@@ -77,6 +77,7 @@ public class TrainElectronicBoardController extends BaseController
@PostMapping
public AjaxResult add(@RequestBody TrainElectronicBoard trainElectronicBoard)
{
+ trainElectronicBoard.setCreateBy(getUsername());
return toAjax(trainElectronicBoardService.insertTrainElectronicBoard(trainElectronicBoard));
}
@@ -88,6 +89,7 @@ public class TrainElectronicBoardController extends BaseController
@PutMapping
public AjaxResult edit(@RequestBody TrainElectronicBoard trainElectronicBoard)
{
+ trainElectronicBoard.setUpdateBy(getUsername());
return toAjax(trainElectronicBoardService.updateTrainElectronicBoard(trainElectronicBoard));
}
@@ -99,6 +101,6 @@ public class TrainElectronicBoardController extends BaseController
@DeleteMapping("/{boardIds}")
public AjaxResult remove(@PathVariable String[] boardIds)
{
- return toAjax(trainElectronicBoardService.deleteTrainElectronicBoardByBoardIds(boardIds));
+ return toAjax(trainElectronicBoardService.deleteTrainElectronicBoardByBoardIds(boardIds, getUsername()));
}
}
diff --git a/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/domain/TrainElectronicBoard.java b/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/domain/TrainElectronicBoard.java
index 6f0105eaa..46951a713 100644
--- a/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/domain/TrainElectronicBoard.java
+++ b/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/domain/TrainElectronicBoard.java
@@ -24,168 +24,154 @@ public class TrainElectronicBoard extends BaseEntity
@Excel(name = "设备硬件序列号")
private String boardSn;
- /** 绑定教室ID train_classroom_info.class_room_id */
- @Excel(name = "绑定教室ID train_classroom_info.class_room_id")
- private String bindClassroomId;
+ /** 设备名称 */
+ @Excel(name = "设备名称")
+ private String boardName;
- /** 绑定开班计划 train_class_plan.plan_id */
- @Excel(name = "绑定开班计划 train_class_plan.plan_id")
- private String bindPlanId;
+ /** 绑定教室ID */
+ @Excel(name = "绑定教室ID")
+ private String bindClassroomId;
/** 设备IP地址 */
@Excel(name = "设备IP地址")
private String boardIp;
- /** 电子班牌显示内容 */
- @Excel(name = "电子班牌显示内容")
- private String boardContent;
+ /** 设备通讯/流媒体端点 */
+ @Excel(name = "设备端点")
+ private String apiEndpoint;
- /** 0 离线 1 在线正常 */
- @Excel(name = "0 离线 1 在线正常")
- private Integer boardPlaymode;
-
- /** 支持签到:人脸,二维码 */
- @Excel(name = "支持签到:人脸,二维码")
+ /** 支持签到:CARD,FACE,QR */
+ @Excel(name = "支持签到方式")
private String supportCheckinType;
/** 0 离线 1 在线正常 */
- @Excel(name = "0 离线 1 在线正常")
+ @Excel(name = "设备状态", readConverterExp = "0=离线,1=在线")
private Integer boardStatus;
/** 最后心跳时间 */
- @JsonFormat(pattern = "yyyy-MM-dd")
- @Excel(name = "最后心跳时间", width = 30, dateFormat = "yyyy-MM-dd")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @Excel(name = "最后心跳时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date lastHeartbeat;
- /** 创建管理员账号 */
- @Excel(name = "创建管理员账号")
- private String createUser;
+ /** 删除标志 (0代表存在 2代表删除) */
+ private String delFlag;
- public void setBoardId(String boardId)
+ public void setBoardId(String boardId)
{
this.boardId = boardId;
}
- public String getBoardId()
+ public String getBoardId()
{
return boardId;
}
- public void setBoardSn(String boardSn)
+ public void setBoardSn(String boardSn)
{
this.boardSn = boardSn;
}
- public String getBoardSn()
+ public String getBoardSn()
{
return boardSn;
}
- public void setBindClassroomId(String bindClassroomId)
+ public void setBoardName(String boardName)
+ {
+ this.boardName = boardName;
+ }
+
+ public String getBoardName()
+ {
+ return boardName;
+ }
+
+ public void setBindClassroomId(String bindClassroomId)
{
this.bindClassroomId = bindClassroomId;
}
- public String getBindClassroomId()
+ public String getBindClassroomId()
{
return bindClassroomId;
}
- public void setBindPlanId(String bindPlanId)
- {
- this.bindPlanId = bindPlanId;
- }
-
- public String getBindPlanId()
- {
- return bindPlanId;
- }
-
- public void setBoardIp(String boardIp)
+ public void setBoardIp(String boardIp)
{
this.boardIp = boardIp;
}
- public String getBoardIp()
+ public String getBoardIp()
{
return boardIp;
}
- public void setBoardContent(String boardContent)
+ public void setApiEndpoint(String apiEndpoint)
{
- this.boardContent = boardContent;
+ this.apiEndpoint = apiEndpoint;
}
- public String getBoardContent()
+ public String getApiEndpoint()
{
- return boardContent;
+ return apiEndpoint;
}
- public void setBoardPlaymode(Integer boardPlaymode)
- {
- this.boardPlaymode = boardPlaymode;
- }
-
- public Integer getBoardPlaymode()
- {
- return boardPlaymode;
- }
-
- public void setSupportCheckinType(String supportCheckinType)
+ public void setSupportCheckinType(String supportCheckinType)
{
this.supportCheckinType = supportCheckinType;
}
- public String getSupportCheckinType()
+ public String getSupportCheckinType()
{
return supportCheckinType;
}
- public void setBoardStatus(Integer boardStatus)
+ public void setBoardStatus(Integer boardStatus)
{
this.boardStatus = boardStatus;
}
- public Integer getBoardStatus()
+ public Integer getBoardStatus()
{
return boardStatus;
}
- public void setLastHeartbeat(Date lastHeartbeat)
+ public void setLastHeartbeat(Date lastHeartbeat)
{
this.lastHeartbeat = lastHeartbeat;
}
- public Date getLastHeartbeat()
+ public Date getLastHeartbeat()
{
return lastHeartbeat;
}
- public void setCreateUser(String createUser)
+ public void setDelFlag(String delFlag)
{
- this.createUser = createUser;
+ this.delFlag = delFlag;
}
- public String getCreateUser()
+ public String getDelFlag()
{
- return createUser;
+ return delFlag;
}
@Override
public String toString() {
- return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("boardId", getBoardId())
.append("boardSn", getBoardSn())
+ .append("boardName", getBoardName())
.append("bindClassroomId", getBindClassroomId())
- .append("bindPlanId", getBindPlanId())
.append("boardIp", getBoardIp())
- .append("boardContent", getBoardContent())
- .append("boardPlaymode", getBoardPlaymode())
+ .append("apiEndpoint", getApiEndpoint())
.append("supportCheckinType", getSupportCheckinType())
.append("boardStatus", getBoardStatus())
.append("lastHeartbeat", getLastHeartbeat())
- .append("createUser", getCreateUser())
+ .append("delFlag", getDelFlag())
+ .append("createBy", getCreateBy())
.append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
diff --git a/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/mapper/TrainElectronicBoardMapper.java b/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/mapper/TrainElectronicBoardMapper.java
index e6d81cad6..39ea4909b 100644
--- a/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/mapper/TrainElectronicBoardMapper.java
+++ b/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/mapper/TrainElectronicBoardMapper.java
@@ -1,6 +1,7 @@
package com.ruoyi.train.mapper;
import java.util.List;
+import org.apache.ibatis.annotations.Param;
import com.ruoyi.train.domain.TrainElectronicBoard;
/**
@@ -44,18 +45,20 @@ public interface TrainElectronicBoardMapper
public int updateTrainElectronicBoard(TrainElectronicBoard trainElectronicBoard);
/**
- * 删除电子班牌设备
+ * 逻辑删除电子班牌设备(补齐操作人)
*
* @param boardId 电子班牌设备主键
+ * @param updateBy 操作人账号
* @return 结果
*/
- public int deleteTrainElectronicBoardByBoardId(String boardId);
+ public int deleteTrainElectronicBoardByBoardId(@Param("boardId") String boardId, @Param("updateBy") String updateBy);
/**
- * 批量删除电子班牌设备
+ * 批量逻辑删除电子班牌设备(补齐操作人)
*
* @param boardIds 需要删除的数据主键集合
+ * @param updateBy 操作人账号
* @return 结果
*/
- public int deleteTrainElectronicBoardByBoardIds(String[] boardIds);
+ public int deleteTrainElectronicBoardByBoardIds(@Param("boardIds") String[] boardIds, @Param("updateBy") String updateBy);
}
diff --git a/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/service/ITrainElectronicBoardService.java b/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/service/ITrainElectronicBoardService.java
index 88831a524..e0e590b99 100644
--- a/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/service/ITrainElectronicBoardService.java
+++ b/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/service/ITrainElectronicBoardService.java
@@ -43,14 +43,32 @@ public interface ITrainElectronicBoardService
*/
public int updateTrainElectronicBoard(TrainElectronicBoard trainElectronicBoard);
+ /**
+ * 批量删除电子班牌设备(补齐操作人)
+ *
+ * @param boardIds 需要删除的电子班牌设备主键集合
+ * @param updateBy 操作人账号
+ * @return 结果
+ */
+ public int deleteTrainElectronicBoardByBoardIds(String[] boardIds, String updateBy);
+
/**
* 批量删除电子班牌设备
- *
+ *
* @param boardIds 需要删除的电子班牌设备主键集合
* @return 结果
*/
public int deleteTrainElectronicBoardByBoardIds(String[] boardIds);
+ /**
+ * 删除电子班牌设备信息(补齐操作人)
+ *
+ * @param boardId 电子班牌设备主键
+ * @param updateBy 操作人账号
+ * @return 结果
+ */
+ public int deleteTrainElectronicBoardByBoardId(String boardId, String updateBy);
+
/**
* 删除电子班牌设备信息
*
diff --git a/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/service/impl/TrainElectronicBoardServiceImpl.java b/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/service/impl/TrainElectronicBoardServiceImpl.java
index 5193819d4..cec787cae 100644
--- a/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/service/impl/TrainElectronicBoardServiceImpl.java
+++ b/RuoYi-Vue/ruoyi-train/src/main/java/com/ruoyi/train/service/impl/TrainElectronicBoardServiceImpl.java
@@ -2,6 +2,8 @@ package com.ruoyi.train.service.impl;
import java.util.List;
import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.uuid.IdUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.train.mapper.TrainElectronicBoardMapper;
@@ -53,6 +55,16 @@ public class TrainElectronicBoardServiceImpl implements ITrainElectronicBoardSer
@Override
public int insertTrainElectronicBoard(TrainElectronicBoard trainElectronicBoard)
{
+ if (StringUtils.isEmpty(trainElectronicBoard.getBoardId()))
+ {
+ trainElectronicBoard.setBoardId(IdUtils.fastSimpleUUID());
+ }
+ // 新建设备时显式初始化 boardStatus = 0 (离线)
+ trainElectronicBoard.setBoardStatus(0);
+ if (StringUtils.isEmpty(trainElectronicBoard.getDelFlag()))
+ {
+ trainElectronicBoard.setDelFlag("0");
+ }
trainElectronicBoard.setCreateTime(DateUtils.getNowDate());
return trainElectronicBoardMapper.insertTrainElectronicBoard(trainElectronicBoard);
}
@@ -66,20 +78,49 @@ public class TrainElectronicBoardServiceImpl implements ITrainElectronicBoardSer
@Override
public int updateTrainElectronicBoard(TrainElectronicBoard trainElectronicBoard)
{
+ // 设备运行状态与心跳写保护:普通管理员 edit 不允许修改 boardStatus 和 lastHeartbeat,保留数据库原值
+ trainElectronicBoard.setBoardStatus(null);
+ trainElectronicBoard.setLastHeartbeat(null);
trainElectronicBoard.setUpdateTime(DateUtils.getNowDate());
return trainElectronicBoardMapper.updateTrainElectronicBoard(trainElectronicBoard);
}
+ /**
+ * 批量删除电子班牌设备(记录操作人)
+ *
+ * @param boardIds 需要删除的电子班牌设备主键
+ * @param updateBy 操作人账号
+ * @return 结果
+ */
+ @Override
+ public int deleteTrainElectronicBoardByBoardIds(String[] boardIds, String updateBy)
+ {
+ return trainElectronicBoardMapper.deleteTrainElectronicBoardByBoardIds(boardIds, updateBy);
+ }
+
/**
* 批量删除电子班牌设备
- *
+ *
* @param boardIds 需要删除的电子班牌设备主键
* @return 结果
*/
@Override
public int deleteTrainElectronicBoardByBoardIds(String[] boardIds)
{
- return trainElectronicBoardMapper.deleteTrainElectronicBoardByBoardIds(boardIds);
+ return deleteTrainElectronicBoardByBoardIds(boardIds, "");
+ }
+
+ /**
+ * 删除电子班牌设备信息(记录操作人)
+ *
+ * @param boardId 电子班牌设备主键
+ * @param updateBy 操作人账号
+ * @return 结果
+ */
+ @Override
+ public int deleteTrainElectronicBoardByBoardId(String boardId, String updateBy)
+ {
+ return trainElectronicBoardMapper.deleteTrainElectronicBoardByBoardId(boardId, updateBy);
}
/**
@@ -91,6 +132,6 @@ public class TrainElectronicBoardServiceImpl implements ITrainElectronicBoardSer
@Override
public int deleteTrainElectronicBoardByBoardId(String boardId)
{
- return trainElectronicBoardMapper.deleteTrainElectronicBoardByBoardId(boardId);
+ return deleteTrainElectronicBoardByBoardId(boardId, "");
}
}
diff --git a/RuoYi-Vue/ruoyi-train/src/main/resources/mapper/train/TrainElectronicBoardMapper.xml b/RuoYi-Vue/ruoyi-train/src/main/resources/mapper/train/TrainElectronicBoardMapper.xml
index 163e4c3de..4ea245ab6 100644
--- a/RuoYi-Vue/ruoyi-train/src/main/resources/mapper/train/TrainElectronicBoardMapper.xml
+++ b/RuoYi-Vue/ruoyi-train/src/main/resources/mapper/train/TrainElectronicBoardMapper.xml
@@ -7,43 +7,40 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+
-
-
-
+
-
+
+
+
- select board_id, board_sn, bind_classroom_id, bind_plan_id, board_ip, board_content, board_playmode, support_checkin_type, board_status, last_heartbeat, create_user, create_time, update_time, remark from train_electronic_board
+ select board_id, board_sn, board_name, bind_classroom_id, board_ip, api_endpoint, support_checkin_type, board_status, last_heartbeat, del_flag, create_by, create_time, update_by, update_time, remark from train_electronic_board
@@ -51,33 +48,35 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
board_id,
board_sn,
+ board_name,
bind_classroom_id,
- bind_plan_id,
board_ip,
- board_content,
- board_playmode,
+ api_endpoint,
support_checkin_type,
board_status,
last_heartbeat,
- create_user,
- create_time,
- update_time,
+ del_flag,
+ create_by,
+ create_time,
+ update_by,
+ update_time,
remark,
#{boardId},
#{boardSn},
+ #{boardName},
#{bindClassroomId},
- #{bindPlanId},
#{boardIp},
- #{boardContent},
- #{boardPlaymode},
+ #{apiEndpoint},
#{supportCheckinType},
#{boardStatus},
#{lastHeartbeat},
- #{createUser},
- #{createTime},
- #{updateTime},
+ #{delFlag},
+ #{createBy},
+ clock_timestamp(),
+ #{updateBy},
+ clock_timestamp(),
#{remark},
@@ -86,30 +85,38 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
update train_electronic_board
board_sn = #{boardSn},
+ board_name = #{boardName},
bind_classroom_id = #{bindClassroomId},
- bind_plan_id = #{bindPlanId},
board_ip = #{boardIp},
- board_content = #{boardContent},
- board_playmode = #{boardPlaymode},
+ api_endpoint = #{apiEndpoint},
support_checkin_type = #{supportCheckinType},
board_status = #{boardStatus},
last_heartbeat = #{lastHeartbeat},
- create_user = #{createUser},
- create_time = #{createTime},
- update_time = #{updateTime},
+ del_flag = #{delFlag},
+ update_by = #{updateBy},
remark = #{remark},
+ update_time = clock_timestamp()
- where board_id = #{boardId}
+ where board_id = #{boardId} and del_flag = '0'
-
- delete from train_electronic_board where board_id = #{boardId}
-
+
+ update train_electronic_board
+ set del_flag = '2',
+ update_by = #{updateBy},
+ update_time = clock_timestamp()
+ where board_id = #{boardId} and del_flag = '0'
+
-
- delete from train_electronic_board where board_id in
-
+
+ update train_electronic_board
+ set del_flag = '2',
+ update_by = #{updateBy},
+ update_time = clock_timestamp()
+ where board_id in
+
#{boardId}
-
-
\ No newline at end of file
+ and del_flag = '0'
+
+
diff --git a/RuoYi-Vue/ruoyi-train/src/test/java/com/ruoyi/train/service/impl/TrainElectronicBoardServiceTest.java b/RuoYi-Vue/ruoyi-train/src/test/java/com/ruoyi/train/service/impl/TrainElectronicBoardServiceTest.java
new file mode 100644
index 000000000..3eaf5d3b6
--- /dev/null
+++ b/RuoYi-Vue/ruoyi-train/src/test/java/com/ruoyi/train/service/impl/TrainElectronicBoardServiceTest.java
@@ -0,0 +1,199 @@
+package com.ruoyi.train.service.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import com.ruoyi.train.domain.TrainElectronicBoard;
+import com.ruoyi.train.mapper.TrainElectronicBoardMapper;
+
+/**
+ * 电子班牌设备生命周期与生命周期只读写保护单元测试
+ *
+ * 验证:
+ * 1. 新增不传 boardId 自动生成唯一 UUID
+ * 2. 新增设备显式初始化 boardStatus = 0 (离线)
+ * 3. 修改设备时 boardStatus 与 lastHeartbeat 受到只读写保护 (清空为 null,保留 DB 原值)
+ * 4. 软删除记录操作人 updateBy 与状态标记
+ */
+public class TrainElectronicBoardServiceTest
+{
+ private TrainElectronicBoardServiceImpl boardService;
+ private MockBoardMapper mockMapper;
+
+ @Before
+ public void setUp() throws Exception
+ {
+ boardService = new TrainElectronicBoardServiceImpl();
+ mockMapper = new MockBoardMapper();
+ Field field = TrainElectronicBoardServiceImpl.class.getDeclaredField("trainElectronicBoardMapper");
+ field.setAccessible(true);
+ field.set(boardService, mockMapper);
+ }
+
+ @Test
+ public void testInsertBoardWithoutBoardIdGeneratesUUIDAndOfflineStatus()
+ {
+ TrainElectronicBoard board = new TrainElectronicBoard();
+ board.setBoardSn("SN-TEST-001");
+ board.setBoardName("1号阶梯教室班牌");
+ board.setBindClassroomId("ROOM-101");
+ board.setBoardIp("192.168.1.50");
+ board.setSupportCheckinType("CARD,FACE");
+ // 显式不设置 boardId,且尝试传入状态 1
+ board.setBoardStatus(1);
+
+ int rows = boardService.insertTrainElectronicBoard(board);
+ assertEquals(1, rows);
+
+ // 验证 boardId 闭环自动生成
+ assertNotNull("boardId 必须自动生成", board.getBoardId());
+ assertTrue("boardId 长度应符合 UUID 格式", board.getBoardId().length() >= 32);
+
+ // 验证新建设备必须显式初始化为 0 (离线)
+ assertEquals("新增班牌状态必须为离线(0)", Integer.valueOf(0), board.getBoardStatus());
+ assertEquals("delFlag 必须为存在状态 0", "0", board.getDelFlag());
+ assertNotNull("createTime 必须已注入", board.getCreateTime());
+
+ // 验证存储与回查
+ TrainElectronicBoard queried = boardService.selectTrainElectronicBoardByBoardId(board.getBoardId());
+ assertNotNull(queried);
+ assertEquals("SN-TEST-001", queried.getBoardSn());
+ }
+
+ @Test
+ public void testUpdateProtectsBoardStatusAndLastHeartbeat()
+ {
+ TrainElectronicBoard board = new TrainElectronicBoard();
+ board.setBoardSn("SN-TEST-002");
+ board.setBoardName("2号多媒体教室班牌");
+ boardService.insertTrainElectronicBoard(board);
+ String boardId = board.getBoardId();
+
+ // 模拟管理员尝试在修改中伪造心跳或篡改状态为在线
+ TrainElectronicBoard updateParam = new TrainElectronicBoard();
+ updateParam.setBoardId(boardId);
+ updateParam.setBoardName("2号多媒体教室班牌-已重命名");
+ updateParam.setBoardStatus(1); // 试图伪造在线
+ updateParam.setLastHeartbeat(new Date()); // 试图伪造心跳
+
+ boardService.updateTrainElectronicBoard(updateParam);
+
+ // 验证写保护:updateParam 的 boardStatus 与 lastHeartbeat 必须被清空,避免在 Mapper 中覆盖原值
+ assertNull("update 必须清除 boardStatus 传参实现写保护", updateParam.getBoardStatus());
+ assertNull("update 必须清除 lastHeartbeat 传参实现写保护", updateParam.getLastHeartbeat());
+ assertNotNull("updateTime 必须已注入", updateParam.getUpdateTime());
+ }
+
+ @Test
+ public void testDeleteUsesLogicalDeleteWithOperator()
+ {
+ TrainElectronicBoard board = new TrainElectronicBoard();
+ board.setBoardSn("SN-TEST-003");
+ board.setBoardName("3号会议室班牌");
+ boardService.insertTrainElectronicBoard(board);
+ String boardId = board.getBoardId();
+
+ int rows = boardService.deleteTrainElectronicBoardByBoardId(boardId, "adminUser");
+ assertEquals(1, rows);
+
+ // 模拟已标记 del_flag = '2',select 过滤
+ TrainElectronicBoard queried = boardService.selectTrainElectronicBoardByBoardId(boardId);
+ assertNull("已软删除的数据查询应返回 null", queried);
+
+ // 验证更新人已被记录
+ TrainElectronicBoard rawInStorage = mockMapper.storage.get(boardId);
+ assertNotNull(rawInStorage);
+ assertEquals("2", rawInStorage.getDelFlag());
+ assertEquals("adminUser", rawInStorage.getUpdateBy());
+ }
+
+ /**
+ * 内存 Mock Mapper
+ */
+ private static class MockBoardMapper implements TrainElectronicBoardMapper
+ {
+ private final Map storage = new HashMap<>();
+
+ @Override
+ public TrainElectronicBoard selectTrainElectronicBoardByBoardId(String boardId)
+ {
+ TrainElectronicBoard b = storage.get(boardId);
+ if (b != null && "0".equals(b.getDelFlag()))
+ {
+ return b;
+ }
+ return null;
+ }
+
+ @Override
+ public List selectTrainElectronicBoardList(TrainElectronicBoard trainElectronicBoard)
+ {
+ List list = new ArrayList<>();
+ for (TrainElectronicBoard b : storage.values())
+ {
+ if ("0".equals(b.getDelFlag()))
+ {
+ list.add(b);
+ }
+ }
+ return list;
+ }
+
+ @Override
+ public int insertTrainElectronicBoard(TrainElectronicBoard trainElectronicBoard)
+ {
+ storage.put(trainElectronicBoard.getBoardId(), trainElectronicBoard);
+ return 1;
+ }
+
+ @Override
+ public int updateTrainElectronicBoard(TrainElectronicBoard trainElectronicBoard)
+ {
+ TrainElectronicBoard exist = storage.get(trainElectronicBoard.getBoardId());
+ if (exist != null)
+ {
+ if (trainElectronicBoard.getBoardName() != null) exist.setBoardName(trainElectronicBoard.getBoardName());
+ if (trainElectronicBoard.getBoardSn() != null) exist.setBoardSn(trainElectronicBoard.getBoardSn());
+ // boardStatus 和 lastHeartbeat 若为 null 则保持原值
+ if (trainElectronicBoard.getBoardStatus() != null) exist.setBoardStatus(trainElectronicBoard.getBoardStatus());
+ if (trainElectronicBoard.getLastHeartbeat() != null) exist.setLastHeartbeat(trainElectronicBoard.getLastHeartbeat());
+ return 1;
+ }
+ return 0;
+ }
+
+ @Override
+ public int deleteTrainElectronicBoardByBoardId(String boardId, String updateBy)
+ {
+ TrainElectronicBoard exist = storage.get(boardId);
+ if (exist != null && "0".equals(exist.getDelFlag()))
+ {
+ exist.setDelFlag("2");
+ exist.setUpdateBy(updateBy);
+ return 1;
+ }
+ return 0;
+ }
+
+ @Override
+ public int deleteTrainElectronicBoardByBoardIds(String[] boardIds, String updateBy)
+ {
+ int c = 0;
+ for (String id : boardIds)
+ {
+ c += deleteTrainElectronicBoardByBoardId(id, updateBy);
+ }
+ return c;
+ }
+ }
+}
diff --git a/build_ui/src/views/train/board/index.vue b/build_ui/src/views/train/board/index.vue
index da2775542..71267b3ed 100644
--- a/build_ui/src/views/train/board/index.vue
+++ b/build_ui/src/views/train/board/index.vue
@@ -1,194 +1,307 @@
-
-
+
+
+
+
+
-
-
+
+ filterable
+ placeholder="请选择绑定教室"
+ >
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+ placeholder="请选择设备状态"
+ >
+
+
+
- 搜索
- 重置
+
+ 搜索
+
+
+ 重置
+
新增
+ >
+ 新增班牌
+
修改
+ >
+ 修改
+
删除
+ >
+ 删除
+
导出
+ >
+ 导出
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
- {{ parseTime(scope.row.lastHeartbeat, '{y}-{m}-{d}') }}
+ {{ classroomNameMap[scope.row.bindClassroomId] || scope.row.bindClassroomId || '—' }}
-
-
-
+
+
+ {{ scope.row.boardIp || '—' }}
+
+
+
+
+
+
+ {{ item }}
+
+
+ —
+
+
+
+
+
+ 在线
+
+
+ 离线
+
+
+
+
+
+ {{ parseTime(scope.row.lastHeartbeat, '{y}-{m}-{d} {h}:{i}:{s}') || '—' }}
+
+
+
+
修改
-
+ 修改
+
+ 删除
+ >
+ 删除
+
-
-
-
-
-
+
+
+
+
+
-
-
+
+
-
-
+
+
+
+
-
-
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
+
+
+ 刷卡签到
+ 人脸识别
+ 二维码打卡
+
-
+