33 Commits
Author SHA1 Message Date
lianlonggang 177e0e4d97 feat(watch): listCustom 接口与导出增加 eventId、locateTime 字段
1. AbnormalEvent 新增 eventId、locateTime 字段
2. listCustom/largeScreenListCustom/listCustomForMap 三个接口返回新字段
3. 导出 Excel 通过 @Excel 注解自动支持新字段(顺序 12、13)
4. locateTime 时间格式化为 yyyy-MM-dd HH:mm:ss
5. 修正 createMonitorData 中遗漏的 eventId 与 locateTime 字段赋值
6. DDL 表名修正为 QH_WAT_MONITOR_DATA(项目实际表名)
2026-09-03 13:43:26 +08:00
lianlonggang f74a2322e4 chore(db): 将已执行完成的 SQL 脚本从 updatesql 迁移至 done 目录
将历史已执行完毕的 SQL 更新脚本统一归档至 db/done/ 目录,
便于区分待执行脚本与已完成脚本。
2026-09-03 10:43:23 +08:00
lianlonggang 822cdbf539 feat(watch): notice 入参新增 eventId、locateTime;新增 updateMonitorGps 接口
1. WatchNotifyVo、WatchMonitorData 新增 eventId 与 locateTime 字段
2. 新增 POST /watchApi/updateMonitorGps 接口
3. watchNo + eventId 联合定位告警数据,任一缺失则忽略
4. 已存在 lon/lat 数据则忽略本次更新,避免覆盖
5. GPS84 → GCJ02 坐标转换 + 高德地址反查(参考 createMonitorData 逻辑)
6. 仅更新 GPS 相关字段,不推送大屏与短信
2026-09-03 10:40:14 +08:00
lianlonggang d75f21c17e feat(db): watch_monitor_data 表新增 EVENT_ID 与 LOCATE_TIME 字段
为支持手表告警事件与定时GPS位置上报的关联,新增两个字段:
- EVENT_ID(事件ID,用于告警事件与GPS位置更新关联)
- LOCATE_TIME(定位时间,手表定时上报的GPS定位时间)

同时新增 IDX_EVENT_ID 单列索引与 IDX_WATCH_NO_EVENT_ID 联合索引,
优化 watchNo + eventId 联合定位查询性能。

