208 lines
9.5 KiB
HTML
208 lines
9.5 KiB
HTML
|
||
<style>
|
||
.doc-tree { list-style: none; margin: 0; padding: 0; }
|
||
.doc-tree ul { list-style: none; margin: 0; padding-left: 22px; }
|
||
.doc-tree li { line-height: 34px; }
|
||
.doc-node { display: flex; align-items: center; padding: 0 8px; border-radius: 3px; }
|
||
.doc-node:hover { background: #f2f5fa; }
|
||
.doc-node .doc-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
.doc-node .doc-name i { margin-right: 6px; color: #999; }
|
||
.doc-node .doc-ops { flex-shrink: 0; visibility: hidden; }
|
||
.doc-node:hover .doc-ops { visibility: visible; }
|
||
.doc-node .layui-btn-xs { margin-left: 4px; }
|
||
.doc-badge { margin-left: 6px; }
|
||
.doc-sortbox { width: 54px; height: 26px; line-height: 26px; padding: 0 4px; margin-right: 8px; border: 1px solid #e6e6e6; border-radius: 3px; text-align: center; }
|
||
</style>
|
||
|
||
<div class="layui-card">
|
||
<div class="layui-card-header">
|
||
<span>文档管理</span>
|
||
<div class="layui-inline" style="float:right;">
|
||
{if condition="$project"}
|
||
<a class="layui-btn layui-btn-sm" href="/docs/backend/doc/add?project_id={$project.id}&version_id={$version.id}">新增文档</a>
|
||
<a class="layui-btn layui-btn-sm layui-btn-normal" href="/docs/backend/doc/import?project_id={$project.id}&version_id={$version.id}">导入文档</a>
|
||
<button class="layui-btn layui-btn-sm layui-btn-primary" id="btnSaveSort">保存排序</button>
|
||
<button class="layui-btn layui-btn-sm layui-btn-primary" id="btnRebuild">重建索引</button>
|
||
<a class="layui-btn layui-btn-sm layui-btn-primary" href="/docs/{$project.name}" target="_blank">预览</a>
|
||
{/if}
|
||
</div>
|
||
</div>
|
||
<div class="layui-card-body">
|
||
{if condition="empty($projects)"}
|
||
<div class="docs-empty">
|
||
还没有文档项目,请先 <a href="/docs/backend/project/add" class="layui-btn layui-btn-sm">创建项目</a>
|
||
</div>
|
||
{else/}
|
||
<form class="layui-form docs-scope-bar">
|
||
<div class="layui-form-item">
|
||
<div class="layui-inline">
|
||
<label class="layui-form-label" style="width:70px;">项目</label>
|
||
<div class="layui-input-inline">
|
||
<select name="project_id" lay-filter="projectPick">
|
||
{volist name="projects" id="p"}
|
||
<option value="{$p.id}" {if condition="$project && $project.id eq $p.id"}selected{/if}>{$p.title}</option>
|
||
{/volist}
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="layui-inline">
|
||
<label class="layui-form-label" style="width:70px;">版本</label>
|
||
<div class="layui-input-inline">
|
||
<select name="version_id" lay-filter="versionPick">
|
||
{volist name="versions" id="v"}
|
||
<option value="{$v.id}" {if condition="$version && $version.id eq $v.id"}selected{/if}>{$v.title}({$v.name})</option>
|
||
{/volist}
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="layui-inline">
|
||
<span class="docs-tip">修改左侧排序框数值后点击「保存排序」生效;序号越小越靠前</span>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
|
||
{if condition="empty($tree)"}
|
||
<div class="docs-empty">
|
||
当前版本下还没有文档,点击右上角「新增文档」或「导入文档」开始创建
|
||
</div>
|
||
{else/}
|
||
<ul class="doc-tree" id="docTree">
|
||
{php}
|
||
/**
|
||
* 递归渲染文档目录树
|
||
* 模板引擎不支持递归 include,这里用函数递归输出
|
||
*/
|
||
if (!function_exists('docs_render_tree')) {
|
||
function docs_render_tree(array $nodes)
|
||
{
|
||
foreach ($nodes as $node) {
|
||
$id = (int) $node['id'];
|
||
$pid = (int) $node['pid'];
|
||
$sort = (int) $node['sort'];
|
||
$isDir = (int) $node['is_dir'] === 1;
|
||
$title = htmlspecialchars((string) $node['title'], ENT_QUOTES, 'UTF-8');
|
||
$name = htmlspecialchars((string) $node['name'], ENT_QUOTES, 'UTF-8');
|
||
|
||
echo '<li>';
|
||
echo '<div class="doc-node" data-id="' . $id . '" data-pid="' . $pid . '">';
|
||
echo '<input type="number" class="doc-sortbox" value="' . $sort . '" title="排序值">';
|
||
echo '<span class="doc-name">';
|
||
echo '<i class="layui-icon ' . ($isDir ? 'layui-icon-folder' : 'layui-icon-file') . '"></i>';
|
||
echo $title . ' <code style="color:#bbb;font-size:12px;">' . $name . '</code>';
|
||
if ($isDir) {
|
||
echo '<span class="layui-badge layui-bg-gray doc-badge">目录</span>';
|
||
}
|
||
if ((int) $node['status'] !== 1) {
|
||
echo '<span class="layui-badge layui-bg-orange doc-badge">隐藏</span>';
|
||
}
|
||
echo '</span>';
|
||
echo '<span class="doc-ops">';
|
||
echo '<a class="layui-btn layui-btn-xs" href="/docs/backend/doc/edit/' . $id . '">编辑</a>';
|
||
echo '<a class="layui-btn layui-btn-xs layui-btn-normal" href="/docs/backend/doc/add?project_id='
|
||
. (int) $node['project_id'] . '&version_id=' . (int) $node['version_id']
|
||
. '&pid=' . $id . '">加子级</a>';
|
||
echo '<a class="layui-btn layui-btn-xs layui-btn-danger doc-del" href="javascript:;" data-id="'
|
||
. $id . '" data-title="' . $title . '">删除</a>';
|
||
echo '</span>';
|
||
echo '</div>';
|
||
|
||
if (!empty($node['children'])) {
|
||
echo '<ul>';
|
||
docs_render_tree($node['children']);
|
||
echo '</ul>';
|
||
}
|
||
echo '</li>';
|
||
}
|
||
}
|
||
}
|
||
docs_render_tree($tree);
|
||
{/php}
|
||
</ul>
|
||
{/if}
|
||
{/if}
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
layui.use(['form', 'layer', 'jquery'], function () {
|
||
var form = layui.form;
|
||
var layer = layui.layer;
|
||
var $ = layui.$;
|
||
|
||
var projectId = {if condition="$project"}{$project.id}{else/}0{/if};
|
||
var versionId = {if condition="$version"}{$version.id}{else/}0{/if};
|
||
|
||
// 切换项目时版本需要重新加载,因此直接整页跳转
|
||
form.on('select(projectPick)', function (data) {
|
||
location.href = '/docs/backend/doc?project_id=' + data.value;
|
||
});
|
||
|
||
form.on('select(versionPick)', function (data) {
|
||
location.href = '/docs/backend/doc?project_id=' + projectId + '&version_id=' + data.value;
|
||
});
|
||
|
||
// 删除文档
|
||
$('#docTree').on('click', '.doc-del', function () {
|
||
var id = $(this).data('id');
|
||
var title = $(this).data('title');
|
||
layer.confirm('删除「' + title + '」将同时删除其所有下级文档,确定继续?', {
|
||
icon: 3, title: '确认删除'
|
||
}, function (index) {
|
||
layer.close(index);
|
||
$.post('/docs/backend/doc/delete/' + id, {}, function (res) {
|
||
if (res.code === 0) {
|
||
layer.msg(res.message, { icon: 1 }, function () { location.reload(); });
|
||
} else {
|
||
layer.msg(res.message || '删除失败', { icon: 2 });
|
||
}
|
||
}, 'json').fail(function () {
|
||
layer.msg('请求失败,请重试', { icon: 2 });
|
||
});
|
||
});
|
||
});
|
||
|
||
// 保存排序:收集所有节点的 id / pid / sort
|
||
$('#btnSaveSort').on('click', function () {
|
||
var nodes = [];
|
||
$('#docTree .doc-node').each(function () {
|
||
var $node = $(this);
|
||
nodes.push({
|
||
id: parseInt($node.data('id'), 10),
|
||
pid: parseInt($node.data('pid'), 10),
|
||
sort: parseInt($node.find('.doc-sortbox').val(), 10) || 0
|
||
});
|
||
});
|
||
|
||
if (!nodes.length) {
|
||
layer.msg('没有可排序的文档', { icon: 0 });
|
||
return;
|
||
}
|
||
|
||
var loading = layer.load(1);
|
||
$.post('/docs/backend/doc/sort', { nodes: JSON.stringify(nodes) }, function (res) {
|
||
layer.close(loading);
|
||
if (res.code === 0) {
|
||
layer.msg(res.message, { icon: 1 }, function () { location.reload(); });
|
||
} else {
|
||
layer.msg(res.message || '保存失败', { icon: 2 });
|
||
}
|
||
}, 'json').fail(function () {
|
||
layer.close(loading);
|
||
layer.msg('请求失败,请重试', { icon: 2 });
|
||
});
|
||
});
|
||
|
||
// 重建搜索索引
|
||
$('#btnRebuild').on('click', function () {
|
||
var loading = layer.load(1);
|
||
$.post('/docs/backend/doc/rebuild-index', { project_id: projectId }, function (res) {
|
||
layer.close(loading);
|
||
layer.msg(res.message || '完成', { icon: res.code === 0 ? 1 : 2 });
|
||
}, 'json').fail(function () {
|
||
layer.close(loading);
|
||
layer.msg('请求失败,请重试', { icon: 2 });
|
||
});
|
||
});
|
||
});
|
||
</script>
|