www_fpvone_cn/application/admin/controller/Docs.php

433 lines
16 KiB
PHP
Raw Normal View History

2024-12-20 12:29:51 +08:00
<?php
namespace app\admin\controller;
use addons\docs\library\Service;
use app\common\controller\Backend;
use fast\Http;
use fast\Tree;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use think\Exception;
use think\Validate;
use ZipArchive;
/**
*
* 文档管理
* @icon fa fa-circle-o
*/
class Docs extends Backend
{
protected $docs = [];
protected $docsdata = [];
protected $typeList = [];
protected $typeColor = [];
protected $noNeedRight = ["selectpage_type", "get_parent_options"];
public function _initialize()
{
parent::_initialize();
$this->docsdata = Service::getDocsData(false);
$config = get_addon_config('docs');
$this->typeList = $this->typeColor = [];
$langs = $config['lang'];
$colors = ["primary", "success", "danger", "warning", "info"];
foreach ($this->docsdata as $type => $pages) {
$this->typeList[$type] = $langs[$type] ?? $type;
$this->typeColor[$type] = array_pop($colors);
}
$this->view->assign('typeList', $this->typeList);
$this->assignconfig('typeList', $this->typeList);
$this->view->assign('typeColor', $this->typeColor);
$this->assignconfig('typeColor', $this->typeColor);
$this->assignconfig('htmlDetect', (bool)($config['htmldetect'] ?? false));
}
/**
* 查看
*/
public function index()
{
//设置过滤方法
$this->request->filter(['strip_tags']);
if ($this->request->isAjax()) {
$filter = $this->request->request('filter', '');
$filter = (array)json_decode($filter, true);
$filter['type'] = isset($filter['type']) && $filter['type'] ? $filter['type'] : '';
$search = $this->request->request("search");
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$list = [];
$docsdata = $this->docsdata;
if ($filter['type']) {
$docsdata = isset($docsdata[$filter['type']]) ? [$filter['type'] => $docsdata[$filter['type']]] : [];
}
foreach ($docsdata as $index => $docsdatum) {
$tree = Tree::instance();
$data = $tree->init($docsdatum, 'parent')->getTreeArray('');
$list = array_merge($list, $tree->getTreeList($data, 'title'));
}
$ids = [];
foreach ($list as $index => $item) {
$ids[] = $item['id'];
}
foreach ($docsdata as $index => $docsdatum) {
foreach ($docsdatum as $key => $item) {
if (!in_array($item['id'], $ids)) {
$list[] = $item;
}
}
}
//foreach ($this->docsdata as $type => $pages) {
// if ($filter['type'] && $type != $filter['type']) {
// continue;
// }
// foreach ($pages as $index => $page) {
// if (!$search || stripos($page['relative'], $search) !== false || stripos($page['title'], $search) !== false) {
// $list[] = $page;
// }
// }
//}
$total = count($list);
$result = array("total" => $total, "rows" => array_slice($list, $offset, $limit));
return json($result);
}
return $this->view->fetch();
}
/**
* 添加
*/
public function add()
{
if ($this->request->isPost()) {
$params = $this->request->post("row/a");
if ($params) {
try {
if (!$params['md']) {
throw new Exception("MD文件不能为空");
}
$config = get_addon_config('docs');
$params['md'] = trim($params['md']);
//未设置后缀
if (stripos($params['md'], ".{$config['suffix']}") === false) {
$params['md'] .= ".{$config['suffix']}";
}
if (mb_substr_count($params['md'], "/") > 1) {
throw new Exception("MD文件中只能包含一个/字符");
}
if (mb_substr_count($params['md'], ".") > 1) {
throw new Exception("MD文件中只能包含一个.字符");
}
if (!Validate::is($params['md'], "/^[A-Za-z0-9\-\_\.\/]+$/")) {
throw new Exception("MD文件只能是字母数字下划线");
}
$exist = Service::getMarkdownData($params['md']);
if ($exist) {
throw new Exception("对应的MD文件已经存在");
}
$parent = $params['parent'] ?? '';
$type = $params['type'] ?? '';
if ($parent) {
if ($parent == str_replace(".md", "", $params['md'])) {
$this->error("父级不能为当前文件");
}
if (!isset($this->docsdata[$type])) {
$this->error("未找到指定分类");
}
$nameArr = [];
foreach ($this->docsdata[$type] as $index => $docsdatum) {
$nameArr[] = $docsdatum['name'];
}
if (!in_array($parent, $nameArr)) {
$this->error("未找到指定父级数据");
}
}
Service::setMarkdownData($params['md'], $params);
} catch (Exception $e) {
$this->error($e->getMessage());
}
$this->success();
}
$this->error(__('Parameter %s can not be empty', ''));
}
return $this->view->fetch();
}
/**
* 编辑
*/
public function edit($ids = null)
{
$ids = $ids ? $ids : $this->request->request('ids');
$row = Service::getMarkdownData($ids, true, false);
if (!$row) {
$this->error(__('No Results were found'));
}
if ($this->request->isPost()) {
$params = $this->request->post("row/a");
if ($params) {
$config = get_addon_config('docs');
$params['md'] = trim(isset($params['md']) && $params['md'] ? $params['md'] : $row['relative']);
$md = $params['md'];
$parent = $params['parent'] ?? '';
$type = $params['type'] ?? '';
if ($parent) {
if ($parent == str_replace(".md", "", $ids)) {
$this->error("父级不能为当前文件");
}
if (!isset($this->docsdata[$type])) {
$this->error("未找到指定分类");
}
$nameArr = [];
foreach ($this->docsdata[$type] as $index => $docsdatum) {
$nameArr[] = $docsdatum['name'];
}
if (!in_array($parent, $nameArr)) {
$this->error("未找到指定父级数据");
}
}
//如果文件名有变更,删除原文件
if ($md != $row['relative']) {
//未设置后缀
if (stripos($params['md'], ".{$config['suffix']}") === false) {
$params['md'] .= ".{$config['suffix']}";
}
if (mb_substr_count($params['md'], "/") > 1) {
throw new Exception("MD文件中只能包含一个/字符");
}
if (mb_substr_count($params['md'], ".") > 1) {
throw new Exception("MD文件中只能包含一个.字符");
}
if (!Validate::is($params['md'], "/^[A-Za-z0-9\-\_\.\/]+$/")) {
throw new Exception("MD文件只能是字母数字下划线");
}
$exist = Service::getMarkdownData($params['md']);
if ($exist) {
throw new Exception("对应的MD文件已经存在");
}
}
try {
//如果变更了分类,则所有子文档分类都需要变更
if ($type != $row['type']) {
$docs = $this->docsdata[$row['type']] ?? [];
$childrenList = Tree::instance()->init($docs, 'parent')->getChildren($row['id']);
foreach ($childrenList as $index => $item) {
$data = Service::getMarkdownData($item['relative'], true);
$data['type'] = $type;
Service::setMarkdownData($item['relative'], $data);
}
}
Service::setMarkdownData($md, $params);
//如果文件名有变更,删除原文件
if ($md != $row['relative']) {
unlink(Service::getDocsSourceDir() . $row['relative']);
}
} catch (Exception $e) {
$this->error($e->getMessage());
}
$this->success();
}
$this->error(__('Parameter %s can not be empty', ''));
}
$allowEditName = true;
$parentList = isset($this->docsdata[$row['type']]) ? $this->docsdata[$row['type']] : [];
foreach ($parentList as $index => $item) {
if ($item['parent'] == $row['name']) {
$allowEditName = false;
break;
}
}
$parentOptions = $this->getParentList($row['type'], $row['id'], $row['parent']);
$this->view->assign("parentOptions", $parentOptions);
$this->view->assign("allowEditName", $allowEditName);
$this->view->assign("row", $row);
return $this->view->fetch();
}
/**
* 删除
*/
public function del($ids = "")
{
if (!$this->request->isPost()) {
$this->error(__("Invalid parameters"));
}
$ids = $ids ? $ids : $this->request->post("ids");
if ($ids) {
if (stripos($ids, ',') !== false) {
$this->error("文档不支持批量删除");
}
$row = Service::getMarkdownData($ids, false, false);
if (!$row) {
$this->error(__('No Results were found'));
}
try {
unlink(Service::getDocsSourceDir() . $row['relative']);
Service::refreshDocsData();
} catch (Exception $e) {
$this->error($e->getMessage());
}
$this->success();
}
$this->error(__('Parameter %s can not be empty', 'ids'));
}
/**
* 刷新
*/
public function refresh()
{
Service::refreshDocsData();
$this->success();
}
/**
* 导出
*/
public function export()
{
try {
//重新生成一次文档
Service::build();
} catch (\Exception $e) {
$this->error($e->getMessage());
}
$distDir = Service::getDocsDistDir();
$zipFile = RUNTIME_PATH . 'addons' . DS . 'export-docs-' . date('YmdHis') . '.zip';
$rootPath = realpath($distDir);
$zip = new ZipArchive();
$zip->open($zipFile, ZipArchive::CREATE | ZipArchive::OVERWRITE);
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($rootPath),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $name => $file) {
if (!$file->isDir()) {
$filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen($rootPath) + 1);
$relativePath = str_replace('\\', '/', $relativePath);
$zip->addFile($filePath, $relativePath);
}
}
$zip->close();
Http::sendToBrowser($zipFile);
}
/**
* 批量更新
* @internal
*/
public function status($ids = "")
{
$ids = $ids ? $ids : $this->request->param("ids");
if ($ids) {
if ($this->request->has('params')) {
parse_str($this->request->post("params"), $values);
if ($values && isset($values['isnew'])) {
$row = Service::getMarkdownData($ids, true, false);
$row = array_merge($row, $values);
try {
Service::setMarkdownData($ids, $row);
} catch (Exception $e) {
$this->error($e->getMessage());
}
$this->success();
} else {
$this->error(__('You have no permission'));
}
}
}
$this->error(__('Parameter %s can not be empty', 'ids'));
}
/**
* 批量更新
* @internal
*/
public function multi($ids = "")
{
return;
}
/**
* 动态下拉选择类型
* @internal
*/
public function selectpage_type()
{
$list = [];
$word = (array)$this->request->request("q_word/a");
$field = $this->request->request('showField');
$keyValue = $this->request->request('keyValue');
$config = get_addon_config('docs');
$typeList = [];
$langs = $config['lang'];
foreach ($this->docsdata as $type => $pages) {
$typeList[$type] = isset($langs[$type]) ? $langs[$type] : $type;
}
$typeArr = $typeList;
if (!$keyValue) {
if (array_filter($word)) {
foreach ($word as $k => $v) {
$list[] = ['id' => $v, $field => $v];
}
}
foreach ($typeArr as $index => $item) {
$list[] = ['id' => $index, $field => $item];
}
} else {
$list[] = ['id' => $keyValue, $field => $typeArr[$keyValue] ?? $keyValue];
}
return json(['total' => count($list), 'list' => $list]);
}
/**
* 获取父级options
* @internal
*/
public function get_parent_options()
{
$type = $this->request->request('type');
$origintype = $this->request->request('origintype');
$id = $parent = null;
if ($type == $origintype) {
$id = $this->request->request('id');
$parent = $this->request->request('parent');
}
$parentOptions = '<option value="">无</option>';
if ($type) {
$parentOptions .= $this->getParentList($type, $id, $parent);
}
$this->success("", '', ['options' => $parentOptions]);
}
protected function getParentList($type, $id = null, $parent = null)
{
$parentList = [];
$parentOptions = '';
if (!isset($this->docsdata[$type])) {
return $parentOptions;
}
foreach ($this->docsdata[$type] as $index => $item) {
$parentList[] = ['id' => $item['id'], 'pid' => $item['parent'], 'name' => $item['title']];
}
if ($parentList) {
$tree = Tree::instance()->init($parentList);
$disableIds = $id ? $tree->getChildrenIds($id, true) : [];
$selectIds = $parent ? [$parent] : [];
$parentOptions = $tree->getTree('', '<option value=@id @selected @disabled>@spacer@name</option>', $selectIds, $disableIds);
}
return $parentOptions;
}
}