Compare commits
61
Commits
4cb3411eca
...
xc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
570ed10c33 | ||
|
|
d47737de5e | ||
|
|
991dbabe8a | ||
|
|
2f5712a678 | ||
|
|
41bce5c0b2 | ||
|
|
5c8b56430d | ||
|
|
674891eba3 | ||
|
|
a8e8b53203 | ||
|
|
a835b874ad | ||
|
|
b6058c5f80 | ||
|
|
245cffecb0 | ||
|
|
b7525d6c7c | ||
|
|
1ad322c16a | ||
|
|
d08d20f1ee | ||
|
|
c260b1d79b | ||
|
|
1028a4e4e1 | ||
|
|
4a15ebe0d2 | ||
|
|
0ae963c4cf | ||
|
|
07d6f21fed | ||
|
|
26ae76a398 | ||
|
|
468314df64 | ||
|
|
3b7f260103 | ||
|
|
693749fece | ||
|
|
e9360d1ad9 | ||
|
|
ab0470c04c | ||
|
|
05c37fd532 | ||
|
|
670d82c868 | ||
|
|
c3afd0adfa | ||
|
|
44e8ac7da5 | ||
|
|
1167ac792e | ||
|
|
df41e0c8ce | ||
|
|
f6f70ebf32 | ||
|
|
661079dd3a | ||
|
|
9111cb40c6 | ||
|
|
3aa16600d8 | ||
|
|
32d8ad3652 | ||
|
|
b5c5251913 | ||
|
|
38a0aa07dd | ||
|
|
be701122ca | ||
|
|
1a5a2dcb3f | ||
|
|
fecfb2a355 | ||
|
|
f604d18b32 | ||
|
|
145cf89a89 | ||
|
|
d4f1d1a7bd | ||
|
|
2d5198ec3f | ||
|
|
e844fec480 | ||
|
|
194c3b2134 | ||
|
|
a1e5625ca7 | ||
|
|
e16c0c2536 | ||
|
|
66b77cc231 | ||
|
|
9b35cfe9c2 | ||
|
|
4898a63b4b | ||
|
|
37132eeeb6 | ||
|
|
8efc5bbd56 | ||
|
|
3c65f7eb24 | ||
|
|
bb95f1d78f | ||
|
|
1484f621bd | ||
|
|
f10221e92c | ||
|
|
945c0b46d7 | ||
|
|
74ecbe6bda | ||
|
|
fd7fd32c8d |
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
-- 1. 资源分类/标签统一表
|
-- 1. 资源分类/标签统一表
|
||||||
-- TYPE: 1=分类(树形), 2=标签(扁平)
|
-- TYPE: 1=分类(树形), 2=标签(扁平)
|
||||||
CREATE TABLE "QH_EME_FIRST_AID_RESOURCE_CATEGORY" (
|
CREATE TABLE "QH_EME_FIR_AID_RES_CATE" (
|
||||||
"ID" VARCHAR2(32) NOT NULL,
|
"ID" VARCHAR2(32) NOT NULL,
|
||||||
"NAME" VARCHAR2(100) NOT NULL,
|
"NAME" VARCHAR2(100) NOT NULL,
|
||||||
"TYPE" NUMBER(1) DEFAULT 1 NOT NULL,
|
"TYPE" NUMBER(1) DEFAULT 1 NOT NULL,
|
||||||
@@ -22,21 +22,21 @@ CREATE TABLE "QH_EME_FIRST_AID_RESOURCE_CATEGORY" (
|
|||||||
"MEMO" VARCHAR2(500),
|
"MEMO" VARCHAR2(500),
|
||||||
PRIMARY KEY ("ID")
|
PRIMARY KEY ("ID")
|
||||||
);
|
);
|
||||||
COMMENT ON TABLE "QH_EME_FIRST_AID_RESOURCE_CATEGORY" IS '急救宣教资源分类/标签';
|
COMMENT ON TABLE "QH_EME_FIR_AID_RES_CATE" IS '急救宣教资源分类/标签';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."ID" IS '主键';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."ID" IS '主键';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."NAME" IS '名称';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."NAME" IS '名称';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."TYPE" IS '类型:1=分类,2=标签';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."TYPE" IS '类型:1=分类,2=标签';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."PARENT_ID" IS '父分类ID(根分类为NULL,标签指向所属分类ID)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."PARENT_ID" IS '父分类ID(根分类为NULL,标签指向所属分类ID)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."DESCRIPTION" IS '描述';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."DESCRIPTION" IS '描述';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."SORT_NO" IS '排序号';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."SORT_NO" IS '排序号';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."STATUS" IS '状态(1=正常,2=冻结)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."STATUS" IS '状态(1=正常,2=冻结)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."DEL_FLAG" IS '删除标记(0=正常,1=已删除)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."DEL_FLAG" IS '删除标记(0=正常,1=已删除)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."MEMO" IS '备注';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."MEMO" IS '备注';
|
||||||
CREATE INDEX "IDX_FA_CATEGORY_TYPE" ON "QH_EME_FIRST_AID_RESOURCE_CATEGORY"("TYPE");
|
CREATE INDEX "IDX_FA_CATEGORY_TYPE" ON "QH_EME_FIR_AID_RES_CATE"("TYPE");
|
||||||
CREATE INDEX "IDX_FA_CATEGORY_PARENT_ID" ON "QH_EME_FIRST_AID_RESOURCE_CATEGORY"("PARENT_ID");
|
CREATE INDEX "IDX_FA_CATEGORY_PARENT_ID" ON "QH_EME_FIR_AID_RES_CATE"("PARENT_ID");
|
||||||
|
|
||||||
-- 2. 资源表
|
-- 2. 资源表
|
||||||
CREATE TABLE "QH_EME_FIRST_AID_RESOURCE" (
|
CREATE TABLE "QH_EME_FIR_AID_RES" (
|
||||||
"ID" VARCHAR2(32) NOT NULL,
|
"ID" VARCHAR2(32) NOT NULL,
|
||||||
"TITLE" VARCHAR2(200) NOT NULL,
|
"TITLE" VARCHAR2(200) NOT NULL,
|
||||||
"SUMMARY" VARCHAR2(500),
|
"SUMMARY" VARCHAR2(500),
|
||||||
@@ -65,35 +65,35 @@ CREATE TABLE "QH_EME_FIRST_AID_RESOURCE" (
|
|||||||
"MEMO" VARCHAR2(500),
|
"MEMO" VARCHAR2(500),
|
||||||
PRIMARY KEY ("ID")
|
PRIMARY KEY ("ID")
|
||||||
);
|
);
|
||||||
COMMENT ON TABLE "QH_EME_FIRST_AID_RESOURCE" IS '急救宣教资源';
|
COMMENT ON TABLE "QH_EME_FIR_AID_RES" IS '急救宣教资源';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."ID" IS '主键';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."ID" IS '主键';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."TITLE" IS '标题';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."TITLE" IS '标题';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."SUMMARY" IS '摘要/简介';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."SUMMARY" IS '摘要/简介';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."CONTENT_TYPE" IS '内容类型:IMAGE_TEXT=图文/VIDEO=视频/AUDIO=音频/PDF';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."CONTENT_TYPE" IS '内容类型:IMAGE_TEXT=图文/VIDEO=视频/AUDIO=音频/PDF';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."CATEGORY_ID" IS '所属分类ID';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."CATEGORY_ID" IS '所属分类ID';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."APPLICABLE_SCENARIO" IS '适用场景';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."APPLICABLE_SCENARIO" IS '适用场景';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."TAGS" IS '标签ID列表(逗号分隔)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."TAGS" IS '标签ID列表(逗号分隔)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."CONTENT" IS '正文内容(富文本HTML)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."CONTENT" IS '正文内容(富文本HTML)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."COVER_IMAGE" IS '封面图URL';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."COVER_IMAGE" IS '封面图URL';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."FILE_URL" IS '附件URL列表(JSON数组)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."FILE_URL" IS '附件URL列表(JSON数组)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."EFFECTIVE_TIME" IS '生效时间';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."EFFECTIVE_TIME" IS '生效时间';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."EXPIRY_TIME" IS '失效时间';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."EXPIRY_TIME" IS '失效时间';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."AUDIT_STATUS" IS '审核状态(NULL=无审核/10=待审核/11=已通过/12=已驳回)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."AUDIT_STATUS" IS '审核状态(NULL=无审核/10=待审核/11=已通过/12=已驳回)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."AUDIT_REJECT_REASON" IS '驳回原因';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."AUDIT_REJECT_REASON" IS '驳回原因';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."AUDIT_BY" IS '审核人';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."AUDIT_BY" IS '审核人';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."AUDIT_BY_ID" IS '审核人ID';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."AUDIT_BY_ID" IS '审核人ID';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."AUDIT_TIME" IS '审核时间';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."AUDIT_TIME" IS '审核时间';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."VIEW_COUNT" IS '浏览次数';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."VIEW_COUNT" IS '浏览次数';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."FAVORITE_COUNT" IS '收藏次数';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."FAVORITE_COUNT" IS '收藏次数';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."STATUS" IS '发布状态(0=草稿,1=已发布,2=已下架)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."STATUS" IS '发布状态(0=草稿,1=已发布,2=已下架)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."DEL_FLAG" IS '删除标记(0=正常,1=已删除)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."DEL_FLAG" IS '删除标记(0=正常,1=已删除)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."MEMO" IS '备注';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."MEMO" IS '备注';
|
||||||
CREATE INDEX "IDX_FA_RESOURCE_CATEGORY_ID" ON "QH_EME_FIRST_AID_RESOURCE"("CATEGORY_ID");
|
CREATE INDEX "IDX_FA_RESOURCE_CATEGORY_ID" ON "QH_EME_FIR_AID_RES"("CATEGORY_ID");
|
||||||
CREATE INDEX "IDX_FA_RESOURCE_AUDIT_STATUS" ON "QH_EME_FIRST_AID_RESOURCE"("AUDIT_STATUS");
|
CREATE INDEX "IDX_FA_RESOURCE_AUDIT_STATUS" ON "QH_EME_FIR_AID_RES"("AUDIT_STATUS");
|
||||||
CREATE INDEX "IDX_FA_RESOURCE_EFFECTIVE_TIME" ON "QH_EME_FIRST_AID_RESOURCE"("EFFECTIVE_TIME");
|
CREATE INDEX "IDX_FA_RESOURCE_EFFECTIVE_TIME" ON "QH_EME_FIR_AID_RES"("EFFECTIVE_TIME");
|
||||||
|
|
||||||
-- 3. 用户行为记录表(阅读+收藏)
|
-- 3. 用户行为记录表(阅读+收藏)
|
||||||
CREATE TABLE "QH_EME_FIRST_AID_RESOURCE_USER_ACTION" (
|
CREATE TABLE "QH_EME_FIR_AID_RES_UACT" (
|
||||||
"ID" VARCHAR2(32) NOT NULL,
|
"ID" VARCHAR2(32) NOT NULL,
|
||||||
"RESOURCE_ID" VARCHAR2(32) NOT NULL,
|
"RESOURCE_ID" VARCHAR2(32) NOT NULL,
|
||||||
"USER_ID" VARCHAR2(50) NOT NULL,
|
"USER_ID" VARCHAR2(50) NOT NULL,
|
||||||
@@ -101,16 +101,16 @@ CREATE TABLE "QH_EME_FIRST_AID_RESOURCE_USER_ACTION" (
|
|||||||
"CREATE_TIME" TIMESTAMP,
|
"CREATE_TIME" TIMESTAMP,
|
||||||
PRIMARY KEY ("ID")
|
PRIMARY KEY ("ID")
|
||||||
);
|
);
|
||||||
COMMENT ON TABLE "QH_EME_FIRST_AID_RESOURCE_USER_ACTION" IS '用户行为记录(阅读/收藏)';
|
COMMENT ON TABLE "QH_EME_FIR_AID_RES_UACT" IS '用户行为记录(阅读/收藏)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_USER_ACTION"."ID" IS '主键';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_UACT"."ID" IS '主键';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_USER_ACTION"."RESOURCE_ID" IS '资源ID';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_UACT"."RESOURCE_ID" IS '资源ID';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_USER_ACTION"."USER_ID" IS '用户ID';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_UACT"."USER_ID" IS '用户ID';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_USER_ACTION"."TYPE" IS '行为类型:1=阅读,2=收藏';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_UACT"."TYPE" IS '行为类型:1=阅读,2=收藏';
|
||||||
CREATE UNIQUE INDEX "UK_FA_USER_ACTION" ON "QH_EME_FIRST_AID_RESOURCE_USER_ACTION"("RESOURCE_ID", "USER_ID", "TYPE");
|
CREATE UNIQUE INDEX "UK_FA_USER_ACTION" ON "QH_EME_FIR_AID_RES_UACT"("RESOURCE_ID", "USER_ID", "TYPE");
|
||||||
CREATE INDEX "IDX_FA_USER_ACTION_USER_TYPE" ON "QH_EME_FIRST_AID_RESOURCE_USER_ACTION"("USER_ID", "TYPE");
|
CREATE INDEX "IDX_FA_USER_ACTION_USER_TYPE" ON "QH_EME_FIR_AID_RES_UACT"("USER_ID", "TYPE");
|
||||||
|
|
||||||
-- 4. 版本历史表
|
-- 4. 版本历史表
|
||||||
CREATE TABLE "QH_EME_FIRST_AID_RESOURCE_VERSION" (
|
CREATE TABLE "QH_EME_FIR_AID_RES_VER" (
|
||||||
"ID" VARCHAR2(32) NOT NULL,
|
"ID" VARCHAR2(32) NOT NULL,
|
||||||
"RESOURCE_ID" VARCHAR2(32) NOT NULL,
|
"RESOURCE_ID" VARCHAR2(32) NOT NULL,
|
||||||
"VERSION_NO" NUMBER(10) NOT NULL,
|
"VERSION_NO" NUMBER(10) NOT NULL,
|
||||||
@@ -122,18 +122,18 @@ CREATE TABLE "QH_EME_FIRST_AID_RESOURCE_VERSION" (
|
|||||||
"CREATE_TIME" TIMESTAMP,
|
"CREATE_TIME" TIMESTAMP,
|
||||||
PRIMARY KEY ("ID")
|
PRIMARY KEY ("ID")
|
||||||
);
|
);
|
||||||
COMMENT ON TABLE "QH_EME_FIRST_AID_RESOURCE_VERSION" IS '资源版本历史';
|
COMMENT ON TABLE "QH_EME_FIR_AID_RES_VER" IS '资源版本历史';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_VERSION"."ID" IS '主键';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_VER"."ID" IS '主键';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_VERSION"."RESOURCE_ID" IS '资源ID';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_VER"."RESOURCE_ID" IS '资源ID';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_VERSION"."VERSION_NO" IS '版本号';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_VER"."VERSION_NO" IS '版本号';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_VERSION"."TITLE" IS '版本时的标题';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_VER"."TITLE" IS '版本时的标题';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_VERSION"."CONTENT" IS '版本时的正文内容';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_VER"."CONTENT" IS '版本时的正文内容';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_VERSION"."CHANGE_DESCRIPTION" IS '变更描述';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_VER"."CHANGE_DESCRIPTION" IS '变更描述';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_VERSION"."IS_CURRENT" IS '是否当前版本(1=是,0=否)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_VER"."IS_CURRENT" IS '是否当前版本(1=是,0=否)';
|
||||||
CREATE INDEX "IDX_FA_VERSION_RESOURCE_ID" ON "QH_EME_FIRST_AID_RESOURCE_VERSION"("RESOURCE_ID");
|
CREATE INDEX "IDX_FA_VERSION_RESOURCE_ID" ON "QH_EME_FIR_AID_RES_VER"("RESOURCE_ID");
|
||||||
|
|
||||||
-- 5. 审核记录表
|
-- 5. 审核记录表
|
||||||
CREATE TABLE "QH_EME_FIRST_AID_RESOURCE_AUDIT" (
|
CREATE TABLE "QH_EME_FIR_AID_RES_AUD" (
|
||||||
"ID" VARCHAR2(32) NOT NULL,
|
"ID" VARCHAR2(32) NOT NULL,
|
||||||
"RESOURCE_ID" VARCHAR2(32) NOT NULL,
|
"RESOURCE_ID" VARCHAR2(32) NOT NULL,
|
||||||
"AUDIT_STATUS" NUMBER(2),
|
"AUDIT_STATUS" NUMBER(2),
|
||||||
@@ -144,19 +144,19 @@ CREATE TABLE "QH_EME_FIRST_AID_RESOURCE_AUDIT" (
|
|||||||
"CREATE_TIME" TIMESTAMP DEFAULT SYSDATE,
|
"CREATE_TIME" TIMESTAMP DEFAULT SYSDATE,
|
||||||
PRIMARY KEY ("ID")
|
PRIMARY KEY ("ID")
|
||||||
);
|
);
|
||||||
COMMENT ON TABLE "QH_EME_FIRST_AID_RESOURCE_AUDIT" IS '急救宣教资源审核记录';
|
COMMENT ON TABLE "QH_EME_FIR_AID_RES_AUD" IS '急救宣教资源审核记录';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_AUDIT"."ID" IS '主键';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_AUD"."ID" IS '主键';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_AUDIT"."RESOURCE_ID" IS '关联资源ID';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_AUD"."RESOURCE_ID" IS '关联资源ID';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_AUDIT"."AUDIT_STATUS" IS '审核状态:10=待审核,11=已通过,12=已驳回';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_AUD"."AUDIT_STATUS" IS '审核状态:10=待审核,11=已通过,12=已驳回';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_AUDIT"."AUDIT_REJECT_REASON" IS '驳回原因';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_AUD"."AUDIT_REJECT_REASON" IS '驳回原因';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_AUDIT"."AUDIT_BY" IS '审核人';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_AUD"."AUDIT_BY" IS '审核人';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_AUDIT"."AUDIT_BY_ID" IS '审核人ID';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_AUD"."AUDIT_BY_ID" IS '审核人ID';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_AUDIT"."AUDIT_TIME" IS '审核时间';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_AUD"."AUDIT_TIME" IS '审核时间';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_AUDIT"."CREATE_TIME" IS '创建时间';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_AUD"."CREATE_TIME" IS '创建时间';
|
||||||
CREATE INDEX "IDX_FA_AUDIT_RESOURCE_ID" ON "QH_EME_FIRST_AID_RESOURCE_AUDIT"("RESOURCE_ID");
|
CREATE INDEX "IDX_FA_AUDIT_RESOURCE_ID" ON "QH_EME_FIR_AID_RES_AUD"("RESOURCE_ID");
|
||||||
|
|
||||||
-- 6. 推送记录表
|
-- 6. 推送记录表
|
||||||
CREATE TABLE "QH_EME_FIRST_AID_PUSH_RECORD" (
|
CREATE TABLE "QH_EME_FIR_AID_PUSH_RD" (
|
||||||
"ID" VARCHAR2(32) NOT NULL,
|
"ID" VARCHAR2(32) NOT NULL,
|
||||||
"RESOURCE_ID" VARCHAR2(32) NOT NULL,
|
"RESOURCE_ID" VARCHAR2(32) NOT NULL,
|
||||||
"RESOURCE_TITLE" VARCHAR2(200) DEFAULT NULL,
|
"RESOURCE_TITLE" VARCHAR2(200) DEFAULT NULL,
|
||||||
@@ -169,17 +169,17 @@ CREATE TABLE "QH_EME_FIRST_AID_PUSH_RECORD" (
|
|||||||
PRIMARY KEY ("ID"),
|
PRIMARY KEY ("ID"),
|
||||||
CONSTRAINT "UK_ORDER_RESOURCE" UNIQUE ("ORDER_ID", "RESOURCE_ID")
|
CONSTRAINT "UK_ORDER_RESOURCE" UNIQUE ("ORDER_ID", "RESOURCE_ID")
|
||||||
);
|
);
|
||||||
COMMENT ON TABLE "QH_EME_FIRST_AID_PUSH_RECORD" IS '急救宣教推送记录表';
|
COMMENT ON TABLE "QH_EME_FIR_AID_PUSH_RD" IS '急救宣教推送记录表';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_PUSH_RECORD"."ID" IS '主键';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_PUSH_RD"."ID" IS '主键';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_PUSH_RECORD"."RESOURCE_ID" IS '资源ID';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_PUSH_RD"."RESOURCE_ID" IS '资源ID';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_PUSH_RECORD"."RESOURCE_TITLE" IS '资源标题(冗余)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_PUSH_RD"."RESOURCE_TITLE" IS '资源标题(冗余)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_PUSH_RECORD"."ORDER_ID" IS '关联应急工单ID';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_PUSH_RD"."ORDER_ID" IS '关联应急工单ID';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_PUSH_RECORD"."TARGET_USER_ID" IS '推送目标用户ID';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_PUSH_RD"."TARGET_USER_ID" IS '推送目标用户ID';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_PUSH_RECORD"."PUSH_BY" IS '推送人';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_PUSH_RD"."PUSH_BY" IS '推送人';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_PUSH_RECORD"."PUSH_BY_ID" IS '推送人ID';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_PUSH_RD"."PUSH_BY_ID" IS '推送人ID';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_PUSH_RECORD"."PUSH_TIME" IS '推送时间';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_PUSH_RD"."PUSH_TIME" IS '推送时间';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_PUSH_RECORD"."TENANT_ID" IS '租户ID';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_PUSH_RD"."TENANT_ID" IS '租户ID';
|
||||||
CREATE INDEX "IDX_FA_PUSH_RECORD_ORDER_ID" ON "QH_EME_FIRST_AID_PUSH_RECORD"("ORDER_ID");
|
CREATE INDEX "IDX_FA_PUSH_RECORD_ORDER_ID" ON "QH_EME_FIR_AID_PUSH_RD"("ORDER_ID");
|
||||||
|
|
||||||
-- 7. 字典数据
|
-- 7. 字典数据
|
||||||
-- 7.1 内容类型
|
-- 7.1 内容类型
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
-- =====================================================
|
||||||
|
-- 缩短急救宣教相关表名(达梦数据库)
|
||||||
|
-- 原因:原表名超过数据库限制
|
||||||
|
-- 日期:2026-08-10
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
-- 1. 急救资源分类表
|
||||||
|
ALTER TABLE QH_EME_FIRST_AID_RESOURCE_CATEGORY RENAME TO QH_EME_FIR_AID_RES_CATE;
|
||||||
|
|
||||||
|
-- 2. 用户操作记录表
|
||||||
|
ALTER TABLE QH_EME_FIRST_AID_RESOURCE_USER_ACTION RENAME TO QH_EME_FIR_AID_RES_UACT;
|
||||||
|
|
||||||
|
-- 3. 资源版本表
|
||||||
|
ALTER TABLE QH_EME_FIRST_AID_RESOURCE_VERSION RENAME TO QH_EME_FIR_AID_RES_VER;
|
||||||
|
|
||||||
|
-- 4. 资源审核表
|
||||||
|
ALTER TABLE QH_EME_FIRST_AID_RESOURCE_AUDIT RENAME TO QH_EME_FIR_AID_RES_AUD;
|
||||||
|
|
||||||
|
-- 5. 推送记录表
|
||||||
|
ALTER TABLE QH_EME_FIRST_AID_PUSH_RECORD RENAME TO QH_EME_FIR_AID_PUSH_RD;
|
||||||
|
|
||||||
|
-- 6. 急救资源主表(最后执行,避免外键依赖)
|
||||||
|
ALTER TABLE QH_EME_FIRST_AID_RESOURCE RENAME TO QH_EME_FIR_AID_RES;
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 验证:确认新表名已生效
|
||||||
|
-- SELECT TABLE_NAME FROM USER_TABLES WHERE TABLE_NAME LIKE 'QH_EME_FIR_AID_%';
|
||||||
|
-- =====================================================
|
||||||
@@ -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");
|
||||||
+46
-2
@@ -258,8 +258,11 @@ public class AnYanClientExecutor implements AnYanClient {
|
|||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public AuthResult publicNetworkTokenNoCache() {
|
* @description: 旧版公网获取token实现(SM4 + AnYanResult 包裹解密),保留备份
|
||||||
|
* @author PengJ
|
||||||
|
*/
|
||||||
|
public AuthResult publicNetworkTokenNoCacheBAK() {
|
||||||
JSONObject param = new JSONObject();
|
JSONObject param = new JSONObject();
|
||||||
String password = anYanProperties.getPublicPassWrod();
|
String password = anYanProperties.getPublicPassWrod();
|
||||||
String userName = anYanProperties.getPublicUserNmae();
|
String userName = anYanProperties.getPublicUserNmae();
|
||||||
@@ -289,6 +292,47 @@ public class AnYanClientExecutor implements AnYanClient {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 公网获取token(密码模式,调用方式与 getAuthTokenByPassword 保持一致)
|
||||||
|
* 表单提交 + 公网 host + QUERY_AUTH_TOKEN,仅 RSA 加密密码,不写 Redis(缓存由调用方负责)
|
||||||
|
* @author PengJ
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AuthResult publicNetworkTokenNoCache() {
|
||||||
|
String username = anYanProperties.getPublicUserNmae();
|
||||||
|
String password = anYanProperties.getPublicPassWrod();
|
||||||
|
try {
|
||||||
|
// 仅 RSA 加密密码,与 getAuthTokenByPassword 保持一致
|
||||||
|
String encryptPassword = StringUtils.encryptByPublicKey(publicKey, password);
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
|
||||||
|
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
|
||||||
|
formData.add("grant_type", "password");
|
||||||
|
formData.add("username", username);
|
||||||
|
formData.add("password", encryptPassword);
|
||||||
|
formData.add("client_id", anYanProperties.getClientId());
|
||||||
|
formData.add("client_secret", anYanProperties.getClientSecret());
|
||||||
|
ResponseEntity<AuthResult> authResult = RestTemplateUtil.postExchangeForGetTokenByPassword(AnYanApiEnum.QUERY_AUTH_TOKEN, formData, headers, AuthResult.class);
|
||||||
|
if (HttpStatus.OK.equals(authResult.getStatusCode())
|
||||||
|
&& ObjectUtils.isNotEmpty(authResult.getBody())) {
|
||||||
|
return authResult.getBody();
|
||||||
|
} else {
|
||||||
|
log.error("------安眼系统获取公网token失败{}------", authResult.getBody());
|
||||||
|
ExceptionAssertsUtil.fail("------安眼系统获取公网token失败------" + authResult.getBody());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (HttpClientErrorException e) {
|
||||||
|
log.error("------安眼系统获取公网token失败{}------", e.getMessage());
|
||||||
|
String replace = Objects.requireNonNull(e.getMessage()).replace("401 Unauthorized: ", "");
|
||||||
|
replace = replace.replace("\"", "");
|
||||||
|
AuthResult bean = JSONUtil.toBean(replace, AuthResult.class);
|
||||||
|
ExceptionAssertsUtil.fail(bean.getMessage());
|
||||||
|
} catch (Exception e) {
|
||||||
|
ExceptionAssertsUtil.fail(e.getMessage());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description: 根据token获取用户信息
|
* @description: 根据token获取用户信息
|
||||||
* @author PengJ
|
* @author PengJ
|
||||||
|
|||||||
+10
-1
@@ -1,5 +1,6 @@
|
|||||||
package com.renkang.anyan.config;
|
package com.renkang.anyan.config;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.renkang.anyan.enums.AnYanApiEnum;
|
import com.renkang.anyan.enums.AnYanApiEnum;
|
||||||
import com.renkang.anyan.model.vo.AnYanResult;
|
import com.renkang.anyan.model.vo.AnYanResult;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -81,7 +82,15 @@ public class RestTemplateUtil {
|
|||||||
public static <T> ResponseEntity<T> postExchangeForGetToken(AnYanApiEnum api, Object requestBody, Class<T> responseType) {
|
public static <T> ResponseEntity<T> postExchangeForGetToken(AnYanApiEnum api, Object requestBody, Class<T> responseType) {
|
||||||
String url = getProperties().getPublicHost() + api.getMethodPath() + api.getMethodParam();
|
String url = getProperties().getPublicHost() + api.getMethodPath() + api.getMethodParam();
|
||||||
HttpEntity<Object> requestEntity = new HttpEntity<>(requestBody);
|
HttpEntity<Object> requestEntity = new HttpEntity<>(requestBody);
|
||||||
return getRestTemplate().exchange(url, api.getHttpMethod(), requestEntity, responseType);
|
// 打印请求入参,便于排查
|
||||||
|
String bodyJson = JSON.toJSONString(requestBody);
|
||||||
|
log.info("安眼获取token请求入参: url={}, body={}", url, bodyJson);
|
||||||
|
// 打印等价 curl(application/json),便于本地手动调试
|
||||||
|
log.info("安眼获取token等价curl: curl -X POST '{}' -H 'Content-Type: application/json' -d '{}'", url, bodyJson);
|
||||||
|
ResponseEntity<T> response = getRestTemplate().exchange(url, api.getHttpMethod(), requestEntity, responseType);
|
||||||
|
// 打印返回信息(状态码 + 响应体)
|
||||||
|
log.info("安眼获取token返回信息: statusCode={}, body={}", response.getStatusCode(), JSON.toJSONString(response.getBody()));
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+25
@@ -15,24 +15,31 @@ import com.renkang.consultation.entity.ConDoctorExAndUser;
|
|||||||
import com.renkang.consultation.service.IConDoctorService;
|
import com.renkang.consultation.service.IConDoctorService;
|
||||||
import com.renkang.consultation.util.TempUtil;
|
import com.renkang.consultation.util.TempUtil;
|
||||||
import com.renkang.consultation.vo.ConDoctorVO;
|
import com.renkang.consultation.vo.ConDoctorVO;
|
||||||
|
import com.renkang.im.api.IMHelloApi;
|
||||||
|
import com.renkang.im.entity.ConSessionRequestDO;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.SecurityUtils;
|
||||||
|
import org.jeecg.bean.request.ListUser;
|
||||||
import org.jeecg.common.api.vo.Result;
|
import org.jeecg.common.api.vo.Result;
|
||||||
import org.jeecg.common.constant.CommonConstant;
|
import org.jeecg.common.constant.CommonConstant;
|
||||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||||
import org.jeecg.common.system.util.DictUtil;
|
import org.jeecg.common.system.util.DictUtil;
|
||||||
import org.jeecg.common.system.vo.DictModel;
|
import org.jeecg.common.system.vo.DictModel;
|
||||||
import org.jeecg.common.system.vo.LoginUser;
|
import org.jeecg.common.system.vo.LoginUser;
|
||||||
|
import org.jeecg.common.system.vo.LoginUserNew;
|
||||||
import org.jeecg.util.RSAEncryptUtils;
|
import org.jeecg.util.RSAEncryptUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping(RequestPrefix.conDoctor)
|
@RequestMapping(RequestPrefix.conDoctor)
|
||||||
public class ConDoctorApiController {
|
public class ConDoctorApiController {
|
||||||
@@ -46,6 +53,8 @@ public class ConDoctorApiController {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DictUtil dictUtil;
|
private DictUtil dictUtil;
|
||||||
|
@Autowired
|
||||||
|
private IMHelloApi imHelloApi;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页列表查询
|
* 分页列表查询
|
||||||
@@ -133,12 +142,28 @@ public class ConDoctorApiController {
|
|||||||
}
|
}
|
||||||
boolean flag = conDoctorService.updateById(conDoctor);
|
boolean flag = conDoctorService.updateById(conDoctor);
|
||||||
if (flag){
|
if (flag){
|
||||||
|
// 同步IM个人资料
|
||||||
|
syncImProfile(conDoctor.getId());
|
||||||
return Result.ok("更新成功!");
|
return Result.ok("更新成功!");
|
||||||
}
|
}
|
||||||
return Result.error("更新失败!");
|
return Result.error("更新失败!");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void syncImProfile(String userId) {
|
||||||
|
try {
|
||||||
|
List<LoginUserNew> users = isysBaseApi.listUserByIds(new ListUser(Collections.singletonList(userId)));
|
||||||
|
if (CollectionUtils.isEmpty(users)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ConSessionRequestDO req = new ConSessionRequestDO();
|
||||||
|
req.setAccountList(Collections.singletonList(users.get(0)));
|
||||||
|
imHelloApi.accountReg(req);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("同步IM个人资料失败, userId: {}", userId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Operation(summary = "查询医生信息", description = "查询医生信息")
|
@Operation(summary = "查询医生信息", description = "查询医生信息")
|
||||||
@GetMapping("/selectDoctorInfo")
|
@GetMapping("/selectDoctorInfo")
|
||||||
|
|||||||
+21
-4
@@ -19,6 +19,8 @@ import com.renkang.consultation.mapper.ConSessionMapper;
|
|||||||
import com.renkang.consultation.service.IConDoctorService;
|
import com.renkang.consultation.service.IConDoctorService;
|
||||||
import com.renkang.consultation.service.IConSessionService;
|
import com.renkang.consultation.service.IConSessionService;
|
||||||
import com.renkang.consultation.vo.ConDoctorExportVO;
|
import com.renkang.consultation.vo.ConDoctorExportVO;
|
||||||
|
import com.renkang.im.api.IMHelloApi;
|
||||||
|
import com.renkang.im.entity.ConSessionRequestDO;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
@@ -62,10 +64,7 @@ import java.io.ByteArrayInputStream;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -98,6 +97,8 @@ public class AsyncExportService {
|
|||||||
private ConHelperMapper conHelperMapper;
|
private ConHelperMapper conHelperMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
private AsyncTaskExecutor taskExecutor;
|
private AsyncTaskExecutor taskExecutor;
|
||||||
|
@Autowired
|
||||||
|
private IMHelloApi imHelloApi;
|
||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void userToDoctorExportXls(ConSessionDTO dto, CommonExportsInfo info, String empFinish, String errCode, String sheetName, String fileName) {
|
public void userToDoctorExportXls(ConSessionDTO dto, CommonExportsInfo info, String empFinish, String errCode, String sheetName, String fileName) {
|
||||||
@@ -580,6 +581,8 @@ public class AsyncExportService {
|
|||||||
BeanUtils.copyProperties(excelVo, conDoctor);
|
BeanUtils.copyProperties(excelVo, conDoctor);
|
||||||
conDoctor.setId(userId);
|
conDoctor.setId(userId);
|
||||||
conDoctorService.saveDoctor(conDoctor);
|
conDoctorService.saveDoctor(conDoctor);
|
||||||
|
// 同步注册IM账号
|
||||||
|
importImAccount(userId);
|
||||||
info.setHandleMsg(index++ + "/" + userList.size());
|
info.setHandleMsg(index++ + "/" + userList.size());
|
||||||
info.setExportStatus("0");
|
info.setExportStatus("0");
|
||||||
info.setId(commonExportsInfo.getId());
|
info.setId(commonExportsInfo.getId());
|
||||||
@@ -598,6 +601,20 @@ public class AsyncExportService {
|
|||||||
sysBaseAPI.updateExportsInfo(info);
|
sysBaseAPI.updateExportsInfo(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void importImAccount(String userId) {
|
||||||
|
try {
|
||||||
|
List<LoginUserNew> users = sysBaseAPI.listUserByIds(new ListUser(Collections.singletonList(userId)));
|
||||||
|
if (CollectionUtils.isEmpty(users)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ConSessionRequestDO req = new ConSessionRequestDO();
|
||||||
|
req.setAccountList(java.util.Collections.singletonList(users.get(0)));
|
||||||
|
imHelloApi.accountReg(req);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("导入IM账号失败, userId: {}", userId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class UserToDoctorExportHandler implements PoiExportHandler<UserToDoctorExport, SessionFilter> {
|
private class UserToDoctorExportHandler implements PoiExportHandler<UserToDoctorExport, SessionFilter> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -275,7 +275,7 @@
|
|||||||
|
|
||||||
## 2. 标签管理 `emergency/firstAid/tag`
|
## 2. 标签管理 `emergency/firstAid/tag`
|
||||||
|
|
||||||
标签与分类共用 `QH_EME_FIRST_AID_RESOURCE_CATEGORY` 表,`type=2` 区分。标签通过 `parentId` 绑定到分类。
|
标签与分类共用 `QH_EME_FIR_AID_RES_CATE` 表,`type=2` 区分。标签通过 `parentId` 绑定到分类。
|
||||||
|
|
||||||
### 2.1 分页列表 `GET /tag/list`
|
### 2.1 分页列表 `GET /tag/list`
|
||||||
|
|
||||||
|
|||||||
+164
-17
@@ -1,5 +1,15 @@
|
|||||||
# 急救模块移动端 API 文档
|
# 急救模块移动端 API 文档
|
||||||
|
|
||||||
|
## 🆕 本次变更(前端联调)
|
||||||
|
|
||||||
|
| # | 接口 | 变更类型 | 说明 |
|
||||||
|
|---|------|:---:|------------------------------------------------------------------------------|
|
||||||
|
| 1 | `GET /createGroupMagFirstAider` | **废除** | 已废除,功能由 `createGroupMag` 承接 |
|
||||||
|
| 2 | `GET /order/myParticipatedOrders` | **新增** | App端查询当前登录人参与的应急工单列表(sessionNow=1),返回被救助人信息 |
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
> **基础信息**
|
> **基础信息**
|
||||||
> 网关地址: `http://{gateway-host}:{port}`(前端加 `/health-emergency` 前缀)
|
> 网关地址: `http://{gateway-host}:{port}`(前端加 `/health-emergency` 前缀)
|
||||||
> 服务直连: `http://{host}:7011`(调试用,不加前缀)
|
> 服务直连: `http://{host}:7011`(调试用,不加前缀)
|
||||||
@@ -14,6 +24,7 @@
|
|||||||
|
|
||||||
1. [应急群聊拉人](#1-应急群聊拉人-apiemergency)
|
1. [应急群聊拉人](#1-应急群聊拉人-apiemergency)
|
||||||
2. [宣教资源](#2-宣教资源-apiemergencyfirstaidresource)
|
2. [宣教资源](#2-宣教资源-apiemergencyfirstaidresource)
|
||||||
|
3. [工单列表](#3-工单列表-apiemergencyorder)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -39,7 +50,15 @@
|
|||||||
"userId": "xxx", "realname": "张医生", "avatar": "https://...",
|
"userId": "xxx", "realname": "张医生", "avatar": "https://...",
|
||||||
"type": "6", "centerId": "xxx",
|
"type": "6", "centerId": "xxx",
|
||||||
"post": "主任医师", "school": "北京大学", "edu": "博士",
|
"post": "主任医师", "school": "北京大学", "edu": "博士",
|
||||||
"goodAt": "心血管内科", "deptName": "急诊科"
|
"goodAt": "心血管内科", "deptName": "急诊科", "phone": "13800000001",
|
||||||
|
"doctorName": "张医生", "doctorNo": "XJ-001", "photo": "https://...",
|
||||||
|
"resourceName": "新疆人民医院", "departmentId": "xxx",
|
||||||
|
"departmentName": "急诊科", "doctorTitle": "主任医师",
|
||||||
|
"doctorJob": "科长", "doctorStatus": "1", "isAccept": "1",
|
||||||
|
"doctorType": "1", "audioStatus": "1", "tfJumpHoliday": "0",
|
||||||
|
"experience": "从事心血管内科临床工作20年...",
|
||||||
|
"sort": 100, "tfRecommend": "1",
|
||||||
|
"introduction": "擅长心血管疾病的诊治..."
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"total": 50, "size": 10, "current": 1
|
"total": 50, "size": 10, "current": 1
|
||||||
@@ -58,6 +77,25 @@
|
|||||||
| edu | 学历 |
|
| edu | 学历 |
|
||||||
| goodAt | 擅长领域 |
|
| goodAt | 擅长领域 |
|
||||||
| deptName | 科室 |
|
| deptName | 科室 |
|
||||||
|
| phone | 手机号 |
|
||||||
|
| **↓ 以下字段来源于咨询服务专家表(qh_con_doctor),非专家时为 null** |
|
||||||
|
| doctorName | 医生姓名 |
|
||||||
|
| doctorNo | 专家编号 |
|
||||||
|
| photo | 医生头像 |
|
||||||
|
| resourceName | 所属医院名称 |
|
||||||
|
| departmentId | 科室ID |
|
||||||
|
| departmentName | 科室名称 |
|
||||||
|
| doctorTitle | 职务(z_doct_lev 字典) |
|
||||||
|
| doctorJob | 职称(z_doct_job 字典) |
|
||||||
|
| doctorStatus | 专家状态(doc_status 字典) |
|
||||||
|
| isAccept | 是否开启咨询(z_doct_sta 字典: 1开启/3关闭) |
|
||||||
|
| doctorType | 专家类型(z_doct_typ 字典: 1收费/2免费/3其他/4义诊) |
|
||||||
|
| audioStatus | 是否提供音视频 |
|
||||||
|
| tfJumpHoliday | 是否跳过节假日 |
|
||||||
|
| experience | 执业经历 |
|
||||||
|
| sort | 排序 |
|
||||||
|
| tfRecommend | 是否推荐(0否/1是) |
|
||||||
|
| introduction | 简介 |
|
||||||
|
|
||||||
### 1.2 搜索员工 `GET /order/searchEmployee`
|
### 1.2 搜索员工 `GET /order/searchEmployee`
|
||||||
|
|
||||||
@@ -105,9 +143,13 @@
|
|||||||
| latitude | String | 是 | 纬度 |
|
| latitude | String | 是 | 纬度 |
|
||||||
| type | String | 否 | 类型 |
|
| type | String | 否 | 类型 |
|
||||||
|
|
||||||
> 返回 `groupId`(群组ID),作为后续拉人接口的入参。
|
> 返回 `groupId`(群组ID),作为后续拉人接口的入参。**此接口会发起音视频通话。**
|
||||||
|
|
||||||
### 1.4 邀请进群 `POST /addGroupUser`
|
### 1.4 创建群聊-急救员 `GET /createGroupMagFirstAider` ⚠️ 已废除
|
||||||
|
|
||||||
|
> ⚠️ 本接口已废除,功能由 `createGroupMag` 承接,请勿调用。
|
||||||
|
|
||||||
|
### 1.5 邀请进群 `POST /addGroupUser`
|
||||||
|
|
||||||
拉专家或员工加入应急群聊。
|
拉专家或员工加入应急群聊。
|
||||||
|
|
||||||
@@ -133,7 +175,7 @@
|
|||||||
|
|
||||||
> 已在群中的人员会自动跳过,不会报错。所有选中的人都在群中时返回失败。
|
> 已在群中的人员会自动跳过,不会报错。所有选中的人都在群中时返回失败。
|
||||||
|
|
||||||
### 1.5 移除群成员 `POST /removeGroupUser`
|
### 1.6 移除群成员 `POST /removeGroupUser`
|
||||||
|
|
||||||
```json
|
```json
|
||||||
// Request Body
|
// Request Body
|
||||||
@@ -152,7 +194,9 @@
|
|||||||
|
|
||||||
> 只能移除后续拉入的协助人员,不能移除发起人和初始操作/专业人员。
|
> 只能移除后续拉入的协助人员,不能移除发起人和初始操作/专业人员。
|
||||||
|
|
||||||
### 1.6 群成员列表 `GET /order/getGroupMemberList`
|
### 1.7 群成员列表 `GET /order/getGroupMemberList`
|
||||||
|
|
||||||
|
> ⚠️ 本接口仅查本地 DB,不验证腾讯 IM。**建议改用 1.8 `/order/getActualGroupMemberList`。**
|
||||||
|
|
||||||
| 参数 | 类型 | 必填 | 说明 |
|
| 参数 | 类型 | 必填 | 说明 |
|
||||||
|------|------|:---:|------|
|
|------|------|:---:|------|
|
||||||
@@ -161,11 +205,11 @@
|
|||||||
```json
|
```json
|
||||||
// 响应 result
|
// 响应 result
|
||||||
[
|
[
|
||||||
{ "orderId": "...", "userId": "发起人id", "userName": "李四", "avatar": "https://...", "isGroupMember": 1, "memberType": -1 },
|
{ "orderId": "...", "userId": "发起人id", "userName": "李四", "avatar": "https://...", "phone": "13800000001", "isGroupMember": 1, "memberType": -1 },
|
||||||
{ "orderId": "...", "userId": "操作人员id", "userName": "王五", "avatar": "https://...", "isGroupMember": 1, "memberType": 0 },
|
{ "orderId": "...", "userId": "操作人员id", "userName": "王五", "avatar": "https://...", "phone": "13800000002", "isGroupMember": 1, "memberType": 0 },
|
||||||
{ "orderId": "...", "userId": "专业人员id", "userName": "张医生", "avatar": "https://...", "isGroupMember": 1, "memberType": 1 },
|
{ "orderId": "...", "userId": "专业人员id", "userName": "张医生", "avatar": "https://...", "phone": "13800000003", "isGroupMember": 1, "memberType": 1 },
|
||||||
{ "orderId": "...", "userId": "员工id", "userName": "张三", "avatar": "https://...", "isGroupMember": 1, "memberType": 2 },
|
{ "orderId": "...", "userId": "员工id", "userName": "张三", "avatar": "https://...", "phone": "13800000004", "isGroupMember": 1, "memberType": 2 },
|
||||||
{ "orderId": "...", "userId": "其他专业人id", "userName": "赵医生", "avatar": "https://...", "isGroupMember": 0, "memberType": 1 }
|
{ "orderId": "...", "userId": "其他专业人id", "userName": "赵医生", "avatar": "https://...", "phone": "13800000005", "isGroupMember": 0, "memberType": 1 }
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -175,10 +219,86 @@
|
|||||||
| userId | 用户ID |
|
| userId | 用户ID |
|
||||||
| userName | 姓名 |
|
| userName | 姓名 |
|
||||||
| avatar | 头像 |
|
| avatar | 头像 |
|
||||||
|
| phone | 手机号 |
|
||||||
| isGroupMember | `1`=在群中, `0`=可邀请 |
|
| isGroupMember | `1`=在群中, `0`=可邀请 |
|
||||||
| memberType | `-1`=发起人, `0`=操作人员, `1`=专业人员, `2`=员工 |
|
| memberType | `-1`=发起人, `0`=操作人员, `1`=专业人员, `2`=员工 |
|
||||||
|
|
||||||
### 1.7 memberType 字典
|
### 1.8 实际群成员列表 `GET /order/getActualGroupMemberList` 🆕
|
||||||
|
|
||||||
|
> **与 1.7 的区别**:本接口先查本地参与人员,再调用腾讯 IM `get_group_member_info` API 获取群内实际成员,以 IM 成员为准取交集,确保返回的都是 IM 群中真实存在的成员。**不过滤本人,通过 `isSelf` 标识。**
|
||||||
|
|
||||||
|
| 参数 | 类型 | 必填 | 说明 |
|
||||||
|
|------|------|:---:|------|
|
||||||
|
| sessionId | String | 是 | 群组ID |
|
||||||
|
|
||||||
|
```json
|
||||||
|
// 响应 result(与 getGroupMemberList 格式完全一致,但不过滤本人)
|
||||||
|
[
|
||||||
|
{ "orderId": "...", "userId": "当前用户id", "userName": "我", "avatar": "https://...", "phone": "13800000000", "isGroupMember": 1, "memberType": 0, "isSelf": 1 },
|
||||||
|
{ "orderId": "...", "userId": "发起人id", "userName": "李四", "avatar": "https://...", "phone": "13800000001", "isGroupMember": 1, "memberType": -1, "isSelf": 0 },
|
||||||
|
{ "orderId": "...", "userId": "专业人员id", "userName": "张医生", "avatar": "https://...", "phone": "13800000003", "isGroupMember": 1, "memberType": 1, "isSelf": 0 }
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
| 字段 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| orderId | 应急单ID |
|
||||||
|
| userId | 用户ID |
|
||||||
|
| userName | 姓名 |
|
||||||
|
| avatar | 头像 |
|
||||||
|
| phone | 手机号 |
|
||||||
|
| isGroupMember | 始终为 `1`(所有返回成员均经 IM 验证在群中) |
|
||||||
|
| memberType | `-1`=发起人, `0`=操作人员, `1`=专业人员, `2`=员工 |
|
||||||
|
| isSelf | `0`=不是本人, `1`=是本人 |
|
||||||
|
|
||||||
|
> **建议**:前端优先使用本接口获取群成员列表,1.7 接口后续可淘汰。
|
||||||
|
|
||||||
|
### 1.9 当前登录人参与的应急工单列表 `GET /order/myParticipatedOrders` 🆕
|
||||||
|
|
||||||
|
> App端接口:查询当前登录人参与过的、正在应急(`sessionNow=1`)的工单列表,返回被救助人信息。
|
||||||
|
|
||||||
|
| 参数 | 类型 | 必填 | 说明 |
|
||||||
|
|------|------|:---:|------|
|
||||||
|
| pageNo | Integer | 否 | 页码,默认1 |
|
||||||
|
| pageSize | Integer | 否 | 每页条数,默认10 |
|
||||||
|
|
||||||
|
```json
|
||||||
|
// 响应 result
|
||||||
|
{
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"orderId": "2074305914885640194",
|
||||||
|
"sessionId": "2074305910070706176",
|
||||||
|
"salvageUserName": "张三",
|
||||||
|
"salvageUserSex": "1",
|
||||||
|
"salvageUserAvatar": "https://fileserver.yg.dt.io/xxx.png",
|
||||||
|
"salvageUserAge": 35,
|
||||||
|
"salvageUserMobile": "13800000000",
|
||||||
|
"orgName": "新疆油田公司",
|
||||||
|
"deptName": "安全环保部",
|
||||||
|
"orderStatus": "1",
|
||||||
|
"initTime": "2026-07-20 10:30:00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total": 5, "size": 10, "current": 1
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| orderId | String | 应急单ID |
|
||||||
|
| sessionId | String | 会话ID |
|
||||||
|
| salvageUserName | String | 被救助人姓名 |
|
||||||
|
| salvageUserSex | String | 被救助人性别(字典: sex2) |
|
||||||
|
| salvageUserAvatar | String | 被救助人头像 |
|
||||||
|
| salvageUserAge | Integer | 被救助人年龄 |
|
||||||
|
| salvageUserMobile | String | 被救助人手机号 |
|
||||||
|
| orgName | String | 单位名称(二级单位) |
|
||||||
|
| deptName | String | 部门名称 |
|
||||||
|
| orderStatus | String | 应急单状态(字典: emergency_order_status) |
|
||||||
|
| initTime | Date | 发起时间 |
|
||||||
|
|
||||||
|
### 1.10 memberType 字典
|
||||||
|
|
||||||
| 值 | 含义 | 场景 |
|
| 值 | 含义 | 场景 |
|
||||||
|:---:|------|------|
|
|:---:|------|------|
|
||||||
@@ -189,14 +309,24 @@
|
|||||||
|
|
||||||
### 典型调用流程
|
### 典型调用流程
|
||||||
|
|
||||||
|
**应急就医(带音视频通话)**:
|
||||||
```
|
```
|
||||||
1. 创建群聊
|
1. 创建群聊
|
||||||
GET /health-emergency/api/emergency/createGroupMag?name=xxx&longitude=xxx&latitude=xxx
|
GET /health-emergency/api/emergency/createGroupMag?name=xxx&longitude=xxx&latitude=xxx
|
||||||
|
|
||||||
2. 查看当前成员
|
2. 查看当前成员 → 搜索要拉的人 → 确认邀请 → 移除成员 → 刷新列表
|
||||||
GET /health-emergency/api/emergency/order/getGroupMemberList?sessionId={groupId}
|
GET /health-emergency/api/emergency/order/getActualGroupMemberList?sessionId={groupId}
|
||||||
→ 展示群成员列表(按 memberType 区分标签展示)
|
(以下步骤同急救员流程)
|
||||||
→ isGroupMember=0 的显示为"可邀请"
|
```
|
||||||
|
|
||||||
|
**急救员**:
|
||||||
|
```
|
||||||
|
1. 创建群聊
|
||||||
|
GET /health-emergency/api/emergency/createGroupMag?name=xxx&longitude=xxx&latitude=xxx
|
||||||
|
|
||||||
|
2. 查看当前成员(🔀 替换原 /order/getGroupMemberList)
|
||||||
|
GET /health-emergency/api/emergency/order/getActualGroupMemberList?sessionId={groupId}
|
||||||
|
→ 返回经腾讯IM验证的实际群成员,新增 isSelf 字段区分本人
|
||||||
|
|
||||||
3. 搜索要拉的人
|
3. 搜索要拉的人
|
||||||
GET /health-emergency/api/emergency/order/searchExpert?realname=张&excludeSessionId={groupId}
|
GET /health-emergency/api/emergency/order/searchExpert?realname=张&excludeSessionId={groupId}
|
||||||
@@ -211,8 +341,8 @@
|
|||||||
POST /health-emergency/api/emergency/removeGroupUser
|
POST /health-emergency/api/emergency/removeGroupUser
|
||||||
{"groupId": "{groupId}", "memberList": ["id1"]}
|
{"groupId": "{groupId}", "memberList": ["id1"]}
|
||||||
|
|
||||||
6. 刷新成员列表
|
6. 刷新成员列表(🔀 替换原 /order/getGroupMemberList)
|
||||||
GET /health-emergency/api/emergency/order/getGroupMemberList?sessionId={groupId}
|
GET /health-emergency/api/emergency/order/getActualGroupMemberList?sessionId={groupId}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -273,3 +403,20 @@
|
|||||||
| expiryTime | Date | 失效时间 |
|
| expiryTime | Date | 失效时间 |
|
||||||
| createTime | Date | 创建时间 |
|
| createTime | Date | 创建时间 |
|
||||||
| updateTime | Date | 更新时间 |
|
| updateTime | Date | 更新时间 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 工单列表 `/api/emergency/order`
|
||||||
|
|
||||||
|
> 网关完整路径: `/health-emergency/api/emergency/order`
|
||||||
|
|
||||||
|
### 3.1 当前登录人参与的应急工单列表 `GET /myParticipatedOrders` 🆕
|
||||||
|
|
||||||
|
**业务逻辑**:
|
||||||
|
1. 查 `QH_EME_ORDER_OPERATOR` 表获取当前登录人参与的所有工单ID(去重)
|
||||||
|
2. 查 `QH_EME_ORDER` 表筛选 `sessionNow=1` 的工单,按创建时间倒序
|
||||||
|
3. 返回被救助人(`salvage` 字段)信息 + 单位/部门名称
|
||||||
|
|
||||||
|
> **调用时机**:登录用户在急救页面查看自己正在参与中的应急工单。仅返回 IM 会话进行中的工单(`sessionNow=1`)。
|
||||||
|
|
||||||
|
请求和响应格式见 **[1.9 当前登录人参与的应急工单列表](#19-当前登录人参与的应急工单列表-get-ordermyparticipatedorders-)**。
|
||||||
|
|||||||
+12
@@ -20,4 +20,16 @@ public class SendIm {
|
|||||||
* 类型 1: 应急单
|
* 类型 1: 应急单
|
||||||
*/
|
*/
|
||||||
private Integer type;
|
private Integer type;
|
||||||
|
/**
|
||||||
|
* 业务标识,用于区分不同业务来源(例:"article"=宣教推送)
|
||||||
|
*/
|
||||||
|
private String businessId;
|
||||||
|
/**
|
||||||
|
* 消息图片URL(封面图全路径)
|
||||||
|
*/
|
||||||
|
private String messageImageUrl;
|
||||||
|
/**
|
||||||
|
* 文章ID(宣教资源ID)
|
||||||
|
*/
|
||||||
|
private String resourceId;
|
||||||
}
|
}
|
||||||
|
|||||||
+62
@@ -130,4 +130,66 @@ public class EmergencyProfessionUser implements Serializable {
|
|||||||
// 科室名称
|
// 科室名称
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
private String deptName;
|
private String deptName;
|
||||||
|
|
||||||
|
// 手机号(非持久字段,查询时填充)
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String phone;
|
||||||
|
|
||||||
|
// ===== 以下字段来源于 qh_con_doctor(咨询服务医生表),查询时批量填充 =====
|
||||||
|
// 医生姓名
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String doctorName;
|
||||||
|
// 专家编号
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String doctorNo;
|
||||||
|
// 医生头像
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String photo;
|
||||||
|
// 医院名称
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String resourceName;
|
||||||
|
// 科室id
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String departmentId;
|
||||||
|
// 科室名称
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String departmentName;
|
||||||
|
// 职务
|
||||||
|
@TableField(exist = false)
|
||||||
|
@Dict(dicCode = "z_doct_lev")
|
||||||
|
private String doctorTitle;
|
||||||
|
// 职称
|
||||||
|
@TableField(exist = false)
|
||||||
|
@Dict(dicCode = "z_doct_job")
|
||||||
|
private String doctorJob;
|
||||||
|
// 专家状态
|
||||||
|
@TableField(exist = false)
|
||||||
|
@Dict(dicCode = "doc_status")
|
||||||
|
private String doctorStatus;
|
||||||
|
// 是否开启咨询(1开启 3关闭)
|
||||||
|
@TableField(exist = false)
|
||||||
|
@Dict(dicCode = "z_doct_sta")
|
||||||
|
private String isAccept;
|
||||||
|
// 专家类型(z_doct_typ) —— 避免与人员type冲突,命名为doctorType
|
||||||
|
@TableField(exist = false)
|
||||||
|
@Dict(dicCode = "z_doct_typ")
|
||||||
|
private String doctorType;
|
||||||
|
// 是否提供音视频
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String audioStatus;
|
||||||
|
// 是否跳过节假日
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String tfJumpHoliday;
|
||||||
|
// 执业经历
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String experience;
|
||||||
|
// 排序
|
||||||
|
@TableField(exist = false)
|
||||||
|
private Integer sort;
|
||||||
|
// 是否推荐(0否1是)
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String tfRecommend;
|
||||||
|
// 简介
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String introduction;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ import java.util.Date;
|
|||||||
* @Date: 2026-06-24
|
* @Date: 2026-06-24
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@TableName("QH_EME_FIRST_AID_PUSH_RECORD")
|
@TableName("QH_EME_FIR_AID_PUSH_RD")
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
@EqualsAndHashCode(callSuper = false)
|
@EqualsAndHashCode(callSuper = false)
|
||||||
@Schema(title = "first_aid_push_record对象", description = "急救宣教推送记录")
|
@Schema(title = "first_aid_push_record对象", description = "急救宣教推送记录")
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ import lombok.experimental.Accessors;
|
|||||||
* @Version: V1.0
|
* @Version: V1.0
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@TableName("QH_EME_FIRST_AID_RESOURCE")
|
@TableName("QH_EME_FIR_AID_RES")
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
@EqualsAndHashCode(callSuper = false)
|
@EqualsAndHashCode(callSuper = false)
|
||||||
@Schema(title = "first_aid_resource对象", description = "急救宣教资源")
|
@Schema(title = "first_aid_resource对象", description = "急救宣教资源")
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ import java.util.Date;
|
|||||||
* @Version: V1.0
|
* @Version: V1.0
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@TableName("QH_EME_FIRST_AID_RESOURCE_AUDIT")
|
@TableName("QH_EME_FIR_AID_RES_AUD")
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
@EqualsAndHashCode(callSuper = false)
|
@EqualsAndHashCode(callSuper = false)
|
||||||
@Schema(title = "first_aid_resource_audit对象", description = "急救宣教资源审核记录")
|
@Schema(title = "first_aid_resource_audit对象", description = "急救宣教资源审核记录")
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ import lombok.experimental.Accessors;
|
|||||||
* @Version: V1.0
|
* @Version: V1.0
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@TableName("QH_EME_FIRST_AID_RESOURCE_CATEGORY")
|
@TableName("QH_EME_FIR_AID_RES_CATE")
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
@EqualsAndHashCode(callSuper = false)
|
@EqualsAndHashCode(callSuper = false)
|
||||||
@Schema(title = "first_aid_resource_category对象", description = "急救宣教资源分类/标签")
|
@Schema(title = "first_aid_resource_category对象", description = "急救宣教资源分类/标签")
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@ import lombok.experimental.Accessors;
|
|||||||
* @Version: V1.0
|
* @Version: V1.0
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@TableName("QH_EME_FIRST_AID_RESOURCE_USER_ACTION")
|
@TableName("QH_EME_FIR_AID_RES_UACT")
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
@EqualsAndHashCode(callSuper = false)
|
@EqualsAndHashCode(callSuper = false)
|
||||||
@Schema(title = "first_aid_resource_user_action对象", description = "用户行为记录(阅读/收藏)")
|
@Schema(title = "first_aid_resource_user_action对象", description = "用户行为记录(阅读/收藏)")
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@ import lombok.experimental.Accessors;
|
|||||||
* @Version: V1.0
|
* @Version: V1.0
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@TableName("QH_EME_FIRST_AID_RESOURCE_VERSION")
|
@TableName("QH_EME_FIR_AID_RES_VER")
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
@EqualsAndHashCode(callSuper = false)
|
@EqualsAndHashCode(callSuper = false)
|
||||||
@Schema(title = "first_aid_resource_version对象", description = "资源版本历史")
|
@Schema(title = "first_aid_resource_version对象", description = "资源版本历史")
|
||||||
|
|||||||
+2
-2
@@ -35,9 +35,9 @@ public class OrderOperator implements Serializable {
|
|||||||
private String orderId;
|
private String orderId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 人员类型(人员类型0:操作人员 1:专业人员)
|
* 人员类型(0:操作人员 1:专业人员 3:急救人员1 4:急救人员2 5:关爱联络员)
|
||||||
*/
|
*/
|
||||||
@Schema(title = "人员类型(人员类型0:操作人员 1:专业人员 2:员工)")
|
@Schema(title = "人员类型(0:操作人员 1:专业人员 2:员工 3:急救人员1 4:急救人员2 5:关爱联络员)")
|
||||||
private Integer operatorType;
|
private Integer operatorType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+12
@@ -48,4 +48,16 @@ public class GroupMemberVO {
|
|||||||
@Schema(title = "成员类型(-1:发起人, 0:操作人员, 1:专业人员, 2:员工)")
|
@Schema(title = "成员类型(-1:发起人, 0:操作人员, 1:专业人员, 2:员工)")
|
||||||
private Integer memberType;
|
private Integer memberType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号
|
||||||
|
*/
|
||||||
|
@Schema(title = "手机号")
|
||||||
|
private String phone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否是当前登录用户, 0:不是, 1:是
|
||||||
|
*/
|
||||||
|
@Schema(title = "是否是当前登录用户, 0:不是, 1:是")
|
||||||
|
private Integer isSelf = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+53
@@ -0,0 +1,53 @@
|
|||||||
|
package com.renkang.emergency.entity.vo;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* App端:当前登录人参与的应急工单VO
|
||||||
|
*
|
||||||
|
* @author PengJ
|
||||||
|
* @date 2026/7/20
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MyParticipatedOrderVO {
|
||||||
|
|
||||||
|
@Schema(title = "应急单ID")
|
||||||
|
private String orderId;
|
||||||
|
|
||||||
|
@Schema(title = "会话ID")
|
||||||
|
private String sessionId;
|
||||||
|
|
||||||
|
@Schema(title = "被救助人姓名")
|
||||||
|
private String salvageUserName;
|
||||||
|
|
||||||
|
@Schema(title = "被救助人性别", description = "字典: sex2")
|
||||||
|
private String salvageUserSex;
|
||||||
|
|
||||||
|
@Schema(title = "被救助人头像")
|
||||||
|
private String salvageUserAvatar;
|
||||||
|
|
||||||
|
@Schema(title = "被救助人年龄")
|
||||||
|
private Integer salvageUserAge;
|
||||||
|
|
||||||
|
@Schema(title = "被救助人手机号")
|
||||||
|
private String salvageUserMobile;
|
||||||
|
|
||||||
|
@Schema(title = "单位名称")
|
||||||
|
private String orgName;
|
||||||
|
|
||||||
|
@Schema(title = "部门名称")
|
||||||
|
private String deptName;
|
||||||
|
|
||||||
|
@Schema(title = "应急单状态", description = "字典: emergency_order_status")
|
||||||
|
private String orderStatus;
|
||||||
|
|
||||||
|
@Schema(title = "发起时间")
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
private Date initTime;
|
||||||
|
}
|
||||||
+9
@@ -104,6 +104,15 @@ public class EmergencyApiController {
|
|||||||
return Result.OK(emergencyApiService.createGroupMag(name, longitude, latitude, type));
|
return Result.OK(emergencyApiService.createGroupMag(name, longitude, latitude, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
@Operation(summary = "[已废弃] 创建群聊-应急就医-急救员,请使用 /createGroupMag")
|
||||||
|
@GetMapping(value = "/createGroupMagFirstAider")
|
||||||
|
public Result<CreateGroupMagVO> createGroupMagFirstAider(@RequestParam("name") String name,
|
||||||
|
@RequestParam("longitude") String longitude,
|
||||||
|
@RequestParam("latitude") String latitude) {
|
||||||
|
return Result.OK(emergencyApiService.createGroupMagFirstAider(name, longitude, latitude));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Operation(summary = "创建群聊-干预")
|
@Operation(summary = "创建群聊-干预")
|
||||||
@GetMapping(value = "/createGroupMagIntervene")
|
@GetMapping(value = "/createGroupMagIntervene")
|
||||||
|
|||||||
+15
@@ -18,6 +18,7 @@ import com.renkang.emergency.entity.OrderDetail;
|
|||||||
import com.renkang.emergency.entity.OrderSendRecord;
|
import com.renkang.emergency.entity.OrderSendRecord;
|
||||||
import com.renkang.emergency.entity.vo.EmployeeVO;
|
import com.renkang.emergency.entity.vo.EmployeeVO;
|
||||||
import com.renkang.emergency.entity.vo.GroupMemberVO;
|
import com.renkang.emergency.entity.vo.GroupMemberVO;
|
||||||
|
import com.renkang.emergency.entity.vo.MyParticipatedOrderVO;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
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;
|
||||||
@@ -298,6 +299,12 @@ public class EmergencyOrderApiController {
|
|||||||
return Result.OK(emergencyOrderApiService.getGroupMemberList(sessionId));
|
return Result.OK(emergencyOrderApiService.getGroupMemberList(sessionId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "获取实际群成员列表(腾讯IM验证)")
|
||||||
|
@GetMapping("/getActualGroupMemberList")
|
||||||
|
public Result<List<GroupMemberVO>> getActualGroupMemberList(@RequestParam("sessionId") String sessionId) {
|
||||||
|
return Result.OK(emergencyOrderApiService.getActualGroupMemberList(sessionId));
|
||||||
|
}
|
||||||
|
|
||||||
@Operation(summary = "搜索专家/专业人员")
|
@Operation(summary = "搜索专家/专业人员")
|
||||||
@GetMapping("/searchExpert")
|
@GetMapping("/searchExpert")
|
||||||
public Result<IPage<EmergencyProfessionUser>> searchExpert(
|
public Result<IPage<EmergencyProfessionUser>> searchExpert(
|
||||||
@@ -322,4 +329,12 @@ public class EmergencyOrderApiController {
|
|||||||
return Result.OK(emergencyOrderApiService.searchEmployee(realname, orgCode, workNo, phone, excludeSessionId, pageNo, pageSize));
|
return Result.OK(emergencyOrderApiService.searchEmployee(realname, orgCode, workNo, phone, excludeSessionId, pageNo, pageSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询当前登录人参与的应急工单列表")
|
||||||
|
@GetMapping("/myParticipatedOrders")
|
||||||
|
public Result<IPage<MyParticipatedOrderVO>> myParticipatedOrders(
|
||||||
|
@RequestParam(defaultValue = "1") Integer pageNo,
|
||||||
|
@RequestParam(defaultValue = "10") Integer pageSize) {
|
||||||
|
return Result.OK(emergencyOrderApiService.myParticipatedOrders(pageNo, pageSize));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-2
@@ -28,12 +28,19 @@ public class FirstAidResourceApiController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IFirstAidResourceService resourceService;
|
private IFirstAidResourceService resourceService;
|
||||||
|
|
||||||
@Operation(summary = "根据宣教ID查询详情")
|
@Operation(summary = "根据宣教ID查询详情(含阅读记录)")
|
||||||
@GetMapping("/queryById")
|
@GetMapping("/queryById")
|
||||||
public Result<FirstAidResource> queryById(@RequestParam("id") String id) {
|
public Result<FirstAidResource> queryById(@RequestParam("id") String id) {
|
||||||
LoginUser loginUser = GlobalUtils.getLoginUser();
|
LoginUser loginUser = GlobalUtils.getLoginUser();
|
||||||
String userId = loginUser != null ? loginUser.getId() : null;
|
String userId = loginUser != null ? loginUser.getId() : null;
|
||||||
FirstAidResource entity = resourceService.getDetail(id, userId);
|
FirstAidResource entity = resourceService.getDetail(id, userId);
|
||||||
return entity == null ? Result.error("未找到对应数据") : Result.OK(entity);
|
if (entity == null) {
|
||||||
|
return Result.error("未找到对应数据");
|
||||||
|
}
|
||||||
|
// 记录阅读(已读自动去重)
|
||||||
|
if (userId != null) {
|
||||||
|
resourceService.incrementViewCount(id, userId);
|
||||||
|
}
|
||||||
|
return Result.OK(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
@@ -33,11 +33,22 @@ public interface EmergencyApiService {
|
|||||||
|
|
||||||
CreateGroupMagVO createGroupMag(String name, String longitude, String latitude, String type);
|
CreateGroupMagVO createGroupMag(String name, String longitude, String latitude, String type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [已废弃] 创建群聊-应急就医-急救员,请使用 {@link #createGroupMag}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
CreateGroupMagVO createGroupMagFirstAider(String name, String longitude, String latitude);
|
||||||
|
|
||||||
Result<Map<String, Object>> createGroupMagIntervene(String name, String longitude, String latitude, String type);
|
Result<Map<String, Object>> createGroupMagIntervene(String name, String longitude, String latitude, String type);
|
||||||
|
|
||||||
List<String> fixOrderStatus();
|
List<String> fixOrderStatus();
|
||||||
|
|
||||||
boolean addGroupUser(AddOtherMemberDTO dto);
|
boolean addGroupUser(AddOtherMemberDTO dto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拉入关爱联络员和急救人员到群聊(兜底补拉用,失败不抛异常)
|
||||||
|
*/
|
||||||
|
void addCareUsersToGroup(String userId, String groupId, String orderId);
|
||||||
|
|
||||||
boolean removeGroupUser(RemoveGroupMemberDTO dto);
|
boolean removeGroupUser(RemoveGroupMemberDTO dto);
|
||||||
}
|
}
|
||||||
|
|||||||
+11
@@ -16,6 +16,7 @@ import com.renkang.emergency.entity.OrderSendRecord;
|
|||||||
import com.renkang.emergency.entity.TblHelpCentorVo;
|
import com.renkang.emergency.entity.TblHelpCentorVo;
|
||||||
import com.renkang.emergency.entity.vo.EmployeeVO;
|
import com.renkang.emergency.entity.vo.EmployeeVO;
|
||||||
import com.renkang.emergency.entity.vo.GroupMemberVO;
|
import com.renkang.emergency.entity.vo.GroupMemberVO;
|
||||||
|
import com.renkang.emergency.entity.vo.MyParticipatedOrderVO;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -77,8 +78,18 @@ public interface EmergencyOrderApiService {
|
|||||||
|
|
||||||
List<GroupMemberVO> getGroupMemberList(String sessionId);
|
List<GroupMemberVO> getGroupMemberList(String sessionId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取实际群成员列表(先查本地参与人员,再匹配腾讯IM实际群成员)
|
||||||
|
*/
|
||||||
|
List<GroupMemberVO> getActualGroupMemberList(String sessionId);
|
||||||
|
|
||||||
IPage<EmergencyProfessionUser> searchExpert(String realname, String centerId, String excludeSessionId, Integer pageNo, Integer pageSize);
|
IPage<EmergencyProfessionUser> searchExpert(String realname, String centerId, String excludeSessionId, Integer pageNo, Integer pageSize);
|
||||||
|
|
||||||
IPage<EmployeeVO> searchEmployee(String realname, String orgCode, String workNo, String phone, String excludeSessionId, Integer pageNo, Integer pageSize);
|
IPage<EmployeeVO> searchEmployee(String realname, String orgCode, String workNo, String phone, String excludeSessionId, Integer pageNo, Integer pageSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询当前登录人参与的应急工单列表 + 自己发起/被救助的应急工单
|
||||||
|
*/
|
||||||
|
IPage<MyParticipatedOrderVO> myParticipatedOrders(Integer pageNo, Integer pageSize);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+311
-8
@@ -7,7 +7,11 @@ import cn.hutool.core.util.ObjectUtil;
|
|||||||
import cn.hutool.core.util.StrUtil;
|
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.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.renkang.anyan.client.AnYanClient;
|
||||||
|
import com.renkang.anyan.model.dto.EmergencyContactParam;
|
||||||
|
import com.renkang.anyan.model.vo.EmergencyContactVO;
|
||||||
import com.renkang.emergency.api.service.EmergencyApiService;
|
import com.renkang.emergency.api.service.EmergencyApiService;
|
||||||
import com.renkang.emergency.bean.request.CallBack;
|
import com.renkang.emergency.bean.request.CallBack;
|
||||||
import com.renkang.emergency.bean.request.EmergencyCall;
|
import com.renkang.emergency.bean.request.EmergencyCall;
|
||||||
@@ -19,6 +23,7 @@ import com.renkang.emergency.entity.*;
|
|||||||
import com.renkang.emergency.entity.dto.AddOtherMemberDTO;
|
import com.renkang.emergency.entity.dto.AddOtherMemberDTO;
|
||||||
import com.renkang.emergency.entity.dto.RemoveGroupMemberDTO;
|
import com.renkang.emergency.entity.dto.RemoveGroupMemberDTO;
|
||||||
import com.renkang.emergency.entity.vo.CreateGroupMagVO;
|
import com.renkang.emergency.entity.vo.CreateGroupMagVO;
|
||||||
|
import com.renkang.emergency.largeScreen.mapper.LargeScreenDataMapper;
|
||||||
import com.renkang.emergency.manager.EmergencyCloudManager;
|
import com.renkang.emergency.manager.EmergencyCloudManager;
|
||||||
import com.renkang.emergency.mapper.*;
|
import com.renkang.emergency.mapper.*;
|
||||||
import com.renkang.emergency.service.IEmergencyCenterService;
|
import com.renkang.emergency.service.IEmergencyCenterService;
|
||||||
@@ -32,11 +37,13 @@ import com.renkang.im.dto.DeleteGroupMemberDTO;
|
|||||||
import com.renkang.im.entity.ConSessionRequestDO;
|
import com.renkang.im.entity.ConSessionRequestDO;
|
||||||
import com.renkang.im.entity.ImGroupMsgTextReqDO;
|
import com.renkang.im.entity.ImGroupMsgTextReqDO;
|
||||||
import com.renkang.im.vo.AddGroupMemberVO;
|
import com.renkang.im.vo.AddGroupMemberVO;
|
||||||
|
import com.renkang.im.vo.GetGroupMemberInfoVO;
|
||||||
import com.renkang.im.vo.ImBaseResult;
|
import com.renkang.im.vo.ImBaseResult;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.jeecg.bean.request.ListUser;
|
import org.jeecg.bean.request.ListUser;
|
||||||
|
import org.jeecg.bean.response.BaseEmployeeInfo;
|
||||||
import org.jeecg.common.api.vo.Result;
|
import org.jeecg.common.api.vo.Result;
|
||||||
import org.jeecg.common.constant.CommonConstant;
|
import org.jeecg.common.constant.CommonConstant;
|
||||||
import org.jeecg.common.exception.ExceptionAssertsUtil;
|
import org.jeecg.common.exception.ExceptionAssertsUtil;
|
||||||
@@ -45,6 +52,7 @@ import org.jeecg.common.system.vo.LoginUser;
|
|||||||
import org.jeecg.common.system.vo.LoginUserNew;
|
import org.jeecg.common.system.vo.LoginUserNew;
|
||||||
import org.jeecg.global.GlobalUtils;
|
import org.jeecg.global.GlobalUtils;
|
||||||
import org.jeecg.modules.manager.ISysCache;
|
import org.jeecg.modules.manager.ISysCache;
|
||||||
|
import org.jeecg.modules.system.entity.SysUser;
|
||||||
import org.parboiled.common.StringUtils;
|
import org.parboiled.common.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -117,6 +125,10 @@ public class EmergencyApiServiceImpl implements EmergencyApiService {
|
|||||||
private OrderOperatorMapper orderOperatorMapper;
|
private OrderOperatorMapper orderOperatorMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
private EmergencyProfessionUserMapper emergencyProfessionUserMapper;
|
private EmergencyProfessionUserMapper emergencyProfessionUserMapper;
|
||||||
|
@Autowired
|
||||||
|
private AnYanClient anYanClient;
|
||||||
|
@Autowired
|
||||||
|
private LargeScreenDataMapper largeScreenDataMapper;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -878,6 +890,8 @@ public class EmergencyApiServiceImpl implements EmergencyApiService {
|
|||||||
String orderId = this.call(emergencyCall);
|
String orderId = this.call(emergencyCall);
|
||||||
//保存参与应急的人员信息 PS: 不想大改之前的代码逻辑此处 没有将同一条记录的赋值逻辑合并
|
//保存参与应急的人员信息 PS: 不想大改之前的代码逻辑此处 没有将同一条记录的赋值逻辑合并
|
||||||
saveOderOperationInfo(orderId, sessionId, majorsId, operatorsId, majorsTwoId, rs.getCenterId(), conSessionRequestDO.getAccountList());
|
saveOderOperationInfo(orderId, sessionId, majorsId, operatorsId, majorsTwoId, rs.getCenterId(), conSessionRequestDO.getAccountList());
|
||||||
|
// 自动拉入关爱联络员+急救员1+急救员2(不阻断主流程)
|
||||||
|
addCareUsersToGroup(sysUser.getId(), sessionId, orderId);
|
||||||
imrs.getResult().put("member", userList);
|
imrs.getResult().put("member", userList);
|
||||||
imrs.getResult().put("tfNew", "1");
|
imrs.getResult().put("tfNew", "1");
|
||||||
imrs.getResult().put("id", orderId);
|
imrs.getResult().put("id", orderId);
|
||||||
@@ -887,6 +901,233 @@ public class EmergencyApiServiceImpl implements EmergencyApiService {
|
|||||||
return createGroupMagVO;
|
return createGroupMagVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
@Override
|
||||||
|
public CreateGroupMagVO createGroupMagFirstAider(String name, String longitude, String latitude) {
|
||||||
|
CreateGroupMagVO createGroupMagVO = new CreateGroupMagVO();
|
||||||
|
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||||
|
//查是否有已经存在的应急工单,有则直接返回相关信息
|
||||||
|
Order order = emergencyResourceApiServiceImpl.sessionNowSession(sysUser.getId());
|
||||||
|
List<String> userList = new ArrayList<>();
|
||||||
|
if (order != null) {
|
||||||
|
createGroupMagVO.setUserId(sysUser.getId());
|
||||||
|
createGroupMagVO.setGroupId(order.getSessionId());
|
||||||
|
createGroupMagVO.setTfNew("0");
|
||||||
|
userList.add(order.getOperationUserId());
|
||||||
|
userList.add(order.getMajorUserId());
|
||||||
|
if (null != order.getMajorUserTwoId()) {
|
||||||
|
userList.add(order.getMajorUserTwoId());
|
||||||
|
}
|
||||||
|
createGroupMagVO.setMember(userList);
|
||||||
|
createGroupMagVO.setId(order.getId());
|
||||||
|
return createGroupMagVO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询当前应急中心值班人员
|
||||||
|
Call rs = this.officerOnDuty();
|
||||||
|
if (rs == null || CollectionUtils.isEmpty(rs.getMajors()) || CollectionUtils.isEmpty(rs.getOperators())) {
|
||||||
|
ExceptionAssertsUtil.fail("没有接受方人员!");
|
||||||
|
}
|
||||||
|
String majorsId = rs.getMajors().get(0).getUserId();
|
||||||
|
String operatorsId = rs.getOperators().get(0).getUserId();
|
||||||
|
String majorsTwoId = null;
|
||||||
|
userList.add(operatorsId);
|
||||||
|
userList.add(majorsId);
|
||||||
|
List<String> yesIds = new ArrayList<>();
|
||||||
|
yesIds.add(sysUser.getId());
|
||||||
|
yesIds.add(majorsId);
|
||||||
|
yesIds.add(operatorsId);
|
||||||
|
//获取参与应急的人员信息
|
||||||
|
ConSessionRequestDO conSessionRequestDO = selectConSessionRequestDO(yesIds, "", name);
|
||||||
|
conSessionRequestDO.setUserId(sysUser.getId());
|
||||||
|
//调用IM创建群组
|
||||||
|
Result<Map<String, Object>> imrs = iMHelloApi.creatGroupMagNew(conSessionRequestDO);
|
||||||
|
if (!imrs.isSuccess()) {
|
||||||
|
ExceptionAssertsUtil.fail("应急单创建失败");
|
||||||
|
}
|
||||||
|
String sessionId = (String) imrs.getResult().get("groupId");
|
||||||
|
createGroupMagVO.setGroupId(sessionId);
|
||||||
|
//直接保存应急工单(不发起点对点音视频通话)
|
||||||
|
String orderId = insertOrderForFirstAider(sysUser, Double.valueOf(longitude), Double.valueOf(latitude), rs.getCenterId());
|
||||||
|
//拉入关爱联络员和急救人员
|
||||||
|
addCareUsersToGroup(sysUser.getId(), sessionId, orderId);
|
||||||
|
//保存参与应急的人员信息
|
||||||
|
saveOderOperationInfo(orderId, sessionId, majorsId, operatorsId, majorsTwoId, rs.getCenterId(), conSessionRequestDO.getAccountList());
|
||||||
|
imrs.getResult().put("member", userList);
|
||||||
|
imrs.getResult().put("tfNew", "1");
|
||||||
|
imrs.getResult().put("id", orderId);
|
||||||
|
createGroupMagVO.setMember(userList);
|
||||||
|
createGroupMagVO.setTfNew("1");
|
||||||
|
createGroupMagVO.setId(orderId);
|
||||||
|
return createGroupMagVO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 急救员场景插入工单(不触发大屏推送和短信)
|
||||||
|
*/
|
||||||
|
private String insertOrderForFirstAider(LoginUser loginUser, Double longitude, Double latitude, String centerId) {
|
||||||
|
Order order = new Order();
|
||||||
|
order.setInitiatorType("1");
|
||||||
|
order.setIsFill(EmergencyConstants.ORDER_IS_FILL_0);
|
||||||
|
// 发起人
|
||||||
|
order.setInitiatorUserId(loginUser.getId());
|
||||||
|
order.setInitiatorUserSex(String.valueOf(loginUser.getSex()));
|
||||||
|
order.setInitiatorUserName(loginUser.getRealname());
|
||||||
|
order.setInitiatorUserMobile(loginUser.getPhone());
|
||||||
|
order.setInitiatorUserIdCard(loginUser.getIdCard());
|
||||||
|
order.setInitiatorLongitude(BigDecimal.valueOf(longitude));
|
||||||
|
order.setInitiatorLatitude(BigDecimal.valueOf(latitude));
|
||||||
|
order.setInitiatorUserDepart(loginUser.getOrgCode());
|
||||||
|
order.setInitiatorUserAvatar(loginUser.getAvatar());
|
||||||
|
// 救助人
|
||||||
|
order.setSalvageUserId(loginUser.getId());
|
||||||
|
order.setSalvageUserSex(String.valueOf(loginUser.getSex()));
|
||||||
|
order.setSalvageUserName(loginUser.getRealname());
|
||||||
|
order.setSalvageUserMobile(loginUser.getPhone());
|
||||||
|
order.setSalvageUserIdCard(loginUser.getIdCard());
|
||||||
|
order.setSalvageUserDepart(loginUser.getOrgCode());
|
||||||
|
order.setSalvageUserAvatar(loginUser.getAvatar());
|
||||||
|
order.setCenterId(centerId);
|
||||||
|
orderMapper.insert(order);
|
||||||
|
return order.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拉入关爱联络员和急救人员到群聊
|
||||||
|
* <p>通过安眼返回的手机号 → EMP_BASIC_INFO查询员工编号 → 本系统用户ID</p>
|
||||||
|
*
|
||||||
|
* @param userId 发起人ID
|
||||||
|
* @param groupId IM群组ID
|
||||||
|
* @param orderId 应急工单ID
|
||||||
|
*/
|
||||||
|
public void addCareUsersToGroup(String userId, String groupId, String orderId) {
|
||||||
|
try {
|
||||||
|
// 1. 获取发起人工号
|
||||||
|
List<BaseEmployeeInfo> employeeInfos = sysBaseAPI.queryBaseEmployeeInfo(Collections.singleton(userId));
|
||||||
|
if (CollUtil.isEmpty(employeeInfos)) {
|
||||||
|
log.warn("未找到发起人的员工信息,跳过拉入关爱/急救人员, userId={}", userId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String workNo = employeeInfos.get(0).getWorkNo();
|
||||||
|
if (StrUtil.isBlank(workNo)) {
|
||||||
|
log.warn("发起人工号为空,跳过拉入关爱/急救人员, userId={}", userId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 查安眼系统获取关爱联络员和急救人员信息
|
||||||
|
EmergencyContactParam param = new EmergencyContactParam();
|
||||||
|
param.setEmployeeNum(workNo);
|
||||||
|
IPage<EmergencyContactVO> page = anYanClient.queryEmergencyContact(param);
|
||||||
|
if (page == null || CollUtil.isEmpty(page.getRecords())) {
|
||||||
|
log.warn("安眼系统未查到关爱/急救人员信息, workNo={}", workNo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EmergencyContactVO contact = page.getRecords().get(0);
|
||||||
|
|
||||||
|
// 3. 收集3个人的手机号 → 角色映射
|
||||||
|
Map<String, Integer> phoneRoleMap = new LinkedHashMap<>();
|
||||||
|
if (StrUtil.isNotBlank(contact.getRelationEmpPhone())) {
|
||||||
|
phoneRoleMap.put(contact.getRelationEmpPhone(), 5); // 关爱联络员
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(contact.getFirstAiderPhone())) {
|
||||||
|
phoneRoleMap.put(contact.getFirstAiderPhone(), 3); // 急救人员1
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(contact.getFirstAiderPhone2())) {
|
||||||
|
phoneRoleMap.put(contact.getFirstAiderPhone2(), 4); // 急救人员2
|
||||||
|
}
|
||||||
|
if (phoneRoleMap.isEmpty()) {
|
||||||
|
log.warn("关爱/急救人员手机号均为空, workNo={}", workNo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 手机号 → EMP_BASIC_INFO 反查员工编号
|
||||||
|
List<String> phones = new ArrayList<>(phoneRoleMap.keySet());
|
||||||
|
List<Map<String, String>> empBasicList = largeScreenDataMapper.selectEmployeeNumsByPhones(phones);
|
||||||
|
if (CollUtil.isEmpty(empBasicList)) {
|
||||||
|
log.warn("关爱/急救人员手机号均未匹配到EMP_BASIC_INFO, phones={}", phones);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 构建 phone → employeeNum 映射(拆分多手机号字段,\D+匹配任意非数字分隔符)
|
||||||
|
Map<String, String> phoneWorkNoMap = new LinkedHashMap<>();
|
||||||
|
for (Map<String, String> row : empBasicList) {
|
||||||
|
String phoneField = row.get("phone");
|
||||||
|
String employeeNum = row.get("employeeNum");
|
||||||
|
if (StrUtil.isNotBlank(phoneField) && StrUtil.isNotBlank(employeeNum)) {
|
||||||
|
for (String singlePhone : phoneField.split("\\D+")) {
|
||||||
|
if (StrUtil.isNotBlank(singlePhone)) {
|
||||||
|
phoneWorkNoMap.put(singlePhone, employeeNum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info("手机号匹配到{}个EMP_BASIC_INFO员工编号, phones={}", phoneWorkNoMap.size(), phones);
|
||||||
|
|
||||||
|
// 5. 员工编号 → 本系统用户ID
|
||||||
|
List<String> workNoList = new ArrayList<>(phoneWorkNoMap.values());
|
||||||
|
List<SysUser> sysUsers = sysBaseAPI.getUserListByWorkNoList(workNoList);
|
||||||
|
if (CollUtil.isEmpty(sysUsers)) {
|
||||||
|
log.warn("关爱/急救人员员工编号均未匹配到本系统用户, workNos={}", workNoList);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log.info("关爱/急救人员员工编号匹配到{}个系统用户, workNos={}", sysUsers.size(), workNoList);
|
||||||
|
|
||||||
|
// 6. 拉入IM群聊
|
||||||
|
Map<String, SysUser> sysUserMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getId, u -> u, (a, b) -> a));
|
||||||
|
List<String> memberAccounts = new ArrayList<>(sysUserMap.keySet());
|
||||||
|
AddGroupMemberDTO addDto = new AddGroupMemberDTO();
|
||||||
|
addDto.setGroupId(groupId);
|
||||||
|
addDto.setSilence(1);
|
||||||
|
addDto.setMemberList(memberAccounts.stream().map(account -> {
|
||||||
|
AddGroupMemberDTO.MemberListDTO m = new AddGroupMemberDTO.MemberListDTO();
|
||||||
|
m.setMemberAccount(account);
|
||||||
|
SysUser u = sysUserMap.get(account);
|
||||||
|
if (u != null && StrUtil.isNotBlank(u.getRealname())) {
|
||||||
|
m.setMemberName(u.getRealname());
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
try {
|
||||||
|
iMHelloApi.addGroupMember(addDto);
|
||||||
|
log.info("关爱/急救人员拉入群聊成功, groupId={}, userIds={}", groupId, memberAccounts);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("关爱/急救人员拉入群聊失败, groupId={}, userIds={}", groupId, memberAccounts, e);
|
||||||
|
// IM拉人失败不影响建群流程,继续写入 order_operator
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. 写入 order_operator 表
|
||||||
|
Date now = new Date();
|
||||||
|
Map<String, Integer> userIdRoleMap = new HashMap<>();
|
||||||
|
for (SysUser sysUser : sysUsers) {
|
||||||
|
String sysUserWorkNo = sysUser.getWorkNo();
|
||||||
|
if (StrUtil.isBlank(sysUserWorkNo)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 遍历 phoneRoleMap 反查:phone → phoneWorkNoMap.get(phone) → 匹配 workNo
|
||||||
|
for (Map.Entry<String, Integer> roleEntry : phoneRoleMap.entrySet()) {
|
||||||
|
String mappedWorkNo = phoneWorkNoMap.get(roleEntry.getKey());
|
||||||
|
if (sysUserWorkNo.equals(mappedWorkNo)) {
|
||||||
|
userIdRoleMap.put(sysUser.getId(), roleEntry.getValue());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, Integer> entry : userIdRoleMap.entrySet()) {
|
||||||
|
OrderOperator orderOperator = new OrderOperator();
|
||||||
|
orderOperator.setOrderId(orderId);
|
||||||
|
orderOperator.setOperatorType(entry.getValue());
|
||||||
|
orderOperator.setUserId(entry.getKey());
|
||||||
|
orderOperator.setJoinType(1);
|
||||||
|
orderOperator.setJoinDate(now);
|
||||||
|
orderOperatorMapper.insert(orderOperator);
|
||||||
|
log.info("写入order_operator, orderId={}, userId={}, operatorType={}", orderId, entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("拉入关爱/急救人员异常,不影响建群主流程, userId={}, groupId={}, orderId={}", userId, groupId, orderId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void saveOderOperationInfo(String orderId, String sessionId, String majorsId, String operatorsId, String majorsTwoId,
|
public void saveOderOperationInfo(String orderId, String sessionId, String majorsId, String operatorsId, String majorsTwoId,
|
||||||
String centerId, List<LoginUserNew> accountList) {
|
String centerId, List<LoginUserNew> accountList) {
|
||||||
Map<String, LoginUserNew> userMap = accountList.stream().collect(Collectors.toMap(LoginUserNew::getId, user -> user));
|
Map<String, LoginUserNew> userMap = accountList.stream().collect(Collectors.toMap(LoginUserNew::getId, user -> user));
|
||||||
@@ -1082,17 +1323,53 @@ public class EmergencyApiServiceImpl implements EmergencyApiService {
|
|||||||
ExceptionAssertsUtil.fail("应急单不存在");
|
ExceptionAssertsUtil.fail("应急单不存在");
|
||||||
}
|
}
|
||||||
String orderId = order.getId();
|
String orderId = order.getId();
|
||||||
|
|
||||||
|
// 0. 获取当前登录用户,过滤掉本人
|
||||||
|
LoginUser loginUser = GlobalUtils.getLoginUser();
|
||||||
|
String currentUserId = loginUser.getId();
|
||||||
|
List<String> candidateList = dto.getMemberList().stream()
|
||||||
|
.filter(userId -> !userId.equals(currentUserId))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (candidateList.isEmpty()) {
|
||||||
|
ExceptionAssertsUtil.fail("不能邀请自己入群");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 查询本地 order_operator 和腾讯IM实际群成员,取并集作为已在群中的用户
|
||||||
|
Set<String> alreadyInGroup = new HashSet<>();
|
||||||
|
// 1a. 本地已有记录
|
||||||
|
List<OrderOperator> existingOps = orderOperatorMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<OrderOperator>()
|
||||||
|
.eq(OrderOperator::getOrderId, orderId));
|
||||||
|
existingOps.forEach(op -> alreadyInGroup.add(op.getUserId()));
|
||||||
|
alreadyInGroup.add(order.getInitiatorUserId());
|
||||||
|
// 1b. 腾讯IM实际群成员
|
||||||
|
try {
|
||||||
|
Result<GetGroupMemberInfoVO> imResult = iMHelloApi.getGroupMemberInfo(groupId);
|
||||||
|
if (imResult != null && imResult.isSuccess() && imResult.getResult() != null) {
|
||||||
|
GetGroupMemberInfoVO vo = imResult.getResult();
|
||||||
|
if ("OK".equals(vo.getActionStatus()) && vo.getMemberList() != null) {
|
||||||
|
vo.getMemberList().forEach(m -> alreadyInGroup.add(m.getMemberAccount()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("获取腾讯IM群成员失败,仅使用本地数据进行去重, groupId: {}", groupId, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 群成员上限校验:最多9人
|
||||||
|
int currentGroupSize = alreadyInGroup.size();
|
||||||
|
int newMemberCount = (int) candidateList.stream()
|
||||||
|
.filter(userId -> !alreadyInGroup.contains(userId)).count();
|
||||||
|
if (currentGroupSize + newMemberCount > 9) {
|
||||||
|
ExceptionAssertsUtil.fail("群成员已达上限");
|
||||||
|
}
|
||||||
|
|
||||||
// memberType: 0=专家/专业人员(默认), 1=员工
|
// memberType: 0=专家/专业人员(默认), 1=员工
|
||||||
Integer memberType = dto.getMemberType();
|
Integer memberType = dto.getMemberType();
|
||||||
Integer operatorType = (memberType != null && memberType == 1) ? 2 : 1;
|
Integer operatorType = (memberType != null && memberType == 1) ? 2 : 1;
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
List<String> newMemberList = new ArrayList<>();
|
List<String> newMemberList = new ArrayList<>();
|
||||||
dto.getMemberList().forEach(userId -> {
|
candidateList.forEach(userId -> {
|
||||||
OrderOperator existing = orderOperatorMapper.selectOne(new LambdaQueryWrapper<OrderOperator>()
|
if (alreadyInGroup.contains(userId)) {
|
||||||
.eq(OrderOperator::getOrderId, orderId)
|
|
||||||
.eq(OrderOperator::getUserId, userId)
|
|
||||||
);
|
|
||||||
if (existing != null) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
OrderOperator orderOperator = new OrderOperator();
|
OrderOperator orderOperator = new OrderOperator();
|
||||||
@@ -1105,20 +1382,46 @@ public class EmergencyApiServiceImpl implements EmergencyApiService {
|
|||||||
newMemberList.add(userId);
|
newMemberList.add(userId);
|
||||||
});
|
});
|
||||||
if (newMemberList.isEmpty()) {
|
if (newMemberList.isEmpty()) {
|
||||||
ExceptionAssertsUtil.fail("所有成员已在群组中");
|
ExceptionAssertsUtil.fail("所选成员已在群聊中");
|
||||||
|
}
|
||||||
|
// 查询成员名称和头像用于IM账号导入
|
||||||
|
Map<String, String> memberNameMap = new HashMap<>();
|
||||||
|
Map<String, String> memberAvatarMap = new HashMap<>();
|
||||||
|
List<EmergencyProfessionUser> profUsers = emergencyProfessionUserMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<EmergencyProfessionUser>().in(EmergencyProfessionUser::getUserId, newMemberList));
|
||||||
|
profUsers.forEach(u -> {
|
||||||
|
memberNameMap.put(u.getUserId(), u.getRealname());
|
||||||
|
if (StrUtil.isNotBlank(u.getAvatar())) {
|
||||||
|
memberAvatarMap.put(u.getUserId(), u.getAvatar());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
List<String> remainingIds = newMemberList.stream()
|
||||||
|
.filter(id -> !memberNameMap.containsKey(id)).collect(Collectors.toList());
|
||||||
|
if (!remainingIds.isEmpty()) {
|
||||||
|
emergencyCloudManager.listUser(remainingIds).forEach((id, u) -> {
|
||||||
|
if (StrUtil.isNotBlank(u.getRealname())) {
|
||||||
|
memberNameMap.put(id, u.getRealname());
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(u.getAvatar())) {
|
||||||
|
memberAvatarMap.put(id, u.getAvatar());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
AddGroupMemberDTO addGroupMemberDTO = new AddGroupMemberDTO();
|
AddGroupMemberDTO addGroupMemberDTO = new AddGroupMemberDTO();
|
||||||
addGroupMemberDTO.setGroupId(dto.getGroupId());
|
addGroupMemberDTO.setGroupId(dto.getGroupId());
|
||||||
addGroupMemberDTO.setMemberList(newMemberList.stream().map(userId -> {
|
addGroupMemberDTO.setMemberList(newMemberList.stream().map(userId -> {
|
||||||
AddGroupMemberDTO.MemberListDTO memberListDTO = new AddGroupMemberDTO.MemberListDTO();
|
AddGroupMemberDTO.MemberListDTO memberListDTO = new AddGroupMemberDTO.MemberListDTO();
|
||||||
memberListDTO.setMemberAccount(userId);
|
memberListDTO.setMemberAccount(userId);
|
||||||
|
memberListDTO.setMemberName(memberNameMap.get(userId));
|
||||||
|
memberListDTO.setMemberAvatar(memberAvatarMap.get(userId));
|
||||||
return memberListDTO;
|
return memberListDTO;
|
||||||
}).collect(Collectors.toList()));
|
}).collect(Collectors.toList()));
|
||||||
//添加群成员
|
//添加群成员
|
||||||
Result<AddGroupMemberVO> addGroupMemberVoResult = iMHelloApi.addGroupMember(addGroupMemberDTO);
|
Result<AddGroupMemberVO> addGroupMemberVoResult = iMHelloApi.addGroupMember(addGroupMemberDTO);
|
||||||
String actionStatus = addGroupMemberVoResult.getResult().getActionStatus();
|
String actionStatus = addGroupMemberVoResult.getResult().getActionStatus();
|
||||||
if (!"OK".equals(actionStatus)) {
|
if (!"OK".equals(actionStatus)) {
|
||||||
ExceptionAssertsUtil.fail(addGroupMemberVoResult.getResult().getErrorInfo());
|
log.error("添加群成员失败, actionStatus: {}, errorInfo: {}", actionStatus, addGroupMemberVoResult.getResult().getErrorInfo());
|
||||||
|
ExceptionAssertsUtil.fail("添加群成员失败");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
+397
-28
@@ -21,13 +21,17 @@ import com.renkang.emergency.constant.EmergencyConstants;
|
|||||||
import com.renkang.emergency.entity.*;
|
import com.renkang.emergency.entity.*;
|
||||||
import com.renkang.emergency.entity.vo.EmployeeVO;
|
import com.renkang.emergency.entity.vo.EmployeeVO;
|
||||||
import com.renkang.emergency.entity.vo.GroupMemberVO;
|
import com.renkang.emergency.entity.vo.GroupMemberVO;
|
||||||
|
import com.renkang.emergency.entity.vo.MyParticipatedOrderVO;
|
||||||
import com.renkang.emergency.manager.EmergencyCacheManager;
|
import com.renkang.emergency.manager.EmergencyCacheManager;
|
||||||
import com.renkang.emergency.manager.EmergencyCloudManager;
|
import com.renkang.emergency.manager.EmergencyCloudManager;
|
||||||
import com.renkang.emergency.mapper.*;
|
import com.renkang.emergency.mapper.*;
|
||||||
import com.renkang.emergency.service.IOrderDetailService;
|
import com.renkang.emergency.service.IOrderDetailService;
|
||||||
import com.renkang.emergency.service.IOrderService;
|
import com.renkang.emergency.service.IOrderService;
|
||||||
import com.renkang.im.api.IMHelloApi;
|
import com.renkang.im.api.IMHelloApi;
|
||||||
|
import com.renkang.im.dto.AddGroupMemberDTO;
|
||||||
import com.renkang.im.entity.ImGroupMsgTextReqDO;
|
import com.renkang.im.entity.ImGroupMsgTextReqDO;
|
||||||
|
import com.renkang.im.vo.AddGroupMemberVO;
|
||||||
|
import com.renkang.im.vo.GetGroupMemberInfoVO;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
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;
|
||||||
@@ -76,9 +80,13 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private EmergencyProfessionUserMapper emergencyProfessionUserMapper;
|
private EmergencyProfessionUserMapper emergencyProfessionUserMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
private ConDoctorMapper conDoctorMapper;
|
||||||
|
@Autowired
|
||||||
private ISysBaseAPI sysBaseAPI;
|
private ISysBaseAPI sysBaseAPI;
|
||||||
@Autowired
|
@Autowired
|
||||||
private EmergencyCloudManager emergencyCloudManager;
|
private EmergencyCloudManager emergencyCloudManager;
|
||||||
|
@Autowired
|
||||||
|
private com.renkang.emergency.api.service.EmergencyApiService emergencyApiService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IPage<InitUserOrder> initUserOrderPage(Page<Order> page) {
|
public IPage<InitUserOrder> initUserOrderPage(Page<Order> page) {
|
||||||
@@ -623,6 +631,7 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService {
|
|||||||
order.getInitiatorUserId(),
|
order.getInitiatorUserId(),
|
||||||
order.getInitiatorUserName(),
|
order.getInitiatorUserName(),
|
||||||
order.getInitiatorUserAvatar(),
|
order.getInitiatorUserAvatar(),
|
||||||
|
order.getInitiatorUserMobile(),
|
||||||
1, -1);
|
1, -1);
|
||||||
|
|
||||||
// 已加入应急单人员
|
// 已加入应急单人员
|
||||||
@@ -662,19 +671,22 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService {
|
|||||||
for (OrderOperator op : orderOperators) {
|
for (OrderOperator op : orderOperators) {
|
||||||
String userName = "";
|
String userName = "";
|
||||||
String avatar = "";
|
String avatar = "";
|
||||||
|
String phone = "";
|
||||||
EmergencyProfessionUser profUser = profUserMap.get(op.getUserId());
|
EmergencyProfessionUser profUser = profUserMap.get(op.getUserId());
|
||||||
if (profUser != null) {
|
if (profUser != null) {
|
||||||
userName = profUser.getRealname();
|
userName = profUser.getRealname();
|
||||||
avatar = profUser.getAvatar();
|
avatar = profUser.getAvatar();
|
||||||
|
phone = profUser.getPhone();
|
||||||
} else {
|
} else {
|
||||||
LoginUserNew sysUser = sysUserMap.get(op.getUserId());
|
LoginUserNew sysUser = sysUserMap.get(op.getUserId());
|
||||||
if (sysUser != null) {
|
if (sysUser != null) {
|
||||||
userName = sysUser.getRealname();
|
userName = sysUser.getRealname();
|
||||||
avatar = sysUser.getAvatar();
|
avatar = sysUser.getAvatar();
|
||||||
|
phone = sysUser.getPhone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handleGroupMember(groupMemberVos, orderId,
|
handleGroupMember(groupMemberVos, orderId,
|
||||||
op.getUserId(), userName, avatar, 1, op.getOperatorType());
|
op.getUserId(), userName, avatar, phone, 1, op.getOperatorType());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 其他专业人员(排除已在应急单中的用户),memberType=1
|
// 其他专业人员(排除已在应急单中的用户),memberType=1
|
||||||
@@ -685,38 +697,234 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<EmergencyProfessionUser> otherMajorMemberList = emergencyProfessionUserMapper.selectList(otherMajorQuery);
|
List<EmergencyProfessionUser> otherMajorMemberList = emergencyProfessionUserMapper.selectList(otherMajorQuery);
|
||||||
|
// 批量查手机号
|
||||||
|
Map<String, String> otherMajorPhoneMap = new HashMap<>();
|
||||||
|
if (!otherMajorMemberList.isEmpty()) {
|
||||||
|
List<String> otherMajorUserIds = otherMajorMemberList.stream()
|
||||||
|
.map(EmergencyProfessionUser::getUserId).collect(Collectors.toList());
|
||||||
|
Map<String, LoginUserNew> otherUserMap = emergencyCloudManager.listUser(otherMajorUserIds);
|
||||||
|
for (EmergencyProfessionUser m : otherMajorMemberList) {
|
||||||
|
LoginUserNew u = otherUserMap.get(m.getUserId());
|
||||||
|
if (u != null) {
|
||||||
|
otherMajorPhoneMap.put(m.getUserId(), u.getPhone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
otherMajorMemberList.forEach(otherMajorMember ->
|
otherMajorMemberList.forEach(otherMajorMember ->
|
||||||
handleGroupMember(groupMemberVos, orderId,
|
handleGroupMember(groupMemberVos, orderId,
|
||||||
otherMajorMember.getUserId(),
|
otherMajorMember.getUserId(),
|
||||||
otherMajorMember.getRealname(),
|
otherMajorMember.getRealname(),
|
||||||
otherMajorMember.getAvatar(),
|
otherMajorMember.getAvatar(),
|
||||||
|
otherMajorPhoneMap.get(otherMajorMember.getUserId()),
|
||||||
0, 1)
|
0, 1)
|
||||||
);
|
);
|
||||||
return groupMemberVos.stream().filter(groupMemberVO -> !groupMemberVO.getUserId().equals(loginUser.getId())).collect(Collectors.toList());
|
return groupMemberVos.stream().filter(groupMemberVO -> !groupMemberVO.getUserId().equals(loginUser.getId())).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleGroupMember(List<GroupMemberVO> groupMemberVos, String orderId, String userId, String userName, String avatar, Integer isGroupMember, Integer memberType) {
|
/**
|
||||||
|
* @description: 获取实际群成员列表(先查本地参与人员,再匹配腾讯IM实际群成员)
|
||||||
|
* @author PengJ
|
||||||
|
* @date 2026/7/7
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<GroupMemberVO> getActualGroupMemberList(String sessionId) {
|
||||||
|
List<GroupMemberVO> groupMemberVos = new ArrayList<>();
|
||||||
|
LoginUser loginUser = GlobalUtils.getLoginUser();
|
||||||
|
|
||||||
|
// 1. 校验订单是否存在
|
||||||
|
Order order = orderMapper.selectOne(new LambdaQueryWrapper<Order>()
|
||||||
|
.eq(Order::getSessionId, sessionId));
|
||||||
|
if (order == null) {
|
||||||
|
ExceptionAssertsUtil.fail("应急单不存在");
|
||||||
|
}
|
||||||
|
String orderId = order.getId();
|
||||||
|
|
||||||
|
// 2. 兜底补拉关爱联络员+急救人员1+急救人员2(重新查询安眼系统)
|
||||||
|
// 发起应急时这些人员可能还未注册,此处兜底
|
||||||
|
try {
|
||||||
|
emergencyApiService.addCareUsersToGroup(order.getInitiatorUserId(), sessionId, orderId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("兜底补拉关爱/急救人员异常, sessionId={}", sessionId, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 查order_operator表获取本地参与人员
|
||||||
|
List<OrderOperator> orderOperators = orderOperatorMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<OrderOperator>()
|
||||||
|
.eq(OrderOperator::getOrderId, orderId));
|
||||||
|
List<String> localUserIds = new ArrayList<>();
|
||||||
|
if (CollectionUtils.isNotEmpty(orderOperators)) {
|
||||||
|
localUserIds = orderOperators.stream()
|
||||||
|
.map(OrderOperator::getUserId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 调腾讯IM获取实际群成员
|
||||||
|
Set<String> imMemberAccounts = new HashSet<>();
|
||||||
|
boolean imSuccess = false;
|
||||||
|
try {
|
||||||
|
Result<GetGroupMemberInfoVO> imResult = imHelloApi.getGroupMemberInfo(sessionId);
|
||||||
|
if (imResult != null && imResult.isSuccess() && imResult.getResult() != null) {
|
||||||
|
GetGroupMemberInfoVO vo = imResult.getResult();
|
||||||
|
if ("OK".equals(vo.getActionStatus()) && vo.getMemberList() != null) {
|
||||||
|
vo.getMemberList().forEach(m -> imMemberAccounts.add(m.getMemberAccount()));
|
||||||
|
imSuccess = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取腾讯IM群成员失败,sessionId: {},降级使用本地参与人员", sessionId, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 自动补拉其他遗漏的预设成员(仅IM可用时)
|
||||||
|
if (imSuccess) {
|
||||||
|
autoInvitePresetMembers(sessionId, order, imMemberAccounts, localUserIds, loginUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 如果IM调用失败,降级使用本地成员全集
|
||||||
|
final Set<String> validAccounts = imSuccess ? imMemberAccounts : new HashSet<>(localUserIds);
|
||||||
|
if (!imSuccess) {
|
||||||
|
log.warn("腾讯IM调用失败,降级返回本地参与人员 {} 人, sessionId: {}", localUserIds.size(), sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. 发起人:匹配验证集
|
||||||
|
if (validAccounts.contains(order.getInitiatorUserId())) {
|
||||||
|
handleGroupMember(groupMemberVos, orderId,
|
||||||
|
order.getInitiatorUserId(),
|
||||||
|
order.getInitiatorUserName(),
|
||||||
|
order.getInitiatorUserAvatar(),
|
||||||
|
order.getInitiatorUserMobile(),
|
||||||
|
1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8. 查order_operator表,匹配验证集
|
||||||
|
if (CollectionUtils.isNotEmpty(orderOperators)) {
|
||||||
|
// 查询专业用户信息
|
||||||
|
Map<String, EmergencyProfessionUser> profUserMap = new HashMap<>();
|
||||||
|
if (!localUserIds.isEmpty()) {
|
||||||
|
List<EmergencyProfessionUser> profUsers = emergencyProfessionUserMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<EmergencyProfessionUser>()
|
||||||
|
.in(EmergencyProfessionUser::getUserId, localUserIds));
|
||||||
|
profUsers.forEach(u -> profUserMap.put(u.getUserId(), u));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询员工成员的系统用户信息(所有profUserMap未命中的userId都走SysUser兜底)
|
||||||
|
List<String> employeeUserIds = orderOperators.stream()
|
||||||
|
.map(OrderOperator::getUserId)
|
||||||
|
.filter(uid -> !profUserMap.containsKey(uid))
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
Map<String, LoginUserNew> sysUserMap = new HashMap<>();
|
||||||
|
if (!employeeUserIds.isEmpty()) {
|
||||||
|
sysUserMap = emergencyCloudManager.listUser(employeeUserIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 遍历order_operator,只保留验证集中的成员
|
||||||
|
for (OrderOperator op : orderOperators) {
|
||||||
|
if (!validAccounts.contains(op.getUserId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String userName = "";
|
||||||
|
String avatar = "";
|
||||||
|
String phone = "";
|
||||||
|
EmergencyProfessionUser profUser = profUserMap.get(op.getUserId());
|
||||||
|
if (profUser != null) {
|
||||||
|
userName = profUser.getRealname();
|
||||||
|
avatar = profUser.getAvatar();
|
||||||
|
phone = profUser.getPhone();
|
||||||
|
} else {
|
||||||
|
LoginUserNew sysUser = sysUserMap.get(op.getUserId());
|
||||||
|
if (sysUser != null) {
|
||||||
|
userName = sysUser.getRealname();
|
||||||
|
avatar = sysUser.getAvatar();
|
||||||
|
phone = sysUser.getPhone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handleGroupMember(groupMemberVos, orderId,
|
||||||
|
op.getUserId(), userName, avatar, phone, 1, op.getOperatorType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 9. 标记本人
|
||||||
|
String currentUserId = loginUser.getId();
|
||||||
|
groupMemberVos.forEach(vo -> vo.setIsSelf(currentUserId.equals(vo.getUserId()) ? 1 : 0));
|
||||||
|
return groupMemberVos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleGroupMember(List<GroupMemberVO> groupMemberVos, String orderId, String userId, String userName, String avatar, String phone, Integer isGroupMember, Integer memberType) {
|
||||||
GroupMemberVO groupMemberVO = new GroupMemberVO();
|
GroupMemberVO groupMemberVO = new GroupMemberVO();
|
||||||
groupMemberVO.setOrderId(orderId);
|
groupMemberVO.setOrderId(orderId);
|
||||||
groupMemberVO.setUserId(userId);
|
groupMemberVO.setUserId(userId);
|
||||||
groupMemberVO.setUserName(userName);
|
groupMemberVO.setUserName(userName);
|
||||||
groupMemberVO.setAvatar(avatar);
|
groupMemberVO.setAvatar(avatar);
|
||||||
|
groupMemberVO.setPhone(phone);
|
||||||
groupMemberVO.setIsGroupMember(isGroupMember);
|
groupMemberVO.setIsGroupMember(isGroupMember);
|
||||||
groupMemberVO.setMemberType(memberType);
|
groupMemberVO.setMemberType(memberType);
|
||||||
|
groupMemberVO.setIsSelf(0);
|
||||||
groupMemberVos.add(groupMemberVO);
|
groupMemberVos.add(groupMemberVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动补拉预设成员入群
|
||||||
|
* 预设成员:被救助人 + order_operator 所有参与人员
|
||||||
|
* 群成员总数不超过9人
|
||||||
|
*/
|
||||||
|
private void autoInvitePresetMembers(String sessionId, Order order, Set<String> imMemberAccounts,
|
||||||
|
List<String> localUserIds, LoginUser loginUser) {
|
||||||
|
Set<String> presetMemberIds = new LinkedHashSet<>();
|
||||||
|
// 被救助人
|
||||||
|
if (StrUtil.isNotBlank(order.getSalvageUserId())) {
|
||||||
|
presetMemberIds.add(order.getSalvageUserId());
|
||||||
|
}
|
||||||
|
// order_operator 中所有参与人员(操作人员、专业人员、紧急联系人、健康联络员)
|
||||||
|
if (CollectionUtils.isNotEmpty(localUserIds)) {
|
||||||
|
presetMemberIds.addAll(localUserIds);
|
||||||
|
}
|
||||||
|
// 排除当前登录用户(不能邀请自己)
|
||||||
|
presetMemberIds.remove(loginUser.getId());
|
||||||
|
|
||||||
|
// 找出不在群中的预设成员
|
||||||
|
List<String> missingPresetMembers = presetMemberIds.stream()
|
||||||
|
.filter(id -> !imMemberAccounts.contains(id))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (missingPresetMembers.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 控制群成员不超过9人
|
||||||
|
int currentCount = imMemberAccounts.size();
|
||||||
|
int maxInvite = Math.max(0, 9 - currentCount);
|
||||||
|
if (maxInvite <= 0) {
|
||||||
|
log.warn("群成员已达上限9人,无法自动补拉预设成员, sessionId={}, current={}", sessionId, currentCount);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<String> toInvite = missingPresetMembers.subList(0, Math.min(missingPresetMembers.size(), maxInvite));
|
||||||
|
|
||||||
|
try {
|
||||||
|
AddGroupMemberDTO addDto = new AddGroupMemberDTO();
|
||||||
|
addDto.setGroupId(sessionId);
|
||||||
|
addDto.setSilence(1);
|
||||||
|
addDto.setMemberList(toInvite.stream().map(userId -> {
|
||||||
|
AddGroupMemberDTO.MemberListDTO m = new AddGroupMemberDTO.MemberListDTO();
|
||||||
|
m.setMemberAccount(userId);
|
||||||
|
return m;
|
||||||
|
}).collect(Collectors.toList()));
|
||||||
|
Result<AddGroupMemberVO> result = imHelloApi.addGroupMember(addDto);
|
||||||
|
if (result != null && result.isSuccess() && result.getResult() != null
|
||||||
|
&& "OK".equals(result.getResult().getActionStatus())) {
|
||||||
|
imMemberAccounts.addAll(toInvite);
|
||||||
|
log.info("自动补拉预设成员入群成功, sessionId={}, userIds={}, currentCount={}",
|
||||||
|
sessionId, toInvite, currentCount + toInvite.size());
|
||||||
|
} else {
|
||||||
|
log.warn("自动补拉预设成员入群失败, sessionId={}, userIds={}", sessionId, toInvite);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("自动补拉预设成员入群异常, sessionId={}", sessionId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IPage<EmergencyProfessionUser> searchExpert(String realname, String centerId, String excludeSessionId, Integer pageNo, Integer pageSize) {
|
public IPage<EmergencyProfessionUser> searchExpert(String realname, String centerId, String excludeSessionId, Integer pageNo, Integer pageSize) {
|
||||||
LambdaQueryWrapper<EmergencyProfessionUser> query = new LambdaQueryWrapper<>();
|
// ---- 1. 收集需要排除的userId(已在群中的人) ----
|
||||||
query.eq(EmergencyProfessionUser::getType, "6");
|
Set<String> excludeUserIds = new HashSet<>();
|
||||||
if (StrUtil.isNotBlank(realname)) {
|
|
||||||
query.like(EmergencyProfessionUser::getRealname, realname);
|
|
||||||
}
|
|
||||||
if (StrUtil.isNotBlank(centerId)) {
|
|
||||||
query.eq(EmergencyProfessionUser::getCenterId, centerId);
|
|
||||||
}
|
|
||||||
// 排除已在群中的人员
|
|
||||||
if (StrUtil.isNotBlank(excludeSessionId)) {
|
if (StrUtil.isNotBlank(excludeSessionId)) {
|
||||||
Order order = orderMapper.selectOne(new LambdaQueryWrapper<Order>()
|
Order order = orderMapper.selectOne(new LambdaQueryWrapper<Order>()
|
||||||
.eq(Order::getSessionId, excludeSessionId));
|
.eq(Order::getSessionId, excludeSessionId));
|
||||||
@@ -724,29 +932,117 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService {
|
|||||||
List<OrderOperator> ops = orderOperatorMapper.selectList(
|
List<OrderOperator> ops = orderOperatorMapper.selectList(
|
||||||
new LambdaQueryWrapper<OrderOperator>()
|
new LambdaQueryWrapper<OrderOperator>()
|
||||||
.eq(OrderOperator::getOrderId, order.getId()));
|
.eq(OrderOperator::getOrderId, order.getId()));
|
||||||
List<String> existUserIds = ops.stream().map(OrderOperator::getUserId).collect(Collectors.toList());
|
excludeUserIds.addAll(ops.stream().map(OrderOperator::getUserId).collect(Collectors.toList()));
|
||||||
if (!existUserIds.isEmpty()) {
|
|
||||||
query.notIn(EmergencyProfessionUser::getUserId, existUserIds);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Page<EmergencyProfessionUser> page = new Page<>(pageNo != null ? pageNo : 1, pageSize != null ? pageSize : 10);
|
|
||||||
IPage<EmergencyProfessionUser> result = emergencyProfessionUserMapper.selectPage(page, query);
|
// ---- 2. 查询 QH_EME_PROFESS_USER(急救专业人员) ----
|
||||||
// 批量查询系统用户信息,填充科室(部门)名称
|
LambdaQueryWrapper<EmergencyProfessionUser> profQuery = new LambdaQueryWrapper<>();
|
||||||
List<String> userIds = result.getRecords().stream()
|
profQuery.eq(EmergencyProfessionUser::getType, "6");
|
||||||
|
if (StrUtil.isNotBlank(realname)) {
|
||||||
|
profQuery.like(EmergencyProfessionUser::getRealname, realname);
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(centerId)) {
|
||||||
|
profQuery.eq(EmergencyProfessionUser::getCenterId, centerId);
|
||||||
|
}
|
||||||
|
if (!excludeUserIds.isEmpty()) {
|
||||||
|
profQuery.notIn(EmergencyProfessionUser::getUserId, excludeUserIds);
|
||||||
|
}
|
||||||
|
List<EmergencyProfessionUser> profUsers = emergencyProfessionUserMapper.selectList(profQuery);
|
||||||
|
|
||||||
|
// ---- 3. 查询 qh_con_doctor(咨询专家),排除已在 profUsers 或已在群中的 ----
|
||||||
|
List<String> skipIds = new ArrayList<>(excludeUserIds);
|
||||||
|
profUsers.forEach(u -> skipIds.add(u.getUserId()));
|
||||||
|
List<EmergencyProfessionUser> doctorUsers = conDoctorMapper.searchDoctorByName(realname, skipIds);
|
||||||
|
|
||||||
|
// ---- 4. 合并两条结果(profUsers 优先,doctorUsers 追加) ----
|
||||||
|
Map<String, EmergencyProfessionUser> mergedMap = new LinkedHashMap<>();
|
||||||
|
for (EmergencyProfessionUser u : profUsers) {
|
||||||
|
mergedMap.put(u.getUserId(), u);
|
||||||
|
}
|
||||||
|
// 从 qh_con_doctor 来的记录,不入 mergedMap 时用 doctorName 兜底 realname/avatar
|
||||||
|
for (EmergencyProfessionUser u : doctorUsers) {
|
||||||
|
mergedMap.putIfAbsent(u.getUserId(), u);
|
||||||
|
}
|
||||||
|
List<EmergencyProfessionUser> allRecords = new ArrayList<>(mergedMap.values());
|
||||||
|
|
||||||
|
// ---- 5. 批量查询 sys_user,统一填充 realname/avatar/phone/deptName ----
|
||||||
|
List<String> allUserIds = allRecords.stream()
|
||||||
.map(EmergencyProfessionUser::getUserId).collect(Collectors.toList());
|
.map(EmergencyProfessionUser::getUserId).collect(Collectors.toList());
|
||||||
if (!userIds.isEmpty()) {
|
if (!allUserIds.isEmpty()) {
|
||||||
Map<String, LoginUserNew> userMap = emergencyCloudManager.listUser(userIds);
|
Map<String, LoginUserNew> userMap = emergencyCloudManager.listUser(allUserIds);
|
||||||
result.getRecords().forEach(prof -> {
|
allRecords.forEach(prof -> {
|
||||||
LoginUserNew sysUser = userMap.get(prof.getUserId());
|
LoginUserNew sysUser = userMap.get(prof.getUserId());
|
||||||
if (sysUser != null && StrUtil.isNotBlank(sysUser.getOrgCode())) {
|
if (sysUser != null) {
|
||||||
prof.setDeptName(emergencyCacheManager.getUserDepart(sysUser.getOrgCode()).getDepartName());
|
// 兜底:从 qh_con_doctor 来的记录没有 realname/avatar,用 sys_user 填充
|
||||||
|
if (StrUtil.isBlank(prof.getRealname())) {
|
||||||
|
prof.setRealname(sysUser.getRealname());
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(prof.getAvatar())) {
|
||||||
|
prof.setAvatar(sysUser.getAvatar());
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(sysUser.getOrgCode())) {
|
||||||
|
prof.setDeptName(emergencyCacheManager.getUserDepart(sysUser.getOrgCode()).getDepartName());
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(prof.getPhone())) {
|
||||||
|
prof.setPhone(sysUser.getPhone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---- 6. 对 profUsers 补充 qh_con_doctor 专家字段 ----
|
||||||
|
List<String> profUserIds = profUsers.stream()
|
||||||
|
.map(EmergencyProfessionUser::getUserId).collect(Collectors.toList());
|
||||||
|
if (!profUserIds.isEmpty()) {
|
||||||
|
List<EmergencyProfessionUser> doctorList = conDoctorMapper.selectDoctorByIds(profUserIds);
|
||||||
|
if (CollectionUtils.isNotEmpty(doctorList)) {
|
||||||
|
Map<String, EmergencyProfessionUser> doctorMap = doctorList.stream()
|
||||||
|
.collect(Collectors.toMap(EmergencyProfessionUser::getUserId, e -> e, (a, b) -> a));
|
||||||
|
profUsers.forEach(prof -> {
|
||||||
|
EmergencyProfessionUser doc = doctorMap.get(prof.getUserId());
|
||||||
|
if (doc == null) return;
|
||||||
|
copyDoctorFields(doc, prof);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- 7. 内存分页 ----
|
||||||
|
int total = allRecords.size();
|
||||||
|
int pn = pageNo != null ? pageNo : 1;
|
||||||
|
int ps = pageSize != null ? pageSize : 10;
|
||||||
|
int fromIndex = Math.min((pn - 1) * ps, total);
|
||||||
|
int toIndex = Math.min(fromIndex + ps, total);
|
||||||
|
List<EmergencyProfessionUser> pageRecords = allRecords.subList(fromIndex, toIndex);
|
||||||
|
|
||||||
|
IPage<EmergencyProfessionUser> result = new Page<>(pn, ps, total);
|
||||||
|
result.setRecords(pageRecords);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void copyDoctorFields(EmergencyProfessionUser doc, EmergencyProfessionUser prof) {
|
||||||
|
prof.setDoctorName(doc.getDoctorName());
|
||||||
|
prof.setDoctorNo(doc.getDoctorNo());
|
||||||
|
prof.setPhoto(doc.getPhoto());
|
||||||
|
prof.setResourceName(doc.getResourceName());
|
||||||
|
prof.setDepartmentId(doc.getDepartmentId());
|
||||||
|
prof.setDepartmentName(doc.getDepartmentName());
|
||||||
|
prof.setDoctorTitle(doc.getDoctorTitle());
|
||||||
|
prof.setDoctorJob(doc.getDoctorJob());
|
||||||
|
prof.setDoctorStatus(doc.getDoctorStatus());
|
||||||
|
prof.setIsAccept(doc.getIsAccept());
|
||||||
|
prof.setDoctorType(doc.getDoctorType());
|
||||||
|
prof.setAudioStatus(doc.getAudioStatus());
|
||||||
|
prof.setTfJumpHoliday(doc.getTfJumpHoliday());
|
||||||
|
prof.setExperience(doc.getExperience());
|
||||||
|
prof.setSort(doc.getSort());
|
||||||
|
prof.setTfRecommend(doc.getTfRecommend());
|
||||||
|
prof.setIntroduction(doc.getIntroduction());
|
||||||
|
if (StrUtil.isNotBlank(doc.getGoodAt())) prof.setGoodAt(doc.getGoodAt());
|
||||||
|
if (StrUtil.isNotBlank(doc.getSchool())) prof.setSchool(doc.getSchool());
|
||||||
|
if (StrUtil.isNotBlank(doc.getEdu())) prof.setEdu(doc.getEdu());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IPage<EmployeeVO> searchEmployee(String realname, String orgCode, String workNo, String phone, String excludeSessionId, Integer pageNo, Integer pageSize) {
|
public IPage<EmployeeVO> searchEmployee(String realname, String orgCode, String workNo, String phone, String excludeSessionId, Integer pageNo, Integer pageSize) {
|
||||||
// 收集需要在结果中排除的用户ID
|
// 收集需要在结果中排除的用户ID
|
||||||
@@ -761,12 +1057,12 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService {
|
|||||||
excludeUserIds.addAll(ops.stream().map(OrderOperator::getUserId).collect(Collectors.toList()));
|
excludeUserIds.addAll(ops.stream().map(OrderOperator::getUserId).collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 构建查询条件
|
// 构建查询条件(姓名、工号、手机号拼接 * 实现模糊搜索)
|
||||||
SysUser filter = new SysUser();
|
SysUser filter = new SysUser();
|
||||||
filter.setRealname(realname);
|
filter.setRealname(StrUtil.isNotBlank(realname) ? "*" + realname + "*" : null);
|
||||||
filter.setOrgCode(orgCode);
|
filter.setOrgCode(orgCode);
|
||||||
filter.setWorkNo(workNo);
|
filter.setWorkNo(StrUtil.isNotBlank(workNo) ? "*" + workNo + "*" : null);
|
||||||
filter.setPhone(phone);
|
filter.setPhone(StrUtil.isNotBlank(phone) ? "*" + phone + "*" : null);
|
||||||
Page<SysUser> srcPage = sysBaseAPI.pageUser(filter, pageNo != null ? pageNo : 1, pageSize != null ? pageSize : 10, null);
|
Page<SysUser> srcPage = sysBaseAPI.pageUser(filter, pageNo != null ? pageNo : 1, pageSize != null ? pageSize : 10, null);
|
||||||
Page<EmployeeVO> targetPage = new Page<>(srcPage.getCurrent(), srcPage.getSize(), srcPage.getTotal());
|
Page<EmployeeVO> targetPage = new Page<>(srcPage.getCurrent(), srcPage.getSize(), srcPage.getTotal());
|
||||||
targetPage.setRecords(srcPage.getRecords().stream()
|
targetPage.setRecords(srcPage.getRecords().stream()
|
||||||
@@ -789,6 +1085,79 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService {
|
|||||||
return targetPage;
|
return targetPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPage<MyParticipatedOrderVO> myParticipatedOrders(Integer pageNo, Integer pageSize) {
|
||||||
|
String userId = GlobalUtils.getLoginUser().getId();
|
||||||
|
// 1. 查当前登录人参与的工单ID(从order_operator表)
|
||||||
|
List<String> participatedOrderIds = orderOperatorMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<OrderOperator>()
|
||||||
|
.select(OrderOperator::getOrderId)
|
||||||
|
.eq(OrderOperator::getUserId, userId)
|
||||||
|
).stream().map(OrderOperator::getOrderId).distinct().collect(Collectors.toList());
|
||||||
|
|
||||||
|
// 2. 查当前用户自己发起的或被救助的应急工单ID(从order表)
|
||||||
|
List<String> ownOrderIds = orderMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<Order>()
|
||||||
|
.select(Order::getId)
|
||||||
|
.and(w -> w.eq(Order::getInitiatorUserId, userId).or().eq(Order::getSalvageUserId, userId))
|
||||||
|
.eq(Order::getDelFlag, CommonConstant.DEL_FLAG_0)
|
||||||
|
.eq(Order::getStatus, 1)
|
||||||
|
).stream().map(Order::getId).distinct().collect(Collectors.toList());
|
||||||
|
|
||||||
|
// 3. 合并去重
|
||||||
|
Set<String> allOrderIds = new LinkedHashSet<>();
|
||||||
|
if (CollectionUtils.isNotEmpty(participatedOrderIds)) {
|
||||||
|
allOrderIds.addAll(participatedOrderIds);
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isNotEmpty(ownOrderIds)) {
|
||||||
|
allOrderIds.addAll(ownOrderIds);
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isEmpty(allOrderIds)) {
|
||||||
|
return new Page<>(pageNo != null ? pageNo : 1, pageSize != null ? pageSize : 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 分页查询正在应急的工单
|
||||||
|
Page<Order> page = new Page<>(pageNo != null ? pageNo : 1, pageSize != null ? pageSize : 10);
|
||||||
|
LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.in(Order::getId, new ArrayList<>(allOrderIds));
|
||||||
|
wrapper.eq(Order::getSessionNow, true);
|
||||||
|
wrapper.eq(Order::getDelFlag, CommonConstant.DEL_FLAG_0);
|
||||||
|
wrapper.eq(Order::getStatus, 1);
|
||||||
|
wrapper.orderByDesc(Order::getCreateTime);
|
||||||
|
IPage<Order> srcPage = orderMapper.selectPage(page, wrapper);
|
||||||
|
// 5. 映射VO
|
||||||
|
Page<MyParticipatedOrderVO> targetPage = new Page<>(srcPage.getCurrent(), srcPage.getSize(), srcPage.getTotal());
|
||||||
|
if (CollectionUtils.isEmpty(srcPage.getRecords())) {
|
||||||
|
return targetPage;
|
||||||
|
}
|
||||||
|
List<MyParticipatedOrderVO> records = srcPage.getRecords().stream().map(order -> {
|
||||||
|
MyParticipatedOrderVO vo = new MyParticipatedOrderVO();
|
||||||
|
vo.setOrderId(order.getId());
|
||||||
|
vo.setSessionId(order.getSessionId());
|
||||||
|
vo.setSalvageUserName(order.getSalvageUserName());
|
||||||
|
vo.setSalvageUserSex(order.getSalvageUserSex());
|
||||||
|
vo.setSalvageUserAvatar(order.getSalvageUserAvatar());
|
||||||
|
vo.setSalvageUserAge(order.getSalvageUserAge());
|
||||||
|
vo.setSalvageUserMobile(order.getSalvageUserMobile());
|
||||||
|
vo.setOrderStatus(order.getOrderStatus());
|
||||||
|
vo.setInitTime(order.getCreateTime());
|
||||||
|
// 解析部门(防NPE)
|
||||||
|
if (StrUtil.isNotBlank(order.getSalvageUserDepart())) {
|
||||||
|
SysDepart secondDepart = emergencyCacheManager.getUserSecondDepart(order.getSalvageUserDepart());
|
||||||
|
SysDepart depart = emergencyCacheManager.getUserDepart(order.getSalvageUserDepart());
|
||||||
|
if (secondDepart != null) {
|
||||||
|
vo.setOrgName(secondDepart.getDepartName());
|
||||||
|
}
|
||||||
|
if (depart != null) {
|
||||||
|
vo.setDeptName(depart.getDepartName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vo;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
targetPage.setRecords(records);
|
||||||
|
return targetPage;
|
||||||
|
}
|
||||||
|
|
||||||
private List<SessionOrderUser> convertOrder(List<Order> orders) {
|
private List<SessionOrderUser> convertOrder(List<Order> orders) {
|
||||||
if (CollectionUtils.isEmpty(orders)) {
|
if (CollectionUtils.isEmpty(orders)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
|||||||
+1
-1
@@ -74,7 +74,7 @@ public class FirstAidResourceController extends JeecgController<FirstAidResource
|
|||||||
return Result.error("标题不能为空");
|
return Result.error("标题不能为空");
|
||||||
}
|
}
|
||||||
resourceService.saveResource(entity);
|
resourceService.saveResource(entity);
|
||||||
return Result.OK("添加成功!");
|
return Result.OK("添加成功!", entity.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "急救宣教资源-编辑")
|
@Operation(summary = "急救宣教资源-编辑")
|
||||||
|
|||||||
+19
-1
@@ -251,7 +251,8 @@ public class LargeScreenNewController {
|
|||||||
* 关爱趋势某一条详情
|
* 关爱趋势某一条详情
|
||||||
*/
|
*/
|
||||||
@GetMapping("loveTrendByOne")
|
@GetMapping("loveTrendByOne")
|
||||||
public Result<CareUserListVo> loveTrendByOne(@RequestParam(name = "anYanUserId", required = false)String anYanUserId,
|
public Result<CareUserListVo>
|
||||||
|
loveTrendByOne(@RequestParam(name = "anYanUserId", required = false)String anYanUserId,
|
||||||
@RequestParam(name = "employeeNum", required = false)String employeeNum){
|
@RequestParam(name = "employeeNum", required = false)String employeeNum){
|
||||||
return Result.ok(largeScreenDataService.loveTrendByOne(anYanUserId,employeeNum));
|
return Result.ok(largeScreenDataService.loveTrendByOne(anYanUserId,employeeNum));
|
||||||
}
|
}
|
||||||
@@ -299,6 +300,23 @@ public class LargeScreenNewController {
|
|||||||
return Result.ok(largeScreenDataService.careUser(userId,workNo));
|
return Result.ok(largeScreenDataService.careUser(userId,workNo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据当前登录用户工号判断是否为联络人员
|
||||||
|
*/
|
||||||
|
@GetMapping("isLiaisonUser")
|
||||||
|
public Result<Boolean> isLiaisonUser(){
|
||||||
|
return Result.ok(largeScreenDataService.isLiaisonUser());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一人一案(移动端)
|
||||||
|
*/
|
||||||
|
@GetMapping("onePersonCase")
|
||||||
|
public Result<OnePersonCaseVO> onePersonCase(){
|
||||||
|
return Result.ok(largeScreenDataService.onePersonCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 或者安眼平台访问token
|
* 或者安眼平台访问token
|
||||||
* @return
|
* @return
|
||||||
|
|||||||
+285
@@ -0,0 +1,285 @@
|
|||||||
|
package com.renkang.emergency.largeScreen.entity.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.Period;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一人一案详情出参
|
||||||
|
* 数据来源:安眼库 AYGC_YWK.EMP_PERSON_FILE 及关联表
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class OnePersonCaseVO {
|
||||||
|
|
||||||
|
@Schema(title = "ID")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Schema(title = "员工ID")
|
||||||
|
private String empId;
|
||||||
|
|
||||||
|
@Schema(title = "员工姓名")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(title = "年龄")
|
||||||
|
private Integer age;
|
||||||
|
|
||||||
|
@Schema(title = "性别")
|
||||||
|
private String sexCode;
|
||||||
|
|
||||||
|
@Schema(title = "身份证号")
|
||||||
|
private String idNo;
|
||||||
|
|
||||||
|
@Schema(title = "手机号")
|
||||||
|
private String phone;
|
||||||
|
|
||||||
|
@Schema(title = "关爱状态")
|
||||||
|
private String careStatus;
|
||||||
|
|
||||||
|
@Schema(title = "工作单位")
|
||||||
|
private String workUnit ;
|
||||||
|
|
||||||
|
@Schema(title = "单位ID")
|
||||||
|
private String workUnitId;
|
||||||
|
|
||||||
|
@Schema(title = "创建时间")
|
||||||
|
private String createDate;
|
||||||
|
|
||||||
|
@Schema(title = "修改时间")
|
||||||
|
private String updateDate;
|
||||||
|
|
||||||
|
@Schema(title = "数据级别")
|
||||||
|
private Integer dataLevel;
|
||||||
|
|
||||||
|
@Schema(title = "负面清单")
|
||||||
|
private String negativeList;
|
||||||
|
|
||||||
|
@Schema(title = "一人一案")
|
||||||
|
private String caseInfo;
|
||||||
|
|
||||||
|
@Schema(title = "肥胖人员标识(1,是,2-否)")
|
||||||
|
private Integer flagFat;
|
||||||
|
|
||||||
|
@Schema(title = "BMI")
|
||||||
|
private String bmi;
|
||||||
|
|
||||||
|
@Schema(title = "身高")
|
||||||
|
private String height;
|
||||||
|
|
||||||
|
@Schema(title = "体重")
|
||||||
|
private String weight;
|
||||||
|
|
||||||
|
@Schema(title = "体重管理目标")
|
||||||
|
private String targetWeight;
|
||||||
|
|
||||||
|
@Schema(title = "目标BMI")
|
||||||
|
private String targetBmi;
|
||||||
|
|
||||||
|
@Schema(title = "目前BMI监测值")
|
||||||
|
private String bmiCurrent;
|
||||||
|
|
||||||
|
@Schema(title = "最新腰围")
|
||||||
|
private String waistNew;
|
||||||
|
|
||||||
|
@Schema(title = "最新体脂率")
|
||||||
|
private String bodyFatPercentNew;
|
||||||
|
|
||||||
|
@Schema(title = "体重风险类型")
|
||||||
|
private String weightRiskType;
|
||||||
|
|
||||||
|
@Schema(title = "高血压(0-否,1-是)")
|
||||||
|
private Integer hypertension;
|
||||||
|
|
||||||
|
@Schema(title = "收缩压均值")
|
||||||
|
private String systolicPressureAvg;
|
||||||
|
|
||||||
|
@Schema(title = "收缩压控制目标")
|
||||||
|
private String systolicPressureTarget;
|
||||||
|
|
||||||
|
@Schema(title = "目前收缩压检测值")
|
||||||
|
private String systolicPressureCurrent;
|
||||||
|
|
||||||
|
@Schema(title = "舒张压平均值")
|
||||||
|
private String diastolicPressureAvg;
|
||||||
|
|
||||||
|
@Schema(title = "舒张压控制目标值")
|
||||||
|
private String diastolicPressureTarget;
|
||||||
|
|
||||||
|
@Schema(title = "舒张压当前检测值")
|
||||||
|
private String diastolicPressureCurrent;
|
||||||
|
|
||||||
|
@Schema(title = "糖尿病标识(0-否,1-是)")
|
||||||
|
private Integer diabetes;
|
||||||
|
|
||||||
|
@Schema(title = "空腹葡萄糖(GLU)")
|
||||||
|
private String glu;
|
||||||
|
|
||||||
|
@Schema(title = "血糖控制目标值")
|
||||||
|
private String bloodSugarTarget;
|
||||||
|
|
||||||
|
@Schema(title = "目前血糖监测值:")
|
||||||
|
private String bloodSugarCurrent;
|
||||||
|
|
||||||
|
@Schema(title = "低密度脂蛋白")
|
||||||
|
private String ldl;
|
||||||
|
|
||||||
|
@Schema(title = "低密度脂蛋白目标控制值")
|
||||||
|
private String ldlTarget;
|
||||||
|
|
||||||
|
@Schema(title = "低密度脂蛋白当前检测值")
|
||||||
|
private String ldlCurrent;
|
||||||
|
|
||||||
|
@Schema(title = "总胆固醇")
|
||||||
|
private String tc;
|
||||||
|
|
||||||
|
@Schema(title = "总胆固醇目标控制值")
|
||||||
|
private String tcTarget;
|
||||||
|
|
||||||
|
@Schema(title = "总胆固醇目前监测值")
|
||||||
|
private String tcCurrent;
|
||||||
|
|
||||||
|
@Schema(title = "甘油三酯")
|
||||||
|
private String tg;
|
||||||
|
|
||||||
|
@Schema(title = "甘油三酯目标控制值")
|
||||||
|
private String tgTarget;
|
||||||
|
|
||||||
|
@Schema(title = "甘油三酯当前监测值")
|
||||||
|
private String tgCurrent;
|
||||||
|
|
||||||
|
@Schema(title = "尿酸")
|
||||||
|
private String uricAcid;
|
||||||
|
|
||||||
|
@Schema(title = "尿酸目标控制值")
|
||||||
|
private String uricAcidTarget;
|
||||||
|
|
||||||
|
@Schema(title = "尿酸当前监测值")
|
||||||
|
private String uricAcidCurrent;
|
||||||
|
|
||||||
|
@Schema(title = "同型半胱氨酸")
|
||||||
|
private String homocysteine;
|
||||||
|
|
||||||
|
@Schema(title = "同型半胱氨酸目标控制值")
|
||||||
|
private String homocysteineTarget;
|
||||||
|
|
||||||
|
@Schema(title = "同型半胱氨酸当前监测值")
|
||||||
|
private String homocysteineCurrent;
|
||||||
|
|
||||||
|
@Schema(title = "血钾")
|
||||||
|
private String bloodK;
|
||||||
|
|
||||||
|
@Schema(title = "冠心病")
|
||||||
|
private String chd;
|
||||||
|
|
||||||
|
@Schema(title = "脑血管")
|
||||||
|
private String cvd;
|
||||||
|
|
||||||
|
@Schema(title = "心房颤动")
|
||||||
|
private String af;
|
||||||
|
|
||||||
|
@Schema(title = "恶性肿瘤")
|
||||||
|
private String ca;
|
||||||
|
|
||||||
|
@Schema(title = "检测指标列表")
|
||||||
|
private String indicatorListStr;
|
||||||
|
|
||||||
|
@Schema(title = "导入指标列表")
|
||||||
|
private String indicatorListStrOrigin;
|
||||||
|
|
||||||
|
@Schema(title = "风险等级")
|
||||||
|
private String riskLevel;
|
||||||
|
|
||||||
|
@Schema(title = "年度")
|
||||||
|
private String year;
|
||||||
|
|
||||||
|
@Schema(title = "筛查项目汇总")
|
||||||
|
private String screeningProjects;
|
||||||
|
|
||||||
|
@Schema(title = "关爱联络员姓名")
|
||||||
|
private String careLiaisonName;
|
||||||
|
|
||||||
|
@Schema(title = "治疗方案")
|
||||||
|
private String treatPlan;
|
||||||
|
|
||||||
|
@Schema(title = "治疗方案反馈")
|
||||||
|
private String treatPlanResponse;
|
||||||
|
|
||||||
|
@Schema(title = "饮食建议")
|
||||||
|
private String dietSuggestion;
|
||||||
|
|
||||||
|
@Schema(title = "饮食建议反馈")
|
||||||
|
private String dietSuggestionResponse;
|
||||||
|
|
||||||
|
@Schema(title = "运动指导")
|
||||||
|
private String sportGuide;
|
||||||
|
|
||||||
|
@Schema(title = "运动指导反馈")
|
||||||
|
private String sportGuideResponse;
|
||||||
|
|
||||||
|
@Schema(title = "日常生活管理")
|
||||||
|
private String lifeManage;
|
||||||
|
|
||||||
|
@Schema(title = "日常生活管理反馈")
|
||||||
|
private String lifeManageResponse;
|
||||||
|
|
||||||
|
@Schema(title = "小屋意见")
|
||||||
|
private String cabinOpinion;
|
||||||
|
|
||||||
|
@Schema(title = "小屋意见时间")
|
||||||
|
private String cabinOpinionTime;
|
||||||
|
|
||||||
|
@Schema(title = "小屋意见员工姓名")
|
||||||
|
private String cabinOpinionUserName;
|
||||||
|
|
||||||
|
@Schema(title = "专家意见")
|
||||||
|
private String expertOpinion;
|
||||||
|
|
||||||
|
@Schema(title = "专家意见时间")
|
||||||
|
private String expertOpinionTime;
|
||||||
|
|
||||||
|
@Schema(title = "专家意见员工姓名")
|
||||||
|
private String expertOpinionUserName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BMI 保留一位小数
|
||||||
|
* 数据库 BMI 列为 VARCHAR,这里解析为数值后四舍五入
|
||||||
|
*/
|
||||||
|
public String getBmi() {
|
||||||
|
if (bmi == null || bmi.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
double v = Double.parseDouble(bmi.trim());
|
||||||
|
return String.valueOf(Math.round(v * 10) / 10.0);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return bmi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 年龄:优先取库中值,为空时根据身份证号计算
|
||||||
|
*/
|
||||||
|
public Integer getAge() {
|
||||||
|
if (age != null) {
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
if (idNo == null || idNo.length() != 18) {
|
||||||
|
return null; // 身份证号无效时返回null
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// 截取出生日期字符串
|
||||||
|
String birthDateStr = idNo.substring(6, 14);
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
|
||||||
|
LocalDate birthDate = LocalDate.parse(birthDateStr, formatter);
|
||||||
|
LocalDate now = LocalDate.now();
|
||||||
|
if (birthDate.isAfter(now)) {
|
||||||
|
return null; // 出生日期在未来,返回null
|
||||||
|
}
|
||||||
|
return Period.between(birthDate, now).getYears();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null; // 解析异常返回null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+42
@@ -2,6 +2,12 @@ package com.renkang.emergency.largeScreen.mapper;
|
|||||||
|
|
||||||
import com.github.yulichang.base.MPJBaseMapper;
|
import com.github.yulichang.base.MPJBaseMapper;
|
||||||
import com.renkang.emergency.entity.LargeScreenData;
|
import com.renkang.emergency.entity.LargeScreenData;
|
||||||
|
import com.renkang.emergency.largeScreen.entity.vo.OnePersonCaseVO;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: large_screen
|
* @Description: large_screen
|
||||||
@@ -11,4 +17,40 @@ import com.renkang.emergency.entity.LargeScreenData;
|
|||||||
*/
|
*/
|
||||||
public interface LargeScreenDataMapper extends MPJBaseMapper<LargeScreenData> {
|
public interface LargeScreenDataMapper extends MPJBaseMapper<LargeScreenData> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据工号查询关爱联络员关系表记录数
|
||||||
|
*
|
||||||
|
* @param workNo 工号
|
||||||
|
* @return 命中记录数,大于 0 表示该工号是关爱联络员
|
||||||
|
*/
|
||||||
|
@Select("SELECT COUNT(1) FROM AYGC_YWK.HYT_RELATION_CARE_NEW WHERE ADMIN_NUM = #{workNo}")
|
||||||
|
int countByAdminNum(@Param("workNo") String workNo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一人一案:根据工号查询最新一条档案详情
|
||||||
|
* SQL 见同包 xml/LargeScreenDataMapper.xml
|
||||||
|
*
|
||||||
|
* @param workNo 工号
|
||||||
|
* @return 一人一案详情,无数据时返回 null
|
||||||
|
*/
|
||||||
|
OnePersonCaseVO selectOnePersonCase(@Param("workNo") String workNo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据手机号批量查询 EMP_BASIC_INFO 的员工编号
|
||||||
|
* SQL 见同包 xml/LargeScreenDataMapper.xml
|
||||||
|
*
|
||||||
|
* @param phones 手机号集合
|
||||||
|
* @return 手机号→员工编号映射列表 (key: PHONE, EMPLOYEE_NUM)
|
||||||
|
*/
|
||||||
|
List<Map<String, String>> selectEmployeeNumsByPhones(@Param("phones") List<String> phones);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询 EMP_CARE_EMP 表中 FIRST_AIDER_INFO 是否包含指定工号
|
||||||
|
*
|
||||||
|
* @param workNo 工号
|
||||||
|
* @return 命中记录数,大于 0 表示该工号是急救人员
|
||||||
|
*/
|
||||||
|
@Select("SELECT COUNT(1) FROM AYGC_YWK.EMP_CARE_EMP WHERE DEL_FLAG = '0' AND FIRST_AIDER_INFO LIKE CONCAT('%', #{workNo}, '%')")
|
||||||
|
int countFirstAiderByWorkNo(@Param("workNo") String workNo);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+207
@@ -0,0 +1,207 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.renkang.emergency.largeScreen.mapper.LargeScreenDataMapper">
|
||||||
|
|
||||||
|
<!-- 一人一案:根据工号取最新一条档案详情 -->
|
||||||
|
<select id="selectOnePersonCase" resultType="com.renkang.emergency.largeScreen.entity.vo.OnePersonCaseVO">
|
||||||
|
SELECT
|
||||||
|
f.ID AS "id",
|
||||||
|
f.EMP_ID AS "empId",
|
||||||
|
b.NAME AS "name",
|
||||||
|
b.ID_NO AS "idNo",
|
||||||
|
b.AGE AS "age",
|
||||||
|
b.PHONE AS "phone",
|
||||||
|
b.IS_HEART_BRAIN_BLOOD_CARE_EMP AS "careStatus",
|
||||||
|
f.DATA_LEVEL AS "dataLevel",
|
||||||
|
f.NEGATIVE_LIST AS "negativeList",
|
||||||
|
f.CASE_INFO AS "caseInfo",
|
||||||
|
f.FLAG_FAT AS "flagFat",
|
||||||
|
f.BMI AS "bmi",
|
||||||
|
f.HEIGHT AS "height",
|
||||||
|
f.WEIGHT AS "weight",
|
||||||
|
f.WEIGHT_TARGET AS "targetWeight",
|
||||||
|
CASE
|
||||||
|
WHEN f.HEIGHT > 0
|
||||||
|
AND REGEXP_LIKE (f.WEIGHT_TARGET, '^[0-9]+(\.[0-9]+)?$') THEN ROUND(
|
||||||
|
TO_NUMBER (f.WEIGHT_TARGET) / POWER(f.HEIGHT / 100.0, 2),
|
||||||
|
2
|
||||||
|
)
|
||||||
|
ELSE NULL
|
||||||
|
END AS "targetBmi",
|
||||||
|
f.HYPERTENSION AS "hypertension",
|
||||||
|
f.SYSTOLIC_PRESSURE_AVG AS "systolicPressureAvg",
|
||||||
|
f.SYSTOLIC_PRESSURE_TARGET AS "systolicPressureTarget",
|
||||||
|
f.DIASTOLIC_PRESSURE_AVG AS "diastolicPressureAvg",
|
||||||
|
f.DIASTOLIC_PRESSURE_TARGET AS "diastolicPressureTarget",
|
||||||
|
f.DIABETES AS "diabetes",
|
||||||
|
f.GLU AS "glu",
|
||||||
|
f.BLOOD_SUGAR_TARGET AS "bloodSugarTarget",
|
||||||
|
f.LDL AS "ldl",
|
||||||
|
f.LDL_TARGET AS "ldlTarget",
|
||||||
|
f.TC AS "tc",
|
||||||
|
f.TC_TARGET AS "tcTarget",
|
||||||
|
f.TG AS "tg",
|
||||||
|
f.TG_TARGET AS "tgTarget",
|
||||||
|
f.URIC_ACID AS "uricAcid",
|
||||||
|
f.URIC_ACID_TARGET AS "uricAcidTarget",
|
||||||
|
f.HOMOCYSTEINE AS "homocysteine",
|
||||||
|
f.HOMOCYSTEINE_TARGET AS "homocysteineTarget",
|
||||||
|
f.BLOOD_K AS "bloodK",
|
||||||
|
f.CHD AS "chd",
|
||||||
|
f.CVD AS "cvd",
|
||||||
|
f.AF AS "af",
|
||||||
|
f.CA AS "ca",
|
||||||
|
f.INDICATOR_LIST_STR AS "indicatorListStr",
|
||||||
|
f.INDICATOR_LIST_STR_ORIGIN AS "indicatorListStrOrigin",
|
||||||
|
f.TREAT_PLAN AS "treatPlan",
|
||||||
|
f.TREAT_PLAN_RESPONSE AS "treatPlanResponse",
|
||||||
|
f.DIET_SUGGESTION AS "dietSuggestion",
|
||||||
|
f.DIET_SUGGESTION_RESPONSE AS "dietSuggestionResponse",
|
||||||
|
f.SPORT_GUIDE AS "sportGuide",
|
||||||
|
f.SPORT_GUIDE_RESPONSE AS "sportGuideResponse",
|
||||||
|
f.LIFE_MANAGE AS "lifeManage",
|
||||||
|
f.LIFE_MANAGE_RESPONSE AS "lifeManageResponse",
|
||||||
|
f.RISK_LEVEL AS "riskLevel",
|
||||||
|
f.YEAR AS "year",
|
||||||
|
w.BMI_NEW AS "bmiCurrent",
|
||||||
|
w.WAIST_NEW AS "waistNew",
|
||||||
|
w.BODY_FAT_PERCENT_NEW AS "bodyFatPercentNew",
|
||||||
|
w.TYPE AS "weightRiskType",
|
||||||
|
ft.PROJECTS AS "screeningProjects",
|
||||||
|
-- 小屋意见
|
||||||
|
(
|
||||||
|
SELECT d.RESPONSE_CONTENT
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
RESPONSE_CONTENT,
|
||||||
|
CREATE_DATE,
|
||||||
|
CREATE_BY,
|
||||||
|
ROW_NUMBER() OVER (ORDER BY CREATE_DATE DESC) as rn
|
||||||
|
FROM AYGC_YWK.EMP_PERSON_FILE_DETAIL
|
||||||
|
WHERE EMP_ID = f.EMP_ID
|
||||||
|
AND DEL_FLAG = '0'
|
||||||
|
AND RESPONSE_TYPE = '小屋意见'
|
||||||
|
) d
|
||||||
|
WHERE d.rn = 1
|
||||||
|
) AS "cabinOpinion",
|
||||||
|
-- 小屋意见时间
|
||||||
|
(
|
||||||
|
SELECT d.CREATE_DATE
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
RESPONSE_CONTENT,
|
||||||
|
CREATE_DATE,
|
||||||
|
CREATE_BY,
|
||||||
|
ROW_NUMBER() OVER (ORDER BY CREATE_DATE DESC) as rn
|
||||||
|
FROM AYGC_YWK.EMP_PERSON_FILE_DETAIL
|
||||||
|
WHERE EMP_ID = f.EMP_ID
|
||||||
|
AND DEL_FLAG = '0'
|
||||||
|
AND RESPONSE_TYPE = '小屋意见'
|
||||||
|
) d
|
||||||
|
WHERE d.rn = 1
|
||||||
|
) AS "cabinOpinionTime",
|
||||||
|
-- 小屋意见员工姓名
|
||||||
|
(
|
||||||
|
SELECT u.NAME
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
CREATE_BY,
|
||||||
|
ROW_NUMBER() OVER (ORDER BY CREATE_DATE DESC) as rn
|
||||||
|
FROM AYGC_YWK.EMP_PERSON_FILE_DETAIL
|
||||||
|
WHERE EMP_ID = f.EMP_ID
|
||||||
|
AND DEL_FLAG = '0'
|
||||||
|
AND RESPONSE_TYPE = '小屋意见'
|
||||||
|
) d
|
||||||
|
LEFT JOIN AYGC_XTK.SYS_USER u ON u.ID = d.CREATE_BY
|
||||||
|
WHERE d.rn = 1
|
||||||
|
) AS "cabinOpinionUserName",
|
||||||
|
-- 专家意见
|
||||||
|
(
|
||||||
|
SELECT d.RESPONSE_CONTENT
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
RESPONSE_CONTENT,
|
||||||
|
CREATE_DATE,
|
||||||
|
CREATE_BY,
|
||||||
|
ROW_NUMBER() OVER (ORDER BY CREATE_DATE DESC) as rn
|
||||||
|
FROM AYGC_YWK.EMP_PERSON_FILE_DETAIL
|
||||||
|
WHERE EMP_ID = f.EMP_ID
|
||||||
|
AND DEL_FLAG = '0'
|
||||||
|
AND RESPONSE_TYPE = '专家意见'
|
||||||
|
) d
|
||||||
|
WHERE d.rn = 1
|
||||||
|
) AS "expertOpinion",
|
||||||
|
-- 专家意见时间
|
||||||
|
(
|
||||||
|
SELECT d.CREATE_DATE
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
RESPONSE_CONTENT,
|
||||||
|
CREATE_DATE,
|
||||||
|
CREATE_BY,
|
||||||
|
ROW_NUMBER() OVER (ORDER BY CREATE_DATE DESC) as rn
|
||||||
|
FROM AYGC_YWK.EMP_PERSON_FILE_DETAIL
|
||||||
|
WHERE EMP_ID = f.EMP_ID
|
||||||
|
AND DEL_FLAG = '0'
|
||||||
|
AND RESPONSE_TYPE = '专家意见'
|
||||||
|
) d
|
||||||
|
WHERE d.rn = 1
|
||||||
|
) AS "expertOpinionTime",
|
||||||
|
-- 专家意见员工姓名
|
||||||
|
(
|
||||||
|
SELECT u.NAME
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
CREATE_BY,
|
||||||
|
ROW_NUMBER() OVER (ORDER BY CREATE_DATE DESC) as rn
|
||||||
|
FROM AYGC_YWK.EMP_PERSON_FILE_DETAIL
|
||||||
|
WHERE EMP_ID = f.EMP_ID
|
||||||
|
AND DEL_FLAG = '0'
|
||||||
|
AND RESPONSE_TYPE = '专家意见'
|
||||||
|
) d
|
||||||
|
LEFT JOIN AYGC_XTK.SYS_USER u ON u.ID = d.CREATE_BY
|
||||||
|
WHERE d.rn = 1
|
||||||
|
) AS "expertOpinionUserName"
|
||||||
|
FROM
|
||||||
|
AYGC_YWK.EMP_PERSON_FILE f
|
||||||
|
LEFT JOIN AYGC_YWK.EMP_BASIC_INFO b ON b.ID = f.EMP_ID AND b.DEL_FLAG = '0'
|
||||||
|
LEFT JOIN AYGC_YWK.WEIGHT_MANAGEMENT w ON w.EMP_ID = f.EMP_ID AND w.DEL_FLAG = '2'
|
||||||
|
AND w.YEAR = f.YEAR
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT
|
||||||
|
EMP_ID,
|
||||||
|
LISTAGG (PROJECT || ':' || NVL (CHECK_RESULT, ''), ';') WITHIN GROUP (
|
||||||
|
ORDER BY
|
||||||
|
CHECK_DATE DESC
|
||||||
|
) AS PROJECTS
|
||||||
|
FROM
|
||||||
|
AYGC_YWK.EMP_FIVE_THREE
|
||||||
|
WHERE
|
||||||
|
DEL_FLAG = 2
|
||||||
|
GROUP BY
|
||||||
|
EMP_ID
|
||||||
|
) ft ON ft.EMP_ID = f.EMP_ID
|
||||||
|
WHERE
|
||||||
|
f.DEL_FLAG = '0'
|
||||||
|
AND b.EMPLOYEE_NUM = #{workNo}
|
||||||
|
ORDER BY f.CREATE_DATE DESC
|
||||||
|
FETCH FIRST 1 ROWS ONLY
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 根据手机号批量查询EMP_BASIC_INFO的员工编号,INSTR模糊匹配支持任意分隔符的多手机号场景 -->
|
||||||
|
<select id="selectEmployeeNumsByPhones" resultType="java.util.HashMap">
|
||||||
|
SELECT
|
||||||
|
b.PHONE AS "phone",
|
||||||
|
b.EMPLOYEE_NUM AS "employeeNum"
|
||||||
|
FROM
|
||||||
|
AYGC_YWK.EMP_BASIC_INFO b
|
||||||
|
WHERE
|
||||||
|
b.DEL_FLAG = '0'
|
||||||
|
AND (
|
||||||
|
<foreach collection="phones" item="phone" separator=" OR " open="(" close=")">
|
||||||
|
INSTR(b.PHONE, #{phone}) > 0
|
||||||
|
</foreach>
|
||||||
|
)
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
+5
@@ -13,6 +13,7 @@ import com.renkang.emergency.entity.dto.LargeScreenDataValueDTO;
|
|||||||
import com.renkang.emergency.entity.vo.DataDetailVO;
|
import com.renkang.emergency.entity.vo.DataDetailVO;
|
||||||
import com.renkang.emergency.entity.vo.MedicalDataVO;
|
import com.renkang.emergency.entity.vo.MedicalDataVO;
|
||||||
import com.renkang.emergency.largeScreen.entity.dto.TodayEmergencyDTO;
|
import com.renkang.emergency.largeScreen.entity.dto.TodayEmergencyDTO;
|
||||||
|
import com.renkang.emergency.largeScreen.entity.vo.OnePersonCaseVO;
|
||||||
import com.renkang.emergency.largeScreen.entity.vo.TodayEmergencyVO;
|
import com.renkang.emergency.largeScreen.entity.vo.TodayEmergencyVO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -51,6 +52,10 @@ public interface ILargeScreenDataService extends IService<LargeScreenData> {
|
|||||||
|
|
||||||
CareUserVO careUser(String userId,String workNo);
|
CareUserVO careUser(String userId,String workNo);
|
||||||
|
|
||||||
|
Boolean isLiaisonUser();
|
||||||
|
|
||||||
|
OnePersonCaseVO onePersonCase();
|
||||||
|
|
||||||
IPage<AnYanHealthCheckNew> queryAnYanHealthCheckNew(AnYanHealthCheckNewParam param);
|
IPage<AnYanHealthCheckNew> queryAnYanHealthCheckNew(AnYanHealthCheckNewParam param);
|
||||||
|
|
||||||
AnYanEmpHealthCheckNew queryCheckNewByCheckId(String id);
|
AnYanEmpHealthCheckNew queryCheckNewByCheckId(String id);
|
||||||
|
|||||||
+21
@@ -22,6 +22,7 @@ import com.renkang.emergency.entity.vo.DataDetailVO;
|
|||||||
import com.renkang.emergency.entity.vo.MedicalDataVO;
|
import com.renkang.emergency.entity.vo.MedicalDataVO;
|
||||||
import com.renkang.emergency.largeScreen.entity.dto.TodayEmergencyDTO;
|
import com.renkang.emergency.largeScreen.entity.dto.TodayEmergencyDTO;
|
||||||
import com.renkang.emergency.largeScreen.entity.vo.LargeScreenMap;
|
import com.renkang.emergency.largeScreen.entity.vo.LargeScreenMap;
|
||||||
|
import com.renkang.emergency.largeScreen.entity.vo.OnePersonCaseVO;
|
||||||
import com.renkang.emergency.largeScreen.entity.vo.TodayEmergencyVO;
|
import com.renkang.emergency.largeScreen.entity.vo.TodayEmergencyVO;
|
||||||
import com.renkang.emergency.largeScreen.mapper.LargeScreenDataMapper;
|
import com.renkang.emergency.largeScreen.mapper.LargeScreenDataMapper;
|
||||||
import com.renkang.emergency.largeScreen.service.ILargeScreenDataService;
|
import com.renkang.emergency.largeScreen.service.ILargeScreenDataService;
|
||||||
@@ -928,6 +929,26 @@ public class LargeScreenDataServiceImpl extends ServiceImpl<LargeScreenDataMappe
|
|||||||
return careUserVO;
|
return careUserVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean isLiaisonUser(){
|
||||||
|
LoginUser loginUser = GlobalUtils.getLoginUser();
|
||||||
|
String workNo = loginUser.getWorkNo();
|
||||||
|
if (StrUtil.isEmpty(workNo)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return baseMapper.countFirstAiderByWorkNo(workNo) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OnePersonCaseVO onePersonCase(){
|
||||||
|
LoginUser loginUser = GlobalUtils.getLoginUser();
|
||||||
|
String workNo = loginUser.getWorkNo();
|
||||||
|
if (StrUtil.isEmpty(workNo)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return baseMapper.selectOnePersonCase(workNo);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IPage<AnYanHealthCheckNew> queryAnYanHealthCheckNew(AnYanHealthCheckNewParam param) {
|
public IPage<AnYanHealthCheckNew> queryAnYanHealthCheckNew(AnYanHealthCheckNewParam param) {
|
||||||
return anYanClient.queryAnYanHealthCheckNew(param);
|
return anYanClient.queryAnYanHealthCheckNew(param);
|
||||||
|
|||||||
+1
-1
@@ -46,7 +46,7 @@ public class EmergencyCloudManager {
|
|||||||
// TODO 微服务调用会发送post请求 暂时将 listUserByIds修改为post
|
// TODO 微服务调用会发送post请求 暂时将 listUserByIds修改为post
|
||||||
list = sysBaseAPI.listUserByIds(listUser);
|
list = sysBaseAPI.listUserByIds(listUser);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("微服务调用失败(system listUserByIds)");
|
logger.error("微服务调用失败(system listUserByIds)", e);
|
||||||
}
|
}
|
||||||
if (CollectionUtils.isEmpty(list)) {
|
if (CollectionUtils.isEmpty(list)) {
|
||||||
return map;
|
return map;
|
||||||
|
|||||||
+65
@@ -0,0 +1,65 @@
|
|||||||
|
package com.renkang.emergency.mapper;
|
||||||
|
|
||||||
|
import com.renkang.emergency.entity.EmergencyProfessionUser;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 咨询服务医生表(qh_con_doctor) 查询
|
||||||
|
* 说明:health-emergency 与 health-consultation 共用同一数据库,
|
||||||
|
* 但模块间无依赖,故在应急模块内直接查询 qh_con_doctor。
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface ConDoctorMapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据医生id(=应急用户userId)批量查询专家资料
|
||||||
|
* 仅返回有效医生:del_flag='0' 且 status='1'
|
||||||
|
*
|
||||||
|
* @param doctorIds 医生id集合
|
||||||
|
* @return 以 EmergencyProfessionUser 承载 con_doctor 字段(仅填充新增的 exist=false 字段与 goodAt/school/edu)
|
||||||
|
*/
|
||||||
|
@Select("<script>" +
|
||||||
|
"SELECT id AS userId, " +
|
||||||
|
"doctor_name AS doctorName, doctor_no AS doctorNo, photo, " +
|
||||||
|
"resource_name AS resourceName, department_id AS departmentId, department_name AS departmentName, " +
|
||||||
|
"doctor_title AS doctorTitle, doctor_job AS doctorJob, doctor_status AS doctorStatus, " +
|
||||||
|
"is_accept AS isAccept, type AS doctorType, audio_status AS audioStatus, tf_jump_holiday AS tfJumpHoliday, " +
|
||||||
|
"experience, good_at AS goodAt, school, e_q AS edu, sort, " +
|
||||||
|
"tf_recommend AS tfRecommend, introduction " +
|
||||||
|
"FROM qh_con_doctor " +
|
||||||
|
"WHERE del_flag = '0' AND status = '1' AND id IN " +
|
||||||
|
"<foreach collection='doctorIds' item='id' open='(' separator=',' close=')'>#{id}</foreach>" +
|
||||||
|
"</script>")
|
||||||
|
List<EmergencyProfessionUser> selectDoctorByIds(@Param("doctorIds") List<String> doctorIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索专家(从 qh_con_doctor 表),排除已在应急专业人员表或已在群中的用户
|
||||||
|
*
|
||||||
|
* @param name 医生姓名,模糊匹配
|
||||||
|
* @param excludeIds 需要排除的用户ID集合(已从 QH_EME_PROFESS_USER 查到 + 已在群中的)
|
||||||
|
* @return 以 EmergencyProfessionUser 承载结果,基础字段由 SQL 别名映射
|
||||||
|
*/
|
||||||
|
@Select("<script>" +
|
||||||
|
"SELECT id AS userId, doctor_name AS realname, photo AS avatar, " +
|
||||||
|
"doctor_name AS doctorName, doctor_no AS doctorNo, " +
|
||||||
|
"resource_name AS resourceName, department_id AS departmentId, department_name AS departmentName, " +
|
||||||
|
"doctor_title AS doctorTitle, doctor_job AS doctorJob, doctor_status AS doctorStatus, " +
|
||||||
|
"is_accept AS isAccept, type AS doctorType, audio_status AS audioStatus, tf_jump_holiday AS tfJumpHoliday, " +
|
||||||
|
"experience, good_at AS goodAt, school, e_q AS edu, sort, " +
|
||||||
|
"tf_recommend AS tfRecommend, introduction " +
|
||||||
|
"FROM qh_con_doctor " +
|
||||||
|
"WHERE del_flag = '0' AND status = '1' " +
|
||||||
|
"<if test='name != null and name != \"\"'>" +
|
||||||
|
"AND doctor_name LIKE CONCAT('%', CONCAT(#{name}, '%')) " +
|
||||||
|
"</if>" +
|
||||||
|
"<if test='excludeIds != null and excludeIds.size() > 0'>" +
|
||||||
|
"AND id NOT IN " +
|
||||||
|
"<foreach collection='excludeIds' item='id' open='(' separator=',' close=')'>#{id}</foreach>" +
|
||||||
|
"</if>" +
|
||||||
|
"</script>")
|
||||||
|
List<EmergencyProfessionUser> searchDoctorByName(@Param("name") String name, @Param("excludeIds") List<String> excludeIds);
|
||||||
|
}
|
||||||
+7
-7
@@ -20,38 +20,38 @@ public interface FirstAidResourceCategoryMapper extends BaseMapper<FirstAidResou
|
|||||||
/**
|
/**
|
||||||
* 查询某分类下的标签数量(级联删除校验用,TYPE=2)
|
* 查询某分类下的标签数量(级联删除校验用,TYPE=2)
|
||||||
*/
|
*/
|
||||||
@Select("SELECT COUNT(*) FROM QH_EME_FIRST_AID_RESOURCE_CATEGORY WHERE PARENT_ID = #{parentId} AND TYPE = 2 AND DEL_FLAG = 0")
|
@Select("SELECT COUNT(*) FROM QH_EME_FIR_AID_RES_CATE WHERE PARENT_ID = #{parentId} AND TYPE = 2 AND DEL_FLAG = 0")
|
||||||
Integer countChildrenByParentId(@Param("parentId") String parentId);
|
Integer countChildrenByParentId(@Param("parentId") String parentId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询某分类下的资源数量(级联删除校验用)
|
* 查询某分类下的资源数量(级联删除校验用)
|
||||||
*/
|
*/
|
||||||
@Select("SELECT COUNT(*) FROM QH_EME_FIRST_AID_RESOURCE WHERE CATEGORY_ID = #{categoryId} AND DEL_FLAG = 0")
|
@Select("SELECT COUNT(*) FROM QH_EME_FIR_AID_RES WHERE CATEGORY_ID = #{categoryId} AND DEL_FLAG = 0")
|
||||||
Integer countResourcesByCategoryId(@Param("categoryId") String categoryId);
|
Integer countResourcesByCategoryId(@Param("categoryId") String categoryId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询引用某标签的资源数量(标签删除校验用)
|
* 查询引用某标签的资源数量(标签删除校验用)
|
||||||
*/
|
*/
|
||||||
@Select("SELECT COUNT(*) FROM QH_EME_FIRST_AID_RESOURCE WHERE DEL_FLAG = 0 AND CONCAT(',', TAGS, ',') LIKE CONCAT('%,', #{tagId}, ',%')")
|
@Select("SELECT COUNT(*) FROM QH_EME_FIR_AID_RES WHERE DEL_FLAG = 0 AND CONCAT(',', TAGS, ',') LIKE CONCAT('%,', #{tagId}, ',%')")
|
||||||
Integer countResourcesByTagId(@Param("tagId") String tagId);
|
Integer countResourcesByTagId(@Param("tagId") String tagId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按父分类ID查询标签列表(TYPE=2)
|
* 按父分类ID查询标签列表(TYPE=2)
|
||||||
*/
|
*/
|
||||||
@Select("SELECT * FROM QH_EME_FIRST_AID_RESOURCE_CATEGORY WHERE PARENT_ID = #{parentId} AND TYPE = 2 AND STATUS = 1 AND DEL_FLAG = 0 ORDER BY SORT_NO ASC")
|
@Select("SELECT * FROM QH_EME_FIR_AID_RES_CATE WHERE PARENT_ID = #{parentId} AND TYPE = 2 AND STATUS = 1 AND DEL_FLAG = 0 ORDER BY SORT_NO ASC")
|
||||||
List<FirstAidResourceCategory> selectByParentId(@Param("parentId") String parentId);
|
List<FirstAidResourceCategory> selectByParentId(@Param("parentId") String parentId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按类型查询分类/标签列表
|
* 按类型查询分类/标签列表
|
||||||
*/
|
*/
|
||||||
@Select("SELECT * FROM QH_EME_FIRST_AID_RESOURCE_CATEGORY WHERE TYPE = #{type} AND STATUS = 1 AND DEL_FLAG = 0 ORDER BY SORT_NO ASC, CREATE_TIME DESC")
|
@Select("SELECT * FROM QH_EME_FIR_AID_RES_CATE WHERE TYPE = #{type} AND STATUS = 1 AND DEL_FLAG = 0 ORDER BY SORT_NO ASC, CREATE_TIME DESC")
|
||||||
List<FirstAidResourceCategory> selectByType(@Param("type") Integer type);
|
List<FirstAidResourceCategory> selectByType(@Param("type") Integer type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按类型+父分类查询标签列表
|
* 按类型+父分类查询标签列表
|
||||||
*/
|
*/
|
||||||
@Select("<script>" +
|
@Select("<script>" +
|
||||||
"SELECT * FROM QH_EME_FIRST_AID_RESOURCE_CATEGORY WHERE TYPE = #{type} AND STATUS = 1 AND DEL_FLAG = 0" +
|
"SELECT * FROM QH_EME_FIR_AID_RES_CATE WHERE TYPE = #{type} AND STATUS = 1 AND DEL_FLAG = 0" +
|
||||||
"<if test='parentId != null and parentId != \"\"'> AND PARENT_ID = #{parentId}</if>" +
|
"<if test='parentId != null and parentId != \"\"'> AND PARENT_ID = #{parentId}</if>" +
|
||||||
" ORDER BY SORT_NO ASC, CREATE_TIME DESC" +
|
" ORDER BY SORT_NO ASC, CREATE_TIME DESC" +
|
||||||
"</script>")
|
"</script>")
|
||||||
@@ -60,7 +60,7 @@ public interface FirstAidResourceCategoryMapper extends BaseMapper<FirstAidResou
|
|||||||
/**
|
/**
|
||||||
* 查询所有根分类(PARENT_ID IS NULL)
|
* 查询所有根分类(PARENT_ID IS NULL)
|
||||||
*/
|
*/
|
||||||
@Select("SELECT * FROM QH_EME_FIRST_AID_RESOURCE_CATEGORY WHERE TYPE = 1 AND PARENT_ID IS NULL AND STATUS = 1 AND DEL_FLAG = 0 ORDER BY SORT_NO ASC")
|
@Select("SELECT * FROM QH_EME_FIR_AID_RES_CATE WHERE TYPE = 1 AND PARENT_ID IS NULL AND STATUS = 1 AND DEL_FLAG = 0 ORDER BY SORT_NO ASC")
|
||||||
List<FirstAidResourceCategory> selectRootCategories();
|
List<FirstAidResourceCategory> selectRootCategories();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -19,24 +19,24 @@ public interface FirstAidResourceMapper extends BaseMapper<FirstAidResource> {
|
|||||||
/**
|
/**
|
||||||
* 查询某分类下的资源数量(级联删除校验用)
|
* 查询某分类下的资源数量(级联删除校验用)
|
||||||
*/
|
*/
|
||||||
@Select("SELECT COUNT(*) FROM QH_EME_FIRST_AID_RESOURCE WHERE CATEGORY_ID = #{categoryId} AND DEL_FLAG = 0")
|
@Select("SELECT COUNT(*) FROM QH_EME_FIR_AID_RES WHERE CATEGORY_ID = #{categoryId} AND DEL_FLAG = 0")
|
||||||
Integer countByCategoryId(@Param("categoryId") String categoryId);
|
Integer countByCategoryId(@Param("categoryId") String categoryId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 浏览计数+1
|
* 浏览计数+1
|
||||||
*/
|
*/
|
||||||
@Update("UPDATE QH_EME_FIRST_AID_RESOURCE SET VIEW_COUNT = VIEW_COUNT + 1 WHERE ID = #{id}")
|
@Update("UPDATE QH_EME_FIR_AID_RES SET VIEW_COUNT = VIEW_COUNT + 1 WHERE ID = #{id}")
|
||||||
void incrementViewCount(@Param("id") String id);
|
void incrementViewCount(@Param("id") String id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 收藏计数+1
|
* 收藏计数+1
|
||||||
*/
|
*/
|
||||||
@Update("UPDATE QH_EME_FIRST_AID_RESOURCE SET FAVORITE_COUNT = FAVORITE_COUNT + 1 WHERE ID = #{id}")
|
@Update("UPDATE QH_EME_FIR_AID_RES SET FAVORITE_COUNT = FAVORITE_COUNT + 1 WHERE ID = #{id}")
|
||||||
void incrementFavoriteCount(@Param("id") String id);
|
void incrementFavoriteCount(@Param("id") String id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 收藏计数-1
|
* 收藏计数-1
|
||||||
*/
|
*/
|
||||||
@Update("UPDATE QH_EME_FIRST_AID_RESOURCE SET FAVORITE_COUNT = FAVORITE_COUNT - 1 WHERE ID = #{id} AND FAVORITE_COUNT > 0")
|
@Update("UPDATE QH_EME_FIR_AID_RES SET FAVORITE_COUNT = FAVORITE_COUNT - 1 WHERE ID = #{id} AND FAVORITE_COUNT > 0")
|
||||||
void decrementFavoriteCount(@Param("id") String id);
|
void decrementFavoriteCount(@Param("id") String id);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -24,7 +24,7 @@ public interface FirstAidResourceUserActionMapper extends BaseMapper<FirstAidRes
|
|||||||
* 查询用户对一批资源的收藏状态
|
* 查询用户对一批资源的收藏状态
|
||||||
*/
|
*/
|
||||||
@Select("<script>" +
|
@Select("<script>" +
|
||||||
"SELECT RESOURCE_ID FROM QH_EME_FIRST_AID_RESOURCE_USER_ACTION " +
|
"SELECT RESOURCE_ID FROM QH_EME_FIR_AID_RES_UACT " +
|
||||||
"WHERE USER_ID = #{userId} AND TYPE = 2 " +
|
"WHERE USER_ID = #{userId} AND TYPE = 2 " +
|
||||||
"AND RESOURCE_ID IN " +
|
"AND RESOURCE_ID IN " +
|
||||||
"<foreach collection='resourceIds' item='id' open='(' separator=',' close=')'>" +
|
"<foreach collection='resourceIds' item='id' open='(' separator=',' close=')'>" +
|
||||||
@@ -37,8 +37,8 @@ public interface FirstAidResourceUserActionMapper extends BaseMapper<FirstAidRes
|
|||||||
/**
|
/**
|
||||||
* 查询用户的收藏资源列表(分页)
|
* 查询用户的收藏资源列表(分页)
|
||||||
*/
|
*/
|
||||||
@Select("SELECT R.* FROM QH_EME_FIRST_AID_RESOURCE R " +
|
@Select("SELECT R.* FROM QH_EME_FIR_AID_RES R " +
|
||||||
"INNER JOIN QH_EME_FIRST_AID_RESOURCE_USER_ACTION A ON R.ID = A.RESOURCE_ID " +
|
"INNER JOIN QH_EME_FIR_AID_RES_UACT A ON R.ID = A.RESOURCE_ID " +
|
||||||
"WHERE A.USER_ID = #{userId} AND A.TYPE = 2 AND R.DEL_FLAG = 0 " +
|
"WHERE A.USER_ID = #{userId} AND A.TYPE = 2 AND R.DEL_FLAG = 0 " +
|
||||||
"ORDER BY A.CREATE_TIME DESC")
|
"ORDER BY A.CREATE_TIME DESC")
|
||||||
IPage<FirstAidResource> selectFavoritePage(Page<FirstAidResource> page, @Param("userId") String userId);
|
IPage<FirstAidResource> selectFavoritePage(Page<FirstAidResource> page, @Param("userId") String userId);
|
||||||
|
|||||||
+3
-3
@@ -20,18 +20,18 @@ public interface FirstAidResourceVersionMapper extends BaseMapper<FirstAidResour
|
|||||||
/**
|
/**
|
||||||
* 查询某资源的最高版本号
|
* 查询某资源的最高版本号
|
||||||
*/
|
*/
|
||||||
@Select("SELECT MAX(VERSION_NO) FROM QH_EME_FIRST_AID_RESOURCE_VERSION WHERE RESOURCE_ID = #{resourceId}")
|
@Select("SELECT MAX(VERSION_NO) FROM QH_EME_FIR_AID_RES_VER WHERE RESOURCE_ID = #{resourceId}")
|
||||||
Integer selectMaxVersionNo(@Param("resourceId") String resourceId);
|
Integer selectMaxVersionNo(@Param("resourceId") String resourceId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询某资源的所有版本历史(按版本号倒序)
|
* 查询某资源的所有版本历史(按版本号倒序)
|
||||||
*/
|
*/
|
||||||
@Select("SELECT * FROM QH_EME_FIRST_AID_RESOURCE_VERSION WHERE RESOURCE_ID = #{resourceId} ORDER BY VERSION_NO DESC")
|
@Select("SELECT * FROM QH_EME_FIR_AID_RES_VER WHERE RESOURCE_ID = #{resourceId} ORDER BY VERSION_NO DESC")
|
||||||
List<FirstAidResourceVersion> selectByResourceId(@Param("resourceId") String resourceId);
|
List<FirstAidResourceVersion> selectByResourceId(@Param("resourceId") String resourceId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询某资源的所有非当前版本ID(按版本号降序),用于清理旧版本
|
* 查询某资源的所有非当前版本ID(按版本号降序),用于清理旧版本
|
||||||
*/
|
*/
|
||||||
@Select("SELECT ID FROM QH_EME_FIRST_AID_RESOURCE_VERSION WHERE RESOURCE_ID = #{resourceId} AND IS_CURRENT = 0 ORDER BY VERSION_NO DESC")
|
@Select("SELECT ID FROM QH_EME_FIR_AID_RES_VER WHERE RESOURCE_ID = #{resourceId} AND IS_CURRENT = 0 ORDER BY VERSION_NO DESC")
|
||||||
List<String> selectNonCurrentVersionIds(@Param("resourceId") String resourceId);
|
List<String> selectNonCurrentVersionIds(@Param("resourceId") String resourceId);
|
||||||
}
|
}
|
||||||
|
|||||||
+26
@@ -14,8 +14,14 @@ import com.renkang.emergency.entity.EmergencyCenterAdmin;
|
|||||||
import com.renkang.emergency.manager.EmergencyCloudManager;
|
import com.renkang.emergency.manager.EmergencyCloudManager;
|
||||||
import com.renkang.emergency.mapper.EmergencyCenterAdminMapper;
|
import com.renkang.emergency.mapper.EmergencyCenterAdminMapper;
|
||||||
import com.renkang.emergency.service.IEmergencyCenterAdminService;
|
import com.renkang.emergency.service.IEmergencyCenterAdminService;
|
||||||
|
import com.renkang.im.api.IMHelloApi;
|
||||||
|
import com.renkang.im.entity.ConSessionRequestDO;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jeecg.bean.request.ListUser;
|
||||||
import org.jeecg.common.constant.CommonConstant;
|
import org.jeecg.common.constant.CommonConstant;
|
||||||
import org.jeecg.common.exception.ExceptionAssertsUtil;
|
import org.jeecg.common.exception.ExceptionAssertsUtil;
|
||||||
|
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||||
|
import org.jeecg.common.system.vo.LoginUserNew;
|
||||||
import org.jeecg.common.system.vo.SysUserModel;
|
import org.jeecg.common.system.vo.SysUserModel;
|
||||||
import org.jeecg.common.util.CheckPasswordUtil;
|
import org.jeecg.common.util.CheckPasswordUtil;
|
||||||
import org.jeecg.common.util.PasswordUtil;
|
import org.jeecg.common.util.PasswordUtil;
|
||||||
@@ -37,6 +43,7 @@ import java.util.List;
|
|||||||
* @Author YangYuanChen
|
* @Author YangYuanChen
|
||||||
* @Data 20242024/8/21下午2:06
|
* @Data 20242024/8/21下午2:06
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class EmergencyCenterAdminServiceImpl extends ServiceImpl<EmergencyCenterAdminMapper, EmergencyCenterAdmin> implements IEmergencyCenterAdminService {
|
public class EmergencyCenterAdminServiceImpl extends ServiceImpl<EmergencyCenterAdminMapper, EmergencyCenterAdmin> implements IEmergencyCenterAdminService {
|
||||||
|
|
||||||
@@ -44,6 +51,10 @@ public class EmergencyCenterAdminServiceImpl extends ServiceImpl<EmergencyCenter
|
|||||||
private EmergencyCloudManager cloudManager;
|
private EmergencyCloudManager cloudManager;
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisStreamUtil redisStreamUtil;
|
private RedisStreamUtil redisStreamUtil;
|
||||||
|
@Autowired
|
||||||
|
private IMHelloApi imHelloApi;
|
||||||
|
@Autowired
|
||||||
|
private ISysBaseAPI sysBaseAPI;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IPage<EmergencyCenterAdmin> customPage(String centerId, String type, String realName, Integer pageNo, Integer pageSize) {
|
public IPage<EmergencyCenterAdmin> customPage(String centerId, String type, String realName, Integer pageNo, Integer pageSize) {
|
||||||
@@ -101,6 +112,21 @@ public class EmergencyCenterAdminServiceImpl extends ServiceImpl<EmergencyCenter
|
|||||||
|
|
||||||
// 修改system
|
// 修改system
|
||||||
updateUserStream(byId.getUserId(), admin.getRealname());
|
updateUserStream(byId.getUserId(), admin.getRealname());
|
||||||
|
// 同步IM个人资料
|
||||||
|
syncImProfile(byId.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void syncImProfile(String userId) {
|
||||||
|
try {
|
||||||
|
List<LoginUserNew> users = sysBaseAPI.listUserByIds(new ListUser(Collections.singletonList(userId)));
|
||||||
|
if (CollUtil.isNotEmpty(users)) {
|
||||||
|
ConSessionRequestDO req = new ConSessionRequestDO();
|
||||||
|
req.setAccountList(Collections.singletonList(users.get(0)));
|
||||||
|
imHelloApi.accountReg(req);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("同步IM个人资料失败, userId: {}", userId, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+27
@@ -17,8 +17,14 @@ import com.renkang.emergency.manager.PermissionManager;
|
|||||||
import com.renkang.emergency.mapper.EmergencyProfessionUserMapper;
|
import com.renkang.emergency.mapper.EmergencyProfessionUserMapper;
|
||||||
import com.renkang.emergency.mapper.EmergencySchedulesNewItemMapper;
|
import com.renkang.emergency.mapper.EmergencySchedulesNewItemMapper;
|
||||||
import com.renkang.emergency.service.EmergencyProfessionUserService;
|
import com.renkang.emergency.service.EmergencyProfessionUserService;
|
||||||
|
import com.renkang.im.api.IMHelloApi;
|
||||||
|
import com.renkang.im.entity.ConSessionRequestDO;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jeecg.bean.request.ListUser;
|
||||||
import org.jeecg.common.constant.CommonConstant;
|
import org.jeecg.common.constant.CommonConstant;
|
||||||
import org.jeecg.common.exception.ExceptionAssertsUtil;
|
import org.jeecg.common.exception.ExceptionAssertsUtil;
|
||||||
|
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||||
|
import org.jeecg.common.system.vo.LoginUserNew;
|
||||||
import org.jeecg.common.system.vo.SysUserModel;
|
import org.jeecg.common.system.vo.SysUserModel;
|
||||||
import org.jeecg.common.util.PasswordUtil;
|
import org.jeecg.common.util.PasswordUtil;
|
||||||
import org.jeecg.redis.RedisStreamKeyEnum;
|
import org.jeecg.redis.RedisStreamKeyEnum;
|
||||||
@@ -27,6 +33,7 @@ import org.jeecg.util.RSAEncryptUtils;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -37,6 +44,7 @@ import java.util.stream.Collectors;
|
|||||||
* @author stan
|
* @author stan
|
||||||
* @since 2024-09-12 09:38:13
|
* @since 2024-09-12 09:38:13
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class EmergencyProfessionUserServiceImpl extends ServiceImpl<EmergencyProfessionUserMapper, EmergencyProfessionUser> implements EmergencyProfessionUserService {
|
public class EmergencyProfessionUserServiceImpl extends ServiceImpl<EmergencyProfessionUserMapper, EmergencyProfessionUser> implements EmergencyProfessionUserService {
|
||||||
|
|
||||||
@@ -48,6 +56,10 @@ public class EmergencyProfessionUserServiceImpl extends ServiceImpl<EmergencyPro
|
|||||||
private PermissionManager permissionManager;
|
private PermissionManager permissionManager;
|
||||||
@Autowired
|
@Autowired
|
||||||
private EmergencySchedulesNewItemMapper emergencySchedulesNewItemMapper;
|
private EmergencySchedulesNewItemMapper emergencySchedulesNewItemMapper;
|
||||||
|
@Autowired
|
||||||
|
private IMHelloApi imHelloApi;
|
||||||
|
@Autowired
|
||||||
|
private ISysBaseAPI sysBaseAPI;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IPage<EmergencyProfessionUser> customPage(String name, String centerId, int type, int pageNo, int pageSize) {
|
public IPage<EmergencyProfessionUser> customPage(String name, String centerId, int type, int pageNo, int pageSize) {
|
||||||
@@ -145,6 +157,21 @@ public class EmergencyProfessionUserServiceImpl extends ServiceImpl<EmergencyPro
|
|||||||
}
|
}
|
||||||
// 修改system
|
// 修改system
|
||||||
updateUserStream(oldData.getUserId(), data.getRealname(), data.getAvatar());
|
updateUserStream(oldData.getUserId(), data.getRealname(), data.getAvatar());
|
||||||
|
// 同步IM个人资料
|
||||||
|
syncImProfile(oldData.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void syncImProfile(String userId) {
|
||||||
|
try {
|
||||||
|
List<LoginUserNew> users = sysBaseAPI.listUserByIds(new ListUser(Collections.singletonList(userId)));
|
||||||
|
if (CollUtil.isNotEmpty(users)) {
|
||||||
|
ConSessionRequestDO req = new ConSessionRequestDO();
|
||||||
|
req.setAccountList(Collections.singletonList(users.get(0)));
|
||||||
|
imHelloApi.accountReg(req);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("同步IM个人资料失败, userId: {}", userId, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+43
-7
@@ -2,9 +2,11 @@ package com.renkang.emergency.service.impl;
|
|||||||
|
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.renkang.emergency.bean.response.SendIm;
|
||||||
import com.renkang.emergency.constant.FirstAidConstants;
|
import com.renkang.emergency.constant.FirstAidConstants;
|
||||||
import com.renkang.emergency.dto.PushBatchSendDTO;
|
import com.renkang.emergency.dto.PushBatchSendDTO;
|
||||||
import com.renkang.emergency.dto.PushFilterDTO;
|
import com.renkang.emergency.dto.PushFilterDTO;
|
||||||
@@ -17,11 +19,14 @@ import com.renkang.emergency.mapper.FirstAidResourceMapper;
|
|||||||
import com.renkang.emergency.mapper.FirstAidResourceCategoryMapper;
|
import com.renkang.emergency.mapper.FirstAidResourceCategoryMapper;
|
||||||
import com.renkang.emergency.mapper.OrderMapper;
|
import com.renkang.emergency.mapper.OrderMapper;
|
||||||
import com.renkang.emergency.service.IFirstAidPushService;
|
import com.renkang.emergency.service.IFirstAidPushService;
|
||||||
|
import com.renkang.im.api.IMHelloApi;
|
||||||
|
import com.renkang.im.entity.ImGroupMsgTextReqDO;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.jeecg.common.constant.CommonConstant;
|
import org.jeecg.common.constant.CommonConstant;
|
||||||
import org.jeecg.common.system.vo.LoginUser;
|
import org.jeecg.common.system.vo.LoginUser;
|
||||||
import org.jeecg.global.GlobalUtils;
|
import org.jeecg.global.GlobalUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
@@ -55,6 +60,15 @@ public class FirstAidPushServiceImpl implements IFirstAidPushService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private FirstAidPushServiceImpl self;
|
private FirstAidPushServiceImpl self;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IMHelloApi imHelloApi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件服务基础URL,用于拼接封面图全路径
|
||||||
|
*/
|
||||||
|
@Value("${jeecg.path.show:}")
|
||||||
|
private String fileBaseUrl;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IPage<FirstAidResource> queryResourceList(String orderId, PushFilterDTO filter, Page<FirstAidResource> page) {
|
public IPage<FirstAidResource> queryResourceList(String orderId, PushFilterDTO filter, Page<FirstAidResource> page) {
|
||||||
LambdaQueryWrapper<FirstAidResource> wrapper = buildFilterWrapper(filter);
|
LambdaQueryWrapper<FirstAidResource> wrapper = buildFilterWrapper(filter);
|
||||||
@@ -108,10 +122,11 @@ public class FirstAidPushServiceImpl implements IFirstAidPushService {
|
|||||||
throw new RuntimeException("该资源已推送,请勿重复操作");
|
throw new RuntimeException("该资源已推送,请勿重复操作");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 获取推送目标
|
// 3. 获取工单信息
|
||||||
String targetUserId = null;
|
String targetUserId = null;
|
||||||
|
Order order = null;
|
||||||
if (StrUtil.isNotBlank(orderId)) {
|
if (StrUtil.isNotBlank(orderId)) {
|
||||||
Order order = orderMapper.selectById(orderId);
|
order = orderMapper.selectById(orderId);
|
||||||
if (order != null) {
|
if (order != null) {
|
||||||
targetUserId = order.getSalvageUserId();
|
targetUserId = order.getSalvageUserId();
|
||||||
}
|
}
|
||||||
@@ -131,11 +146,32 @@ public class FirstAidPushServiceImpl implements IFirstAidPushService {
|
|||||||
record.setPushTime(new Date());
|
record.setPushTime(new Date());
|
||||||
pushRecordMapper.insert(record);
|
pushRecordMapper.insert(record);
|
||||||
|
|
||||||
// 5. 推送通知(预留,当前记录日志)
|
// 5. 构建推送IM消息并发送
|
||||||
log.info("急救宣教推送: resourceId={}, title={}, orderId={}, targetUserId={}, pushById={}, pushByName={}",
|
if (order != null && StrUtil.isNotBlank(order.getSessionId())) {
|
||||||
resourceId, resource.getTitle(), orderId, targetUserId,
|
SendIm sendIm = new SendIm();
|
||||||
loginUser != null ? loginUser.getId() : null,
|
sendIm.setType(1);
|
||||||
loginUser != null ? loginUser.getRealname() : null);
|
sendIm.setTitle(resource.getTitle());
|
||||||
|
sendIm.setContent(StrUtil.isNotBlank(resource.getSummary()) ? resource.getSummary() : resource.getTitle());
|
||||||
|
String coverImage = resource.getCoverImage();
|
||||||
|
if (StrUtil.isNotBlank(coverImage) && !coverImage.startsWith("http")) {
|
||||||
|
coverImage = StrUtil.removeSuffix(fileBaseUrl, "/") + "/" + StrUtil.removePrefix(coverImage, "/");
|
||||||
|
}
|
||||||
|
sendIm.setMessageImageUrl(coverImage);
|
||||||
|
sendIm.setResourceId(resourceId);
|
||||||
|
|
||||||
|
ImGroupMsgTextReqDO im = new ImGroupMsgTextReqDO();
|
||||||
|
im.setGroupId(order.getSessionId());
|
||||||
|
im.setFromUserId(loginUser != null ? loginUser.getId() : "administrator");
|
||||||
|
im.setContent(JSONObject.toJSON(sendIm).toString());
|
||||||
|
|
||||||
|
imHelloApi.sendGroupMsgArticle(im);
|
||||||
|
log.info("急救宣教推送IM消息已发送: resourceId={}, title={}, orderId={}, sessionId={}, pushBy={}, businessId=article",
|
||||||
|
resourceId, resource.getTitle(), orderId, order.getSessionId(),
|
||||||
|
loginUser != null ? loginUser.getRealname() : "unknown");
|
||||||
|
} else {
|
||||||
|
log.warn("急救宣教推送IM消息未发送(工单无群聊sessionId): resourceId={}, orderId={}",
|
||||||
|
resourceId, orderId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,520 +1,4 @@
|
|||||||
[
|
[
|
||||||
{
|
|
||||||
"id": 10641,
|
|
||||||
"empId": "f497b917da064874b022e036ddb7804b",
|
|
||||||
"treatPlanResponse": "",
|
|
||||||
"dietSuggestionResponse": "",
|
|
||||||
"sportGuideResponse": "",
|
|
||||||
"lifeManageResponse": "",
|
|
||||||
"createDate": "2025-08-01 12:43:33",
|
|
||||||
"updateDate": "2025-08-05 10:43:33",
|
|
||||||
"createBy": "13263",
|
|
||||||
"updateBy": "13263",
|
|
||||||
"delFlag": "0",
|
|
||||||
"dataLevel": "0",
|
|
||||||
"negativeList": "",
|
|
||||||
"flagFat": 2,
|
|
||||||
"bmi": 27.02,
|
|
||||||
"height": 176,
|
|
||||||
"weight": 81.8,
|
|
||||||
"bmiCurrent": 26.4,
|
|
||||||
"hypertension": 1,
|
|
||||||
"systolicPressureAvg": 106,
|
|
||||||
"systolicPressureTarget": 120,
|
|
||||||
"systolicPressureCurrent": 122,
|
|
||||||
"diastolicPressureAvg": 71,
|
|
||||||
"diastolicPressureTarget": 90,
|
|
||||||
"diastolicPressureCurrent": 87,
|
|
||||||
"diabetes": 1,
|
|
||||||
"glu": 5.79,
|
|
||||||
"bloodSugarTarget": "6.1",
|
|
||||||
"bloodSugarCurrent": 6.2,
|
|
||||||
"ldl": 0,
|
|
||||||
"ldlTarget": "3.4",
|
|
||||||
"ldlCurrent": 0,
|
|
||||||
"tc": 4.71,
|
|
||||||
"tcTarget": "5.2",
|
|
||||||
"tcCurrent": 4.53,
|
|
||||||
"tg": 0,
|
|
||||||
"tgTarget": "1.7",
|
|
||||||
"tgCurrent": 0,
|
|
||||||
"uricAcid": 0,
|
|
||||||
"uricAcidTarget": "420",
|
|
||||||
"uricAcidCurrent": 350,
|
|
||||||
"homocysteine": 15.04,
|
|
||||||
"homocysteineTarget": "13.54",
|
|
||||||
"homocysteineCurrent": 0,
|
|
||||||
"workUnit": "新疆油田储气库有限公司-机关",
|
|
||||||
"workUnitId": "103074",
|
|
||||||
"age": 36,
|
|
||||||
"sex": "男",
|
|
||||||
"name": "连龙刚",
|
|
||||||
"careLiaisonName": "刘一"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 10641,
|
|
||||||
"empId": "f497b917da064874b022e036ddb7804b",
|
|
||||||
"treatPlanResponse": "",
|
|
||||||
"dietSuggestionResponse": "",
|
|
||||||
"sportGuideResponse": "",
|
|
||||||
"lifeManageResponse": "",
|
|
||||||
"createDate": "2025-09-05 11:43:33",
|
|
||||||
"updateDate": "2025-09-05 11:43:33",
|
|
||||||
"createBy": "13263",
|
|
||||||
"updateBy": "13263",
|
|
||||||
"delFlag": "0",
|
|
||||||
"dataLevel": "0",
|
|
||||||
"negativeList": "",
|
|
||||||
"flagFat": 2,
|
|
||||||
"bmi": 27.02,
|
|
||||||
"height": 176,
|
|
||||||
"weight": 81.8,
|
|
||||||
"bmiCurrent": 26.4,
|
|
||||||
"hypertension": 1,
|
|
||||||
"systolicPressureAvg": 106,
|
|
||||||
"systolicPressureTarget": 120,
|
|
||||||
"systolicPressureCurrent": 122,
|
|
||||||
"diastolicPressureAvg": 71,
|
|
||||||
"diastolicPressureTarget": 90,
|
|
||||||
"diastolicPressureCurrent": 87,
|
|
||||||
"diabetes": 1,
|
|
||||||
"glu": 5.79,
|
|
||||||
"bloodSugarTarget": "6.1",
|
|
||||||
"bloodSugarCurrent": 6.2,
|
|
||||||
"ldl": 0,
|
|
||||||
"ldlTarget": "3.4",
|
|
||||||
"ldlCurrent": 0,
|
|
||||||
"tc": 4.71,
|
|
||||||
"tcTarget": "5.2",
|
|
||||||
"tcCurrent": 4.53,
|
|
||||||
"tg": 0,
|
|
||||||
"tgTarget": "1.7",
|
|
||||||
"tgCurrent": 0,
|
|
||||||
"uricAcid": 0,
|
|
||||||
"uricAcidTarget": "420",
|
|
||||||
"uricAcidCurrent": 350,
|
|
||||||
"homocysteine": 15.04,
|
|
||||||
"homocysteineTarget": "13.54",
|
|
||||||
"homocysteineCurrent": 0,
|
|
||||||
"workUnit": "新疆油田储气库有限公司-机关",
|
|
||||||
"workUnitId": "103074",
|
|
||||||
"age": 41,
|
|
||||||
"sex": "男",
|
|
||||||
"name": "李苏望",
|
|
||||||
"careLiaisonName": "陈二"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 10641,
|
|
||||||
"empId": "f497b917da064874b022e036ddb7804b",
|
|
||||||
"treatPlanResponse": "",
|
|
||||||
"dietSuggestionResponse": "",
|
|
||||||
"sportGuideResponse": "",
|
|
||||||
"lifeManageResponse": "",
|
|
||||||
"createDate": "2025-07-05 11:43:33",
|
|
||||||
"updateDate": "2025-07-05 11:43:33",
|
|
||||||
"createBy": "13263",
|
|
||||||
"updateBy": "13263",
|
|
||||||
"delFlag": "0",
|
|
||||||
"dataLevel": "0",
|
|
||||||
"negativeList": "",
|
|
||||||
"flagFat": 2,
|
|
||||||
"bmi": 27.02,
|
|
||||||
"height": 176,
|
|
||||||
"weight": 81.8,
|
|
||||||
"bmiCurrent": 26.4,
|
|
||||||
"hypertension": 1,
|
|
||||||
"systolicPressureAvg": 106,
|
|
||||||
"systolicPressureTarget": 120,
|
|
||||||
"systolicPressureCurrent": 122,
|
|
||||||
"diastolicPressureAvg": 71,
|
|
||||||
"diastolicPressureTarget": 90,
|
|
||||||
"diastolicPressureCurrent": 87,
|
|
||||||
"diabetes": 1,
|
|
||||||
"glu": 5.79,
|
|
||||||
"bloodSugarTarget": "6.1",
|
|
||||||
"bloodSugarCurrent": 6.2,
|
|
||||||
"ldl": 0,
|
|
||||||
"ldlTarget": "3.4",
|
|
||||||
"ldlCurrent": 0,
|
|
||||||
"tc": 4.71,
|
|
||||||
"tcTarget": "5.2",
|
|
||||||
"tcCurrent": 4.53,
|
|
||||||
"tg": 0,
|
|
||||||
"tgTarget": "1.7",
|
|
||||||
"tgCurrent": 0,
|
|
||||||
"uricAcid": 0,
|
|
||||||
"uricAcidTarget": "420",
|
|
||||||
"uricAcidCurrent": 350,
|
|
||||||
"homocysteine": 15.04,
|
|
||||||
"homocysteineTarget": "13.54",
|
|
||||||
"homocysteineCurrent": 0,
|
|
||||||
"workUnit": "新疆油田储气库有限公司-机关",
|
|
||||||
"workUnitId": "103074",
|
|
||||||
"age": 29,
|
|
||||||
"sex": "男",
|
|
||||||
"name": "王先森",
|
|
||||||
"careLiaisonName": "张三"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 10641,
|
|
||||||
"empId": "f497b917da064874b022e036ddb7804b",
|
|
||||||
"treatPlanResponse": "",
|
|
||||||
"dietSuggestionResponse": "",
|
|
||||||
"sportGuideResponse": "",
|
|
||||||
"lifeManageResponse": "",
|
|
||||||
"createDate": "2024-09-05 11:43:33",
|
|
||||||
"updateDate": "2024-09-05 11:43:33",
|
|
||||||
"createBy": "13263",
|
|
||||||
"updateBy": "13263",
|
|
||||||
"delFlag": "0",
|
|
||||||
"dataLevel": "0",
|
|
||||||
"negativeList": "",
|
|
||||||
"flagFat": 2,
|
|
||||||
"bmi": 27.02,
|
|
||||||
"height": 176,
|
|
||||||
"weight": 81.8,
|
|
||||||
"bmiCurrent": 26.4,
|
|
||||||
"hypertension": 1,
|
|
||||||
"systolicPressureAvg": 106,
|
|
||||||
"systolicPressureTarget": 120,
|
|
||||||
"systolicPressureCurrent": 122,
|
|
||||||
"diastolicPressureAvg": 71,
|
|
||||||
"diastolicPressureTarget": 90,
|
|
||||||
"diastolicPressureCurrent": 87,
|
|
||||||
"diabetes": 1,
|
|
||||||
"glu": 5.79,
|
|
||||||
"bloodSugarTarget": "6.1",
|
|
||||||
"bloodSugarCurrent": 6.2,
|
|
||||||
"ldl": 0,
|
|
||||||
"ldlTarget": "3.4",
|
|
||||||
"ldlCurrent": 0,
|
|
||||||
"tc": 4.71,
|
|
||||||
"tcTarget": "5.2",
|
|
||||||
"tcCurrent": 4.53,
|
|
||||||
"tg": 0,
|
|
||||||
"tgTarget": "1.7",
|
|
||||||
"tgCurrent": 0,
|
|
||||||
"uricAcid": 0,
|
|
||||||
"uricAcidTarget": "420",
|
|
||||||
"uricAcidCurrent": 350,
|
|
||||||
"homocysteine": 15.04,
|
|
||||||
"homocysteineTarget": "13.54",
|
|
||||||
"homocysteineCurrent": 0,
|
|
||||||
"workUnit": "新疆油田储气库有限公司-机关",
|
|
||||||
"workUnitId": "103074",
|
|
||||||
"age": 50,
|
|
||||||
"sex": "男",
|
|
||||||
"name": "阿尔麦江.买买提",
|
|
||||||
"careLiaisonName": "李四"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 10641,
|
|
||||||
"empId": "f497b917da064874b022e036ddb7804b",
|
|
||||||
"treatPlanResponse": "",
|
|
||||||
"dietSuggestionResponse": "",
|
|
||||||
"sportGuideResponse": "",
|
|
||||||
"lifeManageResponse": "",
|
|
||||||
"createDate": "2025-06-05 11:43:33",
|
|
||||||
"updateDate": "2025-06-05 11:43:33",
|
|
||||||
"createBy": "13263",
|
|
||||||
"updateBy": "13263",
|
|
||||||
"delFlag": "0",
|
|
||||||
"dataLevel": "0",
|
|
||||||
"negativeList": "",
|
|
||||||
"flagFat": 2,
|
|
||||||
"bmi": 27.02,
|
|
||||||
"height": 176,
|
|
||||||
"weight": 81.8,
|
|
||||||
"bmiCurrent": 26.4,
|
|
||||||
"hypertension": 1,
|
|
||||||
"systolicPressureAvg": 106,
|
|
||||||
"systolicPressureTarget": 120,
|
|
||||||
"systolicPressureCurrent": 122,
|
|
||||||
"diastolicPressureAvg": 71,
|
|
||||||
"diastolicPressureTarget": 90,
|
|
||||||
"diastolicPressureCurrent": 87,
|
|
||||||
"diabetes": 1,
|
|
||||||
"glu": 5.79,
|
|
||||||
"bloodSugarTarget": "6.1",
|
|
||||||
"bloodSugarCurrent": 6.2,
|
|
||||||
"ldl": 0,
|
|
||||||
"ldlTarget": "3.4",
|
|
||||||
"ldlCurrent": 0,
|
|
||||||
"tc": 4.71,
|
|
||||||
"tcTarget": "5.2",
|
|
||||||
"tcCurrent": 4.53,
|
|
||||||
"tg": 0,
|
|
||||||
"tgTarget": "1.7",
|
|
||||||
"tgCurrent": 0,
|
|
||||||
"uricAcid": 0,
|
|
||||||
"uricAcidTarget": "420",
|
|
||||||
"uricAcidCurrent": 350,
|
|
||||||
"homocysteine": 15.04,
|
|
||||||
"homocysteineTarget": "13.54",
|
|
||||||
"homocysteineCurrent": 0,
|
|
||||||
"workUnit": "新疆油田储气库有限公司-机关",
|
|
||||||
"workUnitId": "103074",
|
|
||||||
"age": 24,
|
|
||||||
"sex": "女",
|
|
||||||
"name": "古力娜扎.艾卡尔",
|
|
||||||
"careLiaisonName": "王五"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 10641,
|
|
||||||
"empId": "f497b917da064874b022e036ddb7804b",
|
|
||||||
"treatPlanResponse": "",
|
|
||||||
"dietSuggestionResponse": "",
|
|
||||||
"sportGuideResponse": "",
|
|
||||||
"lifeManageResponse": "",
|
|
||||||
"createDate": "2024-09-15 11:43:33",
|
|
||||||
"updateDate": "2024-09-15 11:43:33",
|
|
||||||
"createBy": "13263",
|
|
||||||
"updateBy": "13263",
|
|
||||||
"delFlag": "0",
|
|
||||||
"dataLevel": "0",
|
|
||||||
"negativeList": "",
|
|
||||||
"flagFat": 2,
|
|
||||||
"bmi": 27.02,
|
|
||||||
"height": 176,
|
|
||||||
"weight": 81.8,
|
|
||||||
"bmiCurrent": 26.4,
|
|
||||||
"hypertension": 1,
|
|
||||||
"systolicPressureAvg": 106,
|
|
||||||
"systolicPressureTarget": 120,
|
|
||||||
"systolicPressureCurrent": 122,
|
|
||||||
"diastolicPressureAvg": 71,
|
|
||||||
"diastolicPressureTarget": 90,
|
|
||||||
"diastolicPressureCurrent": 87,
|
|
||||||
"diabetes": 1,
|
|
||||||
"glu": 5.79,
|
|
||||||
"bloodSugarTarget": "6.1",
|
|
||||||
"bloodSugarCurrent": 6.2,
|
|
||||||
"ldl": 0,
|
|
||||||
"ldlTarget": "3.4",
|
|
||||||
"ldlCurrent": 0,
|
|
||||||
"tc": 4.71,
|
|
||||||
"tcTarget": "5.2",
|
|
||||||
"tcCurrent": 4.53,
|
|
||||||
"tg": 0,
|
|
||||||
"tgTarget": "1.7",
|
|
||||||
"tgCurrent": 0,
|
|
||||||
"uricAcid": 0,
|
|
||||||
"uricAcidTarget": "420",
|
|
||||||
"uricAcidCurrent": 350,
|
|
||||||
"homocysteine": 15.04,
|
|
||||||
"homocysteineTarget": "13.54",
|
|
||||||
"homocysteineCurrent": 0,
|
|
||||||
"workUnit": "新疆油田储气库有限公司-机关",
|
|
||||||
"workUnitId": "103074",
|
|
||||||
"age": 37,
|
|
||||||
"sex": "男",
|
|
||||||
"name": "梁文斌",
|
|
||||||
"careLiaisonName": "赵六"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 10641,
|
|
||||||
"empId": "f497b917da064874b022e036ddb7804b",
|
|
||||||
"treatPlanResponse": "",
|
|
||||||
"dietSuggestionResponse": "",
|
|
||||||
"sportGuideResponse": "",
|
|
||||||
"lifeManageResponse": "",
|
|
||||||
"createDate": "2025-01-05 11:43:33",
|
|
||||||
"updateDate": "2025-01-05 11:43:33",
|
|
||||||
"createBy": "13263",
|
|
||||||
"updateBy": "13263",
|
|
||||||
"delFlag": "0",
|
|
||||||
"dataLevel": "0",
|
|
||||||
"negativeList": "",
|
|
||||||
"flagFat": 2,
|
|
||||||
"bmi": 27.02,
|
|
||||||
"height": 176,
|
|
||||||
"weight": 81.8,
|
|
||||||
"bmiCurrent": 26.4,
|
|
||||||
"hypertension": 1,
|
|
||||||
"systolicPressureAvg": 106,
|
|
||||||
"systolicPressureTarget": 120,
|
|
||||||
"systolicPressureCurrent": 122,
|
|
||||||
"diastolicPressureAvg": 71,
|
|
||||||
"diastolicPressureTarget": 90,
|
|
||||||
"diastolicPressureCurrent": 87,
|
|
||||||
"diabetes": 1,
|
|
||||||
"glu": 5.79,
|
|
||||||
"bloodSugarTarget": "6.1",
|
|
||||||
"bloodSugarCurrent": 6.2,
|
|
||||||
"ldl": 0,
|
|
||||||
"ldlTarget": "3.4",
|
|
||||||
"ldlCurrent": 0,
|
|
||||||
"tc": 4.71,
|
|
||||||
"tcTarget": "5.2",
|
|
||||||
"tcCurrent": 4.53,
|
|
||||||
"tg": 0,
|
|
||||||
"tgTarget": "1.7",
|
|
||||||
"tgCurrent": 0,
|
|
||||||
"uricAcid": 0,
|
|
||||||
"uricAcidTarget": "420",
|
|
||||||
"uricAcidCurrent": 350,
|
|
||||||
"homocysteine": 15.04,
|
|
||||||
"homocysteineTarget": "13.54",
|
|
||||||
"homocysteineCurrent": 0,
|
|
||||||
"workUnit": "新疆油田储气库有限公司-机关",
|
|
||||||
"workUnitId": "103074",
|
|
||||||
"age": 46,
|
|
||||||
"sex": "男",
|
|
||||||
"name": "加海洋",
|
|
||||||
"careLiaisonName": "孙七"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 10641,
|
|
||||||
"empId": "f497b917da064874b022e036ddb7804b",
|
|
||||||
"treatPlanResponse": "",
|
|
||||||
"dietSuggestionResponse": "",
|
|
||||||
"sportGuideResponse": "",
|
|
||||||
"lifeManageResponse": "",
|
|
||||||
"createDate": "2025-09-02 11:43:33",
|
|
||||||
"updateDate": "2025-09-02 11:43:33",
|
|
||||||
"createBy": "13263",
|
|
||||||
"updateBy": "13263",
|
|
||||||
"delFlag": "0",
|
|
||||||
"dataLevel": "0",
|
|
||||||
"negativeList": "",
|
|
||||||
"flagFat": 2,
|
|
||||||
"bmi": 27.02,
|
|
||||||
"height": 176,
|
|
||||||
"weight": 81.8,
|
|
||||||
"bmiCurrent": 26.4,
|
|
||||||
"hypertension": 1,
|
|
||||||
"systolicPressureAvg": 106,
|
|
||||||
"systolicPressureTarget": 120,
|
|
||||||
"systolicPressureCurrent": 122,
|
|
||||||
"diastolicPressureAvg": 71,
|
|
||||||
"diastolicPressureTarget": 90,
|
|
||||||
"diastolicPressureCurrent": 87,
|
|
||||||
"diabetes": 1,
|
|
||||||
"glu": 5.79,
|
|
||||||
"bloodSugarTarget": "6.1",
|
|
||||||
"bloodSugarCurrent": 6.2,
|
|
||||||
"ldl": 0,
|
|
||||||
"ldlTarget": "3.4",
|
|
||||||
"ldlCurrent": 0,
|
|
||||||
"tc": 4.71,
|
|
||||||
"tcTarget": "5.2",
|
|
||||||
"tcCurrent": 4.53,
|
|
||||||
"tg": 0,
|
|
||||||
"tgTarget": "1.7",
|
|
||||||
"tgCurrent": 0,
|
|
||||||
"uricAcid": 0,
|
|
||||||
"uricAcidTarget": "420",
|
|
||||||
"uricAcidCurrent": 350,
|
|
||||||
"homocysteine": 15.04,
|
|
||||||
"homocysteineTarget": "13.54",
|
|
||||||
"homocysteineCurrent": 0,
|
|
||||||
"workUnit": "新疆油田储气库有限公司-机关",
|
|
||||||
"workUnitId": "103074",
|
|
||||||
"age": 41,
|
|
||||||
"sex": "女",
|
|
||||||
"name": "周八"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 10641,
|
|
||||||
"empId": "f497b917da064874b022e036ddb7804b",
|
|
||||||
"treatPlanResponse": "",
|
|
||||||
"dietSuggestionResponse": "",
|
|
||||||
"sportGuideResponse": "",
|
|
||||||
"lifeManageResponse": "",
|
|
||||||
"createDate": "2025-09-07 11:43:33",
|
|
||||||
"updateDate": "2025-09-07 11:43:33",
|
|
||||||
"createBy": "13263",
|
|
||||||
"updateBy": "13263",
|
|
||||||
"delFlag": "0",
|
|
||||||
"dataLevel": "0",
|
|
||||||
"negativeList": "",
|
|
||||||
"flagFat": 2,
|
|
||||||
"bmi": 27.02,
|
|
||||||
"height": 176,
|
|
||||||
"weight": 81.8,
|
|
||||||
"bmiCurrent": 26.4,
|
|
||||||
"hypertension": 1,
|
|
||||||
"systolicPressureAvg": 106,
|
|
||||||
"systolicPressureTarget": 120,
|
|
||||||
"systolicPressureCurrent": 122,
|
|
||||||
"diastolicPressureAvg": 71,
|
|
||||||
"diastolicPressureTarget": 90,
|
|
||||||
"diastolicPressureCurrent": 87,
|
|
||||||
"diabetes": 1,
|
|
||||||
"glu": 5.79,
|
|
||||||
"bloodSugarTarget": "6.1",
|
|
||||||
"bloodSugarCurrent": 6.2,
|
|
||||||
"ldl": 0,
|
|
||||||
"ldlTarget": "3.4",
|
|
||||||
"ldlCurrent": 0,
|
|
||||||
"tc": 4.71,
|
|
||||||
"tcTarget": "5.2",
|
|
||||||
"tcCurrent": 4.53,
|
|
||||||
"tg": 0,
|
|
||||||
"tgTarget": "1.7",
|
|
||||||
"tgCurrent": 0,
|
|
||||||
"uricAcid": 0,
|
|
||||||
"uricAcidTarget": "420",
|
|
||||||
"uricAcidCurrent": 350,
|
|
||||||
"homocysteine": 15.04,
|
|
||||||
"homocysteineTarget": "13.54",
|
|
||||||
"homocysteineCurrent": 0,
|
|
||||||
"workUnit": "新疆油田储气库有限公司-机关",
|
|
||||||
"workUnitId": "103074",
|
|
||||||
"age": 28,
|
|
||||||
"sex": "女",
|
|
||||||
"name": "吴九"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 10641,
|
|
||||||
"empId": "f497b917da064874b022e036ddb7804b",
|
|
||||||
"treatPlanResponse": "",
|
|
||||||
"dietSuggestionResponse": "",
|
|
||||||
"sportGuideResponse": "",
|
|
||||||
"lifeManageResponse": "",
|
|
||||||
"createDate": "2025-09-06 11:43:33",
|
|
||||||
"updateDate": "2025-09-06 11:43:33",
|
|
||||||
"createBy": "13263",
|
|
||||||
"updateBy": "13263",
|
|
||||||
"delFlag": "0",
|
|
||||||
"dataLevel": "0",
|
|
||||||
"negativeList": "",
|
|
||||||
"flagFat": 2,
|
|
||||||
"bmi": 27.02,
|
|
||||||
"height": 176,
|
|
||||||
"weight": 81.8,
|
|
||||||
"bmiCurrent": 26.4,
|
|
||||||
"hypertension": 1,
|
|
||||||
"systolicPressureAvg": 106,
|
|
||||||
"systolicPressureTarget": 120,
|
|
||||||
"systolicPressureCurrent": 122,
|
|
||||||
"diastolicPressureAvg": 71,
|
|
||||||
"diastolicPressureTarget": 90,
|
|
||||||
"diastolicPressureCurrent": 87,
|
|
||||||
"diabetes": 1,
|
|
||||||
"glu": 5.79,
|
|
||||||
"bloodSugarTarget": "6.1",
|
|
||||||
"bloodSugarCurrent": 6.2,
|
|
||||||
"ldl": 0,
|
|
||||||
"ldlTarget": "3.4",
|
|
||||||
"ldlCurrent": 0,
|
|
||||||
"tc": 4.71,
|
|
||||||
"tcTarget": "5.2",
|
|
||||||
"tcCurrent": 4.53,
|
|
||||||
"tg": 0,
|
|
||||||
"tgTarget": "1.7",
|
|
||||||
"tgCurrent": 0,
|
|
||||||
"uricAcid": 0,
|
|
||||||
"uricAcidTarget": "420",
|
|
||||||
"uricAcidCurrent": 350,
|
|
||||||
"homocysteine": 15.04,
|
|
||||||
"homocysteineTarget": "13.54",
|
|
||||||
"homocysteineCurrent": 0,
|
|
||||||
"workUnit": "新疆油田储气库有限公司-机关",
|
|
||||||
"workUnitId": "103074",
|
|
||||||
"age": 36,
|
|
||||||
"sex": "男",
|
|
||||||
"name": "郑十"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
+67
-67
@@ -7,7 +7,7 @@
|
|||||||
-- TYPE: 1=分类, 2=标签
|
-- TYPE: 1=分类, 2=标签
|
||||||
-- 分类支持多级树形(PARENT_ID 指向父分类,NULL=根分类)
|
-- 分类支持多级树形(PARENT_ID 指向父分类,NULL=根分类)
|
||||||
-- 标签为全局独立,不归属分类
|
-- 标签为全局独立,不归属分类
|
||||||
CREATE TABLE "QH_EME_FIRST_AID_RESOURCE_CATEGORY" (
|
CREATE TABLE "QH_EME_FIR_AID_RES_CATE" (
|
||||||
"ID" VARCHAR2(32) NOT NULL,
|
"ID" VARCHAR2(32) NOT NULL,
|
||||||
"NAME" VARCHAR2(100) NOT NULL,
|
"NAME" VARCHAR2(100) NOT NULL,
|
||||||
"TYPE" NUMBER(1) DEFAULT 1 NOT NULL,
|
"TYPE" NUMBER(1) DEFAULT 1 NOT NULL,
|
||||||
@@ -24,26 +24,26 @@ CREATE TABLE "QH_EME_FIRST_AID_RESOURCE_CATEGORY" (
|
|||||||
PRIMARY KEY ("ID")
|
PRIMARY KEY ("ID")
|
||||||
);
|
);
|
||||||
|
|
||||||
COMMENT ON TABLE "QH_EME_FIRST_AID_RESOURCE_CATEGORY" IS '急救宣教资源分类/标签';
|
COMMENT ON TABLE "QH_EME_FIR_AID_RES_CATE" IS '急救宣教资源分类/标签';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."ID" IS '主键';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."ID" IS '主键';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."NAME" IS '名称';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."NAME" IS '名称';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."TYPE" IS '类型:1=分类,2=标签';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."TYPE" IS '类型:1=分类,2=标签';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."PARENT_ID" IS '父分类ID(分类树形结构,标签为NULL)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."PARENT_ID" IS '父分类ID(分类树形结构,标签为NULL)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."DESCRIPTION" IS '描述';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."DESCRIPTION" IS '描述';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."SORT_NO" IS '排序号';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."SORT_NO" IS '排序号';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."STATUS" IS '状态(1=正常,2=冻结)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."STATUS" IS '状态(1=正常,2=冻结)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."CREATE_BY" IS '创建人';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."CREATE_BY" IS '创建人';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."CREATE_TIME" IS '创建时间';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."CREATE_TIME" IS '创建时间';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."UPDATE_BY" IS '更新人';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."UPDATE_BY" IS '更新人';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."UPDATE_TIME" IS '更新时间';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."UPDATE_TIME" IS '更新时间';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."DEL_FLAG" IS '删除标记(0=正常,1=已删除)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."DEL_FLAG" IS '删除标记(0=正常,1=已删除)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_CATEGORY"."MEMO" IS '备注';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_CATE"."MEMO" IS '备注';
|
||||||
|
|
||||||
CREATE INDEX "IDX_FA_CATEGORY_TYPE" ON "QH_EME_FIRST_AID_RESOURCE_CATEGORY"("TYPE");
|
CREATE INDEX "IDX_FA_CATEGORY_TYPE" ON "QH_EME_FIR_AID_RES_CATE"("TYPE");
|
||||||
CREATE INDEX "IDX_FA_CATEGORY_PARENT_ID" ON "QH_EME_FIRST_AID_RESOURCE_CATEGORY"("PARENT_ID");
|
CREATE INDEX "IDX_FA_CATEGORY_PARENT_ID" ON "QH_EME_FIR_AID_RES_CATE"("PARENT_ID");
|
||||||
|
|
||||||
-- 2. 急救宣教资源表
|
-- 2. 急救宣教资源表
|
||||||
CREATE TABLE "QH_EME_FIRST_AID_RESOURCE" (
|
CREATE TABLE "QH_EME_FIR_AID_RES" (
|
||||||
"ID" VARCHAR2(32) NOT NULL,
|
"ID" VARCHAR2(32) NOT NULL,
|
||||||
"TITLE" VARCHAR2(200) NOT NULL,
|
"TITLE" VARCHAR2(200) NOT NULL,
|
||||||
"SUMMARY" VARCHAR2(500),
|
"SUMMARY" VARCHAR2(500),
|
||||||
@@ -72,40 +72,40 @@ CREATE TABLE "QH_EME_FIRST_AID_RESOURCE" (
|
|||||||
PRIMARY KEY ("ID")
|
PRIMARY KEY ("ID")
|
||||||
);
|
);
|
||||||
|
|
||||||
COMMENT ON TABLE "QH_EME_FIRST_AID_RESOURCE" IS '急救宣教资源';
|
COMMENT ON TABLE "QH_EME_FIR_AID_RES" IS '急救宣教资源';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."ID" IS '主键';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."ID" IS '主键';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."TITLE" IS '标题';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."TITLE" IS '标题';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."SUMMARY" IS '摘要/简介(列表展示用)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."SUMMARY" IS '摘要/简介(列表展示用)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."CONTENT_TYPE" IS '内容类型:IMAGE_TEXT(图文)/VIDEO(视频)/AUDIO(音频)/PDF(PDF)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."CONTENT_TYPE" IS '内容类型:IMAGE_TEXT(图文)/VIDEO(视频)/AUDIO(音频)/PDF(PDF)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."CATEGORY_ID" IS '所属分类ID';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."CATEGORY_ID" IS '所属分类ID';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."APPLICABLE_SCENARIO" IS '适用场景';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."APPLICABLE_SCENARIO" IS '适用场景';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."TAGS" IS '标签ID列表(逗号分隔)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."TAGS" IS '标签ID列表(逗号分隔)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."CONTENT" IS '正文内容(富文本HTML)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."CONTENT" IS '正文内容(富文本HTML)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."COVER_IMAGE" IS '封面图URL';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."COVER_IMAGE" IS '封面图URL';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."FILE_URL" IS '附件URL列表(JSON数组)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."FILE_URL" IS '附件URL列表(JSON数组)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."EFFECTIVE_TIME" IS '生效时间';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."EFFECTIVE_TIME" IS '生效时间';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."EXPIRY_TIME" IS '失效时间';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."EXPIRY_TIME" IS '失效时间';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."AUDIT_STATUS" IS '审核状态(NULL=无审核/10=待审核/11=已通过/12=已驳回)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."AUDIT_STATUS" IS '审核状态(NULL=无审核/10=待审核/11=已通过/12=已驳回)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."AUDIT_REJECT_REASON" IS '驳回原因';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."AUDIT_REJECT_REASON" IS '驳回原因';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."AUDIT_BY" IS '审核人';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."AUDIT_BY" IS '审核人';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."AUDIT_TIME" IS '审核时间';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."AUDIT_TIME" IS '审核时间';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."VIEW_COUNT" IS '浏览次数';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."VIEW_COUNT" IS '浏览次数';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."FAVORITE_COUNT" IS '收藏次数';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."FAVORITE_COUNT" IS '收藏次数';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."STATUS" IS '发布状态(0=草稿,1=已发布,2=已下架)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."STATUS" IS '发布状态(0=草稿,1=已发布,2=已下架)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."CREATE_BY" IS '创建人';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."CREATE_BY" IS '创建人';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."CREATE_TIME" IS '创建时间';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."CREATE_TIME" IS '创建时间';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."UPDATE_BY" IS '更新人';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."UPDATE_BY" IS '更新人';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."UPDATE_TIME" IS '更新时间';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."UPDATE_TIME" IS '更新时间';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."DEL_FLAG" IS '删除标记(0=正常,1=已删除)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."DEL_FLAG" IS '删除标记(0=正常,1=已删除)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."MEMO" IS '备注';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."MEMO" IS '备注';
|
||||||
|
|
||||||
CREATE INDEX "IDX_FA_RESOURCE_CATEGORY_ID" ON "QH_EME_FIRST_AID_RESOURCE"("CATEGORY_ID");
|
CREATE INDEX "IDX_FA_RESOURCE_CATEGORY_ID" ON "QH_EME_FIR_AID_RES"("CATEGORY_ID");
|
||||||
CREATE INDEX "IDX_FA_RESOURCE_AUDIT_STATUS" ON "QH_EME_FIRST_AID_RESOURCE"("AUDIT_STATUS");
|
CREATE INDEX "IDX_FA_RESOURCE_AUDIT_STATUS" ON "QH_EME_FIR_AID_RES"("AUDIT_STATUS");
|
||||||
CREATE INDEX "IDX_FA_RESOURCE_EFFECTIVE_TIME" ON "QH_EME_FIRST_AID_RESOURCE"("EFFECTIVE_TIME");
|
CREATE INDEX "IDX_FA_RESOURCE_EFFECTIVE_TIME" ON "QH_EME_FIR_AID_RES"("EFFECTIVE_TIME");
|
||||||
|
|
||||||
-- 3. 用户行为记录表(阅读+收藏合一)
|
-- 3. 用户行为记录表(阅读+收藏合一)
|
||||||
-- TYPE: 1=阅读, 2=收藏
|
-- TYPE: 1=阅读, 2=收藏
|
||||||
CREATE TABLE "QH_EME_FIRST_AID_RESOURCE_USER_ACTION" (
|
CREATE TABLE "QH_EME_FIR_AID_RES_UACT" (
|
||||||
"ID" VARCHAR2(32) NOT NULL,
|
"ID" VARCHAR2(32) NOT NULL,
|
||||||
"RESOURCE_ID" VARCHAR2(32) NOT NULL,
|
"RESOURCE_ID" VARCHAR2(32) NOT NULL,
|
||||||
"USER_ID" VARCHAR2(50) NOT NULL,
|
"USER_ID" VARCHAR2(50) NOT NULL,
|
||||||
@@ -114,20 +114,20 @@ CREATE TABLE "QH_EME_FIRST_AID_RESOURCE_USER_ACTION" (
|
|||||||
PRIMARY KEY ("ID")
|
PRIMARY KEY ("ID")
|
||||||
);
|
);
|
||||||
|
|
||||||
COMMENT ON TABLE "QH_EME_FIRST_AID_RESOURCE_USER_ACTION" IS '用户行为记录(阅读/收藏)';
|
COMMENT ON TABLE "QH_EME_FIR_AID_RES_UACT" IS '用户行为记录(阅读/收藏)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_USER_ACTION"."ID" IS '主键';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_UACT"."ID" IS '主键';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_USER_ACTION"."RESOURCE_ID" IS '资源ID';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_UACT"."RESOURCE_ID" IS '资源ID';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_USER_ACTION"."USER_ID" IS '用户ID';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_UACT"."USER_ID" IS '用户ID';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_USER_ACTION"."TYPE" IS '行为类型:1=阅读,2=收藏';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_UACT"."TYPE" IS '行为类型:1=阅读,2=收藏';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_USER_ACTION"."CREATE_TIME" IS '创建时间';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_UACT"."CREATE_TIME" IS '创建时间';
|
||||||
|
|
||||||
CREATE UNIQUE INDEX "UK_FA_USER_ACTION"
|
CREATE UNIQUE INDEX "UK_FA_USER_ACTION"
|
||||||
ON "QH_EME_FIRST_AID_RESOURCE_USER_ACTION"("RESOURCE_ID", "USER_ID", "TYPE");
|
ON "QH_EME_FIR_AID_RES_UACT"("RESOURCE_ID", "USER_ID", "TYPE");
|
||||||
CREATE INDEX "IDX_FA_USER_ACTION_USER_TYPE" ON "QH_EME_FIRST_AID_RESOURCE_USER_ACTION"("USER_ID", "TYPE");
|
CREATE INDEX "IDX_FA_USER_ACTION_USER_TYPE" ON "QH_EME_FIR_AID_RES_UACT"("USER_ID", "TYPE");
|
||||||
|
|
||||||
-- 4. 版本历史表
|
-- 4. 版本历史表
|
||||||
-- 每次编辑资源时自动保存版本快照,支持回滚
|
-- 每次编辑资源时自动保存版本快照,支持回滚
|
||||||
CREATE TABLE "QH_EME_FIRST_AID_RESOURCE_VERSION" (
|
CREATE TABLE "QH_EME_FIR_AID_RES_VER" (
|
||||||
"ID" VARCHAR2(32) NOT NULL,
|
"ID" VARCHAR2(32) NOT NULL,
|
||||||
"RESOURCE_ID" VARCHAR2(32) NOT NULL,
|
"RESOURCE_ID" VARCHAR2(32) NOT NULL,
|
||||||
"VERSION_NO" NUMBER(10) NOT NULL,
|
"VERSION_NO" NUMBER(10) NOT NULL,
|
||||||
@@ -139,17 +139,17 @@ CREATE TABLE "QH_EME_FIRST_AID_RESOURCE_VERSION" (
|
|||||||
PRIMARY KEY ("ID")
|
PRIMARY KEY ("ID")
|
||||||
);
|
);
|
||||||
|
|
||||||
COMMENT ON TABLE "QH_EME_FIRST_AID_RESOURCE_VERSION" IS '资源版本历史';
|
COMMENT ON TABLE "QH_EME_FIR_AID_RES_VER" IS '资源版本历史';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_VERSION"."ID" IS '主键';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_VER"."ID" IS '主键';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_VERSION"."RESOURCE_ID" IS '资源ID';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_VER"."RESOURCE_ID" IS '资源ID';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_VERSION"."VERSION_NO" IS '版本号(1,2,3...)';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_VER"."VERSION_NO" IS '版本号(1,2,3...)';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_VERSION"."TITLE" IS '版本时的标题';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_VER"."TITLE" IS '版本时的标题';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_VERSION"."CONTENT" IS '版本时的正文内容';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_VER"."CONTENT" IS '版本时的正文内容';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_VERSION"."CHANGE_DESCRIPTION" IS '变更描述';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_VER"."CHANGE_DESCRIPTION" IS '变更描述';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_VERSION"."CREATE_BY" IS '创建人';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_VER"."CREATE_BY" IS '创建人';
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE_VERSION"."CREATE_TIME" IS '创建时间';
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES_VER"."CREATE_TIME" IS '创建时间';
|
||||||
|
|
||||||
CREATE INDEX "IDX_FA_VERSION_RESOURCE_ID" ON "QH_EME_FIRST_AID_RESOURCE_VERSION"("RESOURCE_ID");
|
CREATE INDEX "IDX_FA_VERSION_RESOURCE_ID" ON "QH_EME_FIR_AID_RES_VER"("RESOURCE_ID");
|
||||||
|
|
||||||
-- =====================================================
|
-- =====================================================
|
||||||
-- 字典数据(需在应用启动后执行)
|
-- 字典数据(需在应用启动后执行)
|
||||||
|
|||||||
+3
-3
@@ -16,7 +16,7 @@
|
|||||||
-- 需用户在系统内重新提交审核。
|
-- 需用户在系统内重新提交审核。
|
||||||
-- 如需保留为"待审核"状态,将下方的 NULL 改为 10 即可。
|
-- 如需保留为"待审核"状态,将下方的 NULL 改为 10 即可。
|
||||||
|
|
||||||
UPDATE "QH_EME_FIRST_AID_RESOURCE"
|
UPDATE "QH_EME_FIR_AID_RES"
|
||||||
SET "AUDIT_STATUS" = CASE
|
SET "AUDIT_STATUS" = CASE
|
||||||
WHEN "AUDIT_STATUS" = 0 THEN NULL -- 草稿(无法区分是否已提交,保守处理)
|
WHEN "AUDIT_STATUS" = 0 THEN NULL -- 草稿(无法区分是否已提交,保守处理)
|
||||||
WHEN "AUDIT_STATUS" = 1 THEN 11 -- 已通过
|
WHEN "AUDIT_STATUS" = 1 THEN 11 -- 已通过
|
||||||
@@ -62,7 +62,7 @@ SELECT
|
|||||||
ELSE '未知状态'
|
ELSE '未知状态'
|
||||||
END AS "审核状态描述",
|
END AS "审核状态描述",
|
||||||
COUNT(*) AS "数量"
|
COUNT(*) AS "数量"
|
||||||
FROM "QH_EME_FIRST_AID_RESOURCE"
|
FROM "QH_EME_FIR_AID_RES"
|
||||||
WHERE "DEL_FLAG" = 0
|
WHERE "DEL_FLAG" = 0
|
||||||
GROUP BY "AUDIT_STATUS"
|
GROUP BY "AUDIT_STATUS"
|
||||||
ORDER BY "AUDIT_STATUS" ASC NULLS FIRST;
|
ORDER BY "AUDIT_STATUS" ASC NULLS FIRST;
|
||||||
@@ -71,7 +71,7 @@ ORDER BY "AUDIT_STATUS" ASC NULLS FIRST;
|
|||||||
-- =====================================================
|
-- =====================================================
|
||||||
-- 4. 更新表字段注释
|
-- 4. 更新表字段注释
|
||||||
-- =====================================================
|
-- =====================================================
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."AUDIT_STATUS" IS
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."AUDIT_STATUS" IS
|
||||||
'审核状态(NULL=无审核/10=待审核/11=已通过/12=已驳回)';
|
'审核状态(NULL=无审核/10=待审核/11=已通过/12=已驳回)';
|
||||||
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|||||||
+2
-2
@@ -5,7 +5,7 @@
|
|||||||
-- =====================================================
|
-- =====================================================
|
||||||
|
|
||||||
-- 注意: null(草稿) 回退为 0,但此时无法区分"草稿"和"待审核"
|
-- 注意: null(草稿) 回退为 0,但此时无法区分"草稿"和"待审核"
|
||||||
UPDATE "QH_EME_FIRST_AID_RESOURCE"
|
UPDATE "QH_EME_FIR_AID_RES"
|
||||||
SET "AUDIT_STATUS" = CASE
|
SET "AUDIT_STATUS" = CASE
|
||||||
WHEN "AUDIT_STATUS" IS NULL THEN 0 -- 草稿 → 0(待审核)
|
WHEN "AUDIT_STATUS" IS NULL THEN 0 -- 草稿 → 0(待审核)
|
||||||
WHEN "AUDIT_STATUS" = 10 THEN 0 -- 待审核 → 0
|
WHEN "AUDIT_STATUS" = 10 THEN 0 -- 待审核 → 0
|
||||||
@@ -18,7 +18,7 @@ WHERE "AUDIT_STATUS" IS NULL OR "AUDIT_STATUS" IN (10, 11, 12);
|
|||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
-- 恢复表字段注释
|
-- 恢复表字段注释
|
||||||
COMMENT ON COLUMN "QH_EME_FIRST_AID_RESOURCE"."AUDIT_STATUS" IS
|
COMMENT ON COLUMN "QH_EME_FIR_AID_RES"."AUDIT_STATUS" IS
|
||||||
'审核状态(0=待审核,1=已通过,2=已驳回)';
|
'审核状态(0=待审核,1=已通过,2=已驳回)';
|
||||||
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|||||||
+505
@@ -0,0 +1,505 @@
|
|||||||
|
-- =====================================================
|
||||||
|
-- 急救宣教资源 - 种子数据(达梦数据库)
|
||||||
|
-- 包含:分类(扁平一层)、标签(归属分类下)、资源内容
|
||||||
|
-- 执行方式:在达梦客户端中直接执行本脚本
|
||||||
|
-- 注意:请先确认 QH_EME_FIR_AID_RES_CATE 和 QH_EME_FIR_AID_RES 表已创建
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 一、分类数据(TYPE=1,扁平一层,不设二级)
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('CAT001', '心肺复苏术(CPR)', 1, NULL, '成人和儿童心肺复苏技术,包括胸外按压、人工呼吸及AED使用', 1, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('CAT002', '常见急症急救', 1, NULL, '心脏病、脑卒中、癫痫、过敏等突发急症的识别与院前急救', 2, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('CAT003', '创伤急救处理', 1, NULL, '止血、包扎、固定、搬运等创伤急救四大技术', 3, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('CAT004', '意外伤害急救', 1, NULL, '溺水、触电、气道异物梗阻、坠落伤等意外伤害的应急处置', 4, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('CAT005', '环境相关急症', 1, NULL, '中暑、失温、冻伤、高原反应等环境因素所致急症的急救', 5, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('CAT006', '中毒急救', 1, NULL, '食物中毒、煤气中毒、化学品中毒及蛇虫咬伤的急救处理', 6, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('CAT007', '特殊人群急救', 1, NULL, '老年人、孕产妇、婴幼儿等特殊群体的急救要点与注意事项', 7, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('CAT008', '灾害事故急救', 1, NULL, '地震、火灾、交通事故等大规模灾害事故的自救互救知识', 8, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 二、标签数据(TYPE=2,PARENT_ID 指向所属分类)
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
-- === 心肺复苏术(CPR)的标签 ===
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG001', '成人CPR', 2, 'CAT001', '成人(12岁及以上)心肺复苏操作流程与要点', 1, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG002', '儿童与婴儿CPR', 2, 'CAT001', '儿童和婴儿心肺复苏的差异化操作', 2, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG003', 'AED使用', 2, 'CAT001', '自动体外除颤器(AED)的操作方法和使用场景', 3, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG004', 'AHA指南', 2, 'CAT001', '参考美国心脏协会(AHA)最新指南编写', 4, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
-- === 常见急症急救的标签 ===
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG005', '心脑血管急症', 2, 'CAT002', '急性心肌梗死、脑卒中的早期识别与急救', 1, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG006', '过敏与休克', 2, 'CAT002', '严重过敏反应的紧急识别与肾上腺素笔使用', 2, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG007', '突发意识障碍', 2, 'CAT002', '癫痫发作、低血糖昏迷、晕厥等现场急救', 3, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
-- === 创伤急救处理的标签 ===
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG008', '止血与包扎', 2, 'CAT003', '各类外伤出血的止血方法和包扎技术', 1, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG009', '骨折与固定', 2, 'CAT003', '骨折、关节脱位的识别及现场固定搬运技术', 2, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG010', '烧烫伤', 2, 'CAT003', '热烧伤、化学烧伤、电烧伤的急救和创面处理', 3, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
-- === 意外伤害急救的标签 ===
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG011', '气道异物梗阻', 2, 'CAT004', '海姆立克急救法——各年龄段气道梗阻解除', 1, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG012', '溺水与触电', 2, 'CAT004', '溺水救援、触电脱离及继发心脏骤停的急救', 2, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
-- === 环境相关急症的标签 ===
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG013', '高温与中暑', 2, 'CAT005', '热痉挛、热衰竭、热射病的识别与分级急救', 1, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG014', '低温损伤', 2, 'CAT005', '失温(低体温症)、冻伤的分级急救与复温技术', 2, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
-- === 中毒急救的标签 ===
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG015', '食物与气体中毒', 2, 'CAT006', '食物中毒、一氧化碳中毒(煤气中毒)的识别与急救', 1, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG016', '动物咬伤与蜇伤', 2, 'CAT006', '蛇咬伤、犬咬伤、蜂蜇伤、蜱虫叮咬的应急处理', 2, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
-- === 特殊人群急救的标签 ===
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG017', '老年人急救', 2, 'CAT007', '老年人跌倒、突发疾病及用药过量的应急处理', 1, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG018', '婴幼儿急救', 2, 'CAT007', '婴幼儿高热惊厥、窒息、烫伤、跌落等常见意外的急救', 2, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
-- === 灾害事故急救的标签 ===
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG019', '火灾与地震', 2, 'CAT008', '火灾逃生、地震避震及次生灾害的应急处置', 1, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES_CATE (ID, NAME, TYPE, PARENT_ID, DESCRIPTION, SORT_NO, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES ('TAG020', '交通事故急救', 2, 'CAT008', '道路交通事故现场的检伤分类、伤员解救和转运要领', 2, 1, 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||||
|
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 三、资源数据
|
||||||
|
-- 审核状态: 11=已通过 状态: 1=已发布
|
||||||
|
-- CATEGORY_ID 指向分类,TAGS 为逗号分隔的标签ID
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
-- ===================== 心肺复苏术(CPR) =====================
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES001',
|
||||||
|
'成人心肺复苏标准操作流程(2025 AHA指南)',
|
||||||
|
'详细讲解成人心脏骤停的识别、胸外按压、人工呼吸及AED使用的完整流程,依据美国心脏协会最新指南编写。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT001',
|
||||||
|
'发现成人突然倒地、无反应、无呼吸或濒死喘息时',
|
||||||
|
'TAG001,TAG003,TAG004',
|
||||||
|
'<h2>一、确保现场安全</h2><p>施救前先观察环境,确认现场对施救者和患者均安全。如存在触电、火灾、有毒气体等危险,先将患者转移到安全区域。</p><h2>二、判断意识和呼吸</h2><ul><li>轻拍患者双肩,大声呼喊:"喂!你怎么了?"</li><li>观察胸部是否有起伏,判断呼吸是否正常(5-10秒)</li><li>无反应 + 无呼吸/濒死喘息 → 立即启动应急反应系统</li></ul><h2>三、呼叫急救</h2><ul><li>指定现场某人拨打120,并取AED</li><li>如果独自一人:先拨打120开免提,再开始CPR</li></ul><h2>四、胸外按压(C - Circulation)</h2><ul><li><strong>位置:</strong>两乳头连线中点(胸骨中下段)</li><li><strong>手法:</strong>双手十指交叉,掌根重叠,手臂伸直,肩肘腕垂直</li><li><strong>深度:</strong>5-6厘米</li><li><strong>频率:</strong>100-120次/分钟</li><li><strong>回弹:</strong>每次按压后让胸廓完全回弹,掌根不离胸壁</li><li>按压/放松时间比1:1</li></ul><h2>五、开放气道(A - Airway)</h2><ul><li>仰头提颏法:一手压前额,一手提下颌</li><li>如有可见异物,用手指清除</li></ul><h2>六、人工呼吸(B - Breathing)</h2><ul><li>捏住患者鼻翼,口对口吹气(每次约1秒)</li><li>见胸廓隆起为有效</li><li>按压:通气 = 30:2</li><li><strong>如不愿或不方便做人工呼吸,可只做单纯胸外按压</strong></li></ul><h2>七、AED到达后</h2><ul><li>立即开机,按语音提示操作</li><li>电极片贴放位置:右锁骨下 + 左腋前线第5肋间</li><li>电击后立即继续CPR,不要耽误</li></ul><h2>八、持续至</h2><ul><li>患者恢复自主呼吸和意识</li><li>医务人员到达接管</li><li>施救者精疲力竭</li><li>AED提示不得电击且无需CPR</li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 2856, 423, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES002',
|
||||||
|
'儿童与婴儿CPR差异化操作要点',
|
||||||
|
'儿童(1-12岁)和婴儿(<1岁)的心肺复苏与成人不同,本节详细对比差异,帮助家长和幼儿工作者掌握正确的急救方法。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT001',
|
||||||
|
'儿童或婴儿突发意识丧失、无反应、无正常呼吸时',
|
||||||
|
'TAG002,TAG004',
|
||||||
|
'<h2>儿童CPR(1岁至青春期)</h2><h3>按压手法</h3><ul><li><strong>单手或双手:</strong>根据儿童体型和施救者力量选择</li><li>单手:掌根置于胸骨中下段</li><li>双手:同成人手法</li></ul><h3>按压深度</h3><ul><li>至少胸廓前后径的1/3(约5厘米)</li></ul><h3>按压:通气比</h3><ul><li><strong>单人施救:30:2</strong></li><li><strong>双人施救:15:2</strong></li></ul><h3>AED</h3><ul><li>1-8岁儿童首选儿童电极片/儿童模式</li><li>没有儿童电极片时可用成人电极片代替</li></ul><hr><h2>婴儿CPR(<1岁)</h2><h3>判断意识</h3><ul><li>轻拍婴儿足底,观察反应</li></ul><h3>按压手法</h3><ul><li><strong>双指法:</strong>单人施救时,用食指和中指指尖垂直按压</li><li><strong>双手环抱拇指法:</strong>双人施救时,双手环抱婴儿胸部,双拇指并排按压</li></ul><h3>按压位置</h3><ul><li>两乳头连线中点稍下方(胸骨中段)</li></ul><h3>按压深度</h3><ul><li>至少胸廓前后径的1/3(约4厘米)</li></ul><h3>人工呼吸</h3><ul><li>口对口鼻共同吹气</li><li>每次吹气量以胸廓微微抬起为准,不可过度用力</li></ul><h3>按压:通气比</h3><ul><li>单人:30:2</li><li>双人:15:2</li></ul><h3>AED</h3><ul><li>婴儿首选手动除颤器</li><li>AED仅在没有手动除颤器且确有必要时使用</li></ul><hr><h2>成人与儿童/婴儿CPR差异速查表</h2><table border="1"><tr><th>项目</th><th>成人</th><th>儿童</th><th>婴儿</th></tr><tr><td>按压深度</td><td>5-6cm</td><td>~5cm</td><td>~4cm</td></tr><tr><td>按压手法</td><td>双手</td><td>单手/双手</td><td>双指/双拇指</td></tr><tr><td>单人按压:通气</td><td>30:2</td><td>30:2</td><td>30:2</td></tr><tr><td>双人按压:通气</td><td>30:2</td><td>15:2</td><td>15:2</td></tr></table>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 1678, 312, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES003',
|
||||||
|
'AED(自动体外除颤器)完全使用指南',
|
||||||
|
'AED是什么、在哪里能找到、怎么用——从开机到电击的全流程图解指南。AED是抢救心脏骤停的关键设备,普通人经过简单学习即可使用。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT001',
|
||||||
|
'心脏骤停患者CPR过程中AED到达现场时;公共场所发现AED设备时',
|
||||||
|
'TAG003,TAG004',
|
||||||
|
'<h2>一、什么是AED?</h2><p>自动体外除颤器(Automated External Defibrillator)是一种便携式医疗设备,可以自动分析心律,判断是否需要电击除颤。它配有语音提示,非专业人员经过简单培训即可安全使用。</p><h2>二、为什么要用AED?</h2><ul><li>心脏骤停最常见的初始心律是<strong>心室颤动(VF)</strong></li><li>电击除颤是终止室颤的唯一有效方法</li><li><strong>每延迟1分钟除颤,生存率下降7%-10%</strong></li><li>CPR+AED可将院外心脏骤停生存率提高至50%以上</li></ul><h2>三、哪里有AED?</h2><ul><li>机场、火车站、地铁站</li><li>大型商场、体育场馆</li><li>学校、写字楼</li><li>微信搜索"AED"或使用"AED地图"小程序</li></ul><h2>四、AED操作步骤</h2><h3>第1步:开机</h3><ul><li>打开机盖或按下电源键,之后全程<strong>按照语音提示操作</strong></li></ul><h3>第2步:贴电极片</h3><ul><li>脱去患者胸前衣物,擦干皮肤(如有水或汗)</li><li>将电极片按包装图示贴在裸露的胸前</li><li><strong>位置一:</strong>右侧锁骨下方(右胸上部)</li><li><strong>位置二:</strong>左侧腋前线第5肋间(左胸下部侧面)</li><li>将电极片插头插入主机(如已预连则跳过)</li></ul><h3>第3步:分析心律</h3><ul><li>AED自动分析,<strong>任何人不得接触患者</strong></li></ul><h3>第4步:电击</h3><ul><li>如需电击,AED自动充电并发声警告</li><li>确认<strong>无人接触患者</strong>后,按下闪烁的放电按钮</li><li>电击后<strong>立即恢复CPR</strong>(从胸外按压开始)</li></ul><h2>五、注意事项</h2><ul><li>贴电极片前确认皮肤干燥、无过多胸毛</li><li>患者胸部有膏药需撕下并擦净</li><li>体内有起搏器/ICD的患者,电极片应避开设备至少2.5厘米</li><li>在水中或金属表面时,将患者移至干燥地面再使用</li></ul><h2>六、AED与CPR配合节奏</h2><p>CPR不间断 → AED到达 → 开机贴片 → 分析 → 电击(如需)→ 立即CPR → 2分钟后AED再次分析 → 循环…</p>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 2103, 388, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ===================== 常见急症急救 =====================
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES004',
|
||||||
|
'急性心肌梗死的早期识别与院前急救',
|
||||||
|
'心梗是最常见的致命急症之一。本文教您识别心梗的典型和非典型症状,以及在救护车到达前如何正确处置。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT002',
|
||||||
|
'突感胸痛、胸闷、出冷汗,疑似心脏病发作时',
|
||||||
|
'TAG005',
|
||||||
|
'<h2>一、什么是急性心肌梗死?</h2><p>冠状动脉突然堵塞,导致心肌缺血坏死。黄金抢救时间窗口仅2小时,<strong>时间就是心肌,时间就是生命</strong>。</p><h2>二、典型症状</h2><ul><li><strong>胸痛:</strong>胸骨后压榨性、闷胀性疼痛,持续不缓解(>20分钟)</li><li><strong>放射痛:</strong>疼痛可向左肩、左臂内侧、颈部、下颌、背部放射</li><li><strong>伴随症状:</strong>出冷汗、恶心呕吐、呼吸困难、濒死感</li></ul><h2>三、非典型症状(尤其警惕!)</h2><ul><li><strong>女性:</strong>可能仅表现为极度疲劳、恶心、背部或下颌疼痛</li><li><strong>老年人:</strong>可能表现为气短、乏力、意识模糊</li><li><strong>糖尿病患者:</strong>可能无痛(无痛性心梗),仅表现为突发心衰</li></ul><h2>四、现场急救步骤</h2><ol><li><strong>立即停止一切活动:</strong>让患者保持安静,取半卧位或坐位(切勿平卧!)</li><li><strong>拨打120:</strong>清楚告知"疑似心脏病发作"和具体地址</li><li><strong>服用药物(如患者自备):</strong>硝酸甘油舌下含服1片,5分钟后不缓解可再含1片(最多3片);阿司匹林嚼服300mg(非肠溶片),除非有禁忌</li><li><strong>保持气道通畅:</strong>解开衣领和腰带</li><li><strong>持续观察:</strong>如患者意识丧失、无呼吸,立即开始CPR</li></ol><h2>五、禁忌事项</h2><ul><li><strong>❌ 不要让患者自行走动</strong></li><li><strong>❌ 不要自行开车送医院</strong>(途中可能发生室颤)</li><li><strong>❌ 不要给非患者本人的药物</strong></li><li><strong>❌ 不要用力咳嗽("咳嗽CPR"未被指南推荐)</strong></li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 3201, 567, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES005',
|
||||||
|
'脑卒中(中风)"120"识别法与急救',
|
||||||
|
'中风抢救争分夺秒。学会"1-2-0"快速识别法,及时发现中风前兆,在"黄金4.5小时"内送医溶栓。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT002',
|
||||||
|
'突发面部不对称、单侧肢体无力、言语不清等疑似中风症状',
|
||||||
|
'TAG005',
|
||||||
|
'<h2>一、认识脑卒中</h2><p>脑卒中分为<strong>缺血性(脑梗死,占70%)</strong>和<strong>出血性(脑出血,占30%)</strong>。无论哪种,都需要紧急就医。溶栓治疗时间窗仅<strong>4.5小时</strong>。</p><h2>二、"中风120"快速识别法</h2><table border="1"><tr><th>数字</th><th>含义</th><th>检查方法</th></tr><tr><td><strong>1</strong></td><td>看<strong>1</strong>张脸</td><td>让患者微笑,观察面部是否对称,有无口角歪斜</td></tr><tr><td><strong>2</strong></td><td>查<strong>2</strong>只胳膊</td><td>让患者平举双臂,观察是否有单侧无力或下垂</td></tr><tr><td><strong>0</strong></td><td><strong>聆</strong>听语言</td><td>让患者说一句简单的话,观察是否含糊不清或无法表达</td></tr></table><p>以上三项中<strong>任何一项异常</strong>,中风可能性约72%,应立即拨打120!</p><h2>三、其他警示症状</h2><ul><li>突发剧烈头痛("一生中最剧烈的头痛")</li><li>突发单眼或双眼视力模糊、视野缺损</li><li>突发眩晕、行走困难、平衡失调</li><li>突发意识障碍或晕厥</li></ul><h2>四、现场急救步骤</h2><ol><li><strong>立即拨打120</strong>,记录发病时间(必须精确到分钟)</li><li>让患者平卧,头偏向一侧(防呕吐误吸)</li><li>解开衣领和腰带,保持气道通畅</li><li>如有呕吐,清除口腔呕吐物</li><li>安抚患者情绪,减少不必要的搬动</li><li>如意识丧失、无呼吸,立即CPR</li></ol><h2>五、绝对禁忌</h2><ul><li><strong>❌ 不要给患者喂水、喂食、喂药</strong>(可能吞咽困难导致窒息)</li><li><strong>❌ 不要摇晃患者</strong></li><li><strong>❌ 不要掐人中、针刺指尖放血等偏方</strong></li><li><strong>❌ 不要让患者自行去厕所</strong></li><li><strong>❌ 不要等待"观察一下"</strong>——时间就是大脑</li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 2567, 445, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES006',
|
||||||
|
'严重过敏反应与肾上腺素笔使用',
|
||||||
|
'食物、药物、蜂蜇等引发的过敏性休克可在数分钟内致命。学会识别过敏反应升级信号,掌握肾上腺素笔的正确使用方法。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT002',
|
||||||
|
'进食服药后突发皮疹、喉头水肿、呼吸困难、血压下降等症状',
|
||||||
|
'TAG006',
|
||||||
|
'<h2>一、认识严重过敏反应</h2><p>严重过敏反应(Anaphylaxis)是IgE介导的全身性超敏反应,<strong>可在数分钟内出现气道阻塞和休克</strong>。常见诱因:食物(花生、海鲜、鸡蛋)、药物(青霉素)、昆虫蜇伤、乳胶。</p><h2>二、识别过敏反应的升级信号</h2><ul><li><strong>皮肤:</strong>荨麻疹、潮红、瘙痒、血管性水肿(尤其是口唇、眼睑肿胀)</li><li><strong>呼吸系统:</strong>喉咙发紧、声音嘶哑、喘鸣、呼吸困难</li><li><strong>消化系统:</strong>恶心、呕吐、腹痛、腹泻</li><li><strong>心血管系统:</strong>头晕、心动过速、血压下降、意识模糊</li><li><strong>注意:</strong>皮肤症状可能缺失!约10%-20%的严重过敏反应<strong>没有皮疹</strong></li></ul><h2>三、肾上腺素笔使用指南</h2><p>肾上腺素是唯一能逆转严重过敏反应的药物,<strong>确诊后应立即注射,刻不容缓</strong>。</p><h3>操作步骤:</h3><ol><li><strong>取下安全帽(蓝色):</strong>不要触碰橙色针头端</li><li><strong>握拳包裹:</strong>橙色端垂直紧贴大腿外侧中部(可隔着裤子)</li><li><strong>用力下压:</strong>听到"咔嗒"声后保持10秒(让药液完全注入)</li><li><strong>拔出按摩:</strong>在注射部位按摩10秒</li><li><strong>拨打120:</strong>即使症状缓解也必须就医,可能发生迟发性反应</li></ol><h2>四、重要提示</h2><ul><li>肾上腺素应注射在大腿外侧(肌肉最丰厚处),<strong>不要注射在臀部或手臂</strong></li><li>如症状无缓解,5-15分钟后可注射第二支</li><li>过敏体质者应随身携带2支肾上腺素笔</li><li>不要将肾上腺素笔存放在高温或阳光直射处</li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 1456, 289, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES007',
|
||||||
|
'癫痫发作的现场急救正确姿势',
|
||||||
|
'癫痫发作时,许多"常识性"做法其实有害无益。本文纠正常见误区,告诉您什么该做,什么绝对不该做。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT002',
|
||||||
|
'身边有人突发全身抽搐、意识丧失时',
|
||||||
|
'TAG007',
|
||||||
|
'<h2>正确做法(4要4不要)</h2><h3>✅ 要做的事:</h3><ol><li><strong>保持镇静,记录发作时间</strong></li><li><strong>清除周围危险物品</strong>(桌椅、尖锐物、火源等)</li><li><strong>保护头部:</strong>在头下垫柔软物品(衣物、靠垫)</li><li><strong>侧卧位:</strong>发作停止后将患者转为侧卧(恢复体位),清理口腔分泌物</li></ol><h3>❌ 绝对不要做的事:</h3><ul><li><strong>❌ 不要往嘴里塞任何东西!</strong>(包括手指、毛巾、筷子、压舌板)——患者不会咬断舌头,塞物反而可能导致牙齿断裂、异物吸入窒息</li><li><strong>❌ 不要强行按压肢体!</strong>——抽搐时骨骼脆弱,强制约束可能导致骨折</li><li><strong>❌ 不要掐人中、灌药、针刺!</strong></li><li><strong>❌ 不要CPR(有正常呼吸脉搏时)!</strong></li></ul><h2>需要拨打120的情况(任一满足)</h2><ul><li>发作持续超过5分钟(<strong>癫痫持续状态</strong>)</li><li>首次发作(从未诊断过癫痫)</li><li>在水中发作</li><li>发作停止后意识未恢复</li><li>发作后再次发作</li><li>患者怀孕</li><li>患者受伤</li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 1876, 267, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ===================== 创伤急救处理 =====================
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES008',
|
||||||
|
'外伤出血的快速止血技术',
|
||||||
|
'严重外伤出血是创伤致死的首要原因。掌握直接压迫、止血带、填塞止血三种方法,关键时刻能救命。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT003',
|
||||||
|
'切割伤、撕裂伤、车祸伤等导致的活动性出血',
|
||||||
|
'TAG008',
|
||||||
|
'<h2>一、出血严重程度判断</h2><table border="1"><tr><th>出血类型</th><th>特征</th><th>危险程度</th></tr><tr><td>毛细血管出血</td><td>缓慢渗出、血色鲜红</td><td>低</td></tr><tr><td>静脉出血</td><td>持续流出、血色暗红</td><td>中</td></tr><tr><td>动脉出血</td><td>喷射状、随心跳搏动、血色鲜红</td><td>⚠️ 致命!</td></tr></table><p>成人失血>500ml = 危险,>1000ml = 休克,>2000ml = 死亡。</p><h2>二、直接压迫止血法(首选)</h2><ol><li>用干净纱布/毛巾/衣物直接按压伤口</li><li>持续用力按压至少10分钟,<strong>不要中途掀开查看</strong></li><li>如纱布被血液浸透,在上面<strong>再加一层</strong>(不要更换!会破坏已形成的血凝块)</li><li>加压包扎固定</li></ol><h2>三、止血带止血法(四肢大出血专用)</h2><ul><li><strong>适应症:</strong>直接加压无效的四肢大出血、肢体离断</li><li><strong>位置:</strong>伤口上方5-8厘米(靠近心脏一侧),避开关节</li><li><strong>力度:</strong>以远端动脉搏动消失、出血停止为准</li><li><strong>标记:</strong>在患者额头或明显位置写上绑扎时间(精确到分钟)</li><li><strong>时间:</strong>不超过2小时(每30分钟松解检查1次,但需评估再出血风险)</li><li>不要用绳索、电线、铁丝代替</li></ul><h2>四、填塞止血法(交界部位深部伤口)</h2><p>适用于腹股沟、腋窝、颈部等不便使用止血带的部位:</p><ol><li>将止血纱布/干净布条塞入伤口深部</li><li>从最深处向外逐层填塞,保持压力</li><li>外部加压包扎固定</li></ol><h2>五、注意事项</h2><ul><li>穿戴手套(如有),避免直接接触血液</li><li>不要取出嵌入伤口的异物(刀、玻璃等)——固定异物,包扎后送医</li><li>怀疑内出血(腹胀、休克、无外伤但血压持续下降)立即送医</li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 2134, 378, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES009',
|
||||||
|
'骨折与脊柱损伤的现场固定与搬运',
|
||||||
|
'错误的搬运可能让骨折变为截瘫。本节讲解骨折的临时固定方法和脊柱损伤的安全搬运技术。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT003',
|
||||||
|
'高处坠落、交通事故、重物砸伤等可能导致骨折或脊柱损伤的场合',
|
||||||
|
'TAG009',
|
||||||
|
'<h2>一、骨折的识别</h2><ul><li>剧烈疼痛,活动时加剧</li><li>局部肿胀、瘀斑</li><li>畸形(与对侧不对称、异常弯曲)</li><li>反常活动(关节以外部位出现活动)</li><li>骨擦音/骨擦感</li><li>功能丧失(无法承重/活动)</li></ul><h2>二、骨折固定原则</h2><ul><li><strong>固定范围:</strong>骨折部位的上下两个关节</li><li>夹板长度应超过骨折上下关节</li><li>夹板与皮肤间用软物衬垫</li><li>固定松紧适度——指尖可触及远端动脉搏动</li><li>开放性骨折:<strong>不要将外露的骨端推回</strong>,覆盖无菌敷料后固定</li></ul><h2>三、脊柱损伤的识别(高度警惕!)</h2><ul><li>高处坠落(>2米)、交通事故(高速撞击)、跳水头部撞底</li><li>伤后颈部疼痛、肢体麻木/无力、大小便失禁</li></ul><h2>四、脊柱损伤安全搬运</h2><h3>🔴 黄金原则:除非有立即生命危险(火灾、爆炸),<strong>绝不要移动疑似脊柱损伤的患者</strong>,等待专业急救人员。</h3><h3>如必须移动:</h3><ol><li>保持头-颈-躯干<strong>呈一直线</strong>(轴线翻身)</li><li>至少3人协作:一人固定头颈,一人托躯干,一人托下肢</li><li>使用硬质担架/门板/桌面</li><li>颈椎用颈托或沙袋/衣物卷固定头部两侧</li></ol><h2>五、各部位固定要点</h2><ul><li><strong>前臂骨折:</strong>夹板固定后三角巾悬吊于胸前(屈肘90°)</li><li><strong>上臂骨折:</strong>夹板固定后上臂紧贴胸壁,前臂三角巾悬吊</li><li><strong>大腿骨折:</strong>长夹板从腋下至足跟,另用短夹板从大腿内侧至小腿</li><li><strong>小腿骨折:</strong>夹板从大腿中部至足跟</li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 1678, 298, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES010',
|
||||||
|
'烧烫伤的急救五步法:"冲脱泡盖送"',
|
||||||
|
'烧烫伤是生活中最常见的意外伤害之一。记住"冲脱泡盖送"五个字,正确处理创面,避免二次伤害和留疤。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT003',
|
||||||
|
'热液烫伤、火焰烧伤、热固体烫伤、化学烧伤等各类烧烫伤',
|
||||||
|
'TAG010',
|
||||||
|
'<h2>急救五步法</h2><h3>冲(最关键的第一反应!)</h3><ul><li>立即用<strong>流动冷水</strong>冲洗伤处15-30分钟</li><li>水温15-25℃为宜,不要用冰水(可能导致血管过度收缩加重损伤)</li><li>化学烧伤需冲洗更长时间(至少30分钟)</li></ul><h3>脱</h3><ul><li>在冷水中<strong>小心去除</strong>覆盖伤处的衣物和饰物(戒指、手表、手镯)</li><li>如衣物与皮肤粘连,<strong>不要强行撕扯</strong>——用剪刀剪开周围衣物</li></ul><h3>泡</h3><ul><li>将伤处浸泡在冷水中持续15-30分钟(仅适用于小面积烧伤)</li><li>大面积烧伤(>10%体表面积)不要长时间浸泡——可能导致低体温</li></ul><h3>盖</h3><ul><li>用<strong>清洁无菌的敷料或保鲜膜</strong>覆盖创面</li><li>保鲜膜覆盖可减少疼痛、防止感染、便于医生观察</li><li>不要用棉花、纸巾(纤维会粘连创面)</li><li>不要涂抹牙膏、酱油、蛋清、香油等偏方!</li></ul><h3>送</h3><ul><li>及时送医:小面积浅度烧伤→社区医院;大面积或深度烧伤→烧伤专科</li></ul><h2>烧伤严重程度判断</h2><table border="1"><tr><th>分度</th><th>表现</th><th>处理</th></tr><tr><td>Ⅰ度(红斑性)</td><td>皮肤发红、疼痛、无水肿和水疱</td><td>自行处理</td></tr><tr><td>浅Ⅱ度(水疱性)</td><td>大水疱、剧痛、基底潮红</td><td>门诊处理</td></tr><tr><td>深Ⅱ度</td><td>小水疱、疼痛迟钝、基底红白相间</td><td>需住院</td></tr><tr><td>Ⅲ度(焦痂性)</td><td>皮肤蜡白或焦黑、无痛觉</td><td>需住院手术</td></tr></table><h2>特殊类型烧伤</h2><ul><li><strong>电烧伤:</strong>入口小出口大,深部组织损伤严重,必须就医</li><li><strong>吸入性烧伤:</strong>面部烧伤+声音嘶哑+鼻腔有烟灰→气道可能已受损,立即就医</li><li><strong>化学烧伤:</strong>干石灰→先刷除再冲洗!遇水产生高温</li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 3567, 634, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ===================== 意外伤害急救 =====================
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES011',
|
||||||
|
'海姆立克急救法:气道异物梗阻的救命技术',
|
||||||
|
'"吃东西噎住了"可能数分钟内致命。海姆立克法是解除气道梗阻最有效的方法,每个人都应该掌握。含成人、儿童、婴儿及自救四种场景。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT004',
|
||||||
|
'进食时突然不能说话、呼吸困难、手抓喉咙(V型手势)、面色发绀',
|
||||||
|
'TAG011',
|
||||||
|
'<h2>一、识别气道异物梗阻</h2><ul><li><strong>完全梗阻:</strong>无法说话、无法咳嗽、无法呼吸、面色发紫、双手抓颈部(典型的"窒息V手势")→ <strong>立即海姆立克!</strong></li><li><strong>部分梗阻:</strong>能说话、能咳嗽→鼓励患者用力咳嗽,不要拍背</li></ul><h2>二、成人/儿童(>1岁)海姆立克法</h2><ol><li><strong>站位:</strong>双脚前后分开,稳定重心</li><li><strong>定位:</strong>双手环绕患者腰部,一手握拳,拳心向内,置于<strong>肚脐上方两横指</strong>处(剑突下)</li><li><strong>冲击:</strong>另一手包住拳头,<strong>向内、向上</strong>快速用力冲击</li><li><strong>重复:</strong>直到异物排出或患者意识丧失</li></ol><h2>三、婴儿(<1岁)急救法</h2><ul><li><strong>不要用海姆立克法!</strong>婴儿腹部器官脆弱,易损伤</li><li>5次拍背 + 5次胸外按压交替</li></ul><ol><li><strong>拍背:</strong>将婴儿面朝下放在前臂上,头低于躯干,用掌根在肩胛骨之间拍击5次</li><li><strong>胸外按压:</strong>翻转婴儿面朝上,头低于躯干,用两指在胸骨中段按压5次</li><li><strong>检查口腔:</strong>如异物可见,用小指取出(<strong>不要盲目掏挖</strong>)</li><li>重复5+5循环直到异物排出</li></ol><h2>四、自救方法</h2><ul><li><strong>腹部冲击法:</strong>一手握拳置于肚脐上方,另一手包住,弯腰后向后上方冲击。或利用椅背、桌角、栏杆等硬物顶压腹部</li><li>立即拨打120(如能说话)</li></ul><h2>五、患者意识丧失后怎么办</h2><ul><li>将患者平放地面,立即开始CPR</li><li>做人工呼吸前检查口腔,如有可见异物取出</li><li>CPR的胸外按压也可产生气道压力,有助于排出异物</li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 4123, 789, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES012',
|
||||||
|
'溺水急救:水中解救与岸上复苏',
|
||||||
|
'溺水导致的死亡大多是可以避免的。了解正确的水中救援方式和岸上心肺复苏要点,不要让自己成为第二个溺水者。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT004',
|
||||||
|
'发现有人溺水或游泳过程中发生意外时',
|
||||||
|
'TAG012',
|
||||||
|
'<h2>一、水中解救(首要原则:保证自身安全!)</h2><ul><li><strong>非专业人员不要贸然下水!</strong></li><li><strong>伸:</strong>用竹竿、树枝、衣物伸向溺水者</li><li><strong>抛:</strong>抛投救生圈、绳索、空塑料桶等漂浮物</li><li><strong>划:</strong>划船靠近</li><li><strong>游:</strong>仅受过专业水中救援训练者可游泳接近,从后方接近避免被溺水者抱住</li></ul><h2>二、岸上急救</h2><h3>判断意识和呼吸</h3><p>将溺水者仰卧于硬质平面,判断反应和呼吸。</p><h3>如无反应+无正常呼吸 → 立即CPR</h3><ol><li><strong>先开放气道</strong>,清理口腔内泥沙、水草等异物</li><li><strong>先给5次人工呼吸</strong>(溺水是缺氧性心脏骤停,先通气!)</li><li>然后按<strong>30:2</strong>进行CPR</li><li>AED到达后使用(擦干胸前皮肤)</li></ol><h2>三、常见误区纠正</h2><ul><li><strong>❌ 不要"控水"!</strong>(倒背跑、按压腹部排水等)——溺水者胃里的水不会堵塞气道,控水只会延误CPR时间,增加呕吐误吸风险</li><li><strong>❌ 不要因为溺水者能说话就掉以轻心</strong>——可能发生"二次溺水"(延迟性肺水肿)</li><li><strong>✅ 所有溺水者(即使看起来没事)都应送医观察</strong></li></ul><h2>四、冷水溺水特点</h2><ul><li>冷水(<10℃)溺水者可能经长时间CPR后存活</li><li>冷水有脑保护作用,不要轻易放弃</li><li>切勿在未确认死亡前停止CPR</li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 2134, 345, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ===================== 环境相关急症 =====================
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES013',
|
||||||
|
'中暑的分级识别与急救处理',
|
||||||
|
'高温天气下中暑高发。热痉挛、热衰竭、热射病是三个逐步升级的阶段,热射病病死率高达50%。早期识别和正确降温是关键。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT005',
|
||||||
|
'高温天气户外工作、运动、或密闭高温环境中出现头晕、恶心等症状',
|
||||||
|
'TAG013',
|
||||||
|
'<h2>一、中暑的三个阶段</h2><h3>1. 热痉挛(轻度)</h3><ul><li><strong>表现:</strong>大量出汗后出现四肢、腹部肌肉痉挛(抽筋),体温正常或略高</li><li><strong>处理:</strong>移至阴凉处→补充含盐饮料/运动饮料→拉伸痉挛肌肉→休息</li></ul><h3>2. 热衰竭(中度)</h3><ul><li><strong>表现:</strong>大汗淋淋、面色苍白、头晕头痛、恶心呕吐、心跳加快、体温升高(38-40℃)、血压下降</li><li><strong>处理:</strong>移至阴凉通风处→松开衣物→补充含盐冷饮(如能吞咽)→冷水擦拭、扇风降温→抬高下肢</li><li>如呕吐或意识改变→立即就医</li></ul><h3>3. 热射病(重度、致命!)</h3><ul><li><strong>表现:</strong>体温>40℃、皮肤干热无汗(典型)、意识障碍(谵妄、抽搐、昏迷)</li><li><strong>死亡率:</strong>高达50%</li><li><strong>处理:</strong><ul><li><strong>立即拨打120!</strong></li><li><strong>立即开始降温!</strong>——争分夺秒,不要等待救护车</li><li>冷水浸泡(最有效):将患者浸入冷水中(水温<20℃),不断搅动</li><li>或冰袋置于颈部、腋下、腹股沟(大血管走行处)</li><li>持续扇风+喷洒冷水</li><li>降温目标:<strong>30分钟内将体温降至<39℃</strong></li></ul></li></ul><h2>二、预防要点</h2><ul><li>高温时段(11:00-15:00)减少户外活动</li><li>每小时饮水500-1000ml(少量多次,勿等口渴再喝)</li><li>补充含盐饮料,不要只喝纯水</li><li>穿透气、浅色衣物</li><li>切勿将儿童或宠物留在密闭车内!</li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 2345, 412, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES014',
|
||||||
|
'失温(低体温症)与冻伤的急救',
|
||||||
|
'低体温症不仅在极寒环境发生,湿冷大风中10℃也能致命。新疆冬季寒冷,是失温和冻伤的高风险地区,每位职工都应掌握。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT005',
|
||||||
|
'寒冷天气户外作业、登山受困、落水获救后、长时间暴露在湿冷阴雨环境中',
|
||||||
|
'TAG014',
|
||||||
|
'<h2>一、低体温症的分级</h2><table border="1"><tr><th>分级</th><th>体温</th><th>表现</th></tr><tr><td>轻度</td><td>32-35℃</td><td>寒战、手脚冰凉、精细动作困难</td></tr><tr><td>中度</td><td>28-32℃</td><td>寒战停止(危险信号!)、意识模糊、言语不清、心跳呼吸减慢</td></tr><tr><td>重度</td><td><28℃</td><td>昏迷、瞳孔散大、心跳呼吸极微弱(可能被误认为死亡)</td></tr></table><h2>二、低体温症急救步骤</h2><ol><li><strong>脱离冷环境:</strong>移到避风保暖处,脱去湿衣物</li><li><strong>被动复温:</strong>用保温毯、睡袋、干衣物包裹全身</li><li><strong>主动复温:</strong>热水袋/暖宝宝置于<strong>胸部、颈部、腹股沟</strong>(大血管区,不要放四肢!四肢加热会导致冷血回流心脏,引发心律失常)</li><li><strong>补充热量:</strong>如患者清醒可吞咽,给予温热含糖饮料(<strong>不要给酒精和咖啡因</strong>)</li><li><strong>避免剧烈动作:</strong>可能诱发室颤</li></ol><h2>三、急救注意事项</h2><ul><li>判断生命体征要<strong>测60秒</strong>(严重低体温时脉搏和呼吸极其缓慢微弱)</li><li>对重度低体温者,<strong>不要轻易认定为死亡</strong>——"Not dead until warm and dead"</li><li>CPR:疑似心脏骤停者,如无法在10秒内确认脉搏,应立即开始CPR</li></ul><h2>四、冻伤的急救</h2><ul><li><strong>不要用雪搓患处!</strong>(加重组织损伤)</li><li><strong>不要用明火/暖气直接烤!</strong>(冻伤部位感觉迟钝,极易烫伤)</li><li><strong>正确复温:</strong>将冻伤部位浸泡在<strong>37-42℃温水</strong>中,持续15-30分钟(水温用健康肢体测试)</li><li>复温过程中会出现剧痛和颜色变化(变红)——这是正常现象</li><li>如水疱形成,不要刺破</li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 1456, 267, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ===================== 中毒急救 =====================
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES015',
|
||||||
|
'一氧化碳(煤气)中毒的识别与急救',
|
||||||
|
'一氧化碳中毒是新疆冬季供暖季最常见的急症之一。CO无色无味,被称为"沉默杀手"。早期识别症状、正确处置可避免悲剧。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT006',
|
||||||
|
'冬季使用煤炉取暖、燃气热水器洗浴、在密闭车库发动汽车时',
|
||||||
|
'TAG015',
|
||||||
|
'<h2>一、一氧化碳为什么危险?</h2><ul><li>CO与血红蛋白亲和力比O₂强<strong>240倍</strong>——空气中极低浓度的CO即可导致严重缺氧</li><li>无色、无味、无刺激——无法靠感官察觉</li><li>中毒早期症状类似"感冒",极易被忽视</li></ul><h2>二、中毒症状分级</h2><table border="1"><tr><th>程度</th><th>症状</th></tr><tr><td>轻度</td><td>头痛、头晕、恶心、呕吐、乏力(像感冒)</td></tr><tr><td>中度</td><td>剧烈头痛、意识模糊、嗜睡、呼吸急促</td></tr><tr><td>重度</td><td>昏迷、抽搐、呼吸和循环衰竭、大小便失禁</td></tr></table><p>特征性体征:<strong>皮肤和黏膜呈樱桃红色</strong>(出现时往往已重度中毒)</p><h2>三、急救步骤</h2><ol><li><strong>第一时间开窗通风!</strong>——不要先做别的</li><li>迅速将患者移到<strong>空气新鲜处</strong>,解开衣领和腰带</li><li>拨打120,明确告知"一氧化碳中毒"</li><li>如患者无呼吸/心跳,立即CPR</li><li><strong>高流量吸氧</strong>(由急救人员操作)——这是最重要的治疗</li></ol><h2>四、常见误区</h2><ul><li><strong>❌ "屋里放盆水能防煤气中毒"</strong>——CO不溶于水,完全无效</li><li><strong>❌ "让中毒者喝醋、灌酸菜汤能解毒"</strong>——无效且可能导致误吸</li><li><strong>❌ "患者醒了就好了"</strong>——CO中毒可能有<strong>迟发性脑病(假愈期)</strong>,必须就医观察</li></ul><h2>五、预防措施</h2><ul><li>煤炉取暖必须安装排烟管道并定期检查</li><li>燃气热水器严禁安装在浴室或通风不良处</li><li>不在密闭车库发动汽车</li><li>安装<strong>一氧化碳报警器</strong></li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 2876, 378, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES016',
|
||||||
|
'蛇咬伤、犬咬伤与蜂蜇伤的应急处理',
|
||||||
|
'新疆地区野外作业可能遇到毒蛇、野犬、蜂群。不同动物伤害的急救方法截然不同,错误处理可能加重后果。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT006',
|
||||||
|
'野外作业、户外活动时被蛇咬伤、犬咬伤或蜂群攻击',
|
||||||
|
'TAG016',
|
||||||
|
'<h2>一、蛇咬伤急救</h2><h3>毒蛇与无毒蛇咬伤的鉴别</h3><ul><li><strong>毒蛇:</strong>一对(或单个)较深牙痕,局部肿胀迅速、剧痛、发黑</li><li><strong>无毒蛇:</strong>两排细密牙痕,轻微疼痛,无全身症状</li><li><strong>不确定时:</strong>一律按毒蛇咬伤处理</li></ul><h3>急救步骤</h3><ol><li><strong>保持镇静:</strong>制动!<strong>减少活动</strong>(降低毒素扩散速度)</li><li><strong>固定伤肢:</strong>用夹板固定,保持伤处低于心脏水平</li><li><strong>去除束缚物:</strong>摘除戒指、手镯、手表等(局部会迅速肿胀)</li><li><strong>清洗伤口:</strong>用清水冲洗(如有条件)</li><li><strong>立即就医:</strong>采集/拍下蛇的照片有助于选择抗蛇毒血清</li></ol><h3>绝对禁忌(传统做法大多有害!)</h3><ul><li><strong>❌ 不要用嘴吸毒!</strong>(吸出量微乎其微,反而导致口咽部吸收中毒)</li><li><strong>❌ 不要切口放血!</strong>(增加感染和损伤)</li><li><strong>❌ 不要扎止血带!</strong>(阻断动脉会导致肢体缺血坏死)</li><li><strong>❌ 不要冰敷!</strong>(加重组织损伤)</li></ul><h2>二、犬咬伤急救</h2><ol><li><strong>冲洗:</strong>大量流动清水+肥皂水交替冲洗伤口至少15分钟</li><li><strong>消毒:</strong>碘伏或75%酒精消毒</li><li><strong>不缝合不包扎:</strong>一般开放性伤口不予缝合包扎(利于引流)</li><li><strong>立即就医:</strong>评估是否需要注射狂犬疫苗和破伤风抗毒素</li></ol><h2>三、蜂蜇伤的急救</h2><h3>局部反应(大多数情况)</h3><ol><li><strong>拔除毒刺:</strong>用指甲或卡片背面沿皮肤<strong>逆刮</strong>,不要用镊子夹(可能将毒囊内毒液挤入体内)</li><li><strong>清洗:</strong>肥皂水冲洗</li><li><strong>冷敷:</strong>减轻肿胀和疼痛</li></ol><h3>警惕严重过敏反应</h3><ul><li>被蜇后短时间出现全身荨麻疹、呼吸困难、面部肿胀 → 过敏性休克</li><li>使用肾上腺素笔(如有)+ 立即拨打120</li></ul><h3>多处蜇伤(>10处)</h3><ul><li>即使无过敏反应,也需就医(蜂毒累积毒性)</li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 1567, 234, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ===================== 特殊人群急救 =====================
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES017',
|
||||||
|
'老年人跌倒后的应急处理',
|
||||||
|
'跌倒是65岁以上老年人伤害死亡的首位原因。老人跌倒后,盲目扶起可能造成二次伤害。正确做法是"先评估、后处理"。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT007',
|
||||||
|
'老年人发生跌倒,尤其在居家、社区活动、如厕洗澡时',
|
||||||
|
'TAG017',
|
||||||
|
'<h2>一、跌倒后第一反应:不要急于扶起!</h2><p>老人跌倒后<strong>保持原位</strong>,先自我检查:</p><ol><li>有没有剧烈疼痛(尤其是髋部、腰部)?</li><li>手脚能不能活动?有没有麻木?</li><li>有没有出血?</li></ol><h2>二、目击者的处理步骤</h2><h3>1. 先评估(不要立即扶起)</h3><ul><li>询问疼痛部位、能否活动</li><li>检查有无外伤出血</li><li>观察意识状态</li></ul><h3>2. 怀疑骨折/脊柱损伤 → 不要移动</h3><ul><li><strong>髋部骨折:</strong>伤肢短缩、外旋、"脚不能动了"</li><li><strong>脊柱骨折:</strong>腰背部剧痛、下肢麻木或不能动</li><li>发现上述症状→<strong>立即拨打120</strong>,保持老人平卧保暖</li></ul><h3>3. 确认无骨折 → 安全扶起</h3><ol><li>协助老人翻身侧卧,屈膝</li><li>用椅子做支撑,手撑椅面缓慢起身</li><li>如老人头晕,先坐一会再尝试站立</li></ol><h2>三、跌倒后最危险的两种情况</h2><h3>髋部骨折</h3><ul><li>被称为"人生最后一次骨折"——骨折后长期卧床易引发肺炎、压疮、血栓,一年内死亡率约20%-30%</li><li>必须有手术意识——条件允许尽早手术</li></ul><h3>硬膜下血肿</h3><ul><li>跌倒撞头后<strong>数天至数周</strong>才出现症状("迟发性")</li><li>表现为:逐渐加重的头痛、嗜睡、一侧肢体无力、反应迟钝</li><li>头部外伤后如出现上述症状<strong>必须就医</strong>,做头颅CT</li></ul><h2>四、预防胜于急救</h2><ul><li>家居防滑:浴室铺防滑垫,清除地面杂物和电线</li><li>改善照明:卧室到卫生间的通道安装夜灯</li><li>适当锻炼:太极拳、平衡训练可显著降低跌倒风险</li><li>定期检查视力和药物副作用(降压药、安眠药等)</li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 1987, 356, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES018',
|
||||||
|
'婴幼儿高热惊厥的正确处置',
|
||||||
|
'高热惊厥是6个月至5岁婴幼儿最常见的中枢神经系统急症。看起来非常吓人,但掌握正确处理后可以安全度过。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT007',
|
||||||
|
'婴幼儿(6个月-5岁)发热时突发全身或局部抽搐、意识丧失',
|
||||||
|
'TAG018',
|
||||||
|
'<h2>一、什么是高热惊厥?</h2><ul><li>通常在体温快速升高阶段发生(>38℃)</li><li>好发年龄:6个月至5岁,高峰18-24个月</li><li>家族遗传倾向明显</li><li><strong>绝大多数是良性的</strong>,不会导致脑损伤或智力问题</li></ul><h2>二、发作时的表现</h2><ul><li>全身僵直或抽搐、双眼上翻或凝视</li><li>口吐白沫、意识丧失</li><li>约持续1-3分钟,一般<strong>5分钟内自行停止</strong></li></ul><h2>三、家长急救步骤</h2><ol><li><strong>保持镇静</strong>,记录发作开始时间</li><li><strong>侧卧位:</strong>将孩子侧放,防止呕吐物/口水呛入气道</li><li><strong>清除周围危险物</strong>(硬物、尖锐物)</li><li><strong>松开衣物:</strong>解开衣领和腰带</li><li><strong>不要往嘴里塞任何东西!</strong>(包括手指、毛巾、筷子、压舌板)</li><li><strong>不要强行按压四肢!</strong></li><li>抽搐停止后,用退热药(对乙酰氨基酚/布洛芬,按体重计算剂量)</li></ol><h2>四、什么情况必须立即就医?</h2><ul><li>抽搐持续<strong>超过5分钟</strong></li><li>抽搐停止后意识未恢复</li><li>反复抽搐</li><li>抽搐后一侧肢体无力(Todd麻痹)</li><li>首次发作</li><li>抽搐前有头部外伤史</li></ul><h2>五、是否会复发?</h2><ul><li>约1/3患儿会复发</li><li>首次发作年龄越小、发热程度越低(<38.5℃就抽搐)、直系亲属有惊厥史者复发率更高</li><li>多数孩子5-6岁后不再发作</li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 2234, 445, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ===================== 灾害事故急救 =====================
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES019',
|
||||||
|
'火灾现场逃生与烧伤急救',
|
||||||
|
'火灾死亡中,大部分不是烧死而是吸入有毒烟雾窒息。了解正确的逃生方法和初期火灾扑救,关键时刻能救命。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT008',
|
||||||
|
'建筑火灾发生时的逃生自救和初期火灾处置',
|
||||||
|
'TAG019',
|
||||||
|
'<h2>一、火灾致死的主要原因</h2><ul><li>烟雾和有毒气体吸入(CO、HCN等)——约占火灾死亡人数的<strong>75%</strong></li><li>高温气体吸入导致的气道烧伤</li><li>直接烧伤</li></ul><h2>二、逃生要诀</h2><h3>如果房间内起火且火势小(初期)</h3><ul><li>可用灭火器或湿棉被扑灭(仅限火势小于垃圾桶大小且你有把握)</li><li>电器着火先断电再灭火</li><li>油锅起火→盖锅盖(不要倒水!)</li></ul><h3>如果火势蔓延或烟雾较大 → 立即逃生!</h3><ol><li><strong>低姿前进:</strong>烟雾和热气向上聚集,贴近地面空气相对清洁。用<strong>湿毛巾捂口鼻</strong>,弯腰或匍匐前进</li><li><strong>触摸门把手:</strong>开门前用手背试门把手温度——烫手说明门外有火,<strong>不要开门</strong></li><li><strong>走楼梯不坐电梯</strong></li><li><strong>身上着火:</strong>停(Stop)-倒(Drop)-滚(Roll),用厚重衣物包裹灭火</li></ol><h3>如果被困无法逃离</h3><ul><li>用湿布堵住门缝和通风口</li><li>拨打119报告自己的具体位置(楼层、房间)</li><li>在窗边挥舞鲜艳衣物发出求救信号</li></ul><h2>三、灭火器使用——"提拔我呀"(提-拔-握-压)</h2><ol><li><strong>提:</strong>提起灭火器</li><li><strong>拔:</strong>拔掉保险销</li><li><strong>握:</strong>握住喷管前端,对准<strong>火焰根部</strong></li><li><strong>压:</strong>压下压把扫射</li></ol><p>站位:站在<strong>上风方向</strong>,距火源2-3米。</p><h2>四、家庭火灾预防</h2><ul><li>安装烟雾报警器(每个卧室+每层至少一个)</li><li>制定家庭逃生计划,确定集合点</li><li>不超负荷用电,不私拉乱接电线</li><li>厨房烹饪不离人,楼道勿堆放杂物</li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 3234, 567, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES020',
|
||||||
|
'道路交通事故现场的检伤分类与急救',
|
||||||
|
'交通事故现场混乱,伤者多,资源有限。了解检伤分类原则和基本急救技术,在专业救援到达前做最有效的处置。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT008',
|
||||||
|
'道路交通事故,尤其是多车相撞、多人受伤的复杂事故现场',
|
||||||
|
'TAG020',
|
||||||
|
'<h2>一、现场安全第一</h2><ul><li>将车辆熄火,拉手刹</li><li>在来车方向设置警示标志(高速路白天150米外,夜间250米外)</li><li>注意燃油泄漏、电线掉落等次生危险</li><li>不要吸烟</li></ul><h2>二、检伤分类(国际通用四色法)</h2><table border="1"><tr><th>颜色</th><th>优先级</th><th>标准</th></tr><tr><td>🔴 红色</td><td>第一优先</td><td>有生命危险但可救治:气道梗阻、张力性气胸、大出血</td></tr><tr><td>🟡 黄色</td><td>第二优先</td><td>重伤但可等待:骨折(无大出血)、脊柱损伤(稳定)</td></tr><tr><td>🟢 绿色</td><td>第三优先</td><td>轻伤可步行:轻微擦伤、软组织挫伤</td></tr><tr><td>⚫ 黑色</td><td>最后</td><td>无生命体征或伤势不可救治</td></tr></table><h2>三、车祸伤员的急救要点</h2><h3>A - 气道管理</h3><ul><li>托下颌开放气道(车祸伤员高度怀疑颈椎损伤,<strong>不要仰头</strong>)</li><li>清除口腔血液和异物</li></ul><h3>B - 呼吸评估</h3><ul><li>观察呼吸频率、对称性</li><li>张力性气胸:呼吸困难+气管偏移+患侧呼吸音消失→需紧急穿刺减压</li></ul><h3>C - 循环与止血</h3><ul><li>控制活动性出血</li><li>评估休克:皮肤苍白湿冷、烦躁不安、脉搏细弱加快</li></ul><h3>D - 脊柱保护</h3><ul><li>除非有立即生命危险,<strong>不要移动伤员</strong></li><li>如必须移动,保持头-颈-躯干轴线不变</li></ul><h2>四、不要做的事</h2><ul><li><strong>❌ 不要给伤者喝水</strong>(可能需紧急手术)</li><li><strong>❌ 不要取出插入体内的异物</strong>(固定后送医)</li><li><strong>❌ 不要将头盔从摩托车手头上摘下</strong>(可能加重颈椎损伤)</li><li><strong>❌ 不要一个人逞强</strong>——分配任务:A打120,B设置警示,C照护伤员</li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 1876, 312, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES021',
|
||||||
|
'地震自救互救"十要点"',
|
||||||
|
'新疆地处地震带,地震风险不容忽视。掌握地震中"伏地、遮挡、手抓牢"的避险原则和震后自救互救技能。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT008',
|
||||||
|
'地震发生时和震后的自救互救',
|
||||||
|
'TAG019',
|
||||||
|
'<h2>一、地震发生时——室内避险</h2><h3>"伏地、遮挡、手抓牢"(Drop-Cover-Hold On)</h3><ol><li><strong>伏地(Drop):</strong>立即蹲下,降低重心</li><li><strong>遮挡(Cover):</strong>钻到牢固的桌子下,或靠在内墙墙角,用双臂/书包/靠垫护住头颈部</li><li><strong>手抓牢(Hold On):</strong>一只手抓住桌腿等固定物,直到晃动停止</li></ol><h3>室内避震"三不"</h3><ul><li><strong>不要站在窗户边</strong>(玻璃飞溅)</li><li><strong>不要乘坐电梯</strong></li><li><strong>不要躲在吊灯、吊扇、高大家具下方</strong></li></ul><h2>二、地震发生时——室外避险</h2><ul><li>远离建筑物、电线杆、广告牌,跑到开阔地带</li><li>如果在开车:靠边停车(避开桥梁、高架、隧道),留在车内</li></ul><h2>三、震后自救</h2><ul><li>保持镇静,不要使用明火(可能发生燃气泄漏)</li><li>如被埋压:<ul><li>清除口鼻灰尘,保持呼吸通畅</li><li>用衣物捂住口鼻,防止吸入粉尘</li><li><strong>不要大声呼喊</strong>(消耗体力和氧气)——用敲击管道、墙壁的方式发出信号</li><li>有规律敲击("三短三长三短"SOS)</li></ul></li></ul><h2>四、震后互救</h2><ol><li>先救近处的、容易救的——"先易后难"</li><li>救人时注意被埋压者的头部暴露和呼吸道清理</li><li>不可用利器强力刨挖,防止二次伤害</li><li>救出后评估伤势并给予基本急救</li></ol><h2>五、地震应急包(建议备好)</h2><ul><li>饮用水(每人每天4L,备3天)、干粮、急救包</li><li>手电筒+备用电池、口哨(求救用)</li><li>防尘口罩、保温毯</li><li>重要证件复印件</li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 2456, 423, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO QH_EME_FIR_AID_RES (ID, TITLE, SUMMARY, CONTENT_TYPE, CATEGORY_ID, APPLICABLE_SCENARIO, TAGS, CONTENT, COVER_IMAGE, FILE_URL, EFFECTIVE_TIME, EXPIRY_TIME, AUDIT_STATUS, AUDIT_REJECT_REASON, AUDIT_BY, AUDIT_TIME, VIEW_COUNT, FAVORITE_COUNT, STATUS, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, DEL_FLAG)
|
||||||
|
VALUES (
|
||||||
|
'RES022',
|
||||||
|
'家庭急救箱的配置与使用指南',
|
||||||
|
'急救箱是每个家庭和车辆的必备品。了解急救箱应该有哪些物品、如何存放、过期如何处理,才能在紧急时刻真正发挥作用。',
|
||||||
|
'IMAGE_TEXT',
|
||||||
|
'CAT004',
|
||||||
|
'家庭日常备置急救箱及发生轻微伤情时的处理',
|
||||||
|
'TAG011',
|
||||||
|
'<h2>一、基础急救箱清单</h2><h3>包扎材料</h3><ol><li>医用纱布片(无菌,各种尺寸)x 10片</li><li>弹性绷带(5cm、8cm各2卷)</li><li>三角巾 x 2条</li><li>创可贴(各种尺寸)x 20片</li><li>医用胶带(透气型)x 1卷</li></ol><h3>消毒用品</h3><ol><li>碘伏棉签/棉球 x 20支</li><li>75%酒精棉片 x 20片</li><li>一次性手套(无粉)x 5双</li></ol><h3>工具</h3><ol><li>圆头剪刀 x 1把</li><li>镊子 x 1把</li><li>体温计(电子或红外)x 1支</li><li>安全别针 x 5个</li><li>一次性冰袋(捏破即冷型)x 2袋</li></ol><h3>药品(需根据家庭成员情况调整)</h3><ol><li>退热镇痛药:对乙酰氨基酚/布洛芬</li><li>抗过敏药:氯雷他定/西替利嗪</li><li>止泻药:蒙脱石散/口服补液盐</li><li>烫伤膏</li><li>抗生素软膏(莫匹罗星)</li><li>个人常备药(硝酸甘油、哮喘吸入剂等)</li></ol><h2>二、急救箱管理要点</h2><ul><li>存放在<strong>阴凉干燥、儿童拿不到但成人方便取用</strong>的地方</li><li>每<strong>3-6个月</strong>检查一次,更换过期物品</li><li>车用急救箱与家用分开</li><li>箱外标注最近医院的地址和电话</li><li>在家人中指定一人负责维护</li></ul><h2>三、急救包的使用禁忌</h2><ul><li><strong>不要给不明原因腹痛者服用止痛药</strong>(可能掩盖阑尾炎等急腹症)</li><li><strong>不要使用过期消毒液和药品</strong></li><li><strong>不要共用眼药水</strong></li><li>任何开放性伤口,确认破伤风疫苗接种在有效期(<5年清洁伤,<10年污染伤)</li></ul>',
|
||||||
|
NULL, NULL,
|
||||||
|
DATE '2026-07-01', DATE '2027-12-31',
|
||||||
|
11, NULL, '系统管理员', SYSDATE, 5432, 1023, 1,
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
);
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
-- =====================================================
|
||||||
|
-- 验证数据
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
-- 查看各分类及其下属标签
|
||||||
|
SELECT
|
||||||
|
c."NAME" AS 分类名称,
|
||||||
|
LISTAGG(t."NAME", '、') WITHIN GROUP (ORDER BY t."SORT_NO") AS 下属标签
|
||||||
|
FROM QH_EME_FIR_AID_RES_CATE c
|
||||||
|
LEFT JOIN QH_EME_FIR_AID_RES_CATE t ON t."PARENT_ID" = c."ID" AND t."TYPE" = 2 AND t."DEL_FLAG" = 0
|
||||||
|
WHERE c."TYPE" = 1 AND c."DEL_FLAG" = 0
|
||||||
|
GROUP BY c."ID", c."NAME", c."SORT_NO"
|
||||||
|
ORDER BY c."SORT_NO";
|
||||||
|
|
||||||
|
-- 统计
|
||||||
|
SELECT '分类' AS 统计项, COUNT(*) AS 数量 FROM QH_EME_FIR_AID_RES_CATE WHERE "TYPE" = 1 AND "DEL_FLAG" = 0
|
||||||
|
UNION ALL
|
||||||
|
SELECT '标签', COUNT(*) FROM QH_EME_FIR_AID_RES_CATE WHERE "TYPE" = 2 AND "DEL_FLAG" = 0
|
||||||
|
UNION ALL
|
||||||
|
SELECT '资源', COUNT(*) FROM QH_EME_FIR_AID_RES WHERE "DEL_FLAG" = 0;
|
||||||
@@ -6,6 +6,7 @@ import com.renkang.im.dto.AddGroupMemberDTO;
|
|||||||
import com.renkang.im.dto.DeleteGroupMemberDTO;
|
import com.renkang.im.dto.DeleteGroupMemberDTO;
|
||||||
import com.renkang.im.entity.*;
|
import com.renkang.im.entity.*;
|
||||||
import com.renkang.im.vo.AddGroupMemberVO;
|
import com.renkang.im.vo.AddGroupMemberVO;
|
||||||
|
import com.renkang.im.vo.GetGroupMemberInfoVO;
|
||||||
import com.renkang.im.vo.ImBaseResult;
|
import com.renkang.im.vo.ImBaseResult;
|
||||||
import org.jeecg.common.api.vo.Result;
|
import org.jeecg.common.api.vo.Result;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
@@ -47,6 +48,9 @@ public interface IMHelloApi {
|
|||||||
@PostMapping(value = "/wnapp/sendGroupMsg")
|
@PostMapping(value = "/wnapp/sendGroupMsg")
|
||||||
IMGroupMsgResDO sendGroupMsg(@RequestBody @Validated ImGroupMsgTextReqDO imGroupMsgTextReqDO);
|
IMGroupMsgResDO sendGroupMsg(@RequestBody @Validated ImGroupMsgTextReqDO imGroupMsgTextReqDO);
|
||||||
|
|
||||||
|
@PostMapping(value = "/wnapp/sendGroupMsgArticle")
|
||||||
|
IMGroupMsgResDO sendGroupMsgArticle(@RequestBody @Validated ImGroupMsgTextReqDO imGroupMsgTextReqDO);
|
||||||
|
|
||||||
@PostMapping(value = "/wnapp/sendGroupMsgTextNew")
|
@PostMapping(value = "/wnapp/sendGroupMsgTextNew")
|
||||||
IMGroupMsgResDO sendGroupMsgTextNew(@RequestBody @Validated ImGroupMsgTextReqDO imGroupMsgTextReqDO);
|
IMGroupMsgResDO sendGroupMsgTextNew(@RequestBody @Validated ImGroupMsgTextReqDO imGroupMsgTextReqDO);
|
||||||
|
|
||||||
@@ -81,6 +85,14 @@ public interface IMHelloApi {
|
|||||||
@GetMapping("/wnapp/destroyGroup")
|
@GetMapping("/wnapp/destroyGroup")
|
||||||
Result<ImBaseResult> destroyGroup(@RequestParam("groupId") String groupId);
|
Result<ImBaseResult> destroyGroup(@RequestParam("groupId") String groupId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 获取群成员详细资料
|
||||||
|
* @author PengJ
|
||||||
|
* @date 2026/7/7
|
||||||
|
*/
|
||||||
|
@GetMapping(value = "/wnapp/getGroupMemberInfo")
|
||||||
|
Result<GetGroupMemberInfoVO> getGroupMemberInfo(@RequestParam("groupId") String groupId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description: 删除群成员
|
* @description: 删除群成员
|
||||||
* @author PengJ
|
* @author PengJ
|
||||||
|
|||||||
@@ -50,5 +50,15 @@ public class AddGroupMemberDTO {
|
|||||||
@NotNull(message = "群成员ID不能为空")
|
@NotNull(message = "群成员ID不能为空")
|
||||||
@JsonProperty("Member_Account")
|
@JsonProperty("Member_Account")
|
||||||
private String memberAccount;
|
private String memberAccount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 群成员名称(可选,仅用于IM账号导入,不发送到腾讯IM)
|
||||||
|
*/
|
||||||
|
private String memberName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 群成员头像URL(可选,仅用于IM账号导入,不发送到腾讯IM)
|
||||||
|
*/
|
||||||
|
private String memberAvatar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package com.renkang.im.vo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author PengJ
|
||||||
|
* @version 1.0
|
||||||
|
* @description: 获取群成员详细资料响应VO
|
||||||
|
* @date 2026/7/7
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
public class GetGroupMemberInfoVO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求处理的结果
|
||||||
|
* OK:表示处理成功。
|
||||||
|
* FAIL:表示失败。
|
||||||
|
*/
|
||||||
|
@JsonProperty("ActionStatus")
|
||||||
|
private String actionStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误信息
|
||||||
|
*/
|
||||||
|
@JsonProperty("ErrorInfo")
|
||||||
|
private String errorInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误码
|
||||||
|
* 0:表示成功。
|
||||||
|
* 非0:表示失败。
|
||||||
|
*/
|
||||||
|
@JsonProperty("ErrorCode")
|
||||||
|
private Integer errorCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本群组的群成员总数
|
||||||
|
*/
|
||||||
|
@JsonProperty("MemberNum")
|
||||||
|
private Integer memberNum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 群成员列表
|
||||||
|
*/
|
||||||
|
@JsonProperty("MemberList")
|
||||||
|
private List<MemberInfo> memberList;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
public static class MemberInfo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 群成员 UserID
|
||||||
|
*/
|
||||||
|
@JsonProperty("Member_Account")
|
||||||
|
private String memberAccount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 群内身份:Owner/Admin/Member
|
||||||
|
*/
|
||||||
|
@JsonProperty("Role")
|
||||||
|
private String role;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 入群时间
|
||||||
|
*/
|
||||||
|
@JsonProperty("JoinTime")
|
||||||
|
private Integer joinTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import com.renkang.im.util.IdWorker;
|
|||||||
import com.renkang.im.util.TencentCloudImUtil;
|
import com.renkang.im.util.TencentCloudImUtil;
|
||||||
import com.renkang.im.util.UniqId;
|
import com.renkang.im.util.UniqId;
|
||||||
import com.renkang.im.vo.AddGroupMemberVO;
|
import com.renkang.im.vo.AddGroupMemberVO;
|
||||||
|
import com.renkang.im.vo.GetGroupMemberInfoVO;
|
||||||
import com.renkang.im.vo.ImBaseResult;
|
import com.renkang.im.vo.ImBaseResult;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
@@ -246,6 +247,14 @@ public class TXController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Operation(summary = "文章推送群消息(宣教推送专用)", description = "发送方由调用方指定,不覆盖businessID")
|
||||||
|
@PostMapping("/sendGroupMsgArticle")
|
||||||
|
public IMGroupMsgResDO sendGroupMsgArticle(@RequestBody @Validated ImGroupMsgTextReqDO imGroupMsgTextReqDO) {
|
||||||
|
|
||||||
|
return tencentCloudImUtil.sendGroupMsgArticle(imGroupMsgTextReqDO);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Operation(summary = "用户发送群消息", description = "用户发送群消息")
|
@Operation(summary = "用户发送群消息", description = "用户发送群消息")
|
||||||
@PostMapping("/sendGroupMsgTextNew")
|
@PostMapping("/sendGroupMsgTextNew")
|
||||||
public IMGroupMsgResDO sendGroupMsgTextNew(@RequestBody @Validated ImGroupMsgTextReqDO imGroupMsgTextReqDO) {
|
public IMGroupMsgResDO sendGroupMsgTextNew(@RequestBody @Validated ImGroupMsgTextReqDO imGroupMsgTextReqDO) {
|
||||||
@@ -330,7 +339,7 @@ public class TXController {
|
|||||||
groupList.add(hashMap);
|
groupList.add(hashMap);
|
||||||
});
|
});
|
||||||
|
|
||||||
String result = tencentCloudImUtil.creatGroup(Owner_Account, Type, GroupId, conSessionRequestDO.getName() + "_" + DateUtils.getCurrentTimestamp(), groupList);
|
String result = tencentCloudImUtil.creatGroup(Owner_Account, Type, GroupId, "应急求助", groupList);
|
||||||
if (!JSONObject.parseObject(result).get("ErrorCode").equals(0)) {
|
if (!JSONObject.parseObject(result).get("ErrorCode").equals(0)) {
|
||||||
return Result.error("创建群聊失败!");
|
return Result.error("创建群聊失败!");
|
||||||
}
|
}
|
||||||
@@ -381,7 +390,7 @@ public class TXController {
|
|||||||
groupList.add(hashMap);
|
groupList.add(hashMap);
|
||||||
});
|
});
|
||||||
|
|
||||||
String result = tencentCloudImUtil.creatGroup(Owner_Account, Type, GroupId, conSessionRequestDO.getName() + "_" + DateUtils.getCurrentTimestamp(), groupList);
|
String result = tencentCloudImUtil.creatGroup(Owner_Account, Type, GroupId, "应急求助", groupList);
|
||||||
if (!JSONObject.parseObject(result).get("ErrorCode").equals(0)) {
|
if (!JSONObject.parseObject(result).get("ErrorCode").equals(0)) {
|
||||||
return Result.error("创建群聊失败!");
|
return Result.error("创建群聊失败!");
|
||||||
}
|
}
|
||||||
@@ -411,6 +420,12 @@ public class TXController {
|
|||||||
return Result.OK(tencentCloudImUtil.destroyGroup(groupId));
|
return Result.OK(tencentCloudImUtil.destroyGroup(groupId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "获取群成员详细资料", description = "获取群成员详细资料")
|
||||||
|
@GetMapping("/getGroupMemberInfo")
|
||||||
|
public Result<GetGroupMemberInfoVO> getGroupMemberInfo(@RequestParam("groupId") String groupId) {
|
||||||
|
return Result.OK(tencentCloudImUtil.getGroupMemberInfo(groupId));
|
||||||
|
}
|
||||||
|
|
||||||
private String encodeChineseCharacters(String str) {
|
private String encodeChineseCharacters(String str) {
|
||||||
return str.codePoints()
|
return str.codePoints()
|
||||||
.mapToObj(c -> {
|
.mapToObj(c -> {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import com.renkang.im.dto.AddGroupMemberDTO;
|
|||||||
import com.renkang.im.dto.DeleteGroupMemberDTO;
|
import com.renkang.im.dto.DeleteGroupMemberDTO;
|
||||||
import com.renkang.im.entity.*;
|
import com.renkang.im.entity.*;
|
||||||
import com.renkang.im.vo.AddGroupMemberVO;
|
import com.renkang.im.vo.AddGroupMemberVO;
|
||||||
|
import com.renkang.im.vo.GetGroupMemberInfoVO;
|
||||||
import com.renkang.im.vo.ImBaseResult;
|
import com.renkang.im.vo.ImBaseResult;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.RandomUtils;
|
import org.apache.commons.lang3.RandomUtils;
|
||||||
@@ -47,10 +48,12 @@ public class TencentCloudImUtil {
|
|||||||
@Value("${IMConfig.requestUrl}")
|
@Value("${IMConfig.requestUrl}")
|
||||||
private String HTTPS_URL_PREFIX;
|
private String HTTPS_URL_PREFIX;
|
||||||
private static final String APP_MANAGER = "administrator";
|
private static final String APP_MANAGER = "administrator";
|
||||||
private static final String REDIS_IM_USER_SIG = "silence:im_user_sig:";
|
private static final String REDIS_IM_USER_SIG_PREFIX = "silence:im_user_sig:";
|
||||||
|
|
||||||
@Value("${IMConfig.sdkAppId}")
|
@Value("${IMConfig.sdkAppId}")
|
||||||
private long sdkAppId;
|
private long sdkAppId;
|
||||||
|
@Value("${IMConfig.secretKey}")
|
||||||
|
private String secretKey;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private TximUtil tximUtil;
|
private TximUtil tximUtil;
|
||||||
@@ -72,23 +75,37 @@ public class TencentCloudImUtil {
|
|||||||
return System.currentTimeMillis() + "" + StrUtil.subSuf(Math.random() + "", 2);
|
return System.currentTimeMillis() + "" + StrUtil.subSuf(Math.random() + "", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取IM配置指纹,用于区分不同配置的缓存
|
||||||
|
* 当 sdkAppId 或 secretKey 变更时指纹变化,旧缓存自动失效
|
||||||
|
*/
|
||||||
|
private String getConfigFingerprint() {
|
||||||
|
return Integer.toHexString(Objects.hash(sdkAppId, secretKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildUserSigKey(String identifier) {
|
||||||
|
return REDIS_IM_USER_SIG_PREFIX + getConfigFingerprint() + ":" + identifier;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取腾讯云用户签名
|
* 获取腾讯云用户签名
|
||||||
*/
|
*/
|
||||||
public String getTxCloudUserSig() {
|
public String getTxCloudUserSig() {
|
||||||
String userSig = (String) redisServiceUtil.get(REDIS_IM_USER_SIG + APP_MANAGER);
|
String key = buildUserSigKey(APP_MANAGER);
|
||||||
|
String userSig = (String) redisServiceUtil.get(key);
|
||||||
if (StringUtils.isEmpty(userSig)) {
|
if (StringUtils.isEmpty(userSig)) {
|
||||||
userSig = tximUtil.genUserSig(APP_MANAGER);
|
userSig = tximUtil.genUserSig(APP_MANAGER);
|
||||||
redisServiceUtil.set(REDIS_IM_USER_SIG + APP_MANAGER, userSig, 86400L);
|
redisServiceUtil.set(key, userSig, 86400L);
|
||||||
}
|
}
|
||||||
return userSig;
|
return userSig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String userSigAndroid(String userId) {
|
public String userSigAndroid(String userId) {
|
||||||
String userSig = (String) redisServiceUtil.get(REDIS_IM_USER_SIG + userId);
|
String key = buildUserSigKey(userId);
|
||||||
|
String userSig = (String) redisServiceUtil.get(key);
|
||||||
if (StringUtils.isEmpty(userSig)) {
|
if (StringUtils.isEmpty(userSig)) {
|
||||||
userSig = tximUtil.genUserSig(userId);
|
userSig = tximUtil.genUserSig(userId);
|
||||||
redisServiceUtil.set(REDIS_IM_USER_SIG + userId, userSig, 86400L);
|
redisServiceUtil.set(key, userSig, 86400L);
|
||||||
}
|
}
|
||||||
return userSig;
|
return userSig;
|
||||||
}
|
}
|
||||||
@@ -157,6 +174,22 @@ public class TencentCloudImUtil {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入多个账号(带昵称)
|
||||||
|
*
|
||||||
|
* @param accounts 账号信息列表,每个元素包含 UserID 和可选的 Nick
|
||||||
|
*/
|
||||||
|
public String importAccountsWithNames(List<JSONObject> accounts) {
|
||||||
|
Integer random = RandomUtils.nextInt(0, 999999999);
|
||||||
|
String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.AccountManage.MULTI_ACCOUNT_IMPORT, random);
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
jsonObject.put("AccountList", accounts);
|
||||||
|
log.info("腾讯云im导入多个账号,请求参数:{}", jsonObject);
|
||||||
|
String result = HttpUtil.doPost(httpsUrl, jsonObject);
|
||||||
|
log.info("腾讯云im导入多个账户,返回结果:{}", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除账号
|
* 删除账号
|
||||||
*
|
*
|
||||||
@@ -271,6 +304,63 @@ public class TencentCloudImUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送文章推送群消息(宣教推送专用)
|
||||||
|
* <p>
|
||||||
|
* 与 sendGroupMsgText 的区别:
|
||||||
|
* 1. From_Account 由调用方指定,不写死为 administrator
|
||||||
|
* 2. 不覆盖 businessID,保留调用方传入的业务标识
|
||||||
|
* 3. CloudCustomData.fromAdmin 根据实际发送人动态设置
|
||||||
|
*
|
||||||
|
* @param req 消息请求
|
||||||
|
* @return IMGroupMsgResDO
|
||||||
|
*/
|
||||||
|
public IMGroupMsgResDO sendGroupMsgArticle(ImGroupMsgTextReqDO req) {
|
||||||
|
IMGroupMsgResDO res = new IMGroupMsgResDO();
|
||||||
|
String url = HTTPS_URL_PREFIX + "v4/group_open_http_svc/send_group_msg";
|
||||||
|
|
||||||
|
String fromUserId = req.getFromUserId();
|
||||||
|
boolean isAdmin = "administrator".equals(fromUserId);
|
||||||
|
|
||||||
|
JSONObject param = new JSONObject();
|
||||||
|
param.put("GroupId", req.getGroupId());
|
||||||
|
param.put("MsgPriority", "High");
|
||||||
|
param.put("Random", this.getRandom());
|
||||||
|
param.put("From_Account", fromUserId);
|
||||||
|
param.put("MsgRandom", this.getRandomNum(8));
|
||||||
|
param.put("MsgTimeStamp", DateUtils.dateToUnixLong(new Date()));
|
||||||
|
param.put("CloudCustomData", new JSONObject().fluentPut("fromAdmin", isAdmin).toJSONString());
|
||||||
|
|
||||||
|
JSONObject jj = JSONObject.parseObject(req.getContent());
|
||||||
|
// 保持与 sendGroupMsgText 一致的协议字段,客户端依赖 businessID 识别消息类型
|
||||||
|
jj.put("businessID", "article");
|
||||||
|
try {
|
||||||
|
JSONObject item = new JSONObject();
|
||||||
|
JSONObject msgContentData = new JSONObject();
|
||||||
|
msgContentData.put("Data", jj.toString());
|
||||||
|
item.put("MsgType", ImSendEnum.TIMCustomElem.getValue());
|
||||||
|
item.put("MsgContent", msgContentData);
|
||||||
|
JSONArray msgBody = new JSONArray();
|
||||||
|
msgBody.add(item);
|
||||||
|
param.put("MsgBody", msgBody);
|
||||||
|
log.info("文章推送请求参数: GroupId={}, From_Account={}, content={}, CloudCustomData={}",
|
||||||
|
req.getGroupId(), fromUserId, jj.toString(),
|
||||||
|
param.getString("CloudCustomData"));
|
||||||
|
String jsonStr = HttpUtil.doPost(buildRequestUrl(url), param.toString());
|
||||||
|
if (StringUtils.isNotEmpty(jsonStr)) {
|
||||||
|
JSONObject jsonObj = JSONObject.parseObject(jsonStr);
|
||||||
|
if (jsonObj.containsKey("ErrorCode") && jsonObj.getInteger("ErrorCode") == 0) {
|
||||||
|
log.info("=========={}==========", "文章推送发送成功!");
|
||||||
|
}
|
||||||
|
res = JsonUtil.toObject(jsonStr, IMGroupMsgResDO.class);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认单发发群文本消息
|
* 默认单发发群文本消息
|
||||||
*
|
*
|
||||||
@@ -462,13 +552,36 @@ public class TencentCloudImUtil {
|
|||||||
*/
|
*/
|
||||||
public AddGroupMemberVO addGroupMember(AddGroupMemberDTO dto) {
|
public AddGroupMemberVO addGroupMember(AddGroupMemberDTO dto) {
|
||||||
try {
|
try {
|
||||||
|
// 先导入账号及其名称,确保成员在IM系统中已注册
|
||||||
|
if (dto.getMemberList() != null && !dto.getMemberList().isEmpty()) {
|
||||||
|
// 构建腾讯IM新版 AccountList 格式(含昵称和头像)
|
||||||
|
List<JSONObject> accountList = dto.getMemberList().stream().map(member -> {
|
||||||
|
JSONObject account = new JSONObject();
|
||||||
|
account.put("UserID", member.getMemberAccount());
|
||||||
|
if (StringUtils.isNotEmpty(member.getMemberName())) {
|
||||||
|
account.put("Nick", member.getMemberName());
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(member.getMemberAvatar())) {
|
||||||
|
account.put("FaceUrl", member.getMemberAvatar());
|
||||||
|
}
|
||||||
|
return account;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
importAccountsWithNames(accountList);
|
||||||
|
}
|
||||||
|
|
||||||
Integer random = RandomUtils.nextInt(0, 999999999);
|
Integer random = RandomUtils.nextInt(0, 999999999);
|
||||||
String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.GroupManage.ADD_GROUP_MEMBER, random);
|
String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.GroupManage.ADD_GROUP_MEMBER, random);
|
||||||
String jsonString = objectMapper.writeValueAsString(dto);
|
String jsonString = objectMapper.writeValueAsString(dto);
|
||||||
JSONObject jsonObject = JSONObject.parseObject(jsonString);
|
JSONObject jsonObject = JSONObject.parseObject(jsonString);
|
||||||
// JSONObject jsonObject = new JSONObject();
|
// 移除内部字段,腾讯IM API 不接受
|
||||||
// jsonObject.put("GroupId", dto.getGroupId());
|
JSONArray memberList = jsonObject.getJSONArray("MemberList");
|
||||||
// jsonObject.put("MemberList", dto.getMemberList());
|
if (memberList != null) {
|
||||||
|
for (int i = 0; i < memberList.size(); i++) {
|
||||||
|
JSONObject member = memberList.getJSONObject(i);
|
||||||
|
member.remove("memberName");
|
||||||
|
member.remove("memberAvatar");
|
||||||
|
}
|
||||||
|
}
|
||||||
log.info("腾讯云im添加群成员,请求参数:{}", jsonObject);
|
log.info("腾讯云im添加群成员,请求参数:{}", jsonObject);
|
||||||
String result = HttpUtil.doPost(httpsUrl, jsonObject);
|
String result = HttpUtil.doPost(httpsUrl, jsonObject);
|
||||||
log.info("腾讯云im添加群成员,返回结果:{}", result);
|
log.info("腾讯云im添加群成员,返回结果:{}", result);
|
||||||
@@ -506,6 +619,30 @@ public class TencentCloudImUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取群成员详细资料
|
||||||
|
*
|
||||||
|
* @param groupId 群组ID
|
||||||
|
* @return GetGroupMemberInfoVO
|
||||||
|
*/
|
||||||
|
public GetGroupMemberInfoVO getGroupMemberInfo(String groupId) {
|
||||||
|
try {
|
||||||
|
Integer random = RandomUtils.nextInt(0, 999999999);
|
||||||
|
String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.GroupManage.GET_GROUP_MEMBER_INFO, random);
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
jsonObject.put("GroupId", groupId);
|
||||||
|
log.info("腾讯云im【获取群成员详细资料】,请求参数:{}", jsonObject);
|
||||||
|
String result = HttpUtil.doPost(httpsUrl, jsonObject);
|
||||||
|
log.info("腾讯云im【获取群成员详细资料】,返回结果:{}", result);
|
||||||
|
return JSONObject.toJavaObject(JSONObject.parseObject(result), GetGroupMemberInfoVO.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("【获取群成员详细资料】异常:{}", e.getMessage());
|
||||||
|
GetGroupMemberInfoVO vo = new GetGroupMemberInfoVO();
|
||||||
|
vo.setActionStatus("FAIL");
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除群成员
|
* 删除群成员
|
||||||
*
|
*
|
||||||
|
|||||||
+14
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
+14
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
+15
@@ -44,6 +44,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
@@ -38,6 +38,17 @@ public interface IWatchMonitorDataService extends IService<WatchMonitorData> {
|
|||||||
*/
|
*/
|
||||||
AjaxJson notice(JSONObject jsonObject);
|
AjaxJson notice(JSONObject jsonObject);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新告警事件GPS位置信息
|
||||||
|
* 根据 watchNo + eventId 联合定位已有告警数据;
|
||||||
|
* 缺失任一定位字段则忽略;已存在GPS信息则忽略;
|
||||||
|
* 仅更新数据,不推送大屏与短信。
|
||||||
|
*
|
||||||
|
* @param jsonObject 入参(含 watchNo、eventId、lon、lat、address、locateTime、gpsErrorMsg 等)
|
||||||
|
* @return 处理结果
|
||||||
|
*/
|
||||||
|
AjaxJson updateMonitorGps(JSONObject jsonObject);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理历史数据 orgCode为空的问题
|
* 处理历史数据 orgCode为空的问题
|
||||||
* @return
|
* @return
|
||||||
|
|||||||
+99
@@ -265,6 +265,102 @@ public class WatchMonitorDataServiceImpl extends ServiceImpl<WatchMonitorDataMap
|
|||||||
return ajaxJson;
|
return ajaxJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新告警事件GPS位置信息
|
||||||
|
* 根据 watchNo + eventId 联合定位已有告警数据;
|
||||||
|
* watchNo 或 eventId 任一缺失则忽略;
|
||||||
|
* 已存在 GPS 信息则忽略本次更新;
|
||||||
|
* 参考 createMonitorData 进行 GPS84 → GCJ02 坐标转换 + 高德地址反查;
|
||||||
|
* 仅更新数据,不推送大屏与短信。
|
||||||
|
*
|
||||||
|
* @param json 入参(含 watchNo、eventId、lon、lat、address、locateTime、gpsErrorMsg 等)
|
||||||
|
* @return 处理结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AjaxJson updateMonitorGps(JSONObject json) {
|
||||||
|
GlobalUtils.setHttpFeignToken();
|
||||||
|
|
||||||
|
AjaxJson ajaxJson = new AjaxJson();
|
||||||
|
logger.info("接收更新告警事件GPS信息=={}", json.toJSONString());
|
||||||
|
|
||||||
|
WatchNotifyVo data = json.toJavaObject(WatchNotifyVo.class);
|
||||||
|
|
||||||
|
// watchNo 或 eventId 任一缺失则忽略
|
||||||
|
if (StrUtil.isBlank(data.getWatchNo()) || StrUtil.isBlank(data.getEventId())) {
|
||||||
|
logger.warn("更新GPS信息缺失关键定位字段,忽略本次请求 watchNo={}, eventId={}", data.getWatchNo(), data.getEventId());
|
||||||
|
ajaxJson.setSuccess(true);
|
||||||
|
return ajaxJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
// watchNo + eventId 联合定位已有告警数据
|
||||||
|
LambdaQueryWrapper<WatchMonitorData> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.eq(WatchMonitorData::getWatchNo, data.getWatchNo())
|
||||||
|
.eq(WatchMonitorData::getEventId, data.getEventId());
|
||||||
|
List<WatchMonitorData> existList = this.list(queryWrapper);
|
||||||
|
if (CollUtil.isEmpty(existList)) {
|
||||||
|
logger.warn("更新GPS信息失败,未匹配到告警记录 watchNo={}, eventId={}", data.getWatchNo(), data.getEventId());
|
||||||
|
ajaxJson.setSuccess(true);
|
||||||
|
return ajaxJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 已存在GPS信息则忽略本次更新,避免覆盖已有有效坐标
|
||||||
|
boolean hasGps = existList.stream().anyMatch(m -> m.getLon() != null && m.getLat() != null);
|
||||||
|
if (hasGps) {
|
||||||
|
logger.info("告警记录已有GPS信息,忽略本次更新 watchNo={}, eventId={}", data.getWatchNo(), data.getEventId());
|
||||||
|
ajaxJson.setSuccess(true);
|
||||||
|
return ajaxJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算高德坐标与高德地址(参考 createMonitorData 逻辑)
|
||||||
|
WatchMonitorData updateEntity = new WatchMonitorData();
|
||||||
|
updateEntity.setLon(data.getLon());
|
||||||
|
updateEntity.setLat(data.getLat());
|
||||||
|
updateEntity.setAddress(data.getAddress());
|
||||||
|
updateEntity.setGpsErrorMsg(data.getGpsErrorMsg());
|
||||||
|
updateEntity.setLocateTime(data.getLocateTime());
|
||||||
|
|
||||||
|
if (Stream.of(data.getLon(), data.getLat()).allMatch(value -> ObjUtil.isNotEmpty(value) && value != 0)) {
|
||||||
|
Gps gps = GPS84ToGCJ02(data.getLon(), data.getLat());
|
||||||
|
if (null != gps) {
|
||||||
|
// 写入高德坐标
|
||||||
|
updateEntity.setLonGd(BigDecimal.valueOf(gps.getLongitude()));
|
||||||
|
updateEntity.setLatGd(BigDecimal.valueOf(gps.getLatitude()));
|
||||||
|
// 调用高德接口获取地址信息
|
||||||
|
AmapResultVo amapResultVo = amapService.getFormattedAddress(gps.getLongitude(), gps.getLatitude(), 5000);
|
||||||
|
if (amapResultVo.isSuccess()) {
|
||||||
|
updateEntity.setAddressGd(amapResultVo.getAddress());
|
||||||
|
updateEntity.setAddress(amapResultVo.getAddress());
|
||||||
|
} else {
|
||||||
|
String originError = StrUtil.isBlank(updateEntity.getGpsErrorMsg()) ? "" : updateEntity.getGpsErrorMsg() + ";";
|
||||||
|
updateEntity.setGpsErrorMsg(originError + amapResultVo.getErrorMsg());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 仅更新 GPS 相关字段,不推送大屏、不发短信
|
||||||
|
boolean updated = this.lambdaUpdate()
|
||||||
|
.eq(WatchMonitorData::getWatchNo, data.getWatchNo())
|
||||||
|
.eq(WatchMonitorData::getEventId, data.getEventId())
|
||||||
|
.set(WatchMonitorData::getLon, updateEntity.getLon())
|
||||||
|
.set(WatchMonitorData::getLat, updateEntity.getLat())
|
||||||
|
.set(WatchMonitorData::getAddress, updateEntity.getAddress())
|
||||||
|
.set(WatchMonitorData::getLonGd, updateEntity.getLonGd())
|
||||||
|
.set(WatchMonitorData::getLatGd, updateEntity.getLatGd())
|
||||||
|
.set(WatchMonitorData::getAddressGd, updateEntity.getAddressGd())
|
||||||
|
.set(WatchMonitorData::getGpsErrorMsg, updateEntity.getGpsErrorMsg())
|
||||||
|
.set(WatchMonitorData::getLocateTime, updateEntity.getLocateTime())
|
||||||
|
.update();
|
||||||
|
|
||||||
|
if (!updated) {
|
||||||
|
logger.warn("更新GPS信息失败 watchNo={}, eventId={}", data.getWatchNo(), data.getEventId());
|
||||||
|
} else {
|
||||||
|
logger.info("更新GPS信息成功 watchNo={}, eventId={}, 共更新{}条", data.getWatchNo(), data.getEventId(), existList.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
ajaxJson.setSuccess(true);
|
||||||
|
return ajaxJson;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建异常数据
|
* 构建异常数据
|
||||||
*
|
*
|
||||||
@@ -272,13 +368,16 @@ public class WatchMonitorDataServiceImpl extends ServiceImpl<WatchMonitorDataMap
|
|||||||
* @return 异常数据
|
* @return 异常数据
|
||||||
*/
|
*/
|
||||||
private WatchMonitorData createMonitorData(WatchNotifyVo data) {
|
private WatchMonitorData createMonitorData(WatchNotifyVo data) {
|
||||||
|
|
||||||
log.info("开始构建异常数据 => {}", JSONObject.toJSONString(data));
|
log.info("开始构建异常数据 => {}", JSONObject.toJSONString(data));
|
||||||
WatchMonitorData monitorDataEntity = new WatchMonitorData();
|
WatchMonitorData monitorDataEntity = new WatchMonitorData();
|
||||||
monitorDataEntity.setAddress(data.getAddress());
|
monitorDataEntity.setAddress(data.getAddress());
|
||||||
monitorDataEntity.setWatchNo(data.getWatchNo());
|
monitorDataEntity.setWatchNo(data.getWatchNo());
|
||||||
monitorDataEntity.setLon(data.getLon());
|
monitorDataEntity.setLon(data.getLon());
|
||||||
monitorDataEntity.setLat(data.getLat());
|
monitorDataEntity.setLat(data.getLat());
|
||||||
|
monitorDataEntity.setLocateTime(data.getLocateTime());
|
||||||
monitorDataEntity.setEventType(data.getEventType());
|
monitorDataEntity.setEventType(data.getEventType());
|
||||||
|
monitorDataEntity.setEventId(data.getEventId());
|
||||||
monitorDataEntity.setDataValue(data.getDataValue());
|
monitorDataEntity.setDataValue(data.getDataValue());
|
||||||
monitorDataEntity.setCreateDate(data.getCreateTime());
|
monitorDataEntity.setCreateDate(data.getCreateTime());
|
||||||
monitorDataEntity.setWarnTime(data.getWarnTime());
|
monitorDataEntity.setWarnTime(data.getWarnTime());
|
||||||
|
|||||||
+7
-1
@@ -42,6 +42,7 @@ import org.jeecgframework.poi.excel.entity.params.ExcelExportEntity;
|
|||||||
import org.jeecgframework.poi.exception.excel.enums.ExcelExportEnum;
|
import org.jeecgframework.poi.exception.excel.enums.ExcelExportEnum;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.core.task.AsyncTaskExecutor;
|
import org.springframework.core.task.AsyncTaskExecutor;
|
||||||
|
import org.springframework.dao.DuplicateKeyException;
|
||||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@@ -208,7 +209,12 @@ public class WatchUserDataServiceImpl extends ServiceImpl<WatchUserDataMapper, W
|
|||||||
watchUserData.setDataDate(bindDateSave);
|
watchUserData.setDataDate(bindDateSave);
|
||||||
watchUserData.setWatchNo(watchNo);
|
watchUserData.setWatchNo(watchNo);
|
||||||
watchUserData.setCreateDate(new Date());
|
watchUserData.setCreateDate(new Date());
|
||||||
this.save(watchUserData);
|
try {
|
||||||
|
this.save(watchUserData);
|
||||||
|
} catch (DuplicateKeyException e) {
|
||||||
|
//并发上报同一手表同一天数据时,先删后插存在竞态,另一线程已插入相同记录,忽略即可
|
||||||
|
log.warn("QH_WAT_USER_DATA并发写入冲突,已忽略: watchNo={}, dataDate={}", watchNo, s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
// @Override
|
||||||
|
|||||||
@@ -43,6 +43,14 @@
|
|||||||
<enabled>true</enabled>
|
<enabled>true</enabled>
|
||||||
</snapshots>
|
</snapshots>
|
||||||
</repository>
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>yixiong-tech</id>
|
||||||
|
<name>yixiong-tech Repository</name>
|
||||||
|
<url>https://maven.ops.yixiong-tech.com/repository/public/</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -367,6 +375,31 @@
|
|||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- IOSP 日志 Kafka 上送:Boot2 starter(JDK8字节码),启动时把日志异步推送到对方Kafka app-log topic -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>ptr.xjyt.iosp.starter</groupId>
|
||||||
|
<artifactId>iosp-starter-log</artifactId>
|
||||||
|
<version>2.0.9.RELEASE</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- hongyousoft logback KafkaAppender 底层实现 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.hongyousoft</groupId>
|
||||||
|
<artifactId>kafka-appender</artifactId>
|
||||||
|
<version>0.0.4</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- SkyWalking 日志 traceId 占位符 %tid 支持(无agent时显示N/A,不影响推送) -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.skywalking</groupId>
|
||||||
|
<artifactId>apm-toolkit-logback-1.x</artifactId>
|
||||||
|
<version>9.3.0</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- Kafka 客户端:与 starter 设计基线一致(2.4.0),对方3.7.2 broker 向下兼容 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.kafka</groupId>
|
||||||
|
<artifactId>kafka-clients</artifactId>
|
||||||
|
<version>2.4.0</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -48,7 +48,8 @@ public enum RoleEnum {
|
|||||||
MANAGER("manager"),
|
MANAGER("manager"),
|
||||||
MEDICALUSER("medicaluser"),
|
MEDICALUSER("medicaluser"),
|
||||||
MEDICALADMIN("medicaladmin"),
|
MEDICALADMIN("medicaladmin"),
|
||||||
HOS_DOCTOR("hos_doctor");
|
HOS_DOCTOR("hos_doctor"),
|
||||||
|
NOTICE_ROLE("notice_role");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 角色名
|
* 角色名
|
||||||
|
|||||||
@@ -2302,7 +2302,7 @@
|
|||||||
},
|
},
|
||||||
"429005": {
|
"429005": {
|
||||||
"4290051": "竹根滩镇",
|
"4290051": "竹根滩镇",
|
||||||
"4290054": "江汉石油管理局",
|
"4290054": "江汉SY管理局",
|
||||||
"42900545": "周矶管理区",
|
"42900545": "周矶管理区",
|
||||||
"429005001": "园林",
|
"429005001": "园林",
|
||||||
"429005002": "杨市",
|
"429005002": "杨市",
|
||||||
|
|||||||
@@ -84,6 +84,10 @@
|
|||||||
<groupId>com.renkang</groupId>
|
<groupId>com.renkang</groupId>
|
||||||
<artifactId>xj-anyan-api</artifactId>
|
<artifactId>xj-anyan-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.renkang</groupId>
|
||||||
|
<artifactId>health-im-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|||||||
+24
-1
@@ -41,13 +41,36 @@ public class SysMessageController extends JeecgController<SysMessage, ISysMessag
|
|||||||
*/
|
*/
|
||||||
@GetMapping(value = "/list")
|
@GetMapping(value = "/list")
|
||||||
public Result<?> queryPageList(SysMessage sysMessage, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
|
public Result<?> queryPageList(SysMessage sysMessage, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
|
||||||
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {
|
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
|
||||||
|
@RequestParam(name = "employeePhone", required = false) String employeePhone,
|
||||||
|
HttpServletRequest req) {
|
||||||
QueryWrapper<SysMessage> queryWrapper = QueryGenerator.initQueryWrapper(sysMessage, req.getParameterMap());
|
QueryWrapper<SysMessage> queryWrapper = QueryGenerator.initQueryWrapper(sysMessage, req.getParameterMap());
|
||||||
|
// 员工电话: esContent中手机号以"3位~4位~4位"(全角波浪线)格式存储,
|
||||||
|
// 前端传入纯数字手机号,此处还原为存储格式后对 esContent 做模糊查询
|
||||||
|
if (employeePhone != null && !employeePhone.trim().isEmpty()) {
|
||||||
|
queryWrapper.like("ES_CONTENT", buildEmployeePhoneLikeValue(employeePhone));
|
||||||
|
}
|
||||||
Page<SysMessage> page = new Page<SysMessage>(pageNo, pageSize);
|
Page<SysMessage> page = new Page<SysMessage>(pageNo, pageSize);
|
||||||
IPage<SysMessage> pageList = sysMessageService.page(page, queryWrapper);
|
IPage<SysMessage> pageList = sysMessageService.page(page, queryWrapper);
|
||||||
return Result.ok(pageList);
|
return Result.ok(pageList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将前端传入的员工电话还原为 esContent 中存储的"3位~4位~4位"(全角波浪线)格式。
|
||||||
|
* 11位纯数字 -> 还原为 ddd~dddd~dddd;其余情况用原始输入兜底(兼容用户直接粘贴带~的原文)。
|
||||||
|
* 等效SQL: ES_CONTENT LIKE '%185~9920~5354%'
|
||||||
|
*
|
||||||
|
* @param employeePhone 前端传入的员工电话
|
||||||
|
* @return 用于模糊查询 esContent 的值
|
||||||
|
*/
|
||||||
|
private String buildEmployeePhoneLikeValue(String employeePhone) {
|
||||||
|
String digits = employeePhone.replaceAll("[^0-9]", "");
|
||||||
|
if (digits.length() == 11) {
|
||||||
|
return digits.substring(0, 3) + "~" + digits.substring(3, 7) + "~" + digits.substring(7, 11);
|
||||||
|
}
|
||||||
|
return employeePhone.trim();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加
|
* 添加
|
||||||
*
|
*
|
||||||
|
|||||||
+1
-1
@@ -85,7 +85,7 @@ public class ArchivesUserServiceImpl implements ArchivesUserService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (managedCodes.contains("A01")) {
|
if (managedCodes.contains("A01")) {
|
||||||
return Collections.singletonList("长庆油田");
|
return Collections.singletonList("分公司");
|
||||||
}
|
}
|
||||||
List<String> result = new ArrayList<>();
|
List<String> result = new ArrayList<>();
|
||||||
managedCodes.forEach(orgCode -> {
|
managedCodes.forEach(orgCode -> {
|
||||||
|
|||||||
+27
@@ -1,6 +1,7 @@
|
|||||||
package org.jeecg.modules.system.controller;
|
package org.jeecg.modules.system.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.http.HtmlUtil;
|
import cn.hutool.http.HtmlUtil;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
@@ -11,12 +12,15 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.renkang.im.api.IMHelloApi;
|
||||||
|
import com.renkang.im.entity.ConSessionRequestDO;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||||
|
import org.jeecg.bean.request.ListUser;
|
||||||
import org.jeecg.bean.request.PeoplePsyAssessPlanVO;
|
import org.jeecg.bean.request.PeoplePsyAssessPlanVO;
|
||||||
import org.jeecg.bean.request.PeopleStatisticVO;
|
import org.jeecg.bean.request.PeopleStatisticVO;
|
||||||
import org.jeecg.common.api.vo.Result;
|
import org.jeecg.common.api.vo.Result;
|
||||||
@@ -25,6 +29,7 @@ import org.jeecg.common.aspect.annotation.PermissionData;
|
|||||||
import org.jeecg.common.config.TenantContext;
|
import org.jeecg.common.config.TenantContext;
|
||||||
import org.jeecg.common.constant.CommonConstant;
|
import org.jeecg.common.constant.CommonConstant;
|
||||||
import org.jeecg.common.constant.SymbolConstant;
|
import org.jeecg.common.constant.SymbolConstant;
|
||||||
|
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||||
import org.jeecg.common.system.bean.request.ResetPassword;
|
import org.jeecg.common.system.bean.request.ResetPassword;
|
||||||
import org.jeecg.common.system.bean.request.SimpleUser;
|
import org.jeecg.common.system.bean.request.SimpleUser;
|
||||||
import org.jeecg.common.system.bean.response.BaseUser;
|
import org.jeecg.common.system.bean.response.BaseUser;
|
||||||
@@ -32,6 +37,7 @@ import org.jeecg.common.system.bean.response.GroupUser;
|
|||||||
import org.jeecg.common.system.query.QueryGenerator;
|
import org.jeecg.common.system.query.QueryGenerator;
|
||||||
import org.jeecg.common.system.util.JwtUtil;
|
import org.jeecg.common.system.util.JwtUtil;
|
||||||
import org.jeecg.common.system.vo.LoginUser;
|
import org.jeecg.common.system.vo.LoginUser;
|
||||||
|
import org.jeecg.common.system.vo.LoginUserNew;
|
||||||
import org.jeecg.common.system.vo.SysUserModel;
|
import org.jeecg.common.system.vo.SysUserModel;
|
||||||
import org.jeecg.common.util.*;
|
import org.jeecg.common.util.*;
|
||||||
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
|
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
|
||||||
@@ -130,6 +136,10 @@ public class SysUserController {
|
|||||||
private ISysUserPostService sysUserPostService;
|
private ISysUserPostService sysUserPostService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserCacheManager userCacheManager;
|
private UserCacheManager userCacheManager;
|
||||||
|
@Autowired
|
||||||
|
private IMHelloApi imHelloApi;
|
||||||
|
@Autowired
|
||||||
|
private ISysBaseAPI sysBaseAPI;
|
||||||
@GetMapping("userRoles")
|
@GetMapping("userRoles")
|
||||||
public Result<?> userRoles(@RequestParam String userId) {
|
public Result<?> userRoles(@RequestParam String userId) {
|
||||||
if (StrUtil.isBlank(userId)) {
|
if (StrUtil.isBlank(userId)) {
|
||||||
@@ -524,6 +534,8 @@ public class SysUserController {
|
|||||||
//获取租户ids
|
//获取租户ids
|
||||||
String relTenantIds = jsonObject.getString("relTenantIds");
|
String relTenantIds = jsonObject.getString("relTenantIds");
|
||||||
sysUserService.editUser(user, roles, departs, relTenantIds);
|
sysUserService.editUser(user, roles, departs, relTenantIds);
|
||||||
|
// 同步IM个人资料
|
||||||
|
syncImProfile(user.getId());
|
||||||
result.success("修改成功!");
|
result.success("修改成功!");
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -1711,6 +1723,8 @@ public class SysUserController {
|
|||||||
}
|
}
|
||||||
sysUser.setUpdateTime(new Date());
|
sysUser.setUpdateTime(new Date());
|
||||||
sysUserService.updateById(sysUser);
|
sysUserService.updateById(sysUser);
|
||||||
|
// 同步IM个人资料
|
||||||
|
syncImProfile(sysUser.getId());
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error(e.getMessage(), e);
|
log.error(e.getMessage(), e);
|
||||||
@@ -2335,4 +2349,17 @@ public class SysUserController {
|
|||||||
Page<ScopeUserVO> page = new Page<>(pageNo, pageSize);
|
Page<ScopeUserVO> page = new Page<>(pageNo, pageSize);
|
||||||
return Result.ok(sysUserService.scopeUserList(query,page));
|
return Result.ok(sysUserService.scopeUserList(query,page));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void syncImProfile(String userId) {
|
||||||
|
try {
|
||||||
|
List<LoginUserNew> users = sysBaseAPI.listUserByIds(new ListUser(Collections.singletonList(userId)));
|
||||||
|
if (CollUtil.isNotEmpty(users)) {
|
||||||
|
ConSessionRequestDO req = new ConSessionRequestDO();
|
||||||
|
req.setAccountList(Collections.singletonList(users.get(0)));
|
||||||
|
imHelloApi.accountReg(req);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("同步IM个人资料失败, userId: {}", userId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -189,12 +189,12 @@ public class SysMessageNoticeServiceImpl extends ServiceImpl<SysMessageNoticeMap
|
|||||||
LoginUser loginUser = GlobalUtils.getLoginUser();
|
LoginUser loginUser = GlobalUtils.getLoginUser();
|
||||||
/*
|
/*
|
||||||
* 1.后台接口的消息列表需要做一定数据权限控制需考虑的角色有admin,system,second_manager,third_manager
|
* 1.后台接口的消息列表需要做一定数据权限控制需考虑的角色有admin,system,second_manager,third_manager
|
||||||
* 2.admin,system可查看所有的活动
|
* 2.admin,system可查看所有的消息通知
|
||||||
* 3.second_manager,third_manager可查看管理单位下的消息列表
|
* 3.second_manager,third_manager可查看管理单位下的消息列表
|
||||||
*/
|
*/
|
||||||
boolean permissions = false;
|
boolean permissions = false;
|
||||||
List<String> roleCodes = Arrays.asList(Objects.toString(loginUser.getRoleCodes(), "").split(","));
|
List<String> roleCodes = Arrays.asList(Objects.toString(loginUser.getRoleCodes(), "").split(","));
|
||||||
if (roleCodes.contains(RoleEnum.ADMIN_MANAGER.roleName) || roleCodes.contains(RoleEnum.SYSTEM.roleName) || roleCodes.contains(RoleEnum.WEIGHT_PLAN_ADMIN.roleName)) {
|
if (roleCodes.contains(RoleEnum.ADMIN_MANAGER.roleName) || roleCodes.contains(RoleEnum.SYSTEM.roleName)) {
|
||||||
permissions = true;
|
permissions = true;
|
||||||
} else if (roleCodes.contains(RoleEnum.SECOND_MANAGER.roleName)) {
|
} else if (roleCodes.contains(RoleEnum.SECOND_MANAGER.roleName)) {
|
||||||
if (StrUtil.isNotEmpty(loginUser.getDepartCodes())) {
|
if (StrUtil.isNotEmpty(loginUser.getDepartCodes())) {
|
||||||
@@ -203,8 +203,8 @@ public class SysMessageNoticeServiceImpl extends ServiceImpl<SysMessageNoticeMap
|
|||||||
permissions = true;
|
permissions = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 没有权限,返回空结果
|
// 只查看本人创建的消息
|
||||||
wrapper.eq(!permissions, SysMessageNotice::getId, "-1");
|
wrapper.eq(!permissions, SysMessageNotice::getCreateBy, loginUser.getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+21
@@ -16,6 +16,8 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|||||||
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
||||||
import com.renkang.consultation.api.ConSessionHelloApi;
|
import com.renkang.consultation.api.ConSessionHelloApi;
|
||||||
import com.renkang.consultation.vo.FamilyNum;
|
import com.renkang.consultation.vo.FamilyNum;
|
||||||
|
import com.renkang.im.api.IMHelloApi;
|
||||||
|
import com.renkang.im.entity.ConSessionRequestDO;
|
||||||
import com.renkang.watch.api.WatchApi;
|
import com.renkang.watch.api.WatchApi;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.compress.utils.Lists;
|
import org.apache.commons.compress.utils.Lists;
|
||||||
@@ -24,6 +26,7 @@ import org.jeecg.bean.entity.UserDataRecordBWH;
|
|||||||
import org.jeecg.bean.entity.UserDataRecordBmi;
|
import org.jeecg.bean.entity.UserDataRecordBmi;
|
||||||
import org.jeecg.bean.enums.UserDataSourceEnum;
|
import org.jeecg.bean.enums.UserDataSourceEnum;
|
||||||
import org.jeecg.bean.request.HealthMealsWeightQueryVO;
|
import org.jeecg.bean.request.HealthMealsWeightQueryVO;
|
||||||
|
import org.jeecg.bean.request.ListUser;
|
||||||
import org.jeecg.bean.request.QueryWeightSignUserParam;
|
import org.jeecg.bean.request.QueryWeightSignUserParam;
|
||||||
import org.jeecg.bean.response.*;
|
import org.jeecg.bean.response.*;
|
||||||
import org.jeecg.common.api.vo.Result;
|
import org.jeecg.common.api.vo.Result;
|
||||||
@@ -34,6 +37,7 @@ import org.jeecg.common.export.PoiExportHandler;
|
|||||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||||
import org.jeecg.common.system.util.DictUtil;
|
import org.jeecg.common.system.util.DictUtil;
|
||||||
import org.jeecg.common.system.vo.LoginUser;
|
import org.jeecg.common.system.vo.LoginUser;
|
||||||
|
import org.jeecg.common.system.vo.LoginUserNew;
|
||||||
import org.jeecg.common.system.vo.SysUserModel;
|
import org.jeecg.common.system.vo.SysUserModel;
|
||||||
import org.jeecg.common.util.*;
|
import org.jeecg.common.util.*;
|
||||||
import org.jeecg.config.mybatis.AnalyzeTableManager;
|
import org.jeecg.config.mybatis.AnalyzeTableManager;
|
||||||
@@ -122,6 +126,8 @@ public class HealthUserEmployeeExServiceImpl extends ServiceImpl<HealthUserEmplo
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ConSessionHelloApi conSessionHelloApi;
|
private ConSessionHelloApi conSessionHelloApi;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
private IMHelloApi imHelloApi;
|
||||||
|
@Autowired
|
||||||
private WatchApi watchApi;
|
private WatchApi watchApi;
|
||||||
@Autowired
|
@Autowired
|
||||||
private CommonExportsInfoController commonExportsInfoController;
|
private CommonExportsInfoController commonExportsInfoController;
|
||||||
@@ -993,6 +999,8 @@ public class HealthUserEmployeeExServiceImpl extends ServiceImpl<HealthUserEmplo
|
|||||||
if (com.xkcoding.http.util.StringUtil.isNotEmpty(orgCode)) {
|
if (com.xkcoding.http.util.StringUtil.isNotEmpty(orgCode)) {
|
||||||
sendUpdateMsgToRedisStream(userEmployee.getId(), orgCode);
|
sendUpdateMsgToRedisStream(userEmployee.getId(), orgCode);
|
||||||
}
|
}
|
||||||
|
// 同步IM个人资料
|
||||||
|
syncImProfile(userEmployee.getId());
|
||||||
return Result.ok("编辑成功");
|
return Result.ok("编辑成功");
|
||||||
} else {
|
} else {
|
||||||
return Result.error("编辑失败");
|
return Result.error("编辑失败");
|
||||||
@@ -1010,6 +1018,19 @@ public class HealthUserEmployeeExServiceImpl extends ServiceImpl<HealthUserEmplo
|
|||||||
redisStreamUtil.add(RedisStreamKeyEnum.CHANGE_USER_DEPART, userModel);
|
redisStreamUtil.add(RedisStreamKeyEnum.CHANGE_USER_DEPART, userModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void syncImProfile(String userId) {
|
||||||
|
try {
|
||||||
|
List<LoginUserNew> users = sysBaseAPI.listUserByIds(new ListUser(Collections.singletonList(userId)));
|
||||||
|
if (CollUtil.isNotEmpty(users)) {
|
||||||
|
ConSessionRequestDO req = new ConSessionRequestDO();
|
||||||
|
req.setAccountList(Collections.singletonList(users.get(0)));
|
||||||
|
imHelloApi.accountReg(req);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("同步IM个人资料失败, userId: {}", userId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean updateByIdAndUser(UserEmployee userEmployee) {
|
public boolean updateByIdAndUser(UserEmployee userEmployee) {
|
||||||
// 添加账号 电话 身份证号校验
|
// 添加账号 电话 身份证号校验
|
||||||
/* List<String> checkExistUser = sysBaseAPI.checkExistUser(userEmployee.getId(), userEmployee.getUsername(), userEmployee.getPhone(), userEmployee.getIdCard());
|
/* List<String> checkExistUser = sysBaseAPI.checkExistUser(userEmployee.getId(), userEmployee.getUsername(), userEmployee.getPhone(), userEmployee.getIdCard());
|
||||||
|
|||||||
+25
@@ -19,6 +19,8 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
||||||
|
import com.renkang.im.api.IMHelloApi;
|
||||||
|
import com.renkang.im.entity.ConSessionRequestDO;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
@@ -35,6 +37,7 @@ import org.jeecg.bean.entity.UserDataRecordBmi;
|
|||||||
import org.jeecg.bean.enums.UserDataSourceEnum;
|
import org.jeecg.bean.enums.UserDataSourceEnum;
|
||||||
import org.jeecg.bean.request.PeoplePsyAssessPlanVO;
|
import org.jeecg.bean.request.PeoplePsyAssessPlanVO;
|
||||||
import org.jeecg.bean.request.PeopleStatisticVO;
|
import org.jeecg.bean.request.PeopleStatisticVO;
|
||||||
|
import org.jeecg.bean.request.ListUser;
|
||||||
import org.jeecg.bean.response.BaseEmployeeInfo;
|
import org.jeecg.bean.response.BaseEmployeeInfo;
|
||||||
import org.jeecg.common.api.vo.Result;
|
import org.jeecg.common.api.vo.Result;
|
||||||
import org.jeecg.common.bean.request.StatAllReq;
|
import org.jeecg.common.bean.request.StatAllReq;
|
||||||
@@ -50,6 +53,7 @@ import org.jeecg.common.desensitization.annotation.SensitiveEncode;
|
|||||||
import org.jeecg.common.exception.ExceptionAssertsUtil;
|
import org.jeecg.common.exception.ExceptionAssertsUtil;
|
||||||
import org.jeecg.common.exception.JeecgBootException;
|
import org.jeecg.common.exception.JeecgBootException;
|
||||||
import org.jeecg.common.export.PoiExportHandler;
|
import org.jeecg.common.export.PoiExportHandler;
|
||||||
|
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||||
import org.jeecg.common.system.bean.request.ResetPassword;
|
import org.jeecg.common.system.bean.request.ResetPassword;
|
||||||
import org.jeecg.common.system.bean.request.SimpleUser;
|
import org.jeecg.common.system.bean.request.SimpleUser;
|
||||||
import org.jeecg.common.system.bean.request.SysUserInfoDO;
|
import org.jeecg.common.system.bean.request.SysUserInfoDO;
|
||||||
@@ -95,6 +99,7 @@ import org.slf4j.Logger;
|
|||||||
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.cache.annotation.CacheEvict;
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
import org.springframework.core.task.AsyncTaskExecutor;
|
import org.springframework.core.task.AsyncTaskExecutor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -197,6 +202,11 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||||||
private UserDataRecordBWHMapper bwhMapper;
|
private UserDataRecordBWHMapper bwhMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserDataRecordBmiMapper bmiMapper;
|
private UserDataRecordBmiMapper bmiMapper;
|
||||||
|
@Autowired
|
||||||
|
private IMHelloApi imHelloApi;
|
||||||
|
@Lazy
|
||||||
|
@Autowired
|
||||||
|
private ISysBaseAPI sysBaseAPI;
|
||||||
|
|
||||||
private final GroupUserExportHandler groupUserExportHandler = new GroupUserExportHandler();
|
private final GroupUserExportHandler groupUserExportHandler = new GroupUserExportHandler();
|
||||||
|
|
||||||
@@ -1811,6 +1821,21 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||||||
userModel.setId(loginUser.getId());
|
userModel.setId(loginUser.getId());
|
||||||
userModel.setAvatar(avatar);
|
userModel.setAvatar(avatar);
|
||||||
redisStreamUtil.add(RedisStreamKeyEnum.UPDATE_USER_INFO, RedisConstant.REDIS_STREAM_KEY_FIELD, userModel);
|
redisStreamUtil.add(RedisStreamKeyEnum.UPDATE_USER_INFO, RedisConstant.REDIS_STREAM_KEY_FIELD, userModel);
|
||||||
|
// 同步IM个人资料
|
||||||
|
syncImProfile(loginUser.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void syncImProfile(String userId) {
|
||||||
|
try {
|
||||||
|
List<LoginUserNew> users = sysBaseAPI.listUserByIds(new ListUser(Collections.singletonList(userId)));
|
||||||
|
if (CollUtil.isNotEmpty(users)) {
|
||||||
|
ConSessionRequestDO req = new ConSessionRequestDO();
|
||||||
|
req.setAccountList(Collections.singletonList(users.get(0)));
|
||||||
|
imHelloApi.accountReg(req);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("同步IM个人资料失败, userId: {}", userId, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -143,7 +143,7 @@
|
|||||||
<repository>
|
<repository>
|
||||||
<id>dt-releases</id>
|
<id>dt-releases</id>
|
||||||
<name>jeecg Repository</name>
|
<name>jeecg Repository</name>
|
||||||
<url>https://maven.icdat.cn/repository/releases/</url>
|
<url>https://maven.ops.yixiong-tech.com/repository/releases/</url>
|
||||||
<snapshots>
|
<snapshots>
|
||||||
<enabled>false</enabled>
|
<enabled>false</enabled>
|
||||||
</snapshots>
|
</snapshots>
|
||||||
@@ -151,7 +151,7 @@
|
|||||||
<repository>
|
<repository>
|
||||||
<id>dt-snapshots</id>
|
<id>dt-snapshots</id>
|
||||||
<name>jeecg-snapshots Repository</name>
|
<name>jeecg-snapshots Repository</name>
|
||||||
<url>https://maven.icdat.cn/repository/shapshots/</url>
|
<url>https://maven.ops.yixiong-tech.com/repository/shapshots/</url>
|
||||||
<releases>
|
<releases>
|
||||||
<enabled>false</enabled>
|
<enabled>false</enabled>
|
||||||
</releases>
|
</releases>
|
||||||
|
|||||||
Reference in New Issue
Block a user