Files
ai-web/resources/views/public/tools/show.blade.php

550 lines
16 KiB
PHP
Raw Normal View History

2026-02-11 17:28:36 +08:00
@extends('layouts.site')
2026-02-13 10:56:23 +08:00
@section('page_class', 'page-tools page-detail')
2026-02-11 17:28:36 +08:00
@section('title', $item->seo_title ?: $item->name.' - AI工具详情')
@section('meta_description', $item->seo_description ?: $item->summary)
@section('canonical', $item->canonical_url ?: route('tools.show', $item->slug))
@section('head')
<style>
2026-02-13 10:56:23 +08:00
.tool-show-shell {
2026-02-11 17:28:36 +08:00
display: grid;
2026-02-13 10:56:23 +08:00
grid-template-columns: 210px minmax(0, 1fr) 320px;
2026-02-12 10:31:53 +08:00
gap: var(--page-section-gap);
2026-02-13 10:56:23 +08:00
align-items: start;
2026-02-11 17:28:36 +08:00
}
2026-02-13 10:56:23 +08:00
.tool-show-left,
.tool-show-right {
2026-02-11 17:28:36 +08:00
position: sticky;
top: 84px;
align-self: start;
}
2026-02-13 10:56:23 +08:00
.tool-show-nav {
border: 1px solid var(--line);
border-radius: 12px;
background: var(--bg-surface);
box-shadow: var(--shadow-sm);
padding: .62rem .54rem;
display: grid;
gap: .3rem;
}
.tool-show-nav-title {
margin: 0;
padding: .1rem .24rem .45rem;
border-bottom: 1px solid var(--line);
color: var(--text-muted);
font-size: .76rem;
letter-spacing: .06em;
text-transform: uppercase;
}
.tool-show-nav-link {
display: grid;
grid-template-columns: 1rem minmax(0, 1fr);
gap: .44rem;
align-items: center;
border: 1px solid transparent;
border-radius: .6rem;
padding: .42rem .46rem;
color: #4e6288;
text-decoration: none;
font-size: .82rem;
transition: .16s ease;
}
.tool-show-nav-link:hover {
border-color: var(--line-strong);
background: var(--brand-soft);
color: #223b67;
}
.tool-show-nav-link i {
color: #6f83aa;
text-align: center;
font-size: .82rem;
}
.tool-main {
min-width: 0;
}
.tool-hero {
border: 1px solid var(--line);
border-radius: 12px;
background:
linear-gradient(160deg, color-mix(in srgb, #eff4ff 88%, #fff) 0, color-mix(in srgb, #f6f9ff 86%, #fff) 100%);
box-shadow: var(--shadow-sm);
padding: .98rem;
margin-bottom: .72rem;
}
.tool-hero-inner {
display: grid;
grid-template-columns: 108px minmax(0, 1fr) auto;
gap: .88rem;
align-items: start;
}
.tool-logo {
width: 108px;
height: 108px;
border-radius: 14px;
border: 1px solid var(--line);
background: #fff;
box-shadow: 0 10px 22px rgba(28, 48, 93, .1);
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
.tool-logo img {
width: 100%;
height: 100%;
object-fit: cover;
}
.tool-logo-fallback {
width: 100%;
height: 100%;
display: inline-flex;
align-items: center;
justify-content: center;
font-family: "Outfit", "Noto Sans SC", sans-serif;
font-size: 1.6rem;
font-weight: 800;
color: #405c94;
background: linear-gradient(160deg, #eef3ff 0, #e2ebff 100%);
}
.tool-name {
margin: .08rem 0 .28rem;
font-family: "Outfit", "Noto Sans SC", sans-serif;
font-size: clamp(1.55rem, 2.8vw, 2.1rem);
font-weight: 800;
letter-spacing: .01em;
line-height: 1.2;
color: #1d2f52;
}
.tool-summary {
margin: 0;
color: #53678f;
font-size: .96rem;
line-height: 1.75;
}
.tool-meta-chips {
display: flex;
flex-wrap: wrap;
gap: .44rem;
margin-bottom: .4rem;
}
.tool-meta-chips span {
display: inline-flex;
align-items: center;
gap: .28rem;
border: 1px solid color-mix(in srgb, var(--line) 92%, #fff);
border-radius: 999px;
background: rgba(255, 255, 255, .86);
padding: .14rem .56rem;
color: #64799f;
font-size: .74rem;
white-space: nowrap;
}
.tool-hero-actions {
min-width: 168px;
display: grid;
gap: .44rem;
}
.tool-hero-actions .btn {
border-radius: 999px;
font-weight: 600;
}
.tool-card {
border: 1px solid var(--line);
border-radius: 12px;
background: var(--bg-surface);
box-shadow: var(--shadow-sm);
padding: .96rem;
margin-bottom: .72rem;
}
.tool-card-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: .5rem;
margin-bottom: .56rem;
}
.tool-card-title {
margin: 0;
font-family: "Outfit", "Noto Sans SC", sans-serif;
font-size: .98rem;
font-weight: 700;
color: #2b4068;
}
.tool-card-sub {
color: #7a8db0;
font-size: .78rem;
}
.tool-capability-grid {
2026-02-11 17:28:36 +08:00
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
2026-02-13 10:56:23 +08:00
gap: .48rem;
2026-02-11 17:28:36 +08:00
}
2026-02-13 10:56:23 +08:00
.tool-capability-item {
border: 1px solid color-mix(in srgb, var(--line) 90%, #fff);
border-radius: .74rem;
background: color-mix(in srgb, var(--bg-soft) 70%, #fff);
padding: .5rem .56rem;
color: #556a92;
font-size: .82rem;
line-height: 1.3;
}
.tool-scenario-list {
margin: 0;
padding-left: 1.15rem;
color: #314a74;
line-height: 1.82;
font-size: .95rem;
}
.tool-scenario-list li + li {
margin-top: .3rem;
}
.tool-related-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: .56rem;
}
.tool-related-item {
2026-02-11 17:28:36 +08:00
border: 1px solid var(--line);
2026-02-13 10:56:23 +08:00
border-radius: .78rem;
2026-02-11 17:28:36 +08:00
background: #fff;
2026-02-13 10:56:23 +08:00
padding: .66rem .7rem;
transition: .16s ease;
2026-02-11 17:28:36 +08:00
}
2026-02-13 10:56:23 +08:00
.tool-related-item:hover {
transform: translateY(-2px);
border-color: color-mix(in srgb, var(--brand) 35%, var(--line));
box-shadow: 0 10px 20px rgba(29, 53, 116, .1);
}
.tool-related-item a {
color: #23406e;
text-decoration: none;
font-weight: 700;
}
.tool-related-item p {
margin: .34rem 0 .42rem;
color: #687d9f;
font-size: .82rem;
line-height: 1.5;
}
.tool-right-card {
border: 1px solid var(--line);
border-radius: 12px;
background: var(--bg-surface);
box-shadow: var(--shadow-sm);
padding: .8rem .82rem;
margin-bottom: .62rem;
}
.tool-right-title {
margin: 0 0 .48rem;
font-family: "Outfit", "Noto Sans SC", sans-serif;
font-size: .92rem;
font-weight: 700;
color: #2a426d;
}
.tool-info-list {
list-style: none;
margin: 0;
padding: 0;
font-size: .82rem;
}
.tool-info-list li {
display: flex;
justify-content: space-between;
gap: .5rem;
padding: .34rem 0;
2026-02-11 17:28:36 +08:00
border-bottom: 1px dashed var(--line);
2026-02-13 10:56:23 +08:00
color: #5e739a;
2026-02-11 17:28:36 +08:00
}
2026-02-13 10:56:23 +08:00
.tool-info-list li:last-child {
2026-02-11 17:28:36 +08:00
border-bottom: 0;
2026-02-13 10:56:23 +08:00
padding-bottom: 0;
2026-02-11 17:28:36 +08:00
}
2026-02-13 10:56:23 +08:00
.tool-info-list strong {
color: #22395f;
font-weight: 700;
}
.tool-right-list {
display: grid;
gap: .42rem;
}
.tool-right-list article {
border: 1px solid var(--line);
border-radius: .7rem;
background: #fff;
padding: .5rem .56rem;
}
.tool-right-list a {
color: #2a4270;
text-decoration: none;
font-size: .84rem;
font-weight: 700;
}
.tool-right-list div {
margin-top: .18rem;
color: #7a8eb0;
font-size: .74rem;
}
@media (max-width: 1280px) {
.tool-show-shell {
grid-template-columns: 190px minmax(0, 1fr) 290px;
}
.tool-capability-grid {
2026-02-11 17:28:36 +08:00
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 991.98px) {
2026-02-13 10:56:23 +08:00
.tool-show-shell {
2026-02-11 17:28:36 +08:00
grid-template-columns: 1fr;
}
2026-02-13 10:56:23 +08:00
.tool-show-left,
.tool-show-right {
2026-02-11 17:28:36 +08:00
position: static;
}
2026-02-13 10:56:23 +08:00
.tool-show-nav {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.tool-show-nav-title {
grid-column: 1 / -1;
}
.tool-hero-inner {
grid-template-columns: 90px minmax(0, 1fr);
}
.tool-logo {
width: 90px;
height: 90px;
}
.tool-hero-actions {
grid-column: 1 / -1;
grid-template-columns: repeat(2, minmax(0, 1fr));
}
2026-02-11 17:28:36 +08:00
}
@media (max-width: 575.98px) {
2026-02-13 10:56:23 +08:00
.tool-show-nav {
grid-template-columns: 1fr;
}
.tool-hero-inner {
grid-template-columns: 1fr;
}
.tool-logo {
width: 76px;
height: 76px;
border-radius: 12px;
}
.tool-hero-actions {
grid-template-columns: 1fr;
}
.tool-related-grid,
.tool-capability-grid {
2026-02-11 17:28:36 +08:00
grid-template-columns: 1fr;
}
}
</style>
<script type="application/ld+json">
{!! json_encode([
'@context' => 'https://schema.org',
'@type' => 'SoftwareApplication',
'name' => $item->name,
'description' => $item->summary,
'url' => $item->official_url,
'applicationCategory' => $item->category?->name,
], JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT) !!}
</script>
@endsection
@section('content')
2026-02-13 10:56:23 +08:00
@php
$name = trim((string) ($item->h1 ?: $item->name));
$logoText = mb_strtoupper(mb_substr($item->name ?: 'AI', 0, 2));
@endphp
2026-02-11 17:28:36 +08:00
@if($showRiskNotice)
2026-02-13 10:56:23 +08:00
<div class="alert alert-warning mb-2" role="alert">
免责声明:涉及医疗、法律、投资等高风险场景的内容仅供学习参考,不构成专业建议。
</div>
2026-02-11 17:28:36 +08:00
@endif
2026-02-13 10:56:23 +08:00
<div class="tool-show-shell">
<aside class="tool-show-left" aria-label="页面目录">
<nav class="tool-show-nav">
<p class="tool-show-nav-title">Tool Detail</p>
<a class="tool-show-nav-link" href="#overview"><i class="bi bi-grid-1x2"></i><span>概览</span></a>
<a class="tool-show-nav-link" href="#details"><i class="bi bi-file-text"></i><span>详细介绍</span></a>
<a class="tool-show-nav-link" href="#highlights"><i class="bi bi-stars"></i><span>功能亮点</span></a>
<!-- <a class="tool-show-nav-link" href="#scenarios"><i class="bi bi-check2-square"></i><span>适用建议</span></a> -->
@if($relatedTools->isNotEmpty())
<a class="tool-show-nav-link" href="#related"><i class="bi bi-diagram-3"></i><span>同类推荐</span></a>
@endif
</nav>
</aside>
<main class="tool-main">
<section class="tool-hero" id="overview">
<div class="tool-hero-inner">
<div class="tool-logo">
@if(!empty($item->logo_url))
<img src="{{ $item->logo_url }}" alt="{{ $item->name }} Logo" loading="lazy">
@else
<span class="tool-logo-fallback">{{ $logoText }}</span>
@endif
</div>
<div>
<div class="tool-meta-chips">
<span><i class="bi bi-grid"></i>{{ $item->category?->name ?? 'AI 工具' }}</span>
<span><i class="bi bi-wallet2"></i>{{ $item->pricing_type }}</span>
<span><i class="bi bi-plug"></i>{{ $item->has_api ? '支持 API' : '无 API' }}</span>
<span><i class="bi bi-shield-check"></i>{{ $item->source_level?->label() ?? '未知来源' }}</span>
</div>
<h1 class="tool-name">{{ $name }}</h1>
<p class="tool-summary">{{ $item->summary }}</p>
</div>
<div class="tool-hero-actions">
<a class="btn btn-primary" href="{{ $item->official_url }}" target="_blank" rel="nofollow noopener">访问官网</a>
@if($item->alternative)
<a class="btn btn-outline-primary" href="{{ route('tools.show', $item->alternative->slug) }}">查看替代工具</a>
@endif
</div>
2026-02-11 17:28:36 +08:00
</div>
2026-02-13 10:56:23 +08:00
</section>
<section class="tool-card" id="details">
<div class="tool-card-head">
<h2 class="tool-card-title">工具详细介绍</h2>
<span class="tool-card-sub">更新于 {{ $item->updated_at?->format('Y-m-d') ?? '-' }}</span>
</div>
<div class="md-content detail-content">
2026-02-11 17:28:36 +08:00
@if(trim((string) $item->description) !== '')
{!! $descriptionHtml !!}
@else
<p>{{ $item->summary }}</p>
@endif
</div>
2026-02-13 10:56:23 +08:00
</section>
2026-02-11 17:28:36 +08:00
2026-02-13 10:56:23 +08:00
<section class="tool-card" id="highlights">
<div class="tool-card-head">
<h2 class="tool-card-title">功能亮点</h2>
<span class="tool-card-sub">基于内容自动提取</span>
</div>
2026-02-11 17:28:36 +08:00
@if(!empty($capabilityTags))
2026-02-13 10:56:23 +08:00
<div class="tool-capability-grid">
2026-02-11 17:28:36 +08:00
@foreach($capabilityTags as $tag)
2026-02-13 10:56:23 +08:00
<div class="tool-capability-item">{{ $tag }}</div>
2026-02-11 17:28:36 +08:00
@endforeach
</div>
2026-02-13 10:56:23 +08:00
@else
<p class="text-muted-soft small mb-0">暂无可展示的功能标签。</p>
2026-02-11 17:28:36 +08:00
@endif
</section>
@if($relatedTools->isNotEmpty())
2026-02-13 10:56:23 +08:00
<section class="tool-card mb-0" id="related">
<div class="tool-card-head">
<h2 class="tool-card-title">同类工具推荐</h2>
<span class="tool-card-sub">按最近发布排序</span>
</div>
<div class="tool-related-grid">
2026-02-11 17:28:36 +08:00
@foreach($relatedTools as $tool)
2026-02-13 10:56:23 +08:00
<article class="tool-related-item">
<a href="{{ route('tools.show', $tool->slug) }}">{{ $tool->name }}</a>
<p class="line-clamp-2">{{ $tool->summary }}</p>
<div class="d-flex flex-wrap gap-2">
<span class="chip">{{ $tool->pricing_type }}</span>
<span class="chip">{{ $tool->has_api ? 'API' : 'No API' }}</span>
</div>
</article>
2026-02-11 17:28:36 +08:00
@endforeach
</div>
</section>
@endif
2026-02-13 10:56:23 +08:00
</main>
2026-02-11 17:28:36 +08:00
2026-02-13 10:56:23 +08:00
<aside class="tool-show-right">
<section class="tool-right-card">
<h3 class="tool-right-title">基础信息</h3>
<ul class="tool-info-list">
<li><span>价格模式</span><strong>{{ $item->pricing_type }}</strong></li>
<li><span>API 支持</span><strong>{{ $item->has_api ? '支持' : '不支持' }}</strong></li>
<li><span>适用平台</span><strong>{{ $item->platform ?: '未提供' }}</strong></li>
<li><span>支持语言</span><strong>{{ $item->language ?: '未提供' }}</strong></li>
<li><span>最后校验</span><strong>{{ $item->last_verified_at?->format('Y-m-d') ?? '未记录' }}</strong></li>
<li><span>状态</span><strong>{{ $item->is_stale ? '可能过期' : '有效' }}</strong></li>
2026-02-11 17:28:36 +08:00
</ul>
</section>
@if($latestTools->isNotEmpty())
2026-02-13 10:56:23 +08:00
<section class="tool-right-card">
<h3 class="tool-right-title">最新收录</h3>
<div class="tool-right-list">
2026-02-11 17:28:36 +08:00
@foreach($latestTools->take(6) as $tool)
<article>
2026-02-13 10:56:23 +08:00
<a href="{{ route('tools.show', $tool->slug) }}">{{ $tool->name }}</a>
<div>{{ $tool->category?->name ?? '未分类' }}</div>
2026-02-11 17:28:36 +08:00
</article>
@endforeach
</div>
</section>
@endif
</aside>
</div>
@endsection