Files
zyt/PRESCRIPTION_GET_BY_APPOINTMENT_PERMISSION.md
T
2026-04-10 14:43:58 +08:00

229 lines
6.9 KiB
Markdown

# 预约处方查询权限控制
## 修改说明
`getByAppointment` 接口添加了权限检查,确保用户只能查询自己有权限查看的处方。
## 修改内容
### 1. Controller 层修改
**文件**: `server/app/adminapi/controller/tcm/PrescriptionController.php`
**修改前**:
```php
public function getByAppointment()
{
$appointmentId = (int)($this->request->get('appointment_id') ?? 0);
if (!$appointmentId) {
return $this->fail('预约ID不能为空');
}
$prescription = PrescriptionLogic::getByAppointment($appointmentId);
return $this->data($prescription ?? []);
}
```
**修改后**:
```php
public function getByAppointment()
{
$appointmentId = (int)($this->request->get('appointment_id') ?? 0);
if (!$appointmentId) {
return $this->fail('预约ID不能为空');
}
$prescription = PrescriptionLogic::getByAppointment($appointmentId, (int)$this->adminId, $this->adminInfo);
if ($prescription === null) {
$msg = PrescriptionLogic::getError();
return $this->fail($msg !== '' ? $msg : '未找到处方或无权限查看');
}
return $this->data($prescription);
}
```
**改进点**:
- 传入当前登录用户的 `adminId``adminInfo`
- 处理权限检查失败的情况,返回明确的错误信息
- 区分"未找到处方"和"无权限查看"两种情况
### 2. Logic 层修改
**文件**: `server/app/adminapi/logic/tcm/PrescriptionLogic.php`
**修改前**:
```php
/**
* 根据预约ID获取处方
*/
public static function getByAppointment(int $appointmentId): ?array
{
$row = Prescription::where('appointment_id', $appointmentId)
->whereNull('delete_time')
->order('id', 'desc')
->find();
return $row ? $row->toArray() : null;
}
```
**修改后**:
```php
/**
* 根据预约ID获取处方(带权限检查)
*/
public static function getByAppointment(int $appointmentId, int $viewerAdminId, array $viewerAdminInfo): ?array
{
self::$error = '';
$row = Prescription::where('appointment_id', $appointmentId)
->whereNull('delete_time')
->order('id', 'desc')
->find();
if (!$row) {
return null;
}
// 权限检查:只返回当前用户有权限查看的处方
if (!self::canViewPrescription($row, $viewerAdminId, $viewerAdminInfo)) {
self::setError('无权限查看此处方');
return null;
}
return $row->toArray();
}
```
**改进点**:
- 添加 `viewerAdminId``viewerAdminInfo` 参数
- 使用 `canViewPrescription()` 方法进行权限检查
- 设置错误信息,便于前端显示
## 权限规则
根据 `canViewPrescription()` 方法,以下用户可以查看处方:
1. **超级管理员** - 可以查看所有处方
2. **处方创建人** - 可以查看自己创建的处方
3. **医助** - 可以查看自己协助的处方
4. **共享处方** - 所有人可以查看标记为共享的处方
5. **可见角色** - 处方指定的可见角色可以查看
6. **有开方权限的医生** - 拥有 `tcm.diagnosis/kaifang` 权限的医生可以查看所有处方(只读)
## 使用场景
这个接口主要用于以下场景:
1. **查看病历按钮** - 在预约列表中点击"查看病历"时调用
2. **处方历史查询** - 根据预约ID查询患者的历史处方
3. **医生协作** - 其他医生查看患者的处方记录(需要有开方权限)
## 前端调用示例
```typescript
// admin/src/views/tcm/appointment/list.vue
const handleViewCase = async (row: any) => {
if (!row.id) {
feedback.msgWarning('预约信息不完整')
return
}
try {
const prescription = await prescriptionGetByAppointment({ appointment_id: row.id })
if (prescription?.id) {
prescriptionRef.value?.openById(prescription.id)
} else {
feedback.msgWarning('该预约暂无病历记录,请先开方')
}
} catch (error: any) {
// 权限不足或其他错误
feedback.msgError(error?.msg || '获取病历失败')
}
}
```
## 错误处理
### 可能的错误信息
1. **"预约ID不能为空"** - 未传入 `appointment_id` 参数
2. **"未找到处方或无权限查看"** - 处方不存在或当前用户无权限查看
3. **"无权限查看此处方"** - 处方存在但当前用户无权限查看
### 前端处理建议
```typescript
try {
const prescription = await prescriptionGetByAppointment({ appointment_id: row.id })
// 成功获取处方
} catch (error: any) {
if (error?.msg?.includes('无权限')) {
feedback.msgWarning('您没有权限查看此处方')
} else if (error?.msg?.includes('未找到')) {
feedback.msgWarning('该预约暂无病历记录')
} else {
feedback.msgError(error?.msg || '获取病历失败')
}
}
```
## 测试建议
### 1. 权限测试
**测试用例 1: 创建人查看自己的处方**
- 医生A创建处方
- 医生A查看该处方
- 预期:成功返回处方数据
**测试用例 2: 其他医生查看处方(有开方权限)**
- 医生A创建处方
- 医生B(有 `tcm.diagnosis/kaifang` 权限)查看该处方
- 预期:成功返回处方数据(只读)
**测试用例 3: 其他医生查看处方(无开方权限)**
- 医生A创建处方
- 医生C(无 `tcm.diagnosis/kaifang` 权限)查看该处方
- 预期:返回"无权限查看此处方"错误
**测试用例 4: 医助查看协助的处方**
- 医生A创建处方,医助B协助
- 医助B查看该处方
- 预期:成功返回处方数据
**测试用例 5: 查看共享处方**
- 医生A创建处方并标记为共享
- 任何用户查看该处方
- 预期:成功返回处方数据
### 2. 边界测试
**测试用例 6: 预约不存在**
- 传入不存在的 `appointment_id`
- 预期:返回"未找到处方或无权限查看"
**测试用例 7: 预约存在但无处方**
- 传入存在的 `appointment_id`,但该预约没有创建处方
- 预期:返回"未找到处方或无权限查看"
**测试用例 8: 处方已删除**
- 传入已删除处方的 `appointment_id`
- 预期:返回"未找到处方或无权限查看"
## 安全性说明
1. **防止越权访问** - 用户只能查看自己有权限的处方,防止查看其他医生的私有处方
2. **数据隔离** - 通过权限检查实现数据隔离,保护患者隐私
3. **审计追踪** - 所有查询操作都会记录当前用户信息,便于审计
4. **错误信息脱敏** - 对于无权限的情况,不暴露处方是否存在的详细信息
## 相关文档
- `PRESCRIPTION_VIEW_PERMISSION_FIX.md` - 处方查看权限修复文档
- `BUG_FIXES_SUMMARY.md` - Bug修复总结文档
## 总结
通过添加权限检查,确保了:
- ✅ 用户只能查询自己有权限查看的处方
- ✅ 防止越权访问其他医生的私有处方
- ✅ 支持医生协作(有开方权限的医生可以查看所有处方)
- ✅ 保护患者隐私和数据安全
- ✅ 提供明确的错误信息,便于前端处理