|
|
@@ -1,9 +1,18 @@
|
|
|
package com.fs.doctor.service.impl;
|
|
|
|
|
|
import java.time.LocalDateTime;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
+import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import com.fs.common.core.redis.RedisCache;
|
|
|
+import com.fs.doctor.vo.DoctorLoginLogVO;
|
|
|
+import com.fs.his.domain.FsDoctor;
|
|
|
+import com.fs.his.mapper.FsDoctorMapper;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import com.fs.doctor.mapper.FsDoctorOnlineMapper;
|
|
|
@@ -16,12 +25,28 @@ import com.fs.doctor.service.IFsDoctorOnlineService;
|
|
|
* @author fs
|
|
|
* @date 2025-12-12
|
|
|
*/
|
|
|
+@Slf4j
|
|
|
@Service
|
|
|
public class FsDoctorOnlineServiceImpl extends ServiceImpl<FsDoctorOnlineMapper, FsDoctorOnline> implements IFsDoctorOnlineService {
|
|
|
|
|
|
@Autowired
|
|
|
private FsDoctorOnlineMapper fsDoctorOnlineMapper;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private FsDoctorMapper fsDoctorMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RedisCache redisCache;
|
|
|
+
|
|
|
+ // 注入 ObjectMapper 用于 JSON 序列化/反序列化
|
|
|
+ @Autowired
|
|
|
+ private ObjectMapper objectMapper;
|
|
|
+
|
|
|
+ /** 医生登录key*/
|
|
|
+ private static final String LOGIN_LOG_REDIS_KEY_PREFIX = "doctor:login:log:";
|
|
|
+ /** key的有效时长*/
|
|
|
+ private static final long REDIS_EXPIRE_HOURS = 48;
|
|
|
+
|
|
|
/**
|
|
|
* 查询医生在线状态
|
|
|
*
|
|
|
@@ -94,7 +119,13 @@ public class FsDoctorOnlineServiceImpl extends ServiceImpl<FsDoctorOnlineMapper,
|
|
|
record.setDoctorId(doctorId);
|
|
|
record.setLastHeartbeat(LocalDateTime.now());
|
|
|
record.setIsOnline(1);
|
|
|
- return fsDoctorOnlineMapper.upsertHeartbeat(record);
|
|
|
+ int result = fsDoctorOnlineMapper.upsertHeartbeat(record);
|
|
|
+ if (result > 0){
|
|
|
+ FsDoctor doctor = fsDoctorMapper.selectFsDoctorByDoctorId(doctorId);
|
|
|
+ //这里用redis记录登录时间(医生名称、医生id、登入、时间)
|
|
|
+ recordUserAction(doctorId, doctor.getDoctorName(), "login", LocalDateTime.now());
|
|
|
+ }
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -103,7 +134,73 @@ public class FsDoctorOnlineServiceImpl extends ServiceImpl<FsDoctorOnlineMapper,
|
|
|
record.setDoctorId(doctorId);
|
|
|
record.setLastHeartbeat(LocalDateTime.now()); // 正常登出,更新为当前时间
|
|
|
record.setIsOnline(0);
|
|
|
- return fsDoctorOnlineMapper.upsertHeartbeat(record);
|
|
|
+ int result = fsDoctorOnlineMapper.upsertHeartbeat(record);
|
|
|
+ if (result > 0){
|
|
|
+ //这里用redis记录登出时间((医生名称、医生id、登出、时间))
|
|
|
+ FsDoctor doctor = fsDoctorMapper.selectFsDoctorByDoctorId(doctorId);
|
|
|
+ recordUserAction(doctorId, doctor.getDoctorName(), "logout", LocalDateTime.now());
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 记录用户登录或登出事件到Redis
|
|
|
+ * @param doctorId 医生ID
|
|
|
+ * @param doctorName 医生姓名
|
|
|
+ * @param action 动作 ("login" or "logout")
|
|
|
+ * @param timestamp 时间戳
|
|
|
+ */
|
|
|
+ private void recordUserAction(Long doctorId, String doctorName, String action, LocalDateTime timestamp) {
|
|
|
+ try {
|
|
|
+ // 构建要存储的对象
|
|
|
+ DoctorLoginLogVO logVO = new DoctorLoginLogVO(doctorId, doctorName, action, timestamp);
|
|
|
+
|
|
|
+ // 序列化为JSON字符串
|
|
|
+ String logJsonStr = objectMapper.writeValueAsString(logVO);
|
|
|
+
|
|
|
+ // 构建key (按天分组)
|
|
|
+ String dateStr = timestamp.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
|
|
+ String redisKey = LOGIN_LOG_REDIS_KEY_PREFIX + dateStr + ":" + doctorId;
|
|
|
+
|
|
|
+ // 将记录推送到Redis的List中
|
|
|
+ redisCache.setVoice(redisKey, logJsonStr);
|
|
|
+
|
|
|
+ // 设置过期时间(48小时)
|
|
|
+ redisCache.expire(redisKey, REDIS_EXPIRE_HOURS, TimeUnit.HOURS);
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 记录错误日志,但不影响主流程
|
|
|
+ log.error("Failed to record user action to Redis. doctorId: {}, action: {}", doctorId, action, e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从Redis查询指定用户某天的登录登出记录
|
|
|
+ * @param doctorId 医生ID
|
|
|
+ * @param date 日期 (格式: "yyyy-MM-dd")
|
|
|
+ * @return 记录列表
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public List<DoctorLoginLogVO> getUserLoginLogByDay(Long doctorId, String date) {
|
|
|
+ try {
|
|
|
+ String redisKey = LOGIN_LOG_REDIS_KEY_PREFIX + date + ":" + doctorId;
|
|
|
+ List<String> jsonLogList = (List<String>) redisCache.getVoiceAllList(redisKey);
|
|
|
+
|
|
|
+ if (jsonLogList == null || jsonLogList.isEmpty()) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ List<DoctorLoginLogVO> logVOList = new ArrayList<>();
|
|
|
+ for (String jsonStr : jsonLogList) {
|
|
|
+ DoctorLoginLogVO logVO = objectMapper.readValue(jsonStr, DoctorLoginLogVO.class);
|
|
|
+ logVOList.add(logVO);
|
|
|
+ }
|
|
|
+ return logVOList;
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("Failed to query user login log from Redis. doctorId: {}, date: {}", doctorId, date, e);
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@Override
|