liusheng
4 天以前 fb89df539c6293a41933e445df25fa9b8047ba18
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
-- =====================================================================================
-- 【已改为代码修复,本文件的 INSERT 不需要执行】
--   2026-11-06 决定:管理员天然拥有全部科室权限,直接查 sys_dept,不再往 sys_user_dept 补数据。
--   代码改动见:
--     SysDeptMapper.xml#selectSysDeptListBySysUserDept(userId 为空时只查 sys_dept)
--     SysDeptServiceImpl#selectLeafSysDeptListBySysUserDept(userId 为空时不做叶子过滤)
--     SysUserServiceImpl#selectLeafSysDeptList / selectLeafSysDeptForAdmin / selectUserByUserName
--     SysLoginController#getInfo(管理员不传 userId、不按院区过滤)
--   本文件保留下来只作为「诊断口径」参考:第 0 步和第 3 步的查询仍可用于核对
--   「某个用户到底能查到多少科室/病区」,第 1、2 步的写入可以忽略。
-- =====================================================================================
 
-- =====================================================================================
-- 修复:admin 登录后没有科室/病区(belongDepts / belongWards 为空),创建任务选不到科室病区
-- 日期:2026-11-06   库:smartor_nhfy
--
-- 结论(代码 + 数据链路已核对,加索引不会改变结果,因为这不是慢,是查不到):
--   前端下拉用的是 /getInfo 返回的 belongDepts / belongWards:
--     SysLoginController#getInfo(L243-254)
--       → SysDeptServiceImpl#selectLeafSysDeptListBySysUserDept(L335-341)
--         → SysDeptMapper#selectSysDeptListBySysUserDept(SysDeptMapper.xml L286-298)
--           核心是 INNER JOIN sys_user_dept ud ON d.dept_code = ud.dept_code
--           并且这次带上了 userId(sysUserDept.setUserId(user.getUserId()))。
--   而 HIS 采集写入 sys_user_dept 时明确排除了 admin:
--     CollectHISMapper.xml yhyksxx(L494)/ yhybfxx(L513)/ yhyyqxx(L536)都有 `ud.user_id != 'admin'`
--   所以 admin 在 sys_user_dept 里没有任何行 → 上面这条 join 返回 0 行 → 两个列表都是空。
--   (登录 token 走的那条 selectUserByUserName2 里 admin 分支不带 userId,所以那条反而是有数据的,
--     这也是为什么“登录成功但还是没有科室病区”——登录返回的和 /getInfo 覆盖的不一致。)
--
--   顺带两个坑:
--     a) sys_dept.campusid 为空的部门会被 `and d.campusid = #{campusid}` 过滤掉;
--     b) sys_config 里没有 sys.authority.campus.all(已查证为空),所以 admin 的 campusid 不会被清空。
-- =====================================================================================
 
 
-- -------------------------------------------------------------------------------------
-- 第 0 步:先确认(只读;这三条跑完就知道是不是这个原因)
-- -------------------------------------------------------------------------------------
-- 0.1 admin 在 sys_user_dept 里到底有没有数据(预期 0 行)
SELECT u.user_id, u.user_name, u.orgid, u.campusid, u.searchscope,
       (SELECT COUNT(*) FROM sys_user_dept ud
         WHERE ud.user_id = u.user_id AND ud.del_flag = '0')                     AS 有效关系数,
       (SELECT COUNT(*) FROM sys_user_dept ud WHERE ud.user_id = u.user_id)      AS 含已删关系数
FROM sys_user u
WHERE u.user_name = 'admin';
 
-- 0.2 复刻 /getInfo 的 SQL(带 userId)—— 预期 0 行
SELECT d.dept_type, COUNT(*) AS rows_, COUNT(DISTINCT d.dept_code) AS codes
FROM sys_dept d
         INNER JOIN sys_user_dept ud ON d.dept_code = ud.dept_code
WHERE d.del_flag = '0' AND ud.del_flag = '0'
  AND d.orgid = '20001001' AND ud.orgid = '20001001'      -- 换成 admin 的 orgid
  AND ud.user_id = (SELECT user_id FROM sys_user WHERE user_name = 'admin')
  AND d.campusid = '30001002'                              -- 换成 admin 的 campusid
GROUP BY d.dept_type;
 
-- 0.3 同一套 SQL 去掉 userId / campusid 之后能查到多少(预期几百行 = 应该看到的量)
SELECT d.dept_type, COUNT(*) AS rows_, COUNT(DISTINCT d.dept_code) AS codes
FROM sys_dept d
WHERE d.del_flag = '0' AND d.orgid = '20001001'
GROUP BY d.dept_type;
 
 
-- -------------------------------------------------------------------------------------
-- 第 1 步(推荐,立刻生效、不用发版):给 admin 补全 sys_user_dept
--   把该机构下所有科室(dept_type='1')和病区(dept_type='2')都挂到 admin 名下,
--   之后 /getInfo 那条 join 就有数据了;配合刚加的索引,查询也是毫秒级。
--   幂等:重复执行不会插重复行(NOT EXISTS 按 user_id + dept_code + dept_type 判重)。
-- -------------------------------------------------------------------------------------
-- 1.1 先看会插多少行(不插,先确认数量合理)
SELECT u.user_name, d.dept_type, COUNT(*) AS will_insert
FROM sys_user u
         JOIN sys_dept d ON d.del_flag = '0'
    AND d.orgid = u.orgid
    AND d.dept_type IN ('1', '2')
