header('医学计算器'); $content->description('列表'); $content->body($this->grid()); }); } /** * 创建新的医学计算器 * * @OA\Post( * path="/api/medical-calculators", * summary="创建新的医学计算器", * tags={"医学计算器"}, * @OA\RequestBody( * required=true, * @OA\JsonContent(ref="#/components/schemas/MedicalCalculator") * ), * @OA\Response( * response=201, * description="创建成功", * @OA\JsonContent(ref="#/components/schemas/MedicalCalculator") * ) * ) */ public function create() { return Admin::content(function (Content $content) { $content->header('医学计算器'); $content->description('新增'); $content->body($this->form()); }); } /** * 编辑现有的医学计算器 * * @OA\Get( * path="/api/medical-calculators/{id}", * summary="编辑现有的医学计算器", * tags={"医学计算器"}, * @OA\Parameter( * name="id", * in="path", * required=true, * @OA\Schema(type="integer") * ), * @OA\Response( * response=200, * description="成功", * @OA\JsonContent(ref="#/components/schemas/MedicalCalculator") * ) * ) * * @param int $id 医学计算器ID */ public function edit($id) { return Admin::content(function (Content $content) use ($id) { $content->header('医学计算器'); $content->description('编辑'); $content->body($this->form($id)->edit($id)); // 传递 $id 给 form 方法 }); } /** * 计算医学计算器的结果 * * @OA\Post( * path="/api/medical-calculators/{id}/calculate", * summary="计算医学计算器的结果", * tags={"医学计算器"}, * @OA\Parameter( * name="id", * in="path", * required=true, * @OA\Schema(type="integer") * ), * @OA\RequestBody( * required=true, * @OA\JsonContent(type="object") * ), * @OA\Response( * response=200, * description="计算结果", * @OA\JsonContent(type="object", @OA\Property(property="result", type="string")) * ) * ) * * @param Request $request 请求对象 * @param int $id 医学计算器ID * @return \Illuminate\Http\JsonResponse 计算结果的JSON响应 */ public function calculate(Request $request, $id) { $calculator = MedicalCalculator::findOrFail($id); $inputs = $request->all(); try { $result = $calculator->calculateResult($inputs); return response()->json(['result' => $result]); } catch (\Exception $e) { return response()->json(['error' => $e->getMessage()], 400); } } /** * 获取指定计算器的问题 * * @OA\Get( * path="/api/medical-calculators/{id}/questions", * summary="获取指定计算器的问题", * tags={"医学计算器"}, * @OA\Parameter( * name="id", * in="path", * required=true, * @OA\Schema(type="integer") * ), * @OA\Response( * response=200, * description="成功", * @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/MedicalQuestion")) * ) * ) * * @param int $id 医学计算器ID * @return \Illuminate\Http\JsonResponse 问题列表的JSON响应 */ public function getQuestions($id) { $questions = MedicalQuestion::where('medical_calculator_id', $id)->with('options')->get(); return response()->json($questions); } /** * 定义医学计算器的表单 * * @param int|null $id 医学计算器ID * @return \Encore\Admin\Form 表单对象 */ protected function form($id = null) { return Admin::form(MedicalCalculator::class, function (Form $form) use ($id) { $form->text('name', '计算器名称'); $form->text('disease_name', '疾病名称')->rules('nullable'); // 确保传递正确的 calculatorId $calculatorId = $id ?? $form->model()->id; $form->html($this->questionsForm($calculatorId)); $form->textarea('formula', '计算公式')->help('直接使用问题的变量名称,例如: weight / (height * height)'); $form->table('results', '结果对照表', function ($table) { $table->decimal('min_score', 8, 2, '最小分数')->rules('required|numeric'); $table->decimal('max_score', 8, 2, '最大分数')->rules('required|numeric'); $table->text('result', '结果描述'); })->default([])->customFormat(function ($value) { if (empty($value)) { return []; } if (is_string($value)) { $decoded = json_decode($value, true); return is_array($decoded) ? array_values($decoded) : []; } return is_array($value) ? array_values($value) : []; }); $form->textarea('instructions', '使用说明')->rules('nullable'); $form->saving(function (Form $form) { if (empty($form->results)) { $form->results = []; } elseif (is_array($form->results)) { $form->results = array_values($form->results); } }); $form->saved(function (Form $form) { $this->saveQuestions($form); admin_toastr('保存成功', 'success'); return redirect()->route('admin.medical-calculators.index'); }); // 在表单显示之前处理 results 字段 if ($form->isEditing()) { $form->editing(function (Form $form) { $results = $form->model()->results; if (is_string($results)) { $decoded = json_decode($results, true); $form->results = is_array($decoded) ? array_values($decoded) : []; } elseif (!is_array($results)) { $form->results = []; } else { $form->results = array_values($results); } }); } Admin::script($this->questionsScript()); }); } /** * 生成问题表单的HTML * * @param int $calculatorId 医学计算器ID * @return string 问题表单的HTML */ protected function questionsForm($calculatorId) { if (!$calculatorId) { return '
'; } $questions = MedicalQuestion::where('medical_calculator_id', $calculatorId)->with('options')->get(); $html = '
'; foreach ($questions as $index => $question) { $html .= $this->questionTemplate($index, $question); } $html .= '
'; $html .= ''; return $html; } /** * 生成单个问题的HTML模板 * * @param int|string $index 问题索引 * @param MedicalQuestion|null $question 问题对象 * @return string 单个问题的HTML模板 */ protected function questionTemplate($index, $question = null) { $index = is_numeric($index) ? $index : "' + questionIndex + '"; $html = '
'; $html .= ''; $html .= '
'; $html .= ''; $html .= ''; $html .= '
'; $html .= '
'; $html .= ''; $html .= ''; $html .= '
'; $html .= '
'; $html .= ''; $html .= ''; $html .= '
'; $html .= '
type == 'radio' || $question->type == 'checkbox') ? 'style="display:none;"' : '') . '>'; $html .= ''; $html .= ''; $html .= '
'; $html .= '
type == 'radio' || $question->type == 'checkbox') ? '' : 'style="display:none;"') . '>'; if ($question && $question->options) { foreach ($question->options as $optionIndex => $option) { $html .= $this->optionTemplate($index, $optionIndex, $option); } } $html .= '
'; $html .= ''; $html .= ''; $html .= '
'; return $html; } /** * 生成单个选项的HTML模板 * * @param int|string $questionIndex 问题索引 * @param int|string $optionIndex 选项索引 * @param MedicalOption|null $option 选项对象 * @return string 单个选项的HTML模板 */ protected function optionTemplate($questionIndex, $optionIndex, $option = null) { $questionIndex = is_numeric($questionIndex) ? $questionIndex : "' + questionIndex + '"; $optionIndex = is_numeric($optionIndex) ? $optionIndex : "' + optionIndex + '"; $html = '
'; $html .= ''; $html .= '
'; $html .= ''; $html .= ''; $html .= '
'; $html .= '
'; $html .= ''; $html .= ''; $html .= '
'; $html .= ''; $html .= '
'; return $html; } /** * 生成问题和选项的JavaScript * * @return string JavaScript代码 */ protected function questionsScript() { $questionTemplate = json_encode($this->questionTemplate("' + questionIndex + '")); $optionTemplate = json_encode($this->optionTemplate("' + questionIndex + '", "' + optionIndex + '")); return <<json($calculators); } /** * 获取指定计算器 * * @param int $id 医学计算器ID * @return \Illuminate\Http\JsonResponse 计算器详情 */ public function show($id) { $calculator = MedicalCalculator::findOrFail($id); return response()->json($calculator); } /** * 更新指定计算器 * * @param Request $request 请求对象 * @param int $id 医学计算器ID * @return \Illuminate\Http\JsonResponse 更新后的计算器详情 */ public function update(Request $request, $id) { $calculator = MedicalCalculator::findOrFail($id); $calculator->update($request->all()); $this->saveQuestions($calculator); admin_toastr('更新成功', 'success'); return redirect()->route('admin.medical-calculators.index'); } /** * 删除指定计算器(支持批量删除) * * @param Request $request * @return \Illuminate\Http\JsonResponse 删除结果 */ public function destroy($id) { $ids = is_array($id) ? $id : [$id]; $successCount = 0; $failCount = 0; \Illuminate\Support\Facades\DB::transaction(function () use ($ids, &$successCount, &$failCount) { // 批量删除关联的问题和选项 $deletedOptionsCount = MedicalOption::whereIn('medical_question_id', function($query) use ($ids) { $query->select('id') ->from('medical_questions') ->whereIn('medical_calculator_id', $ids); })->delete(); $deletedQuestionsCount = MedicalQuestion::whereIn('medical_calculator_id', $ids)->delete(); // 删除计算器 $deletedCalculatorsCount = MedicalCalculator::whereIn('id', $ids)->delete(); $successCount = $deletedCalculatorsCount; $failCount = count($ids) - $deletedCalculatorsCount; }); $message = "成功删除 {$successCount} 个计算器"; if ($failCount > 0) { $message .= ",{$failCount} 个计算器删除失败"; } return response()->json(['message' => $message, 'status' => true]); } /** * 保存问题和选项 * * @param Form|MedicalCalculator $formOrModel 表单对象或模型实例 */ protected function saveQuestions($formOrModel) { if ($formOrModel instanceof Form) { $formModelId = $formOrModel->model()->id; } elseif ($formOrModel instanceof MedicalCalculator) { $formModelId = $formOrModel->id; } else { throw new \InvalidArgumentException('Invalid argument type'); } $questionsData = request()->input('questions'); if (!is_array($questionsData)) { return; // 如果 $questionsData 不是数组,直接返回 } foreach ($questionsData as $index => $questionData) { if (!isset($questionData['question']) || !isset($questionData['type'])) { continue; } try { $variableName = !empty($questionData['variable_name']) ? $questionData['variable_name'] : 'VAR_' . ($index + 1); $question = MedicalQuestion::updateOrCreate( ['id' => $questionData['id'] ?? null], [ 'medical_calculator_id' => $formModelId, 'question' => $questionData['question'], 'variable_name' => $variableName, 'type' => $questionData['type'], 'score' => isset($questionData['score']) ? (float)$questionData['score'] : null, ] ); // 删除旧的选项 $question->options()->delete(); if (isset($questionData['options']) && is_array($questionData['options'])) { foreach ($questionData['options'] as $optionData) { if (!isset($optionData['content'])) { continue; } $option = new MedicalOption([ 'content' => $optionData['content'], 'score' => isset($optionData['score']) ? (float)$optionData['score'] : 0, ]); $question->options()->save($option); } } } catch (\Exception $e) { \Illuminate\Support\Facades\Log::error('Error saving question: ' . $e->getMessage()); } } } /** * 定义医学计算器的表格 * * @return \Encore\Admin\Grid 表格对象 */ protected function grid() { return Admin::grid(MedicalCalculator::class, function (Grid $grid) { $grid->name('计算器名称'); $grid->disease_name('疾病名称'); $grid->column('questions_count', '问题数量'); $grid->paginate(20); $grid->disableExport(); $grid->actions(function ($actions) { $actions->disableView(); }); $grid->filter(function ($filter) { $filter->disableIdFilter(); $filter->like('name', '输入名称搜索'); }); // 启用批量删除 $grid->batchActions(function ($batch) { $batch->disableDelete(); $batch->add(new BatchDeleteAction()); }); }); } }