recordId = (int) $request->route('record'); if (!$this->recordId) { abort(404); } // 从API获取教材数据 $apiService = app(TextbookApiService::class); $textbookData = $apiService->getTextbook($this->recordId); if (!$textbookData) { abort(404); } // 初始化表单数据 $this->data = $textbookData; $this->form->fill($this->data); } public function save(): void { // 验证数据 $this->validate([ 'data.series_id' => 'required|integer', 'data.stage' => 'required|string', 'data.grade' => 'nullable|integer', 'data.semester' => 'nullable|integer', 'data.official_title' => 'required|string|max:255', 'data.isbn' => 'nullable|string|max:255', 'data.status' => 'required|string|in:draft,published,archived', ]); // 只传递标量字段到API,跳过关系字段和嵌套对象 $allowedFields = [ 'series_id', 'stage', 'grade', 'semester', 'naming_scheme', 'track', 'module_type', 'volume_no', 'legacy_code', 'curriculum_standard_year', 'curriculum_revision_year', 'approval_authority', 'approval_year', 'edition_label', 'official_title', 'aliases', 'isbn', 'cover_path', 'status', 'sort_order', 'meta' ]; $updateData = []; foreach ($allowedFields as $field) { if (isset($this->data[$field]) && !is_array($this->data[$field]) && !is_object($this->data[$field])) { $updateData[$field] = $this->data[$field]; } } // 调用API更新 $apiService = app(TextbookApiService::class); $updatedData = $apiService->updateTextbook($this->recordId, $updateData); // 更新本地数据 $this->data = array_merge($this->data, $updatedData); // 显示成功消息 \Filament\Notifications\Notification::make() ->title('教材更新成功') ->success() ->send(); } protected function getHeaderActions(): array { return [ Actions\Action::make('back') ->label('返回列表') ->url(static::$resource::getUrl('index')) ->color('gray'), ]; } public function getTitle(): string { return '编辑教材'; } public function getView(): string { return 'filament.resources.textbook-resource.edit'; } public function form(\Filament\Schemas\Schema $schema): \Filament\Schemas\Schema { return $schema ->schema([ Section::make('基本信息') ->schema([ Forms\Components\Select::make('series_id') ->label('教材系列') ->options(function () { $apiService = app(TextbookApiService::class); $series = $apiService->getTextbookSeries(); $options = []; foreach ($series['data'] as $s) { $options[$s['id']] = $s['name']; } return $options; }) ->required() ->searchable(), Forms\Components\Select::make('stage') ->label('学段') ->options([ 'primary' => '小学', 'junior' => '初中', 'senior' => '高中', ]) ->required() ->reactive(), Forms\Components\TextInput::make('grade') ->label('年级') ->numeric() ->helperText('例如:7表示七年级'), Forms\Components\Select::make('semester') ->label('学期') ->options([ 1 => '上学期', 2 => '下学期', ]) ->helperText('选择学期'), Forms\Components\TextInput::make('official_title') ->label('教材名称') ->required() ->maxLength(255), Forms\Components\TextInput::make('isbn') ->label('ISBN') ->maxLength(255), Forms\Components\Select::make('status') ->label('状态') ->options([ 'draft' => '草稿', 'published' => '已发布', 'archived' => '已归档', ]) ->required(), ]) ->columns(2), Section::make('封面上传') ->schema([ Forms\Components\FileUpload::make('cover_path') ->label('封面图片') ->image() ->directory('textbook-covers') ->saveUploadedFileUsing(function ($component, $file) { $uploader = app(TextbookCoverStorageService::class); $url = $uploader->uploadCover($file, $this->recordId ? (string) $this->recordId : null); if ($url) { return $url; } return $file->storePubliclyAs( $component->getDirectory(), $component->getUploadedFileNameForStorage($file), $component->getDiskName(), ); }) ->helperText('建议尺寸 600x800,JPG/PNG'), ]) ->extraAttributes(['id' => 'cover']), ]) ->statePath('data'); } }