mirror of
https://gitee.com/ulthon/ulthon_information.git
synced 2026-07-01 20:42:49 +08:00
统一处理 publish_time 参数,空字符串按未传处理。在创建和更新文章时,当文章状态为发布且未提供 publish_time 时,自动填充当前时间。同时修复更新文章时,从草稿首次发布且原 publish_time 为 0 时自动填充时间的逻辑。
220 lines
7.4 KiB
HTML
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, ''));
|
|
}
|
|
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>
|