listKnowledgePoints(1, 1000); $this->knowledgePoints = $result['data'] ?? []; } public function edit(string $code): void { $this->mountAction('edit', ['code' => $code]); } public function delete(string $code): void { $this->mountAction('delete', ['code' => $code]); } protected function getHeaderActions(): array { return [ Action::make('create') ->label('新增知识点') ->icon('heroicon-o-plus') ->color('primary') ->form([ TextInput::make('cn_name')->label('中文名称')->required(), TextInput::make('en_name')->label('英文名称'), TextInput::make('kp_code')->label('知识点编码')->placeholder('自动生成或手动输入'), Select::make('phase')->label('学段')->options([ '小学' => '小学', '初中' => '初中', '高中' => '高中' ])->required(), Select::make('grade')->label('年级')->options([ 7 => '七年级', 8 => '八年级', 9 => '九年级' ]), TextInput::make('category')->label('分类')->default('数学'), TextInput::make('importance')->label('重要性')->numeric()->default(5), Textarea::make('description')->label('描述'), ]) ->action(function (array $data, KnowledgeGraphService $service) { if ($service->createKnowledgePoint($data)) { Notification::make()->title('创建成功')->success()->send(); $this->mount($service); } else { Notification::make()->title('创建失败')->danger()->send(); } }), Action::make('import') ->label('导入图谱数据') ->icon('heroicon-o-arrow-up-tray') ->color('success') ->form([ FileUpload::make('tree_file') ->label('Tree JSON (知识点结构)') ->helperText('上传包含知识点层次结构的 JSON 文件') ->required() ->storeFiles(false), FileUpload::make('edges_file') ->label('Edges JSON (依赖关系)') ->helperText('上传包含知识点间关系的 JSON 文件') ->required() ->storeFiles(false), ]) ->action(function (array $data, KnowledgeGraphService $service) { try { $treeFile = $data['tree_file']; $edgesFile = $data['edges_file']; if (is_array($treeFile)) $treeFile = reset($treeFile); if (is_array($edgesFile)) $edgesFile = reset($edgesFile); // 详细日志 \Log::info('开始导入知识图谱', [ 'tree_file' => is_object($treeFile) ? get_class($treeFile) : $treeFile, 'edges_file' => is_object($edgesFile) ? get_class($edgesFile) : $edgesFile ]); // 处理 TemporaryUploadedFile 对象 $treeContent = null; $edgesContent = null; // 读取 Tree 文件 if ($treeFile instanceof \Illuminate\Http\UploadedFile) { // 从临时上传文件读取 $treeContent = json_decode(file_get_contents($treeFile->getRealPath()), true); } elseif (is_string($treeFile)) { // 从字符串路径读取 if (Storage::disk('public')->exists($treeFile)) { $treeContent = json_decode(Storage::disk('public')->get($treeFile), true); } elseif (file_exists($treeFile)) { $treeContent = json_decode(file_get_contents($treeFile), true); } else { throw new \Exception("Tree文件不存在: {$treeFile}"); } } else { throw new \Exception("无效的Tree文件类型"); } // 读取 Edges 文件 if ($edgesFile instanceof \Illuminate\Http\UploadedFile) { $edgesContent = json_decode(file_get_contents($edgesFile->getRealPath()), true); } elseif (is_string($edgesFile)) { if (Storage::disk('public')->exists($edgesFile)) { $edgesContent = json_decode(Storage::disk('public')->get($edgesFile), true); } elseif (file_exists($edgesFile)) { $edgesContent = json_decode(file_get_contents($edgesFile), true); } else { throw new \Exception("Edges文件不存在: {$edgesFile}"); } } else { throw new \Exception("无效的Edges文件类型"); } if (json_last_error() !== JSON_ERROR_NONE) { throw new \Exception('JSON解析错误: ' . json_last_error_msg()); } if (!$treeContent) { throw new \Exception('Tree JSON解析失败或为空'); } if (!$edgesContent) { throw new \Exception('Edges JSON解析失败或为空'); } \Log::info('文件解析成功', [ 'tree_keys' => array_keys($treeContent), 'edges_count' => is_array($edgesContent) ? count($edgesContent) : 0 ]); if ($service->importGraph($treeContent, $edgesContent)) { Notification::make()->title('导入成功')->success()->send(); $this->mount($service); } else { Notification::make()->title('导入失败')->body('请查看日志获取详细信息')->danger()->send(); } } catch (\Exception $e) { \Log::error('导入知识图谱失败', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); Notification::make() ->title('导入失败') ->body($e->getMessage()) ->danger() ->persistent() ->send(); } }) ]; } public function editAction(): Action { return Action::make('edit') ->label('编辑') ->icon('heroicon-o-pencil-square') ->color('warning') ->modalHeading('编辑知识点') ->modalDescription('修改知识点的基本信息和属性') ->form([ TextInput::make('cn_name')->label('中文名称')->required(), TextInput::make('en_name')->label('英文名称'), Select::make('phase')->label('学段')->options([ '小学' => '小学', '初中' => '初中', '高中' => '高中' ])->required(), Select::make('grade')->label('年级')->options([ 7 => '七年级', 8 => '八年级', 9 => '九年级' ]), TextInput::make('category')->label('分类'), TextInput::make('importance')->label('重要性')->numeric(), Textarea::make('description')->label('描述'), ]) ->fillForm(function (array $arguments, KnowledgeGraphService $service) { $code = $arguments['code']; $data = $service->getKnowledgePoint($code); return $data ?? []; }) ->action(function (array $data, array $arguments, KnowledgeGraphService $service) { if ($service->updateKnowledgePoint($arguments['code'], $data)) { Notification::make()->title('更新成功')->success()->send(); $this->mount($service); } else { Notification::make()->title('更新失败')->danger()->send(); } }); } public function deleteAction(): Action { return Action::make('delete') ->label('删除') ->icon('heroicon-o-trash') ->color('error') ->requiresConfirmation() ->modalHeading('删除知识点') ->modalDescription('此操作将永久删除该知识点及其所有关联数据,此操作不可恢复!') ->modalConfirmButtonLabel('确认删除') ->action(function (array $arguments, KnowledgeGraphService $service) { if ($service->deleteKnowledgePoint($arguments['code'])) { Notification::make()->title('删除成功')->success()->send(); $this->mount($service); } else { Notification::make()->title('删除失败')->danger()->send(); } }); } }