增加导航和单页面管理

This commit is contained in:
muzi_ys 2022-07-04 00:54:39 +08:00
parent f9dfa5e1dc
commit c6a0489fa8
33 changed files with 3675 additions and 90 deletions

View File

@ -4,7 +4,9 @@ namespace app\admin\controller;
use app\common\model\AdminAuth;
use app\common\model\Document;
use app\common\model\Document as DocumentModel;
use app\common\model\DocumentCategory;
use app\common\model\DocumentCategory as DocumentCategoryModel;
use app\common\model\MessageForm;
use Exception;
use think\db\exception\DataNotFoundException;
@ -67,4 +69,81 @@ class Index extends AuthController
}
return app("json")->success($menuList);
}
/**
* 生成sitemap.xml
*/
public function sitemap()
{
//获取协议
$protocol = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $_SERVER['SERVER_PORT'] == 443) ?
"https://" : "http://";
//获取域名
$domain = $protocol . $_SERVER['HTTP_HOST'];
//获取页码
$page = input('page/d');
if (!$page) {
$page = 1;
}
$str = '';
if ($page == 1) {
if(file_exists('sitemap.xml'))
unlink('sitemap.xml');
$str .= '<?xml version="1.0" encoding="utf-8"?>';
$str .= '<urlset>';
//首页
$str .= '<url>';
$str .= '<loc>' . $domain . '</loc>';
$str .= '<lastmod>' . date('Y-m-d', time()) . '</lastmod>';
$str .= '<changefreq>daily</changefreq>';
$str .= '<priority>1.0</priority>';
$str .= '</url>';
}
$pagesize = 100;
//获取文章分类url
$documentCategoryModel=new DocumentCategoryModel();
$categoryInfo = $documentCategoryModel->field('id,title,create_time')
->where('display', 1)->where('status', 1)
->page($page, $pagesize)
->order('id desc')->select();
foreach ($categoryInfo as $v) {
$str .= '<url>';
$str .= '<loc>' . $domain . url('article/lists?id=' . $v['id']) . '</loc>';
$str .= '<lastmod>' . $v['create_time']. '</lastmod>';
$str .= '<changefreq>always</changefreq>';
$str .= '<priority>0.8</priority>';
$str .= '</url>';
}
//获取详细页分类url
$documentModel=new DocumentModel();
$documentInfo =$documentModel->field('id,create_time')
->where('status', 1)
->page($page, $pagesize)
->order('id desc')->select();
foreach ($documentInfo as $v) {
$str .= '<url>';
$str .= '<loc>' . $domain . url('article/detail?id=' . $v['id']) . $v['id'] . '</loc>';
$str .= '<lastmod>' . $v['create_time'] . '</lastmod>';
$str .= '<changefreq>monthly</changefreq>';
$str .= '<priority>0.6</priority>';
$str .= '</url>';
}
if (count($categoryInfo) < $pagesize && count($documentInfo) < $pagesize) {
$str .= '</urlset>';
if (!(file_put_contents('sitemap.xml', $str, FILE_APPEND | LOCK_EX))) {
$this->error('站点地图更新失败!');
} else {
$this->success('站点地图全部更新完成!', null,'stop');
}
}
//写入
if (!(file_put_contents('sitemap.xml', $str, FILE_APPEND | LOCK_EX))) {
$this->error('站点地图更新失败!');
} else {
$this->success('站点地图正在生成,请稍后(' . $page . '...', 'sitemap?page=' . ($page + 1));
}
}
}

View File

@ -0,0 +1,144 @@
<?php
namespace app\admin\controller;
use app\admin\extend\FormBuilder as Form;
use app\common\model\Nav as aModel;
use app\Request;
use app\admin\extend\Util as Util;
use Exception;
use FormBuilder\Exception\FormBuilderException;
use FormBuilder\Factory\Elm;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Route as Url;
/**
* Class Nav
* @package app\admin\controller\system
* @author 李玉坤
* @date 2021-02-15 23:20
*/
class Nav extends AuthController
{
public function index()
{
return $this->fetch();
}
/**
* 导航列表
* @param Request $request
* @return array
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function lst(Request $request)
{
$where = Util::postMore([
['title', ''],
['status', '']
]);
return app("json")->layui(\app\common\model\Nav::systemPage($where));
}
/**
* 添加
* @param int $pid
* @return string
* @throws FormBuilderException
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws Exception
*/
public function add($pid = 0)
{
$form = array();
$form[] = Elm::select('pid', '上级导航', (int)$pid)->options(aModel::returnOptions())->col(10);
$form[] = Elm::input('title', '导航名称')->col(10);
// $form[] = Elm::frameInput('icon', '图标', Url::buildUrl('admin/icon/index', array('fodder' => 'icon')))->icon("ios-ionic")->width('96%')->height('390px')->col(10);
$form[] = Elm::input('url', '链接地址')->col(10);
$form[] = Elm::input('params', '参数')->placeholder("php数组,不懂不要填写")->col(10);
$form[] = Elm::number('sort', '排序')->col(10);
$form[] = Elm::radio('status', '状态', 1)->options([['label' => '启用', 'value' => 1], ['label' => '冻结', 'value' => 0]])->col(10);
$form = Form::make_post_form($form, url('save')->build());
$this->assign(compact('form'));
return $this->fetch("public/form-builder");
}
/**
* 添加
* @param int $id
* @return string
* @throws FormBuilderException
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function edit($id = 0)
{
if (!$id) return app("json")->fail("导航id不能为空");
$ainfo = aModel::get($id);
if (!$ainfo) return app("json")->fail("没有该导航");
$form = array();
$form[] = Elm::select('pid', '上级导航', $ainfo['pid'])->options(aModel::returnOptions())->col(10);
$form[] = Elm::input('title', '导航名称', $ainfo['title'])->col(10);
//$form[] = Elm::frameInput('icon', '图标', Url::buildUrl('admin/widget.icon/index', array('fodder' => 'icon')), $ainfo['icon'])->icon("ios-ionic")->width('96%')->height('390px')->col(10);
$form[] = Elm::input('url', '链接地址', $ainfo['url'])->col(10);
$form[] = Elm::input('params', '参数', $ainfo['params'])->placeholder("php数组,不懂不要填写")->col(10);
$form[] = Elm::number('sort', '排序', $ainfo['sort'])->col(10);
$form[] = Elm::radio('status', '状态', $ainfo['status'])->options([['label' => '启用', 'value' => 1], ['label' => '冻结', 'value' => 0]])->col(10);
$form = Form::make_post_form($form, url('save', ['id' => $id])->build());
$this->assign(compact('form'));
return $this->fetch("public/form-builder");
}
/**
* 保存
* @param $id
* @return
*/
public function save($id = "")
{
$data = Util::postMore([
['title', ''],
['pid', 0],
['icon', ''],
['url', ''],
['params', ''],
['sort', 0],
['status', 1]
]);
if ($data['title'] == "") return app("json")->fail("导航名称不能为空");
if ($data['pid'] == "") return app("json")->fail("上级归属不能为空");
if ($data['url'] == "") return app("json")->fail("链接不能为空");
if ($id == "") {
$data['create_time'] = time();
$res = aModel::insert($data);
} else {
$data['update_time'] = time();
$res = aModel::update($data, ['id' => $id]);
}
//清理缓存
aModel::clearCache($this->adminId);
return $res ? app("json")->success("操作成功", 'code') : app("json")->fail("操作失败");
}
/**
* 修改字段
* @param $id
* @return aModel
*/
public function field($id)
{
if (!$id) return app("json")->fail("参数有误Id为空");
$where = Util::postMore([['field', ''], ['value', '']]);
if ($where['field'] == '' || $where['value'] == '') return app("json")->fail("参数有误!");
//清理缓存
aModel::clearCache($this->adminId);
return aModel::update([$where['field'] => $where['value']], ['id' => $id]) ? app("json")->success("操作成功") : app("json")->fail("操作失败");
}
}

View File

@ -0,0 +1,278 @@
<?php
namespace app\admin\controller;
use app\common\model\Document as aModel;
use app\common\model\DocumentCategory as cModel;
use app\common\model\Tag as TagModel;
use app\common\model\DocumentArticle;
use app\common\model\Comment as CommentModel;
use app\Request;
use app\admin\extend\Util as Util;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use think\facade\Log;
/**
* Class Page
* @package app\admin\controller\system
* @author 李玉坤
* @date 2021-02-15 23:20
*/
class Page extends AuthController
{
/**
* 文章管理主页
* @return string
* @throws \Exception
*/
public function index()
{
return $this->fetch();
}
/**
* 文章列表
* @return mixed
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @author 李玉坤
* @date 2021-02-15 23:26
*/
public function lst()
{
$where = Util::postMore([
['title', ''],
['start_time', ''],
['end_time', ''],
['status', ''],
['page', 1],
['limit', 20],
]);
return app("json")->layui(aModel::systemPage($where));
}
/**
* 保存
* @param string $id
* @return mixed
* @author 李玉坤
* @date 2021-02-28 22:43
*/
public function save($id = "")
{
$data = Util::postMore([
['id', ''],
['author', ''],
['title', ''],
['alias', ''],
['category_id', ''],
['type', 'page'],
['abstract', ''],
['keywords', ''],
['content', ''],
['description', ''],
['is_recommend', 0],
['is_top', 0],
['is_hot', 0],
['link_str', ''],
['cover_path', ''],
['display', 1],
['tags', ''],
['sort', ''],
['status', 1],
]);
if ($data['title'] == "") return app("json")->fail("文章名称不能为空");
if ($data['category_id'] == "") return app("json")->fail("栏目分类不能为空");
if ($data['cover_path'] == "") return app("json")->fail("主图不能为空");
$error = "";
try {
$data['author'] = $data['author'] ?: $this->adminInfo['nickname'];
$data['uid'] = $this->adminId;
$content = '';
if (!empty($data['content'])) {
$content = $data['content'];
}
//判断摘要是否为空,为空则从内容摘取
$data['abstract'] = $data['abstract'] ?: mb_substr(strip_tags($content), 0, 100);
//判断是否写了别名,没写则需要生成
if ($data['alias'] == "") $data['alias'] = get_rand_str(6);
unset($data['content']);
if ($data['is_recommend']) $data['is_recommend'] = 1;
if ($data['is_hot']) $data['is_hot'] = 1;
if ($data['display']) $data['display'] = 1;
if ($data['is_top']) $data['is_top'] = 1;
if ($id == "") {
$data['uid'] = $this->adminInfo['uid'];
$data['author'] = $data['author'] ?: $this->adminInfo['nickname'];
$data['create_date'] = date("Y-m-d");
$data['create_time'] = time();
$data['update_time'] = time();
$id = aModel::insertGetId($data);
if (!empty($content)) {
$updateData = [
'id' => $id,
'content' => $content
];
DocumentArticle::insert($updateData);
}
if (!empty($data['tags'])) {
$tagModel = new TagModel();
$tagModel->createTags($data['tags'], $id, $this->adminId);
}
} else {
$ainfo = aModel::get($id);
if (!$ainfo) return app("json")->fail("数据不存在");
aModel::where('id', $id)->save($data);
if (!empty($content)) {
$contentInfo = DocumentArticle::where('id', $id)->find();
if (!$contentInfo) {
$updateData = [
'id' => $id,
'content' => $content
];
DocumentArticle::insert($updateData);
} else {
//更新文档
DocumentArticle::where('id', $id)->save(['content' => $content]);
}
}
if (!empty($data['tags'])) {
$tagModel = new TagModel();
$tagModel->createTags($data['tags'], $id, $this->adminId);
}
}
$res = true;
} catch (Exception $e) {
Log::error('文章修改失败:失败原因:' . $e->getMessage());
$error = $e->getMessage();
$res = false;
}
return $res ? app("json")->success("操作成功", 'code') : app("json")->fail("操作失败,错误原因:".$error);
}
/**
* 修改字段
* @param $id
* @return mixed
* @author 李玉坤
* @date 2021-02-16 23:12
*/
public function field($id)
{
if (!$id) return app("json")->fail("参数有误Id为空");
$where = Util::postMore([['field', ''], ['value', '']]);
if ($where['field'] == '' || $where['value'] == '') return app("json")->fail("参数有误!");
return aModel::update([$where['field'] => $where['value']], ['id' => $id]) ? app("json")->success("操作成功") : app("json")->fail("操作失败");
}
/**
* 新增文章
* @param $category_id
* @return string
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @author 李玉坤
* @date 2021-03-10 14:46
*/
public function add($category_id = '')
{
$where = [
'name' => '',
'status' => ''
];
$category = cModel::systemPage($where);
$category = get_tree_list($category);
$this->assign("category", $category);
$this->assign("category_id", $category_id);
return $this->fetch();
}
/**
* 编辑页
* @return string
* @throws \Exception
* @author 李玉坤
* @date 2021-02-20 17:00
*/
public function edit()
{
$where = Util::postMore([
['name', ''],
['id', '']
]);
if ($where['id'] == '') {
return $this->error('数据不存在');
}
$category = cModel::systemPage($where);
$category = get_tree_list($category);
$info = aModel::get($where['id']);
$content = DocumentArticle::get($where['id']);
if ($content) {
$info->content = $content->content;
} else {
$info->content = '';
}
$this->assign("category", $category);
$this->assign("info", $info);
return $this->fetch();
}
/**
* 文章管理主页
* @return string
* @throws \Exception
*/
public function comment()
{
return $this->fetch();
}
/**
* 文章评论列表
* @return mixed
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @author 李玉坤
* @date 2021-11-03 23:28
*/
public function commentList()
{
$where = Util::postMore([
['document_id', ''],
['name', ''],
['tel', ''],
['email', ''],
['start_time', ''],
['end_time', ''],
['page', 1],
['limit', 20],
]);
if ($where['document_id'] == "") return app("json")->fail("参数错误");
return app("json")->layui(CommentModel::systemPage($where));
}
/**
* 修改字段
* @param $id
* @return mixed
* @author 李玉坤
* @date 2021-02-16 23:12
*/
public function commentField($id)
{
if (!$id) return app("json")->fail("参数有误Id为空");
$where = Util::postMore([['field', ''], ['value', '']]);
if ($where['field'] == '' || $where['value'] == '') return app("json")->fail("参数有误!");
return CommentModel::update([$where['field'] => $where['value']], ['id' => $id]) ? app("json")->success("操作成功") : app("json")->fail("操作失败");
}
}

View File

