ArticleController.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: chenkuan
  5. * Date: 2017/11/9
  6. * Time: 上午10:39
  7. */
  8. namespace frontend\controllers;
  9. use common\helpers\PaginationHelper;
  10. use common\helpers\ValidatorHelper;
  11. use frontend\models\Article;
  12. use frontend\models\ArticleCategory;
  13. use Symfony\Component\Yaml\Tests\A;
  14. use yii\data\Pagination;
  15. /**
  16. * 注:article表的is_publication,is_recommend,is_top的数据类型是bit(1),在线上不能按常规的判断方式判断,所以在这里先转换
  17. * 刚开始使用的是CONVERT函数,但是当select方法的参数是字符串时,select方法会根据逗号分隔成数据,CONVERT函数的两个参数之间有逗号,所以不能正确地转换成数据,解决办法是使用CAST函数或调用select方法时传入数组
  18. *
  19. * CONVERT(is_top, SIGNED) AS is_top 第一个参数是字段,第二个是要转换的类型,AS取别名,Mysql函数有多个参数时,不要传字符串到select方法
  20. * CAST(is_top AS SIGNED) AS is_top 第一个AS是类型转换,第二个AS是取别名
  21. *
  22. * @see \yii\db\Query::select()
  23. * @see https://dev.mysql.com/doc/refman/5.6/en/type-conversion.html
  24. * @see https://dev.mysql.com/doc/refman/5.6/en/cast-functions.html
  25. */
  26. class ArticleController extends BaseController
  27. {
  28. /**
  29. * 前台首页公告/动态/汇评列表获取接口
  30. * 1:Announcement
  31. * 2:Devisenmarkt
  32. * 5:ReviewAnalysis
  33. */
  34. public function actionGetArticleList()
  35. {
  36. $request = \Yii::$app->request;
  37. $articleCategory = $request->get('id',1);
  38. $language = $request->get('language', 0);
  39. $type = $request->get('type', '');
  40. $isContainChildren = $request->get('isContainChildren', true);
  41. $pageNumber = $request->get('pageNumber', 1);
  42. $pageSize = $request->get('pageSize', 10);
  43. $offset = 0;
  44. if ($pageNumber > 1) {
  45. $offset = ($pageNumber - 1) * $pageSize;
  46. }
  47. $ac = ArticleCategory::findOne(['id' => $articleCategory]);
  48. $query = Article::find()->alias('a')
  49. ->leftJoin('bit_article_category ac', 'a.article_category_id = ac.id');
  50. if ($articleCategory != null) {
  51. if (strcasecmp($type, 'top') == 0) {
  52. if ($isContainChildren) {
  53. $query->andWhere([
  54. 'a.is_publication' => 1,
  55. 'a.is_top' => 1,
  56. ])->andWhere(['like', 'ac.path', $ac->path.'%', false])->orderBy([
  57. 'a.is_top' => SORT_DESC,
  58. 'a.create_date' => SORT_DESC,
  59. ]);
  60. } else {
  61. $query->andWhere([
  62. 'a.is_publication' => 1,
  63. 'a.is_top' => 1,
  64. 'a.article_category_id' => $articleCategory,
  65. ])->orderBy([
  66. 'a.is_top' => SORT_DESC,
  67. 'a.create_date' => SORT_DESC,
  68. ]);
  69. }
  70. } elseif (strcasecmp($type, 'recommend') == 0) {
  71. if ($isContainChildren) {
  72. $query->andWhere([
  73. 'a.is_publication' => 1,
  74. 'a.is_recommend' => 1,
  75. ])->andWhere(['like', 'ac.path', $ac->path.'%', false])->orderBy([
  76. 'a.is_top' => SORT_DESC,
  77. 'a.create_date' => SORT_DESC,
  78. ]);
  79. } else {
  80. $query->andWhere([
  81. 'a.is_publication' => 1,
  82. 'a.is_recommend' => 1,
  83. 'a.article_category_id' => $articleCategory,
  84. ])->orderBy([
  85. 'a.is_top' => SORT_DESC,
  86. 'a.create_date' => SORT_DESC,
  87. ]);
  88. }
  89. } elseif (strcasecmp($type, 'hot') == 0) {
  90. if ($isContainChildren) {
  91. $query->andWhere([
  92. 'a.is_publication' => 1,
  93. ])->andWhere(['like', 'ac.path', $ac->path.'%', false])->orderBy([
  94. 'a.hits' => SORT_DESC,
  95. 'a.create_date' => SORT_DESC,
  96. ]);
  97. } else {
  98. $query->andWhere([
  99. 'a.is_publication' => 1,
  100. 'a.article_category_id' => $articleCategory,
  101. ])->orderBy([
  102. 'a.hits' => SORT_DESC,
  103. 'a.create_date' => SORT_DESC,
  104. ]);
  105. }
  106. } elseif (strcasecmp($type, 'img') == 0) {
  107. if ($isContainChildren) {
  108. $query->andWhere([
  109. 'a.is_publication' => 1,
  110. ])->andWhere(['NOT', ['a.image_path' => null]])->andWhere(
  111. ['like', 'ac.path', $ac->path.'%', false]
  112. )->orderBy([
  113. 'a.create_date' => SORT_DESC,
  114. ]);
  115. } else {
  116. $query->andWhere([
  117. 'a.is_publication' => 1,
  118. 'a.article_category_id' => $articleCategory,
  119. ])->andWhere(['NOT', ['a.image_path' => null]])->orderBy([
  120. 'a.hits' => SORT_DESC,
  121. 'a.create_date' => SORT_DESC,
  122. ]);
  123. }
  124. } elseif ($isContainChildren) {
  125. $query->andWhere([
  126. 'a.is_publication' => 1,
  127. ])->andWhere(
  128. ['like', 'ac.path', $ac->path.'%', false]
  129. )->orderBy([
  130. 'a.is_top' => SORT_DESC,
  131. 'a.create_date' => SORT_DESC,
  132. ]);
  133. } else {
  134. $query->andWhere([
  135. 'a.is_publication' => 1,
  136. 'a.article_category_id' => $articleCategory,
  137. ])->orderBy([
  138. 'a.is_top' => SORT_DESC,
  139. 'a.create_date' => SORT_DESC,
  140. ]);
  141. }
  142. } elseif (strcasecmp($type, 'top') == 0) {
  143. $query->andWhere([
  144. 'a.is_publication' => 1,
  145. 'a.is_top' => 1,
  146. ])->orderBy([
  147. 'a.is_top' => SORT_DESC,
  148. 'a.create_date' => SORT_DESC,
  149. ]);
  150. } elseif (strcasecmp($type, 'recommend') == 0) {
  151. $query->andWhere([
  152. 'a.is_publication' => 1,
  153. 'a.is_recommend' => 1,
  154. ])->orderBy([
  155. 'a.is_top' => SORT_DESC,
  156. 'a.create_date' => SORT_DESC,
  157. ]);
  158. } elseif (strcasecmp($type, 'hot') == 0) {
  159. $query->andWhere([
  160. 'a.is_publication' => 1,
  161. ])->orderBy([
  162. 'a.hits' => SORT_DESC,
  163. 'a.create_date' => SORT_DESC,
  164. ]);
  165. } elseif (strcasecmp($type, 'img') == 0) {
  166. $query->andWhere([
  167. 'a.is_publication' => 1,
  168. ])->andWhere(
  169. ['NOT', ['a.image_path' => null]]
  170. )->orderBy([
  171. 'a.create_date' => SORT_DESC,
  172. ]);
  173. } else {
  174. $query->andWhere([
  175. 'a.is_publication' => 1,
  176. ])->orderBy([
  177. 'a.is_top' => SORT_DESC,
  178. 'a.create_date' => SORT_DESC,
  179. ]);
  180. }
  181. $countQuery = clone $query;
  182. $count = (int)$countQuery->select('count(*)')->scalar();
  183. switch($language){
  184. case 0:
  185. $query->select('a.id, CAST(is_publication AS SIGNED) AS is_publication, CAST(is_recommend AS SIGNED) AS is_recommend, CAST(is_top AS SIGNED) AS is_top,a.create_date,
  186. a.article_category_id,a.hits,a.image_path,a.title,a.link_url,
  187. a.min_content,a.content,ac.name,
  188. ac.path');
  189. break;
  190. case 1:
  191. $query->select('a.id, CAST(is_publication AS SIGNED) AS is_publication, CAST(is_recommend AS SIGNED) AS is_recommend, CAST(is_top AS SIGNED) AS is_top,a.create_date,
  192. a.article_category_id,a.hits,a.image_path,a.title1,a.link_url,
  193. a.min_content1,a.content1,ac.name,
  194. ac.path');
  195. break;
  196. case 2:
  197. $query->select('a.id, CAST(is_publication AS SIGNED) AS is_publication, CAST(is_recommend AS SIGNED) AS is_recommend, CAST(is_top AS SIGNED) AS is_top,a.create_date,
  198. a.article_category_id,a.hits,a.image_path,a.title2,a.link_url,
  199. a.min_content2,a.content2,ac.name,
  200. ac.path');
  201. break;
  202. default:
  203. break;
  204. }
  205. $query->offset($offset)->limit($pageSize);
  206. $result['data'] = $query->asArray()->all();
  207. switch($language){
  208. case 1:
  209. foreach($result['data'] as $k => $v){
  210. $result['data'][$k]['title'] = $v['title1'];
  211. $result['data'][$k]['min_content'] = $v['min_content1'];
  212. $result['data'][$k]['content'] = $v['content1'];
  213. }
  214. break;
  215. case 2:
  216. foreach($result['data'] as $k => $v){
  217. $result['data'][$k]['title'] = $v['title2'];
  218. $result['data'][$k]['min_content'] = $v['min_content2'];
  219. $result['data'][$k]['content'] = $v['content2'];
  220. }
  221. break;
  222. default:
  223. break;
  224. }
  225. $result['totalCount'] = $count;
  226. return $this->outJson(1, $result);
  227. }
  228. /**
  229. * 文章详情
  230. */
  231. public function actionArticleDetail()
  232. {
  233. $result = [];
  234. $articleId = \Yii::$app->request->get('id');
  235. $language = \Yii::$app->request->get('language');
  236. $model = Article::find()->alias('a')
  237. ->leftJoin(ArticleCategory::tableName().' ac', 'a.article_category_id = ac.id')
  238. ->select([
  239. 'a.*',
  240. 'CONVERT(a.is_publication, SIGNED) AS is_publication',
  241. 'CONVERT(a.is_recommend, SIGNED) AS is_recommend',
  242. 'CONVERT(a.is_top, SIGNED) AS is_top',
  243. 'ac.name AS category_name'
  244. ])->where(['a.id' => $articleId]);
  245. $modelClone = clone $model;
  246. $article = $modelClone->one();
  247. if ($article) {
  248. $article->hits += 1;
  249. $article->save();
  250. $result['article'] = $modelClone->asArray()->one();
  251. switch($language){
  252. case 1:
  253. $result['article']['title'] = $article['title1'];
  254. $result['article']['sub_title'] = $article['sub_title1'];
  255. $result['article']['content'] = $article['content1'];
  256. $result['article']['min_content'] = $article['min_content1'];
  257. $result['article']['author'] = $article['author1'];
  258. break;
  259. case 2:
  260. $result['article']['title'] = $article['title2'];
  261. $result['article']['sub_title'] = $article['sub_title2'];
  262. $result['article']['content'] = $article['content2'];
  263. $result['article']['min_content'] = $article['min_content2'];
  264. $result['article']['author'] = $article['author2'];
  265. break;
  266. default:
  267. break;
  268. }
  269. $result['nextArticle'] = $this->getNextArticle($article);
  270. $result['previousArticle'] = $this->getPreviousArticle($article);
  271. $result['relationArticle'] = $this->getRelationArticle($article);
  272. return $this->outJson(1, $result);
  273. } else {
  274. return $this->outJson(0, [], '获取文章详情失败');
  275. }
  276. }
  277. private function getNextArticle(Article $article)
  278. {
  279. $query = Article::find()->alias('a')
  280. ->select('a.id,CAST(is_publication AS SIGNED) AS is_publication, CAST(is_recommend AS SIGNED) AS is_recommend, CAST(is_top AS SIGNED) AS is_top,a.create_date,a.create_date,
  281. a.article_category_id,a.hits,a.image_path,a.title,a.link_url,
  282. a.min_content,ac.path')
  283. ->leftJoin('bit_article_category ac', 'a.article_category_id = ac.id')
  284. ->andWhere(['a.article_category_id' => $article->article_category_id])
  285. ->andWhere(['a.is_publication' => 1])
  286. ->andWhere(['>', 'a.create_date', $article->create_date])
  287. ->orderBy(['a.create_date' => SORT_ASC])
  288. ->limit(1);
  289. $rs = $query->asArray()->one();
  290. if (!empty($rs) && count($rs) > 0) {
  291. return $rs;
  292. }
  293. return null;
  294. }
  295. private function getPreviousArticle(Article $article)
  296. {
  297. $query = Article::find()->alias('a')
  298. ->select('a.id,CAST(is_publication AS SIGNED) AS is_publication, CAST(is_recommend AS SIGNED) AS is_recommend, CAST(is_top AS SIGNED) AS is_top,a.create_date,a.create_date,
  299. a.article_category_id,a.hits,a.image_path,a.title,a.link_url,
  300. a.min_content,
  301. ac.path')
  302. ->leftJoin('bit_article_category ac', 'a.article_category_id = ac.id')
  303. ->andWhere(['a.article_category_id' => $article->article_category_id])
  304. ->andWhere(['a.is_publication' => 1])
  305. ->andWhere(['<', 'a.create_date', $article->create_date])
  306. ->orderBy(['a.create_date' => SORT_DESC])
  307. ->limit(1);
  308. $rs = $query->asArray()->one();
  309. if (!empty($rs) && count($rs) > 0) {
  310. return $rs;
  311. }
  312. return null;
  313. }
  314. private function getRelationArticle(Article $article)
  315. {
  316. $ids = [];
  317. $next = $this->getNextArticle($article);
  318. $previous = $this->getPreviousArticle($article);
  319. if (!empty($next)) {
  320. $ids[] = $next['id'];
  321. }
  322. if (!empty($previous)) {
  323. $ids[] = $previous['id'];
  324. }
  325. $query = Article::find()->alias('a')
  326. ->select('a.id,CAST(is_publication AS SIGNED) AS is_publication, CAST(is_recommend AS SIGNED) AS is_recommend, CAST(is_top AS SIGNED) AS is_top,a.create_date,a.create_date,
  327. a.article_category_id,a.hits,a.image_path,a.title,a.link_url,
  328. a.min_content,
  329. ac.path')
  330. ->leftJoin('bit_article_category ac', 'a.article_category_id = ac.id')
  331. ->andWhere(['a.article_category_id' => $article->article_category_id])
  332. ->andWhere(['<>', 'a.id', $article->id])
  333. ->andWhere(['not in', 'a.id', $ids])
  334. ->andWhere(['a.is_publication' => 1])
  335. ->andWhere(['<', 'a.create_date', $article->create_date])
  336. ->orderBy(['a.create_date' => SORT_DESC])
  337. ->limit(4);
  338. $rs = $query->asArray()->all();
  339. if (!empty($rs) && count($rs) > 0) {
  340. return $rs;
  341. }
  342. return null;
  343. }
  344. /**
  345. * 获取不同分类的文章列表
  346. */
  347. public function actionArticleList()
  348. {
  349. $request = \Yii::$app->getRequest()->get();
  350. $data['id'] = (int)$request['id'];
  351. $data['pageNumber'] = isset($request['pageNumber']) ? (int)($request['pageNumber']) : 1;
  352. $data['pageSize'] = isset($request['pageSize']) ? (int)($request['pageSize']) : 20;
  353. $data['orderBy'] = isset($request['orderBy']) ? trim($request['orderBy']) : 'create_date';
  354. $data['order'] = isset($request['order']) ? trim($request['order']) : 'desc';
  355. $data['keyword'] = isset($request['keyword']) ? trim($request['keyword']) : '';
  356. $data['searchBy'] = isset($request['searchBy']) ? trim($request['searchBy']) : 'title';
  357. $data['is_publication'] = isset($request['is_publication']) ? intval($request['is_publication']) : null;
  358. $data = ValidatorHelper::validateData($data, [
  359. ['pageNumber', 'integer', 'min' => 1],
  360. ['pageSize', 'integer', 'min' => 1],
  361. ['orderBy', 'string'],
  362. ], $errors);
  363. if ($data == false) {
  364. return $this->outJson(0, '', $errors);
  365. }
  366. $query = Article::find()
  367. ->select(['*', 'CONVERT(is_publication, SIGNED) AS is_publication', 'CONVERT(is_recommend, SIGNED) AS is_recommend', 'CONVERT(is_top, SIGNED) AS is_top'])
  368. ->where(['article_category_id' => $data['id']])
  369. ->with('category');
  370. // 有逗号隔开的情况,比如is_top asc, create_date desc
  371. if (strpos($data['orderBy'], ',') !== false) {
  372. $query->orderBy($data['orderBy']);
  373. } else {
  374. $query->orderBy($data['orderBy'].' '.$data['order']);
  375. }
  376. // 按标题搜索
  377. if ($data['searchBy'] == 'title' && !empty($data['keyword'])) {
  378. $query->andFilterWhere(['like', 'title', $data['keyword']]);
  379. }
  380. // 是否发布
  381. if ($data['is_publication'] !== null) {
  382. $query->andFilterWhere(['=', 'is_publication', $data['is_publication']]);
  383. }
  384. $result = PaginationHelper::queryPage($query, $data['pageNumber'], $data['pageSize']);
  385. switch($request['language']){
  386. case 1:
  387. foreach($result['dataList'] as $k => $v){
  388. $result['dataList'][$k]['title'] = $v['title1'];
  389. $result['dataList'][$k]['min_content'] = $v['min_content1'];
  390. $result['dataList'][$k]['content'] = $v['content1'];
  391. }
  392. break;
  393. case 2:
  394. foreach($result['dataList'] as $k => $v){
  395. $result['dataList'][$k]['title'] = $v['title2'];
  396. $result['dataList'][$k]['min_content'] = $v['min_content2'];
  397. $result['dataList'][$k]['content'] = $v['content2'];
  398. }
  399. break;
  400. default:
  401. break;
  402. }
  403. return $this->outJson(1, $result);
  404. }
  405. /**
  406. * 保存文章
  407. */
  408. public function actionArticleSave()
  409. {
  410. $request = \Yii::$app->getRequest()->post();
  411. $id = isset($request['id']) ? (int)$request['id'] : '';
  412. if ($id) {
  413. $model = Article::findOne(['id' => $id]);
  414. $model->modify_date = date('Y-m-d H:i:s', strtotime($request['modify_date']));
  415. } else {
  416. $model = new Article();
  417. $model->create_date = date('Y-m-d H:i:s', strtotime($request['create_date']));
  418. $model->up = 0;
  419. $model->down = 0;
  420. $model->image_path = isset($request['image_path']) ? $request['image_path'] : null;
  421. }
  422. $model->article_category_id = (int)$request['article_category_id'];
  423. $model->modifydatea = date('Y-m-d H:i:s', strtotime($request['modifydatea']));
  424. $model->createdatea = date('Y-m-d H:i:s', strtotime($request['createdatea']));
  425. $model->setAttributes($request);
  426. if ($model->save()) {
  427. return $this->outJson(1, $model->getAttributes());
  428. } else {
  429. return $this->outJson(0, [], $model->hasErrors());
  430. }
  431. }
  432. /**
  433. * 获取文章详情
  434. */
  435. public function actionAdminArticleDetail()
  436. {
  437. $articleId = \Yii::$app->request->get('id');
  438. $language = \Yii::$app->request->get('language');
  439. $article = Article::find()->select(['*', 'CONVERT(is_publication, SIGNED) AS is_publication', 'CONVERT(is_recommend, SIGNED) AS is_recommend', 'CONVERT(is_top, SIGNED) AS is_top'])->with('category')->where(['id' => $articleId])->asArray()->one();
  440. switch($language){
  441. case 1:
  442. $article['title'] = $article['title1'];
  443. $article['sub_title'] = $article['sub_title1'];
  444. $article['content'] = $article['content1'];
  445. $article['min_content'] = $article['min_content1'];
  446. $article['author'] = $article['author1'];
  447. break;
  448. case 2:
  449. $article['title'] = $article['title2'];
  450. $article['sub_title'] = $article['sub_title2'];
  451. $article['content'] = $article['content2'];
  452. $article['min_content'] = $article['min_content2'];
  453. $article['author'] = $article['author2'];
  454. break;
  455. default:
  456. break;
  457. }
  458. return $this->outJson(1, $article);
  459. }
  460. /**
  461. * 删除文章(批量)
  462. */
  463. public function actionArticleDelete()
  464. {
  465. $ids = \Yii::$app->request->post('ids');
  466. $rs = Article::deleteAll(['in', 'id', $ids]);
  467. return $this->outJson(1, $rs);
  468. }
  469. }