|
|
@@ -1,14 +1,30 @@
|
|
|
package com.fs.watch.service.impl;
|
|
|
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.fasterxml.jackson.databind.JsonNode;
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import com.fs.aiChat.mapper.InterestAiChatSessionMapper;
|
|
|
+import com.fs.common.core.domain.R;
|
|
|
import com.fs.common.utils.DateUtils;
|
|
|
import com.fs.common.utils.StringUtils;
|
|
|
-import com.fs.watch.domain.WatchBasicInfo;
|
|
|
-import com.fs.watch.domain.WatchDeviceInfo;
|
|
|
-import com.fs.watch.domain.WatchHeartRateData;
|
|
|
-import com.fs.watch.domain.vo.AppFsUserHealthReportVo;
|
|
|
-import com.fs.watch.domain.vo.AppHealthReportVo;
|
|
|
-import com.fs.watch.domain.vo.GnssVo;
|
|
|
-import com.fs.watch.domain.vo.WatchSleepDataVo;
|
|
|
+import com.fs.fastgptApi.param.ChatParam;
|
|
|
+import com.fs.fastgptApi.result.ChatDetailTStreamFResult;
|
|
|
+import com.fs.fastgptApi.result.KnowledgeBaseResult;
|
|
|
+import com.fs.fastgptApi.service.ChatService;
|
|
|
+import com.fs.his.domain.FsThirdDeviceData;
|
|
|
+import com.fs.his.mapper.FsHealthPulseMapper;
|
|
|
+import com.fs.his.mapper.FsHealthSurfaceMapper;
|
|
|
+import com.fs.his.mapper.FsHealthTongueMapper;
|
|
|
+import com.fs.his.mapper.FsThirdDeviceDataMapper;
|
|
|
+import com.fs.his.param.FsHealthPulseListUParam;
|
|
|
+import com.fs.his.param.FsHealthSurfaceListUParam;
|
|
|
+import com.fs.his.param.FsHealthTongueListUParam;
|
|
|
+import com.fs.his.vo.FsHealthPulseListVO;
|
|
|
+import com.fs.his.vo.FsHealthSurfaceListVO;
|
|
|
+import com.fs.his.vo.FsHealthTongueListUVO;
|
|
|
+import com.fs.watch.calculation.SleepScoreCalculator;
|
|
|
+import com.fs.watch.domain.*;
|
|
|
+import com.fs.watch.domain.vo.*;
|
|
|
import com.fs.watch.enums.*;
|
|
|
import com.fs.watch.mapper.*;
|
|
|
import com.fs.watch.param.WatchDataQueryParam;
|
|
|
@@ -16,11 +32,15 @@ import com.fs.watch.service.*;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
import org.mybatis.spring.MyBatisSystemException;
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
import java.util.*;
|
|
|
+import java.util.concurrent.CompletableFuture;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+import java.util.concurrent.TimeoutException;
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
|
|
/**
|
|
|
@@ -55,6 +75,26 @@ public class WatchBasicInfoServiceImpl implements WatchBasicInfoService {
|
|
|
private WatchSportDataService watchSportDataService;
|
|
|
@Autowired
|
|
|
private WatchDeviceInfoMapper watchDeviceInfoMapper;
|
|
|
+ @Autowired
|
|
|
+ private ChatService chatService;
|
|
|
+ @Autowired
|
|
|
+ private WatchUserService userService;
|
|
|
+ @Autowired
|
|
|
+ private WatchSportDataMapper sportDataMapper;
|
|
|
+ @Autowired
|
|
|
+ private FsHealthTongueMapper fsHealthTongueMapper;
|
|
|
+ @Autowired
|
|
|
+ private WatchDeviceWeekMapper watchDeviceWeekMapper;
|
|
|
+ @Autowired
|
|
|
+ private FsHealthSurfaceMapper fsHealthSurfaceMapper;
|
|
|
+ @Autowired
|
|
|
+ private FsHealthPulseMapper fsHealthPulseMapper;
|
|
|
+ @Autowired
|
|
|
+ InterestAiChatSessionMapper interestAiChatSessionMapper;
|
|
|
+ @Autowired
|
|
|
+ private FsThirdDeviceDataMapper fsThirdDeviceDataMapper;
|
|
|
+ private static final ObjectMapper objectMapper = new ObjectMapper();
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* 新增数据
|
|
|
@@ -64,11 +104,6 @@ public class WatchBasicInfoServiceImpl implements WatchBasicInfoService {
|
|
|
*/
|
|
|
@Override
|
|
|
public Boolean insert(WatchBasicInfo watchBasicInfo) {
|
|
|
- //判断创建时间是否唯一
|
|
|
- Integer num = watchBasicInfoMapper.queryByCreateTime(watchBasicInfo.getCreateTime());
|
|
|
- if (num != null && num > 0) {
|
|
|
- return false;
|
|
|
- }
|
|
|
try {
|
|
|
watchBasicInfoMapper.insert(watchBasicInfo);
|
|
|
//更新mysql的腕表数据
|
|
|
@@ -196,6 +231,9 @@ public class WatchBasicInfoServiceImpl implements WatchBasicInfoService {
|
|
|
return gnssVos;
|
|
|
}
|
|
|
|
|
|
+ private static final String APPKEY = "mygpt-nJvzjw0r7aEcvSA8po2BdHbUhm4oy8MEmK2V3r4YDHduo6gCJYWp";
|
|
|
+ private static final String AIURL = "http://154.8.194.176:3000/api";
|
|
|
+
|
|
|
/**
|
|
|
* >3个异常 只给出3个异常,优先级顺序 血糖、血压、心率、尿酸、血氧、睡眠、体温、步数
|
|
|
*
|
|
|
@@ -205,28 +243,132 @@ public class WatchBasicInfoServiceImpl implements WatchBasicInfoService {
|
|
|
* @return
|
|
|
*/
|
|
|
@Override
|
|
|
- public AppFsUserHealthReportVo getAppFsUserHealthReportVo(Date startTime, Date endTime, String deviceId) {
|
|
|
+ public AppFsUserHealthReportVo getAppFsUserHealthReportVo(Date startTime, Date endTime, String deviceId,
|
|
|
+ Long watchUserId,
|
|
|
+ Boolean isFamily,
|
|
|
+ Integer isRefresh,
|
|
|
+ Integer deviceType) {
|
|
|
AppFsUserHealthReportVo res = new AppFsUserHealthReportVo();
|
|
|
+ //查询用户和指定ai医生的会话
|
|
|
+ Integer sessionId = interestAiChatSessionMapper.selectSessionIdByUserAndRole(watchUserId, 140);
|
|
|
+ res.setRoleId(140);
|
|
|
+ if (sessionId != null){
|
|
|
+ res.setSessionId(sessionId);
|
|
|
+ }
|
|
|
+ //1.查询是否存在结果
|
|
|
+ WatchDeviceWeek weekData;
|
|
|
+ if (StringUtils.isBlank(deviceId)) {
|
|
|
+ if (watchUserId == null) {
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+ weekData = watchDeviceWeekMapper.getByUserIdAndTime(watchUserId, startTime);
|
|
|
+ } else {
|
|
|
+ weekData = watchDeviceWeekMapper.getByDeviceIdAndTime(deviceId, startTime);
|
|
|
+ }
|
|
|
+ if (weekData != null ) {
|
|
|
+ if (endTime.before(DateUtils.getNowDate()) || (isRefresh == null || isRefresh == 0)){
|
|
|
+ BeanUtils.copyProperties(weekData, res);
|
|
|
+ String listJson = weekData.getListJson();
|
|
|
+ if (StringUtils.isNotBlank(listJson)) {
|
|
|
+ res.setList(JSON.parseArray(listJson, AppHealthReportVo.class));
|
|
|
+ }
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //获取ai解析
|
|
|
+ CompletableFuture<Void> aiSuggestionFuture = CompletableFuture.runAsync(() -> {
|
|
|
+ getAiSuggestion(startTime, endTime, deviceId, watchUserId, isFamily, res,deviceType);
|
|
|
+ });
|
|
|
+ CompletableFuture<Void> totalScoreFuture = null;
|
|
|
+ if (StringUtils.isNotBlank(deviceId) && (deviceType == null || deviceType == 0)) {
|
|
|
+ //获取异常数据及分析
|
|
|
+ totalScoreFuture = CompletableFuture.runAsync(() -> {
|
|
|
+ getTotalScoreAndNormalData(startTime, endTime, deviceId, res);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ if (totalScoreFuture != null){
|
|
|
+ // 设置超时时间为30秒
|
|
|
+ CompletableFuture.allOf(aiSuggestionFuture, totalScoreFuture)
|
|
|
+ .get(360, TimeUnit.SECONDS);
|
|
|
+ } else {
|
|
|
+ // 设置超时时间为30秒
|
|
|
+ CompletableFuture.allOf(aiSuggestionFuture)
|
|
|
+ .get(360, TimeUnit.SECONDS);
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (TimeoutException e) {
|
|
|
+ // 超时处理
|
|
|
+ throw new RuntimeException("处理超时", e);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("异步执行失败", e);
|
|
|
+ }
|
|
|
+ //存到每周数据表
|
|
|
+ saveWeekData(startTime,endTime, deviceId, watchUserId,res);
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 存到每周数据表
|
|
|
+ *
|
|
|
+ * @param startTime
|
|
|
+ * @param res
|
|
|
+ */
|
|
|
+ private void saveWeekData(Date startTime, Date endTime,String deviceId, Long userId, AppFsUserHealthReportVo res) {
|
|
|
+ //判断最后一天是否晚于当前时间
|
|
|
+// if (!endTime.after(DateUtils.getNowDate())){
|
|
|
+ //否
|
|
|
+ if (StringUtils.isNotBlank(res.getAiSuggestion()) || res.getScore() != null) {
|
|
|
+ WatchDeviceWeek watchDeviceWeek = new WatchDeviceWeek();
|
|
|
+ BeanUtils.copyProperties(res, watchDeviceWeek);
|
|
|
+ List<AppHealthReportVo> list = res.getList();
|
|
|
+ if (list != null && !list.isEmpty()) {
|
|
|
+ watchDeviceWeek.setListJson(JSON.toJSONString(list));
|
|
|
+ }
|
|
|
+ watchDeviceWeek.setCreateTime(startTime);
|
|
|
+ WatchDeviceWeek oldWeekData = null;
|
|
|
+ if (StringUtils.isNotBlank(deviceId)) {
|
|
|
+ watchDeviceWeek.setDeviceId(deviceId);
|
|
|
+ oldWeekData = watchDeviceWeekMapper.getByDeviceIdAndTime(deviceId, startTime);
|
|
|
+
|
|
|
+ } else {
|
|
|
+ watchDeviceWeek.setDeviceId(userId.toString());
|
|
|
+ oldWeekData = watchDeviceWeekMapper.getByUserIdAndTime(userId, startTime);
|
|
|
+ }
|
|
|
+ watchDeviceWeek.setUserId(userId);
|
|
|
+ //查询是否存在 存在更新
|
|
|
+ if (oldWeekData != null && oldWeekData.getId() != null) {
|
|
|
+ watchDeviceWeek.setId(oldWeekData.getId());
|
|
|
+ watchDeviceWeekMapper.updateWatchDeviceWeek(watchDeviceWeek);
|
|
|
+ } else {
|
|
|
+ watchDeviceWeekMapper.insertWatchDeviceWeek(watchDeviceWeek);
|
|
|
+ }
|
|
|
+ }
|
|
|
+// }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void getTotalScoreAndNormalData(Date startTime, Date endTime, String deviceId, AppFsUserHealthReportVo res) {
|
|
|
ArrayList<AppHealthReportVo> vos = new ArrayList<>();
|
|
|
AtomicInteger score = new AtomicInteger(100); //分数
|
|
|
String start = DateUtils.parseDateToStr("yyyy-MM-dd hh:mm:ss", startTime);
|
|
|
String end = DateUtils.parseDateToStr("yyyy-MM-dd hh:mm:ss", endTime);
|
|
|
//先查询睡眠数据
|
|
|
- watchSleepDataService.getSleepStatus(startTime,endTime,deviceId);
|
|
|
+ watchSleepDataService.getSleepStatus(startTime, endTime, deviceId);
|
|
|
|
|
|
// 顺序执行各项异常处理(最多保留3个)
|
|
|
- getHealth(watchBloodGlucoseDataMapper.countBpByDate(start, end, deviceId), vos, WatchBgStatusEnum.class,score);
|
|
|
- getHealth(watchBloodPressureDataMapper.countBpByDate(start, end, deviceId), vos, WatchBpStatusEnum.class,score);
|
|
|
- getHealth(watchHeartRateDataMapper.countBpByDate(start, end, deviceId), vos, WatchHrStatusEnum.class,score);
|
|
|
- getHealth(watchThirdUaDataMapper.countUaByDate(start, end, deviceId), vos, WatchUaStatusEnum.class,score);
|
|
|
- getHealth(watchSpo2DataMapper.countSpByDate(start, end, deviceId), vos, WatchSpo2StatusEnum.class,score);
|
|
|
- getHealth(watchSleepDataService.countSlByDate(start, end, deviceId), vos, WatchSleepStatusEnum.class,score);
|
|
|
- getHealth(watchTemperatureDataMapper.countByDate(start, end, deviceId), vos, WatchTemperatureStatusEnum.class,score);
|
|
|
+ getHealth(watchBloodGlucoseDataMapper.countBpByDate(start, end, deviceId), vos, WatchBgStatusEnum.class, score);
|
|
|
+ getHealth(watchBloodPressureDataMapper.countBpByDate(start, end, deviceId), vos, WatchBpStatusEnum.class, score);
|
|
|
+ getHealth(watchHeartRateDataMapper.countBpByDate(start, end, deviceId), vos, WatchHrStatusEnum.class, score);
|
|
|
+ getHealth(watchThirdUaDataMapper.countUaByDate(start, end, deviceId), vos, WatchUaStatusEnum.class, score);
|
|
|
+ getHealth(watchSpo2DataMapper.countSpByDate(start, end, deviceId), vos, WatchSpo2StatusEnum.class, score);
|
|
|
+ getHealth(watchSleepDataService.countSlByDate(start, end, deviceId), vos, WatchSleepStatusEnum.class, score);
|
|
|
+ getHealth(watchTemperatureDataMapper.countByDate(start, end, deviceId), vos, WatchTemperatureStatusEnum.class, score);
|
|
|
|
|
|
|
|
|
// 2. 步数(枚举可能不需要,可直接判断)
|
|
|
WatchStepStatusEnum weekStatus = watchSportDataService.getWeekStatus(start, end, deviceId);
|
|
|
- if (!Objects.equals(weekStatus.getValue(), WatchStepStatusEnum.NORMAL.getValue())){
|
|
|
+ if (!Objects.equals(weekStatus.getValue(), WatchStepStatusEnum.NORMAL.getValue())) {
|
|
|
AppHealthReportVo vo = new AppHealthReportVo();
|
|
|
vo.setPrediction(weekStatus.getPrediction());
|
|
|
vo.setAnalysis(weekStatus.getAnalysis());
|
|
|
@@ -250,29 +392,496 @@ public class WatchBasicInfoServiceImpl implements WatchBasicInfoService {
|
|
|
res.setScore(finalScore);
|
|
|
|
|
|
WatchHealthEnum healthEnum = null;
|
|
|
- if(finalScore>=90){
|
|
|
+ if (finalScore >= 90) {
|
|
|
healthEnum = WatchHealthEnum.EXCELLENT;
|
|
|
- } else if (finalScore>=80){
|
|
|
+ } else if (finalScore >= 80) {
|
|
|
healthEnum = WatchHealthEnum.GOOD;
|
|
|
- } else if (finalScore>=70){
|
|
|
+ } else if (finalScore >= 70) {
|
|
|
healthEnum = WatchHealthEnum.GENERAL;
|
|
|
- } else{
|
|
|
+ } else {
|
|
|
healthEnum = WatchHealthEnum.POOR;
|
|
|
}
|
|
|
res.setTitle(healthEnum.getTitle());
|
|
|
res.setDesc(healthEnum.getDesc());
|
|
|
+ }
|
|
|
|
|
|
- return res;
|
|
|
+
|
|
|
+ /**
|
|
|
+ *
|
|
|
+ * @param startTime
|
|
|
+ * @param endTime
|
|
|
+ * @param deviceId
|
|
|
+ * @param watchUserId
|
|
|
+ * @param isFamily
|
|
|
+ * @param res
|
|
|
+ * @param deviceType 0腕表1小护士2新表
|
|
|
+ */
|
|
|
+ private void getAiSuggestion(Date startTime, Date endTime, String deviceId, Long watchUserId, Boolean isFamily,
|
|
|
+ AppFsUserHealthReportVo res,Integer deviceType) {
|
|
|
+ String aiSuggestion = "";
|
|
|
+ ChatParam param = new ChatParam();
|
|
|
+ param.setStream(false);
|
|
|
+ param.setDetail(true);
|
|
|
+ ChatParam.Variables variables = new ChatParam.Variables();
|
|
|
+ variables.setName("healthReport");
|
|
|
+ List<ChatParam.Message> messageList = new ArrayList<ChatParam.Message>();
|
|
|
+ param.setMessages(messageList);
|
|
|
+ ChatParam.Message message1 = new ChatParam.Message();
|
|
|
+ message1.setRole("user");
|
|
|
+ //组合询问问题
|
|
|
+ StringBuilder str = new StringBuilder();
|
|
|
+ str.append("今日日期:");
|
|
|
+ str.append(DateUtils.dateTimeNow("MM月dd日"));
|
|
|
+ //1.身高体重
|
|
|
+ if (watchUserId != null) {
|
|
|
+ AppFsUserVo userVo = userService.getUserInfoByDeviceId(deviceId, isFamily, watchUserId,deviceType);
|
|
|
+ if (userVo != null && userVo.getHeight() != null && userVo.getWeight() != null) {
|
|
|
+ str.append("【身高 ").append(userVo.getHeight()).append("cm 体重 ").append(userVo.getWeight()).append("kg】");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //按天查询总数
|
|
|
+ //创建日历实例用于遍历日期
|
|
|
+ Calendar calendar = Calendar.getInstance();
|
|
|
+ calendar.setTime(startTime);
|
|
|
+
|
|
|
+ Calendar endCalendar = Calendar.getInstance();
|
|
|
+ endCalendar.setTime(endTime);
|
|
|
+ //遍历每一天
|
|
|
+ //运动
|
|
|
+ StringBuilder spotStr = new StringBuilder();
|
|
|
+ //血压
|
|
|
+ StringBuilder bpStr = new StringBuilder();
|
|
|
+ //血糖
|
|
|
+ StringBuilder bgStr = new StringBuilder();
|
|
|
+ //心率
|
|
|
+ StringBuilder hrStr = new StringBuilder();
|
|
|
+ //血氧
|
|
|
+ StringBuilder spo2Str = new StringBuilder();
|
|
|
+ //睡眠
|
|
|
+ StringBuilder sleepStr = new StringBuilder();
|
|
|
+ //舌诊
|
|
|
+ StringBuilder tongueStr = new StringBuilder();
|
|
|
+ //面诊
|
|
|
+ StringBuilder surfaceStr = new StringBuilder();
|
|
|
+ StringBuilder pulseStr = new StringBuilder();
|
|
|
+ //判断是否需要ai解析
|
|
|
+ Boolean isRequestAi = false;
|
|
|
+ while (!calendar.after(endCalendar)) {
|
|
|
+ Date currentStartDate = calendar.getTime();
|
|
|
+ String start = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", currentStartDate);
|
|
|
+ String dateToStr = DateUtils.parseDateToStr("MM月dd日", currentStartDate);
|
|
|
+ //创建当天结束时间(23:59:59)
|
|
|
+ Calendar dayEndCalendar = (Calendar) calendar.clone();
|
|
|
+ dayEndCalendar.add(Calendar.DAY_OF_MONTH, 1);
|
|
|
+ dayEndCalendar.add(Calendar.SECOND, -1);
|
|
|
+ Date currentEndDate = dayEndCalendar.getTime();
|
|
|
+ String end = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", currentEndDate);
|
|
|
+
|
|
|
+ if (StringUtils.isNotBlank(deviceId)) {
|
|
|
+ //2.计算每天步数总和
|
|
|
+ calculateStep(deviceId, start, end, spotStr, dateToStr,deviceType);
|
|
|
+ //3.血压
|
|
|
+ calculateBp(deviceId, start, end, bpStr, dateToStr,deviceType);
|
|
|
+
|
|
|
+
|
|
|
+ //4.血糖
|
|
|
+ calculateBg(deviceId, start, end, bgStr, dateToStr,deviceType);
|
|
|
+ //5.心率
|
|
|
+ calculateHr(deviceId, start, end, hrStr, dateToStr,deviceType);
|
|
|
+ //6.血氧
|
|
|
+ calculateSpo2(deviceId, start, end, spo2Str, dateToStr,deviceType);
|
|
|
+
|
|
|
+ //7.睡眠
|
|
|
+ calculateSleep(deviceId, DateUtils.parseDateToStr("yyyy-MM-dd", currentStartDate), sleepStr, dateToStr,deviceType);
|
|
|
+ }
|
|
|
+ if (watchUserId != null) {
|
|
|
+ //8.舌诊
|
|
|
+ calculateTongue(watchUserId, DateUtils.parseDateToStr("yyyy-MM-dd", currentStartDate), tongueStr, dateToStr);
|
|
|
+ //9.面诊
|
|
|
+ calculateSurface(watchUserId, DateUtils.parseDateToStr("yyyy-MM-dd", currentStartDate), surfaceStr, dateToStr);
|
|
|
+ //10.脉诊
|
|
|
+ calculatePulse(watchUserId, DateUtils.parseDateToStr("yyyy-MM-dd", currentStartDate), pulseStr, dateToStr);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ //日期加1天
|
|
|
+ calendar.add(Calendar.DAY_OF_MONTH, 1);
|
|
|
+ setToStartOfDay(calendar);
|
|
|
+ }
|
|
|
+ if (spotStr.length() > 0) {
|
|
|
+ str.append("\n").append("【步行:").append(spotStr).append("】");
|
|
|
+ }
|
|
|
+ if (bpStr.length() > 0) {
|
|
|
+ str.append("\n").append("【血压:").append(bpStr).append("】");
|
|
|
+ isRequestAi = true;
|
|
|
+ }
|
|
|
+ if (bgStr.length() > 0) {
|
|
|
+ str.append("\n").append("【血糖:").append(bgStr).append("】");
|
|
|
+ isRequestAi = true;
|
|
|
+ }
|
|
|
+ if (hrStr.length() > 0) {
|
|
|
+ str.append("\n").append("【心率:").append(hrStr).append("】");
|
|
|
+ isRequestAi = true;
|
|
|
+ }
|
|
|
+ if (spo2Str.length() > 0) {
|
|
|
+ str.append("\n").append("【血氧:").append(spo2Str).append("】");
|
|
|
+ isRequestAi = true;
|
|
|
+ }
|
|
|
+ if (sleepStr.length() > 0) {
|
|
|
+ if (sleepStr.toString().endsWith(",")) {
|
|
|
+ sleepStr.deleteCharAt(sleepStr.length() - 1);
|
|
|
+ }
|
|
|
+ str.append("\n").append("【睡眠:").append(sleepStr).append("】");
|
|
|
+ isRequestAi = true;
|
|
|
+ }
|
|
|
+ if (tongueStr.length() > 0) {
|
|
|
+ str.append("\n").append("【舌诊:").append(tongueStr).append("】");
|
|
|
+ isRequestAi = true;
|
|
|
+ }
|
|
|
+ if (surfaceStr.length() > 0) {
|
|
|
+ str.append("\n").append("【面诊:").append(surfaceStr).append("】");
|
|
|
+ isRequestAi = true;
|
|
|
+ }
|
|
|
+ if (pulseStr.length() > 0) {
|
|
|
+ str.append("\n").append("【脉诊:").append(pulseStr).append("】");
|
|
|
+ isRequestAi = true;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if (StringUtils.isNotBlank(str) && isRequestAi) {
|
|
|
+ log.info("健康报告:{}", str);
|
|
|
+ message1.setContent(str.toString());
|
|
|
+ messageList.add(message1);
|
|
|
+
|
|
|
+
|
|
|
+ R r = chatService.initiatingTakeChat(param, AIURL, APPKEY);
|
|
|
+ if (r != null && r.get("data") != null) {
|
|
|
+ Object data = r.get("data");
|
|
|
+ if (!(data instanceof KnowledgeBaseResult)) {
|
|
|
+ ChatDetailTStreamFResult result = (ChatDetailTStreamFResult) r.get("data");
|
|
|
+ if (result != null) {
|
|
|
+ List<ChatDetailTStreamFResult.Choice> choices = result.getChoices();
|
|
|
+ //默认取第一条
|
|
|
+ if (choices != null && choices.size() > 0) {
|
|
|
+ ChatDetailTStreamFResult.Choice choice = choices.get(0);
|
|
|
+ ChatDetailTStreamFResult.Choice.Message message = choice.message;
|
|
|
+ if (message != null) {
|
|
|
+ String content = message.getContent();
|
|
|
+ if (StringUtils.isNotBlank(content)) {
|
|
|
+ aiSuggestion = content;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ res.setAiSuggestion(aiSuggestion);
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+ private void calculatePulse(Long userId, String date, StringBuilder pulseStr, String dateToStr) {
|
|
|
+ FsHealthPulseListUParam param = new FsHealthPulseListUParam();
|
|
|
+ param.setUserId(userId);
|
|
|
+ param.setCreateDay(date);
|
|
|
+
|
|
|
+ List<FsHealthPulseListVO> fsHealthPulseListVOS = fsHealthPulseMapper.selectFsHealthPulseListVO(param);
|
|
|
+ if (fsHealthPulseListVOS != null && !fsHealthPulseListVOS.isEmpty()) {
|
|
|
+ FsHealthPulseListVO vo = fsHealthPulseListVOS.get(0);
|
|
|
+
|
|
|
+ String leftJson = vo.getLeftHandResult();
|
|
|
+ String rightJson = vo.getRightHandResult();
|
|
|
+
|
|
|
+ String leftResult = "", leftSize = "", rightResult = "", rightSize = "";
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (StringUtils.isNotEmpty(leftJson)) {
|
|
|
+ JsonNode node = objectMapper.readTree(leftJson);
|
|
|
+ leftResult = node.path("leftHandResult").asText("");
|
|
|
+ leftSize = node.path("leftHandSize").asText("");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (StringUtils.isNotEmpty(rightJson)) {
|
|
|
+ JsonNode node = objectMapper.readTree(rightJson);
|
|
|
+ rightResult = node.path("rightHandResult").asText("");
|
|
|
+ rightSize = node.path("rightHandSize").asText("");
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("解析脉象JSON失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ pulseStr.append(dateToStr).append(" 左手 ").append(leftSize).append(" ").append("右手 ").append(rightSize).append(" ");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private void calculateSurface(Long userId, String date, StringBuilder surfaceStr, String dateToStr) {
|
|
|
+ FsHealthSurfaceListUParam param = new FsHealthSurfaceListUParam();
|
|
|
+ param.setUserId(userId);
|
|
|
+ param.setCreateDay(date);
|
|
|
+ List<FsHealthSurfaceListVO> fsHealthSurfaceListVOS = fsHealthSurfaceMapper.selectFsHealthSurfaceListVO(param);
|
|
|
+ if (fsHealthSurfaceListVOS != null && !fsHealthSurfaceListVOS.isEmpty()) {
|
|
|
+ FsHealthSurfaceListVO vo = fsHealthSurfaceListVOS.get(0);
|
|
|
+ surfaceStr.append(dateToStr).append(" ").append(vo.getComplexionResult()).append(" ").append(vo.getGlowResult()).append(" ").append(vo.getSwellingProblems()).append(" ");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算每天舌诊
|
|
|
+ *
|
|
|
+ * @param userId
|
|
|
+ * @param date
|
|
|
+ * @param tongueStr
|
|
|
+ * @param dateToStr
|
|
|
+ */
|
|
|
+ private void calculateTongue(Long userId, String date, StringBuilder tongueStr, String dateToStr) {
|
|
|
+ FsHealthTongueListUParam param = new FsHealthTongueListUParam();
|
|
|
+ param.setUserId(userId);
|
|
|
+ param.setCreateDay(date);
|
|
|
+ List<FsHealthTongueListUVO> vos = fsHealthTongueMapper.selectFsHealthTongueUListVO(param);
|
|
|
+ if (vos != null && !vos.isEmpty()) {
|
|
|
+ FsHealthTongueListUVO vo = vos.get(0);
|
|
|
+ tongueStr.append(dateToStr).append(" ").append(vo.getTypeName()).append(" ").append(vo.getShemianName()).append(" ").append(vo.getTaiseName()).append(" ");
|
|
|
+ try {
|
|
|
+ String chihenDesc = vo.getChihenDesc();
|
|
|
+ if (StringUtils.isNotBlank(chihenDesc)) {
|
|
|
+ chihenDesc = chihenDesc.substring(1).split("表示")[0];
|
|
|
+ tongueStr.append(chihenDesc).append(" ");
|
|
|
+ }
|
|
|
+ String liewenDesc = vo.getLiewenDesc();
|
|
|
+ if (StringUtils.isNotBlank(liewenDesc)) {
|
|
|
+ liewenDesc = liewenDesc.substring(1).split("表示")[0];
|
|
|
+ tongueStr.append(liewenDesc).append(" ");
|
|
|
+ }
|
|
|
+ String botaiDesc = vo.getBotaiDesc();
|
|
|
+ if (StringUtils.isNotBlank(botaiDesc)) {
|
|
|
+ botaiDesc = botaiDesc.substring(1).split("表示")[0];
|
|
|
+ tongueStr.append(botaiDesc).append(" ");
|
|
|
+ }
|
|
|
+ String taiseDesc = vo.getTaiseDesc();
|
|
|
+ if (StringUtils.isNotBlank(taiseDesc)) {
|
|
|
+ tongueStr.append(taiseDesc).append(" ");
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("舌苔详细解析错误{}错误信息:{}", vo, e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算每天睡眠
|
|
|
+ *
|
|
|
+ * @param deviceId
|
|
|
+ * @param date
|
|
|
+ * @param sleepStr
|
|
|
+ * @param dateToStr
|
|
|
+ */
|
|
|
+ private void calculateSleep(String deviceId, String date, StringBuilder sleepStr, String dateToStr,Integer deviceType) {
|
|
|
+ if (deviceType == null || deviceType == 0) {
|
|
|
+ WatchSleepDataVo vo = watchSleepDataService.getSleepSection(date, deviceId);
|
|
|
+ if (vo != null) {
|
|
|
+ if (StringUtils.isNotBlank(vo.getStartTime())) {
|
|
|
+ sleepStr.append(dateToStr).append(" ").append(vo.getStartTime()).append("入睡,");
|
|
|
+ } else {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (StringUtils.isNotBlank(vo.getEndTime())) {
|
|
|
+ sleepStr.append(vo.getEndTime()).append("醒来,");
|
|
|
+ }
|
|
|
+ if (vo.getSleepTime() != null) {
|
|
|
+ sleepStr.append("深睡 ").append(vo.getSleepTime()).append(" 分钟,");
|
|
|
+ }
|
|
|
+ if (vo.getLightSleep() != null) {
|
|
|
+ sleepStr.append("浅睡 ").append(vo.getLightSleep()).append(" 分钟,");
|
|
|
+ }
|
|
|
+ if (vo.getEyemoveSleep() != null) {
|
|
|
+ sleepStr.append("快速眼动 ").append(vo.getEyemoveSleep()).append(" 分钟,");
|
|
|
+ }
|
|
|
+ if (vo.getWeakSleep() != null) {
|
|
|
+ sleepStr.append("清醒 ").append(vo.getWeakSleep()).append(" 分钟,");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Date dateTemp = DateUtils.dateTime("yyyy-MM-dd", date);
|
|
|
+ Date dayStartTime = DateUtils.truncate(dateTemp, Calendar.DATE);
|
|
|
+ Date dayEndTime = DateUtils.addMilliseconds(
|
|
|
+ DateUtils.addDays(DateUtils.truncate(dateTemp, Calendar.DATE), 1),
|
|
|
+ -1
|
|
|
+ );
|
|
|
+ List<FsThirdDeviceData> list = fsThirdDeviceDataMapper.selectListByDateAndDeviceIdAndRecordType(dayStartTime, dayEndTime, deviceId, 7, null);
|
|
|
+ if (list != null && !list.isEmpty()) {
|
|
|
+ SleepStatistics sleepStatistics = SleepScoreCalculator.calculateDetailedStatistics(list);
|
|
|
+ sleepStr.append(dateToStr).append(" ").append(list.get(0).getCreateTime()).append("入睡,");
|
|
|
+ if (list.size() > 1) {
|
|
|
+ sleepStr.append(list.get(list.size()-1).getCreateTime()).append("醒来,");
|
|
|
+ }
|
|
|
+ sleepStr.append("深睡 ").append(sleepStatistics.getDeepSleepHours()*60).append(" 分钟,");
|
|
|
+ sleepStr.append("浅睡 ").append(sleepStatistics.getLightSleepHours()*60).append(" 分钟,");
|
|
|
+ sleepStr.append("清醒 ").append(sleepStatistics.getAwakeHours()*60).append(" 分钟,");
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算每天血氧
|
|
|
+ *
|
|
|
+ * @param deviceId
|
|
|
+ * @param currentStartDate
|
|
|
+ * @param currentEndDate
|
|
|
+ * @param spo2Str
|
|
|
+ * @param dateToStr
|
|
|
+ */
|
|
|
+ private void calculateSpo2(String deviceId, String currentStartDate, String currentEndDate, StringBuilder spo2Str,
|
|
|
+ String dateToStr,Integer deviceType) {
|
|
|
+ Float value = null;
|
|
|
+ if (deviceType == null || deviceType == 1) {
|
|
|
+ value = watchSpo2DataMapper.countAvgBpByDate(currentStartDate, currentEndDate, deviceId);
|
|
|
+
|
|
|
+ } else {
|
|
|
+ value = fsThirdDeviceDataMapper.countAvgBpByDate(currentStartDate, currentEndDate, deviceId);
|
|
|
+ }
|
|
|
+ if (value != null) {
|
|
|
+ spo2Str.append(dateToStr).append(" ").append(value).append("% ");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算每天心率
|
|
|
+ *
|
|
|
+ * @param deviceId
|
|
|
+ * @param currentStartDate
|
|
|
+ * @param currentEndDate
|
|
|
+ * @param hrStr
|
|
|
+ * @param dateToStr
|
|
|
+ */
|
|
|
+ private void calculateHr(String deviceId, String currentStartDate, String currentEndDate, StringBuilder hrStr,
|
|
|
+ String dateToStr,Integer deviceType) {
|
|
|
+ Map<String, Integer> map = null;
|
|
|
+ if (deviceType == null || deviceType == 0) {
|
|
|
+ map = watchHeartRateDataMapper.countMaxAndAvgBpByDate(currentStartDate, currentEndDate, deviceId);
|
|
|
+ } else {
|
|
|
+ map = fsThirdDeviceDataMapper.countMaxAndAvgBpByDate(currentStartDate, currentEndDate, deviceId);
|
|
|
+ }
|
|
|
+ if (map != null && map.get("avgBpm") != null && map.get("maxBpm") != null) {
|
|
|
+ hrStr.append(dateToStr).append(" 平均").append(map.get("avgBpm")).append(" 最高 ").append(map.get("maxBpm")).append(" ");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算每天血糖
|
|
|
+ *
|
|
|
+ * @param deviceId
|
|
|
+ * @param currentStartDate
|
|
|
+ * @param currentEndDate
|
|
|
+ * @param bgStr
|
|
|
+ */
|
|
|
+ private void calculateBg(String deviceId, String currentStartDate, String currentEndDate, StringBuilder bgStr,
|
|
|
+ String dateToStr,Integer deviceType) {
|
|
|
+ if (deviceType == null || deviceType == 0) {
|
|
|
+ List<WatchBloodGlucoseData> bgData = watchBloodGlucoseDataMapper.queryBgByDate(currentStartDate, currentEndDate, deviceId, null);
|
|
|
+
|
|
|
+ if (bgData != null && !bgData.isEmpty()) {
|
|
|
+ WatchBloodGlucoseData watchBloodGlucoseData = bgData.get(bgData.size() - 1);
|
|
|
+ bgStr.append(dateToStr).append(" ").append(watchBloodGlucoseData.getBloodGlucose()).append("mmol/L ");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ List<FsThirdDeviceData> bgData = fsThirdDeviceDataMapper.queryBgByDate(currentStartDate, currentEndDate, deviceId);
|
|
|
+
|
|
|
+ if (bgData != null && !bgData.isEmpty()) {
|
|
|
+ FsThirdDeviceData fsThirdDeviceData = bgData.get(bgData.size() - 1);
|
|
|
+ bgStr.append(dateToStr).append(" ").append(fsThirdDeviceData.getRecordValue()).append("mmol/L ");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算每天血压
|
|
|
+ *
|
|
|
+ * @param deviceId
|
|
|
+ * @param currentStartDate
|
|
|
+ * @param currentEndDate
|
|
|
+ * @param bpStr
|
|
|
+ */
|
|
|
+ private void calculateBp(String deviceId, String currentStartDate, String currentEndDate, StringBuilder bpStr
|
|
|
+ , String dateToStr,Integer deviceType) {
|
|
|
+ Map<String, Integer> map = new HashMap<>();
|
|
|
+ if(deviceType == null || deviceType == 0){
|
|
|
+ //原腕表
|
|
|
+ map = watchBloodPressureDataMapper.countMaxAndMinBpByDate(currentStartDate, currentEndDate, deviceId);
|
|
|
+ } else {
|
|
|
+ //小护士
|
|
|
+ map = fsThirdDeviceDataMapper.countMaxAndMinBpByDate(currentStartDate, currentEndDate, deviceId);
|
|
|
+ }
|
|
|
+ if (map != null && map.get("max") != null && map.get("min") != null) {
|
|
|
+ bpStr.append(dateToStr).append(" 高压 ").append(map.get("max")).append(" 低压 ").append(map.get("min")).append(" ");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算每天步数总和
|
|
|
+ *
|
|
|
+ * @param deviceId
|
|
|
+ * @param currentStartDate
|
|
|
+ * @param currentEndDate
|
|
|
+ * @param spotStr
|
|
|
+ */
|
|
|
+ private void calculateStep(String deviceId, String currentStartDate, String currentEndDate, StringBuilder spotStr,
|
|
|
+ String dateToStr,Integer deviceType) {
|
|
|
+ long dailyStep = 0;
|
|
|
+ if (deviceType == null || deviceType == 0) {
|
|
|
+ List<WatchSportData> list = sportDataMapper.getByType(currentStartDate, currentEndDate, deviceId, null);
|
|
|
+ if (list != null && !list.isEmpty()) {
|
|
|
+ for (WatchSportData data : list) {
|
|
|
+ dailyStep += data.getStep() == null ? 0 : data.getStep();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ //小护士设备
|
|
|
+ WatchSportRecordVo otherData1 = fsThirdDeviceDataMapper.getOtherData(DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", currentStartDate),
|
|
|
+ DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", currentEndDate), deviceId, 5, null);
|
|
|
+ WatchSportRecordVo otherData2 = fsThirdDeviceDataMapper.getOtherData(DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", currentStartDate),
|
|
|
+ DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", currentEndDate), deviceId, 6, null);
|
|
|
+ if (otherData1 != null){
|
|
|
+ dailyStep = dailyStep + (otherData1.getStep() == null?0:otherData1.getStep());
|
|
|
+ }
|
|
|
+ if (otherData2 != null){
|
|
|
+ dailyStep = dailyStep + (otherData2.getStep() == null?0:otherData2.getStep());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (dailyStep > 0) {
|
|
|
+ spotStr.append(dateToStr).append(" ").append(dailyStep).append("步 ");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将日历设置为当天的开始时间(00:00:00)
|
|
|
+ */
|
|
|
+ private void setToStartOfDay(Calendar calendar) {
|
|
|
+ calendar.set(Calendar.HOUR_OF_DAY, 0);
|
|
|
+ calendar.set(Calendar.MINUTE, 0);
|
|
|
+ calendar.set(Calendar.SECOND, 0);
|
|
|
+ calendar.set(Calendar.MILLISECOND, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
public <T extends Enum<T> & HealthStatusEnum> void getHealth(
|
|
|
List<Map<String, Object>> data,
|
|
|
List<AppHealthReportVo> vos,
|
|
|
Class<T> enumClass,
|
|
|
- AtomicInteger score
|
|
|
+ AtomicInteger score
|
|
|
) {
|
|
|
if (data == null) {
|
|
|
return;
|
|
|
@@ -281,7 +890,7 @@ public class WatchBasicInfoServiceImpl implements WatchBasicInfoService {
|
|
|
Integer status = Integer.valueOf(map.get("status").toString());
|
|
|
Integer count = Integer.valueOf(map.get("count").toString());
|
|
|
if (count > 0) {
|
|
|
- AppHealthReportVo vo = createHealthReportVo(status, count, enumClass,score);
|
|
|
+ AppHealthReportVo vo = createHealthReportVo(status, count, enumClass, score);
|
|
|
if (vo != null) {
|
|
|
vos.add(vo);
|
|
|
}
|
|
|
@@ -293,7 +902,7 @@ public class WatchBasicInfoServiceImpl implements WatchBasicInfoService {
|
|
|
Integer status,
|
|
|
Integer count,
|
|
|
Class<T> enumClass,
|
|
|
- AtomicInteger score
|
|
|
+ AtomicInteger score
|
|
|
) {
|
|
|
if (status == null || enumClass == null) return null;
|
|
|
|
|
|
@@ -310,7 +919,7 @@ public class WatchBasicInfoServiceImpl implements WatchBasicInfoService {
|
|
|
vo.setSuggestion(matchedEnum.getSuggestion());
|
|
|
vo.setPrecautions(matchedEnum.getPrecautions());
|
|
|
//扣得分 出现一次异常减5分,无数据不扣分
|
|
|
- score.addAndGet(-(5*count)); // 异常就减分
|
|
|
+ score.addAndGet(-(5 * count)); // 异常就减分
|
|
|
return vo;
|
|
|
}
|
|
|
|