EditTextbook.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. <?php
  2. namespace App\Filament\Resources\TextbookResource\Pages;
  3. use App\Filament\Resources\TextbookResource;
  4. use App\Services\TextbookApiService;
  5. use App\Models\Textbook;
  6. use Filament\Actions;
  7. use Filament\Resources\Pages\Page;
  8. use Illuminate\Http\Request;
  9. class EditTextbook extends Page
  10. {
  11. protected static string $resource = TextbookResource::class;
  12. public array $data = [];
  13. public ?int $recordId = null;
  14. public ?\Filament\Forms\Form $form = null;
  15. public function mount(Request $request): void
  16. {
  17. // 从路由参数获取教材ID,避免Livewire的隐式绑定
  18. $this->recordId = (int) $request->route('record');
  19. if (!$this->recordId) {
  20. abort(404);
  21. }
  22. // 从API获取教材数据
  23. $apiService = app(TextbookApiService::class);
  24. $textbookData = $apiService->getTextbook($this->recordId);
  25. if (!$textbookData) {
  26. abort(404);
  27. }
  28. // 初始化表单数据
  29. $this->data = $textbookData;
  30. }
  31. public function save(): void
  32. {
  33. // 验证数据
  34. $this->validate([
  35. 'data.series_id' => 'required|integer',
  36. 'data.stage' => 'required|string',
  37. 'data.grade' => 'nullable|integer',
  38. 'data.semester' => 'nullable|integer',
  39. 'data.official_title' => 'required|string|max:255',
  40. 'data.isbn' => 'nullable|string|max:255',
  41. 'data.status' => 'required|string|in:draft,published,archived',
  42. ]);
  43. // 只传递标量字段到API,跳过关系字段和嵌套对象
  44. $allowedFields = [
  45. 'series_id', 'stage', 'grade', 'semester', 'naming_scheme',
  46. 'track', 'module_type', 'volume_no', 'legacy_code',
  47. 'curriculum_standard_year', 'curriculum_revision_year',
  48. 'approval_authority', 'approval_year', 'edition_label',
  49. 'official_title', 'aliases', 'isbn',
  50. 'cover_path', 'status', 'sort_order', 'meta'
  51. ];
  52. $updateData = [];
  53. foreach ($allowedFields as $field) {
  54. if (isset($this->data[$field]) && !is_array($this->data[$field]) && !is_object($this->data[$field])) {
  55. $updateData[$field] = $this->data[$field];
  56. }
  57. }
  58. // 调用API更新
  59. $apiService = app(TextbookApiService::class);
  60. $updatedData = $apiService->updateTextbook($this->recordId, $updateData);
  61. // 更新本地数据
  62. $this->data = array_merge($this->data, $updatedData);
  63. // 显示成功消息
  64. \Filament\Notifications\Notification::make()
  65. ->title('教材更新成功')
  66. ->success()
  67. ->send();
  68. }
  69. protected function getHeaderActions(): array
  70. {
  71. return [
  72. Actions\Action::make('back')
  73. ->label('返回列表')
  74. ->url(static::$resource::getUrl('index'))
  75. ->color('gray'),
  76. ];
  77. }
  78. public function getTitle(): string
  79. {
  80. return '编辑教材';
  81. }
  82. public function getView(): string
  83. {
  84. return 'filament.resources.textbook-resource.edit';
  85. }
  86. public function form(\Filament\Forms\Form $form): \Filament\Forms\Form
  87. {
  88. return $form
  89. ->schema([
  90. \Filament\Forms\Components\Section::make('基本信息')
  91. ->schema([
  92. \Filament\Forms\Components\Select::make('data.series_id')
  93. ->label('教材系列')
  94. ->options(function () {
  95. $apiService = app(TextbookApiService::class);
  96. $series = $apiService->getTextbookSeries();
  97. $options = [];
  98. foreach ($series['data'] as $s) {
  99. $options[$s['id']] = $s['name'];
  100. }
  101. return $options;
  102. })
  103. ->required()
  104. ->searchable(),
  105. \Filament\Forms\Components\Select::make('data.stage')
  106. ->label('学段')
  107. ->options([
  108. 'primary' => '小学',
  109. 'junior' => '初中',
  110. 'senior' => '高中',
  111. ])
  112. ->required()
  113. ->reactive(),
  114. \Filament\Forms\Components\TextInput::make('data.grade')
  115. ->label('年级')
  116. ->numeric()
  117. ->helperText('例如:7表示七年级'),
  118. \Filament\Forms\Components\Select::make('data.semester')
  119. ->label('学期')
  120. ->options([
  121. 1 => '上学期',
  122. 2 => '下学期',
  123. ])
  124. ->helperText('选择学期'),
  125. \Filament\Forms\Components\TextInput::make('data.official_title')
  126. ->label('教材名称')
  127. ->required()
  128. ->maxLength(255),
  129. \Filament\Forms\Components\TextInput::make('data.isbn')
  130. ->label('ISBN')
  131. ->maxLength(255),
  132. \Filament\Forms\Components\Select::make('data.status')
  133. ->label('状态')
  134. ->options([
  135. 'draft' => '草稿',
  136. 'published' => '已发布',
  137. 'archived' => '已归档',
  138. ])
  139. ->required(),
  140. ])
  141. ->columns(2),
  142. ])
  143. ->statePath('data');
  144. }
  145. /**
  146. * 获取表单实例供视图使用
  147. */
  148. public function getFormProperty(): string
  149. {
  150. // 直接渲染表单HTML
  151. ob_start();
  152. try {
  153. $form = $this->form();
  154. $form->render();
  155. } catch (\Exception $e) {
  156. // 忽略表单渲染错误
  157. }
  158. return ob_get_clean();
  159. }
  160. }