206 lines
7.4 KiB
PHP
Executable File
206 lines
7.4 KiB
PHP
Executable File
<?php
|
||
|
||
namespace app\adminapi\logic\doctor;
|
||
|
||
use app\common\logic\BaseLogic;
|
||
use app\common\model\doctor\DoctorNote;
|
||
use app\common\service\FileService;
|
||
|
||
class DoctorNoteLogic extends BaseLogic
|
||
{
|
||
/**
|
||
* 按 diagnosis_id + 当天 find-or-create,追加 content / tongue_images / report_files
|
||
*/
|
||
public static function addOrAppend(array $params): bool
|
||
{
|
||
try {
|
||
$diagnosisId = (int) $params['diagnosis_id'];
|
||
$doctorId = (int) ($params['doctor_id'] ?? 0);
|
||
$today = date('Y-m-d');
|
||
$time = date('H:i');
|
||
|
||
$existing = DoctorNote::where('diagnosis_id', $diagnosisId)
|
||
->where('note_date', $today)
|
||
->whereNull('delete_time')
|
||
->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'] ?? []));
|
||
|
||
if ($existing) {
|
||
$data = [];
|
||
|
||
if ($newContent !== '') {
|
||
$prev = trim($existing->content ?? '');
|
||
$line = "[{$time}] {$newContent}";
|
||
$data['content'] = $prev !== '' ? ($prev . "\n" . $line) : $line;
|
||
}
|
||
|
||
if (!empty($newImages)) {
|
||
$prev = self::parseJsonArray($existing->tongue_images);
|
||
$merged = array_values(array_unique(array_merge($prev, $newImages)));
|
||
$data['tongue_images'] = json_encode($merged, JSON_UNESCAPED_UNICODE);
|
||
}
|
||
|
||
if (!empty($newReports)) {
|
||
$prev = self::parseJsonArray($existing->report_files);
|
||
$merged = array_values(array_unique(array_merge($prev, $newReports)));
|
||
$data['report_files'] = json_encode($merged, JSON_UNESCAPED_UNICODE);
|
||
}
|
||
|
||
if (!empty($data)) {
|
||
$existing->save($data);
|
||
}
|
||
} else {
|
||
$content = $newContent !== '' ? "[{$time}] {$newContent}" : '';
|
||
DoctorNote::create([
|
||
'diagnosis_id' => $diagnosisId,
|
||
'doctor_id' => $doctorId,
|
||
'note_date' => $today,
|
||
'content' => $content,
|
||
'tongue_images' => !empty($newImages)
|
||
? json_encode($newImages, JSON_UNESCAPED_UNICODE)
|
||
: null,
|
||
'report_files' => !empty($newReports)
|
||
? json_encode($newReports, JSON_UNESCAPED_UNICODE)
|
||
: null,
|
||
]);
|
||
}
|
||
|
||
return true;
|
||
} catch (\Exception $e) {
|
||
self::setError($e->getMessage());
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 按 diagnosis_id 获取备注列表(note_date DESC)
|
||
*/
|
||
public static function getByDiagnosis(int $diagnosisId, int $limit = 30): array
|
||
{
|
||
try {
|
||
if ($diagnosisId <= 0) {
|
||
return [];
|
||
}
|
||
|
||
$records = DoctorNote::where('diagnosis_id', $diagnosisId)
|
||
->whereNull('delete_time')
|
||
->order('note_date', 'desc')
|
||
->limit($limit)
|
||
->select()
|
||
->toArray();
|
||
|
||
foreach ($records as &$record) {
|
||
$record['tongue_images'] = array_map(function ($url) {
|
||
return empty($url) ? $url : FileService::getFileUrl($url);
|
||
}, self::parseJsonArray($record['tongue_images'] ?? []));
|
||
$record['report_files'] = array_map(function ($url) {
|
||
return empty($url) ? $url : FileService::getFileUrl($url);
|
||
}, self::parseJsonArray($record['report_files'] ?? []));
|
||
}
|
||
|
||
return $records;
|
||
} catch (\Exception $e) {
|
||
self::setError($e->getMessage());
|
||
return [];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 删除备注中的单张图片
|
||
*/
|
||
public static function deleteImage(int $noteId, string $imageType, string $imagePath): bool
|
||
{
|
||
try {
|
||
$note = DoctorNote::where('id', $noteId)->whereNull('delete_time')->find();
|
||
if (!$note) {
|
||
self::setError('记录不存在');
|
||
return false;
|
||
}
|
||
if (!in_array($imageType, ['tongue_images', 'report_files'])) {
|
||
self::setError('类型无效');
|
||
return false;
|
||
}
|
||
$images = self::parseJsonArray($note->$imageType);
|
||
// 统一转为相对路径再匹配
|
||
$targetPath = self::toRelativePath($imagePath);
|
||
$images = array_values(array_filter($images, fn($url) => self::toRelativePath($url) !== $targetPath));
|
||
$note->$imageType = empty($images) ? null : json_encode($images, JSON_UNESCAPED_UNICODE);
|
||
$note->save();
|
||
return true;
|
||
} catch (\Exception $e) {
|
||
self::setError($e->getMessage());
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 聚合某诊单所有备注中的图片(供 DiagnosisLogic::detail 使用)
|
||
*/
|
||
public static function getAggregatedImages(int $diagnosisId): array
|
||
{
|
||
$records = DoctorNote::where('diagnosis_id', $diagnosisId)
|
||
->whereNull('delete_time')
|
||
->select();
|
||
|
||
$tongueImages = [];
|
||
$reportFiles = [];
|
||
foreach ($records as $r) {
|
||
$tongueImages = array_merge($tongueImages, self::parseJsonArray($r->tongue_images));
|
||
$reportFiles = array_merge($reportFiles, self::parseJsonArray($r->report_files));
|
||
}
|
||
|
||
return [
|
||
'tongue_images' => array_map(
|
||
fn($u) => empty($u) ? $u : FileService::getFileUrl($u),
|
||
array_values(array_unique($tongueImages))
|
||
),
|
||
'report_files' => array_map(
|
||
fn($u) => empty($u) ? $u : FileService::getFileUrl($u),
|
||
array_values(array_unique($reportFiles))
|
||
),
|
||
];
|
||
}
|
||
|
||
/**
|
||
* 如果 URL 的域名是当前配置的存储域名则去掉,否则原样保留
|
||
*/
|
||
private static function toRelativePath(string $url): string
|
||
{
|
||
if (empty($url)) return $url;
|
||
if (stripos($url, 'http://') !== 0 && stripos($url, 'https://') !== 0) {
|
||
return $url;
|
||
}
|
||
// 获取当前存储域名
|
||
$domain = self::getStorageDomain();
|
||
if ($domain && stripos($url, rtrim($domain, '/')) === 0) {
|
||
$relative = substr($url, strlen(rtrim($domain, '/')));
|
||
return ltrim($relative, '/');
|
||
}
|
||
// 非当前存储域名,保留完整 URL
|
||
return $url;
|
||
}
|
||
|
||
private static function getStorageDomain(): string
|
||
{
|
||
$default = \app\common\service\ConfigService::get('storage', 'default', 'local');
|
||
if ($default === 'local') {
|
||
return request()->domain() . '/';
|
||
}
|
||
$storage = \app\common\service\ConfigService::get('storage', $default);
|
||
return $storage ? ($storage['domain'] ?? '') : '';
|
||
}
|
||
|
||
private static function parseJsonArray($value): array
|
||
{
|
||
if (is_array($value)) return $value;
|
||
if (is_string($value)) {
|
||
$decoded = json_decode($value, true);
|
||
return is_array($decoded) ? $decoded : [];
|
||
}
|
||
return [];
|
||
}
|
||
}
|