@ -0,0 +1,340 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<title>登录页面 - {:system_config('title')}后台管理系统</title>
{include file="public/header" /}
</head>
<body>
<div class="container-fluid p-t-15">
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-header"><h4>搜索</h4></div>
<div class="card-body">
<form class="form-inline searchForm" onsubmit="return false;">
<div class="form-group">
<label for="title">权限名称</label>
<div class="input-group">
<div class="input-group">
<input type="text" class="form-control" id="title" value="" name="title"
placeholder="请输入权限名称或者ID">
</div>
</div>
</div>
<div class="form-group">
<label for="status">状态</label>
<select name="status" id="status" class="form-control">
<option value="">所有</option>
<option value="1">启用</option>
<option value="0">禁用</option>
</select>
</div>
<button type="submit" class="btn btn-success" style="margin: -10px 0 0 10px;" id="search">搜索
</button>
</form>
</div>
</div>
</div>
<div class="col-lg-12">
<div class="card">
<div class="card-header">
<h4>权限管理</h4>
</div>
<div class="card-body">
<div id="toolbar2" class="toolbar-btn-action">
<button type="button" class="btn btn-primary m-r-5"
onclick="iframe.createIframe('添加权限','/admin/nav/add')"><span class="mdi mdi-plus"
aria-hidden="true"></span>新增
</button>
<button id="btn_edit" type="button" class="btn btn-success m-r-5" onclick="isEnable('enable')">
<span class="mdi mdi-check" aria-hidden="true"></span>启用
</button>
<button id="btn_disable" type="button" class="btn btn-warning m-r-5"
onclick="isEnable('disable')">
<span class="mdi mdi-block-helper" aria-hidden="true"></span>禁用
</button>
<button id="btn_delete" type="button" class="btn btn-danger" onclick="del()">
<span class="mdi mdi-window-close" aria-hidden="true"></span>删除
</button>
</div>
<table class="tree-table"></table>
</div>
</div>
</div>
</div>
</div>
{include file="public/footer"/}
<!--以下是tree-grid的使用示例-->
<link href="/static/admin/js/jquery-treegrid/jquery.treegrid.min.css" rel="stylesheet">
<script type="text/javascript" src="/static/admin/js/jquery-treegrid/jquery.treegrid.min.js"></script>
<script type="text/javascript"
src="/static/admin/js/bootstrap-table/extensions/treegrid/bootstrap-table-treegrid.min.js"></script>
<script type="text/javascript">
// tree-grid使用
var $treeTable = $('.tree-table');
$treeTable.bootstrapTable({
url: '/admin/nav/lst',
method: 'post',
responseHandler: function (res) {
return {
"rows": res.data,
};
},
queryParams: function (params) {
var temp = toArrayList($(".searchForm").serializeArray());
return temp;
},
idField: 'id',
uniqueId: 'id',
dataType: 'json',
toolbar: '#toolbar2',
showColumns: true, // 是否显示所有的列
showRefresh: true, // 是否显示刷新按钮
columns: [
{
field: 'check',
checkbox: true
},
{
field: 'id',
title: 'ID'
},
{
field: 'title',
title: '名称'
},
{
field: 'pid',
title: '父级ID'
},
{
field: 'url',
title: '链接',
},
{
field: 'sort',
title: '排序',
sortable: true,
},
{
field: 'status',
title: '状态',
formatter: function (value, row, index) {
if (value == 0) {
is_checked = '';
} else if (value == 1) {
is_checked = 'checked="checked"';
}
var field = "status";
result = '<label class="lyear-switch switch-primary switch-solid lyear-status"><input type="checkbox" ' + is_checked + '><span onClick="updateStatus(' + row.id + ', ' + value + ', \'' + field + '\')"></span></label>';
return result;
},
},
{
field: 'operate',
title: '操作',
align: 'center',
events: {
'click .role-add': function (e, value, row, index) {
iframe.createIframe('添加权限', '/admin/nav/add?pid=' + row.id);
},
'click .role-delete': function (e, value, row, index) {
$.alert({
title: '系统提示',
content: '删除提醒',
buttons: {
confirm: {
text: '确认',
btnClass: 'btn-primary',
action: function () {
$.post(url = "/admin/nav/del", data = {"id": row.id}, function (res) {
if (res.status == 200) {
parent.lightyear.notify('删除成功', 'success', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
$(".tree-table").bootstrapTable('refresh');
} else parent.lightyear.notify('删除失败', 'danger', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
});
}
},
cancel: {
text: '取消'
}
}
});
},
'click .role-edit': function (e, value, row, index) {
iframe.createIframe('修改权限', '/admin/nav/edit?id=' + row.id)
}
},
formatter: operateFormatter
}
],
treeShowField: 'title',
parentIdField: 'pid',
onResetView: function (data) {
$treeTable.treegrid({
initialState: 'collapsed', // 所有节点都折叠
treeColumn: 1,
onChange: function () {
$treeTable.bootstrapTable('resetWidth');
}
});
// 只展开树形的第一集节点
$treeTable.treegrid('getRootNodes').treegrid('expand');
},
onCheck: function (row) {
var datas = $treeTable.bootstrapTable('getData');
selectChilds(datas, row, 'id', 'pid', true);
selectParentChecked(datas, row, 'id', 'pid');
$treeTable.bootstrapTable('load', datas);
},
onUncheck: function (row) {
var datas = $treeTable.bootstrapTable('getData');
selectChilds(datas, row, 'id', 'pid', false);
$treeTable.bootstrapTable('load', datas);
},
});
// 操作按钮
function operateFormatter(value, row, index) {
return [
'<a type="button" class="role-add btn btn-xs btn-default m-r-5" title="编辑" data-toggle="tooltip"><i class="mdi mdi-plus"></i></a>',
'<a type="button" class="role-edit btn btn-xs btn-default m-r-5" title="修改" data-toggle="tooltip"><i class="mdi mdi-pencil"></i></a>',
'<a type="button" class="role-delete btn btn-xs btn-default" title="删除" data-toggle="tooltip"><i class="mdi mdi-delete"></i></a>'
].join('');
}
/**
* 选中父项时,同时选中子项
* @param datas 所有的数据
* @param row 当前数据
* @param id id 字段名
* @param pid 父id字段名
*/
function selectChilds(datas, row, id, pid, checked) {
for (var i in datas) {
if (datas[i][pid] == row[id]) {
datas[i].check = checked;
selectChilds(datas, datas[i], id, pid, checked);
}
}
}
function selectParentChecked(datas, row, id, pid) {
for (var i in datas) {
if (datas[i][id] == row[pid]) {
datas[i].check = true;
selectParentChecked(datas, datas[i], id, pid);
}
}
}
function updateStatus(id, value, field) {
var newstate = (value == 1) ? 0 : 1; // 发送参数值跟当前参数值相反
$.ajax({
type: "post",
url: "/admin/nav/field?id=" + id,
data: {field: field, value: newstate},
dataType: 'json',
success: function (res) {
if (res.status == 200) {
parent.lightyear.notify('修改成功', 'success', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
$(".tree-table").bootstrapTable('refresh');
} else parent.lightyear.notify('修改失败', 'danger', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
},
error: function () {
parent.lightyear.notify('修改失败', 'danger', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
}
});
}
// 删除
function del() {
var checkID = "";
var selectedItem = $treeTable.bootstrapTable('getSelections');
if (selectedItem == "") return lightyear.notify("没有选中项", 'danger', 3000, 'mdi mdi-emoticon-neutral', 'top', 'center');
for (var i = 0; i < selectedItem.length; i++) {
checkID += selectedItem[i]['id'] + ",";
}
if (checkID == "") return lightyear.notify("没有选中项", 'danger', 3000, 'mdi mdi-emoticon-neutral', 'top', 'center');
$.confirm({
title: '重要提醒!',
content: '选中项将全部被删除,请谨慎操作!',
backgroundDismiss: true,
buttons: {
ok: {
text: '确认',
btnClass: 'btn-danger',
action: function () {
$.post("/admin/nav/del", data = {id: checkID}, function (res) {
if (res.status == 200) {
lightyear.notify(res.msg, 'success', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
location.reload();
} else lightyear.notify(res.msg, 'danger', 3000, 'mdi mdi-emoticon-neutral', 'top', 'center');
})
}
},
cancel: {
text: '取消',
btnClass: 'btn-primary'
}
}
});
}
// 批量启用或者禁用
function isEnable(type) {
var checkID = "";
var selectedItem = $treeTable.bootstrapTable('getSelections');
if (selectedItem == "") return lightyear.notify("没有选中项", 'danger', 3000, 'mdi mdi-emoticon-neutral', 'top', 'center');
for (var i = 0; i < selectedItem.length; i++) {
checkID += selectedItem[i]['id'] + ",";
}
if (checkID == "") return lightyear.notify("没有选中项", 'danger', 3000, 'mdi mdi-emoticon-neutral', 'top', 'center');
$.confirm({
title: '重要提醒!',
content: type == 'enable' ? '选中项将全部启用,请谨慎操作!' : '选中项将全部禁用,请谨慎操作!',
backgroundDismiss: true,
buttons: {
ok: {
text: '确认',
btnClass: 'btn-danger',
action: function () {
if (type == 'enable') {
$.post("/admin/nav/enabled", data = {id: checkID}, function (res) {
if (res.status == 200) {
lightyear.notify(res.msg, 'success', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
location.reload();
} else lightyear.notify(res.msg, 'danger', 3000, 'mdi mdi-emoticon-neutral', 'top', 'center');
})
} else {
$.post("/admin/nav/disabled", data = {id: checkID}, function (res) {
if (res.status == 200) {
lightyear.notify(res.msg, 'success', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
location.reload();
} else lightyear.notify(res.msg, 'danger', 3000, 'mdi mdi-emoticon-neutral', 'top', 'center');
})
}
}
},
cancel: {
text: '取消',
btnClass: 'btn-primary'
}
}
});
}
$("#search").click(function () {
$treeTable.bootstrapTable('refresh', {});
});
</script>
</body>
</html>

View File

@ -0,0 +1,300 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<title>添加文章 - {:system_config('title')}后台管理系统</title>
{include file="public/header" /}
<!--标签插件-->
<link rel="stylesheet" href="/static/admin/js/jquery-tags-input/jquery.tagsinput.min.css">
<!--富文本输入框-->
<link rel="stylesheet" href="/static/admin/js/summernote/summernote.min.css">
</head>
<body>
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-body">
<ul id="myTabs" class="nav nav-tabs" role="tablist">
<li class="active"><a href="#home" id="home-tab" role="tab" data-toggle="tab">基本信息</a></li>
<li><a href="#profile" role="tab" id="profile-tab" data-toggle="tab">文章设置</a></li>
<li class="tab-right"><a data-toggle="tooltip" data-original-title="返回"
onclick="history.back(-1);return false;">返 回</a></li>
</ul>
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="home">
<form action="#!" method="post" class="row add-form" onsubmit="return false;">
<div class="form-group col-md-12">
<label>文章名称</label>
<input type="text" class="form-control" id="title" name="title" value=""
placeholder="文章名称"/>
</div>
<div class="form-group col-md-12">
<label>别名</label>
<input type="text" class="form-control" id="alias" name="alias" value=""
placeholder="别名索引"/>
</div>
<div class="form-group col-md-12">
<label for="category_id">栏目分类</label>
<div class="form-controls">
<select name="category_id" id="category_id" class="form-control">
<option value="0">请选择</option>
{volist name="category" id="vo"}
<option value="{$vo.id}"
{notempty name="pid" }{if $vo.id==$category_id}selected{/if} {/notempty}
>{$vo.html}{$vo.title}</option>
{/volist}
</select>
</div>
</div>
<div class="form-group col-md-12">
<label for="writer">作者</label>
<input type="text" class="form-control" id="writer" name="writer" value=""
placeholder="原作者"/>
</div>
<div class="form-group col-md-12">
<label>主图</label>
<div class="form-controls">
<ul class="list-inline clearfix lyear-uploads-pic">
<li class="col-xs-4 col-sm-3 col-md-2" id="pic-image" style="display: none;">
</li>
<li class="col-xs-4 col-sm-3 col-md-2" id="pic-upload">
<input type="hidden" class="form-control" name="cover_path" id="cover_path"
value=""/>
<input type="file" id="file_cover_path" accept="image/*" style="display: none;"
onchange="upload('cover_path')"/>
<a class="pic-add" href="#!" onclick="btnClick('cover_path')"
title="上传"></a>
</li>
</ul>
</div>
</div>
<div class="form-group col-md-12">
<label for="abstract">摘要</label>
<input type="text" class="form-control" name="abstract" id="abstract"
placeholder="请输入摘要">
</div>
<div class="form-group col-md-12">
<label for="abstract">标签</label>
<input class="form-control js-tags-input" type="text" name="tags" data-height="38px"
placeholder="请输入标签">
</div>
<div class="form-group col-md-12">
<label for="content">文章内容</label>
<textarea id="content" name="content" data-provide="summernote" data-toolbar="full"></textarea>
</div>
<div class="form-group col-md-12">
<button type="submit" class="btn btn-primary ajax-post" target-form="add-form">立即提交
</button>
</div>
</form>
</div>
<div class="tab-pane fade" id="profile">
<form action="#!" method="post" class="row add-form" onsubmit="return false;">
<div class="form-group row col-md-2">
<div class="col-xs-6">推荐</div>
<div class="col-xs-6">
<label class="lyear-switch switch-solid switch-primary">
<input type="checkbox" name="is_recommend">
<span></span>
</label>
</div>
</div>
<div class="form-group row col-md-2">
<div class="col-xs-6">热门</div>
<div class="col-xs-6">
<label class="lyear-switch switch-solid switch-primary">
<input type="checkbox" name="is_hot">
<span></span>
</label>
</div>
</div>
<div class="form-group row col-md-2">
<div class="col-xs-6">置顶</div>
<div class="col-xs-6">
<label class="lyear-switch switch-solid switch-primary">
<input type="checkbox" name="is_top">
<span></span>
</label>
</div>
</div>
<div class="form-group col-md-12">
<label for="abstract">排序</label>
<input type="text" class="form-control" name="sort" placeholder="请输入排序" value="99">
</div>
<div class="form-group col-md-12">
<label for="link_str">外链</label>
<input type="text" class="form-control" name="link_str" id="link_str" placeholder="外链">
</div>
<div class="form-group col-md-12">
<label for="keywords">seo关键字</label>
<input type="text" class="form-control" id="keywords" name="keywords"
placeholder="请输入seo关键字">
</div>
<div class="form-group col-md-12">
<label for="description">seo描述</label>
<input type="text" class="form-control" name="description" id="description"
placeholder="seo描述">
</div>
<div class="form-group col-md-12">
<button type="submit" class="btn btn-primary ajax-post" target-form="add-form">立即提交
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
{include file="public/footer"/}
<!--select2-->
<script type="text/javascript" src="/static/admin/js/select2.min.js"></script>
<!--富文本输入框-->
<script type="text/javascript" src="/static/admin/js/summernote/summernote.min.js"></script>
<script type="text/javascript" src="/static/admin/js/summernote/lang/summernote-zh-CN.min.js"></script>
<!--标签-->
<script src="/static/admin/js/jquery-tags-input/jquery.tagsinput.min.js"></script>
<script>
$(function () {
$('#tag').select2();
});
$(document).ready(function(){
$('[data-provide="summernote"]').each(function() {
var options = {
dialogsInBody: true,
lang: 'zh-CN',
dialogsFade: true,
height:400
};
var config = {};
$.each( $(this).data(), function(key, value){
key = key.replace(/-([a-z])/g, function(x){return x[1].toUpperCase();});
if ( key == 'provide' ) {
return;
}
config[key] = value;
});
options = $.extend(options, config);
options.toolbar = [
// [groupName, [list of button]]
['para_style', ['style']],
['style', ['bold', 'italic', 'underline', 'clear']],
['font', ['strikethrough', 'superscript', 'subscript']],
['fontsize', ['fontname', 'fontsize', 'height']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph', 'hr']],
['table', ['table']],
['insert', ['link', 'picture', 'video']],
['do', ['undo', 'redo']],
['misc', ['fullscreen', 'codeview', 'help']]
];
$(this).summernote(options);
});
$(document).on('click', '[data-summernote-edit]', function(){
var target = $(this).data('summernote-edit');
$(target).summernote({focus: true});
});
$(document).on('click', '[data-summernote-save]', function(){
var target = $(this).data('summernote-save');
var markup = $(target).summernote('code');
$(target).summernote('destroy');
alert('修改完成');
});
});
/**
* 选择文件
* @param inputName
*/
function btnClick(inputName) {
$("#file_" + inputName).click()
}
/**
* 异步上传
* @param inputName
*/
function upload(inputName) {
var formData = new FormData();
formData.append("type", 'image');
formData.append("file", $("#file_" + inputName)[0].files[0]);
$.ajax({
type: 'POST',
url: '/admin/file/upload',
data: formData,
cache: false,
processData: false,
contentType: false,
success: function (res) {
if (res.code == 200) {
$("#" + inputName).val(res.data.filePath);
let html = ' <figure>\n' +
' <img src="' + res.data.filePath + '" alt="' + res.data.name + '">\n' +
' <figcaption>\n' +
' <a class="btn btn-round btn-square btn-danger btn-image-delete" href="#!"><i class="mdi mdi-delete"></i></a>\n' +
' </figcaption>\n' +
' </figure>';
$('#pic-image').html(html);
$('#pic-image').show().next('li').hide();
} else {
lightyear.notify(res.msg, 'danger', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
return false;
}
}
});
}
$(".add-form").submit(function () {
let Arr = $('.add-form').serializeArray();
let checkResult = true;
$.each(Arr, function (index, item) {
try {
switch (item.name) {
case 'category_id':
if (!item.value) {
throw "栏目分类不能为空";
}
break;
case 'title':
if (!item.value) {
throw "文章名称不能为空";
}
break;
case 'cover_path':
if (!item.value) {
throw "主图不能为空";
}
break;
}
} catch (error) {
lightyear.notify(error, 'danger', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
checkResult = false;
return false;
}
})
// 检验不通过终止执行
if (!checkResult) {
return false;
}
$.post(url = "/admin/article/save", $('.add-form').serialize(), function (res) {
if (res.code == 200) {
lightyear.notify(res.msg, 'success', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
setTimeout(function () {
location.href = '/admin/article/index';
}, 2000)
} else lightyear.notify(res.msg, 'danger', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
});
return true;
})
//删除事件
$('body').on('click', '.btn-image-delete', function () {
$('#pic-image').hide().next('li').show();
$('#cover_path').val('');
})
</script>
</body>
</html>

View File

@ -0,0 +1,286 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<title>文章评论管理 - {:system_config('title')}后台管理系统</title>
{include file="public/header" /}
</head>
<body>
<div class="container-fluid p-t-15">
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-header">
<h4>搜索</h4>
<ul class="card-actions">
<li>
<button type="button" data-toggle="tooltip" title="" data-original-title="返回"
onclick="history.back(-1);return false;"><i class="mdi mdi-undo"></i></button>
</li>
</ul>
</div>
<div class="card-body">
<form class="form-inline searchForm" onsubmit="return false;">
<div class="form-group">
<label for="author">姓名</label>
<div class="input-group">
<div class="input-group">
<input type="text" class="form-control" id="author" name="author"
placeholder="请输入姓名">
</div>
</div>
</div>
<div class="form-group">
<label for="email">邮箱</label>
<div class="input-group">
<div class="input-group">
<input type="text" class="form-control" id="email" name="email" placeholder="邮箱">
</div>
</div>
</div>
<div class="form-group">
<label for="url">网址</label>
<div class="input-group">
<div class="input-group">
<input type="text" class="form-control" id="url" name="url" placeholder="网址">
</div>
</div>
</div>
<div class="form-group">
<label for="start_time">操作时间</label>
<div class="input-group">
<input class="form-control js-datetimepicker" type="text" id="start_time"
name="start_time" autocomplete="off" data-side-by-side="true" data-locale="zh-cn"
data-format="YYYY-MM-DD" placeholder="开始时间">
<span class="input-group-addon">~</span>
<input class="form-control js-datetimepicker" type="text" id="end_time" name="end_time"
autocomplete="off" data-side-by-side="true" data-locale="zh-cn"
data-format="YYYY-MM-DD" placeholder="结束时间">
</div>
</div>
<button type="submit" class="btn btn-success" style="margin: -10px 0 0 10px;" id="search">搜索
</button>
</form>
</div>
</div>
</div>
<div class="col-lg-12">
<div class="card">
<div class="card-toolbar clearfix">
<div class="toolbar-btn-action">
<a class="btn btn-warning" href="#!" onclick="delSelect()"><i class="mdi mdi-window-close"></i>
删除</a>
</div>
</div>
<div class="card-body">
<table id="tb_departments"></table>
</div>
</div>
</div>
</div>
</div>
{include file="public/footer"/}
<script type="text/javascript">
var id = GetQueryString("id");
$('#tb_departments').bootstrapTable({
classes: 'table table-bordered table-hover table-striped',
url: '/admin/article/commentList?id=' + id,
method: 'post',
dataType: 'json', // 因为本示例中是跨域的调用,所以涉及到ajax都采用jsonp,
uniqueId: 'id',
idField: 'id', // 每行的唯一标识字段
toolbar: '#toolbar', // 工具按钮容器
showColumns: false, // 是否显示所有的列
showRefresh: false, // 是否显示刷新按钮
responseHandler: function (res) {
return {
"total": res.count,
"rows": res.data,
};
},
pagination: true,
queryParams: function (params) {
let temp = toArrayList($(".searchForm").serializeArray());
temp['document_id'] = id;
temp['limit'] = params.limit;
temp['page'] = (params.offset / params.limit) + 1;
return temp;
},
sidePagination: "server",
pageNumber: 1,
pageSize: 10,
pageList: [10, 20, 50, 100],
columns: [{
checkbox: true, // 是否显示复选框
}, {
field: 'id',
title: 'ID'
}, {
field: 'author',
title: '姓名'
}, {
field: 'email',
title: '邮箱',
}, {
field: 'url',
title: '网址',
}, {
field: 'status',
title: '状态',
formatter: function (value, row, index) {
if (value == 0) {
is_checked = '';
} else if (value == 1) {
is_checked = 'checked="checked"';
}
var field = "display";
result = '<label class="lyear-switch switch-primary switch-solid lyear-status"><input type="checkbox" ' + is_checked + '><span onClick="updateStatus(' + row.id + ', ' + value + ', \'' + field + '\')"></span></label>';
return result;
},
}, {
field: 'create_time',
title: '留言时间',
}, {
field: 'operate',
title: '操作',
formatter: function (value, row, index) {
let html = '<a href="#!" class="btn btn-xs btn-default m-r-5 btn-detail" title="详情" data-toggle="tooltip" data-trigger="hover"><i class="mdi mdi-eye-outline"></i></a> \n' +
'<a class="btn btn-xs btn-default btn-del" href="#!" title="删除" data-toggle="tooltip" onclick="delOne(' + row.id + ')"><i class="mdi mdi-window-close"></i></a>';
return html;
},
events: {
'click .btn-detail': function (event, value, row, index) {
//职位描述+任职要求
let content = ' <div class="p-lr-15">\n' +
' <div class="row show-grid">\n' +
' <div class="col-xs-12 col-md-4">姓名:</div>\n' +
' <div class="col-xs-12 col-md-8">' + row.author + '</div>\n' +
' </div>\n' +
' <div class="row show-grid">\n' +
' <div class="col-xs-12 col-md-4">网址:</div>\n' +
' <div class="col-xs-12 col-md-8">' + row.url + '</div>\n' +
' </div>\n' +
' <div class="row show-grid">\n' +
' <div class="col-xs-12 col-md-4">邮箱:</div>\n' +
' <div class="col-xs-12 col-md-8">' + row.email + '</div>\n' +
' </div>\n' +
' <div class="row show-grid">\n' +
' <div class="col-xs-12 col-md-4">评论内容:</div>\n' +
' <div class="col-xs-12 col-md-8" style="white-space: pre-wrap;">' + row.content + '</div>\n' +
' </div>\n' +
' </div>';
$.alert({
title: '详情',
content: content,
boxWidth: '50%', //定义弹窗宽度
useBootstrap: false, //定义宽度必须设置
buttons: {
cancel: {
text: '关闭',
}
}
});
}
}
}],
onLoadSuccess: function (data) {
$("[data-toggle='tooltip']").tooltip();
}
});
//搜索
$("#search").click(function () {
let start_time = $('#start_time').val();
let end_time = $('#end_time').val();
if (start_time && end_time && start_time > end_time) {
alert('开始时间不能大于结束时间');
return false;
}
$("#tb_departments").bootstrapTable('refresh', {query: {page: 1}, pageNumber: 1});
});
function updateStatus(id, value, field) {
var newstate = (value == 1) ? 0 : 1; // 发送参数值跟当前参数值相反
$.ajax({
type: "post",
url: "/admin/article/commentField?id=" + id,
data: {field: field, value: newstate},
dataType: 'json',
success: function (res) {
if (res.status == 200) {
parent.lightyear.notify('修改成功', 'success', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
$(".tree-table").bootstrapTable('refresh');
} else parent.lightyear.notify('修改失败', 'danger', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
},
error: function () {
parent.lightyear.notify('修改失败', 'danger', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
}
});
}
function delOne(id) {
$.confirm({
title: '重要提醒!',
content: '删除后将不可恢复,请谨慎操作!',
backgroundDismiss: true,
buttons: {
ok: {
text: '确认',
btnClass: 'btn-danger',
action: function () {
$.post("/admin/message/del", data = {id: id}, function (res) {
if (res.status == 200 || res.code == 200) lightyear.notify(res.msg, 'success', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
else lightyear.notify(res.msg, 'danger', 3000, 'mdi mdi-emoticon-neutral', 'top', 'center');
location.reload();
})
}
},
cancel: {
text: '取消',
btnClass: 'btn-primary'
}
}
});
}
function delSelect() {
var checkID = "";
var selectedItem = $('#tb_departments').bootstrapTable('getSelections');
if (selectedItem == "") return lightyear.notify("没有选中项", 'danger', 3000, 'mdi mdi-emoticon-neutral', 'top', 'center');
for (var i = 0; i < selectedItem.length; i++) {
checkID += selectedItem[i]['id'] + ",";
}
if (checkID == "") return lightyear.notify("没有选中项", 'danger', 3000, 'mdi mdi-emoticon-neutral', 'top', 'center');
$.confirm({
title: '重要提醒!',
content: '选中项删除后将不可恢复,请谨慎操作!',
backgroundDismiss: true,
buttons: {
ok: {
text: '确认',
btnClass: 'btn-danger',
action: function () {
$.post("/admin/message/del", data = {id: checkID}, function (res) {
if (res.status == 200 || res.code == 200) {
lightyear.notify(res.msg, 'success', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
location.reload();
} else lightyear.notify(res.msg, 'danger', 3000, 'mdi mdi-emoticon-neutral', 'top', 'center');
})
}
},
cancel: {
text: '取消',
btnClass: 'btn-primary'
}
}
});
}
function GetQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]);
return null;
}
</script>
</body>
</html>

View File

@ -0,0 +1,317 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<title>编辑文章 - {:system_config('title')}后台管理系统</title>
{include file="public/header" /}
<!--标签插件-->
<link rel="stylesheet" href="/static/admin/js/jquery-tags-input/jquery.tagsinput.min.css">
<!--富文本输入框-->
<link rel="stylesheet" href="/static/admin/js/summernote/summernote.min.css">
</head>
<body>
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-body">
<ul id="myTabs" class="nav nav-tabs" role="tablist">
<li class="active"><a href="#home" id="home-tab" role="tab" data-toggle="tab">基本信息</a></li>
<li><a href="#profile" role="tab" id="profile-tab" data-toggle="tab">文章设置</a></li>
<li class="tab-right"><a data-toggle="tooltip" data-original-title="返回"
onclick="history.back(-1);return false;">返 回</a></li>
</ul>
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="home">
<form action="#!" method="post" class="row add-form" onsubmit="return false;">
<div class="form-group col-md-12">
<label>文章名称</label>
<input type="hidden" name="id" value="{$info.id}">
<input type="text" class="form-control" id="title" name="title" placeholder="文章名称" value="{$info.title}"/>
</div>
<div class="form-group col-md-12">
<label>别名</label>
<input type="text" class="form-control" id="alias" name="alias" value="{$info.alias}"
placeholder="别名索引"/>
</div>
<div class="form-group col-md-12">
<label for="category_id">栏目分类</label>
<div class="form-controls">
<select name="category_id" id="category_id" class="form-control">
{volist name="category" id="vo"}
<option value="{$vo.id}" {if $vo.id == $info.category_id}selected{/if}>{$vo.html}{$vo.title}</option>
{/volist}
</select>
</div>
</div>
<div class="form-group col-md-12">
<label for="author">作者</label>
<input type="text" class="form-control" id="author" name="author" placeholder="原作者" value="{$info.author}"/>
</div>
<div class="form-group col-md-12">
<label>主图</label>
<div class="form-controls">
<ul class="list-inline clearfix lyear-uploads-pic">
{notempty name="info.cover_path"}
<li class="col-xs-4 col-sm-3 col-md-2" id="pic-image" style="display: block;">
<figure>
<img src="{$info.cover_path}" alt="{$info.cover_path|basename}">
<figcaption>
<a class="btn btn-round btn-square btn-danger btn-image-delete"
href="#!"><i class="mdi mdi-delete"></i></a>
</figcaption>
</figure>
</li>
<li class="col-xs-4 col-sm-3 col-md-2" id="pic-upload" style="display: none;">
<input type="hidden" class="form-control" name="cover_path" id="cover_path"
value="{$info.cover_path}">
<input type="file" id="file_cover_path" accept="image/*" style="display: none;"
onchange="upload('cover_path')">
<a class="pic-add" href="#!" onclick="btnClick('cover_path')"
title="上传"></a>
</li>
{else /}
<li class="col-xs-4 col-sm-3 col-md-2" id="pic-image"
style="display: none;"></li>
<li class="col-xs-4 col-sm-3 col-md-2" id="pic-upload">
<input type="hidden" class="form-control" name="cover_path" id="cover_path">
<input type="file" id="file_cover_path" accept="image/*" style="display: none;"
onchange="upload('cover_path')">
<a class="pic-add" href="#!" onclick="btnClick('cover_path')"
title="上传"></a>
</li>
{/notempty}
</ul>
</div>
</div>
<div class="form-group col-md-12">
<label for="abstract">摘要</label>
<input type="text" class="form-control" name="abstract" id="abstract"
placeholder="请输入摘要" value="{$info.abstract}">
</div>
<div class="form-group col-md-12">
<label for="abstract">标签</label>
<input class="form-control js-tags-input" type="text" name="tags" data-height="38px"
placeholder="请输入标签" value="{$info.tags}">
</div>
<div class="form-group col-md-12">
<label for="content">文章内容</label>
<textarea id="content" name="content" data-provide="summernote" data-toolbar="full">{$info.content}</textarea>
</div>
<div class="form-group col-md-12">
<button type="submit" class="btn btn-primary ajax-post" target-form="add-form">立即提交
</button>
</div>
</form>
</div>
<div class="tab-pane fade" id="profile">
<form action="#!" method="post" class="row add-form" onsubmit="return false;">
<div class="form-group row col-md-2">
<div class="col-xs-6">推荐</div>
<div class="col-xs-6">
<label class="lyear-switch switch-solid switch-primary">
<input type="checkbox" name="is_recommend" {if $info.is_recommend}checked{/if}>
<span></span>
</label>
</div>
</div>
<div class="form-group row col-md-2">
<div class="col-xs-6">热门</div>
<div class="col-xs-6">
<label class="lyear-switch switch-solid switch-primary">
<input type="checkbox" name="is_hot" {if $info.is_hot}checked{/if}>
<span></span>
</label>
</div>
</div>
<div class="form-group row col-md-2">
<div class="col-xs-6">置顶</div>
<div class="col-xs-6">
<label class="lyear-switch switch-solid switch-primary">
<input type="checkbox" name="is_top" {if $info.is_top}checked{/if}>
<span></span>
</label>
</div>
</div>
<div class="form-group col-md-12">
<label for="abstract">排序</label>
<input type="text" class="form-control" name="sort" placeholder="请输入排序"
value="{$info.sort}">
</div>
<div class="form-group col-md-12">
<label for="link_str">外链</label>
<input type="text" class="form-control" name="link_str" id="link_str" placeholder="外链"
value="{$info.link_str}">
</div>
<div class="form-group col-md-12">
<label for="keywords">seo关键字</label>
<input type="text" class="form-control" id="keywords" name="keywords"
placeholder="请输入seo关键字" value="{$info.keywords}">
</div>
<div class="form-group col-md-12">
<label for="description">seo描述</label>
<input type="text" class="form-control" name="description" id="description"
placeholder="seo描述" value="{$info.description}">
</div>
<div class="form-group col-md-12">
<button type="submit" class="btn btn-primary ajax-post" target-form="add-form">立即提交
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
{include file="public/footer"/}
<!--select2-->
<script type="text/javascript" src="/static/admin/js/select2.min.js"></script>
<!--富文本输入框-->
<script type="text/javascript" src="/static/admin/js/summernote/summernote.min.js"></script>
<script type="text/javascript" src="/static/admin/js/summernote/lang/summernote-zh-CN.min.js"></script>
<!--标签-->
<script src="/static/admin/js/jquery-tags-input/jquery.tagsinput.min.js"></script>
<script>
$(function () {
$('#tag').select2();
});
$(document).ready(function(){
$('[data-provide="summernote"]').each(function() {
var options = {
dialogsInBody: true,
lang: 'zh-CN',
dialogsFade: true,
height:400
};
var config = {};
$.each( $(this).data(), function(key, value){
key = key.replace(/-([a-z])/g, function(x){return x[1].toUpperCase();});
if ( key == 'provide' ) {
return;
}
config[key] = value;
});
options = $.extend(options, config);
options.toolbar = [
// [groupName, [list of button]]
['para_style', ['style']],
['style', ['bold', 'italic', 'underline', 'clear']],
['font', ['strikethrough', 'superscript', 'subscript']],
['fontsize', ['fontname', 'fontsize', 'height']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph', 'hr']],
['table', ['table']],
['insert', ['link', 'picture', 'video']],
['do', ['undo', 'redo']],
['misc', ['fullscreen', 'codeview', 'help']]
];
$(this).summernote(options);
});
$(document).on('click', '[data-summernote-edit]', function(){
var target = $(this).data('summernote-edit');
$(target).summernote({focus: true});
});
$(document).on('click', '[data-summernote-save]', function(){
var target = $(this).data('summernote-save');
var markup = $(target).summernote('code');
$(target).summernote('destroy');
alert('修改完成');
});
});
/**
* 选择文件
* @param inputName
*/
function btnClick(inputName) {
$("#file_" + inputName).click()
}
/**
* 异步上传
* @param inputName
*/
function upload(inputName) {
var formData = new FormData();
formData.append("type", 'image');
formData.append("file", $("#file_" + inputName)[0].files[0]);
$.ajax({
type: 'POST',
url: '/admin/file/upload',
data: formData,
cache: false,
processData: false,
contentType: false,
success: function (res) {
if (res.code == 200) {
$("#" + inputName).val(res.data.filePath);
let html = ' <figure>\n' +
' <img src="' + res.data.filePath + '" alt="' + res.data.name + '">\n' +
' <figcaption>\n' +
' <a class="btn btn-round btn-square btn-danger btn-image-delete" href="#!"><i class="mdi mdi-delete"></i></a>\n' +
' </figcaption>\n' +
' </figure>';
$('#pic-image').html(html);
$('#pic-image').show().next('li').hide();
} else {
lightyear.notify(res.msg, 'danger', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
return false;
}
}
});
}
$(".add-form").submit(function () {
let Arr = $('.add-form').serializeArray();
let checkResult = true;
$.each(Arr, function (index, item) {
try {
switch (item.name) {
case 'category_id':
if (!item.value) {
throw "栏目分类不能为空";
}
break;
case 'title':
if (!item.value) {
throw "文章名称不能为空";
}
break;
case 'cover_path':
if (!item.value) {
throw "主图不能为空";
}
break;
}
} catch (error) {
lightyear.notify(error, 'danger', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
checkResult = false;
return false;
}
})
// 检验不通过终止执行
if (!checkResult) {
return false;
}
$.post(url = "/admin/article/save", $('.add-form').serialize(), function (res) {
if (res.code == 200) {
lightyear.notify(res.msg, 'success', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
setTimeout(function () {
location.href = '/admin/article/index';
}, 2000)
} else lightyear.notify(res.msg, 'danger', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
});
return true;
})
//删除事件
$('body').on('click', '.btn-image-delete', function () {
$('#pic-image').hide().next('li').show();
$('#cover_path').val('');
})
</script>
</body>
</html>

View File

@ -0,0 +1,254 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<title>文章管理 - {:system_config('title')}后台管理系统</title>
{include file="public/header" /}
</head>
<body>
<div class="container-fluid p-t-15">
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-header"><h4>搜索</h4></div>
<div class="card-body">
<form class="form-inline searchForm" onsubmit="return false;">
<div class="form-group">
<label for="title">文章标题</label>
<div class="input-group">
<div class="input-group">
<input type="text" class="form-control" id="title" name="title" placeholder="请输入文章标题">
</div>
</div>
</div>
<div class="form-group">
<label for="start_time">操作时间</label>
<div class="input-group">
<input class="form-control js-datetimepicker" type="text" id="start_time"
name="start_time" autocomplete="off" data-side-by-side="true" data-locale="zh-cn"
data-format="YYYY-MM-DD" placeholder="开始时间">
<span class="input-group-addon">~</span>
<input class="form-control js-datetimepicker" type="text" id="end_time" name="end_time"
autocomplete="off" data-side-by-side="true" data-locale="zh-cn"
data-format="YYYY-MM-DD" placeholder="结束时间">
</div>
</div>
<button type="submit" class="btn btn-success" style="margin: -10px 0 0 10px;" id="search">搜索
</button>
</form>
</div>
</div>
</div>
<div class="col-lg-12">
<div class="card">
<div class="card-toolbar clearfix">
<div class="toolbar-btn-action">
<a class="btn btn-primary m-r-5" href="/admin/page/add"><i class="mdi mdi-plus"></i> 新增</a>
<a class="btn btn-warning" href="#!" onclick="delSelect()"><i class="mdi mdi-window-close"></i>
删除</a>
</div>
</div>
<div class="card-body">
<table id="tb_departments"></table>
</div>
</div>
</div>
</div>
</div>
{include file="public/footer"/}
<script type="text/javascript">
$('#tb_departments').bootstrapTable({
classes: 'table table-bordered table-hover table-striped',
url: '/admin/page/Lst',
method: 'post',
dataType: 'json', // 因为本示例中是跨域的调用,所以涉及到ajax都采用jsonp,
uniqueId: 'id',
idField: 'id', // 每行的唯一标识字段
toolbar: '#toolbar', // 工具按钮容器
showColumns: false, // 是否显示所有的列
showRefresh: false, // 是否显示刷新按钮
responseHandler: function (res) {
return {
"total": res.count,
"rows": res.data,
};
},
pagination: true,
queryParams: function (params) {
let temp = toArrayList($(".searchForm").serializeArray());
temp['limit'] = params.limit;
temp['page'] = (params.offset / params.limit) + 1;
return temp;
},
sidePagination: "server",
pageNumber: 1,
pageSize: 10,
pageList: [10, 20, 50, 100],
columns: [{
checkbox: true, // 是否显示复选框
}, {
field: 'id',
title: '序号'
}, {
field: 'title',
title: '标题'
}, {
field: 'category_title',
title: '分类',
}, {
field: 'display',
title: '可见性',
formatter: function (value, row, index) {
if (value == 0) {
is_checked = '';
} else if (value == 1) {
is_checked = 'checked="checked"';
}
var field = "display";
result = '<label class="lyear-switch switch-primary switch-solid lyear-status"><input type="checkbox" ' + is_checked + '><span onClick="updateStatus(' + row.id + ', ' + value + ', \'' + field + '\')"></span></label>';
return result;
},
}, {
field: 'view',
title: '浏览量',
}, {
field: 'sort',
title: '排序',
editable: {
type: 'text',
emptytext: '',
highlight: false,
mode: 'inline'
}
}, {
field: 'create_time',
title: '创建时间',
}, {
field: 'create_time',
title: '更新时间',
}, {
field: 'operate',
title: '操作',
formatter: function (value, row, index) {
let html =
'<a type="button" class="btn-edit btn btn-xs btn-default m-r-5" href="/admin/page/edit?id=' + row.id + '" title="编辑" data-toggle="tooltip"><i class="mdi mdi-pencil"></i></a>\n' +
'<a class="btn btn-xs btn-default btn-del" href="#!" title="删除" data-toggle="tooltip" onclick="delOne(' + row.id + ')"><i class="mdi mdi-window-close"></i></a>\n' +
'<a type="button" class="btn-edit btn btn-xs btn-default m-r-5" href="/admin/page/comment?id=' + row.id + '" title="查看评论" data-toggle="tooltip"><i class="mdi mdi-message-text"></i></a>\n';
return html;
},
events: {
'click .btn-edit': function (e, value, row, index) {
}
}
}],
onEditableSave: function (field, row) {
$.ajax({
type: "post",
url: "/admin/page/save",
data: row,
success: function (res) {
if (res.code == 200 || res.status == 200) {
parent.lightyear.notify('操作成功', 'success', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
} else {
parent.lightyear.notify(res.msg, 'danger', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
}
},
complete: function () {
}
});
},
onLoadSuccess: function (data) {
$("[data-toggle='tooltip']").tooltip();
}
});
//搜索
$("#search").click(function () {
let start_time = $('#start_time').val();
let end_time = $('#end_time').val();
if (start_time && end_time && start_time > end_time) {
alert('开始时间不能大于结束时间');
return false;
}
$("#tb_departments").bootstrapTable('refresh', {query: {page: 1}, pageNumber: 1});
});
function updateStatus(id, value, field) {
var newstate = (value == 1) ? 0 : 1; // 发送参数值跟当前参数值相反
$.ajax({
type: "post",
url: "/admin/page/field?id=" + id,
data: {field: field, value: newstate},
dataType: 'json',
success: function (res) {
if (res.status == 200) {
parent.lightyear.notify('修改成功', 'success', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
$(".tree-table").bootstrapTable('refresh');
} else parent.lightyear.notify('修改失败', 'danger', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
},
error: function () {
parent.lightyear.notify('修改失败', 'danger', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
}
});
}
function delOne(id) {
$.confirm({
title: '重要提醒!',
content: '删除后将不可恢复,请谨慎操作!',
backgroundDismiss: true,
buttons: {
ok: {
text: '确认',
btnClass: 'btn-danger',
action: function () {
$.post("/admin/admin_log/del", data = {id: id}, function (res) {
if (res.status == 200 || res.code == 200) lightyear.notify(res.msg, 'success', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
else lightyear.notify(res.msg, 'danger', 3000, 'mdi mdi-emoticon-neutral', 'top', 'center');
location.reload();
})
}
},
cancel: {
text: '取消',
btnClass: 'btn-primary'
}
}
});
}
function delSelect() {
var checkID = "";
var selectedItem = $('#tb_departments').bootstrapTable('getSelections');
if (selectedItem == "") return lightyear.notify("没有选中项", 'danger', 3000, 'mdi mdi-emoticon-neutral', 'top', 'center');
for (var i = 0; i < selectedItem.length; i++) {
checkID += selectedItem[i]['id'] + ",";
}
if (checkID == "") return lightyear.notify("没有选中项", 'danger', 3000, 'mdi mdi-emoticon-neutral', 'top', 'center');
$.confirm({
title: '重要提醒!',
content: '选中项删除后将不可恢复,请谨慎操作!',
backgroundDismiss: true,
buttons: {
ok: {
text: '确认',
btnClass: 'btn-danger',
action: function () {
$.post("/admin/admin_log/del", data = {id: checkID}, function (res) {
if (res.status == 200 || res.code == 200) {
lightyear.notify(res.msg, 'success', 3000, 'mdi mdi-emoticon-happy', 'top', 'center');
location.reload();
} else lightyear.notify(res.msg, 'danger', 3000, 'mdi mdi-emoticon-neutral', 'top', 'center');
})
}
},
cancel: {
text: '取消',
btnClass: 'btn-primary'
}
}
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,100 @@
<?php
namespace app\index\controller;
use app\admin\controller\AuthController;
use app\admin\extend\Util as Util;
use app\common\constant\Data;
use app\common\model\FriendLink as friendLinkModel;
use app\common\model\MessageForm as MessageFormModel;
use app\common\model\Tag as TagModel;
use app\common\validate\MessageForm as MessageformValidate;
use app\Request;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
/**
* 应用入口
* Class Index
* @package app\index\controller
*/
class Index extends AuthController
{
/**
* 入口跳转链接
*/
public function index()
{
//判断后台统计配置是否开启 1 开启
if (web_config("web_statistics") == 1) {
//统计url
$this->urlrecord('网站首页');
}
//清除可能存在的栏目分类树id
cache(Data::CURR_CATEGORY_PATENT_ID, false);
//模板兼容性标签
$this->assign('id', false);
$this->assign('cid', false);
return $this->fetch();
}
/**
* 留言页面
* @param Request $request
* @return string
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @author 李玉坤
* @date 2021-10-17 1:03
*/
public function msg(Request $request)
{
if (request()->isPost()) {
$data = Util::postMore([
['author', ''],
['tel', ''],
['email', ''],
['content', ''],
]);
$data['create_time'] = time();
$messageFormValidate = new MessageFormValidate();
if (!$messageFormValidate->check($data)) {
$this->error($messageFormValidate->getError());
}
$res = MessageFormModel::create($data);
if ($res) {
$this->success('留言成功');
} else {
$this->error('留言失败');
}
} else {
//清除可能存在的栏目分类树id
cache(Data::CURR_CATEGORY_PATENT_ID, false);
//模板兼容性标签
$this->assign('id', false);
$this->assign('cid', false);
return $this->fetch();
}
}
/**
* 标签列表
* @return mixed
* @author 李玉坤
* @date 2021-11-11 0:27
*/
public function tagList()
{
$where = Util::postMore([
['name', ''],
['document_id', ''],
['start_time', ''],
['end_time', ''],
['page', 1],
['limit', 10]
]);
return app("json")->layui(TagModel::getList($where));
}
}

View File

@ -11,6 +11,7 @@ class Data
{
//缓存数据key
const DATA_FRIEND_LINK = 'data_friend_link'; //友链
const DATA_NAV_LIST = 'data_nav_list'; //页面导肮
const DATA_DOCUMENT_CATEGORY_LIST = 'data_document_category_list'; //文章分类
const CURR_CATEGORY_PATENT_ID = 'curr_category_patent_id'; //当前分类父级id
const DATA_SYSTEM_CONFIG = 'data_system_config'; //系统配置

195
app/common/model/Nav.php Normal file
View File

@ -0,0 +1,195 @@
<?php
namespace app\common\model;
use FormBuilder\Factory\Elm;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
/**
* Class Document
* @package app\admin\model\system
* @author 李玉坤
* @date 2021-02-15 23:22
*/
class Nav extends BaseModel
{
/**
* 权限列表
* @param $where
* @return array
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public static function systemPage($where): array
{
$model = new self;
if (isset($where['status']) && $where['status'] != '') $model = $model->where("status", $where['status']);
if (isset($where['title']) && $where['title'] != '') $model = $model->where("name|id", "like", "%$where[name]%");
$model = $model->field(['id', 'title', 'icon', 'pid', 'params', 'url', 'sort', 'status']);
$model = $model->order(["sort desc", "id"]);
$data = $model->select();
return $data->toArray() ?: [];
}
/**
* 获取选择数据
* @param int $pid
* @param array $auth
* @return array
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public static function lst(int $pid = 0, array $auth = []): array
{
$model = new self;
$model = $model->where("pid", $pid);
if ($auth != []) $model = $model->where("id", 'in', $auth);
$model = $model->field(['title', 'id']);
$model = $model->order(["sort desc", "id"]);
$data = $model->select()->each(function ($item) use ($auth) {
$item['children'] = self::lst($item['id'], $auth);
});
return $data->toArray() ?: [];
}
/**
* 获取菜单列表缓存key
* @param $adminId
* @return string
* @author 李玉坤
* @date 2021-06-09 17:24
*/
public static function getMenuCacheKey($adminId)
{
return 'menu:List:' . $adminId;
}
/**
* @return string
* @author 李玉坤
* @date 2021-06-15 11:11
*/
public static function getAuthCacheKey()
{
return 'auth:key:list';
}
public static function clearCache($adminId)
{
cache(AdminAuth::getMenuCacheKey($adminId), null);
cache(AdminAuth::getAuthCacheKey(), null);
}
/**
* 遍历选择项
* @param array $data
* @param $list
* @param int $num
* @param bool $clear
*/
public static function myOptions(array $data, &$list, $num = 0, $clear = true)
{
foreach ($data as $k => $v) {
$list[] = ['value' => $v['id'], 'label' => self::cross($num) . $v['title']];
if (is_array($v['children']) && !empty($v['children'])) {
self::myOptions($v['children'], $list, $num + 1, false);
}
}
}
/**
* 返回选择项
* @return array
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public static function returnOptions(): array
{
$list = [];
$list[] = ['value' => 0, 'label' => '总后台'];
self::myOptions(self::lst(), $list, 1, true);
return $list;
}
/**
* 横线
* @param int $num
* @return string
*/
public static function cross(int $num = 0): string
{
$str = "";
if ($num == 1) $str .= "|--";
elseif ($num > 1) for ($i = 0; $i < $num; $i++)
if ($i == 0) $str .= "|--";
else $str .= "--";
return $str . " ";
}
/**
* 生成treeData
* @param int $pid
* @param array $auth
* @param array $list
* @return array
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public static function selectAndBuildTree(int $pid = 0, array $auth = [], array $list = [])
{
$model = new self;
$model = $model->where("pid", $pid);
if ($auth != []) $model = $model->where("id", 'in', $auth);
$model = $model->where("status", 1);
$model = $model->field(['title', 'id']);
$model = $model->order(["sort desc", "id"]);
$data = $model->select();
foreach ($data as $k => $v) {
$list[] = self::buildTreeData($v['id'], $v['title'], self::selectAndBuildTree($v['id'], $auth));
}
return $list;
}
/**
* 获取所有权限id
* @param array $ids
* @return array
*/
public static function getIds(array $ids = []): array
{
if (empty($ids)) return self::where("status", 1)->column("id");
$pids = self::where("id", "in", $ids)->column("pid");
return array_merge($ids, $pids) ?: [];
}
/**
* 获取操作名
* @param string $module
* @param string $controller
* @param string $action
* @return string
*/
public static function getNameByAction(string $module, string $controller, string $action)
{
return self::where("module", $module)->where("controller", $controller)->where("action", $action)->value("title") ?: '未知操作';
}
/**
* 生成单个节点
* @param $id
* @param $title
* @return array
*/
public static function buildTreeData($id, $title, $children = []): array
{
$tree = Elm::TreeData($id, $title);
if (!empty($children)) $tree = $tree->children($children);
return $tree->getOption();
}
}

View File

@ -24,8 +24,42 @@ class Ape extends TagLib
'relevant' => ['attr' => 'id,model,void,row', 'close' => 1],
'tags' => ['attr' => 'tags,void', 'close' => 1],
'archive' => ['attr' => 'type,format,void', 'close' => 1],
'nav' => ['attr' => 'type,typeId,row,void,where,orderBy,display', 'close' => 1],
];
/**
* 导航列表
* type,栏目分类数据读取分类
* typeId,导航列表分类,数字,字符串,或者变量
*/
public function tagNav($tag, $content)
{
$type = isset($tag['type']) ? $tag['type'] : 'son';
$typeId = isset($tag['typeId']) ? $tag['typeId'] : '$cid';
$row = isset($tag['row']) ? $tag['row'] : 100;
$void = isset($tag['void']) ? $tag['void'] : 'field';
$where = isset($tag['where']) ? $tag['where'] : '';
$orderBy = isset($tag['orderBy']) ? $tag['orderBy'] : 'sort asc';
$display = isset($tag['display']) ? $tag['display'] : 1;
$display = $display == 1 ? 1 : 0;
//3中传参类型
//1、栏目id数字类型
//2、多个栏目id逗号隔开
//3、变量
//只有当多个栏目id时才需要单引号加持。保证生成的为字符串
if (strpos($typeId, ',')) {
$typeId = "'$typeId'";
}
$parse = '<?php ';
$parse .= '$__LIST__ = ' . "tpl_get_nav(\"$type\",$typeId,$row,\"$where\",\"$orderBy\",$display);";
$parse .= ' ?>';
$parse .= '{volist name="__LIST__" id="' . $void . '"}';
$parse .= $content;
$parse .= '{/volist}';
return $parse;
}
/**
* 栏目列表

View File

@ -7,6 +7,7 @@ use app\common\model\DocumentCategory;
use app\common\model\DocumentCategoryContent;
use app\common\model\FriendLink;
use app\common\model\Tag;
use app\common\model\Nav;
use think\App;
use think\Collection;
use think\db\exception\DataNotFoundException;
@ -14,6 +15,7 @@ use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use think\facade\Db;
use think\facade\Route as Url;
// 应用公共文件
/**
@ -63,7 +65,7 @@ function get_document_category_list()
$documentCategoryList = DocumentCategory::where('status', 1)->order('sort asc')->select()->toArray();
//转换让id作为数组的键
$documentCategory = [];
foreach ($documentCategoryList as $key => $item) {
foreach ($documentCategoryList as $item) {
//根据栏目类型生成栏目url
$item['url'] = make_category_url($item);
$documentCategory[$item['id']] = $item;
@ -73,7 +75,6 @@ function get_document_category_list()
return $documentCategory;
}
/**
* 获取一个文章分类
*/
@ -90,6 +91,7 @@ function get_document_category($x, $field = false)
if ($field) {
return $documentCategoryList[$x][$field];
} else {
$documentCategoryList[$x]['child'] = implode(",",array_column(getSubs($documentCategoryList,$x),"id"));
return $documentCategoryList[$x];
}
}
@ -262,6 +264,21 @@ function get_document_category_by_parent($pid, $row)
return $tempArr;
}
/*
* 获取所有子集元素
*/
function getSubs($categorys,$catId=0,$level=1){
$subs=array();
foreach($categorys as $item){
if($item['pid']==$catId){
$item['level']=$level;
$subs[]=$item;
$subs=array_merge($subs,getSubs($categorys,$item['id'],$level+1));
}
}
return $subs;
}
function get_document_category_all()
{
$documentCategoryList = get_document_category_list();
@ -1025,3 +1042,199 @@ function comment_face($incoming_comment,$path)
}
return $incoming_comment;
}
/**
* 模板-获取导航
* @param $type
* @param $typeId
* @param int $row
* @param string $where
* @param string $orderby
* @return DocumentCategory[]|array|bool|Collection
* @throws Exception
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @author 李玉坤
* @date 2021-11-12 21:48
*/
function tpl_get_nav($type, $typeId, $row = 100, $where = '', $orderby = '')
{
switch ($type) {
case "all":
//获取顶级导航
return get_nav_all();
break;
case 'top':
//获取顶级导航
return get_nav_by_parent(0, $row);
break;
case 'son':
//获取子级导航
if (!$typeId) {
throw new Exception('请指定要获取的栏目导航id');
}
return get_nav_by_parent($typeId, $row);
break;
case 'self':
//获取同级导航
if (!$typeId) {
throw new Exception('请指定要获取的栏目导航id');
}
$dc = get_nav($typeId);
if (!$dc) {
return false;
}
return get_nav_by_parent($dc['pid'], $row);
break;
case 'find':
//获取所有子孙导航,此操作读取数据库,非缓存!
if (!$typeId) {
throw new Exception('请指定要获取的栏目导航id');
}
$dc = get_nav($typeId);
if (!$dc) {
throw new Exception('导航不存在或已删除!');
}
$tempArr = Nav::where('id', 'in', $dc['child'])->where('status', 1)->limit($row);
$tempArr = $tempArr->select();
foreach ($tempArr as $key => $item) {
//根据栏目类型生成栏目url
$item['url'] = make_category_url($item);
$tempArr[$key] = $item;
}
return $tempArr;
break;
case 'parent':
//获取父级导航
if (!$typeId) {
throw new Exception('请指定要获取的栏目导航id');
}
$dc = get_nav($typeId);
$tempArr = array();
$parent = get_nav($dc['pid']);
array_push($tempArr, $parent);
return $tempArr;
break;
case 'root':
if (!$typeId) {
throw new Exception('请指定要获取的栏目导航id');
}
$dc = get_nav($typeId);
if ($dc['pid'] != 0) {
//获取根导航,此操作读取数据库,非缓存!
$dc = Nav::where('pid', 0)->where('status', 1)
->where("CONCAT(',',child,',') like '%,$typeId,%'")->limit($row);
$dc = $dc->find();
}
//根据栏目类型生成栏目url
$dc['url'] = make_category_url($dc);
$tempArr = [];
array_push($tempArr, $dc);
return $tempArr;
break;
case 'where':
//根据自定义条件获取导航where语句此操作读取数据库非缓存
$tempArr = Nav::where('status', 1)->where($where)->order($orderby)->limit($row);
$tempArr = $tempArr->select();
foreach ($tempArr as $key => $item) {
//根据栏目类型生成栏目url
$item['url'] = make_category_url($item);
$tempArr[$key] = $item;
}
return $tempArr;
break;
case 'ids':
//根据多个栏目id逗号隔开的那种获得栏目列表
$tempArr = Nav::where('status', 1)->where('id', 'in', $typeId)->order($orderby)->limit($row);
$tempArr = $tempArr->select();
foreach ($tempArr as $key => $item) {
//根据栏目类型生成栏目url
$item['url'] = make_category_url($item);
$tempArr[$key] = $item;
}
return $tempArr;
break;
default:
$tempArr = [];
return $tempArr;
break;
}
}
/**
* 获取一个文章导航
*/
function get_nav($x, $field = false)
{
if (!$x) {
throw new Exception('请指定要获取的栏目导航id');
}
//获取缓存的文章菜单
$list = get_nav_list();
if (!isset($list[$x])) {
return false;
}
if ($field) {
return $list[$x][$field];
} else {
return $list[$x];
}
}
/**
* 获取导航列表
*/
function get_nav_list()
{
//缓存文章菜单
$navList = cache(Data::DATA_NAV_LIST);
if ($navList === null) {
$list = Nav::where('status', 1)->order('sort asc')->select()->toArray();
//转换让id作为数组的键
$navList = [];
foreach ($list as $item) {
$navList[$item['id']] = $item;
}
cache(Data::DATA_NAV_LIST, $navList);
}
return $navList;
}
function get_nav_all()
{
$list = get_nav_list();
$tempArr = array();
foreach ($list as $item) {
if ($item['pid'] == 0) {
$tempArr[$item['id']] = $item;
} else {
$tempArr[$item['pid']]['child'][] = $item;
}
}
return $tempArr;
}
/**
* 根据父级导航id获取子导航
* $pid=父级id
* $row=获取多少数目
*/
function get_nav_by_parent($pid, $row)
{
$list = get_nav_list();
$x = 1;
$tempArr = array();
foreach ($list as $item) {
if ($x > $row) {
break;
}
if ($item['pid'] == $pid) {
$x = $x + 1;
array_push($tempArr, $item);
}
}
return $tempArr;
}

View File

@ -18,7 +18,7 @@ use think\facade\Log;
/**
* 应用入口
* Class Index
* Class Article
* @package app\index\controller
*/
class Article extends Base
@ -249,25 +249,6 @@ class Article extends Base
return $this->fetch();
}
/**
* 标签列表
* @return mixed
* @author 李玉坤
* @date 2021-11-11 0:27
*/
public function tagList()
{
$where = Util::postMore([
['name', ''],
['document_id', ''],
['start_time', ''],
['end_time', ''],
['page', 1],
['limit', 10]
]);
return app("json")->layui(TagModel::getList($where));
}
/**
* 搜索页面
* @return string

View File

@ -4,6 +4,7 @@ namespace app\index\controller;
use app\admin\extend\Util as Util;
use app\common\constant\Data;
use app\common\model\Document;
use app\common\model\FriendLink as friendLinkModel;
use app\common\model\MessageForm as MessageFormModel;
use app\common\validate\MessageForm as MessageformValidate;
@ -11,6 +12,7 @@ use app\Request;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Log;
/**
* 应用入口
@ -83,7 +85,7 @@ class Index extends Base
}
/**
* 留言
* 留言页面
* @param Request $request
* @return string
* @throws DataNotFoundException
@ -121,4 +123,64 @@ class Index extends Base
return $this->fetch();
}
}
/**
* 关于页面
* @param Request $request
* @author 李玉坤
* @date 2022-06-21 23:48
*/
public function about(Request $request)
{
$id = "about";
//获取该文章
$documentModel = new Document();
$article = $documentModel->where('status', 1)->where('id|alias', $id)->find();
if (!$article) {
$this->error('文章不存在或已删除!');
}
$article = $article->toArray();
//根据分类id找分类信息
$dc = get_document_category($article['category_id']);
if (!$dc) {
$this->error('栏目不存在或已删除!');
}
//获取该文章内容
//根据文章类型,加载不同的内容。
$articleType = $article['type'] ? $article['type'] : 'article';
$articleExt = $documentModel::name('document_' . $articleType)->where('id', $article['id'])->find();
if (!$articleExt) {
$this->error('文章不存在或已删除!');
}
$articleExt = $articleExt->toArray();
$article = array_merge($article, $articleExt);
//添加当前页面的位置信息
$article['position'] = tpl_get_position($dc);
//更新浏览次数
$documentModel->where('id', $article['id'])->inc('view')->update();
$templateFile = config('view.view_path') . 'article/' . $articleType . '.html';
if (!is_file($templateFile)) {
$this->error('模板文件不存在!');
}
$article['category_title'] = $dc['title'];
//判断SEO 为空则取系统
$article['keywords'] = $article['keywords'] ?: web_config('keywords');
$article['description'] = $article['description'] ?: web_config('description');
//输出文章内容
$this->assign('apeField', $article);
$this->assign('id', $id);
//当前页面所属分类id
$this->assign('cid', $article['category_id']);
//缓存当前页面栏目分类树ids
cache(Data::CURR_CATEGORY_PATENT_ID, $dc['pid'] ? $dc['pid'] . ',' . $article['category_id'] : $article['category_id']);
//设置文章的url
$article['link_str'] = make_detail_url($article);
//判断后台统计配置是否开启 1 开启
if (web_config("web_statistics") == 1) {
//统计url
$this->urlrecord($article['title']);
}
Log::info('详情页模板路径:' . $templateFile);
return $this->fetch('article/' . $articleType);
}
}

View File

@ -0,0 +1,345 @@
<?php
namespace app\index\controller;
use app\admin\extend\Util as Util;
use app\common\constant\Data;
use app\common\model\Comment as commentModel;
use app\common\model\Document;
use app\common\model\DocumentCategory;
use app\common\model\DocumentCategoryContent;
use app\common\model\Tag as TagModel;
use app\Request;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use think\facade\Log;
/**
* 应用入口
* Class Page
* @package app\index\controller
*/
class Page extends Base
{
/**
* 列表页
* @return string
* @throws Exception
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @author 李玉坤
* @date 2021-10-29 0:17
*/
public function lists()
{
$dc = false;
//栏目分类id
$id = input('id/d');
//栏目分类标识
$name = input('name');
if ($id) {
//获取分类信息
$dc = get_document_category($id);
} elseif ($name) {
//接收name字段,当name不为空的时候通过name查询分类一般name会用于伪静态
$dc = get_document_category_by_name($name);
}
if (!$dc) {
$this->error('栏目不存在或已删除!');
}
//赋值分类id可能是通过栏目分类id获取的栏目分类数据
$id = $dc['id'];
$documentCategoryModel = new DocumentCategory();
//栏目存在 增加访问量
$documentCategoryModel->where('id|alias', $id)->inc('view')->update();
//判断后台统计配置是否开启 1 开启
if (web_config("web_statistics") == 1) {
//统计url
$this->urlrecord($dc['title']);
}
//读取列表页模板
if ($dc['type'] == 0) {
if (empty($dc['template'])) {
$this->error('请在栏目分类中,指定当前栏目的列表模板!');
}
} elseif ($dc['type'] == 1) {
if (empty($dc['template'])) {
$this->error('请在栏目分类中,指定当前栏目的单篇模板!');
}
//如果是单篇栏目,加载内容
$contentModel = new DocumentCategoryContent();
$dcContent = $contentModel->find($id);
$dc['content'] = $dcContent['content'];
}
$listTmp = $dc['template'];
if (!is_file(config('view.view_path') . 'category/' . $listTmp)) {
$this->error('模板文件不存在!');
}
Log::info('列表页模板路径:' . config('view.view_path') . 'category/' . $listTmp);
//文章兼容字段
$dc['category_id'] = $dc['id'];
//判断seo标题是否存在
$dc['meta_title'] = $dc['meta_title'] ? $dc['meta_title'] : $dc['title'];
//判断SEO 为空则取系统
$article['keywords'] = $dc['keywords'] ?: web_config('keywords');
$article['description'] = $dc['description'] ?: web_config('description');
//添加当前页面的位置信息
$dc['position'] = tpl_get_position($dc);
//输出文章分类
$this->assign('apeField', $dc);
$this->assign('id', $id);
//当前页面所属分类id
$this->assign('cid', $id);
//缓存当前页面栏目分类树ids
cache(Data::CURR_CATEGORY_PATENT_ID, $dc['pid'] ? $dc['pid'] . ',' . $id : $id);
//去除后缀
$listTmp = substr($listTmp, 0, strpos($listTmp, '.'));
return $this->fetch('category/' . $listTmp);
}
/**
* 详情页
* @return string
* @throws Exception
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @author 李玉坤
* @date 2021-10-29 0:17
*/
public function detail()
{
$id = input('id');
if (!$id) {
$this->error('参数错误!');
}
//获取该文章
$documentModel = new Document();
$article = $documentModel->where('status', 1)->where('id|alias', $id)->find();
if (!$article) {
$this->error('文章不存在或已删除!');
}
$article = $article->toArray();
//根据分类id找分类信息
$dc = get_document_category($article['category_id']);
if (!$dc) {
$this->error('栏目不存在或已删除!');
}
//获取该文章内容
//根据文章类型,加载不同的内容。
$articleType = $article['type'] ? $article['type'] : 'article';
$articleExt = $documentModel::name('document_' . $articleType)->where('id', $article['id'])->find();
if (!$articleExt) {
$this->error('文章不存在或已删除!');
}
$articleExt = $articleExt->toArray();
$article = array_merge($article, $articleExt);
//添加当前页面的位置信息
$article['position'] = tpl_get_position($dc);
//更新浏览次数
$documentModel->where('id', $article['id'])->inc('view')->update();
$templateFile = config('view.view_path') . 'article/' . $articleType . '.html';
if (!is_file($templateFile)) {
$this->error('模板文件不存在!');
}
$article['category_title'] = $dc['title'];
//判断SEO 为空则取系统
$article['keywords'] = $article['keywords'] ?: web_config('keywords');
$article['description'] = $article['description'] ?: web_config('description');
//输出文章内容
$this->assign('apeField', $article);
$this->assign('id', $id);
//当前页面所属分类id
$this->assign('cid', $article['category_id']);
//缓存当前页面栏目分类树ids
cache(Data::CURR_CATEGORY_PATENT_ID, $dc['pid'] ? $dc['pid'] . ',' . $article['category_id'] : $article['category_id']);
//设置文章的url
$article['link_str'] = make_detail_url($article);
//判断后台统计配置是否开启 1 开启
if (web_config("web_statistics") == 1) {
//统计url
$this->urlrecord($article['title']);
}
Log::info('详情页模板路径:' . $templateFile);
return $this->fetch('article/' . $articleType);
}
/**
* 创建评论
* @param Request $request
* @return mixed
* @author 李玉坤
* @date 2021-10-17 19:13
*/
public function create_comment(Request $request)
{
$data = Util::postMore([
['document_id', ''],
['pid', ''],
['author', ''],
['url', ''],
['email', ''],
['content', ''],
]);
if (!web_config('comment_close')){
$this->error('非法操作,请检查后重试', null);
}
if (web_config('comment_visitor')){
if ($data['author'] == "") $this->error("昵称不能为空");
if ($data['email'] == "") $this->error("邮箱不能为空");
if ($data['url'] == "") $this->error("url不能为空");
}else{
$data['author'] = $this->userInfo['nickname']?:$this->userInfo['username'];
$data['email'] = $this->userInfo['email']?:'';
$data['url'] = '';
}
if ($data['document_id'] == "") $this->error("文章id不能为空");
if ($data['content'] == "") $this->error("内容能为空");
$data['status'] = web_config('comment_review') ? 0 : 1;
$res = commentModel::create($data);
if ($res) {
cookie(Data::COOKIE_KEY_COMMENT_AUTHOR,$data['author'],Data::COOKIE_KEY_COMMENT_EXPIRE);
cookie(Data::COOKIE_KEY_COMMENT_AUTHOR_EMAIL,$data['email'],Data::COOKIE_KEY_COMMENT_EXPIRE);
cookie(Data::COOKIE_KEY_COMMENT_AUTHOR_URL,$data['url'],Data::COOKIE_KEY_COMMENT_EXPIRE);
$this->success('提交成功', url('detail', ['id' => $data['document_id']]));
} else {
$this->error('提交失败,请联系站长查看', null);
}
}
/**
* 文章标签页面
* @return string
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @author 李玉坤
* @date 2021-10-29 0:19
*/
public function tag()
{
$tag = input('t');
if (!trim($tag)) {
$this->error('请输入标签');
}
if (!mb_check_encoding($tag, 'utf-8')) {
$tag = iconv('gbk', 'utf-8', $tag);
}
$apeField['id'] = '0';
$apeField['title'] = $tag;
$apeField['meta_title'] = $tag;
$apeField['keywords'] = web_config('keywords');
$apeField['description'] = web_config('description');
$apeField['position'] = '<a href="/">首页</a> > <a>' . $tag . '</a>';
$this->assign('apeField', $apeField);
$this->assign('tag', $tag);
//清除可能存在的栏目分类树id
cache(Data::CURR_CATEGORY_PATENT_ID, false);
//模板兼容性标签
$this->assign('id', false);
$this->assign('cid', false);
$templateFile = config('view.view_path') . 'article/tag.html';
if (!is_file($templateFile)) {
$this->error('模板文件不存在!');
}
return $this->fetch();
}
/**
* 标签列表
* @return mixed
* @author 李玉坤
* @date 2021-11-11 0:27
*/
public function tagList()
{
$where = Util::postMore([
['name', ''],
['document_id', ''],
['start_time', ''],
['end_time', ''],
['page', 1],
['limit', 10]
]);
return app("json")->layui(TagModel::getList($where));
}
/**
* 搜索页面
* @return string
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @author 李玉坤
* @date 2021-10-29 0:18
*/
public function search()
{
$kw = input('kw');
if (!trim($kw)) {
$this->error('请输入搜索关键词');
}
if (!mb_check_encoding($kw, 'utf-8')) {
$kw = iconv('gbk', 'utf-8', $kw);
}
$apeField['id'] = '0';
$apeField['title'] = '搜索';
$apeField['meta_title'] = '搜索';
$apeField['keywords'] = web_config('keywords');
$apeField['description'] = web_config('description');
$apeField['position'] = '<a href="/">首页</a> > <a>搜索</a>';
$this->assign('apeField', $apeField);
$this->assign('kw', $kw);
//清除可能存在的栏目分类树id
cache(Data::CURR_CATEGORY_PATENT_ID, false);
//模板兼容性标签
$this->assign('id', false);
$this->assign('cid', false);
$templateFile = config('view.view_path') . 'article/search.html';
if (!is_file($templateFile)) {
$this->error('模板文件不存在!');
}
return $this->fetch();
}
/**
* 用户首页
* @return string
* @throws Exception
* @author 李玉坤
* @date 2022-01-24 1:23
*/
public function user()
{
$author = input('author');
if (!trim($author)) {
$this->error('请输入搜索关键词');
}
if (!mb_check_encoding($author, 'utf-8')) {
$kw = iconv('gbk', 'utf-8', $author);
}
$apeField['id'] = '0';
$apeField['title'] = $author;
$apeField['meta_title'] = $author;
$apeField['keywords'] = web_config('keywords');
$apeField['description'] = web_config('description');
$apeField['position'] = '<a href="/">首页</a> > <a>' . $author . '</a>';
$this->assign('apeField', $apeField);
$this->assign('author', $author);
//清除可能存在的栏目分类树id
cache(Data::CURR_CATEGORY_PATENT_ID, false);
//模板兼容性标签
$this->assign('id', false);
$this->assign('cid', false);
$templateFile = config('view.view_path') . 'article/user.html';
if (!is_file($templateFile)) {
$this->error('模板文件不存在!');
}
return $this->fetch();
}
}

View File

@ -7,11 +7,7 @@ return [
'disks' => [
'local' => [
'type' => 'local',
'root' => app()->getRootPath() . 'public/upload',
// 磁盘路径对应的外部URL路径
'url' => '/upload',
// 可见性
'visibility' => 'public',
'root' => app()->getRuntimePath() . 'storage',
],
'public' => [
// 磁盘类型

View File

@ -0,0 +1,327 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<title>{$apeField['title']} - {:web_config('title')}</title>
<meta name="keywords" content="{$apeField['keywords']}" />
<meta name="description" content="{$apeField['description']}"/>
{include file="public/head" /}
<style>
.post-content-post img {
border-radius: 10px;
}
</style>
<style>
post-content-content img {
box-shadow: 0 0 5px 0 rgba(0, 0, 0, .1);
}
</style>
<link rel="stylesheet" href="__CSS__/comment-module.css">
<link rel="stylesheet" href="__CSS__/post-content.css">
<link rel="stylesheet" href="__LIB__/fancybox/jquery.fancybox.min.css">
<link rel="stylesheet" href="__LIB__/highlight/style/corepress-dark.css">
</head>
<body>
<script>NProgress.start();</script>
<div id="app">
{include file="public/header" /}
<div class="top-divider"></div>
<main class="container">
<div class="html-main">
<div class="post-main">
<div class="post-content-body">
<div class="crumbs-plane-body">
<div class="crumbs-plane">
<span class="corepress-crumbs-ul">{$apeField['position']|raw}</span>
</div>
</div>
<div class="post-content">
<h1 class="post-title">{$apeField['title']}</h1>
<div class="post-info">
<div class="post-info-left">
<a class="nickname url fn j-user-card" data-user="1"
href="{:url('article/user')}?author={$apeField['author']}"><i class="fa fa-user" aria-hidden="true"></i>{$apeField['author']}
</a>
<span class="dot"></span>
<time class="entry-date published" datetime="{$apeField['create_time']}" pubdate=""><i
class="far fa-clock"></i>
{$apeField['create_time']}
</time>
<span class="dot"></span><i class="fas fa-folder"></i>
<a href="{:url('article/lists')}?id={$apeField['category_id']}" rel="category tag"> {$apeField['category_title']}</a>
<span class="dot"></span>
<span><i class="fa fa-eye" aria-hidden="true"></i>{$apeField['view']} 阅读</span>
</div>
<div class="post-info-right">
<span title="关闭或显示侧边栏" class="post-info-switch-sidebar post-info-switch-sidebar-show"><i class="fas fa-toggle-on"></i></span>
</div>
</div>
<div class="post-content-post">
<div class="post-content-content">
{$apeField['content']|raw}
</div>
<div class="post-end-tools">
<div class="post-copyright">
<p>版权声明:
<br />作者:{$apeField['author']}
<br />链接:
<span>
<u>
<a href="{$Request.domain . $Request.url}" target="_blank">{$Request.domain . $Request.url}</a>
</u>
</span>
<br />来源:{:web_config('title')}
<br />文章版权归作者所有,未经允许请勿转载。</p>
</div>
<div class="post-end-dividing">THE END</div>
<div class="post-tags"></div>
<div class="post-end-tool-btns">
<div class="post-share-btn post-end-tool-btn-item" onclick="showplane('.post-share-btn','#share-plane',event)">
{:file_echo_svg('__IMG__/share-btn.svg')}分享</div>
<div class="post-qrcode-btn post-end-tool-btn-item" onclick="showplane('.post-qrcode-btn','#qrcode-plane',event)">
{:file_echo_svg('__IMG__/svg-ewm.svg')}二维码</div>
<div class="post-reward-btn post-end-tool-btn-item" onclick="showplane('.post-reward-btn','#reward-plane',event)">
{:file_echo_svg('__IMG__/reward.svg')}打赏</div>
<div id="share-plane" class="post-pop-plane">
<div class="post-share-list">
<a href="https://connect.qq.com/widget/shareqq/index.html?url={$Request.domain.$Request.url}&title={$apeField['title']}&source={:web_config('title')}&desc={:web_config('title')}-{$apeField['description']}&pics=&summary={$apeField['abstract']}" target="_blank">
{:file_echo_svg('__IMG__/share-qq.svg')}
</a>
<a href="http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url={$Request.domain.$Request.url}&title={$apeField['title']}&source={:web_config('title')}&desc={:web_config('title')}-{$apeField['description']}&pics=&summary={$apeField['abstract']}" target="_blank">
{:file_echo_svg('__IMG__/share-qzone.svg')}
</a>
<a href="https://service.weibo.com/share/share.php?url={$Request.domain.$Request.url}&title={$apeField['title']}&pic=&appkey=&searchPic=true" target="_blank">
{:file_echo_svg('__IMG__/share-weibo.svg')}
</a>
</div>
</div>
<div id="qrcode-plane" class="post-pop-plane">
<div id="qrcode-img"></div>
</div>
<div id="reward-plane" class="post-pop-plane">
{notempty name="(web_config('web_weixin_pay'))"}<img src="{:file_cdn(web_config('web_weixin_pay'))}" alt="{:web_config('web_weixin_pay')}" />{/notempty}
{notempty name="(web_config('web_zhifubao_pay'))"}<img src="{:file_cdn(web_config('web_zhifubao_pay'))}" alt="{:web_config('web_zhifubao_pay')}"/>{/notempty}
</div>
</div>
<div class="post-turn-page-plane">
<div class="post-turn-page post-turn-page-previous">
<div class="post-turn-page-main">
{ape:prenext get="pre" cid="$apeField['category_id']"}
<div>
<a href="{:url('/index/article/detail')}?id={$field['id']}">{$field['title']}</a>
</div>
<div class="post-turn-page-link-pre">
<a href="{:url('/index/article/detail')}?id={$field['id']}"><<上一篇></上一篇></a>
</div>
{/ape:prenext}
</div>
</div>
<div class="post-turn-page post-turn-page-next">
{ape:prenext get="next" cid="$apeField['category_id']"}
<div class="post-turn-page-main">
<a href="{:url('/index/article/detail')}?id={$field['id']}">{$field['title']}</a>
<div class="post-turn-page-link-next">
<a href="javascript:">下一篇>></a>
</div>
</div>
{/ape:prenext}
</div>
</div>
</div>
<div class="post-tool-plane"></div>
</div>
</div>
</div>
<div class="relevant-plane">
<div class="plane-title">相关内容</div>
<div>
<ul class="relevant-list">
{ape:relevant row="5" id="$apeField['id']"}
<li><a href="{$field['url']}">{$field['title']}</a></li>
{/ape:relevant}
</ul>
</div>
</div>
{if web_config('comment_close') ==1}
<div id="comments" class="responsesWrapper">
<div class="reply-title">发表评论</div>
<div id="respond" class="comment-respond">
<h3 id="reply-title" class="comment-reply-title">
<small>
<a rel="nofollow" id="cancel-comment-reply-link" href="{:url('/index/article/detail')}?id={$field['id']}#respond" style="display:none;">
取消回复
</a>
</small>
</h3>
<form action="{:url('/index/article/create_comment')}" method="post" id="form_comment" class="comment-form">
<div class="comment-user-plane">
<div class="logged-in-as">
<img class="comment-user-avatar" width="48" height="auto" src="__IMG__/avatar.png" alt="comment-user-avatar">
</div>
<div class="comment_form_textarea_box">
<textarea class="comment_form_textarea" name="content" id="comment"
placeholder="发表你的看法" rows="5"></textarea>
<div id="comment_addplane">
<button class="popover-btn popover-btn-face" type="button">
<i class="far fa-smile-wink">
</i>添加表情
</button>
<div class="conment-face-plane">
{:file_load_face('__IMG__/face/')}
</div>
</div>
</div>
</div>
{if web_config('comment_visitor') && empty($user_id)}
<div class="comment_userinput">
<div class="comment-form-author">
<input id="author" name="author" placeholder="昵称(*)" type="text" value="{$Request.cookie.comment_author}" size="30"
class="required"/>
</div>
<div class="comment-form-email">
<input id="email" name="email" type="text" placeholder="邮箱(*)" value="{$Request.cookie.comment_author_email}"
class="required"/>
</div>
<div class="comment-form-url">
<input id="url" placeholder="网址" name="url" type="text" value="{$Request.cookie.comment_author_url}" size="30"/>
</div>
<div style="display: none" class="comment-form-cookies-consent">
<input id="wp-comment-cookies-consent" name="wp-comment-cookies-consent"
type="checkbox" value="yes" checked="checked"/>记住用户信息
</div>
</div>
{/if}
<div class="form-submit">
<div style="text-align: right">
<input name="submit" type="submit" id="commit_submit" class="button primary-btn"
value="发表评论">
</div>
<input type="hidden" name="document_id" value="{$apeField['id']}"
id="comment_document_id">
<input type="hidden" name="pid" id="comment_parent" value="0">
</div>
</form>
</div>
<!-- #respond -->
<meta content="UserComments:0" itemprop="interactionCount">
<h3 class="comments-title">共有<span class="commentCount">{:get_comment_count($apeField['id'])}</span>条评论</h3>
<div class="comment-sofa">
{if get_comment_count($apeField['id']) ==0}
<i class="fas fa-couch"></i>沙发空余
{/if}
</div>
<ol class="commentlist">
{ape:comment type="top" typeId="$apeField['id']" void='field'}
<li class="comment">
<div class="comment-item" id="comment-{$field['id']}">
<div class="comment-media">
<div class="avatar-img">
<img src="{$field['cover_path']}" alt="avatar-im">
</div>
</div>
<div class="comment-metadata">
<div class="media-body">
<p class="author_name">{$field['author']}<a href="{$field['url']}" rel="external nofollow ugc" target="_blank" class="url"></a><span class="comment-zhan"><img title="网站主" src="__IMG__/zhan.svg" alt=""></span></p>
<div class="comment-text">
<p>{:comment_face($field['content'],'__IMG__/face/')}</p>
</div>
</div>
<span class="comment-pub-time">{$field['create_time']}</span>
<span class="comment-btn-reply">
<a rel="nofollow" class="comment-reply-link" href="{$field['reply_url']}" data-commentid="{$field['id']}" data-postid="{$apeField['id']}" data-belowelement="comment-{$field['id']}" data-respondelement="respond" data-replyto="回复给{$field['author']}" aria-label="回复给{$field['author']}"><i class="fa fa-reply"></i> 回复</a>
</span>
</div>
</div>
{ape:comment type="son" typeId="$field['id']" void="vo"}
<ol class="children">
<li class="comment">
<div class="comment-item" id="comment-{$vo.id}">
<div class="comment-media">
<div class="avatar-img">
<img src="{$field['cover_path']}" alt="">
</div>
</div>
<div class="comment-metadata">
<div class="media-body">
<p class="author_name">{$vo['author']}<span class="user-identity user-admin" title="{$vo['author']}"></span><span class="comment-from">@<a href="#comment-2264">{$field['author']}</a></span></p>
<div class="comment-text">
<p>{:comment_face($vo['content'],'__IMG__/face/')}</p>
</div>
</div>
<span class="comment-pub-time">{$vo.create_time}</span>
<span class="comment-btn-reply">
<a rel="nofollow" class="comment-reply-link" href="{$vo['reply_url']}" data-commentid="{$vo.id}" data-postid="{$apeField['id']}" data-belowelement="comment-{$vo.id}" data-respondelement="respond" data-replyto="回复给{$vo['author']}" aria-label="回复给{$vo['author']}"><i class="fa fa-reply"></i> 回复</a>
</span>
</div>
</div>
</li><!-- #comment-## -->
</ol><!-- .children -->
{/ape:comment}
</li><!-- #comment-## -->
{/ape:comment}
</ol>
<script type='text/javascript' src='__JS__/comment-reply.min.js'></script>
<script type='text/javascript'>
$('body').on('click', '.comment-reply-link', function (e) {
addComment.moveForm("li-comment-" + $(this).attr('data-commentid'), $(this).attr('data-commentid'), "respond", $(this).attr('data-postid'));
e.stopPropagation();
return false;
});
$(document).click(function (e) {
$('.conment-face-plane').css("opacity", "0");
$('.conment-face-plane').css("visibility", "hidden");
e.stopPropagation();
});
$('body').on('click', '.img-pace', function (e) {
$('.comment_form_textarea').val($('.comment_form_textarea').val() + '[f=' + $(this).attr('facename') + ']')
});
$('body').on('click', '.popover-btn-face', function (e) {
if ($('.conment-face-plane').css("visibility") == 'visible') {
$('.conment-face-plane').css("opacity", "0");
$('.conment-face-plane').css("visibility", "hidden");
} else {
$('.conment-face-plane').css("opacity", "1");
$('.conment-face-plane').css("visibility", "visible");
}
e.stopPropagation();
});
</script>
<nav class="comment-navigation pages"></nav>
</div>
{/if}
</div>
<div class="sidebar">
<div class="sidebar-box-list">
<div class="aside-box">
<h2 class="widget-title">热门文章</h2>
{ape:arclist row="8" orderBy="view desc" type="where"}
<div class="hot-post-widget-item">
<div>
<span class="hot-post-widget-item-num">{$i}</span>
<span class="hot-post-widget-item-title">
<a href="{$field['url']}">{:cn_substr($field['title'],15)}</a>
</span>
</div>
<div class="hot-post-widget-item-meta">
<div>{$field['create_time']}</div>
<div>
<a href="{:url('article/lists')}?id={$field['category_id']}">{:cn_substr($field['category_title'],5)}</a>
</div>
</div>
</div>
{/ape:arclist}
</div>
</div>
</div>
</div>
</main>
{include file="public/footer"/}
</div>
<script src="__LIB__/highlight/init.js"></script>
<script src="__JS__/post-content.js"></script>
<script src="__JS__/clipboard.min.js"></script>
<script src="__LIB__/fancybox/jquery.fancybox.min.js"></script>
<script src="__LIB__/fancybox/init.js"></script>
<script src="__LIB__/highlight/highlight.min.js"></script>
</body>
</html>

View File

@ -0,0 +1,327 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<title>{$apeField['title']} - {:web_config('title')}</title>
<meta name="keywords" content="{$apeField['keywords']}" />
<meta name="description" content="{$apeField['description']}"/>
{include file="public/head" /}
<style>
.post-content-post img {
border-radius: 10px;
}
</style>
<style>
post-content-content img {
box-shadow: 0 0 5px 0 rgba(0, 0, 0, .1);
}
</style>
<link rel="stylesheet" href="__CSS__/comment-module.css">
<link rel="stylesheet" href="__CSS__/post-content.css">
<link rel="stylesheet" href="__LIB__/fancybox/jquery.fancybox.min.css">
<link rel="stylesheet" href="__LIB__/highlight/style/corepress-dark.css">
</head>
<body>
<script>NProgress.start();</script>
<div id="app">
{include file="public/header" /}
<div class="top-divider"></div>
<main class="container">
<div class="html-main">
<div class="post-main">
<div class="post-content-body">
<div class="crumbs-plane-body">
<div class="crumbs-plane">
<span class="corepress-crumbs-ul">{$apeField['position']|raw}</span>
</div>
</div>
<div class="post-content">
<h1 class="post-title">{$apeField['title']}</h1>
<div class="post-info">
<div class="post-info-left">
<a class="nickname url fn j-user-card" data-user="1"
href="{:url('article/user')}?author={$apeField['author']}"><i class="fa fa-user" aria-hidden="true"></i>{$apeField['author']}
</a>
<span class="dot"></span>
<time class="entry-date published" datetime="{$apeField['create_time']}" pubdate=""><i
class="far fa-clock"></i>
{$apeField['create_time']}
</time>
<span class="dot"></span><i class="fas fa-folder"></i>
<a href="{:url('article/lists')}?id={$apeField['category_id']}" rel="category tag"> {$apeField['category_title']}</a>
<span class="dot"></span>
<span><i class="fa fa-eye" aria-hidden="true"></i>{$apeField['view']} 阅读</span>
</div>
<div class="post-info-right">
<span title="关闭或显示侧边栏" class="post-info-switch-sidebar post-info-switch-sidebar-show"><i class="fas fa-toggle-on"></i></span>
</div>
</div>
<div class="post-content-post">
<div class="post-content-content">
{$apeField['content']|raw}
</div>
<div class="post-end-tools">
<div class="post-copyright">
<p>版权声明:
<br />作者:{$apeField['author']}
<br />链接:
<span>
<u>
<a href="{$Request.domain . $Request.url}" target="_blank">{$Request.domain . $Request.url}</a>
</u>
</span>
<br />来源:{:web_config('title')}
<br />文章版权归作者所有,未经允许请勿转载。</p>
</div>
<div class="post-end-dividing">THE END</div>
<div class="post-tags"></div>
<div class="post-end-tool-btns">
<div class="post-share-btn post-end-tool-btn-item" onclick="showplane('.post-share-btn','#share-plane',event)">
{:file_echo_svg('__IMG__/share-btn.svg')}分享</div>
<div class="post-qrcode-btn post-end-tool-btn-item" onclick="showplane('.post-qrcode-btn','#qrcode-plane',event)">
{:file_echo_svg('__IMG__/svg-ewm.svg')}二维码</div>
<div class="post-reward-btn post-end-tool-btn-item" onclick="showplane('.post-reward-btn','#reward-plane',event)">
{:file_echo_svg('__IMG__/reward.svg')}打赏</div>
<div id="share-plane" class="post-pop-plane">
<div class="post-share-list">
<a href="https://connect.qq.com/widget/shareqq/index.html?url={$Request.domain.$Request.url}&title={$apeField['title']}&source={:web_config('title')}&desc={:web_config('title')}-{$apeField['description']}&pics=&summary={$apeField['abstract']}" target="_blank">
{:file_echo_svg('__IMG__/share-qq.svg')}
</a>
<a href="http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url={$Request.domain.$Request.url}&title={$apeField['title']}&source={:web_config('title')}&desc={:web_config('title')}-{$apeField['description']}&pics=&summary={$apeField['abstract']}" target="_blank">
{:file_echo_svg('__IMG__/share-qzone.svg')}
</a>
<a href="https://service.weibo.com/share/share.php?url={$Request.domain.$Request.url}&title={$apeField['title']}&pic=&appkey=&searchPic=true" target="_blank">
{:file_echo_svg('__IMG__/share-weibo.svg')}
</a>
</div>
</div>
<div id="qrcode-plane" class="post-pop-plane">
<div id="qrcode-img"></div>
</div>
<div id="reward-plane" class="post-pop-plane">
{notempty name="(web_config('web_weixin_pay'))"}<img src="{:file_cdn(web_config('web_weixin_pay'))}" alt="{:web_config('web_weixin_pay')}" />{/notempty}
{notempty name="(web_config('web_zhifubao_pay'))"}<img src="{:file_cdn(web_config('web_zhifubao_pay'))}" alt="{:web_config('web_zhifubao_pay')}"/>{/notempty}
</div>
</div>
<div class="post-turn-page-plane">
<div class="post-turn-page post-turn-page-previous">
<div class="post-turn-page-main">
{ape:prenext get="pre" cid="$apeField['category_id']"}
<div>
<a href="{:url('/index/article/detail')}?id={$field['id']}">{$field['title']}</a>
</div>
<div class="post-turn-page-link-pre">
<a href="{:url('/index/article/detail')}?id={$field['id']}"><<上一篇></上一篇></a>
</div>
{/ape:prenext}
</div>
</div>
<div class="post-turn-page post-turn-page-next">
{ape:prenext get="next" cid="$apeField['category_id']"}
<div class="post-turn-page-main">
<a href="{:url('/index/article/detail')}?id={$field['id']}">{$field['title']}</a>
<div class="post-turn-page-link-next">
<a href="javascript:">下一篇>></a>
</div>
</div>
{/ape:prenext}
</div>
</div>
</div>
<div class="post-tool-plane"></div>
</div>
</div>
</div>
<div class="relevant-plane">
<div class="plane-title">相关内容</div>
<div>
<ul class="relevant-list">
{ape:relevant row="5" id="$apeField['id']"}
<li><a href="{$field['url']}">{$field['title']}</a></li>
{/ape:relevant}
</ul>
</div>
</div>
{if web_config('comment_close') ==1}
<div id="comments" class="responsesWrapper">
<div class="reply-title">发表评论</div>
<div id="respond" class="comment-respond">
<h3 id="reply-title" class="comment-reply-title">
<small>
<a rel="nofollow" id="cancel-comment-reply-link" href="{:url('/index/article/detail')}?id={$field['id']}#respond" style="display:none;">
取消回复
</a>
</small>
</h3>
<form action="{:url('/index/article/create_comment')}" method="post" id="form_comment" class="comment-form">
<div class="comment-user-plane">
<div class="logged-in-as">
<img class="comment-user-avatar" width="48" height="auto" src="__IMG__/avatar.png" alt="comment-user-avatar">
</div>
<div class="comment_form_textarea_box">
<textarea class="comment_form_textarea" name="content" id="comment"
placeholder="发表你的看法" rows="5"></textarea>
<div id="comment_addplane">
<button class="popover-btn popover-btn-face" type="button">
<i class="far fa-smile-wink">
</i>添加表情
</button>
<div class="conment-face-plane">
{:file_load_face('__IMG__/face/')}
</div>
</div>
</div>
</div>
{if web_config('comment_visitor') && empty($user_id)}
<div class="comment_userinput">
<div class="comment-form-author">
<input id="author" name="author" placeholder="昵称(*)" type="text" value="{$Request.cookie.comment_author}" size="30"
class="required"/>
</div>
<div class="comment-form-email">
<input id="email" name="email" type="text" placeholder="邮箱(*)" value="{$Request.cookie.comment_author_email}"
class="required"/>
</div>
<div class="comment-form-url">
<input id="url" placeholder="网址" name="url" type="text" value="{$Request.cookie.comment_author_url}" size="30"/>
</div>
<div style="display: none" class="comment-form-cookies-consent">
<input id="wp-comment-cookies-consent" name="wp-comment-cookies-consent"
type="checkbox" value="yes" checked="checked"/>记住用户信息
</div>
</div>
{/if}
<div class="form-submit">
<div style="text-align: right">
<input name="submit" type="submit" id="commit_submit" class="button primary-btn"
value="发表评论">
</div>
<input type="hidden" name="document_id" value="{$apeField['id']}"
id="comment_document_id">
<input type="hidden" name="pid" id="comment_parent" value="0">
</div>
</form>
</div>
<!-- #respond -->
<meta content="UserComments:0" itemprop="interactionCount">
<h3 class="comments-title">共有<span class="commentCount">{:get_comment_count($apeField['id'])}</span>条评论</h3>
<div class="comment-sofa">
{if get_comment_count($apeField['id']) ==0}
<i class="fas fa-couch"></i>沙发空余
{/if}
</div>
<ol class="commentlist">
{ape:comment type="top" typeId="$apeField['id']" void='field'}
<li class="comment">
<div class="comment-item" id="comment-{$field['id']}">
<div class="comment-media">
<div class="avatar-img">
<img src="{$field['cover_path']}" alt="avatar-im">
</div>
</div>
<div class="comment-metadata">
<div class="media-body">
<p class="author_name">{$field['author']}<a href="{$field['url']}" rel="external nofollow ugc" target="_blank" class="url"></a><span class="comment-zhan"><img title="网站主" src="__IMG__/zhan.svg" alt=""></span></p>
<div class="comment-text">
<p>{:comment_face($field['content'],'__IMG__/face/')}</p>
</div>
</div>
<span class="comment-pub-time">{$field['create_time']}</span>
<span class="comment-btn-reply">
<a rel="nofollow" class="comment-reply-link" href="{$field['reply_url']}" data-commentid="{$field['id']}" data-postid="{$apeField['id']}" data-belowelement="comment-{$field['id']}" data-respondelement="respond" data-replyto="回复给{$field['author']}" aria-label="回复给{$field['author']}"><i class="fa fa-reply"></i> 回复</a>
</span>
</div>
</div>
{ape:comment type="son" typeId="$field['id']" void="vo"}
<ol class="children">
<li class="comment">
<div class="comment-item" id="comment-{$vo.id}">
<div class="comment-media">
<div class="avatar-img">
<img src="{$field['cover_path']}" alt="">
</div>
</div>
<div class="comment-metadata">
<div class="media-body">
<p class="author_name">{$vo['author']}<span class="user-identity user-admin" title="{$vo['author']}"></span><span class="comment-from">@<a href="#comment-2264">{$field['author']}</a></span></p>
<div class="comment-text">
<p>{:comment_face($vo['content'],'__IMG__/face/')}</p>
</div>
</div>
<span class="comment-pub-time">{$vo.create_time}</span>
<span class="comment-btn-reply">
<a rel="nofollow" class="comment-reply-link" href="{$vo['reply_url']}" data-commentid="{$vo.id}" data-postid="{$apeField['id']}" data-belowelement="comment-{$vo.id}" data-respondelement="respond" data-replyto="回复给{$vo['author']}" aria-label="回复给{$vo['author']}"><i class="fa fa-reply"></i> 回复</a>
</span>
</div>
</div>
</li><!-- #comment-## -->
</ol><!-- .children -->
{/ape:comment}
</li><!-- #comment-## -->
{/ape:comment}
</ol>
<script type='text/javascript' src='__JS__/comment-reply.min.js'></script>
<script type='text/javascript'>
$('body').on('click', '.comment-reply-link', function (e) {
addComment.moveForm("li-comment-" + $(this).attr('data-commentid'), $(this).attr('data-commentid'), "respond", $(this).attr('data-postid'));
e.stopPropagation();
return false;
});
$(document).click(function (e) {
$('.conment-face-plane').css("opacity", "0");
$('.conment-face-plane').css("visibility", "hidden");
e.stopPropagation();
});
$('body').on('click', '.img-pace', function (e) {
$('.comment_form_textarea').val($('.comment_form_textarea').val() + '[f=' + $(this).attr('facename') + ']')
});
$('body').on('click', '.popover-btn-face', function (e) {
if ($('.conment-face-plane').css("visibility") == 'visible') {
$('.conment-face-plane').css("opacity", "0");
$('.conment-face-plane').css("visibility", "hidden");
} else {
$('.conment-face-plane').css("opacity", "1");
$('.conment-face-plane').css("visibility", "visible");
}
e.stopPropagation();
});
</script>
<nav class="comment-navigation pages"></nav>
</div>
{/if}
</div>
<div class="sidebar">
<div class="sidebar-box-list">
<div class="aside-box">
<h2 class="widget-title">热门文章</h2>
{ape:arclist row="8" orderBy="view desc" type="where"}
<div class="hot-post-widget-item">
<div>
<span class="hot-post-widget-item-num">{$i}</span>
<span class="hot-post-widget-item-title">
<a href="{$field['url']}">{:cn_substr($field['title'],15)}</a>
</span>
</div>
<div class="hot-post-widget-item-meta">
<div>{$field['create_time']}</div>
<div>
<a href="{:url('article/lists')}?id={$field['category_id']}">{:cn_substr($field['category_title'],5)}</a>
</div>
</div>
</div>
{/ape:arclist}
</div>
</div>
</div>
</div>
</main>
{include file="public/footer"/}
</div>
<script src="__LIB__/highlight/init.js"></script>
<script src="__JS__/post-content.js"></script>
<script src="__JS__/clipboard.min.js"></script>
<script src="__LIB__/fancybox/jquery.fancybox.min.js"></script>
<script src="__LIB__/fancybox/init.js"></script>
<script src="__LIB__/highlight/highlight.min.js"></script>
</body>
</html>

View File

@ -25,7 +25,7 @@
<nav class="menu-footer-plane">
<ul id="menu-list-footer" class="menu-footer-list">
<li id="menu-item-306" class="menu-item menu-item-306">
<a href="{:url('/index/article/detail?id=1')}">关于本站</a>
<a href="{:url('/index/index/about')}">关于本站</a>
</li>
<li id="menu-item-307" class="menu-item menu-item-307">
<a href="{:url('/index/index/msg')}">留言建议</a>

View File

@ -43,8 +43,7 @@
<div class="drawer-menu-list">
<div class="menu-mobile">
<ul class="menu-mobile-header-list">
<li id="menu-item-0" class="menu-item menu-item-0"><a href="/" aria-current="page">首页</a></li>
{ape:channel type="all"}
{ape:nav type="all"}
<li id="menu-item-{$field.id}" class="menu-item {notempty name="field['child']"}menu-item-has-children{/notempty} {:is_active_nav($cid,$field['id'])?'current-menu-item current_page_item':''} menu-item-{$field['id']}">
{notempty name="field['child']"}
<a href="#" aria-current="page">{$field['title']}</a>
@ -53,15 +52,15 @@
{/notempty}
{notempty name="field['child']"}
<ul class="sub-menu">
{ape:channel type="son" typeId="$field['id']" void="vo"}
{ape:nav type="son" typeId="$field['id']" void="vo"}
<li id="menu-item-{$vo.id}" class="menu-item menu-item-{$vo.id} {:is_active_nav($cid,$vo['id'])?'current-menu-item':''}">
<a title="{$vo['title']}" aria-current="page" href="{$vo['url']}" {if $vo['link_str']} target="_blank"{/if}>{$vo['title']}</a>
<a title="{$vo['title']}" aria-current="page" href="{$vo['url']}" {if $vo['target']} target="_blank"{/if}>{$vo['title']}</a>
</li>
{/ape:channel}
{/ape:nav}
</ul>
{/notempty}
</li>
{/ape:channel}
{/ape:nav}
</ul>
</div>
</div>
@ -91,8 +90,7 @@
<div class="menu-plane">
<nav class="menu-header-plane">
<ul id="menu-header-list" class="menu-header-list">
<li class="menu-item menu-item-0"><a href="/">首页</a></li>
{ape:channel type="all"}
{ape:nav type="all"}
<li class="menu-item {notempty name="field['child']"}menu-item-has-children{/notempty} {:is_active_nav($cid,$field['id'])?'current-menu-item':''} menu-item-{$field['id']}">
{notempty name="field['child']"}
<a href="#" aria-current="page">{$field['title']}</a>
@ -101,15 +99,15 @@
{/notempty}
{notempty name="field['child']"}
<ul class="sub-menu">
{ape:channel type="son" typeId="$field['id']" void="vo"}
{ape:nav type="son" typeId="$field['id']" void="vo"}
<li id="menu-item-{$vo.id}" class="menu-item menu-item-{$vo.id} {:is_active_nav($cid,$vo['id'])?'current-menu-item':''}">
<a title="{$vo['title']}" href="{$vo['url']}" {if $vo['link_str']} target="_blank"{/if}>{$vo['title']}</a>
<a title="{$vo['title']}" href="{$vo['url']}" {if $vo["target"]} target="_blank"{/if}>{$vo['title']}</a>
</li>
{/ape:channel}
{/ape:nav}
</ul>
{/notempty}
</li>
{/ape:channel}
{/ape:nav}
</ul>
</nav>
</div>

View File

@ -7,9 +7,9 @@ $baseDir = dirname($vendorDir);
return array(
'9b552a3cc426e3287cc811caefa3cf53' => $vendorDir . '/topthink/think-helper/src/helper.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'35fab96057f1bf5e7aba31a8a6d5fdde' => $vendorDir . '/topthink/think-orm/stubs/load_stubs.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',

View File

@ -8,9 +8,9 @@ class ComposerStaticInit4b57298e8d0e895486f3307a354a7e1a
{
public static $files = array (
'9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'35fab96057f1bf5e7aba31a8a6d5fdde' => __DIR__ . '/..' . '/topthink/think-orm/stubs/load_stubs.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',

View File

@ -996,17 +996,17 @@
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.25.0",
"version_normalized": "1.25.0.0",
"version": "v1.26.0",
"version_normalized": "1.26.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825"
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825",
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"shasum": "",
"mirrors": [
{
@ -1024,11 +1024,11 @@
"suggest": {
"ext-mbstring": "For best performance"
},
"time": "2021-11-30T18:21:41+00:00",
"time": "2022-05-24T11:49:31+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1068,7 +1068,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
},
"funding": [
{
@ -1088,17 +1088,17 @@
},
{
"name": "symfony/polyfill-php72",
"version": "v1.25.0",
"version_normalized": "1.25.0.0",
"version": "v1.26.0",
"version_normalized": "1.26.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "9a142215a36a3888e30d0a9eeea9766764e96976"
"reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976",
"reference": "9a142215a36a3888e30d0a9eeea9766764e96976",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/bf44a9fd41feaac72b074de600314a93e2ae78e2",
"reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2",
"shasum": "",
"mirrors": [
{
@ -1110,11 +1110,11 @@
"require": {
"php": ">=7.1"
},
"time": "2021-05-27T09:17:38+00:00",
"time": "2022-05-24T11:49:31+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1153,7 +1153,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php72/tree/v1.25.0"
"source": "https://github.com/symfony/polyfill-php72/tree/v1.26.0"
},
"funding": [
{
@ -1173,17 +1173,17 @@
},
{
"name": "symfony/polyfill-php80",
"version": "v1.25.0",
"version_normalized": "1.25.0.0",
"version": "v1.26.0",
"version_normalized": "1.26.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c"
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c",
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
"shasum": "",
"mirrors": [
{
@ -1195,11 +1195,11 @@
"require": {
"php": ">=7.1"
},
"time": "2022-03-04T08:16:47+00:00",
"time": "2022-05-10T07:21:04+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1245,7 +1245,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
},
"funding": [
{

View File

@ -5,7 +5,7 @@
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => 'c6f0e8b484140c10d99913401cd5f1fc7a51297e',
'reference' => 'f9dfa5e1dc3d41f2de077e66f0e346d029a093b0',
'name' => 'topthink/think',
'dev' => true,
),
@ -137,30 +137,30 @@
'dev_requirement' => false,
),
'symfony/polyfill-mbstring' => array(
'pretty_version' => 'v1.25.0',
'version' => '1.25.0.0',
'pretty_version' => 'v1.26.0',
'version' => '1.26.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
'aliases' => array(),
'reference' => '0abb51d2f102e00a4eefcf46ba7fec406d245825',
'reference' => '9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e',
'dev_requirement' => false,
),
'symfony/polyfill-php72' => array(
'pretty_version' => 'v1.25.0',
'version' => '1.25.0.0',
'pretty_version' => 'v1.26.0',
'version' => '1.26.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-php72',
'aliases' => array(),
'reference' => '9a142215a36a3888e30d0a9eeea9766764e96976',
'reference' => 'bf44a9fd41feaac72b074de600314a93e2ae78e2',
'dev_requirement' => true,
),
'symfony/polyfill-php80' => array(
'pretty_version' => 'v1.25.0',
'version' => '1.25.0.0',
'pretty_version' => 'v1.26.0',
'version' => '1.26.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
'aliases' => array(),
'reference' => '4407588e0d3f1f52efb65fbe92babe41f37fe50c',
'reference' => 'cfa0ae98841b9e461207c13ab093d76b0fa7bace',
'dev_requirement' => false,
),
'symfony/var-dumper' => array(
@ -187,7 +187,7 @@
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => 'c6f0e8b484140c10d99913401cd5f1fc7a51297e',
'reference' => 'f9dfa5e1dc3d41f2de077e66f0e346d029a093b0',
'dev_requirement' => false,
),
'topthink/think-captcha' => array(

2
vendor/services.php vendored
View File

@ -1,5 +1,5 @@
<?php
// This file is automatically generated at:2022-06-01 10:33:01
// This file is automatically generated at:2022-06-12 21:34:01
declare (strict_types = 1);
return array (
0 => 'think\\captcha\\CaptchaService',

View File

@ -568,7 +568,7 @@ final class Mbstring
}
$rx .= '.{'.$split_length.'})/us';
return preg_split($rx, $string, null, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
return preg_split($rx, $string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
}
$result = [];

View File

@ -5,7 +5,7 @@ This component provides a partial, native PHP implementation for the
[Mbstring](https://php.net/mbstring) extension.
More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).
License
=======

View File

@ -31,7 +31,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",

View File

@ -6,6 +6,12 @@ This component provides functions added to PHP 7.2 core:
- [`spl_object_id`](https://php.net/spl_object_id)
- [`stream_isatty`](https://php.net/stream_isatty)
And also functions added to PHP 7.2 mbstring:
- [`mb_ord`](https://php.net/mb_ord)
- [`mb_chr`](https://php.net/mb_chr)
- [`mb_scrub`](https://php.net/mb_scrub)
On Windows only:
- [`sapi_windows_vt100_support`](https://php.net/sapi_windows_vt100_support)
@ -16,11 +22,12 @@ Moved to core since 7.2 (was in the optional XML extension earlier):
- [`utf8_decode`](https://php.net/utf8_decode)
Also, it provides constants added to PHP 7.2:
- [`PHP_FLOAT_*`](https://php.net/reserved.constants#constant.php-float-dig)
- [`PHP_OS_FAMILY`](https://php.net/reserved.constants#constant.php-os-family)
More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).
License
=======

View File

@ -25,7 +25,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",

View File

@ -3,12 +3,13 @@ Symfony Polyfill / Php80
This component provides features added to PHP 8.0 core:
- `Stringable` interface
- [`Stringable`](https://php.net/stringable) interface
- [`fdiv`](https://php.net/fdiv)
- `ValueError` class
- `UnhandledMatchError` class
- [`ValueError`](https://php.net/valueerror) class
- [`UnhandledMatchError`](https://php.net/unhandledmatcherror) class
- `FILTER_VALIDATE_BOOL` constant
- [`get_debug_type`](https://php.net/get_debug_type)
- [`PhpToken`](https://php.net/phptoken) class
- [`preg_last_error_msg`](https://php.net/preg_last_error_msg)
- [`str_contains`](https://php.net/str_contains)
- [`str_starts_with`](https://php.net/str_starts_with)

View File

@ -30,7 +30,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.26-dev"
},
"thanks": {
"name": "symfony/polyfill",