- 编辑器 pre code 移除 wangEditor 内置 border,与预览区样式统一 - 代码块语言标签 padding 加大并用 !important 对抗 wangEditor 全局重置 - 编辑器 ::before 伪元素仅作降级方案,避免与 JS 注入的 .code-lang-label 冲突 - 编辑器 pre padding-top 统一为 36px,font-size/line-height 对齐预览区 - 提交改用 editor.getHtml(),后端 sanitizeHTML 替代 renderMarkdown,保留富文本格式 - 详情页 post-detail-header 覆盖 common.css sticky,固定在文章卡片内 - 详情页增加白色卡片背景、圆角、阴影和内边距 - 详情页添加代码块语言标签 JS 注入 - 详情页用户名移除括号 UID 显示,移除管理按钮
86 lines
3.1 KiB
HTML
86 lines
3.1 KiB
HTML
{{template "layout/header.html" .}}
|
|
<body>
|
|
|
|
{{template "layout/nav.html" .}}
|
|
|
|
<div class="container post-detail">
|
|
<article class="post-article">
|
|
<header class="post-detail-header">
|
|
<h1 class="post-detail-title">{{.Post.Title}}</h1>
|
|
<div class="post-detail-meta">
|
|
<span class="post-author">{{if .Post.AuthorName}}{{.Post.AuthorName}}{{else}}UID{{.Post.UserID}}{{end}}</span>
|
|
<span class="post-time">{{.Post.CreatedAt.Format "2006-01-02 15:04"}}</span>
|
|
{{if ne .Post.Status "approved"}}
|
|
<span class="post-status post-status-{{.Post.Status}}">{{index $.StatusNames .Post.Status}}</span>
|
|
{{end}}
|
|
</div>
|
|
</header>
|
|
|
|
<div class="post-detail-body">
|
|
{{.PostBodyHTML}}
|
|
{{/* 如果 BodyHTML 为空,直接显示原文 */}}
|
|
</div>
|
|
{{if not .PostBodyHTML}}
|
|
<div class="post-detail-body-raw">{{.Post.Body}}</div>
|
|
{{end}}
|
|
|
|
{{if .Post.RejectReason}}
|
|
<div class="post-reject-reason">
|
|
<strong>退回理由:</strong>{{.Post.RejectReason}}
|
|
</div>
|
|
{{end}}
|
|
</article>
|
|
|
|
{{if .IsLoggedIn}}
|
|
<div class="post-actions">
|
|
{{if and $.Post (or (eq $.Post.UserID $.UID) $.CanAccessAdmin) (ne $.Post.Status "pending") (ne $.Post.Status "locked")}}
|
|
<a href="/posts/{{$.Post.ID}}/edit" class="btn btn-secondary">编辑</a>
|
|
{{end}}
|
|
{{if and $.Post (eq $.Post.UserID $.UID) (or (eq $.Post.Status "draft") (eq $.Post.Status "rejected"))}}
|
|
<button class="btn btn-primary" id="submitAuditBtn" data-id="{{$.Post.ID}}">提交审核</button>
|
|
{{end}}
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
|
|
{{template "layout/footer.html" .}}
|
|
|
|
<script src="/static/js/common.js"></script>
|
|
<script>
|
|
(function() {
|
|
// 代码块语言标签注入
|
|
document.querySelectorAll('.post-detail-body pre').forEach(function(pre) {
|
|
var code = pre.querySelector('code[class*="language-"]');
|
|
if (!code) return;
|
|
var match = code.className.match(/language-(\w+)/);
|
|
if (!match) return;
|
|
var label = document.createElement('span');
|
|
label.className = 'code-lang-label';
|
|
label.textContent = match[1];
|
|
pre.insertBefore(label, pre.firstChild);
|
|
});
|
|
|
|
var btn = document.getElementById('submitAuditBtn');
|
|
if (!btn) return;
|
|
btn.addEventListener('click', function() {
|
|
if (!confirm('确认提交审核?审核通过后将公开发布。')) return;
|
|
var csrf = document.querySelector('meta[name="csrf-token"]');
|
|
fetch('/api/posts/' + btn.dataset.id + '/submit', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRF-Token': csrf ? csrf.getAttribute('content') : ''
|
|
}
|
|
})
|
|
.then(function(r) { return r.json(); })
|
|
.then(function(d) {
|
|
if (d.success) { window.location.reload(); }
|
|
else { alert(d.message || '提交失败'); }
|
|
})
|
|
.catch(function() { alert('请求失败'); });
|
|
});
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|