geng
This commit is contained in:
@@ -627,10 +627,35 @@ class AppointmentLogic extends BaseLogic
|
||||
* @param array $params
|
||||
* @return array
|
||||
*/
|
||||
public static function reception(array $params): array
|
||||
{
|
||||
// 1) 挂号详情(已包含 patient_name / patient_phone / doctor_name / status_desc 等)
|
||||
$appointment = self::detail($params);
|
||||
public static function reception(array $params, int $adminId, array $adminInfo): array
|
||||
{
|
||||
self::$error = '';
|
||||
$appointmentId = (int) ($params['id'] ?? 0);
|
||||
$appointmentRow = $appointmentId > 0
|
||||
? Appointment::where('id', $appointmentId)->field(['id', 'patient_id', 'doctor_id'])->find()
|
||||
: null;
|
||||
if (!$appointmentRow) {
|
||||
self::setError('预约记录不存在或无权访问');
|
||||
|
||||
return [];
|
||||
}
|
||||
$diagnosisRow = Diagnosis::where('id', (int) $appointmentRow->patient_id)
|
||||
->whereNull('delete_time')
|
||||
->field(['id', 'assistant_id'])
|
||||
->find();
|
||||
if (!self::appointmentRowManageableByAdmin(
|
||||
$appointmentRow,
|
||||
$diagnosisRow ?: null,
|
||||
$adminId,
|
||||
$adminInfo
|
||||
)) {
|
||||
self::setError('预约记录不存在或无权访问');
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
// 1) 挂号详情(已包含 patient_name / patient_phone / doctor_name / status_desc 等)
|
||||
$appointment = self::detail($params);
|
||||
if (empty($appointment)) {
|
||||
return [];
|
||||
}
|
||||
@@ -883,40 +908,62 @@ class AppointmentLogic extends BaseLogic
|
||||
/**
|
||||
* 与 AppointmentLists 一致的可见性(不含 progress_board / diag_scope_relax)
|
||||
*/
|
||||
private static function appointmentRowManageableByAdmin(
|
||||
Appointment $appointment,
|
||||
?Diagnosis $diag,
|
||||
int $adminId,
|
||||
array $adminInfo
|
||||
): bool {
|
||||
$roleIds = array_map('intval', AdminRole::where('admin_id', $adminId)->column('role_id'));
|
||||
|
||||
if (in_array(1, $roleIds, true) && (int) $appointment->doctor_id !== $adminId) {
|
||||
return false;
|
||||
}
|
||||
if (in_array(2, $roleIds, true)) {
|
||||
$asst = $diag ? (int) $diag->assistant_id : 0;
|
||||
if ($asst !== $adminId) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!DataScopeService::isEnabled()) {
|
||||
return true;
|
||||
}
|
||||
$ids = DataScopeService::getVisibleAdminIds($adminId, $adminInfo);
|
||||
if ($ids === []) {
|
||||
return false;
|
||||
}
|
||||
if ($ids === null) {
|
||||
return true;
|
||||
}
|
||||
$docId = (int) $appointment->doctor_id;
|
||||
$asstId = $diag ? (int) $diag->assistant_id : 0;
|
||||
|
||||
return in_array($docId, $ids, true)
|
||||
|| ($asstId > 0 && in_array($asstId, $ids, true));
|
||||
}
|
||||
private static function appointmentRowManageableByAdmin(
|
||||
Appointment $appointment,
|
||||
?Diagnosis $diag,
|
||||
int $adminId,
|
||||
array $adminInfo
|
||||
): bool {
|
||||
$docId = (int) $appointment->doctor_id;
|
||||
$asstId = $diag ? (int) $diag->assistant_id : 0;
|
||||
$isRoot = !empty($adminInfo['root']) && (int) $adminInfo['root'] === 1;
|
||||
$roleIds = $isRoot
|
||||
? []
|
||||
: array_map('intval', AdminRole::where('admin_id', $adminId)->column('role_id'));
|
||||
$visibleIds = null;
|
||||
if (!$isRoot && DataScopeService::isEnabled()) {
|
||||
$visibleIds = DataScopeService::getVisibleAdminIds($adminId, $adminInfo);
|
||||
}
|
||||
|
||||
return self::appointmentRowManageableForScope(
|
||||
$docId,
|
||||
$asstId,
|
||||
$adminId,
|
||||
$roleIds,
|
||||
$visibleIds,
|
||||
$isRoot
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, int> $roleIds
|
||||
* @param array<int, int>|null $visibleIds null 表示未启用数据范围或全量可见
|
||||
*/
|
||||
private static function appointmentRowManageableForScope(
|
||||
int $doctorId,
|
||||
int $assistantId,
|
||||
int $adminId,
|
||||
array $roleIds,
|
||||
?array $visibleIds,
|
||||
bool $isRoot
|
||||
): bool {
|
||||
if ($isRoot) {
|
||||
return true;
|
||||
}
|
||||
if (in_array(1, $roleIds, true) && $doctorId !== $adminId) {
|
||||
return false;
|
||||
}
|
||||
if (in_array(2, $roleIds, true) && $assistantId !== $adminId) {
|
||||
return false;
|
||||
}
|
||||
if ($visibleIds === []) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $visibleIds === null
|
||||
|| in_array($doctorId, $visibleIds, true)
|
||||
|| ($assistantId > 0 && in_array($assistantId, $visibleIds, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台编辑挂号(预约日期/时段/类型/状态/备注/医助)
|
||||
|
||||
@@ -25,8 +25,8 @@ class DoctorNoteLogic extends BaseLogic
|
||||
->find();
|
||||
|
||||
$newContent = trim($params['content'] ?? '');
|
||||
$newImages = array_map([self::class, 'toRelativePath'], self::parseJsonArray($params['tongue_images'] ?? []));
|
||||
$newReports = array_map([self::class, 'toRelativePath'], self::parseJsonArray($params['report_files'] ?? []));
|
||||
$newImages = self::normalizeNewAttachmentPaths($params['tongue_images'] ?? []);
|
||||
$newReports = self::normalizeNewAttachmentPaths($params['report_files'] ?? []);
|
||||
|
||||
if ($existing) {
|
||||
$data = [];
|
||||
@@ -169,15 +169,51 @@ class DoctorNoteLogic extends BaseLogic
|
||||
*/
|
||||
private static function toRelativePath(string $url): string
|
||||
{
|
||||
if (empty($url)) return $url;
|
||||
if (stripos($url, 'http://') !== 0 && stripos($url, 'https://') !== 0) {
|
||||
$url = trim($url);
|
||||
if ($url === '') return $url;
|
||||
|
||||
$urlParts = parse_url($url);
|
||||
if (!is_array($urlParts) || empty($urlParts['scheme'])) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
$scheme = strtolower((string) $urlParts['scheme']);
|
||||
if (!in_array($scheme, ['http', 'https'], true)) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
// 获取当前存储域名
|
||||
$domain = self::getStorageDomain();
|
||||
if ($domain && stripos($url, rtrim($domain, '/')) === 0) {
|
||||
$relative = substr($url, strlen(rtrim($domain, '/')));
|
||||
return ltrim($relative, '/');
|
||||
$domain = rtrim(self::getStorageDomain(), '/');
|
||||
$domainParts = $domain !== '' ? parse_url($domain) : false;
|
||||
if (is_array($domainParts)) {
|
||||
$domainScheme = strtolower((string) ($domainParts['scheme'] ?? ''));
|
||||
$urlHost = strtolower(rtrim((string) ($urlParts['host'] ?? ''), '.'));
|
||||
$domainHost = strtolower(rtrim((string) ($domainParts['host'] ?? ''), '.'));
|
||||
$urlPort = (int) ($urlParts['port'] ?? ($scheme === 'https' ? 443 : 80));
|
||||
$domainPort = (int) (
|
||||
$domainParts['port'] ?? ($domainScheme === 'https' ? 443 : 80)
|
||||
);
|
||||
$urlPath = (string) ($urlParts['path'] ?? '');
|
||||
$domainPath = rtrim((string) ($domainParts['path'] ?? ''), '/');
|
||||
$pathInsideDomain = $domainPath === ''
|
||||
|| $urlPath === $domainPath
|
||||
|| str_starts_with($urlPath, $domainPath . '/');
|
||||
|
||||
if (
|
||||
$domainScheme === $scheme
|
||||
&& $domainHost !== ''
|
||||
&& $domainHost === $urlHost
|
||||
&& $domainPort === $urlPort
|
||||
&& $pathInsideDomain
|
||||
) {
|
||||
$relative = $domainPath === ''
|
||||
? $urlPath
|
||||
: substr($urlPath, strlen($domainPath));
|
||||
if (isset($urlParts['query']) && $urlParts['query'] !== '') {
|
||||
$relative .= '?' . $urlParts['query'];
|
||||
}
|
||||
return ltrim($relative, '/');
|
||||
}
|
||||
}
|
||||
// 非当前存储域名,保留完整 URL
|
||||
return $url;
|
||||
@@ -193,6 +229,36 @@ class DoctorNoteLogic extends BaseLogic
|
||||
return $storage ? ($storage['domain'] ?? '') : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 备注附件只接受站内相对路径或当前存储域已上传的 URL。
|
||||
* 存储域 URL 先转为相对路径,避免将任意外部 URL 持久化到病例页。
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return array<int, string>
|
||||
*/
|
||||
private static function normalizeNewAttachmentPaths($value): array
|
||||
{
|
||||
$paths = [];
|
||||
foreach (self::parseJsonArray($value) as $rawPath) {
|
||||
$path = trim((string) $rawPath);
|
||||
if ($path === '') {
|
||||
continue;
|
||||
}
|
||||
$path = self::toRelativePath($path);
|
||||
$scheme = parse_url($path, PHP_URL_SCHEME);
|
||||
if (
|
||||
(is_string($scheme) && $scheme !== '')
|
||||
|| str_starts_with($path, '//')
|
||||
|| str_contains($path, "\0")
|
||||
) {
|
||||
throw new \InvalidArgumentException('备注附件必须来自当前文件存储域');
|
||||
}
|
||||
$paths[] = $path;
|
||||
}
|
||||
|
||||
return array_values(array_unique($paths));
|
||||
}
|
||||
|
||||
private static function parseJsonArray($value): array
|
||||
{
|
||||
if (is_array($value)) return $value;
|
||||
|
||||
Reference in New Issue
Block a user