fix: 修复编辑器代码块样式不一致 + 提交 HTML 保留格式 + 详情页布局优化
- 编辑器 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 显示,移除管理按钮
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
<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}}({{.Post.UserID}}){{else}}UID{{.Post.UserID}}{{end}}</span>
|
||||
<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>
|
||||
@ -39,9 +39,6 @@
|
||||
{{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}}
|
||||
{{if $.CanAccessAdmin}}
|
||||
<a href="/admin/posts" class="btn btn-secondary">管理</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
@ -51,6 +48,18 @@
|
||||
<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() {
|
||||
|
||||
@ -61,11 +61,21 @@
|
||||
/* ========== 帖子详情 ========== */
|
||||
.post-detail {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 32px 16px;
|
||||
margin: 24px auto 40px;
|
||||
}
|
||||
|
||||
.post-article {
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.08);
|
||||
padding: 40px 48px;
|
||||
}
|
||||
|
||||
.post-detail-header {
|
||||
position: static !important;
|
||||
z-index: auto !important;
|
||||
box-shadow: none !important;
|
||||
background: transparent !important;
|
||||
margin-bottom: 32px;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
@ -115,28 +125,18 @@
|
||||
color: #2980b9;
|
||||
}
|
||||
|
||||
.post-detail-body pre {
|
||||
position: relative;
|
||||
background: #f3f4f6;
|
||||
padding: 16px;
|
||||
padding-top: 36px;
|
||||
border-radius: 8px;
|
||||
overflow-x: auto;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* 代码块语言标签(编辑器内 + 预览页通用) */
|
||||
/* 代码块基础样式(详情页预览 + 编辑器内通用) */
|
||||
.post-detail-body pre,
|
||||
#editor-container [data-slate-editor] pre {
|
||||
position: relative;
|
||||
background: #f3f4f6;
|
||||
padding: 16px;
|
||||
padding: 12px 16px;
|
||||
padding-top: 36px;
|
||||
border-radius: 8px;
|
||||
overflow-x: auto;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
font-family: 'Menlo', 'Consolas', 'Monaco', 'Liberation Mono', monospace;
|
||||
}
|
||||
|
||||
/* 通过 JS 动态注入语言标签,因为 CSS attr() 无法从 class 中提取 */
|
||||
@ -145,7 +145,7 @@
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 4px 16px;
|
||||
padding: 8px 16px !important;
|
||||
background: #e5e7eb;
|
||||
color: #6b7280;
|
||||
font-size: 11px;
|
||||
@ -157,6 +157,7 @@
|
||||
.post-detail-body pre code,
|
||||
#editor-container [data-slate-editor] pre code {
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
padding: 0 !important;
|
||||
font-size: inherit !important;
|
||||
}
|
||||
@ -433,28 +434,29 @@
|
||||
font-style: normal !important;
|
||||
}
|
||||
|
||||
/* 编辑器内代码块样式 */
|
||||
/* 编辑器内代码块样式 — 以预览区样式为准 */
|
||||
#editor-container [data-slate-editor] pre {
|
||||
position: relative;
|
||||
background: #f3f4f6 !important;
|
||||
padding: 12px 16px !important;
|
||||
padding-top: 32px !important;
|
||||
padding-top: 36px !important;
|
||||
border-radius: 8px !important;
|
||||
font-family: 'Menlo', 'Consolas', 'Monaco', 'Liberation Mono', monospace !important;
|
||||
font-size: 13px !important;
|
||||
line-height: 1.6 !important;
|
||||
font-size: 14px !important;
|
||||
line-height: 1.5 !important;
|
||||
overflow-x: auto !important;
|
||||
margin: 12px 0 !important;
|
||||
}
|
||||
|
||||
/* 编辑器内代码块语言标签 */
|
||||
#editor-container [data-slate-editor] pre::before {
|
||||
/* 语言标签由 JS 动态注入 .code-lang-label,不再使用 ::before 伪元素 */
|
||||
/* 若 wangEditor 的 pre 上有 data-language 属性,则作为降级方案 */
|
||||
#editor-container [data-slate-editor] pre[data-language]::before {
|
||||
content: attr(data-language);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 3px 16px;
|
||||
padding: 8px 16px;
|
||||
background: #e5e7eb;
|
||||
color: #6b7280;
|
||||
font-size: 11px;
|
||||
@ -465,6 +467,7 @@
|
||||
|
||||
#editor-container [data-slate-editor] pre code {
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
padding: 0 !important;
|
||||
font-size: inherit !important;
|
||||
}
|
||||
|
||||
@ -372,10 +372,11 @@ form.addEventListener('submit', e => {
|
||||
e.preventDefault();
|
||||
|
||||
const title = titleEl.value.trim();
|
||||
const body = getEditorText();
|
||||
const body = getEditorHtml();
|
||||
const bodyText = getEditorText();
|
||||
|
||||
if (!title) { alert('请输入标题'); return; }
|
||||
if (!body) { alert('请输入正文'); return; }
|
||||
if (!bodyText) { alert('请输入正文'); return; }
|
||||
|
||||
let url = '/api/posts';
|
||||
let method = 'POST';
|
||||
|
||||
Reference in New Issue
Block a user