has('import_id') && !empty(request()->input('import_id')); // 2. 或者是管理员角色(直接检查 role 字段) $user = auth()->user(); $isAdmin = $user && in_array($user->role, ['super_admin', 'admin']); return $hasImportId || $isAdmin; } public static function canCreate(): bool { // 不允许手动创建候选题目,只能从 Markdown 解析生成 return false; } public static function canEdit(Model $record): bool { // 允许在“人工校对”阶段对候选题进行编辑(题干/选项/标记) return true; } public static function table(Tables\Table $table): Tables\Table { return $table ->columns([ TextColumn::make('sequence') ->label('序') ->sortable() ->width('60px'), TextColumn::make('index') ->label('题号') ->sortable() ->width('70px'), TextColumn::make('question_number') ->label('原题号') ->sortable() ->toggleable() ->width('80px'), TextColumn::make('part.title') ->label('区块') ->toggleable() ->limit(16), TextColumn::make('sourcePaper.title') ->label('卷子') ->toggleable() ->limit(16), TextColumn::make('raw_markdown') ->label('题目预览') ->wrap() ->limit(140) ->toggleable(), Tables\Columns\ImageColumn::make('first_image') ->label('图片') ->height(60) ->width(60) ->circular(), TextColumn::make('ai_confidence') ->label('AI 置信度') ->badge() ->color(fn (Model $record): string => $record->confidence_badge) ->formatStateUsing(function (?float $state, Model $record): string { $val = $state ?? $record->confidence; return $val !== null ? number_format((float)$val * 100, 1) . '%' : 'N/A'; }), TextColumn::make('structured_json') ->label('结构化') ->getStateUsing(fn (?Model $record) => $record?->structured_json ? '已生成' : '未生成') ->badge() ->color(fn (?Model $record) => $record?->structured_json ? 'success' : 'gray') ->toggleable(isToggledHiddenByDefault: true), Tables\Columns\ToggleColumn::make('is_question_candidate') ->label('是题目'), TextColumn::make('status') ->label('状态') ->badge() ->color(fn (Model $record): string => $record->status_badge), ]) ->filters([ Tables\Filters\SelectFilter::make('import_id') ->label('导入记录') ->options(function () { return \App\Models\MarkdownImport::query() ->pluck('file_name', 'id') ->toArray(); }) ->query(function ($query, $data) { if (!empty($data['value'])) { $query->where('import_id', $data['value']); } }), TernaryFilter::make('is_question_candidate') ->label('是否为题目'), Tables\Filters\SelectFilter::make('status') ->label('审核状态') ->options([ 'ai_pending' => 'AI 解析中', 'pending' => '待审核', 'reviewed' => '已审核', 'accepted' => '已接受', 'rejected' => '已拒绝', 'superseded' => '已被新解析覆盖', ]), ]) ->actions([ Action::make('review_edit') ->label('校对/编辑') ->icon('heroicon-o-pencil-square') ->color('primary') ->modalHeading(fn (Model $record): string => "校对候选题 #{$record->index}") ->form([ Section::make('审核标记') ->schema([ Toggle::make('is_question_candidate') ->label('是题目') ->default(fn (Model $record) => (bool) $record->is_question_candidate), TextInput::make('ai_confidence') ->label('AI 置信度') ->disabled(), ])->columns(2), Section::make('原始 Markdown(可编辑)') ->schema([ Textarea::make('raw_markdown') ->label('raw_markdown') ->rows(10) ->required(), ])->columnSpanFull(), Section::make('结构化字段(可编辑)') ->schema([ Textarea::make('stem') ->label('题干(stem)') ->rows(6), Textarea::make('options') ->label('选项(JSON)') ->rows(6) ->helperText('示例:{"A":"...","B":"..."};没有选项填空留空'), TagsInput::make('images') ->label('图片 URLs') ->placeholder('https://...'), Textarea::make('tables') ->label('表格(JSON 数组或 HTML)') ->rows(6) ->helperText('支持填写 JSON 数组(推荐)或直接粘贴