更新
This commit is contained in:
@@ -3025,7 +3025,7 @@ class DiagnosisLogic extends BaseLogic
|
||||
->field([
|
||||
'id', 'patient_id', 'patient_name', 'gender', 'age',
|
||||
'diagnosis_date', 'diagnosis_type', 'syndrome_type',
|
||||
'status', 'create_time', 'update_time'
|
||||
'status', 'create_source', 'create_time', 'update_time'
|
||||
])
|
||||
->order('create_time', 'desc')
|
||||
->select()
|
||||
|
||||
@@ -19,6 +19,8 @@ use app\adminapi\logic\tcm\TrackingNoteLogic;
|
||||
use app\api\logic\tcm\DailyGamifyLogic;
|
||||
use app\api\logic\tcm\DailyFamilyLikeLogic;
|
||||
use app\api\logic\tcm\DailyShareLogic;
|
||||
use app\api\logic\tcm\DailyPhoneLogic;
|
||||
use app\api\logic\tcm\DailyDietAiLogic;
|
||||
use app\adminapi\logic\ConfigLogic;
|
||||
use app\common\model\tcm\Diagnosis;
|
||||
use app\common\model\tcm\BloodRecord;
|
||||
@@ -242,7 +244,8 @@ class TcmController extends BaseApiController
|
||||
'treatment_principle' => $this->request->post('treatment_principle'),
|
||||
'prescription' => $this->request->post('prescription'),
|
||||
'doctor_advice' => $this->request->post('doctor_advice'),
|
||||
'remark' => $this->request->post('remark')
|
||||
'remark' => $this->request->post('remark'),
|
||||
'create_source' => DailyPhoneLogic::CREATE_SOURCE_MNP,
|
||||
];
|
||||
// patient_id 可选:不传则创建时自动生成(新患者首张就诊卡)
|
||||
try {
|
||||
@@ -469,6 +472,34 @@ class TcmController extends BaseApiController
|
||||
return ['ok' => true, 'diagnosis' => $diagnosis];
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 日常记录-手机号快捷建档(无就诊卡时,已绑定手机号即可录入血糖)
|
||||
*
|
||||
* 路由:POST /api/tcm/dailyEnsurePhoneContext
|
||||
*
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function dailyEnsurePhoneContext()
|
||||
{
|
||||
$sex = $this->request->post('sex', null);
|
||||
$options = [];
|
||||
if ($sex !== null && $sex !== '') {
|
||||
$options['sex'] = (int) $sex;
|
||||
}
|
||||
|
||||
$result = DailyPhoneLogic::ensureDailyContext((int) $this->userId, $options);
|
||||
if (empty($result['ok'])) {
|
||||
$data = [];
|
||||
if (!empty($result['need_mobile'])) {
|
||||
$data['need_mobile'] = 1;
|
||||
}
|
||||
return $this->fail($result['error'] ?? '无法开始录入', $data);
|
||||
}
|
||||
|
||||
unset($result['ok'], $result['error'], $result['need_mobile']);
|
||||
return $this->data($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 日常记录-获取今日已录入的血糖血压记录(患者端)
|
||||
*
|
||||
@@ -777,6 +808,136 @@ class TcmController extends BaseApiController
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 日常记录-AI 今日饮食推荐(霍大夫升糖指数)
|
||||
*
|
||||
* 路由:GET /api/tcm/dailyDietAiRecommend?diagnosis_id=:id&refresh=0|1
|
||||
*/
|
||||
public function dailyDietAiRecommend()
|
||||
{
|
||||
$diagnosisId = (int) $this->request->get('diagnosis_id', 0);
|
||||
$check = $this->ensurePatientOwnsDiagnosis($diagnosisId);
|
||||
if (!$check['ok']) {
|
||||
return $this->fail($check['error']);
|
||||
}
|
||||
|
||||
$refresh = (int) $this->request->get('refresh', 0) === 1;
|
||||
$result = DailyDietAiLogic::getDailyRecommend($diagnosisId, $refresh);
|
||||
if (empty($result['ok'])) {
|
||||
return $this->fail($result['error'] ?? '获取推荐失败');
|
||||
}
|
||||
|
||||
return $this->data($result['data']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 日常记录-AI 饮食问答(能不能吃某食物)
|
||||
*
|
||||
* 路由:POST /api/tcm/dailyDietAiAsk body: diagnosis_id, question
|
||||
*/
|
||||
public function dailyDietAiAsk()
|
||||
{
|
||||
$diagnosisId = (int) $this->request->post('diagnosis_id', 0);
|
||||
$check = $this->ensurePatientOwnsDiagnosis($diagnosisId);
|
||||
if (!$check['ok']) {
|
||||
return $this->fail($check['error']);
|
||||
}
|
||||
|
||||
$question = trim((string) $this->request->post('question', ''));
|
||||
$result = DailyDietAiLogic::askFood($diagnosisId, $question);
|
||||
if (empty($result['ok'])) {
|
||||
return $this->fail($result['error'] ?? '咨询失败');
|
||||
}
|
||||
|
||||
return $this->data($result['data']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 日常记录-AI 今日饮食推荐(SSE 流式)
|
||||
*
|
||||
* 路由:GET /api/tcm/dailyDietAiRecommendStream?diagnosis_id=:id&refresh=0|1
|
||||
*/
|
||||
public function dailyDietAiRecommendStream()
|
||||
{
|
||||
$diagnosisId = (int) $this->request->get('diagnosis_id', 0);
|
||||
$check = $this->ensurePatientOwnsDiagnosis($diagnosisId);
|
||||
if (!$check['ok']) {
|
||||
return $this->fail($check['error']);
|
||||
}
|
||||
|
||||
$refresh = (int) $this->request->get('refresh', 0) === 1;
|
||||
$this->runDailyDietSse(static function (callable $emit) use ($diagnosisId, $refresh): void {
|
||||
DailyDietAiLogic::streamDailyRecommend($diagnosisId, $refresh, $emit);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 日常记录-AI 饮食问答(SSE 流式)
|
||||
*
|
||||
* 路由:POST /api/tcm/dailyDietAiAskStream body: diagnosis_id, question
|
||||
*/
|
||||
public function dailyDietAiAskStream()
|
||||
{
|
||||
$diagnosisId = (int) $this->request->post('diagnosis_id', 0);
|
||||
$check = $this->ensurePatientOwnsDiagnosis($diagnosisId);
|
||||
if (!$check['ok']) {
|
||||
return $this->fail($check['error']);
|
||||
}
|
||||
|
||||
$question = trim((string) $this->request->post('question', ''));
|
||||
$this->runDailyDietSse(static function (callable $emit) use ($diagnosisId, $question): void {
|
||||
DailyDietAiLogic::streamAskFood($diagnosisId, $question, $emit);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable(callable(string, array<string, mixed>):void):void $runner
|
||||
*/
|
||||
private function runDailyDietSse(callable $runner): void
|
||||
{
|
||||
while (ob_get_level() > 0) {
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
@ini_set('output_buffering', 'off');
|
||||
@ini_set('zlib.output_compression', '0');
|
||||
if (function_exists('apache_setenv')) {
|
||||
@apache_setenv('no-gzip', '1');
|
||||
}
|
||||
|
||||
header('Content-Type: text/event-stream; charset=utf-8');
|
||||
header('Cache-Control: no-cache, no-transform');
|
||||
header('Connection: keep-alive');
|
||||
header('X-Accel-Buffering: no');
|
||||
header('Content-Encoding: none');
|
||||
|
||||
// 撑开 Nginx/FastCGI 缓冲,让后续 chunk 能立即下发
|
||||
echo ':' . str_repeat(' ', 2048) . "\n\n";
|
||||
if (function_exists('ob_flush')) {
|
||||
@ob_flush();
|
||||
}
|
||||
flush();
|
||||
|
||||
$emit = static function (string $event, array $payload): void {
|
||||
echo 'event: ' . $event . "\n";
|
||||
echo 'data: ' . json_encode($payload, JSON_UNESCAPED_UNICODE) . "\n\n";
|
||||
if (function_exists('ob_flush')) {
|
||||
@ob_flush();
|
||||
}
|
||||
flush();
|
||||
};
|
||||
|
||||
$emit('start', ['message' => '已连接,正在生成…']);
|
||||
|
||||
try {
|
||||
$runner($emit);
|
||||
} catch (\Throwable $e) {
|
||||
$emit('error', ['message' => '服务异常,请稍后再试']);
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 日常记录-获取今日运动记录
|
||||
*
|
||||
|
||||
@@ -255,10 +255,14 @@ class UserLogic extends BaseLogic
|
||||
}
|
||||
|
||||
// 绑定手机号
|
||||
User::update([
|
||||
$update = [
|
||||
'id' => $params['user_id'],
|
||||
'mobile' => $phoneNumber
|
||||
]);
|
||||
'mobile' => $phoneNumber,
|
||||
];
|
||||
if (isset($params['sex']) && in_array((int) $params['sex'], [1, 2], true)) {
|
||||
$update['sex'] = (int) $params['sex'];
|
||||
}
|
||||
User::update($update);
|
||||
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
|
||||
@@ -27,10 +27,12 @@ class UserValidate extends BaseValidate
|
||||
|
||||
protected $rule = [
|
||||
'code' => 'require',
|
||||
'sex' => 'in:1,2',
|
||||
];
|
||||
|
||||
protected $message = [
|
||||
'code.require' => '参数缺失',
|
||||
'sex.in' => '性别参数无效',
|
||||
];
|
||||
|
||||
|
||||
@@ -42,7 +44,7 @@ class UserValidate extends BaseValidate
|
||||
*/
|
||||
public function sceneGetMobileByMnp()
|
||||
{
|
||||
return $this->only(['code']);
|
||||
return $this->only(['code', 'sex']);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user