界面优化
This commit is contained in:
@@ -27,15 +27,15 @@ class ToolController extends Controller
|
||||
$querySignature = sha1((string) $request->getQueryString());
|
||||
$activeTab = $this->resolveTab($request);
|
||||
|
||||
$payload = Cache::remember("tools_index_v4_{$querySignature}", now()->addMinutes(10), function () use ($request, $activeTab): array {
|
||||
$payload = Cache::remember("tools_portal_v2_{$querySignature}", now()->addMinutes(10), function () use ($request, $activeTab): array {
|
||||
$builder = Tool::query()
|
||||
->published()
|
||||
->with(['category', 'alternative']);
|
||||
->with('category');
|
||||
|
||||
$this->applyFilters($builder, $request);
|
||||
$this->applyFilters($builder, $request, false);
|
||||
$this->applyTabSorting($builder, $activeTab);
|
||||
|
||||
$categoryNavigation = Category::query()
|
||||
$categories = Category::query()
|
||||
->where('type', 'tool')
|
||||
->where('is_active', true)
|
||||
->withCount([
|
||||
@@ -45,37 +45,73 @@ class ToolController extends Controller
|
||||
->orderBy('name')
|
||||
->get();
|
||||
|
||||
$totalPublished = Tool::query()->published()->count();
|
||||
$totalApiSupported = Tool::query()->published()->where('has_api', true)->count();
|
||||
$totalFreeAvailable = Tool::query()->published()->whereIn('pricing_type', ['free', 'freemium'])->count();
|
||||
$updatedInSevenDays = Tool::query()->published()->where('updated_at', '>=', now()->subDays(7))->count();
|
||||
$portalTools = $builder->limit(360)->get();
|
||||
$toolsByCategory = $portalTools->groupBy(fn (Tool $tool): string => $tool->category?->slug ?? 'uncategorized');
|
||||
|
||||
$categorySections = $categories->map(function (Category $category) use ($toolsByCategory): array {
|
||||
$sectionTools = $toolsByCategory->get($category->slug, collect())->take(18);
|
||||
|
||||
return [
|
||||
'slug' => $category->slug,
|
||||
'name' => $category->name,
|
||||
'count' => (int) ($category->published_tools_count ?? 0),
|
||||
'tools' => $sectionTools,
|
||||
];
|
||||
})->values();
|
||||
|
||||
return [
|
||||
'items' => $builder->paginate(24)->withQueryString(),
|
||||
'categories' => $categoryNavigation,
|
||||
'filters' => $request->only(['q', 'category', 'pricing', 'api', 'tab']),
|
||||
'categories' => $categories,
|
||||
'categorySections' => $categorySections,
|
||||
'hotTools' => $portalTools->take(18),
|
||||
'latestTools' => Tool::query()->published()->with('category')->latest('published_at')->limit(18)->get(),
|
||||
'filters' => $request->only(['q', 'pricing', 'api', 'tab']),
|
||||
'activeTab' => $activeTab,
|
||||
'tabOptions' => $this->tabOptions(),
|
||||
'toolStats' => [
|
||||
'total' => $totalPublished,
|
||||
'api' => $totalApiSupported,
|
||||
'free' => $totalFreeAvailable,
|
||||
'updated_7d' => $updatedInSevenDays,
|
||||
],
|
||||
'featuredTools' => Tool::query()->published()->with('category')->orderByDesc('published_at')->limit(8)->get(),
|
||||
'sidebarModels' => AiModel::published()->orderByDesc('total_score')->limit(8)->get(),
|
||||
'sidebarNews' => Article::published()->latest('published_at')->limit(8)->get(),
|
||||
'toolStats' => $this->buildToolStats(),
|
||||
];
|
||||
});
|
||||
|
||||
return view('public.tools.index', $payload);
|
||||
}
|
||||
|
||||
public function list(Request $request): View
|
||||
{
|
||||
$activeTab = $this->resolveTab($request);
|
||||
|
||||
$builder = Tool::query()
|
||||
->published()
|
||||
->with('category');
|
||||
|
||||
$this->applyFilters($builder, $request, true);
|
||||
$this->applyTabSorting($builder, $activeTab);
|
||||
|
||||
$categories = Category::query()
|
||||
->where('type', 'tool')
|
||||
->where('is_active', true)
|
||||
->withCount([
|
||||
'tools as published_tools_count' => fn (Builder $query): Builder => $query->published(),
|
||||
])
|
||||
->orderByDesc('published_tools_count')
|
||||
->orderBy('name')
|
||||
->get();
|
||||
|
||||
return view('public.tools.list', [
|
||||
'items' => $builder->paginate(36)->withQueryString(),
|
||||
'categories' => $categories,
|
||||
'filters' => $request->only(['q', 'category', 'pricing', 'api', 'tab']),
|
||||
'activeTab' => $activeTab,
|
||||
'tabOptions' => $this->tabOptions(),
|
||||
'toolStats' => $this->buildToolStats(),
|
||||
'sidebarModels' => AiModel::query()->published()->orderByDesc('total_score')->limit(8)->get(),
|
||||
'sidebarNews' => Article::query()->published()->latest('published_at')->limit(8)->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function byCategory(string $slug, Request $request): View
|
||||
{
|
||||
$request->merge(['category' => $slug]);
|
||||
|
||||
return $this->index($request);
|
||||
return $this->list($request);
|
||||
}
|
||||
|
||||
public function show(string $slug): View
|
||||
@@ -129,7 +165,7 @@ class ToolController extends Controller
|
||||
return [
|
||||
['key' => 'recommended', 'label' => '综合推荐'],
|
||||
['key' => 'latest', 'label' => '最新收录'],
|
||||
['key' => 'api', 'label' => 'API 优先'],
|
||||
['key' => 'api', 'label' => 'API优先'],
|
||||
['key' => 'free', 'label' => '免费优先'],
|
||||
];
|
||||
}
|
||||
@@ -156,14 +192,14 @@ class ToolController extends Controller
|
||||
->orderByDesc('published_at');
|
||||
}
|
||||
|
||||
private function applyFilters(Builder $builder, Request $request): void
|
||||
private function applyFilters(Builder $builder, Request $request, bool $withCategory): void
|
||||
{
|
||||
if ($request->filled('q')) {
|
||||
$keyword = trim((string) $request->string('q'));
|
||||
$builder->whereFullText(['name', 'summary', 'description'], $keyword);
|
||||
}
|
||||
|
||||
if ($request->filled('category')) {
|
||||
if ($withCategory && $request->filled('category')) {
|
||||
$builder->whereHas('category', function (Builder $categoryQuery) use ($request): void {
|
||||
$categoryQuery->where('slug', (string) $request->string('category'));
|
||||
});
|
||||
@@ -178,6 +214,19 @@ class ToolController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{total:int, api:int, free:int, updated_7d:int}
|
||||
*/
|
||||
private function buildToolStats(): array
|
||||
{
|
||||
return [
|
||||
'total' => Tool::query()->published()->count(),
|
||||
'api' => Tool::query()->published()->where('has_api', true)->count(),
|
||||
'free' => Tool::query()->published()->whereIn('pricing_type', ['free', 'freemium'])->count(),
|
||||
'updated_7d' => Tool::query()->published()->where('updated_at', '>=', now()->subDays(7))->count(),
|
||||
];
|
||||
}
|
||||
|
||||
private function containsRiskKeyword(string $text): bool
|
||||
{
|
||||
return str_contains($text, '医疗')
|
||||
@@ -243,3 +292,4 @@ class ToolController extends Controller
|
||||
return array_values(array_unique(array_slice($tags, 0, 8)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user