控制台应用,yzncms本身基于tp5.1框架,里面的队列用不了,bug,坑
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | Yzncms [ 御宅男工作室 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2018 http://yzncms.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: 御宅男 <530765310@qq.com>
  10. // +----------------------------------------------------------------------
  11. // +----------------------------------------------------------------------
  12. // | 栏目管理
  13. // +----------------------------------------------------------------------
  14. namespace app\admin\controller\cms;
  15. use app\admin\model\cms\Category as CategoryModel;
  16. use app\admin\model\cms\CategoryPriv as CategoryPrivModel;
  17. use app\common\controller\Adminbase;
  18. use think\Db;
  19. class Category extends Adminbase
  20. {
  21. private $categoryTemplate;
  22. private $listTemplate;
  23. private $showTemplate;
  24. private $pageTemplate;
  25. protected $noNeedRight = ['count_items', 'public_cache', 'public_tpl_file_list'];
  26. protected function initialize()
  27. {
  28. parent::initialize();
  29. $this->modelClass = new CategoryModel;
  30. //取得当前内容模型模板存放目录
  31. $themePath = TEMPLATE_PATH . (config('site.theme') ?: "default") . DS . "cms" . DS;
  32. //取得栏目频道模板列表
  33. $this->categoryTemplate = str_replace($themePath . DS, '', glob($themePath . DS . 'category*'));
  34. //取得栏目列表模板列表
  35. $this->listTemplate = str_replace($themePath . DS, '', glob($themePath . DS . 'list*'));
  36. //取得内容页模板列表
  37. $this->showTemplate = str_replace($themePath . DS, '', glob($themePath . DS . 'show*'));
  38. //取得单页模板
  39. $this->pageTemplate = str_replace($themePath . DS, '', glob($themePath . DS . 'page*'));
  40. }
  41. //栏目列表
  42. public function index()
  43. {
  44. if ($this->request->isAjax()) {
  45. $models = cache('Model');
  46. $tree = new \util\Tree();
  47. $tree->icon = ['&nbsp;&nbsp;&nbsp;│ ', '&nbsp;&nbsp;&nbsp;├─ ', '&nbsp;&nbsp;&nbsp;└─ '];
  48. $tree->nbsp = '&nbsp;&nbsp;&nbsp;';
  49. $categorys = [];
  50. $result = Db::name('category')->order('listorder DESC, id DESC')->select();
  51. foreach ($result as $k => $v) {
  52. if (isset($models[$v['modelid']]['name'])) {
  53. $v['modelname'] = $models[$v['modelid']]['name'];
  54. } else {
  55. $v['modelname'] = '/';
  56. }
  57. $v['catname'] = '<a data-width="900" data-height="600" data-open="' . url('edit', ['id' => $v['id']]) . '"">' . $v['catname'] . '</a>';
  58. $v['add_url'] = url("add", ["parentid" => $v['id']]);
  59. $v['url'] = buildCatUrl($v['id'], $v['url']);
  60. $categorys[$v['id']] = $v;
  61. }
  62. $tree->init($categorys);
  63. $_list = $tree->getTreeList($tree->getTreeArray(0), 'catname');
  64. $total = count($_list);
  65. $result = ["code" => 0, "count" => $total, "data" => $_list];
  66. return json($result);
  67. }
  68. return $this->fetch();
  69. }
  70. //新增栏目
  71. public function add()
  72. {
  73. if ($this->request->isPost()) {
  74. $data = $this->request->post();
  75. if (empty($data)) {
  76. $this->error('添加栏目数据不能为空!');
  77. }
  78. switch ($data['type']) {
  79. //单页
  80. case 1:
  81. $scene = 'page';
  82. break;
  83. //列表
  84. case 2:
  85. $scene = 'list';
  86. break;
  87. //外链
  88. case 3:
  89. $scene = 'link';
  90. break;
  91. default:
  92. $this->error('栏目类型错误~');
  93. }
  94. if ($data['isbatch']) {
  95. unset($data['isbatch'], $data['info']['catname'], $data['info']['catdir']);
  96. //需要批量添加的栏目
  97. $batch_add = explode(PHP_EOL, $data['batch_add']);
  98. if (empty($batch_add) || empty($data['batch_add'])) {
  99. $this->error('请填写需要添加的栏目!');
  100. }
  101. foreach ($batch_add as $rs) {
  102. if (trim($rs) == '') {
  103. continue;
  104. }
  105. $cat = explode('|', $rs, 2);
  106. $data['catname'] = $cat[0];
  107. $data['catdir'] = $cat[1] ?? '';
  108. $data['catdir'] = $this->get_dirpinyin($data['catname'], $data['catdir']);
  109. $result = $this->validate($data, 'app\admin\validate\cms\Category.' . $scene);
  110. if (true !== $result) {
  111. $this->error($result);
  112. }
  113. try {
  114. $this->modelClass->allowField(true)->isUpdate(false)->data($data)->save();
  115. } catch (\Exception $e) {
  116. $this->error($e->getMessage());
  117. }
  118. }
  119. $this->success("添加成功!");
  120. } else {
  121. $data['catdir'] = $this->get_dirpinyin($data['catname'], $data['catdir']);
  122. $result = $this->validate($data, 'app\admin\validate\cms\Category.' . $scene);
  123. if (true !== $result) {
  124. $this->error($result);
  125. }
  126. try {
  127. $this->modelClass->allowField(true)->save($data);
  128. } catch (\Exception $e) {
  129. $this->error($e->getMessage());
  130. }
  131. $this->success("添加成功!");
  132. }
  133. } else {
  134. $parentid = $this->request->param('parentid/d', 0);
  135. if (!empty($parentid)) {
  136. $Ca = getCategory($parentid);
  137. if (empty($Ca)) {
  138. $this->error("父栏目不存在!");
  139. }
  140. }
  141. //输出可用模型
  142. $modelsdata = cache("Model");
  143. $models = [];
  144. foreach ($modelsdata as $v) {
  145. if ($v['status'] == 1 && $v['module'] == 'cms') {
  146. $models[] = $v;
  147. }
  148. }
  149. //栏目列表 可以用缓存的方式
  150. $array = Db::name('Category')->order('listorder DESC, id DESC')->column('*', 'id');
  151. if (!empty($array) && is_array($array)) {
  152. $tree = new \util\Tree();
  153. $tree->icon = ['&nbsp;&nbsp;│ ', '&nbsp;&nbsp;├─ ', '&nbsp;&nbsp;└─ '];
  154. $tree->nbsp = '&nbsp;&nbsp;';
  155. $str = "<option value=@id @selected @disabled>@spacer @catname</option>";
  156. $tree->init($array);
  157. $categorydata = $tree->getTree(0, $str, $parentid);
  158. } else {
  159. $categorydata = '';
  160. }
  161. $this->assign([
  162. 'category' => $categorydata,
  163. 'models' => $models,
  164. 'tp_category' => $this->categoryTemplate,
  165. 'tp_list' => $this->listTemplate,
  166. 'tp_show' => $this->showTemplate,
  167. 'tp_page' => $this->pageTemplate,
  168. 'parentid_modelid' => $Ca['modelid'] ?? 0,
  169. "Member_Group" => cache("Member_Group"),
  170. "cmsConfig" => get_addon_config("cms"),
  171. ]);
  172. return $this->fetch();
  173. }
  174. }
  175. //编辑栏目
  176. public function edit()
  177. {
  178. if ($this->request->isPost()) {
  179. $catid = $this->request->param('id/d', 0);
  180. $row = $this->modelClass->get($catid);
  181. if (!$row) {
  182. $this->error('记录未找到');
  183. }
  184. $data = $this->request->post();
  185. //上级栏目不能是自身
  186. if ($data['parentid'] == $catid) {
  187. $this->error('上级栏目不能是自身!');
  188. }
  189. switch ($data['type']) {
  190. //单页
  191. case 1:
  192. $data['modelid'] = 0;
  193. $scene = 'page';
  194. break;
  195. //列表
  196. case 2:
  197. $scene = 'list';
  198. break;
  199. //列表
  200. case 3:
  201. $data['modelid'] = 0;
  202. $scene = 'link';
  203. break;
  204. default:
  205. $this->error('栏目类型错误~');
  206. }
  207. $data['catdir'] = $this->get_dirpinyin($data['catname'], $data['catdir'], $catid);
  208. $result = $this->validate($data, 'app\admin\validate\cms\Category.' . $scene);
  209. if (true !== $result) {
  210. $this->error($result);
  211. }
  212. try {
  213. $row->allowField(true)->save($data);
  214. } catch (\Exception $e) {
  215. $this->error($e->getMessage());
  216. }
  217. $this->success("修改成功!");
  218. } else {
  219. $catid = $this->request->param('id/d', 0);
  220. if (empty($catid)) {
  221. $this->error('请选择需要修改的栏目!');
  222. }
  223. $data = Db::name('category')->where(['id' => $catid])->find();
  224. $setting = unserialize($data['setting']);
  225. //输出可用模型
  226. $modelsdata = cache("Model");
  227. $models = [];
  228. foreach ($modelsdata as $v) {
  229. if ($v['status'] == 1 && $v['module'] == 'cms') {
  230. $models[] = $v;
  231. }
  232. }
  233. //栏目列表 可以用缓存的方式
  234. $array = Db::name('Category')->order('listorder DESC, id DESC')->column('*', 'id');
  235. if (!empty($array) && is_array($array)) {
  236. $tree = new \util\Tree();
  237. $tree->icon = ['&nbsp;&nbsp;│ ', '&nbsp;&nbsp;├─ ', '&nbsp;&nbsp;└─ '];
  238. $tree->nbsp = '&nbsp;&nbsp;';
  239. $str = "<option value=@id @selected @disabled>@spacer @catname</option>";
  240. $tree->init($array);
  241. $categorydata = $tree->getTree(0, $str, $data['parentid']);
  242. } else {
  243. $categorydata = '';
  244. }
  245. $this->assign([
  246. 'data' => $data,
  247. 'setting' => $setting,
  248. 'category' => $categorydata,
  249. 'models' => $models,
  250. 'tp_category' => $this->categoryTemplate,
  251. 'tp_list' => $this->listTemplate,
  252. 'tp_show' => $this->showTemplate,
  253. 'tp_page' => $this->pageTemplate,
  254. 'privs' => CategoryPrivModel::where('catid', $catid)->select(),
  255. "cmsConfig" => get_addon_config("cms"),
  256. "Member_Group" => cache("Member_Group"),
  257. ]);
  258. return $this->fetch();
  259. }
  260. }
  261. //栏目授权
  262. public function cat_priv()
  263. {
  264. $act = $this->request->param('act');
  265. $id = $this->request->param('id');
  266. if ($act == 'authorization') {
  267. if (empty($id)) {
  268. $this->error('请指定需要授权的角色!');
  269. }
  270. if ($this->request->isAjax()) {
  271. $data = $this->request->post();
  272. $priv = [];
  273. if (isset($data['priv'])) {
  274. foreach ($data['priv'] as $k => $v) {
  275. foreach ($v as $e => $q) {
  276. $priv[] = ["roleid" => $id, "catid" => $k, "action" => $q, "is_admin" => 1];
  277. }
  278. }
  279. Db::name("CategoryPriv")->where("roleid", $id)->delete();
  280. Db::name("CategoryPriv")->insertAll($priv);
  281. $this->success("栏目授权成功!");
  282. } else {
  283. $this->error('请指定需要授权的栏目!');
  284. }
  285. } else {
  286. $tree = new \util\Tree();
  287. $tree->icon = ['&nbsp;&nbsp;&nbsp;│ ', '&nbsp;&nbsp;&nbsp;├─ ', '&nbsp;&nbsp;&nbsp;└─ '];
  288. $tree->nbsp = '&nbsp;&nbsp;&nbsp;';
  289. $category_priv = Db::name('CategoryPriv')->where("roleid", $id)->select();
  290. $priv = [];
  291. foreach ($category_priv as $k => $v) {
  292. $priv[$v['catid']][$v['action']] = true;
  293. }
  294. $categorys = Db::name('category')->order('listorder DESC, id DESC')->select();
  295. foreach ($categorys as $k => $v) {
  296. if ($v['type'] == 1 || $v['child']) {
  297. $v['disabled'] = 'disabled';
  298. $v['init_check'] = '';
  299. $v['add_check'] = '';
  300. $v['delete_check'] = '';
  301. $v['listorder_check'] = '';
  302. $v['move_check'] = '';
  303. $v['edit_check'] = '';
  304. $v['status_check'] = '';
  305. } else {
  306. $v['disabled'] = '';
  307. $v['add_check'] = isset($priv[$v['id']]['add']) ? 'checked' : '';
  308. $v['delete_check'] = isset($priv[$v['id']]['delete']) ? 'checked' : '';
  309. $v['listorder_check'] = isset($priv[$v['id']]['listorder']) ? 'checked' : '';
  310. $v['move_check'] = isset($priv[$v['id']]['remove']) ? 'checked' : '';
  311. $v['edit_check'] = isset($priv[$v['id']]['edit']) ? 'checked' : '';
  312. $v['status_check'] = isset($priv[$v['id']]['status']) ? 'checked' : '';
  313. }
  314. $v['init_check'] = isset($priv[$v['id']]['init']) ? 'checked' : '';
  315. $categorys[$k] = $v;
  316. }
  317. $str = "<tr>
  318. <td align='center'><input type='checkbox' value='1' data-name='@id' lay-skin='primary'></td>
  319. <td>@spacer@catname</td>
  320. <td align='center'><input type='checkbox' name='priv[@id][]' @init_check lay-skin='primary' value='init' ></td>
  321. <td align='center'><input type='checkbox' name='priv[@id][]' @disabled @add_check lay-skin='primary' value='add' ></td>
  322. <td align='center'><input type='checkbox' name='priv[@id][]' @disabled @edit_check lay-skin='primary' value='edit' ></td>
  323. <td align='center'><input type='checkbox' name='priv[@id][]' @disabled @delete_check lay-skin='primary' value='delete' ></td>
  324. <td align='center'><input type='checkbox' name='priv[@id][]' @disabled @listorder_check lay-skin='primary' value='listorder' ></td>
  325. <td align='center'><input type='checkbox' name='priv[@id][]' @disabled @status_check lay-skin='primary' value='status' ></td>
  326. <td align='center'><input type='checkbox' name='priv[@id][]' @disabled @move_check lay-skin='primary' value='remove' ></td>
  327. </tr>";
  328. $tree->init($categorys);
  329. $categorydata = $tree->getTree(0, $str);
  330. $this->assign("categorys", $categorydata);
  331. return $this->fetch('authorization');
  332. }
  333. } elseif ($act == 'remove') {
  334. Db::name('CategoryPriv')->where('roleid', $id)->delete();
  335. $this->success('删除成功!');
  336. }
  337. if ($this->request->isAjax()) {
  338. $priv_num = [];
  339. $category_priv = Db::name('CategoryPriv')->field("count(*) as num,roleid")->group("roleid")->select();
  340. foreach ($category_priv as $k => $v) {
  341. $priv_num[$v['roleid']] = $v['num'];
  342. }
  343. $_list = Db::name('AuthGroup')->where('status', 1)->order('id', 'desc')->field('id,title')->select();
  344. foreach ($_list as $k => $v) {
  345. $_list[$k]['admin'] = $v['id'] == 1;
  346. $_list[$k]['num'] = $priv_num[$v['id']] ?? 0;
  347. }
  348. $result = ["code" => 0, "data" => $_list];
  349. return json($result);
  350. } else {
  351. $cmsConfig = get_addon_config("cms");
  352. $this->assign("cmsConfig", $cmsConfig);
  353. return $this->fetch();
  354. }
  355. }
  356. //更新栏目缓存并修复
  357. public function public_cache()
  358. {
  359. $this->repair();
  360. $this->cache();
  361. $this->success("更新缓存成功!", Url("cms/category/index"));
  362. }
  363. //清除栏目缓存
  364. protected function cache()
  365. {
  366. cache('Category', null);
  367. }
  368. //修复栏目数据
  369. private function repair()
  370. {
  371. //取出需要处理的栏目数据
  372. $categorys = Db::name('Category')->order('listorder DESC, id DESC')->column('*', 'id');
  373. if (empty($categorys)) {
  374. return true;
  375. }
  376. try {
  377. if (is_array($categorys)) {
  378. foreach ($categorys as $catid => $cat) {
  379. //获取父栏目ID列表
  380. $arrparentid = CategoryModel::get_arrparentid($catid);
  381. //获取子栏目ID列表
  382. $arrchildid = CategoryModel::get_arrchildid($catid);
  383. $child = is_numeric($arrchildid) ? 0 : 1; //是否有子栏目
  384. //检查所有父id 子栏目id 等相关数据是否正确,不正确更新
  385. if ($cat['arrparentid'] != $arrparentid || $cat['arrchildid'] != $arrchildid || $cat['child'] != $child) {
  386. Db::name('Category')->where('id', $catid)->update(['arrparentid' => $arrparentid, 'arrchildid' => $arrchildid, 'child' => $child]);
  387. }
  388. \think\facade\Cache::rm('getCategory_' . $catid, null);
  389. //删除在非正常显示的不含信息或子栏目的栏目
  390. if ($cat['parentid'] != 0 && !isset($categorys[$cat['parentid']])) {
  391. CategoryModel::destroy($catid);
  392. }
  393. }
  394. }
  395. } catch (\Exception $e) {
  396. //$this->error($e->getMessage());
  397. }
  398. return true;
  399. }
  400. //重新统计栏目信息数量
  401. public function count_items()
  402. {
  403. $result = Db::name('Category')->order('listorder DESC, id DESC')->select();
  404. $model_cache = cache("Model");
  405. foreach ($result as $r) {
  406. if ($r['type'] == 2) {
  407. $modelid = $r['modelid'];
  408. if (isset($model_cache[$modelid])) {
  409. $number = Db::name(ucwords($model_cache[$modelid]['tablename']))->where('catid', $r['id'])->count();
  410. Db::name('Category')->where('id', $r['id'])->update(['items' => $number]);
  411. } else {
  412. Db::name('Category')->where('id', $r['id'])->update(['items' => 0]);
  413. }
  414. } else {
  415. Db::name('Category')->where('id', $r['id'])->update(['items' => 0]);
  416. }
  417. }
  418. $this->success("栏目数量校正成功!");
  419. }
  420. public function multi()
  421. {
  422. $id = $this->request->param('id/d');
  423. cache('Category', null);
  424. getCategory($id, '', true);
  425. return parent::multi();
  426. }
  427. //获取栏目的拼音
  428. private function get_dirpinyin($catname = '', $catdir = '', $id = 0)
  429. {
  430. $pinyin = new \Overtrue\Pinyin\Pinyin('Overtrue\Pinyin\MemoryFileDictLoader');
  431. if (empty($catdir)) {
  432. $catdir = $pinyin->permalink($catname, '');
  433. }
  434. if (strval(intval($catdir)) == strval($catdir)) {
  435. $catdir .= genRandomString(3);
  436. }
  437. $map = [
  438. ['catdir', '=', $catdir],
  439. ];
  440. if (intval($id) > 0) {
  441. $map[] = ['id', '<>', $id];
  442. }
  443. $result = Db::name('Category')->field('id')->where($map)->find();
  444. if (!empty($result)) {
  445. $nowDirname = $catdir . genRandomString(3);
  446. return $this->get_dirpinyin($catname, $nowDirname, $id);
  447. }
  448. return $catdir;
  449. }
  450. //动态根据模型ID加载栏目模板
  451. public function public_tpl_file_list()
  452. {
  453. $id = $this->request->param('id/d');
  454. $data = Db::name('Model')->where('id', $id)->find();
  455. if ($data) {
  456. $json = ['code' => 0, 'data' => unserialize($data['setting'])];
  457. return json($json);
  458. }
  459. }
  460. }