yxh
7 天以前 68ff33beff11310e830b0615b5a81f83fad0f683
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
package cn.lihu.jh.module.ecg.service.room;
 
import java.util.*;
import javax.validation.Valid;
import cn.lihu.jh.framework.common.pojo.PageResult;
import cn.lihu.jh.module.ecg.controller.admin.room.vo.MonitorInfoVO;
import cn.lihu.jh.module.ecg.controller.admin.room.vo.RoomPageReqVO;
import cn.lihu.jh.module.ecg.controller.admin.room.vo.RoomSaveReqVO;
import cn.lihu.jh.module.ecg.controller.admin.room.vo.RoomSeatRespVO;
import cn.lihu.jh.module.ecg.controller.admin.room.vo.RoomSelectBedRespVO;
import cn.lihu.jh.module.ecg.dal.dataobject.room.RoomDO;
import cn.lihu.jh.module.ecg.dal.dataobject.room.RoomProfile;
 
 
/**
 * 诊室和诊疗床 Service 接口
 *
 * @author 芋道源码
 */
public interface RoomService {
 
    /**
     * 创建诊室和诊疗床
     *
     * @param createReqVO 创建信息
     * @return 编号
     */
    Integer createRoom(@Valid RoomSaveReqVO createReqVO);
 
    /**
     * 更新诊室和诊疗床
     *
     * @param updateReqVO 更新信息
     */
    void updateRoom(@Valid RoomSaveReqVO updateReqVO);
 
    /**
     * 删除诊室和诊疗床
     *
     * @param id 编号
     */
    void deleteRoom(Integer id);
 
    /**
     * 获得诊室和诊疗床
     *
     * @param id 编号
     * @return 诊室和诊疗床
     */
    RoomDO getRoom(Integer id);
 
    RoomProfile getRoomByIP(String ip, Long roomId);
 
    /**
     * 「选择工位模式」- 按本机IP匹配工位:返回该IP下的候选工位(本人已占用 → 空闲 → 被他人占用)。
     * <p>仅查询、不改变任何状态;自动入座由前端拿到结果后沿用原有的 bedDoctorOn 流程完成。</p>
     *
     * @param ip    来访IP
     * @param docId 当前登录人ID(可能为空)
     */
    List<RoomSelectBedRespVO.RoomSelectBedItem> matchBedsByIp(String ip, Long docId);
 
    /**
     * 「选择工位模式」- 把本机IP写到指定工位(只改 clinic_room.ip 一个字段)。
     *
     * @param id 工位主键
     * @param ip 来访IP
     * @return 受影响行数
     */
    Integer bindIpToBed(Integer id, String ip);
 
    /**
     * 该IP是否已经绑在别的工位上(冲突检测,供前端弹确认后再覆盖)。
     *
     * @param ip        待绑定IP
     * @param excludeId 排除的工位主键,可为空
     */
    List<RoomDO> listIpBindings(String ip, Integer excludeId);
 
    /**
     * 「选择工位模式」- 一键自动入座:按来访 IP 匹配工位并**直接落座**(模式 1/3 用)。
     *
     * <p>为什么要有这个接口:前端原来把「{@code get-ip-bed} 匹配 → {@code bind-ip} 写 IP →
     * {@code bed-doctor-on} 入座」拆成三个请求自己拼,任一步失败都只能回落到"手选工位",
     * 现场表现就是"登录后没有自动入座"且看不出原因。这里收敛成一次调用,并返回**识别到的 IP**
     * 与**未入座原因**(ip_invalid / nomatch / multi / occupied / error)。
     *
     * <p>策略与原有前端逻辑保持一致:
     * ① 已是我的工位 → 幂等恢复;② **恰好一个**空闲工位 → 占用;③ 多个空闲 → 不擅自入座(multi);
     * ④ 全被他人占用 → 不挤掉(occupied + 占用人姓名)。
     *
     * @param ip      来访 IP(调用方已用 {@code IpUtils.normalize} 规范化)
     * @param docId   当前登录人
     * @param docName 当前登录人姓名
     */
    RoomSeatRespVO autoSeatByIp(String ip, Long docId, String docName);
 
    /**
     * 查询当前登录人**已入座**的工位(给系统顶栏显示"当前工位"用)。
     *
     * @param docId 当前登录人
     * @return 未入座时返回 {@code seated=false} 的空结果
     */
    RoomSeatRespVO getMySeat(Long docId);
 
