TextbookFormSchema.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. <?php
  2. namespace App\Filament\Resources\TextbookResource\Schemas;
  3. use App\Filament\Resources\TextbookResource;
  4. use App\Services\TextbookApiService;
  5. use App\Services\TextbookCoverStorageService;
  6. use Filament\Forms\Components\FileUpload;
  7. use Filament\Forms\Components\Select;
  8. use Filament\Schemas\Components\Section;
  9. use Filament\Forms\Components\TextInput;
  10. use Filament\Forms\Components\Textarea;
  11. use Filament\Schemas\Schema;
  12. class TextbookFormSchema
  13. {
  14. public static function make(Schema $schema): Schema
  15. {
  16. return $schema
  17. ->schema([
  18. Section::make('基本信息')
  19. ->schema([
  20. Select::make('series_id')
  21. ->label('教材系列')
  22. ->options(function () {
  23. $series = app(TextbookApiService::class)->getTextbookSeries();
  24. $options = [];
  25. foreach ($series['data'] as $s) {
  26. $displayName = $s['name'];
  27. if (!empty($s['publisher'])) {
  28. $displayName .= ' (' . $s['publisher'] . ')';
  29. }
  30. $options[$s['id']] = $displayName;
  31. }
  32. return $options;
  33. })
  34. ->required()
  35. ->searchable()
  36. ->preload(),
  37. TextInput::make('official_title')
  38. ->label('教材名称')
  39. ->maxLength(512)
  40. ->helperText('教材名称(用户输入)'),
  41. TextInput::make('isbn')
  42. ->label('ISBN')
  43. ->maxLength(20),
  44. Textarea::make('aliases')
  45. ->label('别名')
  46. ->helperText('JSON 格式,如:["别名1", "别名2"]')
  47. ->formatStateUsing(fn ($state) => is_array($state) ? json_encode($state, JSON_UNESCAPED_UNICODE) : $state)
  48. ->dehydrateStateUsing(fn ($state) => is_string($state) ? json_decode($state, true) : $state)
  49. ->columnSpanFull(),
  50. ])
  51. ->columns(2),
  52. Section::make('学段/年级/学期')
  53. ->schema([
  54. Select::make('stage')
  55. ->label('学段')
  56. ->options([
  57. 'primary' => '小学',
  58. 'junior' => '初中',
  59. 'senior' => '高中',
  60. ])
  61. ->default('junior')
  62. ->required()
  63. ->reactive(),
  64. Select::make('schooling_system')
  65. ->label('学制')
  66. ->options([
  67. '63' => '六三学制',
  68. '54' => '五四学制',
  69. ])
  70. ->default('63')
  71. ->visible(fn ($get): bool => in_array($get('stage'), ['primary', 'junior'])),
  72. TextInput::make('grade')
  73. ->label('年级')
  74. ->numeric()
  75. ->minValue(1)
  76. ->maxValue(12)
  77. ->helperText('数字1-12,例:1年级填1'),
  78. Select::make('semester')
  79. ->label('学期')
  80. ->options([
  81. 1 => '上学期',
  82. 2 => '下学期',
  83. ])
  84. ->required(),
  85. ])
  86. ->columns(2),
  87. Section::make('封面上传')
  88. ->schema([
  89. FileUpload::make('cover_path')
  90. ->label('封面图片')
  91. ->image()
  92. ->directory('textbook-covers')
  93. ->saveUploadedFileUsing(function ($component, $file) {
  94. $uploader = app(TextbookCoverStorageService::class);
  95. $url = $uploader->uploadCover($file, null);
  96. if ($url) {
  97. return $url;
  98. }
  99. return $file->storePubliclyAs(
  100. $component->getDirectory(),
  101. $component->getUploadedFileNameForStorage($file),
  102. $component->getDiskName(),
  103. );
  104. }),
  105. ]),
  106. Section::make('发布与排序')
  107. ->schema([
  108. Select::make('status')
  109. ->label('状态')
  110. ->options([
  111. 'draft' => '草稿',
  112. 'published' => '已发布',
  113. 'archived' => '已归档',
  114. ])
  115. ->default('draft')
  116. ->required(),
  117. TextInput::make('sort_order')
  118. ->label('排序')
  119. ->numeric()
  120. ->default(0)
  121. ->helperText('数字越小排序越靠前'),
  122. Textarea::make('meta')
  123. ->label('扩展信息')
  124. ->helperText('JSON 格式')
  125. ->formatStateUsing(fn ($state) => is_array($state) ? json_encode($state, JSON_UNESCAPED_UNICODE) : $state)
  126. ->dehydrateStateUsing(fn ($state) => is_string($state) ? json_decode($state, true) : $state)
  127. ->columnSpanFull(),
  128. ])
  129. ->columns(2),
  130. ])
  131. ->columns(2);
  132. }
  133. }