1
This commit is contained in:
@@ -138,6 +138,25 @@ class DiagnosisController extends BaseAdminController
|
||||
return $this->data($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 跟踪信息(血糖血压 / 饮食 / 运动)—— 按日期区间 lazy load
|
||||
*
|
||||
* 路由:GET /tcm.diagnosis/trackingWindow?id=:diagnosisId&start_date=&end_date=
|
||||
* 权限:tcm.diagnosis/readonlyDetail(与只读病例页同档;接诊台亦复用)
|
||||
*
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function trackingWindow()
|
||||
{
|
||||
$params = (new DiagnosisValidate())->goCheck('trackingWindow');
|
||||
$result = DiagnosisLogic::fetchTrackingWindow(
|
||||
(int) $params['id'],
|
||||
(string) ($params['start_date'] ?? ''),
|
||||
(string) ($params['end_date'] ?? '')
|
||||
);
|
||||
return $this->data($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 诊单挂号 / 取消挂号 操作日志(谁在何时操作)
|
||||
*/
|
||||
|
||||
@@ -516,10 +516,8 @@ class AppointmentLogic extends BaseLogic
|
||||
? DiagnosisLogic::detail(['id' => $diagnosisId])
|
||||
: [];
|
||||
|
||||
// 3) 血糖血压记录
|
||||
$bloodRecords = $diagnosisId > 0
|
||||
? BloodRecordLogic::getRecordsByPatient(['diagnosis_id' => $diagnosisId])
|
||||
: [];
|
||||
// 3) 跟踪信息(血糖血压 / 饮食 / 运动)改为前端按窗口 lazy load,
|
||||
// 详见 DiagnosisController::trackingWindow。此处不再一次性返回。
|
||||
|
||||
// 4) 补全医助姓名(detail() 未关联 admin 助理表)
|
||||
$assistantName = '';
|
||||
@@ -554,7 +552,6 @@ class AppointmentLogic extends BaseLogic
|
||||
return [
|
||||
'appointment' => $appointment,
|
||||
'diagnosis' => $diagnosis,
|
||||
'blood_records' => $bloodRecords,
|
||||
'doctor_notes' => $doctorNotes,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -3397,14 +3397,8 @@ class DiagnosisLogic extends BaseLogic
|
||||
// 3) 最近一条挂号(PatientInfoCard 显示用,无挂号则给默认空对象)
|
||||
$appointment = self::buildLatestAppointmentForReadonly((int) ($diagnosis['id'] ?? $diagnosisId), $diagnosis);
|
||||
|
||||
// 4) 最近 30 天的跟踪记录(一次性 join 出三类,前端透视为矩阵)
|
||||
$windowDays = 30;
|
||||
$sinceTs = strtotime('-' . $windowDays . ' days');
|
||||
$sinceTs = $sinceTs > 0 ? $sinceTs : 0;
|
||||
|
||||
$bloodRecords = self::fetchBloodRecordsForReadonly($diagnosisId, $sinceTs);
|
||||
$dietRecords = self::fetchDietRecordsForReadonly($diagnosisId, $sinceTs);
|
||||
$exerciseRecords = self::fetchExerciseRecordsForReadonly($diagnosisId, $sinceTs);
|
||||
// 4) 跟踪信息(血糖血压 / 饮食 / 运动)改为前端按窗口 lazy load,
|
||||
// 详见 DiagnosisController::trackingWindow。此处不再一次性返回。
|
||||
|
||||
// 5) 医生备注
|
||||
$doctorNotes = DoctorNoteLogic::getByDiagnosis($diagnosisId);
|
||||
@@ -3419,13 +3413,39 @@ class DiagnosisLogic extends BaseLogic
|
||||
return [
|
||||
'appointment' => $appointment,
|
||||
'diagnosis' => $diagnosis,
|
||||
'blood_records' => $bloodRecords,
|
||||
'diet_records' => $dietRecords,
|
||||
'exercise_records' => $exerciseRecords,
|
||||
'doctor_notes' => $doctorNotes,
|
||||
'unserved_days' => $unservedDays,
|
||||
'last_blood_record_at' => $lastBloodRecordAt,
|
||||
'window_days' => $windowDays,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 取指定日期区间内的三类跟踪记录(血糖血压 / 饮食 / 运动),供 readonlyDetail 与
|
||||
* 医生接诊台 reception 通过独立接口 lazy load。
|
||||
*
|
||||
* 区间语义:闭区间 [startDate, endDate](Y-m-d),均不传则不限。
|
||||
*
|
||||
* @return array{
|
||||
* blood_records: array<int,array<string,mixed>>,
|
||||
* diet_records: array<int,array<string,mixed>>,
|
||||
* exercise_records: array<int,array<string,mixed>>,
|
||||
* start_date: string,
|
||||
* end_date: string,
|
||||
* }
|
||||
*/
|
||||
public static function fetchTrackingWindow(int $diagnosisId, string $startDate = '', string $endDate = ''): array
|
||||
{
|
||||
$sinceTs = $startDate !== '' ? (int) strtotime($startDate . ' 00:00:00') : 0;
|
||||
$untilTs = $endDate !== '' ? (int) strtotime($endDate . ' 23:59:59') : 0;
|
||||
$sinceTs = $sinceTs > 0 ? $sinceTs : 0;
|
||||
$untilTs = $untilTs > 0 ? $untilTs : 0;
|
||||
|
||||
return [
|
||||
'blood_records' => self::fetchBloodRecordsForReadonly($diagnosisId, $sinceTs, $untilTs),
|
||||
'diet_records' => self::fetchDietRecordsForReadonly($diagnosisId, $sinceTs, $untilTs),
|
||||
'exercise_records' => self::fetchExerciseRecordsForReadonly($diagnosisId, $sinceTs, $untilTs),
|
||||
'start_date' => $startDate,
|
||||
'end_date' => $endDate,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -3502,12 +3522,15 @@ class DiagnosisLogic extends BaseLogic
|
||||
/**
|
||||
* @return array<int,array<string,mixed>>
|
||||
*/
|
||||
private static function fetchBloodRecordsForReadonly(int $diagnosisId, int $sinceTs): array
|
||||
private static function fetchBloodRecordsForReadonly(int $diagnosisId, int $sinceTs, int $untilTs = 0): array
|
||||
{
|
||||
$query = BloodRecord::where('diagnosis_id', $diagnosisId);
|
||||
if ($sinceTs > 0) {
|
||||
$query->where('record_date', '>=', $sinceTs);
|
||||
}
|
||||
if ($untilTs > 0) {
|
||||
$query->where('record_date', '<=', $untilTs);
|
||||
}
|
||||
$rows = $query->order('record_date', 'desc')
|
||||
->order('record_time', 'desc')
|
||||
->select()
|
||||
@@ -3526,12 +3549,15 @@ class DiagnosisLogic extends BaseLogic
|
||||
/**
|
||||
* @return array<int,array<string,mixed>>
|
||||
*/
|
||||
private static function fetchDietRecordsForReadonly(int $diagnosisId, int $sinceTs): array
|
||||
private static function fetchDietRecordsForReadonly(int $diagnosisId, int $sinceTs, int $untilTs = 0): array
|
||||
{
|
||||
$query = DietRecord::where('diagnosis_id', $diagnosisId);
|
||||
if ($sinceTs > 0) {
|
||||
$query->where('record_date', '>=', $sinceTs);
|
||||
}
|
||||
if ($untilTs > 0) {
|
||||
$query->where('record_date', '<=', $untilTs);
|
||||
}
|
||||
$rows = $query->order('record_date', 'desc')->select()->toArray();
|
||||
|
||||
foreach ($rows as &$row) {
|
||||
@@ -3546,12 +3572,15 @@ class DiagnosisLogic extends BaseLogic
|
||||
/**
|
||||
* @return array<int,array<string,mixed>>
|
||||
*/
|
||||
private static function fetchExerciseRecordsForReadonly(int $diagnosisId, int $sinceTs): array
|
||||
private static function fetchExerciseRecordsForReadonly(int $diagnosisId, int $sinceTs, int $untilTs = 0): array
|
||||
{
|
||||
$query = ExerciseRecord::where('diagnosis_id', $diagnosisId);
|
||||
if ($sinceTs > 0) {
|
||||
$query->where('record_date', '>=', $sinceTs);
|
||||
}
|
||||
if ($untilTs > 0) {
|
||||
$query->where('record_date', '<=', $untilTs);
|
||||
}
|
||||
$rows = $query->order('record_date', 'desc')
|
||||
->append(['intensity_text'])
|
||||
->select()
|
||||
|
||||
@@ -37,6 +37,8 @@ class DiagnosisValidate extends BaseValidate
|
||||
'tongue_images' => 'array',
|
||||
'report_files' => 'array',
|
||||
'diabetes_discovery_year' => 'max:50',
|
||||
'start_date' => 'date',
|
||||
'end_date' => 'date|checkDateRange',
|
||||
];
|
||||
|
||||
protected $message = [
|
||||
@@ -55,6 +57,8 @@ class DiagnosisValidate extends BaseValidate
|
||||
'status.in' => '状态参数错误',
|
||||
'current_medications.max' => '在用药物最多2000个字符',
|
||||
'diabetes_discovery_year.max' => '发现糖尿病患病史最多50个字符',
|
||||
'start_date.date' => '开始日期格式不正确',
|
||||
'end_date.date' => '结束日期格式不正确',
|
||||
];
|
||||
|
||||
public function sceneAdd()
|
||||
@@ -76,7 +80,12 @@ class DiagnosisValidate extends BaseValidate
|
||||
{
|
||||
return $this->only(['id']);
|
||||
}
|
||||
|
||||
|
||||
public function sceneTrackingWindow()
|
||||
{
|
||||
return $this->only(['id', 'start_date', 'end_date']);
|
||||
}
|
||||
|
||||
public function sceneGenerateQrcode()
|
||||
{
|
||||
return $this->only(['diagnosis_id', 'doctor_id', 'patient_id', 'share_user_id', 'mini_program_path'])
|
||||
@@ -112,6 +121,16 @@ class DiagnosisValidate extends BaseValidate
|
||||
return true;
|
||||
}
|
||||
|
||||
/** end_date 不能早于 start_date */
|
||||
protected function checkDateRange($value, $rule, $data = [])
|
||||
{
|
||||
$start = $data['start_date'] ?? '';
|
||||
if ($start && $value && strtotime($value) < strtotime($start)) {
|
||||
return '结束日期不能早于开始日期';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** 视频场景需 doctor_id,确认诊单需 diagnosis_id */
|
||||
protected function checkQrcodeIds($value, $rule, $data = [])
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user