    /**
     * 【本需求·一人多工位】查询当前登录人**占据的全部工位**(节假日值班多岗位)。
     *
     * <p>返回「医生在座 / 医生暂停」状态的工位,按 roomId + bedNo 升序;
     * 未占任何工位时返回空列表(前端据此显示"未入座")。
     *
     * @param docId 当前登录人
     */
    List<RoomSeatRespVO> getMySeats(Long docId);
 
    /**
     * 【本需求·接班自助接管】把指定工位从"别人占用"改为"当前登录人占用"。
     *
     * <p>使用场景:上一班医生下班未点「离座」,下一班医生在同一台电脑/同一工位接班。
     * 行为:
     * <ol>
     *   <li>工位不存在 → 报错;</li>
     *   <li>工位空闲,或本来就属于当前登录人 → **幂等成功**(不报错);</li>
     *   <li>被他人占用 → 记录审计日志(工位、原占用人、操作人)→ 强制清空原占用人 → **立即让当前登录人入座**。</li>
     * </ol>
     *
     * @param roomId 诊室编号
     * @param bedNo  工位编号
     */
    void takeOverBed(Long roomId, String bedNo);
 
    /**
     * 校验「当前登录人必须是该工位的主人」,否则抛
     * {@link cn.lihu.jh.module.ecg.enums.ErrorCodeConstants#ROOM_NOT_OWNER}。
     *
     * <p>用于"主/围观"模型的写操作鉴权:围观人只能看,不能改数据。
     * {@code @RequireBedOwner} 切面会调用它;只带 rentId 之类的接口需要自行调用。
     *
     * @param roomId 诊室编号
     * @param bedNo  工位号
     */
    void assertBedOwner(Long roomId, String bedNo);
 
    /**
     * 同上,但**按患者反查工位**:用于只带患者信息、没有 roomId/bedNo 的写接口
     * (放弃检查 / 放弃领用 / 放弃装机)。
     *
     * <p>反查依据:{@code queue} 表当前该患者 + 检查项目的那一行上的 room_id / bed_no。
     * 查不到工位时**拒绝**(宁可拒绝也不放行)。
     */
    void assertBedOwnerByPatient(String patId, Integer checkType);
 
    /**
     * 同上,但查不到工位时**记警告放行**。
     *
     * <p>用于确费/取消确费:这两步常在流程末端调用,患者可能已经不在工位队列上;
     * 一律拒绝会把正常业务挡掉,故这里只记警告(前端在围观模式下已禁用按钮)。
     */
    void assertBedOwnerByPatientSoft(String patId, Integer checkType);
 
    /**
     * 校验「该工位当前的主人就是 ownerDocId」。
     *
     * <p>用于围观人查看**工位主人的已完成检查记录**:不要求调用者入座(围观本来就是不入座也能看),
     * 但必须确认这个 docId 确实是该工位现在的主人,避免被当成"任意查别人记录"的入口。
     *
     * @param roomId     诊室编号
     * @param bedNo      工位号
     * @param ownerDocId 期望的工位主人
     */
    void assertBedOwnerIs(Long roomId, String bedNo, Long ownerDocId);
 
    /**
     * 工位状态诊断(排查"入座报状态异常/找不到工位")。
     *
     * <p>把库里的**原始行**摊开:`id / room_id / bed_no(含长度与 HEX,用于发现结尾空格/全角) /
     * status / doc_id / doc_name / deleted / update_time`,并给出一句结论。
     *
     * @param id     工位主键(优先,含已删除行)
     * @param roomId 诊室编号(id 为空时用)
     * @param bedNo  工位号(id 为空时用,按 TRIM 宽松匹配)
     */
    Map<String, Object> diagnoseBed(Integer id, Long roomId, String bedNo);
 
    /**
     * 获得诊室和诊疗床分页
     *
     * @param pageReqVO 分页查询
     * @return 诊室和诊疗床分页
     */
    PageResult<RoomDO> getRoomPage(RoomPageReqVO pageReqVO);
 
    List<RoomDO> simpleRoomList();
 
    void resetRoom(Boolean needCloseBed);
 
    MonitorInfoVO getMonitorInfo();
 
}