优化后台功能

This commit is contained in:
jiangdong.cheng
2026-02-13 10:56:23 +08:00
parent a795b2c896
commit a7f1b7e331
27 changed files with 3725 additions and 197 deletions

View File

@@ -1,6 +1,6 @@
@extends('layouts.site')
@section('page_class', 'page-guides')
@section('page_class', 'page-guides page-detail')
@section('title', $item->seo_title ?: $item->title.' - AI教程')
@section('meta_description', $item->seo_description ?: $item->excerpt)
@section('canonical', $item->canonical_url ?: route('guides.show', $item->slug))
@@ -31,7 +31,7 @@
<div class="module-grid">
<div>
<article class="surface-card p-3 p-lg-4">
<div class="md-content">{!! $bodyHtml !!}</div>
<div class="md-content detail-content">{!! $bodyHtml !!}</div>
</article>
</div>

View File

@@ -1,6 +1,6 @@
@extends('layouts.site')
@section('page_class', 'page-models')
@section('page_class', 'page-models page-detail')
@section('title', $item->seo_title ?: $item->name.' - AI模型详情')
@section('meta_description', $item->seo_description ?: $item->summary)
@section('canonical', $item->canonical_url ?: route('models.show', $item->slug))
@@ -37,7 +37,7 @@
<h2 class="section-title mb-0"><i class="bi bi-card-text text-primary"></i> 模型介绍</h2>
<span class="chip">总分 {{ $item->total_score }}</span>
</div>
<div class="md-content">{{ $item->description ?: $item->summary }}</div>
<div class="md-content detail-content">{{ $item->description ?: $item->summary }}</div>
</section>
<section class="surface-card p-3 p-lg-4 mb-3">

View File

@@ -1,6 +1,6 @@
@extends('layouts.site')
@section('page_class', 'page-news')
@section('page_class', 'page-news page-detail')
@section('title', $item->seo_title ?: $item->title.' - AI资讯')
@section('meta_description', $item->seo_description ?: $item->excerpt)
@section('canonical', $item->canonical_url ?: route('news.show', $item->slug))
@@ -36,7 +36,7 @@
<div>
<article class="surface-card p-3 p-lg-4 mb-3">
<p class="lead">{{ $item->excerpt }}</p>
<div class="md-content">{!! $bodyHtml !!}</div>
<div class="md-content detail-content">{!! $bodyHtml !!}</div>
</article>
<div class="surface-card p-3 p-lg-4">

View File

