Archives.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. <?php
  2. namespace app\index\controller\cms;
  3. use addons\cms\library\FulltextSearch;
  4. use addons\cms\library\IntCode;
  5. use addons\cms\library\Service;
  6. use addons\cms\model\Channel;
  7. use addons\cms\model\Modelx;
  8. use addons\cms\model\Tag;
  9. use app\common\controller\Frontend;
  10. use app\common\model\User;
  11. use fast\Tree;
  12. use think\Db;
  13. use think\Exception;
  14. use think\Validate;
  15. /**
  16. * 会员文档
  17. */
  18. class Archives extends Frontend
  19. {
  20. protected $layout = 'default';
  21. protected $noNeedLogin = [];
  22. protected $noNeedRight = ['*'];
  23. /**
  24. * 发表文章
  25. */
  26. public function post()
  27. {
  28. $config = get_addon_config('cms');
  29. $id = $this->request->get('id');
  30. $id = $config['archiveshashids'] ? IntCode::decode($id) : $id;
  31. $archives = $id ? \app\admin\model\cms\Archives::get($id) : null;
  32. if ($archives) {
  33. $channel = Channel::get($archives['channel_id']);
  34. if (!$channel) {
  35. $this->error(__('未找到指定栏目'));
  36. }
  37. $model = \addons\cms\model\Modelx::get($channel['model_id']);
  38. if (!$model) {
  39. $this->error(__('未找到指定模型'));
  40. }
  41. if ($archives['user_id'] != $this->auth->id) {
  42. $this->error("无法进行越权操作!");
  43. }
  44. } else {
  45. $model = null;
  46. $model_id = $this->request->request('model_id');
  47. // 如果有model_id则调用指定模型
  48. if ($model_id) {
  49. $model = Modelx::get($model_id);
  50. }
  51. }
  52. // 如果来源于提交
  53. if ($this->request->isPost()) {
  54. $this->token();
  55. if (isset($config['limitscore']['postarchives']) && $this->auth->score < $config['limitscore']['postarchives']) {
  56. $this->error("积分必须大于{$config['limitscore']['postarchives']}才可以发布文章");
  57. }
  58. $row = $this->request->post('row/a', '', 'trim,xss_clean');
  59. $rule = [
  60. 'title|标题' => 'require|length:3,100',
  61. 'channel_id|栏目' => 'require|integer',
  62. ];
  63. $msg = [
  64. 'title.require' => '标题不能为空',
  65. 'title.length' => '标题长度限制在3~100个字符',
  66. 'channel_id' => '栏目不能为空',
  67. 'content.require' => '内容不能为空',
  68. ];
  69. $validate = new Validate($rule, $msg);
  70. $result = $validate->check($row);
  71. if (!$result) {
  72. $this->error($validate->getError());
  73. }
  74. $channelIds = isset($row['channel_ids']) ? (is_array($row['channel_ids']) ? $row['channel_ids'] : explode(',', $row['channel_ids'])) : [];
  75. $channelIds = array_merge([$row['channel_id']], $channelIds);
  76. $channelIds = array_filter($channelIds);
  77. $count = Channel::where('id', 'in', $channelIds)->where('iscontribute', 0)->count();
  78. if ($count > 0) {
  79. $this->error("栏目不允许投稿");
  80. }
  81. //审核状态
  82. $status = 'normal';
  83. if ($config['isarchivesaudit'] == 1) {
  84. $status = 'hidden';
  85. } elseif ($config['isarchivesaudit'] == 0) {
  86. $status = 'normal';
  87. } else {
  88. $textArr = array_map(function ($item) {
  89. return is_array($item) ? json_encode($item, JSON_UNESCAPED_UNICODE) : $item;
  90. }, $row);
  91. if (!Service::isContentLegal(implode(' ', $textArr))) {
  92. $status = 'hidden';
  93. }
  94. }
  95. $row['user_id'] = $this->auth->id;
  96. $row['status'] = $status;
  97. $row['publishtime'] = time();
  98. Db::startTrans();
  99. try {
  100. if ($archives) {
  101. $archives->allowField(true)->save($row);
  102. } else {
  103. (new \app\admin\model\cms\Archives)->allowField(true)->save($row);
  104. }
  105. //增加积分
  106. $status == 'normal' && User::score($config['score']['postarchives'], $this->auth->id, '发布文章');
  107. Db::commit();
  108. } catch (Exception $e) {
  109. Db::rollback();
  110. $this->error("发生错误:" . $e->getMessage());
  111. }
  112. if ($status === 'hidden') {
  113. //发送通知
  114. $status === 'hidden' && Service::notice(config('cms.sitename') . '收到一篇新的文章审核');
  115. $this->success("发布成功!请等待审核!");
  116. } else {
  117. $this->success("发布成功!");
  118. }
  119. }
  120. // 合并主副表
  121. if ($archives) {
  122. $addon = db($model['table'])->where('id', $archives['id'])->find();
  123. if ($addon) {
  124. $archives->setData($addon);
  125. }
  126. }
  127. $selectedIds = $archives ? $archives['channel_id'] : '';
  128. if (!$archives && !$model) {
  129. $firstChannel = Channel::where('status', 'normal')->where('iscontribute', 1)->order('weigh DESC,id DESC')->find();
  130. $model = Modelx::get($firstChannel['model_id']);
  131. $selectedIds = $firstChannel['id'];
  132. }
  133. list($channelList, $disabledIds) = Channel::getContributeInfo($archives, $model);
  134. $tree = Tree::instance()->init($channelList, 'parent_id');
  135. $channelOptions = $tree->getTree(0, "<option model='@model_id' value=@id @selected @disabled>@spacer@name</option>", $selectedIds, $disabledIds);
  136. $this->view->assign('channelOptions', $channelOptions);
  137. $this->view->assign([
  138. 'archives' => $archives,
  139. 'channelOptions' => $channelOptions,
  140. 'categoryList' => '',
  141. 'extendHtml' => $this->get_model_extend_html($archives, $model)
  142. ]);
  143. $this->assignconfig('archives_id', $archives ? $archives['id'] : 0);
  144. $tree = Tree::instance()->init($channelList, 'parent_id');
  145. $secondChannelOptions = $tree->getTree(0, "<option model='@model_id' value=@id @selected @disabled>@spacer@name</option>", explode(',', $archives ? $archives['channel_ids'] : ''), $disabledIds);
  146. $this->view->assign('secondChannelOptions', $secondChannelOptions);
  147. $modelName = $model ? $model['name'] : '文章';
  148. $this->view->assign('title', $archives ? "修改{$modelName}" : "发布{$modelName}");
  149. $this->view->assign('model', $model);
  150. return $this->view->fetch();
  151. }
  152. /**
  153. * 我的发布
  154. */
  155. public function my()
  156. {
  157. $archives = new \addons\cms\model\Archives;
  158. $model = null;
  159. $model_id = (int)$this->request->request('model_id');
  160. $channel_id = (int)$this->request->request('channel_id');
  161. $q = $this->request->request('q');
  162. $config = ['query' => []];
  163. // 指定模型
  164. if ($model_id) {
  165. $model = Modelx::get($model_id);
  166. if ($model) {
  167. $archives->where('model_id', $model_id);
  168. $config['query']['model_id'] = $model_id;
  169. }
  170. }
  171. // 搜索关键字
  172. if ($q) {
  173. $archives->where('title|keywords|description', 'like', '%' . $q . '%');
  174. $config['query']['q'] = $q;
  175. }
  176. // 栏目
  177. if ($channel_id) {
  178. $archives->where('channel_id', $channel_id);
  179. $config['query']['channel_id'] = $channel_id;
  180. }
  181. $user_id = $this->auth->id;
  182. $archivesList = $archives->where('user_id', $user_id)
  183. ->order('id', 'desc')
  184. ->paginate(10, null, $config);
  185. $channelList = Channel::where('id', 'in', function ($query) use ($user_id) {
  186. $query->name('cms_archives')->where('user_id', $user_id)->field('channel_id');
  187. })->where('status', 'normal')->select();
  188. $this->view->assign('archivesList', $archivesList);
  189. $this->view->assign('channelList', $channelList);
  190. $this->view->assign('title', '我发布的' . ($model ? $model['name'] : '文档'));
  191. $this->view->assign('model', $model);
  192. return $this->view->fetch();
  193. }
  194. /**
  195. * 删除文档
  196. */
  197. public function delete()
  198. {
  199. $config = get_addon_config('cms');
  200. $id = $this->request->request('id');
  201. $id = $config['archiveshashids'] ? IntCode::decode($id) : $id;
  202. if (!$id) {
  203. $this->error("参数不正确");
  204. }
  205. $archives = \addons\cms\model\Archives::where('id', $id)->where('user_id', $this->auth->id)->find();
  206. if (!$archives) {
  207. $this->error("未找到指定的文档");
  208. }
  209. Db::startTrans();
  210. try {
  211. $archives->delete();
  212. if ($archives->channel->items > 0) {
  213. $archives->channel->setDec("items");
  214. }
  215. Db::commit();
  216. } catch (Exception $e) {
  217. Db::rollback();
  218. $this->error("删除文档失败");
  219. }
  220. $this->success("删除文档成功");
  221. }
  222. /**
  223. * 获取栏目列表
  224. * @internal
  225. */
  226. public function get_channel_fields()
  227. {
  228. $this->view->engine->layout(false);
  229. $channel_id = $this->request->post('channel_id');
  230. $archives_id = $this->request->post('archives_id');
  231. $channel = Channel::get($channel_id, 'model');
  232. if ($channel && $channel['type'] != 'link') {
  233. $archives = null;
  234. $model = null;
  235. $model_id = $channel['model_id'];
  236. if ($archives_id) {
  237. $archives = \app\admin\model\cms\Archives::get($archives_id);
  238. $model_id = $archives ? $archives['model_id'] : $model_id;
  239. }
  240. $model = Modelx::get($model_id);
  241. $setting = $model->setting ?? [];
  242. $html = $this->get_model_extend_html($archives, $model);
  243. $this->success('', null, ['contributefields' => $setting['contributefields'] ?? [], 'html' => $html]);
  244. } else {
  245. $this->error(__('请选择栏目'));
  246. }
  247. $this->error(__('参数不能为空', 'ids'));
  248. }
  249. /**
  250. * 获取模型的扩展HTML
  251. * @internal
  252. */
  253. protected function get_model_extend_html($archives, $model)
  254. {
  255. if (!$archives && !$model) {
  256. return '';
  257. }
  258. $fields = [];
  259. $values = [];
  260. if ($archives) {
  261. $model = $model ? $model : Modelx::get($archives['model_id']);
  262. $values = db($model['table'])->where('id', $archives['id'])->find();
  263. }
  264. $fields = Service::getCustomFields('model', $model['id'], $values, ['iscontribute' => 1]);
  265. return $this->view->fetch('cms/common/fields', ['fields' => $fields, 'values' => $values]);
  266. }
  267. /**
  268. * 标签自动完成
  269. * @internal
  270. */
  271. public function tags_autocomplete()
  272. {
  273. $q = $this->request->request('q');
  274. $list = \addons\cms\model\Tag::where('name', 'like', '%' . $q . '%')->limit(10)->column('name');
  275. echo json_encode($list);
  276. return;
  277. }
  278. /**
  279. * 搜索建议
  280. * @internal
  281. */
  282. public function suggestion()
  283. {
  284. $q = trim($this->request->request("q"));
  285. $id = trim($this->request->request("id/d"));
  286. $list = [];
  287. $result = \addons\cms\model\Archives::where("title|keywords|description", "like", "%{$q}%")->where('id', '<>', $id)->limit(10)->order("id", "desc")->select();
  288. foreach ($result as $index => $item) {
  289. $list[] = ['id' => $item['id'], 'url' => $item['fullurl'], 'image' => cdnurl($item['image']), 'title' => $item['title'], 'create_date' => datetime($item['createtime'])];
  290. }
  291. return json($list);
  292. }
  293. }