TextbookFormSchema.php 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. <?php
  2. namespace App\Filament\Resources\TextbookResource\Schemas;
  3. use App\Filament\Resources\TextbookResource;
  4. use App\Services\TextbookApiService;
  5. use Filament\Forms\Components\FileUpload;
  6. use Filament\Forms\Components\Select;
  7. use Filament\Forms\Components\Section;
  8. use Filament\Forms\Components\TextInput;
  9. use Filament\Forms\Components\Textarea;
  10. use Filament\Schemas\Schema;
  11. class TextbookFormSchema
  12. {
  13. public static function make(Schema $schema): Schema
  14. {
  15. return $schema
  16. ->schema([
  17. Section::make('基本信息')
  18. ->schema([
  19. Select::make('series_id')
  20. ->label('教材系列')
  21. ->options(function () {
  22. $series = app(TextbookApiService::class)->getTextbookSeries();
  23. $options = [];
  24. foreach ($series['data'] as $s) {
  25. $displayName = $s['name'];
  26. if (!empty($s['publisher'])) {
  27. $displayName .= ' (' . $s['publisher'] . ')';
  28. }
  29. $options[$s['id']] = $displayName;
  30. }
  31. return $options;
  32. })
  33. ->required()
  34. ->searchable()
  35. ->preload(),
  36. TextInput::make('official_title')
  37. ->label('教材名称')
  38. ->maxLength(512)
  39. ->helperText('教材名称(用户输入)'),
  40. TextInput::make('isbn')
  41. ->label('ISBN')
  42. ->maxLength(20),
  43. Textarea::make('aliases')
  44. ->label('别名')
  45. ->helperText('JSON 格式,如:["别名1", "别名2"]')
  46. ->formatStateUsing(fn ($state) => is_array($state) ? json_encode($state, JSON_UNESCAPED_UNICODE) : $state)
  47. ->dehydrateStateUsing(fn ($state) => is_string($state) ? json_decode($state, true) : $state)
  48. ->columnSpanFull(),
  49. ])
  50. ->columns(2),
  51. Section::make('学段/年级/学期')
  52. ->schema([
  53. Select::make('stage')
  54. ->label('学段')
  55. ->options([
  56. 'primary' => '小学',
  57. 'junior' => '初中',
  58. 'senior' => '高中',
  59. ])
  60. ->default('junior')
  61. ->required()
  62. ->reactive(),
  63. Select::make('schooling_system')
  64. ->label('学制')
  65. ->options([
  66. '63' => '六三学制',
  67. '54' => '五四学制',
  68. ])
  69. ->default('63')
  70. ->visible(fn ($get): bool => in_array($get('stage'), ['primary', 'junior'])),
  71. TextInput::make('grade')
  72. ->label('年级')
  73. ->numeric()
  74. ->minValue(1)
  75. ->maxValue(12)
  76. ->helperText('数字1-12,例:1年级填1'),
  77. Select::make('semester')
  78. ->label('学期')
  79. ->options([
  80. 1 => '上学期',
  81. 2 => '下学期',
  82. ])
  83. ->required(),
  84. ])
  85. ->columns(2),
  86. Section::make('版本与系列')
  87. ->schema([
  88. Select::make('naming_scheme')
  89. ->label('命名体系')
  90. ->options([
  91. 'new' => '新体系',
  92. 'old' => '旧体系',
  93. ])
  94. ->default('new')
  95. ->required(),
  96. Select::make('track')
  97. ->label('方向')
  98. ->options([
  99. 'science' => '理科',
  100. 'liberal_arts' => '文科',
  101. ])
  102. ->visible(fn ($get): bool => $get('stage') === 'senior'),
  103. Select::make('module_type')
  104. ->label('模块类型')
  105. ->options([
  106. 'compulsory' => '必修',
  107. 'selective_compulsory' => '选择性必修',
  108. 'elective' => '选修',
  109. ])
  110. ->visible(fn ($get): bool => $get('stage') === 'senior'),
  111. TextInput::make('volume_no')
  112. ->label('册次')
  113. ->numeric()
  114. ->minValue(1)
  115. ->maxValue(3)
  116. ->helperText('数字1-3,例:第一册填1'),
  117. TextInput::make('legacy_code')
  118. ->label('旧版代号')
  119. ->helperText('旧教材编号,如:上册-1'),
  120. TextInput::make('curriculum_standard_year')
  121. ->label('课程标准年份')
  122. ->numeric()
  123. ->minValue(2000)
  124. ->maxValue(2099),
  125. TextInput::make('curriculum_revision_year')
  126. ->label('课程修订年份')
  127. ->numeric()
  128. ->minValue(2000)
  129. ->maxValue(2099),
  130. TextInput::make('approval_authority')
  131. ->label('审批机构')
  132. ->default('教育部'),
  133. TextInput::make('approval_year')
  134. ->label('审批年份')
  135. ->numeric()
  136. ->minValue(2000)
  137. ->maxValue(2099),
  138. TextInput::make('edition_label')
  139. ->label('版本标识')
  140. ->helperText('如:第一版、第二版'),
  141. ])
  142. ->columns(2),
  143. Section::make('封面上传')
  144. ->schema([
  145. FileUpload::make('cover_path')
  146. ->label('封面图片')
  147. ->image()
  148. ->directory('textbook-covers'),
  149. ]),
  150. Section::make('发布与排序')
  151. ->schema([
  152. Select::make('status')
  153. ->label('状态')
  154. ->options([
  155. 'draft' => '草稿',
  156. 'published' => '已发布',
  157. 'archived' => '已归档',
  158. ])
  159. ->default('draft')
  160. ->required(),
  161. TextInput::make('sort_order')
  162. ->label('排序')
  163. ->numeric()
  164. ->default(0)
  165. ->helperText('数字越小排序越靠前'),
  166. Textarea::make('meta')
  167. ->label('扩展信息')
  168. ->helperText('JSON 格式')
  169. ->formatStateUsing(fn ($state) => is_array($state) ? json_encode($state, JSON_UNESCAPED_UNICODE) : $state)
  170. ->dehydrateStateUsing(fn ($state) => is_string($state) ? json_decode($state, true) : $state)
  171. ->columnSpanFull(),
  172. ])
  173. ->columns(2),
  174. ])
  175. ->columns(2);
  176. }
  177. }