Files
Tstore/resources/views/admin/packages/show.blade.php
浪子 04a2034975 前端极简黑白重设计,并纳入客户端注册、站点设置与后台相关改动
- storefront 全站改为极简黑白配色:直角、细线分隔、卡片 hover 浅底、深色模式(跟随系统+手动切换)
- 抽出 storefront/partials/card 复用卡片
- 一并提交此前暂存的客户端注册 API、站点设置、后台页面与测试

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-22 08:35:49 +08:00

434 lines
21 KiB
PHP

@php
$typeLabel = $package->type === 'plugin' ? '插件' : '主题';
$statusLabels = [
'draft' => '草稿',
'published' => '发布中',
'hidden' => '隐藏',
'deprecated' => '弃用',
];
$statusTone = [
'draft' => 'muted',
'published' => 'ok',
'hidden' => 'warn',
'deprecated' => 'warn',
];
$currentVersion = $package->versions->firstWhere('is_latest', true)
?: $package->versions->firstWhere('is_stable', true)
?: $package->versions->first();
@endphp
@extends('admin.layout', [
'title' => 'Tstore Admin · ' . $package->name,
'pageTitle' => $package->name,
'pageSubtitle' => $typeLabel . ' · ' . $package->slug,
'pageBadge' => ucfirst($package->type),
])
@section('content')
<div class="grid">
<section class="stats">
<div class="stat"><span class="label">扩展类型</span><span class="value">{{ strtoupper($package->type) }}</span><span class="hint">{{ $typeLabel }} package</span></div>
<div class="stat"><span class="label">当前状态</span><span class="value">{{ $statusLabels[$package->status] ?? $package->status }}</span><span class="hint">可在下方直接调整</span></div>
<div class="stat"><span class="label">当前主版本</span><span class="value">{{ $currentVersion?->version ?: '-' }}</span><span class="hint">最新或稳定版本</span></div>
<div class="stat"><span class="label">版本数量</span><span class="value">{{ $package->versions->count() }}</span><span class="hint">历史记录总数</span></div>
<div class="stat"><span class="label">截图数量</span><span class="value">{{ $package->screenshots->count() }}</span><span class="hint">当前展示素材</span></div>
<div class="stat"><span class="label">下载次数</span><span class="value">{{ $package->download_count }}</span><span class="hint">累计下载总量</span></div>
</section>
<div class="split">
<section class="panel">
<div class="entity-head">
<div class="entity-icon">
@if ($package->icon_url)
<img src="{{ $package->icon_url }}" alt="{{ $package->name }}">
@else
{{ $package->type === 'plugin' ? 'P' : 'T' }}
@endif
</div>
<div class="entity-copy">
<h2>基础资料</h2>
<p>这里维护扩展展示信息、排序、推荐状态以及分类关联。</p>
</div>
</div>
<form method="post" action="{{ route('webadmin.packages.update', [$package->type, $package->slug]) }}" class="grid">
@csrf
@method('PUT')
<div class="form-grid">
<div class="field">
<label>类型</label>
<input class="input" name="type" value="{{ $package->type }}" readonly>
</div>
<div class="field">
<label>Slug</label>
<input class="input" name="slug" value="{{ $package->slug }}" readonly>
</div>
<div class="field">
<label>名称</label>
<input class="input" name="name" value="{{ old('name', $package->name) }}" required>
</div>
<div class="field">
<label>状态</label>
<select class="select" name="status">
@foreach ($statusLabels as $status => $label)
<option value="{{ $status }}" @selected(old('status', $package->status) === $status)>{{ $label }}</option>
@endforeach
</select>
</div>
<div class="field">
<label>作者</label>
<input class="input" name="author" value="{{ old('author', $package->author) }}">
</div>
<div class="field">
<label>License</label>
<input class="input" name="license" value="{{ old('license', $package->license) }}">
</div>
<div class="field">
<label>排序</label>
<input class="input" type="number" name="sort_order" value="{{ old('sort_order', $package->sort_order ?? 0) }}">
</div>
<div class="field">
<label>主页</label>
<input class="input" name="homepage" value="{{ old('homepage', $package->homepage) }}">
</div>
</div>
<div class="field">
<label>图标 URL</label>
<input class="input" name="icon_url" value="{{ old('icon_url', $package->icon_url) }}">
</div>
<div class="field">
<label>摘要</label>
<input class="input" name="summary" value="{{ old('summary', $package->summary) }}">
</div>
<div class="field">
<label>描述</label>
<textarea name="description">{{ old('description', $package->description) }}</textarea>
</div>
<div class="field">
<label>分类名称或 slug,优先用逗号分隔</label>
<input class="input" name="categories_text" value="{{ old('categories_text', $package->categories->map(fn ($category) => $category->name ?: $category->slug)->implode(', ')) }}">
</div>
<div class="checkbox-row">
<label><input type="checkbox" name="is_featured" value="1" @checked(old('is_featured', $package->is_featured))> 设为推荐扩展</label>
</div>
<div class="form-actions">
<button class="btn" type="submit">保存{{ $typeLabel }}信息</button>
<a class="btn ghost" href="{{ route('webadmin.packages', ['type' => $package->type]) }}">返回{{ $typeLabel }}列表</a>
</div>
</form>
<div class="form-actions" style="margin-top:16px">
<form method="post" action="{{ route('webadmin.packages.destroy', [$package->type, $package->slug]) }}" onsubmit="return confirm('确认删除这个{{ $typeLabel }}吗?版本、截图和分类关联都会一起删除。');">
@csrf
@method('DELETE')
<button class="btn danger" type="submit">删除{{ $typeLabel }}</button>
</form>
</div>
</section>
<div class="stack">
<section class="panel soft">
<div class="section-title">
<div>
<h2>当前资料</h2>
<p>快速核对基础信息、时间戳和前台展示状态。</p>
</div>
</div>
<div class="kv-grid">
<div class="kv-card">
<span class="kv-label">Slug</span>
<span class="kv-value">{{ $package->slug }}</span>
</div>
<div class="kv-card">
<span class="kv-label">状态</span>
<span class="kv-value"><span class="chip {{ $statusTone[$package->status] ?? 'muted' }}">{{ $statusLabels[$package->status] ?? $package->status }}</span></span>
</div>
<div class="kv-card">
<span class="kv-label">作者</span>
<span class="kv-value">{{ $package->author ?: '未填写' }}</span>
</div>
<div class="kv-card">
<span class="kv-label">主页</span>
<span class="kv-value">{{ $package->homepage ?: '未填写' }}</span>
</div>
<div class="kv-card">
<span class="kv-label">创建时间</span>
<span class="kv-value">{{ optional($package->created_at)->format('Y-m-d H:i') ?: '-' }}</span>
</div>
<div class="kv-card">
<span class="kv-label">更新时间</span>
<span class="kv-value">{{ optional($package->updated_at)->format('Y-m-d H:i') ?: '-' }}</span>
</div>
</div>
<div class="tags">
@foreach ($package->categories as $category)
<span class="chip">{{ $category->name }}</span>
@endforeach
@if ($package->categories->isEmpty())
<span class="muted">尚未关联分类</span>
@endif
<span class="chip {{ $package->is_featured ? 'ok' : 'muted' }}">{{ $package->is_featured ? '推荐扩展' : '普通扩展' }}</span>
</div>
</section>
<section class="panel soft">
<div class="section-title">
<div>
<h2>截图管理</h2>
<p>手动录入详情页预览截图,第一张会优先作为前台主预览展示。</p>
</div>
</div>
<form method="post" action="{{ route('webadmin.packages.screenshots.store', [$package->type, $package->slug]) }}" class="grid">
@csrf
<div class="field">
<label>图片 URL</label>
<input class="input" name="image_url" value="{{ old('image_url') }}" placeholder="https://example.com/screenshots/home.webp" required>
</div>
<div class="field">
<label>截图说明</label>
<input class="input" name="caption" value="{{ old('caption') }}" placeholder="首页、设置页、文章页等">
</div>
<div class="field">
<label>排序</label>
<input class="input" type="number" name="sort_order" value="{{ old('sort_order', 0) }}">
</div>
<div class="form-actions">
<button class="btn" type="submit">添加截图</button>
</div>
</form>
@if ($package->screenshots->isNotEmpty())
<div class="preview-grid" style="margin-top:18px">
@foreach ($package->screenshots as $shot)
<article class="preview-card">
<figure class="preview-shot">
<img src="{{ $shot->image_url }}" alt="{{ $shot->caption ?: $package->name }}">
<figcaption>{{ $shot->caption ?: $package->name . ' 截图' }}</figcaption>
</figure>
<div class="preview-tools">
<span class="chip muted">排序 {{ $shot->sort_order }}</span>
<form method="post" action="{{ route('webadmin.packages.screenshots.destroy', [$package->type, $package->slug, $shot->id]) }}" onsubmit="return confirm('确认删除这张截图吗?');">
@csrf
@method('DELETE')
<button class="btn danger small" type="submit">删除</button>
</form>
</div>
</article>
@endforeach
</div>
@else
<div class="empty">当前还没有截图。</div>
@endif
</section>
</div>
</div>
<div class="split">
<section class="panel">
<div class="section-title">
<div>
<h2>版本记录</h2>
<p>统一查看版本号、兼容区间、发布时间与稳定状态。</p>
</div>
</div>
<div class="table-wrap">
<table class="table">
<thead>
<tr>
<th>版本</th>
<th>状态</th>
<th>兼容性</th>
<th>发布时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
@forelse ($package->versions as $version)
<tr>
<td>
<strong>v{{ $version->version }}</strong>
<div class="muted">{{ $version->package_url ?: '未生成下载地址' }}</div>
</td>
<td>
<div class="tags" style="margin-top:0">
<span class="chip {{ $version->is_stable ? 'ok' : 'warn' }}">{{ $version->is_stable ? '稳定版' : '预发布' }}</span>
<span class="chip {{ $version->is_latest ? 'ok' : 'muted' }}">{{ $version->is_latest ? '最新' : '历史' }}</span>
</div>
</td>
<td>
<div class="muted">Typecho {{ $version->typecho_min ?: '-' }} ~ {{ $version->typecho_max ?: '-' }}</div>
<div class="muted">PHP {{ $version->php_min ?: '-' }} ~ {{ $version->php_max ?: '-' }}</div>
</td>
<td>{{ optional($version->published_at)->format('Y-m-d H:i') ?: '-' }}</td>
<td>
<form method="post" action="{{ route('webadmin.packages.versions.destroy', [$package->type, $package->slug, $version->id]) }}" onsubmit="return confirm('确认删除这个版本吗?');">
@csrf
@method('DELETE')
<button class="btn danger small" type="submit">删除</button>
</form>
</td>
</tr>
@empty
<tr>
<td colspan="5">
<div class="empty">当前还没有版本记录。</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</section>
<section class="panel soft">
<div class="section-title">
<div>
<h2>zip 发布</h2>
<p>上传 zip 后补充版本字段,服务端会校验目录结构并生成可供 API 返回的版本元数据。</p>
</div>
</div>
<form method="post" action="{{ route('webadmin.packages.publish', [$package->type, $package->slug]) }}" class="grid" enctype="multipart/form-data">
@csrf
<div class="field">
<label>zip 文件</label>
<input class="input" type="file" name="package_file" accept=".zip" required>
</div>
<div class="field">
<label>版本号</label>
<input class="input" name="version" value="{{ old('version') }}" placeholder="如 zip 不含 manifest,可在这里手动填写 1.0.0">
</div>
<div class="field">
<label>发布说明</label>
<textarea name="changelog" placeholder="补充这次发布的主要变化">{{ old('changelog') }}</textarea>
</div>
<div class="form-grid compact">
<div class="field">
<label>Typecho Min</label>
<input class="input" name="typecho_min" value="{{ old('typecho_min', '1.2.0') }}" placeholder="1.2.0">
</div>
<div class="field">
<label>Typecho Max</label>
<input class="input" name="typecho_max" value="{{ old('typecho_max') }}" placeholder="1.3.*">
</div>
<div class="field">
<label>PHP Min</label>
<input class="input" name="php_min" value="{{ old('php_min', '7.4') }}" placeholder="7.4">
</div>
<div class="field">
<label>PHP Max</label>
<input class="input" name="php_max" value="{{ old('php_max') }}" placeholder="8.3">
</div>
<div class="field">
<label>PHP Extensions</label>
<input class="input" name="php_extensions" value="{{ is_array(old('php_extensions')) ? implode(',', old('php_extensions')) : old('php_extensions') }}" placeholder="curl,json">
</div>
<div class="field">
<label>发布时间</label>
<input class="input" type="datetime-local" name="published_at" value="{{ old('published_at') }}">
</div>
</div>
<div class="checkbox-row">
<label><input type="checkbox" name="is_stable" value="1" @checked(old('is_stable', 1))> 设为稳定版</label>
<label><input type="checkbox" name="mark_as_latest" value="1" @checked(old('mark_as_latest', 1))> 设为最新版本</label>
</div>
<div class="form-actions">
<button class="btn" type="submit">上传并发布</button>
</div>
</form>
</section>
</div>
<section class="panel">
<div class="section-title">
<div>
<h2>手动添加版本</h2>
<p>调试或补录历史版本时,可以直接写入元数据而不经过 zip 发布流程。</p>
</div>
</div>
<form method="post" action="{{ route('webadmin.packages.versions.store', [$package->type, $package->slug]) }}" class="grid">
@csrf
<div class="form-grid compact">
<div class="field">
<label>版本号</label>
<input class="input" name="version" value="{{ old('version') }}" placeholder="1.0.0" required>
</div>
<div class="field">
<label>发布时间</label>
<input class="input" type="datetime-local" name="published_at" value="{{ old('published_at') }}">
</div>
<div class="field">
<label>Typecho Min</label>
<input class="input" name="typecho_min" value="{{ old('typecho_min') }}" placeholder="1.2.0">
</div>
<div class="field">
<label>Typecho Max</label>
<input class="input" name="typecho_max" value="{{ old('typecho_max') }}" placeholder="1.3.*">
</div>
<div class="field">
<label>PHP Min</label>
<input class="input" name="php_min" value="{{ old('php_min') }}" placeholder="7.4">
</div>
<div class="field">
<label>PHP Max</label>
<input class="input" name="php_max" value="{{ old('php_max') }}" placeholder="8.3">
</div>
<div class="field">
<label>Package URL</label>
<input class="input" name="package_url" value="{{ old('package_url') }}" placeholder="https://...">
</div>
<div class="field">
<label>Size</label>
<input class="input" type="number" name="package_size" value="{{ old('package_size') }}" placeholder="238000">
</div>
<div class="field">
<label>SHA256</label>
<input class="input" name="sha256" value="{{ old('sha256') }}" placeholder="可选,默认会补 64 位 0">
</div>
<div class="field">
<label>PHP Extensions</label>
<input class="input" name="php_extensions" value="{{ old('php_extensions') }}" placeholder="curl,json">
</div>
</div>
<div class="field">
<label>发布说明</label>
<textarea name="changelog" placeholder="输入更新内容">{{ old('changelog') }}</textarea>
</div>
<div class="checkbox-row">
<label><input type="checkbox" name="is_stable" value="1" @checked(old('is_stable'))> 设为稳定版</label>
<label><input type="checkbox" name="is_latest" value="1" @checked(old('is_latest'))> 设为最新版本</label>
</div>
<div class="form-actions">
<button class="btn" type="submit">添加版本</button>
</div>
</form>
</section>
</div>
@endsection