数据库:118-DM 达梦数据库,SQL 全大写规范。
2026-09-03 10:40:02 +08:00
lianlonggangandClaude Opus 4.7 ffee8611fe fix(watch): 恢复设备导入校验和手表绑定单位限制,新增未分配设备数统计
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 11:05:33 +08:00
lianlonggang 0e8f5e7b14 feat(watch): 导入设备绑定时,手表所属单位以员工信息为准 2026-05-06 14:47:33 +08:00
lianlonggang 115407026f fix(device): 解决设备导入和绑定功能的部门权限问题
- 移除设备导入时的部门必填验证,允许为空时默认归入新疆油田公司(A01)
- 移除设备绑定时的跨单位限制检查
- 在设备绑定时根据员工信息更新手表的单位信息
- 修复部门统计数据查询中的层级展示逻辑
- 优化部门统计服务中的注释文档和代码结构
- 添加设备表更新操作中单位编码和部门ID的条件设置
2026-04-30 14:13:26 +08:00
lianlonggang 9f545952e4 fix(upload): 修复文件上传和权限配置问题
- 修正 MyUploadUtil 中 tar/apk 文件上传调用参数,添加必需的布尔参数
- 注释掉 Shiro 配置中 /sys/upload/down/** 和 /sys/upload/show/** 的匿名访问权限
- 解决文件上传功能与安全配置的兼容性问题
2026-04-30 08:49:19 +08:00
lianlonggang 1988e031e5 feat(file-upload): 集成新疆OSS文件上传功能并优化设备删除逻辑
- 实现新疆油田平台OSS文件上传工具类XjOssUtil,支持OAuth2鉴权和文件操作
- 在MyUploadUtil中集成OSS上传逻辑,通过oss_flag配置动态选择上传方式
- 为.tar和.apk文件强制使用MyUploadUtil上传,其他文件根据oss_flag配置决定上传方式
- 在手表设备删除接口中增加绑定用户检查,已绑定用户的手表不允许删除
- 添加GlobalManager依赖注入以支持动态配置读取
- 实现文件上传流程的日志记录和错误处理机制
2026-04-21 17:22:09 +08:00
lianlonggang 44b0f6ca2b feat(care-user): 添加年度参数并导入日期工具类
- 导入 cn.hutool.core.date.DateUtil 工具类
- 新增 year 字段用于存储当前年份
- 使用 DateUtil.thisYear() 设置默认值为当前年份
2026-04-14 10:34:10 +08:00
lianlonggang ae866f0791 fix(controller): 禁止移动端解绑手表设备并优化异步处理
- 移动端解绑设备接口返回错误提示,需联系健康管理员解绑
- 设备绑定流程中的警告开关设置改为异步执行
- 防止外部系统异常影响主业务流程
- 解绑操作中移除对数据中心的通知调用
2026-04-10 10:28:06 +08:00
wanghaoandClaude Sonnet 4.6 4610ac4737 fix(健康监测): 禁用移动端手表解绑功能,改为提示联系管理员操作
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 17:19:35 +08:00
wanghaoandClaude Opus 4.6 6d6920a2b3 fix(健康监测): 修复手表绑定单位校验使用前端传入orgCode导致的校验失效问题
将绑定校验的orgCode来源从dto改为watchDevice实体,
避免前端未传orgCode时校验必定失败,同时消除伪造绕过风险

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 14:41:42 +08:00
hejiayang c7041fa69e fix: 解决用户搜索中HTML转义字符显示问题(漏) 2026-03-31 14:12:18 +08:00
wanghao 370f5e0089 Merge remote-tracking branch 'origin/develop' into develop 2026-03-30 18:29:06 +08:00
hejiayang a47f27967e fix: 防止HTML注入(用户姓名中的 · ),对用户输入姓名进行转义处理
- 在AccountDTO中对doctorName字段进行HTML转义处理
- 在ConDoctorDTO中对doctorName字段进行HTML转义处理
- 在ConEvaluateDTO中对userName和expertName字段进行HTML转义处理
- 在ConHealthInfoAnswerDTO中对fromName字段进行HTML转义处理
- 在ConHelperDTO中对userName字段进行HTML转义处理
- 在ConSessionDTO中对fromName和doctorName字段进行HTML转义处理
- 在CallLogDTO中对realName字段进行HTML转义处理
- 在PhoneListDTO中对realName字段进行HTML转义处理
- 在TblQimoNoticeDTO中对realName字段进行HTML转义处理
- 在EmergencyProfessionUserController中对name参数进行HTML转义处理
- 在OrderServiceImpl中对salvageUserName字段进行HTML转义处理
- 在AbnormalEventFilter中对userName字段进行HTML转义处理
- 在CalorieDataByUserDTO中对realName字段进行HTML转义处理
- 在WatchBindHisServiceImpl中对bindRealName字段进行HTML转义处理
- 在WatchDataServiceImpl中对username字段进行HTML转义处理
- 在WatchDeviceServiceImpl中对bindRealName字段进行HTML转义处理
- 在HealthUserEmployeeExController中对realname字段进行HTML转义处理
- 在SysUserController中对realname字段进行HTML转义处理
- 在SysUserDepartChangeApplyController中对userName参数进行HTML转义处理
- 在SelectWrapperDTO中对realName字段进行HTML转义处理
- 在SysBaseApiImpl中对username参数进行HTML转义处理
- 在SysUserServiceImpl中对name参数进行HTML转义处理
2026-03-30 17:54:36 +08:00
wanghaoandClaude Sonnet 4.6 6c08f5f141 fix(用户管理): 修复不传 realname 时查询用户列表抛 NPE 的问题
对 realname 参数增加非空判断,避免 null 值时调用 replaceAll 抛出 NullPointerException

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 17:22:05 +08:00
lianlonggang 690f688c6a 屏蔽pom文件不需要的配置 2026-03-30 16:07:27 +08:00
wanghaoandClaude Sonnet 4.6 63cc815022 fix(用户管理): 修复用户查询时名字中间隔号被 HTML 实体转义的问题
将查询参数中的 &middot; 转义回 · 后再执行查询

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 14:54:56 +08:00
wanghaoandClaude Sonnet 4.6 8f00d07377 feat(健康咨询): 新增音视频咨询超时关闭功能及定时任务
- 新增 endVideoSession 接口,供手动触发和定时任务调用
- Mapper 层添加 UPDATE SQL:预约日期已过的视频咨询,有通话记录改为待评价(4),无记录改为取消(6)
- SyncScheduleJob 新增 XXL-Job 任务 endVideoSession,每日自动处理过期视频咨询

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 14:54:33 +08:00
wanghaoandClaude Sonnet 4.6 2e90ec71cc fix(手表设备): 手表绑定时校验只能绑定本单位人员
新增单位编码前6位匹配校验,禁止跨单位绑定手表;
同时将"该设备已绑定该员工"改为"该设备已被绑定"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 15:48:55 +08:00
wanghao a43806c4e9 fix(手表设备): 优化错误提示信息,将"该工具不存在"改为"该监测工具不存在" 2026-03-18 14:47:39 +08:00
wanghao 237df3ef38 修改移动端手表绑定接口 2026-03-12 17:28:52 +08:00
wanghao bd9fece99c 新增移动端手表绑定解绑接口 2026-03-12 16:16:58 +08:00
pengjie 47cebd3392 【用户信息】增加返回字段,加密接口 2026-03-06 17:01:49 +08:00
wanghao 61e049cc47 手表数据修改 2026-03-05 17:05:31 +08:00
wanghao ad03177e50 手表数据修改 2026-03-05 17:00:18 +08:00
wanghao 3db3301fe3 手表数据修改 2026-03-05 16:10:31 +08:00
wanghao fa9a186a5e 手表数据修改 2026-03-05 15:53:40 +08:00
wanghao 3cea926a1e 手表接口修改 2026-03-04 17:23:32 +08:00
wanghao fe82afd934 手表接口修改 2026-03-04 15:30:07 +08:00
wanghao 96242b5c00 手表数据返回处理 2026-03-03 17:22:20 +08:00
wanghao 291f6a4eaa 移动端首页手表数据修改 2026-03-03 10:13:15 +08:00
160 changed files with 2380 additions and 690 deletions
@@ -0,0 +1,10 @@
-- QH_WAT_MONITOR_DATA 新增 EVENT_ID事件ID LOCATE_TIME定位时间字段
-- 数据库118-DM 达梦数据库SQL 全大写规范
ALTER TABLE "QH_WAT_MONITOR_DATA" ADD "EVENT_ID" VARCHAR(64) DEFAULT NULL;
ALTER TABLE "QH_WAT_MONITOR_DATA" ADD "LOCATE_TIME" DATETIME DEFAULT NULL;
COMMENT ON COLUMN "QH_WAT_MONITOR_DATA"."EVENT_ID" IS '事件ID';
COMMENT ON COLUMN "QH_WAT_MONITOR_DATA"."LOCATE_TIME" IS '定位时间';
CREATE INDEX "IDX_EVENT_ID" ON "QH_WAT_MONITOR_DATA"("EVENT_ID");
CREATE INDEX "IDX_WATCH_NO_EVENT_ID" ON "QH_WAT_MONITOR_DATA"("WATCH_NO", "EVENT_ID");
@@ -30,6 +30,10 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId> <artifactId>spring-boot-starter-validation</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId> <artifactId>spring-boot-configuration-processor</artifactId>
@@ -25,7 +25,6 @@ import org.springframework.core.task.TaskExecutor;
import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.jdbc.support.JdbcTransactionManager;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.util.StringUtils;
import javax.sql.DataSource; import javax.sql.DataSource;
import java.util.List; import java.util.List;
@@ -126,21 +125,8 @@ public class BatchAutoConfiguration {
@BatchDataSource ObjectProvider<DataSource> batchDataSource, @BatchDataSource ObjectProvider<DataSource> batchDataSource,
BatchProperties properties BatchProperties properties
) { ) {
DataSource dataSourceToUse = batchDataSource.getIfAvailable(() -> dataSource); return new BatchDataSourceScriptDatabaseInitializer(batchDataSource.getIfAvailable(() -> dataSource),
BatchProperties.Jdbc jdbc = properties.getJdbc(); properties.getJdbc());
// 达梦数据库兼容处理:设置platform绕过构造器中的自动类型检测
if (!StringUtils.hasText(jdbc.getPlatform())) {
jdbc.setPlatform("dm");
}
// 重写afterPropertiesSet()跳过SQL脚本初始化:
// 父类会先断言SQL文件存在再检查initializeSchema mode,导致找不到schema-dm.sql时报错
// Batch元数据表已通过数据迁移创建,无需自动建表
return new BatchDataSourceScriptDatabaseInitializer(dataSourceToUse, jdbc) {
@Override
public void afterPropertiesSet() {
// 跳过Batch元数据表的自动建表,防止找不到schema-dm.sql文件报错
}
};
} }
} }
@@ -34,13 +34,6 @@ public class CustomBatchConfigurer extends BasicBatchConfigurer {
this.taskExecutor = taskExecutor; this.taskExecutor = taskExecutor;
} }
@Override
public void initialize() {
// 达梦数据库兼容处理:跳过Spring Batch数据库类型自动检测
// BasicBatchConfigurer.initialize()中DatabaseType.fromProductName()无法识别"DM DBMS"产品名
// 保持父类默认隔离级别ISOLATION_SERIALIZABLEDM8与此兼容
}
@Override @Override
protected JobLauncher createJobLauncher() throws Exception { protected JobLauncher createJobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher(); SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
@@ -99,7 +99,7 @@ public enum AnYanApiEnum {
/** /**
* 18.查询关爱联络员信息及急救人员查询接口 * 18.查询关爱联络员信息及急救人员查询接口
*/ */
QUERY_EMPLOYEE_CARE_PERSON("/aygc-znhpt-sys/0/api/empCareEmp/findPageByIdNo", "", HttpMethod.POST), QUERY_EMPLOYEE_CARE_PERSON("/aygc-znhpt-sys/0/api/empCareEmp/findPage", "", HttpMethod.POST),
/** /**
* 19.批量更新员工关键信息接口 * 19.批量更新员工关键信息接口
@@ -1,5 +1,6 @@
package com.renkang.anyan.model.dto; package com.renkang.anyan.model.dto;
import cn.hutool.core.date.DateUtil;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@@ -34,4 +35,6 @@ public class CareUserDetailsParam {
@Schema(title = "pageType") @Schema(title = "pageType")
private String pageType = "plus"; private String pageType = "plus";
private int year = DateUtil.thisYear();
} }
@@ -11,18 +11,19 @@
a.icon, a.icon,
a.points, a.points,
CASE CASE
WHEN a.frequency = 1 THEN WHEN a.frequency = 1 THEN -- 单次
CASE WHEN COUNT(b.id) > 0 THEN 1 ELSE 0 END IF(COUNT(b.id) > 0, 1, 0)
WHEN a.frequency = 2 THEN WHEN a.frequency = 2 THEN -- 日/次
CASE WHEN COUNT(CASE WHEN TRUNC(b.create_time) = TRUNC(SYSDATE) THEN 1 END) > 0 THEN 1 ELSE 0 END IF(COUNT(CASE WHEN DATE(b.create_time) = CURDATE() THEN 1 END) > 0, 1, 0)
WHEN a.frequency = 3 THEN WHEN a.frequency = 3 THEN -- 周/次
CASE WHEN COUNT(CASE WHEN TO_CHAR(b.create_time, 'IYYY-IW') = TO_CHAR(SYSDATE, 'IYYY-IW') THEN 1 END) > 0 THEN 1 ELSE 0 END IF(COUNT(CASE WHEN YEARWEEK(b.create_time, 1) = YEARWEEK(CURDATE(), 1) THEN 1 END) > 0, 1, 0)
WHEN a.frequency = 4 THEN WHEN a.frequency = 4 THEN -- 月/次
CASE WHEN COUNT(CASE WHEN TO_CHAR(b.create_time, 'YYYY-MM') = TO_CHAR(SYSDATE, 'YYYY-MM') THEN 1 END) > 0 THEN 1 ELSE 0 END IF(COUNT(CASE WHEN DATE_FORMAT(b.create_time, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m') THEN 1 END) > 0, 1, 0)
WHEN a.frequency = 5 THEN WHEN a.frequency = 5 THEN -- 季度/次
CASE WHEN COUNT(CASE WHEN TO_CHAR(b.create_time, 'Q') = TO_CHAR(SYSDATE, 'Q') AND EXTRACT(YEAR FROM b.create_time) = EXTRACT(YEAR FROM SYSDATE) THEN 1 END) > 0 THEN 1 ELSE 0 END IF(COUNT(CASE WHEN QUARTER(b.create_time) = QUARTER(CURDATE()) AND YEAR(b.create_time) = YEAR(CURDATE()) THEN 1
WHEN a.frequency = 6 THEN END) > 0, 1, 0)
CASE WHEN COUNT(CASE WHEN EXTRACT(YEAR FROM b.create_time) = EXTRACT(YEAR FROM SYSDATE) THEN 1 END) > 0 THEN 1 ELSE 0 END WHEN a.frequency = 6 THEN -- 年/次
IF(COUNT(CASE WHEN YEAR(b.create_time) = YEAR(CURDATE()) THEN 1 END) > 0, 1, 0)
ELSE 0 ELSE 0
END AS clockInStatus END AS clockInStatus
FROM FROM
@@ -459,7 +459,7 @@ public class UserPointsServiceImpl extends ServiceImpl<UserPointsMapper, UserPoi
List<UserPointsDetails> details = userPointsDetailsMapper.selectList(new LambdaQueryWrapper<UserPointsDetails>() List<UserPointsDetails> details = userPointsDetailsMapper.selectList(new LambdaQueryWrapper<UserPointsDetails>()
.eq(UserPointsDetails::getUserId, userId) .eq(UserPointsDetails::getUserId, userId)
.eq(UserPointsDetails::getChangeType, HealthBankConstants.CHANGE_TYPE_ADD) .eq(UserPointsDetails::getChangeType, HealthBankConstants.CHANGE_TYPE_ADD)
.apply("TO_CHAR(create_time, 'YYYY-MM-DD') = {0}", DateUtil.today()) .apply("DATE_FORMAT(create_time, '%Y-%m-%d') = {0}", DateUtil.today())
); );
double sum = details.stream().map(UserPointsDetails::getPoints).mapToDouble(BigDecimal::doubleValue).sum(); double sum = details.stream().map(UserPointsDetails::getPoints).mapToDouble(BigDecimal::doubleValue).sum();
userPoints.setLatestAddDaySum(BigDecimal.valueOf(sum).add(pointsRule.getPoints())); userPoints.setLatestAddDaySum(BigDecimal.valueOf(sum).add(pointsRule.getPoints()));
@@ -1,5 +1,6 @@
package com.renkang.consultation.dto; package com.renkang.consultation.dto;
import cn.hutool.http.HtmlUtil;
import com.renkang.consultation.entity.ConPage; import com.renkang.consultation.entity.ConPage;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@@ -11,6 +12,10 @@ public class AccountDTO extends ConPage {
@Schema(title = "专家姓名") @Schema(title = "专家姓名")
private String doctorName; private String doctorName;
public void setDoctorName(String doctorName) {
this.doctorName = doctorName != null ? HtmlUtil.unescape(doctorName) : null;
}
@Schema(title = "医院选择") @Schema(title = "医院选择")
private String hospitalName; private String hospitalName;
@@ -1,5 +1,6 @@
package com.renkang.consultation.dto; package com.renkang.consultation.dto;
import cn.hutool.http.HtmlUtil;
import com.renkang.consultation.entity.ConPage; import com.renkang.consultation.entity.ConPage;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@@ -10,6 +11,10 @@ public class ConDoctorDTO extends ConPage {
@Schema(title = "专家姓名") @Schema(title = "专家姓名")
private String doctorName; private String doctorName;
public void setDoctorName(String doctorName) {
this.doctorName = doctorName != null ? HtmlUtil.unescape(doctorName) : null;
}
@Schema(title = "专家编号") @Schema(title = "专家编号")
private String doctorNo; private String doctorNo;
@@ -1,5 +1,6 @@
package com.renkang.consultation.dto; package com.renkang.consultation.dto;
import cn.hutool.http.HtmlUtil;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.renkang.consultation.entity.ConPage; import com.renkang.consultation.entity.ConPage;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
@@ -17,6 +18,9 @@ public class ConEvaluateDTO extends ConPage {
@Schema(title = "咨询人") @Schema(title = "咨询人")
private String userName; private String userName;
public void setUserName(String userName) {
this.userName = userName != null ? HtmlUtil.unescape(userName) : null;
}
@Schema(title = "二级单位id") @Schema(title = "二级单位id")
private String sysOrgSecondId; private String sysOrgSecondId;
@@ -27,6 +31,10 @@ public class ConEvaluateDTO extends ConPage {
@Schema(title = "咨询专家") @Schema(title = "咨询专家")
private String expertName; private String expertName;
public void setExpertName(String expertName) {
this.expertName = expertName != null ? HtmlUtil.unescape(expertName) : null;
}
@Schema(title = "专家医院") @Schema(title = "专家医院")
private String expertHospital; private String expertHospital;
@@ -1,5 +1,6 @@
package com.renkang.consultation.dto; package com.renkang.consultation.dto;
import cn.hutool.http.HtmlUtil;
import com.renkang.consultation.entity.ConPage; import com.renkang.consultation.entity.ConPage;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@@ -10,6 +11,10 @@ public class ConHealthInfoAnswerDTO extends ConPage {
@Schema(title = "员工姓名") @Schema(title = "员工姓名")
private String fromName; private String fromName;
public void setFromName(String fromName) {
this.fromName = fromName != null ? HtmlUtil.unescape(fromName) : null;
}
@Schema(title = "手机号") @Schema(title = "手机号")
private String phone; private String phone;
@@ -1,5 +1,6 @@
package com.renkang.consultation.dto; package com.renkang.consultation.dto;
import cn.hutool.http.HtmlUtil;
import com.renkang.consultation.entity.ConPage; import com.renkang.consultation.entity.ConPage;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@@ -11,6 +12,10 @@ public class ConHelperDTO extends ConPage {
@Schema(title = "全科医生姓名") @Schema(title = "全科医生姓名")
private String userName; private String userName;
public void setUserName(String userName) {
this.userName = userName != null ? HtmlUtil.unescape(userName) : null;
}
@Schema(title = "状态") @Schema(title = "状态")
private Integer status; private Integer status;
@@ -1,5 +1,6 @@
package com.renkang.consultation.dto; package com.renkang.consultation.dto;
import cn.hutool.http.HtmlUtil;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.renkang.consultation.entity.ConPage; import com.renkang.consultation.entity.ConPage;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
@@ -17,6 +18,10 @@ public class ConSessionDTO extends ConPage {
@Schema(title = "员工姓名") @Schema(title = "员工姓名")
private String fromName; private String fromName;
public void setFromName(String fromName) {
this.fromName = fromName != null ? HtmlUtil.unescape(fromName) : null;
}
@Schema(title = "员工id") @Schema(title = "员工id")
private String fromAccount; private String fromAccount;
@@ -26,6 +31,10 @@ public class ConSessionDTO extends ConPage {
@Schema(title = "专家姓名") @Schema(title = "专家姓名")
private String doctorName; private String doctorName;
public void setDoctorName(String doctorName) {
this.doctorName = doctorName != null ? HtmlUtil.unescape(doctorName) : null;
}
@Schema(title = "咨询状态(0待确认 1接收预约 2拒绝预约 3已过期 4已取消 5咨询中 6专家咨询结束 7员工咨询结束 8超时自动结束)") @Schema(title = "咨询状态(0待确认 1接收预约 2拒绝预约 3已过期 4已取消 5咨询中 6专家咨询结束 7员工咨询结束 8超时自动结束)")
private String contentStatus; private String contentStatus;
@@ -77,7 +77,7 @@ public class ConSessionView implements Serializable {
@TableField(value = "medical_records_id") @TableField(value = "medical_records_id")
@Schema(description = "") @Schema(description = "")
private String medicalRecordsId; private String medicalRecordsId;
@TableField(value = "status") @TableField(value = "`status`")
@Schema(description = "") @Schema(description = "")
private Integer status; private Integer status;
@TableField(value = "del_flag") @TableField(value = "del_flag")
@@ -480,4 +480,10 @@ public class ConSessionApiController {
return conSessionApiService.insertUserAndHelperSessionNew(); return conSessionApiService.insertUserAndHelperSessionNew();
} }
@Operation(summary = "超时关闭视频咨询", description = "超时关闭视频咨询")
@GetMapping("/endVideoSession")
public Result<String> endVideoSession() {
return Result.ok(conSessionApiService.endVideoSession());
}
} }
@@ -115,4 +115,6 @@ public interface ConSessionApiService {
UserSessionCount countForUser(); UserSessionCount countForUser();
String endVideoSession();
} }
@@ -2114,4 +2114,8 @@ public class ConSessionApiServiceImpl implements ConSessionApiService {
return conSessionMapper.selectCount(wrapper).intValue(); return conSessionMapper.selectCount(wrapper).intValue();
} }
public String endVideoSession() {
return conSessionMapper.endVideoSession();
}
} }
@@ -27,7 +27,7 @@ public interface ConDepartmentMapper extends BaseMapper<ConDepartment> , MPJBase
@Select("SELECT * FROM con_department WHERE status = '1' and del_flag = '0' and id = #{departmentId} order by tf_top desc,sort") @Select("SELECT * FROM con_department WHERE status = '1' and del_flag = '0' and id = #{departmentId} order by tf_top desc,sort")
public ConDepartment selectDepartmentNameById(String departmentId); public ConDepartment selectDepartmentNameById(String departmentId);
@Select("SELECT LISTAGG(id, ',') WITHIN GROUP (ORDER BY id) FROM con_department WHERE status = '1' and del_flag = '0' and officeparid = #{departmentId}") @Select("SELECT GROUP_CONCAT(id) FROM con_department WHERE status = '1' and del_flag = '0' and officeparid = #{departmentId}")
public String selectDepartmentIdByLevelOneId(String departmentId); public String selectDepartmentIdByLevelOneId(String departmentId);
@Select("SELECT count(1) FROM con_department WHERE status = '1' and del_flag = '0' and office_level = 1") @Select("SELECT count(1) FROM con_department WHERE status = '1' and del_flag = '0' and office_level = 1")
@@ -117,7 +117,7 @@ public interface ConDoctorMapper extends BaseMapper<ConDoctor> , MPJBaseMapper<C
*/ */
List<ConDoctor> getFreeDoctor(CondepartmentId departmentId); List<ConDoctor> getFreeDoctor(CondepartmentId departmentId);
@Select("select id,sicks_name as sicksName from con_sicks where status = 1 and del_flag = 0 and INSTR(',' || #{sickIds} || ',', ',' || id || ',') > 0") @Select("select id,sicks_name as sicksName from con_sicks where status = 1 and del_flag = 0 and FIND_IN_SET(id,#{sickIds})")
List<Map<String, String>> selectSickName(String sickIds); List<Map<String, String>> selectSickName(String sickIds);
@Select("SELECT * FROM con_doctor WHERE status = '1' AND del_flag = '0'") @Select("SELECT * FROM con_doctor WHERE status = '1' AND del_flag = '0'")
@@ -136,11 +136,11 @@ public interface ConDoctorMapper extends BaseMapper<ConDoctor> , MPJBaseMapper<C
@Update("update con_doctor set audio_status = #{audioStatus},tf_jump_holiday= #{tfJumpHoliday} WHERE status = '1' and del_flag = '0' and id = #{id}") @Update("update con_doctor set audio_status = #{audioStatus},tf_jump_holiday= #{tfJumpHoliday} WHERE status = '1' and del_flag = '0' and id = #{id}")
int updateAudioStatus(String id, String audioStatus, String tfJumpHoliday); int updateAudioStatus(String id, String audioStatus, String tfJumpHoliday);
@Select("select count(1) from con_doctor where del_flag = '0' AND status = 1 and doctor_status != 3 AND INSTR(',' || #{sickId} || ',', ',' || good_at_sickness || ',') > 0") @Select("select count(1) from con_doctor where del_flag = '0' AND status = 1 and doctor_status != 3 AND FIND_IN_SET(#{sickId},good_at_sickness)")
int selectDoctorNumBySickId(String sickId); int selectDoctorNumBySickId(String sickId);
@Select("select count(1) from con_doctor where del_flag = '0' AND status = 1 AND doctor_status != 3 AND INSTR(',' || #{departmentId} || ',', ',' || department_id || ',') > 0") @Select("select count(1) from con_doctor where del_flag = '0' AND status = 1 AND doctor_status != 3 AND FIND_IN_SET(department_id,#{departmentId})")
int selectDoctorNumByDepartmentId(String departmentId); int selectDoctorNumByDepartmentId(String departmentId);
List<ConDoctor> selectListByQuery(@Param("conDoctor") ConDoctor conDoctor); List<ConDoctor> selectListByQuery(@Param("conDoctor") ConDoctor conDoctor);
@@ -170,7 +170,7 @@ public interface ConDoctorMapper extends BaseMapper<ConDoctor> , MPJBaseMapper<C
@Select("select count(1) from con_doctor where del_flag = '0' AND status = 1 AND INSTR(',' || #{departmentId} || ',', ',' || department_id || ',') > 0 and resource_id = #{resourceId} and doctor_status != 3") @Select("select count(1) from con_doctor where del_flag = '0' AND status = 1 AND FIND_IN_SET(department_id,#{departmentId}) and resource_id = #{resourceId} and doctor_status != 3")
int selectDoctorNumByDepartmentIdAndResourceId(String departmentId,String resourceId); int selectDoctorNumByDepartmentIdAndResourceId(String departmentId,String resourceId);
@@ -20,7 +20,7 @@ public interface ConDoctorSchedulingDateMapper extends BaseMapper<ConDoctorSched
IPage<ConDoctorSchedulingDate> queryPageList(IPage<ConDoctorSchedulingDate> page, @Param("conDoctorSchedulingDate") ConDoctorSchedulingDate conDoctorSchedulingDate); IPage<ConDoctorSchedulingDate> queryPageList(IPage<ConDoctorSchedulingDate> page, @Param("conDoctorSchedulingDate") ConDoctorSchedulingDate conDoctorSchedulingDate);
@Select("SELECT * FROM con_doctor_scheduling_date WHERE status = '1' and del_flag = '0' and user_id = #{doctorId} and scheduling_date >= TO_CHAR(SYSDATE,'YYYY-MM-DD') order by scheduling_date") @Select("SELECT * FROM con_doctor_scheduling_date WHERE status = '1' and del_flag = '0' and user_id = #{doctorId} and scheduling_date >= DATE_FORMAT(SYSDATE(),'%Y-%m-%d') order by scheduling_date")
public List<ConDoctorSchedulingDateListDO> selectDoctorById(String doctorId); public List<ConDoctorSchedulingDateListDO> selectDoctorById(String doctorId);
@Select("SELECT * FROM con_doctor_scheduling_date WHERE status = '1' and del_flag = '0' and id = #{id}") @Select("SELECT * FROM con_doctor_scheduling_date WHERE status = '1' and del_flag = '0' and id = #{id}")
@@ -34,11 +34,11 @@ public interface ConDoctorSchedulingDateMapper extends BaseMapper<ConDoctorSched
public int updateScheduleAddMinus(String id); public int updateScheduleAddMinus(String id);
@Select("SELECT * FROM con_doctor_scheduling_date WHERE status = '1' and del_flag = '0' and user_id = #{doctorId} and scheduling_date >= TO_CHAR(#{schedulingDate},'YYYY-MM-DD')") @Select("SELECT * FROM con_doctor_scheduling_date WHERE status = '1' and del_flag = '0' and user_id = #{doctorId} and scheduling_date >= DATE_FORMAT(#{schedulingDate},'%Y-%m-%d')")
public List<ConDoctorSchedulingDateListDO> selectDoctorScheduleDateById(String doctorId, Date schedulingDate); public List<ConDoctorSchedulingDateListDO> selectDoctorScheduleDateById(String doctorId, Date schedulingDate);
@Select("SELECT * FROM con_doctor_scheduling_date WHERE status = '1' and del_flag = '0' and user_id = #{userId} and scheduling_date >= TRUNC(SYSDATE) and week = #{week}") @Select("SELECT * FROM con_doctor_scheduling_date WHERE status = '1' and del_flag = '0' and user_id = #{userId} and scheduling_date >= DATE(NOW()) and week = #{week}")
public List<ConDoctorSchedulingDateListDO> selectDoctorSchedulingByWeekAndUserId(String userId, String week); public List<ConDoctorSchedulingDateListDO> selectDoctorSchedulingByWeekAndUserId(String userId, String week);
@@ -46,7 +46,7 @@ public interface ConDoctorSchedulingDateMapper extends BaseMapper<ConDoctorSched
public int updateScheduleNum(String schedulingNum, String id); public int updateScheduleNum(String schedulingNum, String id);
@Select("SELECT * FROM con_doctor_scheduling_date WHERE status = '1' and del_flag = '0' and user_id = #{doctorId} and scheduling_date = TO_CHAR(#{schedulingDate},'YYYY-MM-DD') and type = #{type}") @Select("SELECT * FROM con_doctor_scheduling_date WHERE status = '1' and del_flag = '0' and user_id = #{doctorId} and scheduling_date = DATE_FORMAT(#{schedulingDate},'%Y-%m-%d') and type = #{type}")
public List<ConDoctorSchedulingDateListDO> selectDoctorScheduleDate(String doctorId, Date schedulingDate, String type); public List<ConDoctorSchedulingDateListDO> selectDoctorScheduleDate(String doctorId, Date schedulingDate, String type);
Boolean insertBatchSomeColumn(@Param("list") List<ConDoctorSchedulingDate> list); Boolean insertBatchSomeColumn(@Param("list") List<ConDoctorSchedulingDate> list);
@@ -56,8 +56,8 @@ public interface ConResourceMapper extends BaseMapper<ConResource> {
List<HospitalDepartment> selectResourceInfoByDepartId(@Param("idList") List<String> idList); List<HospitalDepartment> selectResourceInfoByDepartId(@Param("idList") List<String> idList);
@Select("SELECT c.id,c.resource_name as resourceName FROM con_resource c WHERE EXISTS (SELECT 1 FROM con_doctor d WHERE c.id = d.resource_id and d.del_flag = 0 and d.status = 1)" + @Select("SELECT c.id,c.resource_name as resourceName FROM con_resource c WHERE EXISTS (SELECT 1 FROM con_doctor d WHERE c.id = d.resource_id and d.del_flag = 0 and d.`status` = 1)" +
"and c.del_flag = 0 and c.status = 1 ORDER BY c.tf_top DESC,c.sort") "and c.del_flag = 0 and c.`status` = 1 ORDER BY c.tf_top DESC,c.sort")
public List<ConResourceDO> selectHospitalListVersionTwo(); public List<ConResourceDO> selectHospitalListVersionTwo();
@@ -20,7 +20,7 @@ public interface ConServiceMapper extends BaseMapper<ConService> {
ConService selectConServiceByDoctrId(String doctorId); ConService selectConServiceByDoctrId(String doctorId);
@Select("select count(1) from con_service where service_status = 0 and doctor_id = #{doctorId} and del_flag = 0 and status = 1 and TO_CHAR(#{scheduleDate}, 'YYYY-MM-DD') >= TO_CHAR(start_day, 'YYYY-MM-DD') and TO_CHAR(#{scheduleDate}, 'YYYY-MM-DD') <= TO_CHAR(end_day, 'YYYY-MM-DD')") @Select("select count(1) from con_service where service_status = 0 and doctor_id = #{doctorId} and del_flag = 0 and status = 1 and DATE_FORMAT(#{scheduleDate}, '%Y-%m-%d') >= DATE_FORMAT(start_day, '%Y-%m-%d') and DATE_FORMAT(#{scheduleDate}, '%Y-%m-%d') <= DATE_FORMAT(end_day, '%Y-%m-%d')")
int selectConServiceByDoctrIdExist(String doctorId, Date scheduleDate); int selectConServiceByDoctrIdExist(String doctorId, Date scheduleDate);
} }
@@ -114,24 +114,24 @@ public interface ConSessionMapper extends BaseMapper<ConSession> , MPJBaseMapper
@Select("select * from con_session where im_id = #{imId} and to_account = #{toAccount} and del_flag = 0 and status = 1") @Select("select * from con_session where im_id = #{imId} and to_account = #{toAccount} and del_flag = 0 and status = 1")
ConSession selectConSessionByImId(String imId, String toAccount); ConSession selectConSessionByImId(String imId, String toAccount);
@Update("update con_session set reply_time = SYSDATE where im_id = #{imId}") @Update("update con_session set reply_time = NOW() where im_id = #{imId}")
int updateSessionReplyTime(String imId); int updateSessionReplyTime(String imId);
@Select("select * from con_session where im_id = #{imId} and del_flag = 0 and status = 1") @Select("select * from con_session where im_id = #{imId} and del_flag = 0 and status = 1")
ConSession selectConSessionByImIdOnly(String imId); ConSession selectConSessionByImIdOnly(String imId);
@Update("update con_session set content_status = 4 where (SYSDATE - CAST(reply_time AS DATE)) * 24 >= 4 and content_status = 3 and content_type = 1") @Update("update con_session set content_status = 4 where TIMESTAMPDIFF(HOUR,reply_time,now()) >= 4 and content_status = 3 and content_type = 1")
int sessionSendMessageExpire(); int sessionSendMessageExpire();
@Update("update con_session set content_status = 8 where (SYSDATE - CAST(create_time AS DATE)) * 24 >= 24 and content_type = 1 and (content_status = 1 or content_status = 2)") @Update("update con_session set content_status = 8 where TIMESTAMPDIFF(HOUR,create_time,now()) >= 24 and content_type = 1 and (content_status = 1 or content_status = 2)")
int sessionSendMessageExpireAnother(); int sessionSendMessageExpireAnother();
@Update("update con_session set content_status = 8 where TRUNC(SYSDATE) > session_date and content_type = 2 and (content_status = 1 or content_status = 2)") @Update("update con_session set content_status = 8 where DATE(NOW()) > session_date and content_type = 2 and (content_status = 1 or content_status = 2)")
int sessionSendMessageExpireVideo(); int sessionSendMessageExpireVideo();
@Update("update con_session set content_status = 4 where TRUNC(SYSDATE) > session_date and content_type = 2 and content_status = 3 ") @Update("update con_session set content_status = 4 where DATE(NOW()) > session_date and content_type = 2 and content_status = 3 ")
int sessionSendMessageExpireVideoAnother(); int sessionSendMessageExpireVideoAnother();
@Select("select * from con_session where del_flag = 0 and status = 1 and from_account = #{fromAccount} and session_type = #{sessionType} and content_status = 3 limit 1") @Select("select * from con_session where del_flag = 0 and status = 1 and from_account = #{fromAccount} and session_type = #{sessionType} and content_status = 3 limit 1")
@@ -178,7 +178,7 @@ public interface ConSessionMapper extends BaseMapper<ConSession> , MPJBaseMapper
* *
* @return * @return
*/ */
@Update("update con_session set content_status = 5 where session_type != 1 and content_status = 3 and (SYSDATE - CAST(reply_time AS DATE)) * 24 >= #{expireHour} and tf_reply = 1") @Update("update con_session set content_status = 5 where session_type != 1 and content_status = 3 and timestampdiff(HOUR,reply_time,NOW()) >= #{expireHour} and tf_reply = 1")
int changeEndUserAndProfessiorHelper(String expireHour); int changeEndUserAndProfessiorHelper(String expireHour);
/** /**
@@ -186,7 +186,7 @@ public interface ConSessionMapper extends BaseMapper<ConSession> , MPJBaseMapper
* *
* @return * @return
*/ */
@Update("update con_session set content_status = 4 where session_type = 1 and content_type = 1 and content_status = 3 and (SYSDATE - CAST(reply_time AS DATE)) * 24 >= #{expireHour} and tf_reply = 1") @Update("update con_session set content_status = 4 where session_type = 1 and content_type = 1 and content_status = 3 and timestampdiff(HOUR,reply_time,NOW()) >= #{expireHour} and tf_reply = 1")
int endSession(String expireHour); int endSession(String expireHour);
/** /**
@@ -194,7 +194,7 @@ public interface ConSessionMapper extends BaseMapper<ConSession> , MPJBaseMapper
* *
* @return * @return
*/ */
@Update("update con_session set content_status = 8 where content_type != 2 and (SYSDATE - CAST(create_time AS DATE)) * 24 >= #{expireHour} and tf_reply = 0") @Update("update con_session set content_status = 8 where content_type != 2 and timestampdiff(HOUR,create_time,NOW()) >= #{expireHour} and tf_reply = 0")
int expireMeaaage(String expireHour); int expireMeaaage(String expireHour);
@@ -244,7 +244,7 @@ public interface ConSessionMapper extends BaseMapper<ConSession> , MPJBaseMapper
ConSession selectConSessionByImIdOnlyBackUp(String imId); ConSession selectConSessionByImIdOnlyBackUp(String imId);
@Update("update con_session_qh set reply_time = SYSDATE where im_id = #{imId}") @Update("update con_session_qh set reply_time = NOW() where im_id = #{imId}")
int updateSessionReplyTimeBackUp(String imId); int updateSessionReplyTimeBackUp(String imId);
@Update("update con_session_qh set tf_reply = 1 where id = #{id}") @Update("update con_session_qh set tf_reply = 1 where id = #{id}")
@@ -282,7 +282,7 @@ public interface ConSessionMapper extends BaseMapper<ConSession> , MPJBaseMapper
List<ConSessionDO> selectSessionListByUserIdHelperAnother(IPage<ConSessionDO> page, @Param("contentType") String contentType, @Param("state") String state, @Param("userId") String userId); List<ConSessionDO> selectSessionListByUserIdHelperAnother(IPage<ConSessionDO> page, @Param("contentType") String contentType, @Param("state") String state, @Param("userId") String userId);
@Select("select * from con_session where session_type = 1 and content_type = 1 and content_status = 3 and (SYSDATE - CAST(reply_time AS DATE)) * 24 >= #{expireHour} and tf_reply = 1") @Select("select * from con_session where session_type = 1 and content_type = 1 and content_status = 3 and timestampdiff(HOUR,reply_time,NOW()) >= #{expireHour} and tf_reply = 1")
List<ConSession> selectEndSession(String expireHour); List<ConSession> selectEndSession(String expireHour);
@@ -294,4 +294,13 @@ public interface ConSessionMapper extends BaseMapper<ConSession> , MPJBaseMapper
@Param("doctorjob")String doctorjob, @Param("doctorjob")String doctorjob,
@Param("contentType")String contentType, @Param("contentType")String contentType,
@Param("toAccount")String toAccount); @Param("toAccount")String toAccount);
/**
* 音视频咨询过期处理:预约日期已过的视频咨询,有通话记录则改为待评价,无通话记录则改为取消
* content_status: 4=待评价,6=取消
*/
@Update("UPDATE con_session SET content_status = CASE WHEN session_time IS NOT NULL THEN 4 ELSE 6 END " +
"WHERE content_type = 2 AND CURDATE() > session_date " +
"AND content_status NOT IN (4, 5, 6, 7, 8) AND del_flag = 0 AND status = 1")
String endVideoSession();
} }
@@ -55,11 +55,11 @@ public interface ConSicksMapper extends BaseMapper<ConSicks> {
List<ConSicks> selectListByIdList(@Param("idList") List<String> idList); List<ConSicks> selectListByIdList(@Param("idList") List<String> idList);
@Select("select count(1) from con_sicks where del_flag = 0 and status = 1 and INSTR(',' || #{departmentId} || ',', ',' || department_id || ',') > 0") @Select("select count(1) from con_sicks where del_flag = 0 and status = 1 and FIND_IN_SET(department_id,#{departmentId})")
int selectSickNumByDepartment(String departmentId); int selectSickNumByDepartment(String departmentId);
@Select("select id from con_sicks where del_flag = 0 and status = 1 and INSTR(',' || #{departmentId} || ',', ',' || department_id || ',') > 0") @Select("select id from con_sicks where del_flag = 0 and status = 1 and FIND_IN_SET(department_id,#{departmentId})")
List<String> selectSickNumByDepartmentByDepartment(String departmentId); List<String> selectSickNumByDepartmentByDepartment(String departmentId);
@@ -71,11 +71,11 @@ public interface ConSicksMapper extends BaseMapper<ConSicks> {
List<ConSicks> selectSickByTopAndHaveDoctor(); List<ConSicks> selectSickByTopAndHaveDoctor();
@Select("select id,department_id as departmentId,sicks_name as sicksName,descript from con_sicks where del_flag = 0 and status = 1 and INSTR(',' || #{departmentId} || ',', ',' || department_id || ',') > 0 order by tf_top desc,sort") @Select("select id,department_id as departmentId,sicks_name as sicksName,descript from con_sicks where del_flag = 0 and status = 1 and FIND_IN_SET(department_id,#{departmentId}) order by tf_top desc,sort")
List<ConSicksDO> selectSickListByDepartment(String departmentId); List<ConSicksDO> selectSickListByDepartment(String departmentId);
@Select("select LISTAGG(id, ',') WITHIN GROUP (ORDER BY id) from con_sicks where department_id = #{departmentId}") @Select("select GROUP_CONCAT(id) from con_sicks where department_id = #{departmentId}")
String selectSickListByDepartmentIdAnother(String departmentId); String selectSickListByDepartmentIdAnother(String departmentId);
@Update("update con_sicks set department_id = #{departmentOne} where department_id = #{departmentTwo}") @Update("update con_sicks set department_id = #{departmentOne} where department_id = #{departmentTwo}")
@@ -73,7 +73,7 @@
and cct.operate_type = '5' and cct.operate_type = '5'
</if> </if>
<if test='date != "1"'> <if test='date != "1"'>
and TO_CHAR(cct.income_time, 'YYYY-MM')=#{date} and DATE_FORMAT(cct.income_time, '%Y-%m')=#{date}
</if> </if>
<if test="userId != null and userId != ''"> <if test="userId != null and userId != ''">
and cct.user_id = #{userId} and cct.user_id = #{userId}
@@ -87,8 +87,8 @@
FROM con_session cs FROM con_session cs
where cs.content_type is not null where cs.content_type is not null
and cs.content_type &lt;&gt; '4' and cs.content_type &lt;&gt; '4'
and TO_CHAR(cs.create_time, 'YYYY-MM') = #{date} and DATE_FORMAT(cs.create_time, '%Y-%m') = #{date}
group by cs.content_type, TO_CHAR(cs.create_time, 'YYYY-MM') group by cs.content_type, DATE_FORMAT(cs.create_time, '%Y-%m')
</select> </select>
@@ -99,7 +99,7 @@
and cs.content_type &lt;&gt; '4' and cs.content_type &lt;&gt; '4'
and cs.to_account = #{userId} and session_type = 1 and cs.to_account = #{userId} and session_type = 1
<if test="date != null and date != ''"> <if test="date != null and date != ''">
and TO_CHAR(cs.create_time, 'YYYY-MM') = #{date} and DATE_FORMAT(cs.create_time, '%Y-%m') = #{date}
</if> </if>
group by cs.content_type, session_status group by cs.content_type, session_status
</select> </select>
@@ -108,7 +108,7 @@
from con_cost_statistics ccs from con_cost_statistics ccs
<where> <where>
<if test='conCostStatistics.startDate != null and conCostStatistics.endDate != null'> <if test='conCostStatistics.startDate != null and conCostStatistics.endDate != null'>
and ccs.income_time between TRUNC(#{conCostStatistics.startDate}) and TRUNC(#{conCostStatistics.endDate}) + 1 - 1/86400 and ccs.income_time between DATE_FORMAT(#{conCostStatistics.startDate}, '%Y-%m-%d 00:00:00') and DATE_FORMAT(#{conCostStatistics.endDate}, '%Y-%m-%d 23:59:59')
</if> </if>
<if test='conCostStatistics.operateType != null and conCostStatistics.operateType != "" and conCostStatistics.operateType == "0"'> <if test='conCostStatistics.operateType != null and conCostStatistics.operateType != "" and conCostStatistics.operateType == "0"'>
and ccs.operate_type != '5' and ccs.operate_type != '5'
@@ -172,7 +172,7 @@
and content_status &gt; 3 and content_status &gt; 3
</if> </if>
<if test="date != null and date != ''"> <if test="date != null and date != ''">
and TO_CHAR(create_time, 'YYYY-MM') = #{date} and DATE_FORMAT(create_time, '%Y-%m') = #{date}
</if> </if>
</select> </select>
<select id="selectByDoctorIds" resultType="com.renkang.consultation.entity.ConCostStatistics"> <select id="selectByDoctorIds" resultType="com.renkang.consultation.entity.ConCostStatistics">
@@ -74,7 +74,7 @@
where status = 1 where status = 1
and del_flag = 0 and del_flag = 0
<if test="officeparid == null"> <if test="officeparid == null">
and NVL(officeparid,'') = '' and ifnull(officeparid,'') = ''
</if> </if>
<if test="officeparid != null"> <if test="officeparid != null">
and officeparid = #{officeparid} and officeparid = #{officeparid}
@@ -97,16 +97,25 @@
order by tf_top desc, sort order by tf_top desc, sort
</select> </select>
<select id="selectChildAll" resultType="com.renkang.consultation.entity.ConDepartment"> <select id="selectChildAll" resultType="com.renkang.consultation.entity.ConDepartment">
SELECT * FROM con_department SELECT *
WHERE id != #{departmentId} FROM (
START WITH id = #{departmentId} SELECT d1.*,
CONNECT BY PRIOR id = officeparid @pv := CONCAT(@pv, ',', d1.id) AS path
ORDER BY LEVEL, id FROM
con_department AS d1
JOIN
(SELECT @pv := #{departmentId}) AS initial
WHERE
FIND_IN_SET(d1.officeparid
, @pv)
> 0
) AS subquery
ORDER BY LENGTH(path)
</select> </select>
<select id="getOneDepartList" resultType="com.renkang.consultation.entity.ConDepartment"> <select id="getOneDepartList" resultType="com.renkang.consultation.entity.ConDepartment">
SELECT * SELECT *
FROM con_department FROM `con_department`
WHERE office_level = 1 WHERE office_level = 1
and del_flag = 0 and del_flag = 0
and status = 1 and status = 1
@@ -114,7 +123,7 @@
<select id="getTwoDepartList" resultType="com.renkang.consultation.entity.ConDepartment"> <select id="getTwoDepartList" resultType="com.renkang.consultation.entity.ConDepartment">
SELECT * SELECT *
FROM con_department FROM `con_department`
WHERE office_level = 2 WHERE office_level = 2
and del_flag = 0 and del_flag = 0
and status = 1 and status = 1
@@ -124,10 +133,10 @@
SELECT * SELECT *
from con_doctor from con_doctor
where department_id in where department_id in
(SELECT id FROM con_department WHERE office_level in (1, 2) and del_flag = 0 and status = 1) (SELECT id FROM `con_department` WHERE office_level in (1, 2) and del_flag = 0 and status = 1)
and del_flag = 0 and del_flag = 0
and status = 1 and status = 1
ORDER BY doctor_status DESC ORDER BY doctor_status DESC;
</select> </select>
<select id="selectChildById" resultType="com.renkang.consultation.entity.ConDepartment"> <select id="selectChildById" resultType="com.renkang.consultation.entity.ConDepartment">
@@ -165,7 +174,7 @@
(case when (select count(1) from con_department cd2 where cd2.officeparid = cdd.id)>0 then 0 else 1 end) as isLeaf, (case when (select count(1) from con_department cd2 where cd2.officeparid = cdd.id)>0 then 0 else 1 end) as isLeaf,
officeparid as parentId officeparid as parentId
from con_department cdd from con_department cdd
where CASE WHEN (officeparid IS NULL OR officeparid = '') THEN '0' ELSE officeparid END = #{pid} where if(officeparid is null or officeparid = '','0',officeparid) = #{pid}
</select> </select>
@@ -2,31 +2,31 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.renkang.consultation.mapper.ConHelperSchedulingHistoryMapper"> <mapper namespace="com.renkang.consultation.mapper.ConHelperSchedulingHistoryMapper">
<select id="queryPageList" resultType="com.renkang.consultation.entity.ConHelperSchedulingHistory"> <select id="queryPageList" resultType="com.renkang.consultation.entity.ConHelperSchedulingHistory">
select "time" from con_helper_scheduling_history select `time` from con_helper_scheduling_history
<where> <where>
<if test="dto.startTime != null and dto.startTime!='' and dto.endTime != null and dto.endTime != ''"> <if test="dto.startTime != null and dto.startTime!='' and dto.endTime != null and dto.endTime != ''">
and "time" &gt;= #{dto.startTime} and "time" &lt;= #{dto.endTime} and `time` &gt;= #{dto.startTime} and `time` &lt;= #{dto.endTime}
</if> </if>
<if test="dto.week != null and dto.week!=''"> <if test="dto.week != null and dto.week!=''">
and week = #{dto.week} and week = #{dto.week}
</if> </if>
and status = 1 and del_flag = 0 GROUP BY "time" order by "time" desc and status = 1 and del_flag = 0 GROUP BY `time` order by `time` desc
</where> </where>
</select> </select>
<select id="pageByScheduleTime" resultType="java.lang.String"> <select id="pageByScheduleTime" resultType="java.lang.String">
SELECT TO_CHAR("time", 'YYYY-MM-DD') AS scheduleTime FROM con_helper_scheduling_history SELECT DATE_FORMAT(time, '%Y-%m-%d') AS `time` FROM con_helper_scheduling_history
<where> <where>
<!-- 日期范围条件 --> <!-- 日期范围条件 -->
<if test="dto.startTime != null and dto.startTime != ''"> <if test="dto.startTime != null and dto.startTime != ''">
AND "time" &gt;= TO_DATE(#{dto.startTime}, 'YYYY-MM-DD HH24:MI:SS') AND `time` &gt;= DATE_FORMAT(#{dto.startTime}, '%Y-%m-%d 00:00:00')
</if> </if>
<if test="dto.endTime != null and dto.endTime != ''"> <if test="dto.endTime != null and dto.endTime != ''">
AND "time" &lt;= TO_DATE(#{dto.endTime}, 'YYYY-MM-DD HH24:MI:SS') AND `time` &lt;= DATE_FORMAT(#{dto.endTime}, '%Y-%m-%d 23:59:59')
</if> </if>
<if test="dto.week != null and dto.week != ''"> <if test="dto.week != null and dto.week != ''">
and week = #{dto.week} and week = #{dto.week}
</if> </if>
and status = 1 and del_flag = 0 GROUP BY "time" order by "time" desc and status = 1 and del_flag = 0 GROUP BY `time` order by `time` desc
</where> </where>
</select> </select>
</mapper> </mapper>
@@ -21,7 +21,7 @@
AND cr.address LIKE CONCAT('%', #{conResource.province}, '%') AND cr.address LIKE CONCAT('%', #{conResource.province}, '%')
</if> </if>
<if test="conResource.level != null and conResource.level != ''"> <if test="conResource.level != null and conResource.level != ''">
AND cr."level" = #{conResource.level} AND cr.`level` = #{conResource.level}
</if> </if>
<if test="conResource.status != null and conResource.status != ''"> <if test="conResource.status != null and conResource.status != ''">
AND cr.status = #{conResource.status} AND cr.status = #{conResource.status}
@@ -42,7 +42,7 @@
</select> </select>
<select id="selectHostitalList" resultType="com.renkang.consultation.vo.ConsultResourceVO"> <select id="selectHostitalList" resultType="com.renkang.consultation.vo.ConsultResourceVO">
select id, select id,
resource_name as name `resource_name` as `name`
from con_resource from con_resource
where del_flag = 0 where del_flag = 0
order by sort order by sort
@@ -542,8 +542,8 @@
<foreach item="id" collection="doctorIds" open="(" separator="," close=")"> <foreach item="id" collection="doctorIds" open="(" separator="," close=")">
#{id} #{id}
</foreach> </foreach>
AND EXTRACT(YEAR FROM session_date) = EXTRACT(YEAR FROM SYSDATE) AND YEAR(session_date) = YEAR(CURRENT_DATE())
AND EXTRACT(MONTH FROM session_date) = EXTRACT(MONTH FROM SYSDATE) AND MONTH(session_date) = MONTH(CURRENT_DATE())
</select> </select>
@@ -667,10 +667,10 @@
<!-- 日期范围条件 --> <!-- 日期范围条件 -->
<if test="conSession.startDate != null and conSession.startDate != ''"> <if test="conSession.startDate != null and conSession.startDate != ''">
AND c.create_time &gt;= TRUNC(#{conSession.startDate}) AND c.create_time &gt;= DATE_FORMAT(#{conSession.startDate}, '%Y-%m-%d 00:00:00')
</if> </if>
<if test="conSession.endDate != null and conSession.endDate != ''"> <if test="conSession.endDate != null and conSession.endDate != ''">
AND c.create_time &lt;= TRUNC(#{conSession.endDate}) + 1 - 1/86400 AND c.create_time &lt;= DATE_FORMAT(#{conSession.endDate}, '%Y-%m-%d 23:59:59')
</if> </if>
<!-- ID 和账户条件 --> <!-- ID 和账户条件 -->
@@ -3,7 +3,6 @@ package com.renkang.consultation.service.impl;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -249,9 +248,6 @@ public class ConDoctorServiceImpl extends ServiceImpl<ConDoctorMapper, ConDoctor
if (StringUtils.hasLength(dto.getHospitalName())) { if (StringUtils.hasLength(dto.getHospitalName())) {
conDoctor.setResourceId(dto.getHospitalName()); conDoctor.setResourceId(dto.getHospitalName());
} }
if (StrUtil.isNotEmpty(dto.getDoctorName())){
conDoctor.setDoctorName(HtmlUtil.unescape(dto.getDoctorName()));
}
IPage<ConDoctor> conDoctorIPage = conDoctorMapper.queryPageList(page, conDoctor); IPage<ConDoctor> conDoctorIPage = conDoctorMapper.queryPageList(page, conDoctor);
List<ConDoctor> conDoctorList = conDoctorIPage.getRecords(); List<ConDoctor> conDoctorList = conDoctorIPage.getRecords();
if (CollectionUtils.isEmpty(conDoctorList)) { if (CollectionUtils.isEmpty(conDoctorList)) {
@@ -7,6 +7,7 @@ import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.context.XxlJobHelper; import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob; import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant; import org.jeecg.common.constant.CommonConstant;
import org.jeecg.config.shiro.ClientSignThreadLocal; import org.jeecg.config.shiro.ClientSignThreadLocal;
import org.parboiled.common.StringUtils; import org.parboiled.common.StringUtils;
@@ -36,10 +37,10 @@ public class SyncScheduleJob {
String expireHour = "168"; String expireHour = "168";
String param = XxlJobHelper.getJobParam(); String param = XxlJobHelper.getJobParam();
if(StringUtils.isNotEmpty(param)){ if (StringUtils.isNotEmpty(param)) {
JSONObject jsonObject = JSONObject.parseObject(param); JSONObject jsonObject = JSONObject.parseObject(param);
String expireHourRequest = jsonObject.getString("expireHour"); String expireHourRequest = jsonObject.getString("expireHour");
if(StringUtils.isNotEmpty(expireHourRequest)){ if (StringUtils.isNotEmpty(expireHourRequest)) {
expireHour = jsonObject.getString("expireHour"); expireHour = jsonObject.getString("expireHour");
} }
} }
@@ -53,4 +54,12 @@ public class SyncScheduleJob {
return ReturnT.SUCCESS; return ReturnT.SUCCESS;
} }
@XxlJob(value = "endVideoSession")
public Result<String> endVideoSession() {
// 20260327 新增 音视频咨询过期处理 规则为:超过预约时间,比如预约的是 12月9日和专家视频沟通,但超过时间一天,即为过期,需要关闭咨询
conSessionApiController.endVideoSession();
return Result.ok("success");
}
} }
@@ -1,9 +1,8 @@
PROFILE_NAME=dev PROFILE_NAME=dev
SERVER_PORT=7010 SERVER_PORT=7010
NACOS_SERVER_ADDR=192.168.1.80:8848 NACOS_SERVER_ADDR=localhost:8848
NACOS_USERNAME=xjuser NACOS_USERNAME=nacos
NACOS_PASSWORD=Aa135790!123 NACOS_PASSWORD=nacos
NACOS_NAMESPACE=xjxc-space-common NACOS_NAMESPACE=f3f65fb2-303b-4bf7-bccb-4755886503c1
NACOS_NAMESPACE_DISCOVERY=xjxc-space-common
NACOS_GROUP=dev NACOS_GROUP=dev
FILE_SERVER_URL=http://fileserver.yg.dt.io FILE_SERVER_URL=http://fileserver.yg.dt.io
@@ -21,7 +21,7 @@ spring:
password: ${spring.cloud.nacos.password} password: ${spring.cloud.nacos.password}
discovery: discovery:
enabled: true enabled: true
namespace: ${NACOS_NAMESPACE_DISCOVERY:} namespace: ${NACOS_NAMESPACE:}
group: ${NACOS_GROUP:DEFAULT_GROUP} group: ${NACOS_GROUP:DEFAULT_GROUP}
server-addr: ${spring.cloud.nacos.server-addr} server-addr: ${spring.cloud.nacos.server-addr}
username: ${spring.cloud.nacos.username} username: ${spring.cloud.nacos.username}
@@ -1,5 +1,6 @@
package com.renkang.emergency.entity.dto; package com.renkang.emergency.entity.dto;
import cn.hutool.http.HtmlUtil;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@@ -7,6 +8,10 @@ import lombok.Data;
public class CallLogDTO { public class CallLogDTO {
@Schema(description = "姓名") @Schema(description = "姓名")
private String realName; private String realName;
public void setRealName(String realName) {
this.realName = realName != null ? HtmlUtil.unescape(realName) : null;
}
@Schema(description = "呼叫中心") @Schema(description = "呼叫中心")
private String centerId; private String centerId;
@Schema(description = "坐席工号") @Schema(description = "坐席工号")
@@ -1,5 +1,6 @@
package com.renkang.emergency.entity.dto; package com.renkang.emergency.entity.dto;
import cn.hutool.http.HtmlUtil;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@@ -21,6 +22,10 @@ public class PhoneListDTO {
private String phoneType; private String phoneType;
@Schema(description = "姓名") @Schema(description = "姓名")
private String realName; private String realName;
public void setRealName(String realName) {
this.realName = realName != null ? HtmlUtil.unescape(realName) : null;
}
/** /**
* 0:全部 1:女 2:男 * 0:全部 1:女 2:男
*/ */
@@ -1,5 +1,6 @@
package com.renkang.emergency.entity.dto; package com.renkang.emergency.entity.dto;
import cn.hutool.http.HtmlUtil;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@@ -9,6 +10,10 @@ public class TblQimoNoticeDTO {
private String seatId; private String seatId;
@Schema(title = "姓名") @Schema(title = "姓名")
private String realName; private String realName;
public void setRealName(String realName) {
this.realName = realName != null ? HtmlUtil.unescape(realName) : null;
}
@Schema(title = "所属应急中心") @Schema(title = "所属应急中心")
private String centerId; private String centerId;
@Schema(title = "orgCode") @Schema(title = "orgCode")
@@ -59,7 +59,7 @@ public interface AedEquipmentMangerMapper extends BaseMapper<AedEquipmentManger>
* 按单位统计aed设备数量 * 按单位统计aed设备数量
* @return 统计数据 * @return 统计数据
*/ */
@Select(value = "SELECT LEFT(depart_code,6) as orgCode, count(1) as aedCount FROM aed_equipment_manger where del_flag = 0 GROUP BY LEFT(depart_code,6)") @Select(value = "SELECT LEFT(depart_code,6) as orgCode, count(1) as aedCount FROM `aed_equipment_manger` where del_flag = 0 GROUP BY LEFT(depart_code,6)")
List<JSONObject> statisticAedByOrgCode(); List<JSONObject> statisticAedByOrgCode();
List<AedLocationEquipment> getLocation(@Param("idList") List<Long> idList); List<AedLocationEquipment> getLocation(@Param("idList") List<Long> idList);
@@ -1,6 +1,7 @@
package com.renkang.emergency.controller; package com.renkang.emergency.controller;
import cn.hutool.http.HtmlUtil;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.renkang.emergency.entity.EmergencyProfessionUser; import com.renkang.emergency.entity.EmergencyProfessionUser;
import com.renkang.emergency.service.EmergencyProfessionUserService; import com.renkang.emergency.service.EmergencyProfessionUserService;
@@ -40,6 +41,7 @@ public class EmergencyProfessionUserController {
@RequestParam(name = "type", defaultValue = "5") Integer type, @RequestParam(name = "type", defaultValue = "5") Integer type,
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) { @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
name = HtmlUtil.unescape(name);
IPage<EmergencyProfessionUser> pageList = emergencyProfessionUserService.customPage(name, centerId, type, pageNo, pageSize); IPage<EmergencyProfessionUser> pageList = emergencyProfessionUserService.customPage(name, centerId, type, pageNo, pageSize);
return Result.OK(pageList); return Result.OK(pageList);
} }
@@ -6,11 +6,11 @@
SELECT t1.user_id as userId, SELECT t1.user_id as userId,
t3.realname as userName, t3.realname as userName,
t3.type as userType t3.type as userType
FROM emergency_schedules_new_item t1 FROM `emergency_schedules_new_item` t1
LEFT JOIN emergency_new_schedules t2 ON t1.schedules_id = t2.id LEFT JOIN emergency_new_schedules t2 ON t1.schedules_id = t2.id
left join emergency_profession_user t3 on t1.user_id = t3.user_id left join emergency_profession_user t3 on t1.user_id = t3.user_id
WHERE t2.center_id = #{centerId} WHERE t2.center_id = #{centerId}
AND TO_CHAR(t2.schedules_time, 'YYYY-MM-DD') = #{time} AND date_format(t2.schedules_time, '%Y-%m-%d') = #{time}
ORDER BY ORDER BY
t3.type, t3.type,
t1.sort t1.sort
@@ -11,7 +11,7 @@
WHERE operation_user_id is not null WHERE operation_user_id is not null
and operation_user_id != '' and operation_user_id != ''
and session_now = 1 and session_now = 1
and TO_CHAR(create_time, 'YYYY-MM-DD') = #{targetDateStr} and DATE_FORMAT(create_time, '%Y-%m-%d') = #{targetDateStr}
GROUP BY GROUP BY
operation_user_id operation_user_id
</select> </select>
@@ -26,7 +26,7 @@
WHERE major_user_id is not null WHERE major_user_id is not null
and major_user_id != '' and major_user_id != ''
and session_now = 1 and session_now = 1
and TO_CHAR(create_time, 'YYYY-MM-DD') = #{targetDateStr} and DATE_FORMAT(create_time, '%Y-%m-%d') = #{targetDateStr}
GROUP BY GROUP BY
major_user_id major_user_id
</select> </select>
@@ -58,7 +58,7 @@
</foreach> </foreach>
</if> </if>
<if test="type != null and type != '' and '0'.toString().equals(type)"> <if test="type != null and type != '' and '0'.toString().equals(type)">
AND EXTRACT(YEAR FROM create_time) = EXTRACT(YEAR FROM SYSDATE) AND year(create_time) = year(now())
</if> </if>
</where> </where>
GROUP BY center_id GROUP BY center_id
@@ -11,7 +11,7 @@
and type = #{amOrPm} and type = #{amOrPm}
</if> </if>
<if test="date != null and date != ''"> <if test="date != null and date != ''">
and TO_CHAR(schedule_time, 'YYYY-MM-DD') = #{date} and DATE_FORMAT(schedule_time, '%Y-%m-%d') = #{date}
</if> </if>
and status = 1 and status = 1
and del_flag = 0 and del_flag = 0
@@ -30,7 +30,7 @@
user_sex user_sex
FROM emergency_schedule_custom FROM emergency_schedule_custom
WHERE user_id = #{userId} WHERE user_id = #{userId}
AND EXTRACT(YEAR FROM schedule_time) = #{year} AND YEAR (schedule_time) = #{year}
AND EXTRACT(MONTH FROM schedule_time) = #{month} AND MONTH (schedule_time) = #{month}
</select> </select>
</mapper> </mapper>
@@ -11,7 +11,7 @@
and type = #{amOrPm} and type = #{amOrPm}
</if> </if>
<if test="date != null and date != ''"> <if test="date != null and date != ''">
and TO_CHAR(schedule_time, 'YYYY-MM-DD') = #{date} and DATE_FORMAT(schedule_time, '%Y-%m-%d') = #{date}
</if> </if>
</where> </where>
GROUP BY GROUP BY
@@ -22,16 +22,16 @@
<select id="scheduleRecord" resultType="com.renkang.emergency.entity.ScheduleRecord"> <select id="scheduleRecord" resultType="com.renkang.emergency.entity.ScheduleRecord">
SELECT SELECT
id,schedule_time,type,user_type,user_name,user_id,user_sex, id,schedule_time,type,user_type,user_name,user_id,user_sex,
EXTRACT(MONTH FROM schedule_time) AS month, MONTH(schedule_time) AS month,
EXTRACT(DAY FROM schedule_time) AS day DAY(schedule_time) AS day
FROM FROM
emergency_schedule_record emergency_schedule_record
<where> <where>
<if test="year != null and year != ''"> <if test="year != null and year != ''">
and EXTRACT(YEAR FROM schedule_time) = #{year} and YEAR (schedule_time) = #{year}
</if> </if>
<if test="month != null and month != ''"> <if test="month != null and month != ''">
and EXTRACT(MONTH FROM schedule_time) = #{month} and MONTH(schedule_time) = #{month}
</if> </if>
<if test="userId != null and userId != ''"> <if test="userId != null and userId != ''">
and user_id = #{userId} and user_id = #{userId}
@@ -3,27 +3,27 @@
<mapper namespace="com.renkang.emergency.mapper.TblBaseHospitalMapper"> <mapper namespace="com.renkang.emergency.mapper.TblBaseHospitalMapper">
<select id="getHospitalList" resultType="com.renkang.emergency.entity.TblBaseHospitalVo"> <select id="getHospitalList" resultType="com.renkang.emergency.entity.TblBaseHospitalVo">
SELECT id,name,latitude lat ,longitude lon,type SELECT id,`name`,latitude lat ,longitude lon,`type`
FROM emergency_resource FROM emergency_resource
WHERE 1 = 1 and del_flag = 0 WHERE 1 = 1 and del_flag = 0
<if test="type != null and type.length() > 0"> <if test="type != null and type.length() > 0">
AND type = #{type} AND `type` = #{type}
</if> </if>
<if test="hospitalName != null and hospitalName.length() > 0"> <if test="hospitalName != null and hospitalName.length() > 0">
AND name LIKE CONCAT('%', #{hospitalName}, '%') AND `name` LIKE CONCAT('%', #{hospitalName}, '%')
</if> </if>
ORDER BY id ORDER BY id
</select> </select>
<select id="getHospitalListNew" resultType="com.renkang.emergency.entity.TblBaseHospitalVo"> <select id="getHospitalListNew" resultType="com.renkang.emergency.entity.TblBaseHospitalVo">
SELECT id,name,latitude lat ,longitude lon,type SELECT id,`name`,latitude lat ,longitude lon,`type`
FROM emergency_resource FROM emergency_resource
WHERE 1 = 1 and del_flag = 0 and type != 3 WHERE 1 = 1 and del_flag = 0 and type != 3
<if test="type != null and type != ''"> <if test="type != null and type != ''">
AND type = #{type} AND `type` = #{type}
</if> </if>
<if test="hospitalName != null and hospitalName.length() > 0"> <if test="hospitalName != null and hospitalName.length() > 0">
AND name LIKE CONCAT('%', #{hospitalName}, '%') AND `name` LIKE CONCAT('%', #{hospitalName}, '%')
</if> </if>
ORDER BY id ORDER BY id
</select> </select>
@@ -15,13 +15,13 @@
) AS sub_query ) AS sub_query
<where> <where>
<if test="condition != null and condition != '' and condition == 2"> <if test="condition != null and condition != '' and condition == 2">
EXTRACT(YEAR FROM help_time) = EXTRACT(YEAR FROM SYSDATE) YEAR(help_time) = YEAR(NOW())
</if> </if>
<if test="condition != null and condition != '' and condition == 3"> <if test="condition != null and condition != '' and condition == 3">
TO_CHAR(help_time, 'YYYYMM') = TO_CHAR(SYSDATE, 'YYYYMM') DATE_FORMAT(help_time, '%Y%m') = DATE_FORMAT(CURDATE(), '%Y%m')
</if> </if>
<if test="condition != null and condition != '' and condition == 4"> <if test="condition != null and condition != '' and condition == 4">
TO_CHAR(help_time, 'IYYY-IW') = TO_CHAR(SYSDATE, 'IYYY-IW') YEARWEEK(date_format(help_time, '%Y-%m-%d')) = YEARWEEK(now())
</if> </if>
</where> </where>
GROUP BY type GROUP BY type
@@ -9,16 +9,16 @@
<where> <where>
del_flag = 0 del_flag = 0
<if test="type != null and type == 0"> <if test="type != null and type == 0">
-- 周(使用 ISO 年-周 比较) -- 周
AND TO_CHAR(start_time, 'IYYY-IW') = TO_CHAR(SYSDATE, 'IYYY-IW') AND YEARWEEK(start_time, 1) = YEARWEEK(NOW(), 1)
</if> </if>
<if test="type != null and type == 1"> <if test="type != null and type == 1">
-- 月 -- 月
AND TO_CHAR(start_time,'YYYYMM') = TO_CHAR(SYSDATE,'YYYYMM') AND DATE_FORMAT(start_time,'%Y%m')=DATE_FORMAT(CURDATE(),'%Y%m')
</if> </if>
<if test="type != null and type == 2"> <if test="type != null and type == 2">
-- 年 -- 年
AND EXTRACT(YEAR FROM start_time) = EXTRACT(YEAR FROM SYSDATE) AND YEAR(start_time) =YEAR(NOW())
</if> </if>
</where> </where>
GROUP BY injury_level GROUP BY injury_level
@@ -6,6 +6,7 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -58,6 +59,9 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
@Override @Override
public IPage<Order> pageCustom(Page<Order> page, Order order, HttpServletRequest req) { public IPage<Order> pageCustom(Page<Order> page, Order order, HttpServletRequest req) {
if(StrUtil.isNotBlank(order.getSalvageUserName())){
order.setSalvageUserName(HtmlUtil.unescape(order.getSalvageUserName()));
}
String salvageUserName = order.getSalvageUserName(); String salvageUserName = order.getSalvageUserName();
String initiatorUserName = order.getInitiatorUserName(); String initiatorUserName = order.getInitiatorUserName();
Order orderCopy = new Order(); Order orderCopy = new Order();
@@ -110,13 +110,13 @@ public class TblUserHelpServiceImpl extends ServiceImpl<TblUserHelpMapper, TblUs
// 1:全部,2:年,3:月,4:周 // 1:全部,2:年,3:月,4:周
switch (dto.getCondition()) { switch (dto.getCondition()) {
case "2": case "2":
queryWrapper.apply("EXTRACT(YEAR FROM help_time) = EXTRACT(YEAR FROM SYSDATE)"); queryWrapper.apply("DATE_FORMAT(help_time,'%Y') = DATE_FORMAT(NOW(),'%Y')");
break; break;
case "3": case "3":
queryWrapper.apply("TO_CHAR(help_time,'YYYY-MM') = TO_CHAR(SYSDATE,'YYYY-MM')"); queryWrapper.apply("DATE_FORMAT(help_time,'%Y-%m') = DATE_FORMAT(NOW(),'%Y-%m')");
break; break;
case "4": case "4":
queryWrapper.apply("TO_CHAR(help_time,'IYYY-IW') = TO_CHAR(SYSDATE,'IYYY-IW')"); queryWrapper.apply("YEARWEEK(date_format(help_time,'%Y-%m-%d'), 1) = YEARWEEK(now(), 1)");
break; break;
} }
} }
@@ -224,13 +224,13 @@ public class TblUserHelpServiceImpl extends ServiceImpl<TblUserHelpMapper, TblUs
// 1:全部,2:年,3:月,4:周 // 1:全部,2:年,3:月,4:周
switch (condition) { switch (condition) {
case "2": case "2":
queryWrapper.apply("EXTRACT(YEAR FROM help_time) = EXTRACT(YEAR FROM SYSDATE)"); queryWrapper.apply("DATE_FORMAT(help_time,'%Y') = DATE_FORMAT(NOW(),'%Y')");
break; break;
case "3": case "3":
queryWrapper.apply("TO_CHAR(help_time,'YYYY-MM') = TO_CHAR(SYSDATE,'YYYY-MM')"); queryWrapper.apply("DATE_FORMAT(help_time,'%Y-%m') = DATE_FORMAT(NOW(),'%Y-%m')");
break; break;
case "4": case "4":
queryWrapper.apply("TO_CHAR(help_time,'IYYY-IW') = TO_CHAR(SYSDATE,'IYYY-IW')"); queryWrapper.apply("YEARWEEK(date_format(help_time,'%Y-%m-%d')) = YEARWEEK(now())");
break; break;
} }
} }
@@ -1,9 +1,8 @@
PROFILE_NAME=dev PROFILE_NAME=dev
SERVER_PORT=7011 SERVER_PORT=7011
NACOS_SERVER_ADDR=192.168.1.80:8848 NACOS_SERVER_ADDR=localhost:8848
NACOS_USERNAME=xjuser NACOS_USERNAME=nacos
NACOS_PASSWORD=Aa135790!123 NACOS_PASSWORD=nacos
NACOS_NAMESPACE=xjxc-space-common NACOS_NAMESPACE=f3f65fb2-303b-4bf7-bccb-4755886503c1
NACOS_NAMESPACE_DISCOVERY=xjxc-space-common
NACOS_GROUP=dev NACOS_GROUP=dev
FILE_SERVER_URL=http://fileserver.yg.dt.io FILE_SERVER_URL=http://fileserver.yg.dt.io
@@ -21,7 +21,7 @@ spring:
password: ${spring.cloud.nacos.password} password: ${spring.cloud.nacos.password}
discovery: discovery:
enabled: true enabled: true
namespace: ${NACOS_NAMESPACE_DISCOVERY:} namespace: ${NACOS_NAMESPACE:}
group: ${NACOS_GROUP:DEFAULT_GROUP} group: ${NACOS_GROUP:DEFAULT_GROUP}
server-addr: ${spring.cloud.nacos.server-addr} server-addr: ${spring.cloud.nacos.server-addr}
username: ${spring.cloud.nacos.username} username: ${spring.cloud.nacos.username}
@@ -22,6 +22,10 @@ public class WatchH5IndexItemNewVo {
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd")
private Date dataDate; private Date dataDate;
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date dataDateNew;
/** /**
* 注意 当wdType=sleep时此字段返回长睡时长 * 注意 当wdType=sleep时此字段返回长睡时长
*/ */
@@ -1,5 +1,6 @@
package com.renkang.watch.bean.request; package com.renkang.watch.bean.request;
import cn.hutool.http.HtmlUtil;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data; import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
@@ -19,6 +20,9 @@ public class AbnormalEventFilter {
private String departOrgCode; private String departOrgCode;
// 用户名称 // 用户名称
private String userName; private String userName;
public void setUserName(String userName) {
this.userName = userName != null ? HtmlUtil.unescape(userName) : null;
}
// 工具编码 // 工具编码
private String watchNo; private String watchNo;
//员工编号 //员工编号
@@ -52,4 +52,18 @@ public class AbnormalEvent extends BaseUser {
private Date bindDate; private Date bindDate;
@Schema(title = "重点指标用户(0:非重点指标用户 1:大病异常 2:慢病异常 3:指标异常)") @Schema(title = "重点指标用户(0:非重点指标用户 1:大病异常 2:慢病异常 3:指标异常)")
private List<WatchKeyUser> keyUserList; private List<WatchKeyUser> keyUserList;
/**
* 事件ID(用于告警事件与GPS位置更新关联的唯一标识)
*/
@Excel(name = "事件ID", width = 32, orderNum = "12")
@Schema(title = "事件ID")
private String eventId;
/**
* 定位时间(手表定时上报的GPS定位时间)
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "定位时间", format = "yyyy-MM-dd HH:mm:ss", width = 20, orderNum = "13")
@Schema(title = "定位时间")
private Date locateTime;
} }
@@ -0,0 +1,19 @@
package com.renkang.watch.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* @author TianZi
* @date 2023/11/7 14:13
*/
@Data
public class BindDeviceDTO {
@Schema(title = "手表编号")
private String watchNo;
}
@@ -1,5 +1,6 @@
package com.renkang.watch.dto; package com.renkang.watch.dto;
import cn.hutool.http.HtmlUtil;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@@ -18,6 +19,10 @@ public class CalorieDataByUserDTO {
private Integer pageSize = 10; private Integer pageSize = 10;
@Schema(title = "用户姓名") @Schema(title = "用户姓名")
private String realName; private String realName;
public void setRealName(String realName) {
this.realName = realName != null ? HtmlUtil.unescape(realName) : null;
}
@Schema(title = "工号") @Schema(title = "工号")
private String workNo; private String workNo;
@Schema(title = "用户id组") @Schema(title = "用户id组")
@@ -71,7 +71,7 @@ public class WatchDataWorkoutTrace implements Serializable {
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd")
@Schema(title = "时间戳") @Schema(title = "时间戳")
@TableField("utc_time") @TableField("`utc_time`")
private java.util.Date utcTime; private java.util.Date utcTime;
/** /**
* 数据是否合法 * 数据是否合法
@@ -151,6 +151,20 @@ public class WatchMonitorData implements Serializable {
@Excel(name = "部门编码", width = 15) @Excel(name = "部门编码", width = 15)
@Schema(title = "部门编码") @Schema(title = "部门编码")
private java.lang.String orgCode; private java.lang.String orgCode;
/**
* 事件ID(用于告警事件与GPS位置更新关联的唯一标识)
*/
@Excel(name = "事件ID", width = 32)
@Schema(title = "事件ID")
private java.lang.String eventId;
/**
* 定位时间(手表上报的GPS定位时间,定时上报场景使用)
*/
@Excel(name = "定位时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(title = "定位时间")
private java.util.Date locateTime;
@Schema(title = "员工编号") @Schema(title = "员工编号")
@TableField(exist = false) @TableField(exist = false)
@@ -1,22 +1,71 @@
package com.renkang.watch.vo.UserData.res; package com.renkang.watch.vo.UserData.res;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.renkang.watch.WatchH5IndexItemNewVo;
import lombok.Data; import lombok.Data;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
/** 用户统计数据 /**
* 用户统计数据
*
* @author stan * @author stan
* @since 2024-11-04 16:33 * @since 2024-11-04 16:33
*/ */
@Data @Data
public class UserStat { public class UserStat {
/**
* 数据类型:0=心率 1=血氧 2=压力 3=体温 4=睡眠
*/
private String type;
private BigDecimal latest; private BigDecimal latest;
private BigDecimal max; private BigDecimal max;
private BigDecimal min; private BigDecimal min;
private BigDecimal avg; private BigDecimal avg;
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date latestTime; private Date latestTime;
public UserStat() {
}
public UserStat(WatchH5IndexItemNewVo watchH5IndexItemNewVo) {
switch (watchH5IndexItemNewVo.getWdType()) {
case "sleep":
this.type = "4";
break;
case "heart_rate":
this.type = "0";
break;
case "stress":
this.type = "2";
break;
case "spo2":
this.type = "1";
break;
case "temperature":
this.type = "3";
break;
default:
break;
}
this.latest = parseSafe(watchH5IndexItemNewVo.getDataValue());
this.max = parseSafe(watchH5IndexItemNewVo.getDataMax());
this.min = parseSafe(watchH5IndexItemNewVo.getDataMin());
this.avg = parseSafe(watchH5IndexItemNewVo.getDataAvg());
this.latestTime = watchH5IndexItemNewVo.getDataDateNew();
}
/**
* 安全解析字符串为 BigDecimal,入参为 null 或空串时返回 null
*
* @param value 待解析的字符串数值
* @return 解析结果,无效输入返回 null
*/
private static BigDecimal parseSafe(String value) {
if (value == null || value.isEmpty()) {
return null;
}
return BigDecimal.valueOf(Double.parseDouble(value));
}
} }
@@ -45,4 +45,15 @@ public class WatchNotifyVo implements Serializable {
private Date warnTime; private Date warnTime;
private String gpsErrorMsg; private String gpsErrorMsg;
/**
* 事件ID(用于告警事件与GPS位置更新关联的唯一标识)
*/
private String eventId;
/**
* 定位时间(手表上报的GPS定位时间,定时上报场景使用)
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date locateTime;
} }
@@ -18,9 +18,14 @@ public class DeptStatData {
/** /**
* 已分配设备数 * 已分配设备数
*/ */
@Excel(name = "分配设备数", width = 15,orderNum = "4") @Excel(name = "分配设备数", width = 15,orderNum = "4")
private Integer assignedDeviceNums; private Integer assignedDeviceNums;
/**
* 未分配设备数(入库设备数 - 已分配设备数,仅一、二级部门有值)
*/
@Excel(name = "未分配设备数", width = 15,orderNum = "5")
private Integer undistributedDeviceNums;
@Excel(name = "入库设备数", width = 15,orderNum = "3") @Excel(name = "入库设备数", width = 15,orderNum = "3")
private Integer totalAssignedDeviceNums; private Integer totalAssignedDeviceNums;
@@ -28,25 +33,22 @@ public class DeptStatData {
/** /**
* 佩戴人员数 * 佩戴人员数
*/ */
@Excel(name = "佩戴人员数", width = 15,orderNum = "5") @Excel(name = "佩戴人员数", width = 15,orderNum = "6")
private Integer assignedUserNums; private Integer assignedUserNums;
/** /**
* 未佩戴人员数 * 未佩戴人员数
*/ */
@Excel(name = "未佩戴人员数", width = 15,orderNum = "6") @Excel(name = "未佩戴人员数", width = 15,orderNum = "7")
private Integer undistributedUserNums; private Integer undistributedUserNums;
@Excel(name = "心率异常人数", width = 15,orderNum = "7") @Excel(name = "心率异常人数", width = 15,orderNum = "8")
private Integer heartRateNums; private Integer heartRateNums;
@Excel(name = "血氧异常人数", width = 15,orderNum = "8") @Excel(name = "血氧异常人数", width = 15,orderNum = "9")
private Integer spo2Nums; private Integer spo2Nums;
@Excel(name = "压力异常人数", width = 15,orderNum = "9") @Excel(name = "压力异常人数", width = 15,orderNum = "10")
private Integer stressNums; private Integer stressNums;
@Excel(name = "体温异常人数", width = 15,orderNum = "10") @Excel(name = "体温异常人数", width = 15,orderNum = "11")
private Integer tempNums; private Integer tempNums;
} }
@@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.Map; import java.util.Map;
@RestController @RestController
@@ -41,6 +42,16 @@ public class WatchDataApiController {
return Result.ok(watchDataApiService.userStatResult(type)); return Result.ok(watchDataApiService.userStatResult(type));
} }
/**
* 用户手表数据(批量返回)
*
* @return data
*/
@GetMapping("userWatchDataAll")
public Result<List<UserStat>> userStatResultAll(@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date date) {
return Result.ok(watchDataApiService.userStatResultAll(date));
}
/** /**
* 用户此刻是否拥有手表 * 用户此刻是否拥有手表
* *
@@ -11,6 +11,7 @@ import com.renkang.watch.vo.UserData.res.sleep.WatchDataSleepRes;
import org.jeecg.common.api.vo.Result; import org.jeecg.common.api.vo.Result;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.Map; import java.util.Map;
public interface WatchDataApiService { public interface WatchDataApiService {
@@ -43,6 +44,14 @@ public interface WatchDataApiService {
UserStat userStatResult(String type); UserStat userStatResult(String type);
/**
* 查询当前登录用户所有健康指标统计数据(按指定日期过滤)
*
* @param date 查询日期,为 null 时返回最新一条数据
* @return 各指标统计结果列表
*/
List<UserStat> userStatResultAll(Date date);
Boolean userHaveWatch(String userId); Boolean userHaveWatch(String userId);
UserWatchInfo findWatchInfo(String userId); UserWatchInfo findWatchInfo(String userId);
@@ -7,6 +7,8 @@ import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.renkang.watch.WatchH5IndexItemNewVo;
import com.renkang.watch.api.bean.response.UserWatchInfo; import com.renkang.watch.api.bean.response.UserWatchInfo;
import com.renkang.watch.api.service.WatchDataApiService; import com.renkang.watch.api.service.WatchDataApiService;
import com.renkang.watch.dto.WatchDataWorkoutDTO; import com.renkang.watch.dto.WatchDataWorkoutDTO;
@@ -24,31 +26,34 @@ import com.renkang.watch.vo.UserData.res.bodyTemperature.BodyTempStat;
import com.renkang.watch.vo.UserData.res.bodyTemperature.BodyTempStatRes; import com.renkang.watch.vo.UserData.res.bodyTemperature.BodyTempStatRes;
import com.renkang.watch.vo.UserData.res.heartRate.WatchDataHeartRateRes; import com.renkang.watch.vo.UserData.res.heartRate.WatchDataHeartRateRes;
import com.renkang.watch.vo.UserData.res.sleep.WatchDataSleepRes; import com.renkang.watch.vo.UserData.res.sleep.WatchDataSleepRes;
import com.renkang.watch.vo.WatchH5IndexItemVo;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.jeecg.common.api.vo.Result; import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.DateUtils; import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.global.GlobalUtils; import org.jeecg.global.GlobalUtils;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Service @Service
public class WatchDataApiServiceImpl implements WatchDataApiService { public class WatchDataApiServiceImpl implements WatchDataApiService {
@Autowired @Autowired
private WatchDataWorkoutMapper watchDataWorkoutMapper; private WatchDataWorkoutMapper watchDataWorkoutMapper;
@Autowired
private WatchStatUserInfoDayHeartRateMapper watchStatUserInfoDayHeartRateMapper;
@Autowired @Autowired
private WatchDataHeartRateMapper watchDataHeartRateMapper; private WatchDataHeartRateMapper watchDataHeartRateMapper;
@@ -60,9 +65,6 @@ public class WatchDataApiServiceImpl implements WatchDataApiService {
@Autowired @Autowired
private WatchStatUserInfoDaySpo2ServiceImpl watchStatUserInfoDaySpo2ServiceImpl; private WatchStatUserInfoDaySpo2ServiceImpl watchStatUserInfoDaySpo2ServiceImpl;
@Autowired
private WatchStatUserInfoDaySleepMapper watchStatUserInfoDaySleepMapper;
@Autowired @Autowired
private WatchDataSleepNewMinuteMapper watchDataSleepNewMinuteMapper; private WatchDataSleepNewMinuteMapper watchDataSleepNewMinuteMapper;
@@ -96,7 +98,6 @@ public class WatchDataApiServiceImpl implements WatchDataApiService {
@Autowired @Autowired
private IWatchDataTemperatureService watchDataTemperatureService; private IWatchDataTemperatureService watchDataTemperatureService;
@Autowired @Autowired
private IWatchDataStressService watchDataStressService; private IWatchDataStressService watchDataStressService;
@Autowired @Autowired
@@ -106,12 +107,47 @@ public class WatchDataApiServiceImpl implements WatchDataApiService {
@Autowired @Autowired
private WatchUserDataMapper watchUserDataMapper; private WatchUserDataMapper watchUserDataMapper;
@Autowired @Autowired
private WatchStatUserInfoDayHeartRateMapper watchStatUserInfoDayHeartRateMapper;
@Autowired
private WatchStatUserInfoDaySleepMapper watchStatUserInfoDaySleepMapper;
@Autowired
private WatchStatUserInfoDaySpo2Mapper watchStatUserInfoDaySpo2Mapper; private WatchStatUserInfoDaySpo2Mapper watchStatUserInfoDaySpo2Mapper;
@Autowired @Autowired
private WatchStatUserInfoDayStressMapper watchStatUserInfoDayStressMapper; private WatchStatUserInfoDayStressMapper watchStatUserInfoDayStressMapper;
@Autowired @Autowired
private WatchStatUserInfoDayTempMapper watchStatUserInfoDayTempMapper; private WatchStatUserInfoDayTempMapper watchStatUserInfoDayTempMapper;
@Autowired
private RedisUtil redisUtil;
/** 用户统计全量数据 Redis 缓存 key 前缀 */
private static final String USER_STAT_ALL_CACHE_KEY = "watch:userStatAll:";
private AsyncTaskExecutor asyncTaskExecutor;
public AsyncTaskExecutor getAsyncTaskExecutor() {
if (asyncTaskExecutor == null) {
initAsyncExecutor();
}
return asyncTaskExecutor;
}
@PostConstruct
public void init() {
initAsyncExecutor();
}
private void initAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(150);
taskExecutor.setMaxPoolSize(500);
taskExecutor.setQueueCapacity(500);
taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
taskExecutor.setThreadNamePrefix("watch-latest-pool1-");
taskExecutor.initialize();
asyncTaskExecutor = taskExecutor;
}
@Override @Override
public Result<Map<String,Object>> selectSportCostListApi() { public Result<Map<String,Object>> selectSportCostListApi() {
LoginUser loginUser = GlobalUtils.getLoginUser(); LoginUser loginUser = GlobalUtils.getLoginUser();
@@ -834,20 +870,171 @@ public class WatchDataApiServiceImpl implements WatchDataApiService {
String userId = GlobalUtils.getLoginUser().getId(); String userId = GlobalUtils.getLoginUser().getId();
switch (type) { switch (type) {
case "0": case "0":
return handleHeartRate(userId); return handleHeartRate(userId,null);
case "1": case "1":
return handleBloodOxygen(userId); return handleBloodOxygen(userId,null);
case "2": case "2":
return handleStress(userId); return handleStress(userId,null);
case "3": case "3":
return handleBodyTemperature(userId); return handleBodyTemperature(userId,null);
case "4": case "4":
return handleSleep(userId); return handleSleep(userId,null);
default: default:
return null; return null;
} }
} }
@Override
public List<UserStat> userStatResultAll(Date date) {
// 在主线程提前获取 userId,避免子线程无法访问 ThreadLocal 中的登录信息
String userId = GlobalUtils.getLoginUser().getId();
// 有时间参数时缓存 key 携带日期,避免与无参缓存冲突
String cacheKey = USER_STAT_ALL_CACHE_KEY + userId + (date != null ? "_" + date.getTime() : "");
// 命中 Redis 缓存直接返回
Object cached = redisUtil.get(cacheKey);
if (cached != null) {
return (List<UserStat>) cached;
}
// 构建「数据类型 → 异步查询 Future」映射,消除 switch-case 冗余
Map<String, CompletableFuture<WatchH5IndexItemNewVo>> futureMap = new HashMap<>();
futureMap.put("sleep", CompletableFuture.supplyAsync(() -> latestSleepData(userId), getAsyncTaskExecutor()));
futureMap.put("heart_rate", CompletableFuture.supplyAsync(() -> latestHeartRateData(userId), getAsyncTaskExecutor()));
futureMap.put("spo2", CompletableFuture.supplyAsync(() -> latestSpo2Data(userId), getAsyncTaskExecutor()));
futureMap.put("stress", CompletableFuture.supplyAsync(() -> latestStressData(userId), getAsyncTaskExecutor()));
futureMap.put("temperature", CompletableFuture.supplyAsync(() -> latestTempData(userId), getAsyncTaskExecutor()));
// 等待全部异步查询完成
CompletableFuture.allOf(futureMap.values().toArray(new CompletableFuture[0])).join();
// 转为顺序流遍历,避免并行流写入 ArrayList 的线程安全问题
List<WatchH5IndexItemNewVo> list = new ArrayList<>();
emptyItems().sequential().forEach(itemVo -> {
CompletableFuture<WatchH5IndexItemNewVo> future = futureMap.get(itemVo.getWdType());
// steps 等暂无对应查询的类型直接跳过
if (future == null) {
return;
}
WatchH5IndexItemNewVo data = future.join();
if (data == null) {
data = new WatchH5IndexItemNewVo();
}
// 将模板字段(wdType、wdTypeName、阈值)合并到结果对象
data.fieldCopy(itemVo);
// 睡眠数据特殊处理:dataValue 为空时补 "0"
if ("sleep".equals(itemVo.getWdType()) && StrUtil.isEmpty(data.getDataValue())) {
data.setDataValue("0");
}
list.add(data);
});
List<UserStat> result = list.stream().map(UserStat::new).collect(Collectors.toList());
// 写入 Redis 缓存,TTL=3分钟(180秒)
redisUtil.set(cacheKey, result, 180);
return result;
}
private Stream<WatchH5IndexItemVo> emptyItems() {
//睡眠
WatchH5IndexItemVo sleepVo = new WatchH5IndexItemVo();
sleepVo.setWdType("sleep");
//步数
WatchH5IndexItemVo stepsVo = new WatchH5IndexItemVo();
stepsVo.setWdType("steps");
//心率
WatchH5IndexItemVo hearRateVo = new WatchH5IndexItemVo();
hearRateVo.setWdType("heart_rate");
//压力
WatchH5IndexItemVo stressVo = new WatchH5IndexItemVo();
stressVo.setWdType("stress");
//血氧饱和度
WatchH5IndexItemVo spo2Vo = new WatchH5IndexItemVo();
spo2Vo.setWdType("spo2");
//体温
WatchH5IndexItemVo tempVo = new WatchH5IndexItemVo();
tempVo.setWdType("temperature");
List<WatchH5IndexItemVo> list = Arrays.asList(sleepVo, stepsVo, hearRateVo, stressVo, spo2Vo, tempVo);
return list.parallelStream()
.peek(itemVo -> {
itemVo.setWarnMin("0.0");
itemVo.setWarnMax("0.0");
});
}
private WatchH5IndexItemNewVo latestSleepData(String userId) {
MPJLambdaWrapper<WatchStatUserInfoDaySleep> wrapper = new MPJLambdaWrapper<>();
//因为睡眠详情页取的是长睡时长作为当天的睡眠时间 , 所以这里保持一致并没有取当天的睡眠总时长
wrapper.selectAs(WatchStatUserInfoDaySleep::getLongDurationTotal,WatchH5IndexItemNewVo::getDataValue);
wrapper.selectAs(WatchStatUserInfoDaySleep::getDeepSleepTimes,WatchH5IndexItemNewVo::getDataMax);
wrapper.selectAs(WatchStatUserInfoDaySleep::getLightSleepTimes,WatchH5IndexItemNewVo::getDataMin);
wrapper.selectAs(WatchStatUserInfoDaySleep::getSleepAvg,WatchH5IndexItemNewVo::getDataAvg);
wrapper.selectAs(WatchStatUserInfoDaySleep::getLastUploadTime,WatchH5IndexItemNewVo::getDataDateNew);
wrapper.eq(WatchStatUserInfoDaySleep::getUserId, userId);
wrapper.orderByDesc(WatchStatUserInfoDaySleep::getDataDate);
wrapper.last("limit 1");
return watchStatUserInfoDaySleepMapper.selectJoinOne(WatchH5IndexItemNewVo.class,wrapper);
}
private WatchH5IndexItemNewVo latestHeartRateData(String userId) {
MPJLambdaWrapper<WatchStatUserInfoDayHeartRate> wrapper = new MPJLambdaWrapper<>();
// 必须是watch_stat_user_info_day_heart_rate表中new_data字段启用后才能这样查
wrapper.selectAs(WatchStatUserInfoDayHeartRate::getNewValue,WatchH5IndexItemNewVo::getDataValue);
wrapper.selectAs(WatchStatUserInfoDayHeartRate::getMaxValue,WatchH5IndexItemNewVo::getDataMax);
wrapper.selectAs(WatchStatUserInfoDayHeartRate::getMinValue,WatchH5IndexItemNewVo::getDataMin);
wrapper.selectAs(WatchStatUserInfoDayHeartRate::getAvgValue,WatchH5IndexItemNewVo::getDataAvg);
wrapper.selectAs(WatchStatUserInfoDayHeartRate::getLastUploadTime,WatchH5IndexItemNewVo::getDataDateNew);
wrapper.eq(WatchStatUserInfoDayHeartRate::getUserId, userId);
wrapper.orderByDesc(WatchStatUserInfoDayHeartRate::getDataDate);
wrapper.last("limit 1");
return watchStatUserInfoDayHeartRateMapper.selectJoinOne(WatchH5IndexItemNewVo.class,wrapper);
}
private WatchH5IndexItemNewVo latestSpo2Data(String userId) {
MPJLambdaWrapper<WatchStatUserInfoDaySpo2> wrapper = new MPJLambdaWrapper<>();
// 必须是watch_stat_user_info_day_spo2表中new_data字段启用后才能这样查
wrapper.selectAs(WatchStatUserInfoDaySpo2::getNewValue,WatchH5IndexItemNewVo::getDataValue);
wrapper.selectAs(WatchStatUserInfoDaySpo2::getMaxValue,WatchH5IndexItemNewVo::getDataMax);
wrapper.selectAs(WatchStatUserInfoDaySpo2::getMinValue,WatchH5IndexItemNewVo::getDataMin);
wrapper.selectAs(WatchStatUserInfoDaySpo2::getAvgValue,WatchH5IndexItemNewVo::getDataAvg);
wrapper.selectAs(WatchStatUserInfoDaySpo2::getLastUploadTime,WatchH5IndexItemNewVo::getDataDateNew);
wrapper.eq(WatchStatUserInfoDaySpo2::getUserId, userId);
wrapper.orderByDesc(WatchStatUserInfoDaySpo2::getDataDate);
wrapper.last("limit 1");
return watchStatUserInfoDaySpo2Mapper.selectJoinOne(WatchH5IndexItemNewVo.class,wrapper);
}
private WatchH5IndexItemNewVo latestStressData(String userId) {
MPJLambdaWrapper<WatchStatUserInfoDayStress> wrapper = new MPJLambdaWrapper<>();
// 必须是watch_stat_user_info_day_stress表中new_data字段启用后才能这样查
wrapper.selectAs(WatchStatUserInfoDayStress::getNewValue,WatchH5IndexItemNewVo::getDataValue);
wrapper.selectAs(WatchStatUserInfoDayStress::getMaxValue,WatchH5IndexItemNewVo::getDataMax);
wrapper.selectAs(WatchStatUserInfoDayStress::getMinValue,WatchH5IndexItemNewVo::getDataMin);
wrapper.selectAs(WatchStatUserInfoDayStress::getAvgValue,WatchH5IndexItemNewVo::getDataAvg);
wrapper.selectAs(WatchStatUserInfoDayStress::getLastUploadTime,WatchH5IndexItemNewVo::getDataDateNew);
wrapper.eq(WatchStatUserInfoDayStress::getUserId, userId);
wrapper.orderByDesc(WatchStatUserInfoDayStress::getDataDate);
wrapper.last("limit 1");
return watchStatUserInfoDayStressMapper.selectJoinOne(WatchH5IndexItemNewVo.class,wrapper);
}
private WatchH5IndexItemNewVo latestTempData(String userId) {
MPJLambdaWrapper<WatchStatUserInfoDayTemp> wrapper = new MPJLambdaWrapper<>();
// 必须是watch_stat_user_info_day_temp表中new_data字段启用后才能这样查
wrapper.selectAs(WatchStatUserInfoDayTemp::getNewValue,WatchH5IndexItemNewVo::getDataValue);
wrapper.selectAs(WatchStatUserInfoDayTemp::getMaxValue,WatchH5IndexItemNewVo::getDataMax);
wrapper.selectAs(WatchStatUserInfoDayTemp::getMinValue,WatchH5IndexItemNewVo::getDataMin);
wrapper.selectAs(WatchStatUserInfoDayTemp::getAvgValue,WatchH5IndexItemNewVo::getDataAvg);
wrapper.selectAs(WatchStatUserInfoDayTemp::getLastUploadTime,WatchH5IndexItemNewVo::getDataDateNew);
wrapper.eq(WatchStatUserInfoDayTemp::getUserId, userId);
wrapper.orderByDesc(WatchStatUserInfoDayTemp::getDataDate);
wrapper.last("limit 1");
return watchStatUserInfoDayTempMapper.selectJoinOne(WatchH5IndexItemNewVo.class,wrapper);
}
@Override @Override
public Boolean userHaveWatch(String userId) { public Boolean userHaveWatch(String userId) {
if (StrUtil.isBlank(userId)) { if (StrUtil.isBlank(userId)) {
@@ -885,7 +1072,7 @@ public class WatchDataApiServiceImpl implements WatchDataApiService {
} }
private UserStat handleSleep(String userId) { private UserStat handleSleep(String userId, Date date) {
LambdaQueryWrapper<WatchStatUserInfoDaySleep> queryWrapper = Wrappers.lambdaQuery(WatchStatUserInfoDaySleep.class) LambdaQueryWrapper<WatchStatUserInfoDaySleep> queryWrapper = Wrappers.lambdaQuery(WatchStatUserInfoDaySleep.class)
.select(WatchStatUserInfoDaySleep::getId, .select(WatchStatUserInfoDaySleep::getId,
WatchStatUserInfoDaySleep::getDeepSleepTimes, WatchStatUserInfoDaySleep::getDeepSleepTimes,
@@ -893,13 +1080,15 @@ public class WatchDataApiServiceImpl implements WatchDataApiService {
WatchStatUserInfoDaySleep::getDeepLightTimes, WatchStatUserInfoDaySleep::getDeepLightTimes,
WatchStatUserInfoDaySleep::getDataDate) WatchStatUserInfoDaySleep::getDataDate)
.eq(WatchStatUserInfoDaySleep::getUserId, userId) .eq(WatchStatUserInfoDaySleep::getUserId, userId)
.orderByDesc(WatchStatUserInfoDaySleep::getDataDate) // 传了日期则精确匹配,否则取最新一条
.eq(date != null, WatchStatUserInfoDaySleep::getDataDate, date)
.orderByDesc(date == null, WatchStatUserInfoDaySleep::getDataDate)
.last("limit 1"); .last("limit 1");
WatchStatUserInfoDaySleep data = watchStatUserInfoDaySleepMapper.selectOne(queryWrapper); WatchStatUserInfoDaySleep data = watchStatUserInfoDaySleepMapper.selectOne(queryWrapper);
if (data == null) { if (data == null) {
return null; return new UserStat();
} }
UserStat stat = new UserStat(); UserStat stat = new UserStat();
@@ -915,15 +1104,15 @@ public class WatchDataApiServiceImpl implements WatchDataApiService {
return stat; return stat;
} }
private UserStat handleBodyTemperature(String userId) { private UserStat handleBodyTemperature(String userId, Date date) {
int type = 5; int type = 5;
int scale = 1; int scale = 1;
// 最新数据 // 最新数据
UserStat userStat = userWatchDataLatest(userId, type, scale); UserStat userStat = userWatchDataLatest(userId, type, scale);
if (userStat == null) { if (userStat == null) {
return null; return new UserStat();
} }
LambdaQueryWrapper<WatchStatUserInfoDayTemp> queryWrapper = getQueryWrapper(userId); LambdaQueryWrapper<WatchStatUserInfoDayTemp> queryWrapper = getQueryWrapper(userId, date);
WatchStatUserInfoDayTemp data = watchStatUserInfoDayTempMapper.selectOne(queryWrapper); WatchStatUserInfoDayTemp data = watchStatUserInfoDayTempMapper.selectOne(queryWrapper);
if (data == null) { if (data == null) {
return userStat; return userStat;
@@ -933,15 +1122,15 @@ public class WatchDataApiServiceImpl implements WatchDataApiService {
return userStat; return userStat;
} }
private UserStat handleStress(String userId) { private UserStat handleStress(String userId, Date date) {
int type = 3; int type = 3;
int scale = 0; int scale = 0;
// 最新数据 // 最新数据
UserStat userStat = userWatchDataLatest(userId, type, scale); UserStat userStat = userWatchDataLatest(userId, type, scale);
if (userStat == null) { if (userStat == null) {
return null; return new UserStat();
} }
LambdaQueryWrapper<WatchStatUserInfoDayStress> queryWrapper = getQueryWrapper(userId); LambdaQueryWrapper<WatchStatUserInfoDayStress> queryWrapper = getQueryWrapper(userId, date);
WatchStatUserInfoDayStress data = watchStatUserInfoDayStressMapper.selectOne(queryWrapper); WatchStatUserInfoDayStress data = watchStatUserInfoDayStressMapper.selectOne(queryWrapper);
if (data == null) { if (data == null) {
return userStat; return userStat;
@@ -951,15 +1140,15 @@ public class WatchDataApiServiceImpl implements WatchDataApiService {
return userStat; return userStat;
} }
private UserStat handleBloodOxygen(String userId) { private UserStat handleBloodOxygen(String userId, Date date) {
int type = 2; int type = 2;
int scale = 0; int scale = 0;
// 最新数据 // 最新数据
UserStat userStat = userWatchDataLatest(userId, type, scale); UserStat userStat = userWatchDataLatest(userId, type, scale);
if (userStat == null) { if (userStat == null) {
return null; return new UserStat();
} }
LambdaQueryWrapper<WatchStatUserInfoDaySpo2> queryWrapper = getQueryWrapper(userId); LambdaQueryWrapper<WatchStatUserInfoDaySpo2> queryWrapper = getQueryWrapper(userId, date);
WatchStatUserInfoDaySpo2 data = watchStatUserInfoDaySpo2Mapper.selectOne(queryWrapper); WatchStatUserInfoDaySpo2 data = watchStatUserInfoDaySpo2Mapper.selectOne(queryWrapper);
if (data == null) { if (data == null) {
return userStat; return userStat;
@@ -969,15 +1158,15 @@ public class WatchDataApiServiceImpl implements WatchDataApiService {
return userStat; return userStat;
} }
private UserStat handleHeartRate(String userId) { private UserStat handleHeartRate(String userId, Date date) {
int type = 1; int type = 1;
int scale = 0; int scale = 0;
// 最新数据 // 最新数据
UserStat userStat = userWatchDataLatest(userId, type, scale); UserStat userStat = userWatchDataLatest(userId, type, scale);
if (userStat == null) { if (userStat == null) {
return null; return new UserStat();
} }
LambdaQueryWrapper<WatchStatUserInfoDayHeartRate> queryWrapper = getQueryWrapper(userId); LambdaQueryWrapper<WatchStatUserInfoDayHeartRate> queryWrapper = getQueryWrapper(userId, date);
WatchStatUserInfoDayHeartRate data = watchStatUserInfoDayHeartRateMapper.selectOne(queryWrapper); WatchStatUserInfoDayHeartRate data = watchStatUserInfoDayHeartRateMapper.selectOne(queryWrapper);
if (data == null) { if (data == null) {
return userStat; return userStat;
@@ -1029,10 +1218,12 @@ public class WatchDataApiServiceImpl implements WatchDataApiService {
return stat; return stat;
} }
private <T> LambdaQueryWrapper<T> getQueryWrapper(String userId) { private <T> LambdaQueryWrapper<T> getQueryWrapper(String userId, Date date) {
QueryWrapper<T> queryWrapper = new QueryWrapper<>(); QueryWrapper<T> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_id", userId) queryWrapper.eq("user_id", userId)
.orderByDesc("data_date") // 传了日期则精确匹配,否则取最新一条
.eq(date != null, "data_date", date)
.orderByDesc(date == null, "data_date")
.last("limit 1"); .last("limit 1");
return queryWrapper.lambda(); return queryWrapper.lambda();
} }
@@ -1051,4 +1242,17 @@ public class WatchDataApiServiceImpl implements WatchDataApiService {
return BigDecimal.valueOf(value).setScale(0, RoundingMode.HALF_UP); return BigDecimal.valueOf(value).setScale(0, RoundingMode.HALF_UP);
} }
/**
* 设置统计数据类型标识,stat 为 null 时直接返回 null
*
* @param stat UserStat 对象
* @param type 类型编码:0=心率 1=血氧 2=压力 3=体温 4=睡眠
*/
private UserStat setType(UserStat stat, String type) {
if (stat != null) {
stat.setType(type);
}
return stat;
}
} }
@@ -336,8 +336,9 @@ public class AsyncImportService {
updatedWatchDevice.setBindDate(watchDevice.getBindDate()==null?new Date():watchDevice.getBindDate()); updatedWatchDevice.setBindDate(watchDevice.getBindDate()==null?new Date():watchDevice.getBindDate());
updatedWatchDevice.setUpdateDate(new Date()); updatedWatchDevice.setUpdateDate(new Date());
updatedWatchDevice.setUpdateBy(sysUser.getId()); updatedWatchDevice.setUpdateBy(sysUser.getId());
updatedWatchDevice.setDeptId(device.getDeptId()); // 这里修改成以用户的部门为准,更新手表的所属部门
updatedWatchDevice.setOrgCode(device.getOrgCode()); updatedWatchDevice.setDeptId(sysCache.getDepartIdByOrgCode(user.getOrgCode()));
updatedWatchDevice.setOrgCode(user.getOrgCode());
updateList.add(updatedWatchDevice); updateList.add(updatedWatchDevice);
} }
info1.setHandleMsg(index + "/" + count); info1.setHandleMsg(index + "/" + count);
@@ -38,6 +38,21 @@ public class WatchApiController {
return watchMonitorDataService.notice(json); return watchMonitorDataService.notice(json);
} }
/**
* 更新告警事件GPS位置信息接口
* 根据 watchNo + eventId 联合定位已有告警数据;
* 仅更新GPS相关字段,不推送大屏与短信;
* 内部会调用高德接口进行GPS84→GCJ02坐标转换与地址反查。
*
* @param json 入参(watchNo、eventId、lon、lat、address、locateTime、gpsErrorMsg
* @return 处理结果
*/
@PostMapping("/updateMonitorGps")
@Operation(summary = "更新告警事件GPS位置信息")
public AjaxJson updateMonitorGps(@RequestBody JSONObject json) {
return watchMonitorDataService.updateMonitorGps(json);
}
@GetMapping("/setData") @GetMapping("/setData")
public AjaxJson setData() { public AjaxJson setData() {
AjaxJson ajaxJson = new AjaxJson(); AjaxJson ajaxJson = new AjaxJson();
@@ -11,10 +11,7 @@ import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result; import org.jeecg.common.api.vo.Result;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@@ -327,4 +324,5 @@ public class WatchController {
// } // }
return result; return result;
} }
} }
@@ -185,6 +185,12 @@ public class WatchDeviceController extends JeecgController<WatchDevice, IWatchDe
return watchDeviceService.bindUser(dto); return watchDeviceService.bindUser(dto);
} }
@Operation(summary = "移动端绑定设备(手表)", description = "移动端绑定设备(手表)")
@GetMapping("/app/bindDevice")
public Result bindDevice(@RequestParam(name = "watchNo") String watchNo) throws ParseException {
return watchDeviceService.bindDevice(watchNo);
}
/** /**
* 解绑用户 * 解绑用户
* *
@@ -194,10 +200,18 @@ public class WatchDeviceController extends JeecgController<WatchDevice, IWatchDe
@Operation(summary = "解绑用户", description = "解绑用户") @Operation(summary = "解绑用户", description = "解绑用户")
@PostMapping(value = "/unbundleUser") @PostMapping(value = "/unbundleUser")
@RequiresPermissions("watch:watch_device:unbindUser") @RequiresPermissions("watch:watch_device:unbindUser")
public Result unbundleUser(@RequestBody() BindUserDTO dto) throws ParseException { public Result unbundleUser(@RequestBody() BindUserDTO dto) {
return watchDeviceService.unbundleUser(dto); return watchDeviceService.unbundleUser(dto);
} }
@Operation(summary = "移动端解绑设备(手表)", description = "移动端解绑设备(手表)")
@GetMapping("/app/unbundleDevice")
public Result unbundleDevice(@RequestParam(name = "watchNo") String watchNo) {
//移动端暂不允许解绑手表
return Result.error("请联系健康管理员解绑");
// return watchDeviceService.unbundleDevice(watchNo);
}
/** /**
* 设置上传频次 * 设置上传频次
* *
@@ -343,6 +357,10 @@ public class WatchDeviceController extends JeecgController<WatchDevice, IWatchDe
@DeleteMapping(value = "/delete") @DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name = "id", required = true) String id) { public Result<String> delete(@RequestParam(name = "id", required = true) String id) {
WatchDevice watchDevice = watchDeviceService.getById(id); WatchDevice watchDevice = watchDeviceService.getById(id);
// 已绑定用户的手表不允许删除
if (StringUtils.hasLength(watchDevice.getBindUserId())) {
return Result.error("该手表已绑定用户,请先解绑后再删除!");
}
watchDeviceService.removeById(id); watchDeviceService.removeById(id);
// 删除开关 // 删除开关
LambdaQueryWrapper<WatchDeviceSwitch> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<WatchDeviceSwitch> queryWrapper = new LambdaQueryWrapper<>();
@@ -422,6 +440,8 @@ public class WatchDeviceController extends JeecgController<WatchDevice, IWatchDe
} }
if (!StringUtils.hasLength(deptId) || "undefined".equals(deptId)) { if (!StringUtils.hasLength(deptId) || "undefined".equals(deptId)) {
throw new JeecgBootException("部门不能为空"); throw new JeecgBootException("部门不能为空");
//可为空,空则算入新疆油田公司
// deptId = sysCache.getDepartIdByOrgCode("A01");
} }
String sheetName = "设备导入"; String sheetName = "设备导入";
String fileName = sheetName + "_" + DateUtils.getDate("yyyyMMddHHmmss"); String fileName = sheetName + "_" + DateUtils.getDate("yyyyMMddHHmmss");
@@ -687,12 +707,12 @@ public class WatchDeviceController extends JeecgController<WatchDevice, IWatchDe
@Operation(summary = "获取时间范围的走跑数据", description = "获取时间范围的走跑数据") @Operation(summary = "获取时间范围的走跑数据", description = "获取时间范围的走跑数据")
@PostMapping("getSdcDataMapByUserIds") @PostMapping("getSdcDataMapByUserIds")
public Map<String,List<WatchStatUserInfoDaySdc>> getSdcDataMapByUserIds(@RequestBody List<String> userIds, public Map<String,List<WatchStatUserInfoDaySdc>> getSdcDataMapByUserIds(@RequestBody List<String> userIds,
@RequestParam(name = "startTime") @RequestParam(name = "startTime")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd") Date startTime, @DateTimeFormat(pattern = "yyyy-MM-dd") Date startTime,
@RequestParam(name = "endTime") @RequestParam(name = "endTime")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd") Date endTime) { @DateTimeFormat(pattern = "yyyy-MM-dd") Date endTime) {
return watchDeviceService.getSdcDataMapByUserIds(userIds, startTime, endTime); return watchDeviceService.getSdcDataMapByUserIds(userIds, startTime, endTime);
} }
@@ -66,7 +66,7 @@ public interface WatchDeviceMapper extends MPJBaseMapper<WatchDevice> {
List<String> selectDeviceUserId(@Param("deptId") String deptId); List<String> selectDeviceUserId(@Param("deptId") String deptId);
@Select(value = "SELECT LEFT(org_code,6) as orgCode, count(1) as medicalCount FROM watch_device GROUP BY LEFT(org_code,6)") @Select(value = "SELECT LEFT(org_code,6) as orgCode, count(1) as medicalCount FROM `watch_device` GROUP BY LEFT(org_code,6)")
List<JSONObject> getWatchSum(); List<JSONObject> getWatchSum();
List<WearCount> selectWearCount(@Param("orgCodeList") List<String> orgCodeList); List<WearCount> selectWearCount(@Param("orgCodeList") List<String> orgCodeList);
@@ -16,10 +16,10 @@ import java.util.Map;
@Mapper @Mapper
public interface WatchMapper { public interface WatchMapper {
@Select("SELECT ROUND(SYSDATE - (SELECT CAST(bind_date AS DATE) FROM watch_bind_his WHERE bind_user_id = #{id} ORDER BY bind_date DESC limit 1)) AS days") @Select("SELECT DATEDIFF(NOW(), (SELECT bind_date FROM watch_bind_his WHERE bind_user_id = #{id} ORDER BY bind_date DESC limit 1)) AS days")
Integer getUseDays(@Param("id") String id); Integer getUseDays(@Param("id") String id);
@Select("select length(nm.status) minutes,TO_CHAR(n.data_date,'YYYY-MM-DD') dataDate from watch_data_sleep_new_minute nm left join watch_data_sleep_new n on nm.sleep_id = n.id where n.id = ( select id from watch_data_sleep_new WHERE bind_user_id = #{id} order by data_date desc limit 1) and nm.STATUS not like '%55%' limit 1") @Select("select length(nm.status) minutes,DATE_FORMAT(n.data_date,'%Y-%m-%d') dataDate from watch_data_sleep_new_minute nm left join watch_data_sleep_new n on nm.sleep_id = n.id where n.id = ( select id from watch_data_sleep_new WHERE bind_user_id = #{id} order by data_date desc limit 1) and nm.STATUS not like '%55%' limit 1")
WatchDataDTO getDataSleep(@Param("id") String id); WatchDataDTO getDataSleep(@Param("id") String id);
/** /**
@@ -30,22 +30,22 @@ public interface WatchMapper {
@Select("SELECT long_duration_total minutes, data_date dataDate FROM watch_stat_user_info_day_sleep WHERE user_id = #{id} and long_duration_total > 0 ORDER BY data_date DESC LIMIT 1;") @Select("SELECT long_duration_total minutes, data_date dataDate FROM watch_stat_user_info_day_sleep WHERE user_id = #{id} and long_duration_total > 0 ORDER BY data_date DESC LIMIT 1;")
WatchDataDTO getDataSleepNew(@Param("id") String id); WatchDataDTO getDataSleepNew(@Param("id") String id);
@Select("SELECT AVG(ROUND((CAST(d.wake_up_time AS DATE) - CAST(d.fall_asleep_time AS DATE)) * 24 * 60)) AS aveMinute FROM watch_data_sleep_new_day d LEFT JOIN watch_data_sleep_new n ON d.sleep_id = n.id WHERE n.id IN (SELECT id FROM watch_data_sleep_new WHERE bind_user_id = #{id})") @Select("SELECT AVG(TIMESTAMPDIFF(MINUTE, d.fall_asleep_time, d.wake_up_time)) AS aveMinute FROM watch_data_sleep_new_day d LEFT JOIN watch_data_sleep_new n ON d.sleep_id = n.id WHERE n.id IN (SELECT id FROM watch_data_sleep_new WHERE bind_user_id = #{id})")
Double getAverageSleep(@Param("id") String id); Double getAverageSleep(@Param("id") String id);
@Select("select MAX(data_value) dataValue,data_date dataDate from watch_data_steps where bind_user_id = #{id} group by data_date order by data_date desc limit 1") @Select("select MAX(data_value) dataValue,data_date dataDate from watch_data_steps force index(bind_user_id) where bind_user_id = #{id} group by data_date order by data_date desc limit 1")
WatchDataDTO getDataSteps(@Param("id") String id); WatchDataDTO getDataSteps(@Param("id") String id);
@Select("SELECT SUM(data_value) FROM watch_data_distance WHERE bind_user_id = #{id}") @Select("SELECT SUM(data_value) FROM watch_data_distance WHERE bind_user_id = #{id}")
Integer getDataDistance(@Param("id") String id); Integer getDataDistance(@Param("id") String id);
@Select("SELECT CAST(data_value as INTEGER) dataValue,data_date dataDate from watch_data_heart_rate where bind_user_id = #{id} order by time_stamp desc limit 1") @Select("SELECT CAST(data_value as SIGNED) dataValue,data_date dataDate from watch_data_heart_rate where bind_user_id = #{id} order by time_stamp desc limit 1")
WatchDataDTO getHeartRate(@Param("id") String id); WatchDataDTO getHeartRate(@Param("id") String id);
@Select("SELECT CAST(data_value as INTEGER) dataValue,data_date dataDate from watch_data_spo2 where bind_user_id = #{id} order by time_stamp desc limit 1") @Select("SELECT CAST(data_value as SIGNED ) dataValue,data_date dataDate from watch_data_spo2 where bind_user_id = #{id} order by time_stamp desc limit 1")
WatchDataDTO getDataSpo2(@Param("id") String id); WatchDataDTO getDataSpo2(@Param("id") String id);
@Select("select cast(data_value as INTEGER) dataValue,data_date dataDate from watch_data_stress where bind_user_id = #{id} order by end_time_stamp desc limit 1") @Select("select cast(data_value as SIGNED ) dataValue,data_date dataDate from watch_data_stress where bind_user_id = #{id} order by end_time_stamp desc limit 1")
WatchDataDTO getStress(@Param("id") String id); WatchDataDTO getStress(@Param("id") String id);
@Select("select data_value dataValue,data_date dataDate from watch_data_temperature where bind_user_id = #{id} order by time_stamp desc limit 1") @Select("select data_value dataValue,data_date dataDate from watch_data_temperature where bind_user_id = #{id} order by time_stamp desc limit 1")
@@ -54,17 +54,17 @@ public interface WatchMapper {
@Select("SELECT * FROM watch_data_sleep_new_minute WHERE sleep_id IN (SELECT id FROM watch_data_sleep_new WHERE sleep_flag= '1' AND bind_user_id = #{id} AND data_date = #{date})") @Select("SELECT * FROM watch_data_sleep_new_minute WHERE sleep_id IN (SELECT id FROM watch_data_sleep_new WHERE sleep_flag= '1' AND bind_user_id = #{id} AND data_date = #{date})")
List<WatchDataSleepNewMinute> getNewMinuteList(@Param("id") String id, @Param("date") Date date); List<WatchDataSleepNewMinute> getNewMinuteList(@Param("id") String id, @Param("date") Date date);
@Select("SELECT DISTINCT data_date dateDate FROM watch_data_sleep_new WHERE TO_CHAR( data_date, 'YYYY-MM' ) = TO_CHAR(#{date}, 'YYYY-MM' ) AND bind_user_id = #{id} AND sleep_flag = '1'") @Select("SELECT DISTINCT data_date dateDate FROM watch_data_sleep_new WHERE DATE_FORMAT( data_date, '%Y-%m' ) = DATE_FORMAT(#{date}, '%Y-%m' ) AND bind_user_id = #{id} AND sleep_flag = '1'")
List<Date> getSleepNewDateList(@Param("id") String id, @Param("date") Date date); List<Date> getSleepNewDateList(@Param("id") String id, @Param("date") Date date);
List<Map<String, Object>> selectData(@Param("id") String id, @Param("format") String format, @Param("date") String date); List<Map<String, Object>> selectData(@Param("id") String id, @Param("format") String format, @Param("date") String date);
@Select("select max(data_value) maxValue,min(data_value) minValue,max(skin_tempera) maxSkinValue,min(skin_tempera) minSkinValue from watch_data_temperature where bind_user_id = #{id} and data_date = #{date}") @Select("select max(data_value) `maxValue`,min(data_value) `minValue`,max(skin_tempera) maxSkinValue,min(skin_tempera) minSkinValue from watch_data_temperature where bind_user_id = #{id} and data_date = #{date}")
Map<String, Object> getMapValue(@Param("id") String id, @Param("date") Date date); Map<String, Object> getMapValue(@Param("id") String id, @Param("date") Date date);
List<Map<String, Object>> getData(@Param("id") String id, @Param("format") String format, @Param("date") String date); List<Map<String, Object>> getData(@Param("id") String id, @Param("format") String format, @Param("date") String date);
@Select("select max(data_value) maxValue,min(data_value) minValue from watch_data_heart_rate where bind_user_id = #{id} and data_date = #{date}") @Select("select max(data_value) `maxValue`,min(data_value) `minValue` from watch_data_heart_rate where bind_user_id = #{id} and data_date = #{date}")
Map<String, Object> getMapRate(@Param("id") String id, @Param("date") Date date); Map<String, Object> getMapRate(@Param("id") String id, @Param("date") Date date);
Map<String, Object> getMapRateValue(@Param("id") String id, @Param("date") Date date); Map<String, Object> getMapRateValue(@Param("id") String id, @Param("date") Date date);
@@ -73,12 +73,12 @@ public interface WatchMapper {
List<Map<String, Object>> getMapDataValueFormat(@Param("id") String id, @Param("date") String date, @Param("format") String format); List<Map<String, Object>> getMapDataValueFormat(@Param("id") String id, @Param("date") String date, @Param("format") String format);
@Select("select max(data_value) maxValue,min(data_value) minValue ,round(avg(data_value)) avgValue from watch_data_stress where bind_user_id = #{id} and data_date = #{date}") @Select("select max(data_value) `maxValue`,min(data_value) `minValue` ,round(avg(data_value)) `avgValue` from watch_data_stress where bind_user_id = #{id} and data_date = #{date}")
Map<String, Object> getMapStress(@Param("id") String id, @Param("date") Date date); Map<String, Object> getMapStress(@Param("id") String id, @Param("date") Date date);
List<Map<String, Object>> getMapStressValueFormat(@Param("id") String id, @Param("date") String date, @Param("format") String format); List<Map<String, Object>> getMapStressValueFormat(@Param("id") String id, @Param("date") String date, @Param("format") String format);
@Select("select max(data_value) maxValue,min(data_value) minValue from watch_data_spo2 where bind_user_id = #{id} and data_date = #{date}") @Select("select max(data_value) `maxValue`,min(data_value) `minValue` from watch_data_spo2 where bind_user_id = #{id} and data_date = #{date}")
Map<String, Object> getMapSpo2(@Param("id") String id, @Param("date") Date date); Map<String, Object> getMapSpo2(@Param("id") String id, @Param("date") Date date);
@Select("select data_value lastValue from watch_data_spo2 where bind_user_id = #{id} and data_date = #{date} order by time_stamp desc limit 1") @Select("select data_value lastValue from watch_data_spo2 where bind_user_id = #{id} and data_date = #{date} order by time_stamp desc limit 1")
@@ -64,6 +64,6 @@ public interface WatchUserDataMapper extends BaseMapper<WatchUserData> {
* @param watchNo * @param watchNo
* @return * @return
*/ */
@Select("SELECT MAX(data_date) FROM watch_user_data where bind_user_id = #{userId} and watch_no = #{watchNo}") @Select("SELECT MAX(data_date) FROM `watch_user_data` where bind_user_id = #{userId} and watch_no = #{watchNo}")
Date lastDataDate(@Param("userId") String userId,@Param("watchNo") String watchNo); Date lastDataDate(@Param("userId") String userId,@Param("watchNo") String watchNo);
} }
@@ -51,7 +51,7 @@ public class WatchStatisticsProvider {
sb.append(orgCodeStr) sb.append(orgCodeStr)
.append(" as org_code, event_type, count(distinct bind_user_id) as warning_count ") .append(" as org_code, event_type, count(distinct bind_user_id) as warning_count ")
.append("from watch_monitor_data ") .append("from watch_monitor_data ")
.append("where warn_time between TRUNC(#{start}) and TRUNC(#{end}) + 1 - 1/86400 ") .append("where warn_time between date_format(#{start}, '%Y-%m-%d 00:00:00') and date_format(#{end}, '%Y-%m-%d 23:59:59') ")
.append("and event_type in ('heart_rate','spo2','stress','temperature_anomalies') "); .append("and event_type in ('heart_rate','spo2','stress','temperature_anomalies') ");
if (StrUtil.isNotEmpty(filter.getOrgCodeLeaf())) { if (StrUtil.isNotEmpty(filter.getOrgCodeLeaf())) {
sb.append("and org_code like CONCAT(#{orgCodeLeaf},'%')"); sb.append("and org_code like CONCAT(#{orgCodeLeaf},'%')");
@@ -65,11 +65,11 @@ public class WatchStatisticsProvider {
public String wearingDetail() { public String wearingDetail() {
return "SELECT " + return "SELECT " +
" max(wd.bind_user_id) as bind_user_id," + " max(wd.bind_user_id) as bind_user_id," +
" max(wbh.bind_date) as bind_date," + " max(distinct wbh.bind_date) as bind_date," +
" count(distinct wud.data_date) as date_count," + " count(distinct wud.data_date) as date_count," +
" wd.watch_no," + " wd.watch_no," +
" max(wd.org_code) as watch_org_code," + " max(wd.org_code) as watch_org_code," +
" LISTAGG(wud.data_date, ',') WITHIN GROUP (ORDER BY wud.data_date) as date_list" + " GROUP_CONCAT(distinct wud.data_date order by wud.data_date) as date_list" +
" FROM watch_device wd" + " FROM watch_device wd" +
" LEFT JOIN watch_bind_his wbh" + " LEFT JOIN watch_bind_his wbh" +
" ON wd.watch_no = wbh.watch_no AND wd.bind_user_id = wbh.bind_user_id AND wbh.bind_end_date IS NULL" + " ON wd.watch_no = wbh.watch_no AND wd.bind_user_id = wbh.bind_user_id AND wbh.bind_end_date IS NULL" +

Some files were not shown because too many files have changed in this diff Show More