- Post 模型新增 PendingTitle/PendingBody 字段,分离已发布内容与待审修订 - Update: approved 帖子编辑写入 Pending 字段,不覆盖正文,不改变发布状态 - Approve: 有 PendingBody 时复制到正式字段后清空,无 PendingBody 走首次审核 - Reject: 有 PendingBody 时仅清空待审修订(保持已发布),无 PendingBody 走普通退回 - 新增 ListPendingRevisions 查询,管理后台独立展示"修订待审核"区域 - 详情页展示"修订审核中"标识,编辑页加载待审内容 - 通过修订后直接覆盖,不保留历史版本
128 lines
6.7 KiB
HTML
128 lines
6.7 KiB
HTML
{{template "admin/layout/base.html" .}}
|
|
<div class="page-header">
|
|
<h1>内容管理</h1>
|
|
<p class="page-desc">管理所有社区帖子</p>
|
|
</div>
|
|
|
|
<div class="admin-filter-bar">
|
|
<form class="filter-form" method="GET" action="/admin/posts">
|
|
<input type="text" name="keyword" value="{{.Keyword}}" placeholder="搜索标题..." class="form-input filter-input">
|
|
<select name="status" class="form-select filter-select">
|
|
<option value="">全部状态</option>
|
|
<option value="draft" {{if eq .Status "draft"}}selected{{end}}>草稿</option>
|
|
<option value="pending" {{if eq .Status "pending"}}selected{{end}}>待审核</option>
|
|
<option value="approved" {{if eq .Status "approved"}}selected{{end}}>已发布</option>
|
|
<option value="rejected" {{if eq .Status "rejected"}}selected{{end}}>已退回</option>
|
|
</select>
|
|
<button type="submit" class="btn btn-primary">搜索</button>
|
|
</form>
|
|
</div>
|
|
|
|
{{if .Error}}
|
|
<div class="error-message">{{.Error}}</div>
|
|
{{end}}
|
|
|
|
{{if .Revisions}}
|
|
<div class="revision-section">
|
|
<h2>修订待审核 <span class="revision-count">{{len .Revisions}}</span></h2>
|
|
<table class="admin-table revision-table">
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>标题</th>
|
|
<th>作者</th>
|
|
<th>状态</th>
|
|
<th>时间</th>
|
|
<th>操作</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{{range .Revisions}}
|
|
<tr class="post-row revision-row">
|
|
<td>{{.ID}}</td>
|
|
<td><a href="/posts/{{.ID}}" target="_blank" class="post-link">{{.Title}}</a> <span class="revision-badge">修订中</span></td>
|
|
<td>{{if .AuthorName}}{{.AuthorName}}({{.UserID}}){{else}}UID{{.UserID}}{{end}}</td>
|
|
<td><span class="status-badge status-{{.Status}}">{{index $.StatusNames .Status}}</span>{{if .IsLocked}} <span class="status-badge status-locked">已锁定</span>{{end}}</td>
|
|
<td>{{.CreatedAt.Format "2006-01-02 15:04"}}</td>
|
|
<td class="actions-cell">
|
|
<div class="action-btns">
|
|
<button class="btn btn-sm btn-success post-approve" data-id="{{.ID}}">通过修订</button>
|
|
<button class="btn btn-sm btn-warning post-reject" data-id="{{.ID}}">退回修订</button>
|
|
{{if and (not .IsLocked)}}
|
|
<button class="btn btn-sm btn-danger post-lock" data-id="{{.ID}}">锁定</button>
|
|
{{end}}
|
|
{{if .IsLocked}}
|
|
<button class="btn btn-sm btn-success post-unlock" data-id="{{.ID}}">解锁</button>
|
|
{{end}}
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{{end}}
|
|
|
|
<table class="admin-table">
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>标题</th>
|
|
<th>作者</th>
|
|
<th>状态</th>
|
|
<th>时间</th>
|
|
<th>操作</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{{if and (eq (len .Posts) 0) (eq (len .Revisions) 0)}}
|
|
<tr><td colspan="6" class="empty">暂无帖子</td></tr>
|
|
{{end}}
|
|
{{range .Posts}}
|
|
<tr class="post-row">
|
|
<td>{{.ID}}</td>
|
|
<td><a href="/posts/{{.ID}}" target="_blank" class="post-link">{{.Title}}</a>{{if .PendingBody}} <span class="revision-badge">修订中</span>{{end}}</td>
|
|
<td>{{if .AuthorName}}{{.AuthorName}}({{.UserID}}){{else}}UID{{.UserID}}{{end}}</td>
|
|
<td><span class="status-badge status-{{.Status}}">{{index $.StatusNames .Status}}</span>{{if .IsLocked}} <span class="status-badge status-locked">已锁定</span>{{end}}</td>
|
|
<td>{{.CreatedAt.Format "2006-01-02 15:04"}}</td>
|
|
<td class="actions-cell">
|
|
<div class="action-btns">
|
|
{{if eq .Status "pending"}}
|
|
<button class="btn btn-sm btn-success post-approve" data-id="{{.ID}}">通过</button>
|
|
<button class="btn btn-sm btn-warning post-reject" data-id="{{.ID}}">退回</button>
|
|
{{end}}
|
|
{{if and (eq .Status "approved") (not .PendingBody)}}
|
|
<button class="btn btn-sm btn-warning post-reject" data-id="{{.ID}}">退回</button>
|
|
{{end}}
|
|
{{if and (eq .Status "approved") .PendingBody}}
|
|
<button class="btn btn-sm btn-success post-approve" data-id="{{.ID}}">通过修订</button>
|
|
<button class="btn btn-sm btn-warning post-reject" data-id="{{.ID}}">退回修订</button>
|
|
{{end}}
|
|
{{if and (not .IsLocked) (ne .Status "pending")}}
|
|
<button class="btn btn-sm btn-danger post-lock" data-id="{{.ID}}">锁定</button>
|
|
{{end}}
|
|
{{if .IsLocked}}
|
|
<button class="btn btn-sm btn-success post-unlock" data-id="{{.ID}}">解锁</button>
|
|
{{end}}
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
|
|
{{if gt .TotalPages 1}}
|
|
<div class="pagination">
|
|
{{if gt .Page 1}}
|
|
<a href="?page={{.PrevPage}}{{if .Keyword}}&keyword={{.Keyword}}{{end}}{{if .Status}}&status={{.Status}}{{end}}" class="page-link">上一页</a>
|
|
{{end}}
|
|
<span class="page-info">第 {{.Page}} / {{.TotalPages}} 页 (共 {{.Total}} 条)</span>
|
|
{{if lt .Page .TotalPages}}
|
|
<a href="?page={{.NextPage}}{{if .Keyword}}&keyword={{.Keyword}}{{end}}{{if .Status}}&status={{.Status}}{{end}}" class="page-link">下一页</a>
|
|
{{end}}
|
|
</div>
|
|
{{end}}
|
|
|
|
<script src="/admin/static/js/posts.js"></script>
|
|
{{template "admin/layout/footer.html" .}}
|