# 预约处方查询权限控制 ## 修改说明 为 `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修复总结文档 ## 总结 通过添加权限检查,确保了: - ✅ 用户只能查询自己有权限查看的处方 - ✅ 防止越权访问其他医生的私有处方 - ✅ 支持医生协作(有开方权限的医生可以查看所有处方) - ✅ 保护患者隐私和数据安全 - ✅ 提供明确的错误信息,便于前端处理