Arctype.php 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085
  1. <?php
  2. /**
  3. * 易优CMS
  4. * ============================================================================
  5. * 版权所有 2016-2028 海南赞赞网络科技有限公司,并保留所有权利。
  6. * 网站地址: http://www.eyoucms.com
  7. * ----------------------------------------------------------------------------
  8. * 如果商业用途务必到官方购买正版授权, 以免引起不必要的法律纠纷.
  9. * ============================================================================
  10. * Author: 小虎哥 <1105415366@qq.com>
  11. * Date: 2018-4-3
  12. */
  13. namespace app\admin\controller;
  14. use think\Page;
  15. use think\Db;
  16. use app\common\logic\ArctypeLogic;
  17. use app\admin\logic\FieldLogic;
  18. class Arctype extends Base
  19. {
  20. public $fieldLogic;
  21. public $arctypeLogic;
  22. // 栏目对应模型ID
  23. public $arctype_channel_id = '';
  24. // 允许发布文档的模型ID
  25. public $allowReleaseChannel = array();
  26. // 禁用的目录名称
  27. public $disableDirname = [];
  28. public function _initialize()
  29. {
  30. parent::_initialize();
  31. $this->fieldLogic = new FieldLogic();
  32. $this->arctypeLogic = new ArctypeLogic();
  33. $this->allowReleaseChannel = config('global.allow_release_channel');
  34. $this->arctype_channel_id = config('global.arctype_channel_id');
  35. $this->disableDirname = config('global.disable_dirname');
  36. /*兼容每个用户的自定义字段,重新生成数据表字段缓存文件*/
  37. $arctypeFieldInfo = include DATA_PATH . 'schema/' . PREFIX . 'arctype.php';
  38. foreach (['weapp_code'] as $key => $val) {
  39. if (!isset($arctypeFieldInfo[$val])) {
  40. try {
  41. schemaTable('arctype');
  42. } catch (\Exception $e) {}
  43. break;
  44. }
  45. }
  46. /*--end*/
  47. }
  48. public function index()
  49. {
  50. $arctype_list = array();
  51. // 目录列表
  52. $where['is_del'] = '0'; // 回收站功能
  53. $arctype_list = $this->arctypeLogic->arctype_list(0, 0, false, 0, $where, false);
  54. $this->assign('arctype_list', $arctype_list);
  55. /*多语言模式下,栏目ID显示主体语言的ID和属性title名称*/
  56. $main_arctype_list = [];
  57. if ($this->admin_lang != $this->main_lang) {
  58. $attr_values = get_arr_column($arctype_list, 'id');
  59. $languageAttrRow = Db::name('language_attr')->field('attr_name,attr_value')->where([
  60. 'attr_value' => ['IN', $attr_values],
  61. 'attr_group' => 'arctype',
  62. 'lang' => $this->admin_lang,
  63. ])->getAllWithIndex('attr_value');
  64. $typeids = [];
  65. foreach ($languageAttrRow as $key => $val) {
  66. $tid_tmp = str_replace('tid', '', $val['attr_name']);
  67. array_push($typeids, intval($tid_tmp));
  68. }
  69. $main_ArctypeRow = Db::name('arctype')->field("id,typename,CONCAT('tid', id) AS attr_name")
  70. ->where([
  71. 'id' => ['IN', $typeids],
  72. 'lang' => $this->main_lang,
  73. ])->getAllWithIndex('attr_name');
  74. foreach ($arctype_list as $key => $val) {
  75. $key_tmp = !empty($languageAttrRow[$val['id']]['attr_name']) ? $languageAttrRow[$val['id']]['attr_name'] : '';
  76. $main_arctype_list[$val['id']] = [
  77. 'id' => !empty($main_ArctypeRow[$key_tmp]['id']) ? $main_ArctypeRow[$key_tmp]['id'] : 0,
  78. 'typename' => !empty($main_ArctypeRow[$key_tmp]['typename']) ? $main_ArctypeRow[$key_tmp]['typename'] : '',
  79. ];
  80. }
  81. }
  82. $this->assign('main_arctype_list', $main_arctype_list);
  83. /*end*/
  84. // 模型列表
  85. $channeltype_list = getChanneltypeList();
  86. $this->assign('channeltype_list', $channeltype_list);
  87. // 栏目最多级别
  88. $arctype_max_level = intval(config('global.arctype_max_level'));
  89. $this->assign('arctype_max_level', $arctype_max_level);
  90. /* 生成静态页面代码 */
  91. $typeid = input('param.typeid/d',0);
  92. $is_del = input('param.is_del/d',0);
  93. $this->assign('typeid',$typeid);
  94. $this->assign('is_del',$is_del);
  95. /* end */
  96. return $this->fetch();
  97. }
  98. /**
  99. * 新增
  100. */
  101. public function add()
  102. {
  103. //防止php超时
  104. function_exists('set_time_limit') && set_time_limit(0);
  105. $this->language_access(); // 多语言功能操作权限
  106. if (IS_POST) {
  107. $post = input('post.');
  108. if ($post) {
  109. /*目录名称*/
  110. $post['dirname'] = func_preg_replace([' ',' '], '', $post['dirname']);
  111. $dirname = $this->arctypeLogic->get_dirname($post['typename'], $post['dirname']);
  112. // 检测
  113. if (!empty($post['dirname']) && !$this->arctypeLogic->dirname_unique($post['dirname'])) {
  114. $this->error('目录名称与系统内置冲突,请更改!');
  115. }
  116. /*--end*/
  117. $dirpath = rtrim($post['dirpath'],'/');
  118. /* ------临时代码,当能支持静态页面生成,再去掉 */
  119. $dirpath = $dirpath . '/' . $dirname;
  120. /* -----------end----------- */
  121. $typelink = !empty($post['is_part']) ? $post['typelink'] : '';
  122. /*封面图的本地/远程图片处理*/
  123. $is_remote = !empty($post['is_remote']) ? $post['is_remote'] : 0;
  124. $litpic = '';
  125. if ($is_remote == 1) {
  126. $litpic = $post['litpic_remote'];
  127. } else {
  128. $litpic = $post['litpic_local'];
  129. }
  130. /*--end*/
  131. // 获取顶级模型ID
  132. if (empty($post['parent_id'])) {
  133. $channeltype = $post['current_channel'];
  134. } else {
  135. $channeltype = M('arctype')->where('id', $post['parent_id'])->getField('channeltype');
  136. }
  137. /*SEO描述*/
  138. $seo_description = $post['seo_description'];
  139. /*--end*/
  140. /*处理自定义字段值*/
  141. $addonField = array();
  142. if (!empty($post['addonField'])) {
  143. $addonField = $this->fieldLogic->handleAddonField($this->arctype_channel_id, $post['addonField']);
  144. }
  145. /*--end*/
  146. $newData = array(
  147. 'dirname' => $dirname,
  148. 'dirpath' => $dirpath,
  149. 'typelink' => $typelink,
  150. 'litpic' => $litpic,
  151. 'channeltype' => $channeltype,
  152. 'current_channel' => $post['current_channel'],
  153. 'seo_keywords' => str_replace(',', ',', $post['seo_keywords']),
  154. 'seo_description' => $seo_description,
  155. 'admin_id' => session('admin_info.admin_id'),
  156. 'lang' => $this->admin_lang,
  157. 'sort_order' => 100,
  158. 'add_time' => getTime(),
  159. 'update_time' => getTime(),
  160. );
  161. $data = array_merge($post, $newData, $addonField);
  162. $insertId = model('Arctype')->addData($data);
  163. if($insertId){
  164. $_POST['id'] = $insertId;
  165. /*同步栏目ID到多语言的模板栏目变量里*/
  166. $this->arctypeLogic->syn_add_language_attribute($insertId);
  167. /*--end*/
  168. adminLog('新增栏目:'.$data['typename']);
  169. // 生成静态页面代码
  170. $this->success("操作成功!", url('Arctype/index', ['typeid'=>$insertId]));
  171. exit;
  172. }
  173. }
  174. $this->error("操作失败!");
  175. exit;
  176. }
  177. $assign_data = array();
  178. /* 模型 */
  179. $map = array(
  180. 'status' => 1,
  181. );
  182. $channeltype_list = model('Channeltype')->getAll('id,title,nid', $map, 'id');
  183. $this->assign('channeltype_list', $channeltype_list);
  184. // 新增栏目在指定的上一级栏目下
  185. $parent_id = input('param.parent_id/d');
  186. $grade = 0;
  187. $current_channel = '';
  188. $predirpath = ''; // 生成静态页面代码
  189. $ptypename = '';
  190. if (0 < $parent_id) {
  191. $info = M('arctype')->where(array('id'=>$parent_id))->find();
  192. if ($info) {
  193. // 级别
  194. $grade = $info['grade'] + 1;
  195. // 菜单对应下的栏目
  196. // $selected = $info['id'];
  197. // 模型
  198. $current_channel = $info['current_channel'];
  199. // 上级目录
  200. $predirpath = $info['dirpath'];
  201. // 上级栏目名称
  202. $ptypename = $info['typename'];
  203. }
  204. }
  205. $this->assign('predirpath', $predirpath);
  206. $this->assign('parent_id', $parent_id);
  207. $this->assign('ptypename', $ptypename);
  208. $this->assign('grade',$grade);
  209. $this->assign('current_channel',$current_channel);
  210. /*发布文档的模型ID,用于是否显示文档模板列表*/
  211. $js_allow_channel_arr = '[';
  212. foreach ($this->allowReleaseChannel as $key => $val) {
  213. if ($key > 0) {
  214. $js_allow_channel_arr .= ',';
  215. }
  216. $js_allow_channel_arr .= $val;
  217. }
  218. $js_allow_channel_arr = $js_allow_channel_arr.']';
  219. $this->assign('js_allow_channel_arr', $js_allow_channel_arr);
  220. /*--end*/
  221. /*模板列表*/
  222. $templateList = $this->ajax_getTemplateList('add');
  223. $this->assign('templateList', $templateList);
  224. /*--end*/
  225. /*自定义字段*/
  226. $assign_data['addonFieldExtList'] = model('Field')->getTabelFieldList(config('global.arctype_channel_id'));
  227. $assign_data['aid'] = 0;
  228. $assign_data['channeltype'] = 6;
  229. $assign_data['nid'] = 'arctype';
  230. /*--end*/
  231. $this->assign($assign_data);
  232. return $this->fetch();
  233. }
  234. /**
  235. * 编辑
  236. */
  237. public function edit()
  238. {
  239. if (IS_POST) {
  240. $post = input('post.');
  241. if (!empty($post['id'])) {
  242. /*自己的上级不能是自己*/
  243. if (intval($post['id']) == intval($post['parent_id'])) {
  244. $this->error('自己不能成为自己的上级栏目');
  245. }
  246. /*--end*/
  247. /*目录名称*/
  248. $post['dirname'] = func_preg_replace([' ', ' '], '', $post['dirname']);
  249. $dirname = $this->arctypeLogic->get_dirname($post['typename'], $post['dirname'], $post['id']);
  250. // 检测
  251. if (!empty($post['dirname']) && !$this->arctypeLogic->dirname_unique($post['dirname'], $post['id'])) {
  252. $this->error('目录名称与系统内置冲突,请更改!');
  253. }
  254. /*--end*/
  255. $dirpath = rtrim($post['dirpath'], '/');
  256. $typelink = !empty($post['is_part']) ? $post['typelink'] : '';
  257. /*封面图的本地/远程图片处理*/
  258. $is_remote = !empty($post['is_remote']) ? $post['is_remote'] : 0;
  259. $litpic = '';
  260. if ($is_remote == 1) {
  261. $litpic = $post['litpic_remote'];
  262. } else {
  263. $litpic = $post['litpic_local'];
  264. }
  265. /*--end*/
  266. // 最顶级模型ID
  267. $channeltype = $post['channeltype'];
  268. // 当前更改的等级
  269. $grade = $post['grade'];
  270. // 根据栏目ID获取最新的最顶级模型ID
  271. if (intval($post['parent_id']) > 0) {
  272. $arctype_row = Db::name('arctype')->field('grade,channeltype')->where('id', $post['parent_id'])->find();
  273. $channeltype = $arctype_row['channeltype'];
  274. $grade = $arctype_row['grade'] + 1;
  275. }
  276. /*SEO描述*/
  277. $seo_description = $post['seo_description'];
  278. /*--end*/
  279. /*处理自定义字段值*/
  280. $addonField = array();
  281. if (!empty($post['addonField'])) {
  282. $addonField = $this->fieldLogic->handleAddonField($this->arctype_channel_id, $post['addonField']);
  283. }
  284. /*--end*/
  285. $newData = array(
  286. 'dirname' => $dirname,
  287. 'dirpath' => $dirpath,
  288. 'typelink' => $typelink,
  289. 'litpic' => $litpic,
  290. 'channeltype' => $channeltype,
  291. 'grade' => $grade,
  292. 'seo_keywords' => str_replace(',', ',', $post['seo_keywords']),
  293. 'seo_description' => $seo_description,
  294. 'lang' => $this->admin_lang,
  295. 'update_time' => getTime(),
  296. );
  297. $data = array_merge($post, $newData, $addonField);
  298. $r = model('Arctype')->updateData($data);
  299. if($r){
  300. //查出该栏目所有子级,包括自己
  301. $hasChildrenRow = model('Arctype')->getHasChildren($post['id'], true);
  302. /*当前栏目以及所有子孙栏目的静态HTML保存路径的变动、模板继承*/
  303. $subSaveData = [];
  304. foreach ($hasChildrenRow as $key => $val) {
  305. $dirpathArr = explode('/', trim($val['dirpath'], '/'));
  306. $dirpathArr[$grade] = $dirname;
  307. $dirpath = '/'.implode('/', $dirpathArr);
  308. $subSaveData_tmp = [
  309. 'id' => $val['id'],
  310. 'dirpath' => $dirpath,
  311. 'update_time' => getTime(),
  312. ];
  313. /*父级模板继承*/
  314. if (!empty($post['inherit_status']) && $post['inherit_status'] == 1) {
  315. $subSaveData_tmp['templist'] = $post['templist'];
  316. $subSaveData_tmp['tempview'] = $post['tempview'];
  317. }
  318. /*end*/
  319. $subSaveData[] = $subSaveData_tmp;
  320. }
  321. if (!empty($subSaveData)) {
  322. model('Arctype')->saveAll($subSaveData);
  323. }
  324. /*end*/
  325. adminLog('编辑栏目:'.$data['typename']);
  326. // 生成静态页面代码
  327. $this->success("操作成功!", url('Arctype/index', ['typeid'=>$post['id']]));
  328. exit;
  329. }
  330. }
  331. $this->error("操作失败!");
  332. exit;
  333. }
  334. $assign_data = array();
  335. $id = input('id/d');
  336. $info = M('arctype')->where([
  337. 'id' => $id,
  338. 'lang' => $this->admin_lang,
  339. ])->find();
  340. if (empty($info)) {
  341. $this->error('数据不存在,请联系管理员!');
  342. exit;
  343. }
  344. // 栏目图片处理
  345. if (is_http_url($info['litpic'])) {
  346. $info['is_remote'] = 1;
  347. $info['litpic_remote'] = handle_subdir_pic($info['litpic']);
  348. } else {
  349. $info['is_remote'] = 0;
  350. $info['litpic_local'] = handle_subdir_pic($info['litpic']);
  351. }
  352. $this->assign('field',$info);
  353. // 获得上级目录路径
  354. if (!empty($info['dirpath'])) {
  355. $predirpath = preg_replace('/\/([^\/]*)$/i', '', $info['dirpath']);
  356. } else {
  357. $predirpath = ''; // 生成静态页面代码
  358. }
  359. $this->assign('predirpath',$predirpath);
  360. // 是否有子栏目
  361. $hasChildren = model('Arctype')->hasChildren($id);
  362. if ($hasChildren > 0) {
  363. $select_html = M('arctype')->where('id', $info['parent_id'])->getField('typename');
  364. $select_html = !empty($select_html) ? $select_html : '顶级栏目';
  365. } else {
  366. // 所属栏目
  367. // $channeltype = $info['channeltype'];
  368. $select_html = '<option value="0" data-grade="-1" data-dirpath="' . tpCache('seo.seo_html_arcdir') . '">顶级栏目</option>';
  369. $selected = $info['parent_id'];
  370. $arctype_max_level = intval(config('global.arctype_max_level'));
  371. $arctypeWhere = ['is_del' => 0];
  372. $options = $this->arctypeLogic->arctype_list(0, $selected, false, $arctype_max_level - 1, $arctypeWhere);
  373. foreach ($options AS $var)
  374. {
  375. $select_html .= '<option value="' . $var['id'] . '" data-grade="' . $var['grade'] . '" data-dirpath="'.$var['dirpath'].'"';
  376. $select_html .= ($selected == $var['id']) ? "selected='ture'" : '';
  377. $select_html .= ($id == $var['id']) ? "disabled='ture' style='background-color:#f5f5f5;' " : '';
  378. $select_html .= '>';
  379. if ($var['level'] > 0)
  380. {
  381. $select_html .= str_repeat('&nbsp;', $var['level'] * 4);
  382. }
  383. $select_html .= htmlspecialchars(addslashes($var['typename'])) . '</option>';
  384. }
  385. }
  386. $this->assign('select_html',$select_html);
  387. $this->assign('hasChildren',$hasChildren);
  388. /* 模型 */
  389. $channeltype_list = model('Channeltype')->getAll('id,title,nid,ctl_name', [], 'id');
  390. // 模型对应模板文件不存在报错
  391. if (!isset($channeltype_list[$info['current_channel']])) {
  392. $row = model('Channeltype')->getInfo($info['current_channel']);
  393. $file = 'lists_'.$row['nid'].'.htm';
  394. $this->error($row['title'].'缺少模板文件'.$file);
  395. }
  396. // 选项卡内容的链接
  397. $ctl_name = $channeltype_list[$info['current_channel']]['ctl_name'];
  398. $list_url = url("{$ctl_name}/index")."?typeid={$id}";
  399. $this->assign('list_url', $list_url);
  400. $this->assign('channeltype_list', $channeltype_list);
  401. /*发布文档的模型ID,用于是否显示文档模板列表*/
  402. $js_allow_channel_arr = '[';
  403. foreach ($this->allowReleaseChannel as $key => $val) {
  404. if ($key > 0) {
  405. $js_allow_channel_arr .= ',';
  406. }
  407. $js_allow_channel_arr .= $val;
  408. }
  409. $js_allow_channel_arr = $js_allow_channel_arr.']';
  410. $this->assign('js_allow_channel_arr', $js_allow_channel_arr);
  411. /*--end*/
  412. /*选项卡*/
  413. $tab = input('param.tab/d', 1);
  414. $this->assign('tab', $tab);
  415. /*--end*/
  416. /*模板列表*/
  417. $templateList = $this->ajax_getTemplateList('edit', $info['templist'], $info['tempview']);
  418. $this->assign('templateList', $templateList);
  419. /*--end*/
  420. /*自定义字段*/
  421. $assign_data['addonFieldExtList'] = model('Field')->getTabelFieldList(config('global.arctype_channel_id'), $id);
  422. $assign_data['aid'] = $id;
  423. $assign_data['channeltype'] = 6;
  424. $assign_data['nid'] = 'arctype';
  425. /*--end*/
  426. $this->assign($assign_data);
  427. return $this->fetch();
  428. }
  429. /**
  430. * 内容管理
  431. */
  432. public function single_edit()
  433. {
  434. if (IS_POST) {
  435. $post = input('post.');
  436. $typeid = input('post.typeid/d', 0);
  437. if(!empty($typeid)){
  438. $info = M('arctype')->field('id,typename,current_channel')
  439. ->where([
  440. 'id' => $typeid,
  441. 'lang' => $this->admin_lang,
  442. ])->find();
  443. $aid = M('archives')->where([
  444. 'typeid' => $typeid,
  445. 'channel' => 6,
  446. 'lang' => $this->admin_lang,
  447. ])->getField('aid');
  448. /*修复新增单页栏目的关联数据不完善,进行修复*/
  449. if (empty($aid)) {
  450. $archivesData = array(
  451. 'title' => $info['typename'],
  452. 'typeid'=> $info['id'],
  453. 'channel' => $info['current_channel'],
  454. 'sort_order' => 100,
  455. 'add_time' => getTime(),
  456. 'update_time' => getTime(),
  457. 'lang' => $this->admin_lang,
  458. );
  459. $aid = M('archives')->insertGetId($archivesData);
  460. }
  461. /*--end*/
  462. if (!isset($post['addonFieldExt'])) {
  463. $post['addonFieldExt'] = array();
  464. }
  465. $updateData = array(
  466. 'aid' => $aid,
  467. 'typename' => $info['typename'],
  468. 'addonFieldExt' => $post['addonFieldExt'],
  469. );
  470. model('Single')->afterSave($aid, $updateData, 'edit');
  471. \think\Cache::clear("arctype");
  472. adminLog('编辑栏目:'.$info['typename']);
  473. // 生成静态页面代码
  474. $this->success("操作成功!", $post['gourl'].'&typeid='.$typeid);
  475. exit;
  476. }
  477. $this->error("操作失败!");
  478. exit;
  479. }
  480. $assign_data = array();
  481. $typeid = input('typeid/d');
  482. $info = M('arctype')->where([
  483. 'id' => $typeid,
  484. 'lang' => $this->admin_lang,
  485. ])->find();
  486. if (empty($info)) {
  487. $this->error('数据不存在,请联系管理员!');
  488. exit;
  489. }
  490. $assign_data['info'] = $info;
  491. /*自定义字段*/
  492. $addonFieldExtList = model('Field')->getChannelFieldList(6, 0, $typeid, $info);
  493. $channelfieldBindRow = Db::name('channelfield_bind')->where([
  494. 'typeid' => ['IN', [0,$typeid]],
  495. ])->column('field_id');
  496. if (!empty($channelfieldBindRow)) {
  497. foreach ($addonFieldExtList as $key => $val) {
  498. if (!in_array($val['id'], $channelfieldBindRow)) {
  499. unset($addonFieldExtList[$key]);
  500. }
  501. }
  502. }
  503. $assign_data['addonFieldExtList'] = $addonFieldExtList;
  504. $assign_data['aid'] = $typeid;
  505. $assign_data['channeltype'] = 6;
  506. $assign_data['nid'] = 'single';
  507. /*--end*/
  508. /*返回上一层*/
  509. $gourl = input('param.gourl/s', '');
  510. if (empty($gourl)) {
  511. $gourl = url('Arctype/index');
  512. }
  513. $assign_data['gourl'] = $gourl;
  514. /*--end*/
  515. $this->assign($assign_data);
  516. /* 生成静态页面代码 */
  517. $this->assign('typeid',$typeid);
  518. /* end */
  519. return $this->fetch();
  520. }
  521. /**
  522. * 伪删除
  523. */
  524. public function pseudo_del()
  525. {
  526. if (IS_POST) {
  527. $this->language_access(); // 多语言功能操作权限
  528. $post = input('post.');
  529. $post['del_id'] = eyIntval($post['del_id']);
  530. /*当前栏目信息*/
  531. $row = M('arctype')->field('id, current_channel, typename')
  532. ->where([
  533. 'id' => $post['del_id'],
  534. 'lang' => $this->admin_lang,
  535. ])
  536. ->find();
  537. $r = model('arctype')->pseudo_del($post['del_id']);
  538. if (false !== $r) {
  539. adminLog('伪删除栏目:'.$row['typename']);
  540. $this->success('删除成功');
  541. } else {
  542. $this->error('删除失败');
  543. }
  544. }
  545. $this->error('非法访问');
  546. }
  547. /**
  548. * 删除[1.2.7之后废弃]
  549. */
  550. public function del()
  551. {
  552. $this->language_access(); // 多语言功能操作权限
  553. $post = input('post.');
  554. $post['del_id'] = eyIntval($post['del_id']);
  555. /*当前栏目信息*/
  556. $row = M('arctype')->field('id, current_channel, typename')
  557. ->where([
  558. 'id' => $post['del_id'],
  559. 'lang' => $this->admin_lang,
  560. ])
  561. ->find();
  562. $r = model('arctype')->del($post['del_id']);
  563. if (false !== $r) {
  564. adminLog('删除栏目:'.$row['typename']);
  565. $this->success('删除成功');
  566. } else {
  567. $this->error('删除失败');
  568. }
  569. }
  570. /**
  571. * 通过模型获取栏目
  572. */
  573. public function ajax_get_arctype($channeltype = 0)
  574. {
  575. $arctype_max_level = intval(config('global.arctype_max_level'));
  576. $options = $this->arctypeLogic->arctype_list(0, 0, false, $arctype_max_level, array('channeltype' => $channeltype));
  577. $select_html = '<option value="0" data-grade="-1">顶级栏目</option>';
  578. foreach ($options AS $var)
  579. {
  580. $select_html .= '<option value="' . $var['id'] . '" data-grade="' . $var['grade'] . '" data-dirpath="'.$var['dirpath'].'"';
  581. $select_html .= '>';
  582. if ($var['level'] > 0)
  583. {
  584. $select_html .= str_repeat('&nbsp;', $var['level'] * 4);
  585. }
  586. $select_html .= htmlspecialchars(addslashes($var['typename'])) . '</option>';
  587. }
  588. $returndata = array(
  589. 'status' => 1,
  590. 'select_html' => $select_html,
  591. );
  592. respose($returndata);
  593. }
  594. /**
  595. * 获取栏目的拼音
  596. */
  597. public function ajax_get_dirpinyin($typename = '')
  598. {
  599. $typename = input('post.typename/s');
  600. $pinyin = get_pinyin($typename);
  601. respose(array(
  602. 'status' => 1,
  603. 'msg' => $pinyin
  604. ));
  605. }
  606. /**
  607. * 检测文件保存目录是否存在
  608. */
  609. public function ajax_check_dirpath()
  610. {
  611. $dirpath = input('post.dirpath/s');
  612. $id = input('post.id/d');
  613. $map = array(
  614. 'dirpath' => $dirpath,
  615. 'lang' => $this->admin_lang,
  616. );
  617. if (intval($id) > 0) {
  618. $map['id'] = array('neq', $id);
  619. }
  620. $result = M('arctype')->where($map)->find();
  621. if (!empty($result)) {
  622. respose(array(
  623. 'status' => 0,
  624. 'msg' => '文件保存目录已存在,请更改',
  625. ));
  626. } else {
  627. respose(array(
  628. 'status' => 1,
  629. 'msg' => '文件保存目录可用',
  630. ));
  631. }
  632. }
  633. public function ajax_getTemplateList($opt = 'add', $templist = '', $tempview = '')
  634. {
  635. $planPath = 'template/pc';
  636. $dirRes = opendir($planPath);
  637. $view_suffix = config('template.view_suffix');
  638. /*模板PC目录文件列表*/
  639. $templateArr = array();
  640. while($filename = readdir($dirRes))
  641. {
  642. if (in_array($filename, array('.','..'))) {
  643. continue;
  644. }
  645. array_push($templateArr, $filename);
  646. }
  647. !empty($templateArr) && asort($templateArr);
  648. /*--end*/
  649. /*多语言全部标识*/
  650. $markArr = Db::name('language_mark')->column('mark');
  651. /*--end*/
  652. $templateList = array();
  653. $channelList = model('Channeltype')->getAll();
  654. foreach ($channelList as $k1 => $v1) {
  655. $l = 1;
  656. $v = 1;
  657. $lists = ''; // 销毁列表模板
  658. $view = ''; // 销毁文档模板
  659. $templateList[$v1['id']] = array();
  660. foreach ($templateArr as $k2 => $v2) {
  661. $v2 = iconv('GB2312', 'UTF-8', $v2);
  662. if ('add' == $opt) {
  663. $selected = 0; // 默认选中状态
  664. } else {
  665. $selected = 1; // 默认选中状态
  666. }
  667. preg_match('/^(lists|view)_'.$v1['nid'].'(_(.*))?(_'.$this->admin_lang.')?\.'.$view_suffix.'/i', $v2, $matches1);
  668. $langtpl = preg_replace('/\.'.$view_suffix.'$/i', "_{$this->admin_lang}.{$view_suffix}", $v2);
  669. if (file_exists(realpath($planPath.DS.$langtpl))) {
  670. continue;
  671. } else if (preg_match('/^(.*)_([a-zA-z]{2,2})\.'.$view_suffix.'$/i',$v2,$matches2)) {
  672. if (in_array($matches2[2], $markArr) && $matches2[2] != $this->admin_lang) {
  673. continue;
  674. }
  675. }
  676. if (!empty($matches1)) {
  677. $selectefile = '';
  678. if ('lists' == $matches1[1]) {
  679. $lists .= '<option value="'.$v2.'" ';
  680. $lists .= ($templist == $v2 || $selected == $l) ? " selected='true' " : '';
  681. $lists .= '>'.$v2.'</option>';
  682. $l++;
  683. } else if ('view' == $matches1[1]) {
  684. $view .= '<option value="'.$v2.'" ';
  685. $view .= ($tempview == $v2 || $selected == $v) ? " selected='true' " : '';
  686. $view .= '>'.$v2.'</option>';
  687. $v++;
  688. }
  689. }
  690. }
  691. $nofileArr = [];
  692. if ('add' == $opt) {
  693. if (empty($lists)) {
  694. $lists = '<option value="">无</option>';
  695. $nofileArr[] = "lists_{$v1['nid']}.{$view_suffix}";
  696. }
  697. if (empty($view)) {
  698. $view = '<option value="">无</option>';
  699. if (!in_array($v1['nid'], ['single','guestbook'])) {
  700. $nofileArr[] = "view_{$v1['nid']}.{$view_suffix}";
  701. }
  702. }
  703. } else {
  704. if (empty($lists)) {
  705. $nofileArr[] = "lists_{$v1['nid']}.{$view_suffix}";
  706. }
  707. $lists = '<option value="">请选择模板…</option>'.$lists;
  708. if (empty($view)) {
  709. if (!in_array($v1['nid'], ['single','guestbook'])) {
  710. $nofileArr[] = "view_{$v1['nid']}.{$view_suffix}";
  711. }
  712. }
  713. $view = '<option value="">请选择模板…</option>'.$view;
  714. }
  715. $msg = '';
  716. if (!empty($nofileArr)) {
  717. $msg = '<font color="red">该模型缺少模板文件:'.implode(' 和 ', $nofileArr).'</font>';
  718. }
  719. $templateList[$v1['id']] = array(
  720. 'lists' => $lists,
  721. 'view' => $view,
  722. 'msg' => $msg,
  723. 'nid' => $v1['nid'],
  724. );
  725. }
  726. if (IS_AJAX) {
  727. $this->success('请求成功', null, ['templateList'=>$templateList]);
  728. } else {
  729. return $templateList;
  730. }
  731. }
  732. /**
  733. * 新建模板文件
  734. */
  735. public function ajax_newtpl()
  736. {
  737. if (IS_POST) {
  738. $post = input('post.', '', null);
  739. $content = input('post.content', '', null);
  740. $view_suffix = config('template.view_suffix');
  741. if (!empty($post['filename'])) {
  742. if (!preg_match("/^[\w\-\_]{1,}$/u", $post['filename'])) {
  743. $this->error('文件名称只允许字母、数字、下划线、连接符的任意组合!');
  744. }
  745. $filename = "{$post['type']}_{$post['nid']}_{$post['filename']}.{$view_suffix}";
  746. } else {
  747. $filename = "{$post['type']}_{$post['nid']}.{$view_suffix}";
  748. }
  749. $content = !empty($content) ? $content : '';
  750. $tpldirpath = !empty($post['tpldir']) ? '/template/'.trim($post['tpldir']) : '/template/pc';
  751. if (file_exists(ROOT_PATH.ltrim($tpldirpath, '/').'/'.$filename)) {
  752. $this->error('文件名称已经存在,请重新命名!', null, ['focus'=>'filename']);
  753. }
  754. $nosubmit = input('param.nosubmit/d');
  755. if (1 == $nosubmit) {
  756. $this->success('检测通过');
  757. }
  758. $filemanagerLogic = new \app\admin\logic\FilemanagerLogic;
  759. $r = $filemanagerLogic->editFile($filename, $tpldirpath, $content);
  760. if ($r === true) {
  761. $this->success('操作成功', null, ['filename'=>$filename,'type'=>$post['type']]);
  762. } else {
  763. $this->error($r);
  764. }
  765. }
  766. $type = input('param.type/s');
  767. $nid = input('param.nid/s');
  768. $tpldirList = glob('template/*');
  769. foreach ($tpldirList as $key => $val) {
  770. if (!preg_match('/template\/(pc|mobile)$/i', $val)) {
  771. unset($tpldirList[$key]);
  772. } else {
  773. $tpldirList[$key] = preg_replace('/^(.*)template\/(pc|mobile)$/i', '$2', $val);
  774. }
  775. }
  776. !empty($tpldirList) && arsort($tpldirList);
  777. $this->assign('tpldirList', $tpldirList);
  778. $this->assign('type', $type);
  779. $this->assign('nid', $nid);
  780. return $this->fetch();
  781. }
  782. /**
  783. * 批量增加栏目
  784. */
  785. public function batch_add()
  786. {
  787. //防止php超时
  788. function_exists('set_time_limit') && set_time_limit(0);
  789. $this->language_access(); // 多语言功能操作权限
  790. if (IS_POST) {
  791. $post = input('post.');
  792. if ($post) {
  793. if (empty($post['parent_id'])) { // 增加顶级栏目
  794. foreach ($post['toptype'] as $key => $val) {
  795. $val = trim($val);
  796. if (empty($val)) {
  797. unset($post['toptype'][$key]);
  798. }
  799. }
  800. if (empty($post['toptype'])) {
  801. $this->error('顶级栏目名称不能为空!');
  802. }
  803. $this->batch_add_toptype($post);
  804. }
  805. else { // 增加下级栏目
  806. foreach ($post['reltype'] as $key => $val) {
  807. $val = trim($val);
  808. if (empty($val)) {
  809. unset($post['reltype'][$key]);
  810. }
  811. }
  812. if (empty($post['reltype'])) {
  813. $this->error('栏目名称不能为空!');
  814. }
  815. $this->batch_add_subtype($post);
  816. }
  817. }
  818. $this->error("操作失败!");
  819. exit;
  820. }
  821. /* 模型 */
  822. $map = array(
  823. 'status' => 1,
  824. );
  825. $channeltype_list = model('Channeltype')->getAll('id,title,nid', $map, 'id');
  826. $this->assign('channeltype_list', $channeltype_list);
  827. /*发布文档的模型ID,用于是否显示文档模板列表*/
  828. $js_allow_channel_arr = '[';
  829. foreach ($this->allowReleaseChannel as $key => $val) {
  830. if ($key > 0) {
  831. $js_allow_channel_arr .= ',';
  832. }
  833. $js_allow_channel_arr .= $val;
  834. }
  835. $js_allow_channel_arr = $js_allow_channel_arr.']';
  836. $this->assign('js_allow_channel_arr', $js_allow_channel_arr);
  837. /*--end*/
  838. // 所属栏目
  839. $select_html = '<option value="0" data-grade="-1" data-dirpath="'.tpCache('seo.seo_html_arcdir').'">顶级栏目</option>';
  840. $selected = 0;
  841. $arctype_max_level = intval(config('global.arctype_max_level'));
  842. $arctypeWhere = ['is_del'=>0];
  843. $options = $this->arctypeLogic->arctype_list(0, $selected, false, $arctype_max_level - 1, $arctypeWhere);
  844. foreach ($options AS $var)
  845. {
  846. $select_html .= '<option value="' . $var['id'] . '" data-grade="' . $var['grade'] . '" data-dirpath="'.$var['dirpath'].'">';
  847. if ($var['level'] > 0)
  848. {
  849. $select_html .= str_repeat('&nbsp;', $var['level'] * 4);
  850. }
  851. $select_html .= htmlspecialchars(addslashes($var['typename'])) . '</option>';
  852. }
  853. $this->assign('select_html',$select_html);
  854. /*模板列表*/
  855. $templateList = $this->ajax_getTemplateList('add');
  856. $this->assign('templateList', $templateList);
  857. /*--end*/
  858. $dirpath = tpCache('seo.seo_html_arcdir');
  859. $this->assign('dirpath', $dirpath);
  860. return $this->fetch();
  861. }
  862. /**
  863. * 批量增加顶级栏目
  864. */
  865. private function batch_add_toptype($post = [])
  866. {
  867. $saveData = [];
  868. $dirnameArr = [];
  869. foreach ($post['toptype'] as $key => $val) {
  870. $typename = func_preg_replace([',',','], '', trim($val));
  871. if (empty($typename)) continue;
  872. // 子栏目
  873. if (!empty($post['sontype'][$key])) {
  874. $sontype = str_replace(',', ',', $post['sontype'][$key]);
  875. $post['sontype'][$key] = explode(',', $sontype);
  876. }
  877. // 目录名称
  878. $dirname = $this->arctypeLogic->get_dirname($typename, '', 0, $dirnameArr);
  879. array_push($dirnameArr, $dirname);
  880. $dirpath = '/'.$dirname;
  881. $data = [
  882. 'typename' => $typename,
  883. 'channeltype' => $post['current_channel'],
  884. 'current_channel' => $post['current_channel'],
  885. 'parent_id' => 0,
  886. 'dirname' => $dirname,
  887. 'dirpath' => $dirpath,
  888. 'grade' => 0,
  889. 'templist' => !empty($post['templist']) ? $post['templist'] : '',
  890. 'tempview' => !empty($post['tempview']) ? $post['tempview'] : '',
  891. 'is_hidden' => $post['is_hidden'],
  892. 'seo_description' => '',
  893. 'admin_id' => session('admin_info.admin_id'),
  894. 'lang' => $this->admin_lang,
  895. 'sort_order' => !empty($post['sort_order'][$key]) ? intval($post['sort_order'][$key]) : 100,
  896. 'add_time' => getTime(),
  897. 'update_time' => getTime(),
  898. ];
  899. $saveData[] = $data;
  900. }
  901. if (!empty($saveData)) {
  902. $result = model('Arctype')->batchAddTopData($saveData, $post);
  903. if (!empty($result)) {
  904. $typenameArr = get_arr_column($result, 'typename');
  905. $typenameStr = implode(',', $typenameArr);
  906. adminLog('批量增加栏目:'.$typenameStr);
  907. // 生成静态页面代码
  908. $msg = '操作成功!';
  909. $seo_pseudo = config('tpcache.seo_pseudo');
  910. if (2 == $seo_pseudo) {
  911. $msg = '操作成功,请手工生成静态页面!';
  912. }
  913. $this->success($msg, url('Arctype/index'));
  914. exit;
  915. }
  916. }
  917. $this->error("操作失败!");
  918. }
  919. /**
  920. * 批量增加下级栏目
  921. */
  922. private function batch_add_subtype($post = [])
  923. {
  924. // 获取顶级模型ID
  925. $channeltype = Db::name('arctype')->where('id', $post['parent_id'])->getField('channeltype');
  926. $saveData = [];
  927. $dirnameArr = [];
  928. foreach ($post['reltype'] as $key => $val) {
  929. $typename = func_preg_replace([',',','], '', trim($val));
  930. if (empty($typename)) continue;
  931. // 目录名称
  932. $dirname = $this->arctypeLogic->get_dirname($typename, '', 0, $dirnameArr);
  933. array_push($dirnameArr, $dirname);
  934. $dirpath = $post['dirpath'].'/'.$dirname;
  935. $data = [
  936. 'typename' => $typename,
  937. 'channeltype' => $channeltype,
  938. 'current_channel' => $post['current_channel'],
  939. 'parent_id' => intval($post['parent_id']),
  940. 'dirname' => $dirname,
  941. 'dirpath' => $dirpath,
  942. 'grade' => intval($post['grade']),
  943. 'templist' => !empty($post['templist']) ? $post['templist'] : '',
  944. 'tempview' => !empty($post['tempview']) ? $post['tempview'] : '',
  945. 'is_hidden' => $post['is_hidden'],
  946. 'seo_description' => '',
  947. 'admin_id' => session('admin_info.admin_id'),
  948. 'lang' => $this->admin_lang,
  949. 'sort_order' => !empty($post['sort_order_1'][$key]) ? intval($post['sort_order_1'][$key]) : 100,
  950. 'add_time' => getTime(),
  951. 'update_time' => getTime(),
  952. ];
  953. $saveData[] = $data;
  954. }
  955. if (!empty($saveData)) {
  956. $result = model('Arctype')->batchAddSubData($saveData);
  957. if (!empty($result)) {
  958. $typenameArr = get_arr_column($result, 'typename');
  959. $typenameStr = implode(',', $typenameArr);
  960. adminLog('批量增加栏目:'.$typenameStr);
  961. // 生成静态页面代码
  962. $msg = '操作成功!';
  963. $seo_pseudo = config('tpcache.seo_pseudo');
  964. if (2 == $seo_pseudo) {
  965. $msg = '操作成功,请手工生成静态页面!';
  966. }
  967. $this->success($msg, url('Arctype/index'));
  968. exit;
  969. }
  970. }
  971. $this->error("操作失败!");
  972. }
  973. }