Files
ulthon_information/view/admin/post/edit_content_markdown.html
augushong 0e3a442ddd fix(API): 修复文章发布时 publish_time 自动填充逻辑
统一处理 publish_time 参数,空字符串按未传处理。在创建和更新文章时,当文章状态为发布且未提供 publish_time 时,自动填充当前时间。同时修复更新文章时,从草稿首次发布且原 publish_time 为 0 时自动填充时间的逻辑。
2026-05-01 20:57:20 +08:00

220 lines
7.4 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>内容管理</title>
{include file="common/_require"}
<link rel="stylesheet" href="/static/lib/vditor/dist/index.css">
<script src="/static/lib/vditor/dist/index.min.js"></script>
<script>
var currentHeaderNavItem = 'Post-{$Request.param.type|default="1"}';
var currentLeftNavItem = 'post-{$Request.param.type|default="1"}';
</script>
<style>
html,
body {
background-color: #fff;
height: 100%;
overflow: hidden;
color: #333;
}
#top-container {
border-bottom: 1px solid #e8e8e8;
padding-left: 30px;
}
#content {
height: calc(100% - 440px);
background-color: rgb(245, 245, 245);
overflow-y: auto;
position: relative;
}
#editor-container {
width: 850px;
margin: 30px auto 30px auto;
background-color: #fff;
padding: 20px 50px 50px 50px;
border: 1px solid #e8e8e8;
box-shadow: 0 2px 10px rgb(0 0 0 / 12%);
}
#editor-container li {
list-style: inherit;
}
#title-container {
padding: 20px 0;
border-bottom: 1px solid #e8e8e8;
}
#title-container input {
font-size: 30px;
border: 0;
outline: none;
width: 100%;
line-height: 1;
}
#editor-text-area {
margin-top: 20px;
}
</style>
</head>
<body class="layui-layout-body">
<div class="layui-layout layui-layout-admin">
{include file="common/_header"}
{include file="common/left_post"}
<div class="layui-body">
<div style="">
<div class="">
<div id="content">
<div id="editor-container">
<div id="title-container">
<input id="title-input" value="{$post->title}">
</div>
<div id="editor-text-area"></div>
</div>
</div>
<div style="height: 30px;line-height: 30px;padding-left: 15px;border-top: 1px solid #e8e8e8;color: #666;">
<span id="content-state">内容变动自动提交</span>
<a href="{:url('output',['id'=>$post.id])}">
去导出
</a>
</div>
<div id="content-data" style="display: none;">{:rawurlencode($post->content??$post->content_html??'')}</div>
</div>
</div>
</div>
{include file="common/_footer"}
</div>
<script>
var lastContent = '';
var contentSaveLock = true;
function autoSaveContent() {
if (contentSaveLock) {
setTimeout(() => {
autoSaveContent();
}, 2600);
} else {
contentSaveLock = true;
$.post('{:url("update")}', {
content: vditor.getValue(),
id: '{$post->id}'
}, function (result) {
$('#content-state').text('自动提交成功')
setTimeout(() => {
autoSaveContent();
}, 2600);
})
}
}
autoSaveContent();
var vditor = new Vditor('editor-text-area', {
height: 'auto',
cache: { enable: false },
cdn: '/static/lib/vditor',
mode: 'wysiwyg',
toolbar: [
'headings', 'bold', 'italic', 'strike', '|',
'list', 'ordered-list', 'check', '|',
'quote', 'code', 'inline-code', '|',
'link', 'upload', 'table', '|',
'undo', 'redo', '|',
'fullscreen', 'preview'
],
upload: {
url: '{:url("File/vditorSave")}',
fieldName: 'file[]',
extraData: function () {
return { type: 'editor' };
}
},
value: decodeURIComponent($('#content-data').html()),
input: function (value) {
contentSaveLock = false;
$('#content-state').text('等待自动提交');
},
after: function () {
setTimeout(function () {
var toolbarHeight = 0;
var toolbarEl = document.querySelector('.vditor-toolbar');
if (toolbarEl) {
toolbarHeight = toolbarEl.offsetHeight;
}
$('#content').height(window.innerHeight - toolbarHeight - 30 - 45 - 7 - 31);
}, 300);
}
});
// 外部 URL 图片粘贴处理
// Vditor 粘贴 HTML 时会将 <img> 转为 Markdown 图片语法
// 需要延迟等待 Vditor 完成粘贴解析后,再替换外部 URL 为本地 URL
document.addEventListener('paste', function (e) {
var pasteStr = e.clipboardData.getData('text/html');
if (!pasteStr) return;
var imgReg = /<img[^>]*src=[\'\"]?([^\'\"]*)[\'\"]?/gi;
var externalUrls = [];
var match;
while ((match = imgReg.exec(pasteStr)) !== null) {
if (match[1] && match[1].substr(0, 4) === 'http') {
externalUrls.push(match[1]);
}
}
if (externalUrls.length === 0) return;
setTimeout(function () {
var pending = externalUrls.length;
layer.load();
externalUrls.forEach(function (url) {
$.ajax({
type: 'POST',
url: "{:url('File/urlSave')}",
data: { url: url, type: 'editor' },
success: function (result) {
if (result.code === 0) {
var escapedUrl = url.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
var regex = new RegExp('!\\[[^\\]]*\\]\\(' + escapedUrl + '\\)', 'g');
var current = vditor.getValue();
vditor.setValue(current.replace(regex, '![](' + result.data.src + ')'));
}
pending--;
if (pending === 0) layer.closeAll('loading');
},
error: function () {
pending--;
if (pending === 0) layer.closeAll('loading');
}
});
});
}, 800);
}, true);
// 标题变更保存
$('#title-input').change(function () {
window.loading = layer.load();
$.post('{:url("update")}', {
title: $('#title-input').val(),
id: '{$post->id}'
}, function (result) {
layer.close(window.loading);
});
});
</script>
</body>
</html>