WHERE u.user_name = 'admin'
  AND NOT EXISTS (SELECT 1 FROM sys_user_dept x
                  WHERE x.user_id = u.user_id
                    AND x.dept_code = d.dept_code
                    AND x.dept_type = d.dept_type
                    AND IFNULL(x.orgid, '') = IFNULL(d.orgid, ''))
GROUP BY u.user_name, d.dept_type;
 
-- 1.2 正式插入(要跨院区看全部就把 campusid 一并按 sys_dept 带过去)
INSERT INTO sys_user_dept
(user_id, dept_id, dept_code, dept_name, dept_type, orgid, campusid, del_flag, create_time, update_time)
SELECT u.user_id, d.dept_id, d.dept_code, d.dept_name, d.dept_type, d.orgid, d.campusid,
       '0', NOW(), NOW()
FROM sys_user u
         JOIN sys_dept d ON d.del_flag = '0'
    AND d.orgid = u.orgid
    AND d.dept_type IN ('1', '2')
WHERE u.user_name = 'admin'
  AND NOT EXISTS (SELECT 1 FROM sys_user_dept x
                  WHERE x.user_id = u.user_id
                    AND x.dept_code = d.dept_code
                    AND x.dept_type = d.dept_type
                    AND IFNULL(x.orgid, '') = IFNULL(d.orgid, ''));
 
-- 1.3 回滚 1.2(如果插多了):按插入时间精确删
-- DELETE FROM sys_user_dept
--  WHERE user_id = (SELECT user_id FROM sys_user WHERE user_name = 'admin')
--    AND create_time >= '2026-11-06 00:00:00'
--    AND update_time = create_time;
 
 
-- -------------------------------------------------------------------------------------
-- 第 2 步(可选,让它看到全部院区):把 admin 加进「不限院区」白名单
--   SysLoginController#getInfo L227-233 会读这个配置,命中就把 campusid 置空,
--   于是 `and d.campusid = #{campusid}` 这条过滤不再拼,跨院区的科室病区也能出来。
--   现在 sys_config 里没有这个 key(已查证),需要手工加一条。
-- -------------------------------------------------------------------------------------
-- INSERT INTO sys_config (config_name, config_key, config_value, config_type, create_by, create_time, remark)
-- VALUES ('不限院区的账号', 'sys.authority.campus.all', 'admin', 'N', 'admin', NOW(),
--         '多个账号用英文逗号分隔,命中后登录不按院区过滤');
-- 改完要清缓存:重启或调用 /system/config/refreshCache(若前端有该按钮)。
 
 
-- -------------------------------------------------------------------------------------
-- 第 3 步:验证(重启/刷新前端后跑;期望两条都有几百条)
-- -------------------------------------------------------------------------------------
-- 3.1 模拟 /getInfo 的两个查询
SELECT d.dept_type, COUNT(DISTINCT d.dept_code) AS visible_codes
FROM sys_dept d
         INNER JOIN sys_user_dept ud ON d.dept_code = ud.dept_code
WHERE d.del_flag = '0' AND ud.del_flag = '0'
  AND d.orgid = '20001001' AND ud.orgid = '20001001'
  AND ud.user_id = (SELECT user_id FROM sys_user WHERE user_name = 'admin')
  AND d.campusid = '30001002'
GROUP BY d.dept_type;
 
-- 3.2 直接看科室/病区名字前 10 条,确认是真实科室而不是测试数据
SELECT d.dept_type, d.dept_code, d.dept_name
FROM sys_dept d
         INNER JOIN sys_user_dept ud ON d.dept_code = ud.dept_code
WHERE d.del_flag = '0' AND ud.del_flag = '0'
  AND d.orgid = '20001001' AND ud.orgid = '20001001'
  AND ud.user_id = (SELECT user_id FROM sys_user WHERE user_name = 'admin')
  AND d.campusid = '30001002'
  AND d.dept_type = '1'
LIMIT 10;
 
 
-- -------------------------------------------------------------------------------------
-- 第 4 步(根治,发版时做):代码里 admin 不该走 sys_user_dept
--   4.1 SysDeptMapper.xml L286 按 userId 分支:无 userId 时直接查 sys_dept(见对话里的 diff)
--   4.2 /getInfo 与 /system/user/getInfo 里判 admin,不传 userId
--   4.3 campusid 条件改成 and (d.campusid is null or d.campusid = #{campusid})
--   4.4 列表为空时兜底:再按 orgid 查一次全量,避免以后再出现「登录成功但下拉空」
-- -------------------------------------------------------------------------------------