290 lines
6.0 KiB
Markdown
290 lines
6.0 KiB
Markdown
# 医生列表接口优化
|
||
|
||
## 问题描述
|
||
|
||
在挂号预约页面中,获取医生列表时调用了 `adminapi/auth.admin/lists?role_id=1` 接口,该接口需要管理员权限,可能导致权限不足的问题。
|
||
|
||
## 解决方案
|
||
|
||
创建一个专门的接口 `adminapi/tcm.diagnosis/getDoctors` 用于获取医生列表,不需要额外的权限验证。
|
||
|
||
## 实现细节
|
||
|
||
### 1. 后端实现
|
||
|
||
#### 控制器方法
|
||
**文件:** `server/app/adminapi/controller/tcm/DiagnosisController.php`
|
||
|
||
```php
|
||
/**
|
||
* @notes 获取医生列表
|
||
* @return \think\response\Json
|
||
*/
|
||
public function getDoctors()
|
||
{
|
||
$result = DiagnosisLogic::getDoctors();
|
||
return $this->data($result);
|
||
}
|
||
```
|
||
|
||
#### 逻辑层方法
|
||
**文件:** `server/app/adminapi/logic/tcm/DiagnosisLogic.php`
|
||
|
||
```php
|
||
/**
|
||
* @notes 获取医生列表
|
||
* @return array
|
||
*/
|
||
public static function getDoctors()
|
||
{
|
||
try {
|
||
// 通过中间表查询角色ID为1的管理员(医生)
|
||
$doctors = \app\common\model\auth\Admin::alias('a')
|
||
->join('admin_role ar', 'a.id = ar.admin_id')
|
||
->where('ar.role_id', 1)
|
||
->where('a.disable', 0)
|
||
->field(['a.id', 'a.name', 'a.account'])
|
||
->order('a.id', 'asc')
|
||
->select()
|
||
->toArray();
|
||
|
||
return $doctors;
|
||
} catch (\Exception $e) {
|
||
\think\facade\Log::error('获取医生列表失败: ' . $e->getMessage());
|
||
return [];
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2. 前端实现
|
||
|
||
#### API 方法
|
||
**文件:** `admin/src/api/tcm.ts`
|
||
|
||
```typescript
|
||
// 获取医生列表
|
||
export function getDoctors() {
|
||
return request.get({ url: '/tcm.diagnosis/getDoctors' })
|
||
}
|
||
```
|
||
|
||
#### 组件更新
|
||
**文件:** `admin/src/views/tcm/diagnosis/appointment.vue`
|
||
|
||
```typescript
|
||
// 导入新的 API
|
||
import { getDoctors } from '@/api/tcm'
|
||
|
||
// 移除旧的导入
|
||
// import { adminLists } from '@/api/perms/admin'
|
||
|
||
// 更新加载医生列表的方法
|
||
const loadDoctors = async () => {
|
||
try {
|
||
loading.value = true
|
||
const res = await getDoctors()
|
||
doctorList.value = res || []
|
||
} catch (error) {
|
||
console.error('加载医生列表失败:', error)
|
||
feedback.msgError('加载医生列表失败')
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
```
|
||
|
||
## 数据库结构
|
||
|
||
### 表关系
|
||
|
||
```
|
||
zyt_admin (管理员表)
|
||
├─ id
|
||
├─ name
|
||
├─ account
|
||
└─ disable
|
||
|
||
zyt_admin_role (管理员角色关联表)
|
||
├─ admin_id → zyt_admin.id
|
||
└─ role_id → 1 (医生) / 2 (医助)
|
||
```
|
||
|
||
### SQL 查询
|
||
|
||
```sql
|
||
SELECT a.id, a.name, a.account
|
||
FROM zyt_admin a
|
||
INNER JOIN zyt_admin_role ar ON a.id = ar.admin_id
|
||
WHERE ar.role_id = 1
|
||
AND a.disable = 0
|
||
ORDER BY a.id ASC
|
||
```
|
||
|
||
## 接口说明
|
||
|
||
### 请求
|
||
|
||
```
|
||
GET /adminapi/tcm.diagnosis/getDoctors
|
||
```
|
||
|
||
### 响应
|
||
|
||
```json
|
||
{
|
||
"code": 1,
|
||
"msg": "success",
|
||
"data": [
|
||
{
|
||
"id": 1,
|
||
"name": "张医生",
|
||
"account": "doctor1"
|
||
},
|
||
{
|
||
"id": 2,
|
||
"name": "李医生",
|
||
"account": "doctor2"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 返回字段说明
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | int | 医生ID |
|
||
| name | string | 医生姓名 |
|
||
| account | string | 医生账号 |
|
||
|
||
## 优势
|
||
|
||
1. **权限独立**:不依赖管理员列表接口的权限
|
||
2. **数据精简**:只返回必要的字段(id、name、account)
|
||
3. **性能优化**:直接通过中间表查询医生角色
|
||
4. **易于维护**:专门的接口更容易理解和维护
|
||
5. **正确的关联**:使用中间表 `admin_role` 而不是直接查询 `role_id` 字段
|
||
|
||
## 查询条件
|
||
|
||
- 通过 `zyt_admin_role` 中间表关联
|
||
- `ar.role_id = 1`:只查询医生角色
|
||
- `a.disable = 0`:只查询启用状态的医生
|
||
- 按 `a.id` 升序排列
|
||
|
||
## 测试
|
||
|
||
### 测试步骤
|
||
|
||
1. 登录管理后台
|
||
2. 访问诊单管理页面
|
||
3. 点击某条诊单的"挂号"按钮
|
||
4. 查看医生下拉列表是否正常显示
|
||
|
||
### 预期结果
|
||
|
||
- ✅ 医生列表正常加载
|
||
- ✅ 下拉框显示所有启用的医生
|
||
- ✅ 不会出现权限不足的错误
|
||
- ✅ 可以正常选择医生和预约
|
||
|
||
### 测试 SQL
|
||
|
||
```sql
|
||
-- 检查医生数据
|
||
SELECT
|
||
a.id,
|
||
a.name,
|
||
a.account,
|
||
ar.role_id,
|
||
a.disable
|
||
FROM zyt_admin a
|
||
INNER JOIN zyt_admin_role ar ON a.id = ar.admin_id
|
||
WHERE ar.role_id = 1
|
||
ORDER BY a.id ASC;
|
||
|
||
-- 检查中间表数据
|
||
SELECT * FROM zyt_admin_role WHERE role_id = 1;
|
||
```
|
||
|
||
## 已修改的文件
|
||
|
||
- ✅ `server/app/adminapi/controller/tcm/DiagnosisController.php`
|
||
- ✅ `server/app/adminapi/logic/tcm/DiagnosisLogic.php`
|
||
- ✅ `admin/src/api/tcm.ts`
|
||
- ✅ `admin/src/views/tcm/diagnosis/appointment.vue`
|
||
|
||
## 相关接口
|
||
|
||
### 医助列表接口
|
||
|
||
同时也创建了医助列表接口,使用相同的逻辑:
|
||
|
||
```
|
||
GET /adminapi/tcm.diagnosis/getAssistants
|
||
```
|
||
|
||
查询条件:`ar.role_id = 2`(医助角色)
|
||
|
||
## 注意事项
|
||
|
||
1. **中间表关联**:必须通过 `zyt_admin_role` 中间表查询,不能直接查询 `role_id` 字段
|
||
2. **角色ID**:
|
||
- 医生:`role_id = 1`
|
||
- 医助:`role_id = 2`
|
||
3. **状态检查**:只返回 `disable = 0` 的用户
|
||
4. **字段精简**:只返回必要的字段,减少数据传输
|
||
5. **错误处理**:捕获异常并记录日志,返回空数组而不是抛出错误
|
||
|
||
## 数据库检查
|
||
|
||
### 检查医生数据
|
||
|
||
```sql
|
||
-- 查看所有医生
|
||
SELECT
|
||
a.id,
|
||
a.name,
|
||
a.account,
|
||
ar.role_id,
|
||
a.disable,
|
||
a.create_time
|
||
FROM zyt_admin a
|
||
INNER JOIN zyt_admin_role ar ON a.id = ar.admin_id
|
||
WHERE ar.role_id = 1
|
||
ORDER BY a.id ASC;
|
||
```
|
||
|
||
### 添加测试医生
|
||
|
||
```sql
|
||
-- 1. 添加管理员
|
||
INSERT INTO zyt_admin (
|
||
name,
|
||
account,
|
||
password,
|
||
disable,
|
||
create_time,
|
||
update_time
|
||
) VALUES (
|
||
'测试医生',
|
||
'test_doctor',
|
||
'e10adc3949ba59abbe56e057f20f883e', -- 密码:123456
|
||
0,
|
||
UNIX_TIMESTAMP(),
|
||
UNIX_TIMESTAMP()
|
||
);
|
||
|
||
-- 2. 获取刚插入的ID
|
||
SET @admin_id = LAST_INSERT_ID();
|
||
|
||
-- 3. 添加角色关联
|
||
INSERT INTO zyt_admin_role (admin_id, role_id)
|
||
VALUES (@admin_id, 1);
|
||
```
|
||
|
||
---
|
||
|
||
**修复日期:** 2024-03-04
|
||
**状态:** ✅ 完成
|