TextbookFormSchema.php 6.7 KB

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