You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
4.6 KiB
146 lines
4.6 KiB
<?php
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Paper;
|
|
use App\Models\ResearchDirection;
|
|
use App\Support\ApiResponse;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
|
|
class PaperController extends Controller
|
|
{
|
|
use ApiResponse;
|
|
|
|
public function index(Request $request): JsonResponse
|
|
{
|
|
$query = Paper::query()->withCount('teachers');
|
|
|
|
if ($kw = $request->query('keyword')) {
|
|
$query->where(function ($q) use ($kw) {
|
|
$q->where('title', 'like', "%{$kw}%")
|
|
->orWhere('authors', 'like', "%{$kw}%")
|
|
->orWhere('school_name', 'like', "%{$kw}%")
|
|
->orWhere('summary', 'like', "%{$kw}%");
|
|
});
|
|
}
|
|
if ($request->filled('school_name')) {
|
|
$query->where('school_name', $request->query('school_name'));
|
|
}
|
|
if ($request->filled('university_id')) {
|
|
$query->where('university_id', (int) $request->query('university_id'));
|
|
}
|
|
if ($request->filled('research_direction_id')) {
|
|
$dirId = (int) $request->query('research_direction_id');
|
|
$query->whereHas('teachers.researchDirections', fn ($q) => $q->where('research_directions.id', $dirId));
|
|
} elseif ($request->filled('research_direction')) {
|
|
$dir = $request->query('research_direction');
|
|
$query->whereHas('teachers.researchDirections', fn ($q) => $q->where('research_directions.name', 'like', "%{$dir}%"));
|
|
}
|
|
if ($request->query('link_status') === 'linked') {
|
|
$query->has('teachers');
|
|
} elseif ($request->query('link_status') === 'unlinked') {
|
|
$query->doesntHave('teachers');
|
|
}
|
|
if ($request->filled('source')) {
|
|
$query->where('source', $request->query('source'));
|
|
}
|
|
if ($request->filled('crawl_job_id')) {
|
|
$query->where('crawl_job_id', (int) $request->query('crawl_job_id'));
|
|
}
|
|
|
|
$paginator = $query
|
|
->orderByDesc('published_at')
|
|
->orderByDesc('id')
|
|
->paginate((int) $request->query('page_size', 20))
|
|
->withQueryString();
|
|
|
|
$paginator->getCollection()->transform(fn (Paper $p) => $this->serializeList($p));
|
|
|
|
return $this->paginated($paginator);
|
|
}
|
|
|
|
public function filterOptions(): JsonResponse
|
|
{
|
|
$schools = Paper::query()
|
|
->whereNotNull('school_name')
|
|
->distinct()
|
|
->orderBy('school_name')
|
|
->pluck('school_name')
|
|
->filter()
|
|
->values();
|
|
|
|
$directions = ResearchDirection::query()
|
|
->where('status', 1)
|
|
->whereHas('teachers')
|
|
->orderBy('sort')
|
|
->orderBy('name')
|
|
->pluck('name')
|
|
->values();
|
|
|
|
return $this->ok([
|
|
'school_names' => $schools,
|
|
'research_directions' => $directions,
|
|
]);
|
|
}
|
|
|
|
public function show(int $paper): JsonResponse
|
|
{
|
|
$model = Paper::query()->with(['teachers.university'])->findOrFail($paper);
|
|
|
|
return $this->ok($this->serializeDetail($model));
|
|
}
|
|
|
|
public function destroy(int $paper): JsonResponse
|
|
{
|
|
$model = Paper::query()->findOrFail($paper);
|
|
$model->teachers()->detach();
|
|
$model->delete();
|
|
|
|
return $this->ok(null, '已删除');
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
protected function serializeList(Paper $p): array
|
|
{
|
|
$isNew = $p->source === 'crawl'
|
|
&& $p->created_at
|
|
&& $p->created_at->gte(Carbon::now()->subDay());
|
|
|
|
return [
|
|
'id' => $p->id,
|
|
'title' => $p->title,
|
|
'authors' => $p->authors,
|
|
'school_name' => $p->school_name,
|
|
'published_at' => $p->published_at?->format('Y-m'),
|
|
'imported_at' => $p->created_at?->format('Y-m-d'),
|
|
'url' => $p->url,
|
|
'summary' => $p->summary,
|
|
'source' => $p->source,
|
|
'is_new' => $isNew,
|
|
'teachers_count' => (int) ($p->teachers_count ?? 0),
|
|
'is_linked' => (int) ($p->teachers_count ?? 0) > 0,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
protected function serializeDetail(Paper $p): array
|
|
{
|
|
$row = $this->serializeList($p);
|
|
$row['published_at'] = $p->published_at?->toDateString();
|
|
$row['teachers'] = $p->teachers->map(fn ($t) => [
|
|
'id' => $t->id,
|
|
'name' => $t->name,
|
|
'university_name' => $t->university?->name,
|
|
])->values();
|
|
|
|
return $row;
|
|
}
|
|
}
|