- 作者显示 用户名(UID): 修正Post.AuthorName GORM标签从 -:all 改为 -:migration;<-:false;column:author_name
- 审核流程: 帖子详情页新增"提交审核"按钮(draft/rejected时作者可见)
- 图片上传: 新增 POST /api/posts/upload-image 端点,限制5MB/jpg/png/gif/webp
- 代码块语言标注: 工具栏插入代码块时弹出语言输入框,生成 language-xxx class
- 状态中文显示: 管理后台/帖子详情页状态改为 PostStatusDisplayNames 映射
- 修复代码块插入位置错误: init时调用switchMode同步DOM; 无选区时appendChild; 防<pre>嵌套
- 修复 bluemonday.UGCPolicy() 剥离 code/pre 的 class 属性,显式 AllowAttrs("class")
- 修复分割线工具栏插入多余text占位符: hr/link/image以外不强制填占位文本
91 lines
5.4 KiB
HTML
91 lines
5.4 KiB
HTML
{{template "layout/header.html" .}}
|
|
<body>
|
|
|
|
{{template "layout/nav.html" .}}
|
|
|
|
<div class="container editor-container">
|
|
<h1 class="editor-title">{{if .Post}}编辑帖子{{else}}撰写帖子{{end}}</h1>
|
|
|
|
<form id="postForm" class="post-form">
|
|
<input type="hidden" id="postId" value="{{if .Post}}{{.Post.ID}}{{end}}">
|
|
|
|
<div class="form-group">
|
|
<label for="postTitle">标题</label>
|
|
<input type="text" id="postTitle" class="form-input" value="{{if .Post}}{{.Post.Title}}{{end}}" maxlength="200" required>
|
|
</div>
|
|
|
|
{{/* 模式切换标签 */}}
|
|
<div class="editor-modes">
|
|
<button type="button" class="mode-tab active" data-mode="wysiwyg">所见即所得</button>
|
|
<button type="button" class="mode-tab" data-mode="source">源码</button>
|
|
<button type="button" class="mode-tab" data-mode="split">分屏预览</button>
|
|
</div>
|
|
|
|
{{/* 工具条 */}}
|
|
<div class="editor-toolbar" id="toolbar">
|
|
<button type="button" class="tb-btn" data-action="bold" title="加粗 (Ctrl+B)">
|
|
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M15.6 10.79c.97-.67 1.65-1.77 1.65-2.79 0-2.26-1.75-4-4-4H7v14h7.04c2.09 0 3.71-1.7 3.71-3.79 0-1.52-.86-2.82-2.15-3.42zM10 6.5h3c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5h-3v-3zm3.5 9H10v-3h3.5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5z"/></svg>
|
|
</button>
|
|
<button type="button" class="tb-btn" data-action="italic" title="斜体 (Ctrl+I)">
|
|
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M10 4v3h2.21l-3.42 8H6v3h8v-3h-2.21l3.42-8H18V4z"/></svg>
|
|
</button>
|
|
<span class="tb-sep"></span>
|
|
<button type="button" class="tb-btn" data-action="h2" title="标题">H2</button>
|
|
<button type="button" class="tb-btn" data-action="h3" title="子标题">H3</button>
|
|
<span class="tb-sep"></span>
|
|
<button type="button" class="tb-btn" data-action="link" title="链接">
|
|
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/></svg>
|
|
</button>
|
|
<button type="button" class="tb-btn" data-action="image" title="图片">
|
|
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></svg>
|
|
</button>
|
|
<span class="tb-sep"></span>
|
|
<button type="button" class="tb-btn" data-action="quote" title="引用">
|
|
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M6 17h3l2-4V7H5v6h3zm8 0h3l2-4V7h-6v6h3z"/></svg>
|
|
</button>
|
|
<button type="button" class="tb-btn" data-action="code" title="行内代码">
|
|
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M9.4 16.6 4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0 4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"/></svg>
|
|
</button>
|
|
<button type="button" class="tb-btn" data-action="pre" title="代码块">
|
|
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 3h18v18H3V3zm2 2v14h14V5H5zm4 2h6v2H9V7zm0 4h6v2H9v-2z"/></svg>
|
|
</button>
|
|
<span class="tb-sep"></span>
|
|
<button type="button" class="tb-btn" data-action="ul" title="无序列表">
|
|
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M4 10.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0-6c-.83 0-1.5.67-1.5 1.5S3.17 7.5 4 7.5 5.5 6.83 5.5 6 4.83 4.5 4 4.5zm0 12c-.83 0-1.5.68-1.5 1.5s.68 1.5 1.5 1.5 1.5-.68 1.5-1.5-.67-1.5-1.5-1.5zM7 19h14v-2H7v2zm0-6h14v-2H7v2zm0-8v2h14V5H7z"/></svg>
|
|
</button>
|
|
<button type="button" class="tb-btn" data-action="ol" title="有序列表">
|
|
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M2 17h2v.5H3v1h1v.5H2v1h3v-4H2v1zm1-9h1V4H2v1h1v3zm-1 3h1.8L2 13.1v.9h3v-1H3.2L5 10.9V10H2v1zm5-6v2h14V5H7zm0 14h14v-2H7v2zm0-6h14v-2H7v2z"/></svg>
|
|
</button>
|
|
<button type="button" class="tb-btn" data-action="hr" title="分割线">—</button>
|
|
</div>
|
|
|
|
{{/* 源码编辑器 */}}
|
|
<div class="editor-body">
|
|
<textarea id="postBody" class="form-textarea" rows="20" required
|
|
placeholder="使用 Markdown 编写正文...">{{if .Post}}{{.Post.Body}}{{end}}</textarea>
|
|
|
|
{{/* WYSIWYG 编辑器 */}}
|
|
<div id="wysiwygEditor" class="wysiwyg-editor" contenteditable="true" style="display:none;"></div>
|
|
|
|
{{/* 分屏预览 */}}
|
|
<div id="splitPreview" class="split-preview" style="display:none;">
|
|
<div class="split-preview-content post-detail-body"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="editor-actions">
|
|
<button type="submit" class="btn btn-primary">{{if .Post}}保存修改{{else}}发布帖子{{end}}</button>
|
|
</div>
|
|
</form>
|
|
|
|
{{/* 隐藏的图片上传控件 */}}
|
|
<input type="file" id="imageFileInput" accept="image/jpeg,image/png,image/gif,image/webp" style="display:none;">
|
|
</div>
|
|
|
|
{{template "layout/footer.html" .}}
|
|
|
|
{{if .ExtraJS}}<script src="{{.ExtraJS}}"></script>{{end}}
|
|
<script src="/static/js/common.js"></script>
|
|
</body>
|
|
</html>
|