wip: article AI polish, category SEO fields, cover generator, membership plan seeder
This commit is contained in:
@@ -129,6 +129,32 @@ a:hover { color: var(--teal); }
|
||||
}
|
||||
|
||||
.post-list { display: grid; gap: 0; }
|
||||
.post-item__cover {
|
||||
display: block;
|
||||
margin: 0 0 0.75rem;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
aspect-ratio: 16 / 9;
|
||||
background: #e8eef2;
|
||||
}
|
||||
.post-item__cover img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
.post__cover {
|
||||
margin: 0 0 1.25rem;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
background: #e8eef2;
|
||||
}
|
||||
.post__cover img {
|
||||
width: 100%;
|
||||
max-height: 420px;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
.post-item {
|
||||
padding: 1.35rem 0;
|
||||
border-bottom: 1px solid var(--line);
|
||||
@@ -148,6 +174,24 @@ a:hover { color: var(--teal); }
|
||||
.meta { color: var(--muted); font-size: 0.92rem; margin: 0 0 0.55rem; }
|
||||
.excerpt { margin: 0; color: #243442; }
|
||||
|
||||
.category-hero { margin-bottom: 1.25rem; }
|
||||
.category-hero__cover {
|
||||
margin: 0 0 1rem;
|
||||
border-radius: calc(var(--radius) - 0.35rem);
|
||||
overflow: hidden;
|
||||
}
|
||||
.category-hero__cover img {
|
||||
width: 100%;
|
||||
max-height: 240px;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
.category-hero__intro {
|
||||
margin: 0 0 0.75rem;
|
||||
color: #243442;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-family: var(--serif);
|
||||
font-size: clamp(1.8rem, 3vw, 2.4rem);
|
||||
@@ -292,6 +336,8 @@ a:hover { color: var(--teal); }
|
||||
margin-bottom: 0.35rem;
|
||||
}
|
||||
.comment__author { color: var(--ink); }
|
||||
a.comment__author { text-decoration: none; }
|
||||
a.comment__author:hover { color: var(--teal); }
|
||||
.comment__body { color: #243442; }
|
||||
|
||||
.article-body .body { font-size: 1.05rem; }
|
||||
|
||||
@@ -34,6 +34,12 @@
|
||||
</p>
|
||||
</header>
|
||||
|
||||
@if($article->hasCover() && ($coverUrl = $article->coverUrl()))
|
||||
<figure class="post__cover">
|
||||
<img src="{{ $coverUrl }}" alt="{{ $article->title }}" itemprop="image">
|
||||
</figure>
|
||||
@endif
|
||||
|
||||
@if(count($toc) >= 2)
|
||||
<nav class="post__toc" aria-labelledby="post-toc-heading">
|
||||
<h2 id="post-toc-heading" class="post__toc-title">{{ __('frontend.article.toc') }}</h2>
|
||||
@@ -70,7 +76,7 @@
|
||||
@forelse($article->comments as $comment)
|
||||
<article class="comment">
|
||||
<header class="comment__meta">
|
||||
<strong class="comment__author">{{ $comment->author }}</strong>
|
||||
@include('theme::partials.comment-author')
|
||||
@if($comment->published_at)
|
||||
<time datetime="{{ $comment->published_at->toIso8601String() }}">
|
||||
{{ $comment->published_at->format('Y-m-d H:i') }}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
@extends('theme::layout')
|
||||
|
||||
@section('content')
|
||||
<header class="category-hero panel">
|
||||
@if(filled($category->coverUrl()))
|
||||
<figure class="category-hero__cover">
|
||||
<img src="{{ $category->coverUrl() }}" alt="{{ $category->name }}">
|
||||
</figure>
|
||||
@endif
|
||||
<h1 class="page-title">{{ $category->name }}</h1>
|
||||
@if(filled($category->intro))
|
||||
<div class="category-hero__intro">{!! nl2br(e($category->intro)) !!}</div>
|
||||
@elseif(filled($category->description))
|
||||
<p class="excerpt">{{ $category->description }}</p>
|
||||
@endif
|
||||
<p class="meta">{{ __('frontend.category.post_count', ['count' => $articles->total()]) }}</p>
|
||||
</header>
|
||||
<div class="post-list">
|
||||
@forelse($articles as $article)
|
||||
<article class="post-item">
|
||||
@if($article->hasCover() && ($coverUrl = $article->coverUrl()))
|
||||
<a class="post-item__cover" href="{{ url('/show-'.$article->id.'.shtml') }}">
|
||||
<img src="{{ $coverUrl }}" alt="{{ $article->title }}" loading="lazy">
|
||||
</a>
|
||||
@endif
|
||||
<h2><a href="{{ url('/show-'.$article->id.'.shtml') }}">{{ $article->title }}</a></h2>
|
||||
<p class="meta">
|
||||
{{ optional($article->published_at)->format('Y-m-d') }}
|
||||
· {{ strtoupper($article->content_format) }}
|
||||
@if($article->stick) · {{ __('frontend.common.pinned') }} @endif
|
||||
</p>
|
||||
<p class="excerpt">{{ app(\App\Domain\Blog\ArticleExcerpt::class)->forList($article) }}</p>
|
||||
</article>
|
||||
@empty
|
||||
<div class="panel">
|
||||
<p class="meta">{{ __('frontend.common.no_posts') }}</p>
|
||||
</div>
|
||||
@endforelse
|
||||
</div>
|
||||
<div class="pagination">{{ $articles->links() }}</div>
|
||||
@endsection
|
||||
@@ -5,7 +5,7 @@
|
||||
<div class="panel">
|
||||
@forelse($comments as $comment)
|
||||
<div class="comment">
|
||||
<strong>{{ $comment->author }}</strong>
|
||||
@include('theme::partials.comment-author')
|
||||
<span class="meta"> · <a href="{{ url('/show-'.$comment->article_id.'.shtml') }}">{{ $comment->article?->title }}</a></span>
|
||||
<div>{!! $comment->content !!}</div>
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
<div class="post-list">
|
||||
@forelse($articles as $article)
|
||||
<article class="post-item">
|
||||
@if($article->hasCover() && ($coverUrl = $article->coverUrl()))
|
||||
<a class="post-item__cover" href="{{ url('/show-'.$article->id.'.shtml') }}">
|
||||
<img src="{{ $coverUrl }}" alt="{{ $article->title }}" loading="lazy">
|
||||
</a>
|
||||
@endif
|
||||
<h2><a href="{{ url('/show-'.$article->id.'.shtml') }}">{{ $article->title }}</a></h2>
|
||||
<p class="meta">
|
||||
{{ optional($article->published_at)->format('Y-m-d') }}
|
||||
|
||||
@@ -73,7 +73,12 @@
|
||||
<h3>{{ __('frontend.sidebar.categories') }}</h3>
|
||||
<ul>
|
||||
@forelse(($categories ?? []) as $category)
|
||||
<li><a href="{{ url('/category-'.$category->id.'.shtml') }}">{{ $category->name }}</a></li>
|
||||
<li>
|
||||
<a href="{{ $category->publicUrl() }}">{{ $category->name }}</a>
|
||||
@if((int) $category->articles_count > 0)
|
||||
<span class="meta">({{ $category->articles_count }})</span>
|
||||
@endif
|
||||
</li>
|
||||
@empty
|
||||
<li class="note">{{ __('frontend.sidebar.empty_category') }}</li>
|
||||
@endforelse
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
@php
|
||||
$websiteHref = $comment->websiteHref();
|
||||
@endphp
|
||||
@if($websiteHref)
|
||||
<a class="comment__author" href="{{ $websiteHref }}" rel="nofollow noopener noreferrer" target="_blank">{{ $comment->author }}</a>
|
||||
@else
|
||||
<strong class="comment__author">{{ $comment->author }}</strong>
|
||||
@endif
|
||||
@@ -11,6 +11,21 @@
|
||||
</ul>
|
||||
@endif
|
||||
<p class="meta">用户名:{{ $user->username ?: $user->name }}</p>
|
||||
@if(!empty($membership))
|
||||
<div class="panel" style="margin: 1rem 0; padding: 0.75rem 1rem; background: #eef7f6;">
|
||||
@if($membership['active'] ?? false)
|
||||
<p>{{ __('frontend.membership.active', ['plan' => $membership['plan_name'] ?? '—']) }}</p>
|
||||
@if(!empty($membership['expires_at']))
|
||||
<p class="meta">{{ __('frontend.membership.expires', ['date' => $membership['expires_at']]) }}</p>
|
||||
@else
|
||||
<p class="meta">{{ __('frontend.membership.lifetime') }}</p>
|
||||
@endif
|
||||
@else
|
||||
<p>{{ __('frontend.membership.inactive') }}</p>
|
||||
@endif
|
||||
<p class="meta"><a href="{{ url('/plugins/membership') }}">{{ __('frontend.membership.manage') }}</a></p>
|
||||
</div>
|
||||
@endif
|
||||
<form class="stack" method="post" action="{{ url('/post.php') }}">
|
||||
@csrf
|
||||
<input type="hidden" name="action" value="modpro">
|
||||
|
||||
@@ -68,7 +68,9 @@
|
||||
<h3>{{ __('frontend.sidebar.categories') }}</h3>
|
||||
<ul>
|
||||
@foreach(($categories ?? []) as $category)
|
||||
<li><a href="{{ url('/category-'.$category->id.'.shtml') }}">{{ $category->name }}</a></li>
|
||||
<li>
|
||||
<a href="{{ $category->publicUrl() }}">{{ $category->name }}</a>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user