Forum.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. <?php
  2. namespace app\controller;
  3. use app\BaseController;
  4. use think\facade\Db;
  5. //论坛控制器
  6. class Forum extends BaseController
  7. {
  8. protected $noNeedLogin = ['getCategory', 'getCategoryNotice', 'getForumCategoryData', 'getForumCategoryOnly', 'getThreads', 'getThread', 'getThreadReply', 'getCategoryData'];
  9. //获取版块
  10. public function getCategory()
  11. {
  12. $data = Db::table('tb_forum_category')
  13. ->order('priority ASC')
  14. ->select();
  15. $this->success('success', $data);
  16. }
  17. //获取版块置顶公告
  18. public function getCategoryNotice()
  19. {
  20. $categoryId = $this->request->post('categoryId'); //版块ID
  21. if (!is_numeric($categoryId)) {
  22. $this->fail(500, 'categoryId参数校验错误');
  23. }
  24. $data = Db::table('tb_forum_category_notice')
  25. ->where(['category_id' => $categoryId])
  26. ->find();
  27. if (!$data) {
  28. $this->fail(501, '找不到categoryId对应的版块公告');
  29. }
  30. $this->success('success', $data);
  31. }
  32. //获取版块数据
  33. public function getCategoryData()
  34. {
  35. $categoryId = $this->request->post('categoryId'); //版块ID
  36. if (!is_numeric($categoryId)) {
  37. $this->fail(500, 'categoryId参数校验错误');
  38. }
  39. $category = Db::table('tb_forum_category')
  40. ->where(['id' => $categoryId])
  41. ->find();
  42. if (!$category) {
  43. $this->fail(501, '版块ID不存在');
  44. }
  45. $today = Db::table('tb_thread')
  46. ->where(['category_id' => $categoryId])
  47. ->where('created_at', '>', strtotime(date('Y-m-d') . ' 00:00:00'))
  48. ->count();
  49. $topic = Db::table('tb_thread')
  50. ->where(['category_id' => $categoryId])
  51. ->count();
  52. $admin = Db::table('tb_user')
  53. ->field('id,username,avatar')
  54. ->where(['id' => $category['admin_id']])
  55. ->find();
  56. //解析获取头像url
  57. if (str_starts_with($admin['avatar'], 'system://')) {
  58. $data = explode('//', $admin['avatar']);
  59. $avatarId = intval($data[1]);
  60. $avatar = Db::table('tb_system_avatar')
  61. ->where(['id' => $avatarId])
  62. ->find();
  63. $admin['avatar'] = $avatar['image_url'];
  64. }
  65. $this->success('success', [
  66. 'name' => $category['name'], //版块名称
  67. 'today' => $today, //今日
  68. 'topic' => $topic, //主题
  69. 'admin' => $admin, //版主信息
  70. ]);
  71. }
  72. //获取帖子分类带数据
  73. public function getForumCategoryData()
  74. {
  75. $categoryId = $this->request->post('categoryId'); //版块ID
  76. if (!is_numeric($categoryId)) {
  77. $this->fail(500, 'categoryId参数校验错误');
  78. }
  79. $threadCategory = Db::table('tb_forum_thread_category')
  80. ->where(['category_id' => $categoryId])
  81. ->select();
  82. $data = [];
  83. foreach ($threadCategory as $categoryData) {
  84. $threadsCount = Db::table('tb_thread')
  85. ->where(['category_id' => $categoryId])
  86. ->where(['thread_category' => $categoryData['id']])
  87. ->count();
  88. $data[] = [
  89. 'threadCategoryId' => $categoryData['id'], //分类ID
  90. 'threadCategoryTitle' => $categoryData['title'], //帖子分类标题
  91. 'threadsCount' => $threadsCount, //帖子数量
  92. ];
  93. }
  94. $this->success('success', $data);
  95. }
  96. //仅获取帖子分类
  97. public function getForumCategoryOnly()
  98. {
  99. $categoryId = $this->request->post('categoryId'); //版块ID
  100. if (!is_numeric($categoryId)) {
  101. $this->fail(500, 'categoryId参数校验错误');
  102. }
  103. $threadCategory = Db::table('tb_forum_thread_category')
  104. ->where(['category_id' => $categoryId])
  105. ->select();
  106. $this->success('success', $threadCategory);
  107. }
  108. //获取版块下帖子列表
  109. public function getThreads()
  110. {
  111. $page = $this->request->post('page'); // 页码
  112. $list = $this->request->post('list'); // 每页记录数
  113. $categoryId = $this->request->post('categoryId'); //版块ID 999代表全部
  114. $thread_category = $this->request->post('thread_category'); // 板块下分类ID
  115. if (!is_numeric($page)|| !is_numeric($list)|| !is_numeric($categoryId)) {
  116. $this->fail(500, '参数校验错误');
  117. }
  118. $query = Db::table('tb_thread')
  119. ->alias('tt')
  120. ->order('tt.created_at DESC')
  121. ->join('tb_user tu', 'tt.user_id = tu.id')
  122. ->field('tt.*, tu.username, tu.avatar');
  123. if($categoryId == 999) {
  124. // 999的情况下不做任何筛选
  125. } else {
  126. $query->where(['tt.category_id' => $categoryId]);
  127. }
  128. if ($thread_category) {
  129. $query->where(['tt.thread_category' => $thread_category]);
  130. }
  131. $data = $query->paginate([
  132. 'page' => $page,
  133. 'list_rows' => $list
  134. ]);
  135. // // 处理头像数据
  136. // $items = $data->getCollection()->toArray();
  137. // foreach($items as &$item) {
  138. // if (isset($item['avatar'])) {
  139. // $item['avatar'] = $this->getUserAvatar($item['avatar']);
  140. // }
  141. // }
  142. // unset($item); // 释放引用
  143. // // 重新设置处理后的数据
  144. // $data->setCollection(collect($items));
  145. $this->success('success', $data);
  146. }
  147. //获取帖子内容,前端需要做下判断:如果登录了header需要传token,没登录就不传
  148. public function getThread()
  149. {
  150. $token = $this->request->header('token');
  151. $threadId = $this->request->post('threadId');
  152. if (!is_numeric($threadId)) {
  153. $this->fail(500, 'threadId参数校验错误');
  154. }
  155. $thread = Db::table('tb_thread')
  156. ->alias('tt')
  157. ->where(['tt.id' => $threadId])
  158. ->join('tb_user tu', 'tt.user_id = tu.id')
  159. ->field('tt.*, tu.username, tu.avatar')
  160. ->find();
  161. if (!$thread) {
  162. $this->fail(501, '找不到threadId对应的帖子');
  163. }
  164. $thread['avatar'] = $this->getUserAvatar($thread['avatar']);
  165. $userId = 0;
  166. $isUser = 0;
  167. if (!empty($token)) {
  168. $userToken = Db::table('tb_user_token')
  169. ->where(['token' => $token])
  170. ->find();
  171. if ($userToken && $userToken['expired_at'] > time()) {
  172. $userId = $userToken['user_id'];
  173. $isUser = 1;
  174. }
  175. }
  176. Db::table('tb_thread_visit')
  177. ->insert([
  178. 'user_id' => $userId,
  179. 'is_user' => $isUser,
  180. 'created_at' => time(),
  181. ]);
  182. Db::table('tb_thread')
  183. ->where(['id' => $threadId])
  184. ->update([
  185. 'browse' => $thread['browse'] + 1,
  186. ]);
  187. $thread['theme_count'] = Db::table('tb_thread')->where('user_id', $userId)->count();
  188. $thread['theme_count'] = Db::table('tb_thread_reply')->where('user_id', $userId)->count();
  189. $thread['user_score'] = Db::table('tb_user')->where('id', $userId)->value('score');
  190. $this->success('success', $thread);
  191. }
  192. //获取自己的帖子内容
  193. public function getSelfThread()
  194. {
  195. $threadId = $this->request->post('threadId');
  196. if (!is_numeric($threadId)) {
  197. $this->fail(500, 'threadId参数校验错误');
  198. }
  199. $thread = Db::table('tb_thread')
  200. ->where(['id' => $threadId])
  201. ->where(['user_id' => $this->getUser()->user_id])
  202. ->find();
  203. if (!$thread) {
  204. $this->fail(501, '找不到threadId对应的帖子');
  205. }
  206. $this->success('success', $thread);
  207. }
  208. //获取自己的回复内容
  209. public function getSelfReply()
  210. {
  211. $replyId = $this->request->post('replyId');
  212. if (!is_numeric($replyId)) {
  213. $this->fail(500, 'replyId参数校验错误');
  214. }
  215. $reply = Db::table('tb_thread_reply')
  216. ->where(['id' => $replyId])
  217. ->where(['user_id' => $this->getUser()->user_id])
  218. ->find();
  219. if (!$reply) {
  220. $this->fail(501, '找不到replyId对应的帖子');
  221. }
  222. $this->success('success', $reply);
  223. }
  224. //发表帖子
  225. public function postThread()
  226. {
  227. $categoryId = $this->request->post('categoryId'); //版块ID
  228. $title = $this->request->post('title'); //帖子标题
  229. $threadCategoryId = $this->request->post('threadCategoryId'); //帖子分类ID
  230. $content = $this->request->post('content'); //帖子内容
  231. if (!is_numeric($categoryId) || empty($title) || empty($content) || !is_numeric($threadCategoryId)) {
  232. $this->fail(500, '参数校验错误');
  233. }
  234. //版块ID是否存在
  235. $forumCategory = Db::table('tb_forum_category')
  236. ->where(['id' => $categoryId])
  237. ->find();
  238. if (!$forumCategory) {
  239. $this->fail(501, '对应的版块ID不存在');
  240. }
  241. //帖子分类ID是否存在
  242. $threadCategory = Db::table('tb_forum_thread_category')
  243. ->where(['id' => $threadCategoryId])
  244. ->find();
  245. if (!$threadCategory) {
  246. $this->fail(502, '帖子分类ID不存在');
  247. }
  248. Db::table('tb_thread')
  249. ->insert([
  250. 'category_id' => $categoryId,
  251. 'thread_category' => $threadCategoryId,
  252. 'user_id' => $this->getUser()->user_id,
  253. 'title' => $title,
  254. 'content' => $content,
  255. 'browse' => 0,
  256. 'created_at' => time(),
  257. 'updated_at' => time(),
  258. ]);
  259. $this->success('success', null);
  260. }
  261. //编辑帖子
  262. public function editThread()
  263. {
  264. $threadId = $this->request->post('threadId'); //帖子ID
  265. $title = $this->request->post('title'); //帖子标题
  266. $threadCategoryId = $this->request->post('threadCategoryId'); //帖子分类ID
  267. $content = $this->request->post('content'); //帖子内容
  268. if (!is_numeric($threadId) || !is_numeric($categoryId) || empty($title) || empty($content) || !is_numeric($threadCategory)) {
  269. $this->fail(500, '参数校验错误');
  270. }
  271. $selfThread = Db::table('tb_thread')
  272. ->where(['user_id' => $this->getUser()->user_id])
  273. ->where(['id' => $threadId])
  274. ->find();
  275. if (!$selfThread) {
  276. $this->fail(501, '只能编辑自己的帖子');
  277. }
  278. Db::table('tb_thread')
  279. ->where(['id' => $threadId])
  280. ->where(['user_id' => $this->getUser()->user_id])
  281. ->update([
  282. 'thread_category' => $threadCategoryId,
  283. 'title' => $title,
  284. 'content' => $content,
  285. 'updated_at' => time(),
  286. ]);
  287. $this->success('success', null);
  288. }
  289. //发表回复
  290. public function postReply()
  291. {
  292. $threadId = $this->request->post('threadId'); //帖子ID
  293. $content = $this->request->post('content'); //回复内容
  294. if (!is_numeric($threadId) || empty($content)) {
  295. $this->fail(500, '参数校验错误');
  296. }
  297. $thread = Db::table('tb_thread')
  298. ->where(['id' => $threadId])
  299. ->find();
  300. if (!$thread) {
  301. $this->fail(501, '帖子ID不存在');
  302. }
  303. Db::table('tb_thread_reply')
  304. ->insert([
  305. 'user_id' => $this->getUser()->user_id,
  306. 'thread_id' => $threadId,
  307. 'content' => $content,
  308. 'created_at' => time(),
  309. 'updated_at' => time(),
  310. ]);
  311. $this->success('success', null);
  312. }
  313. //编辑回复
  314. public function editReply()
  315. {
  316. $replyId = $this->request->post('replyId');
  317. $content = $this->request->post('content');
  318. if (!is_numeric($replyId)) {
  319. $this->fail(500, '参数校验错误');
  320. }
  321. $reply = Db::table('tb_thread_reply')
  322. ->where(['id' => $replyId])
  323. ->where(['user_id' => $this->getUser()->user_id])
  324. ->find();
  325. if (!$reply) {
  326. $this->fail(501, '只能编辑自己的帖子回复');
  327. }
  328. Db::table('tb_thread_reply')
  329. ->where(['id' => $replyId])
  330. ->where(['user_id' => $this->getUser()->user_id])
  331. ->update([
  332. 'content' => $content,
  333. 'updated_at' => time(),
  334. ]);
  335. $this->success('success', null);
  336. }
  337. //获取帖子回复,需要支持分页
  338. public function getThreadReply()
  339. {
  340. $page = $this->request->post('page'); // 当前页数
  341. $list = $this->request->post('list'); // 每页记录数
  342. $threadId = $this->request->post('threadId'); //帖子ID
  343. if (!is_numeric($threadId)) {
  344. $this->fail(500, 'threadId参数校验错误');
  345. }
  346. $data = Db::table('tb_thread_reply')
  347. ->where(['thread_id' => $threadId])
  348. ->order('created_at ASC')
  349. ->paginate([
  350. 'page' => $page,
  351. 'list_rows' => $list
  352. ]);
  353. $this->success('success', $data);
  354. }
  355. //上传图片,图片文件不能超过2MB
  356. public function uploadImage()
  357. {
  358. $file = $this->request->file('file');
  359. if (empty($file)) {
  360. $this->fail(500, '上传的图片文件不能为空');
  361. }
  362. // 使用验证器验证上传的文件
  363. validate(['file' => [
  364. // 限制文件大小(单位b),这里限制为2M
  365. 'fileSize' => 2 * 1024 * 1024,
  366. // 限制文件后缀,多个后缀以英文逗号分割
  367. 'fileExt' => 'jpg,jpeg,png,gif,bmp,webp',
  368. ]])->check(['file' => $file]);
  369. $saveName = \think\facade\Filesystem::disk('public')->putFile('images', $file);
  370. $this->success('success', [
  371. 'filePath' => $this->request->scheme() . '://' . $this->request->host() . '/storage/' . $saveName,
  372. ]);
  373. }
  374. //上传附件,单个附件不得超过50MB
  375. public function uploadAttachment()
  376. {
  377. $file = $this->request->file('file');
  378. if (empty($file)) {
  379. $this->fail(500, '上传的图片文件不能为空');
  380. }
  381. // 使用验证器验证上传的文件
  382. validate(['file' => [
  383. // 限制文件大小(单位b),这里限制为20M
  384. 'fileSize' => 50 * 1024 * 1024,
  385. // 限制文件后缀,多个后缀以英文逗号分割
  386. 'fileExt' => 'rar,zip,tar.gz,gz,7z,txt',
  387. ]])->check(['file' => $file]);
  388. $saveName = \think\facade\Filesystem::disk('public')->putFile('attachments', $file);
  389. $this->success('success', [
  390. 'filePath' => $this->request->scheme() . '://' . $this->request->host() . '/storage/' . $saveName,
  391. ]);
  392. }
  393. }