@@ -1,64 +1,396 @@
@extends('layouts.site')
@section('page_class', 'page-tools')
@section('page_class', 'page-tools page-detail')
@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>
.detail-layout {
.tool-show-shell {
display: grid;
grid-template-columns: minmax(0, 1fr) 320px;
grid-template-columns: 210px minmax(0, 1fr) 320px;
gap: var(--page-section-gap);
align-items: start;
}
.detail-sidebar {
.tool-show-left,
.tool-show-right {
position: sticky;
top: 84px;
align-self: start;
}
.showcase-grid {
.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 {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: .5rem;
gap: .48rem;
}
.showcase-box {
.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 {
border: 1px solid var(--line);
border-radius: 10px;
border-radius: .78rem;
background: #fff;
padding: .62rem;
padding: .66rem .7rem;
transition: .16s ease;
}
.info-list li {
padding: .3rem 0;
.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;
border-bottom: 1px dashed var(--line);
color: #5e739a;
}
.info-list li:last-child {
.tool-info-list li:last-child {
border-bottom: 0;
padding-bottom: 0;
}
@media (max-width: 1200px) {
.showcase-grid {
.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 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 991.98px) {
.detail-layout {
.tool-show-shell {
grid-template-columns: 1fr;
}
.detail-sidebar {
.tool-show-left,
.tool-show-right {
position: static;
}
.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));
}
}
@media (max-width: 575.98px) {
.showcase-grid {
.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 {
grid-template-columns: 1fr;
}
}
@@ -76,120 +408,137 @@
@endsection
@section('content')
<section class="module-hero">
<div class="position-relative">
<div class="d-flex flex-wrap align-items-center gap-2 mb-2">
<span class="hero-chip">{{ $item->category?->name ?? 'AI 工具' }}</span>
<span class="hero-chip">{{ $item->pricing_type }}</span>
<span class="hero-chip">{{ $item->has_api ? '支持 API' : '无 API' }}</span>
</div>
<h1 class="h2 fw-bold mb-2">{{ $item->h1 ?: $item->name }}</h1>
<p class="hero-subtext">{{ $item->summary }}</p>
</div>
</section>
@php
$name = trim((string) ($item->h1 ?: $item->name));
$logoText = mb_strtoupper(mb_substr($item->name ?: 'AI', 0, 2));
@endphp
@if($showRiskNotice)
<div class="alert alert-warning" role="alert">免责声明:涉及医疗、法律、投资等高风险场景的内容仅供学习参考,不构成专业建议。</div>
<div class="alert alert-warning mb-2" role="alert">
免责声明:涉及医疗、法律、投资等高风险场景的内容仅供学习参考,不构成专业建议。
</div>
@endif
<div class="detail-layout">
<div>
<section class="surface-card p-3 p-lg-4 mb-3">
<div class="d-flex justify-content-between align-items-center mb-2">
<h2 class="section-title mb-0"><i class="bi bi-card-text text-primary"></i> 工具介绍</h2>
<span class="small text-muted-soft">更新时间:{{ $item->updated_at?->format('Y-m-d') }}</span>
<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>
</div>
<div class="md-content mb-3">
</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">
@if(trim((string) $item->description) !== '')
{!! $descriptionHtml !!}
@else
<p>{{ $item->summary }}</p>
@endif
</div>
</section>
<section class="tool-card" id="highlights">
<div class="tool-card-head">
<h2 class="tool-card-title">功能亮点</h2>
<span class="tool-card-sub">基于内容自动提取</span>
</div>
@if(!empty($capabilityTags))
<div class="d-flex flex-wrap gap-2">
<div class="tool-capability-grid">
@foreach($capabilityTags as $tag)
<span class="chip">{{ $tag }}</span>
<div class="tool-capability-item">{{ $tag }}</div>
@endforeach
</div>
@else
<p class="text-muted-soft small mb-0">暂无可展示的功能标签。</p>
@endif
</section>
<section class="surface-card p-3 p-lg-4 mb-3">
<h2 class="section-title mb-3"><i class="bi bi-lightning text-primary"></i> 快速看点</h2>
<div class="showcase-grid">
<div class="showcase-box">
<div class="small text-muted-soft">适用平台</div>
<div class="fw-semibold">{{ $item->platform ?: '未提供' }}</div>
</div>
<div class="showcase-box">
<div class="small text-muted-soft">支持语言</div>
<div class="fw-semibold">{{ $item->language ?: '未提供' }}</div>
</div>
<div class="showcase-box">
<div class="small text-muted-soft">来源可信度</div>
<div class="fw-semibold">{{ $item->source_level?->label() ?? '未知' }}</div>
</div>
</div>
</section>
<section class="surface-card p-3 p-lg-4 mb-3">
<h2 class="section-title mb-3"><i class="bi bi-list-check text-primary"></i> 适用场景建议</h2>
<ul class="mb-0">
<li class="mb-2">如果你是首次上手,建议先用免费方案完成一个小任务验证效果。</li>
<li class="mb-2">有团队协作需求时,优先验证 API、权限管理与数据导出能力。</li>
<li>生产使用前,建议再次核验官方价格、条款与数据安全说明。</li>
</ul>
</section>
@if($relatedTools->isNotEmpty())
<section class="surface-card p-3 p-lg-4">
<h2 class="section-title mb-3"><i class="bi bi-diagram-3 text-primary"></i> 同类工具推荐</h2>
<div class="row g-3">
<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">
@foreach($relatedTools as $tool)
<div class="col-md-6">
<article class="entry-item h-100">
<a class="fw-semibold text-decoration-none" href="{{ route('tools.show', $tool->slug) }}">{{ $tool->name }}</a>
<p class="small text-muted-soft line-clamp-2 mb-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>
</div>
<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>
@endforeach
</div>
</section>
@endif
</div>
</main>
<aside class="detail-sidebar">
<section class="surface-card p-3 p-lg-4 mb-3">
<h3 class="section-title mb-3">工具信息</h3>
<ul class="list-unstyled small info-list mb-0">
<li>价格模式<strong>{{ $item->pricing_type }}</strong></li>
<li>API 支持<strong>{{ $item->has_api ? '支持' : '不支持' }}</strong></li>
<li>最后校验:<strong>{{ $item->last_verified_at?->format('Y-m-d') ?? '未记录' }}</strong></li>
<li>状态:<strong>{{ $item->is_stale ? '可能过期' : '有效' }}</strong></li>
<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>
</ul>
</section>
<section class="surface-card p-3 p-lg-4 mb-3 d-grid gap-2">
<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
</section>
@if($latestTools->isNotEmpty())
<section class="surface-card p-3 p-lg-4">
<h3 class="section-title mb-3">最新收录</h3>
<div class="list-tight">
<section class="tool-right-card">
<h3 class="tool-right-title">最新收录</h3>
<div class="tool-right-list">
@foreach($latestTools->take(6) as $tool)
<article>
<a class="fw-semibold text-decoration-none" href="{{ route('tools.show', $tool->slug) }}">{{ $tool->name }}</a>
<div class="small text-muted-soft">{{ $tool->category?->name ?? '未分类' }}</div>
<a href="{{ route('tools.show', $tool->slug) }}">{{ $tool->name }}</a>
<div>{{ $tool->category?->name ?? '未分类' }}</div>
</article>
@endforeach
</div>