Modules_Api_Controllers_MessageController.proxy.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. <?php
  2. namespace Modules\Api\Controllers;
  3. use App\Constants\AdConstrant;
  4. use App\Constants\CommonConstant;
  5. use App\Model\CommentModel;
  6. use App\Model\Mongo\MessageModel;
  7. use App\Model\Mongo\UserRelationModel;
  8. use App\Model\Mongo\VideoLikeModel;
  9. use App\Model\UserModel;
  10. use App\Model\VideoModel;
  11. use App\Repositories\ConfigRepoistory;
  12. use App\Repositories\MessageRepository;
  13. use App\Repositories\Utils\M3u8CacheRepository;
  14. use Carbon\Carbon;
  15. use Hyperf\Validation\Contract\ValidatorFactoryInterface;
  16. use Modules\Api\Services\VideoService;
  17. class MessageController extends BaseController
  18. {
  19. use \Hyperf\Di\Aop\ProxyTrait;
  20. use \Hyperf\Di\Aop\PropertyHandlerTrait;
  21. function __construct()
  22. {
  23. if (method_exists(parent::class, '__construct')) {
  24. parent::__construct(...func_get_args());
  25. }
  26. $this->__handlePropertyHandler(__CLASS__);
  27. }
  28. public function index()
  29. {
  30. $userCode = $this->getUserId();
  31. $inputData = $this->getJsonData();
  32. $configRepo = make(ConfigRepoistory::class);
  33. $videoService = make(VideoService::class);
  34. $adList = $videoService->getAdList(AdConstrant::MESSAGE_INDEX);
  35. $ad = null;
  36. if (!empty($adList[0])) {
  37. $link = M3u8CacheRepository::getLinkUrl($adList[0]['link'], ['user_code' => $userCode]);
  38. $ad = ['position' => $adList[0]['position'], 'title' => $adList[0]['title'], 'cover' => !empty($adList[0]['cover']) ? M3u8CacheRepository::getImageUrl($adList[0]['cover']) : '', 'link' => $link, 'scheme' => $adList[0]['scheme'], 'type' => $adList[0]['type'], 'play' => !empty($adList[0]['play']) ? M3u8CacheRepository::getM3u8Url($adList[0]['play']) : '', 'resolution' => $adList[0]['resolution'] ?? ''];
  39. if (!empty($ad['link'])) {
  40. $ad['link'] = M3u8CacheRepository::getLinkUrl($ad['link'], ['user_code' => $userCode]);
  41. }
  42. }
  43. $kefuUrl = $configRepo->get('server_link', 'sys', '');
  44. if (strripos($kefuUrl, '?')) {
  45. $kefuUrl .= '&user_code=' . $userCode;
  46. } else {
  47. $kefuUrl .= '?user_code=' . $userCode;
  48. }
  49. // 系统消息的第一条,包含统计
  50. $sysMsg = make(MessageRepository::class)->firstSys($userCode);
  51. $arrData = ['ad' => $ad, 'kefu' => ['url' => $kefuUrl, 'description' => '亲,有什么可以帮助您的?'], 'sys' => $sysMsg, 'talk' => null];
  52. // 私聊消息
  53. $shopsMsg = make(MessageRepository::class)->firstSys($userCode, 'user');
  54. $arrData['count_unread'] = $shopsMsg['count_unread'];
  55. return json_success($arrData);
  56. }
  57. /**
  58. * 系统消息分页.
  59. * @return mixed
  60. */
  61. public function sysPages()
  62. {
  63. $userCode = $this->getUserId();
  64. $inputData = $this->getJsonData();
  65. $previousDate = isset($inputData['previous_date']) ? trim($inputData['previous_date']) : '';
  66. if (empty($previousDate)) {
  67. $previousDate = Carbon::now()->toDateTimeString();
  68. }
  69. $limitNum = 20;
  70. $result = ['previous_date' => $previousDate, 'data' => null];
  71. $items = make(MessageRepository::class)->previousSysPages($userCode, $previousDate, $limitNum, true);
  72. if (!empty($items)) {
  73. $result['data'] = $items;
  74. }
  75. return json_success($result);
  76. }
  77. /**
  78. * 标记消息为已读.
  79. * @return mixed|void
  80. */
  81. public function doRead()
  82. {
  83. $userCode = $this->getUserId();
  84. $inputData = $this->getJsonData();
  85. $msgId = isset($inputData['msg_id']) ? trim($inputData['msg_id']) : '';
  86. if (empty($msgId)) {
  87. return json_fail('参数有误1');
  88. }
  89. if (!preg_match('/^[a-z0-9]{16,32}$/i', $msgId)) {
  90. return json_fail('参数有误2');
  91. }
  92. $result = make(MessageRepository::class)->doRead($msgId, $userCode);
  93. if (!$result) {
  94. return json_fail('不能正确操作已读');
  95. }
  96. return json_success(['result' => 'success']);
  97. }
  98. /**
  99. * 删除自己的消息.
  100. * @return mixed
  101. */
  102. public function deleteMyself()
  103. {
  104. $userCode = $this->getUserId();
  105. $inputData = $this->getJsonData();
  106. $msgIds = isset($inputData['msg_ids']) ? trim($inputData['msg_ids']) : '';
  107. $receiveUid = $userCode;
  108. if (empty($msgIds)) {
  109. return json_fail('缺少参数1');
  110. }
  111. $arrMsgIds = [];
  112. if (is_string($msgIds)) {
  113. if (stripos($msgIds, ',') !== false) {
  114. $arrMsgIds = explode(',', $msgIds);
  115. } else {
  116. $arrMsgIds[] = $msgIds;
  117. }
  118. } else {
  119. $arrMsgIds = $msgIds;
  120. }
  121. $result = make(MessageRepository::class)->slientDelete($arrMsgIds, $userCode);
  122. if (!$result) {
  123. return json_fail('删除消息有误.');
  124. }
  125. return json_success(['result' => 'success']);
  126. }
  127. /**
  128. * 被关注分页列表
  129. */
  130. public function followedPages()
  131. {
  132. $userCode = $this->getUserId();
  133. $inputData = $this->getJsonData();
  134. $validatorFactory = make(ValidatorFactoryInterface::class);
  135. $rules = ['page' => 'nullable|int', 'page_size' => 'nullable|int'];
  136. $validator = $validatorFactory->make($inputData, $rules);
  137. if ($validator->fails()) {
  138. // 如果有错误(可能是多个信息),这里只取第一个错误信息返回.
  139. return json_fail($validator->errors()->first());
  140. }
  141. $page = $inputData['page'] ?? 1;
  142. $pageSize = $inputData['page_size'] ?? CommonConstant::PAGE_SIZE;
  143. if ($pageSize > 100) {
  144. $pageSize = CommonConstant::PAGE_SIZE;
  145. }
  146. $page = format_page($page);
  147. $pageSize = intval($pageSize);
  148. $relationRepo = make(UserRelationModel::class);
  149. $filters = ['to_user_id' => $userCode];
  150. $amount = $relationRepo->db()->countDocuments($filters);
  151. $skip = ($page - 1) * $pageSize;
  152. $options = ['skip' => $skip, 'limit' => $pageSize, 'sort' => ['date' => -1]];
  153. $temItems = $relationRepo->db()->find($filters, $options)->toArray();
  154. $data = [];
  155. $result = ['current_page' => $page, 'per_page' => $pageSize, 'total' => $amount, 'data' => []];
  156. if (!empty($temItems)) {
  157. foreach ($temItems as $item) {
  158. $fromUserCode = $item['from_user_id'];
  159. $fromUser = UserModel::query()->where('code', $fromUserCode)->first(['id', 'code', 'nick', 'avatar']);
  160. if ($fromUser) {
  161. $fromUser = $fromUser->toArray();
  162. $fromUser['avatar'] = M3u8CacheRepository::getImageUrl($fromUser['avatar']);
  163. $fromUser['date'] = Carbon::parse($item['date'])->toDateTimeString();
  164. unset($fromUser['id']);
  165. $data[] = $fromUser;
  166. }
  167. }
  168. }
  169. $result['data'] = $data;
  170. return json_success($result);
  171. }
  172. /**
  173. * 被点赞视频分页列表
  174. */
  175. public function likedPages()
  176. {
  177. $userCode = $this->getUserId();
  178. $inputData = $this->getJsonData();
  179. $validatorFactory = make(ValidatorFactoryInterface::class);
  180. $rules = ['page' => 'nullable|int', 'page_size' => 'nullable|int'];
  181. $validator = $validatorFactory->make($inputData, $rules);
  182. if ($validator->fails()) {
  183. // 如果有错误(可能是多个信息),这里只取第一个错误信息返回.
  184. return json_fail($validator->errors()->first());
  185. }
  186. $page = $inputData['page'] ?? 1;
  187. $pageSize = $inputData['page_size'] ?? CommonConstant::PAGE_SIZE;
  188. if ($pageSize > 100) {
  189. $pageSize = CommonConstant::PAGE_SIZE;
  190. }
  191. $page = format_page($page);
  192. $pageSize = intval($pageSize);
  193. $relationRepo = make(VideoLikeModel::class);
  194. $filters = ['uid' => $userCode];
  195. $amount = $relationRepo->db()->countDocuments($filters);
  196. $skip = ($page - 1) * $pageSize;
  197. $options = ['skip' => $skip, 'limit' => $pageSize, 'sort' => ['date' => -1]];
  198. $temItems = $relationRepo->db()->find($filters, $options)->toArray();
  199. $data = [];
  200. $result = ['current_page' => $page, 'per_page' => $pageSize, 'total' => $amount, 'data' => []];
  201. $cacheVideo = [];
  202. if (!empty($temItems)) {
  203. $videoColumns = ['id', 'uid', 'title', 'cover'];
  204. foreach ($temItems as $item) {
  205. $fromUserCode = $item['uid'];
  206. $videoId = $item['vid'];
  207. if (empty($cacheVideo[$videoId])) {
  208. $videoInfo = VideoModel::query()->where(['status' => 1])->find($videoId, $videoColumns);
  209. if (empty($videoInfo)) {
  210. break;
  211. }
  212. $videoInfo = $videoInfo->toArray();
  213. $cacheVideo[$videoId] = $videoInfo;
  214. } else {
  215. $videoInfo = $cacheVideo[$videoId];
  216. }
  217. $fromUser = UserModel::query()->where('code', $fromUserCode)->first(['id', 'code', 'nick', 'avatar']);
  218. if ($fromUser) {
  219. $fromUser = $fromUser->toArray();
  220. $fromUser['avatar'] = M3u8CacheRepository::getImageUrl($fromUser['avatar']);
  221. $fromUser['date'] = Carbon::parse($item['date'])->toDateTimeString();
  222. $fromUser['video'] = ['id' => $videoInfo['id'], 'title' => $videoInfo['title'], 'cover' => M3u8CacheRepository::getImageUrl($videoInfo['cover']), 'uid' => $videoInfo['uid']];
  223. unset($fromUser['id']);
  224. $data[] = $fromUser;
  225. }
  226. }
  227. }
  228. $result['data'] = $data;
  229. return json_success($result);
  230. }
  231. /**
  232. * 被评论分页列表
  233. */
  234. public function commentedPages()
  235. {
  236. $userCode = $this->getUserId();
  237. $inputData = $this->getJsonData();
  238. $validatorFactory = make(ValidatorFactoryInterface::class);
  239. $rules = ['page' => 'nullable|int', 'page_size' => 'nullable|int'];
  240. $validator = $validatorFactory->make($inputData, $rules);
  241. if ($validator->fails()) {
  242. // 如果有错误(可能是多个信息),这里只取第一个错误信息返回.
  243. return json_fail($validator->errors()->first());
  244. }
  245. $page = $inputData['page'] ?? 1;
  246. $pageSize = $inputData['page_size'] ?? CommonConstant::PAGE_SIZE;
  247. if ($pageSize > 100) {
  248. $pageSize = CommonConstant::PAGE_SIZE;
  249. }
  250. $page = format_page($page);
  251. $pageSize = intval($pageSize);
  252. if ($pageSize <= 0) {
  253. $pageSize = CommonConstant::PAGE_SIZE;
  254. }
  255. $columns = ['id', 'user_id', 'module', 'svalue', 'content', 'created_at'];
  256. $items = CommentModel::query()->where(['module_user_uid' => $userCode])->orderByDesc('created_at')->paginate($pageSize, $columns, 'page', $page);
  257. $result = $items->toArray();
  258. $cacheData = ['video' => []];
  259. if (!empty($result['data'])) {
  260. $videoColumns = ['id', 'uid', 'title', 'cover'];
  261. foreach ($result['data'] as $k => &$v) {
  262. $fromUserCode = $v['user_id'];
  263. $moduleInfo = [];
  264. if ($v['module'] == 'video') {
  265. $videoId = $v['svalue'];
  266. if (empty($cacheData['video'][$videoId])) {
  267. $videoInfo = VideoModel::query()->where(['status' => 1])->find($videoId, $videoColumns);
  268. if (!empty($videoInfo)) {
  269. $videoInfo = $videoInfo->toArray();
  270. $cacheData['video'][$videoId] = $videoInfo;
  271. }
  272. } else {
  273. $videoInfo = $cacheData['video'][$videoId];
  274. }
  275. $moduleInfo = [
  276. 'module' => $v['module'],
  277. 'id' => !empty($videoInfo['id']) ? (string) $videoInfo['id'] : '',
  278. // 强语言,统一转换字符串.
  279. 'title' => !empty($videoInfo['title']) ? $videoInfo['title'] : '视频已下架',
  280. 'cover' => !empty($videoInfo['cover']) ? M3u8CacheRepository::getImageUrl($videoInfo['cover']) : '',
  281. 'uid' => !empty($videoInfo['uid']) ? $videoInfo['uid'] : '',
  282. ];
  283. }
  284. $fromUser = UserModel::query()->where('code', $fromUserCode)->first(['id', 'code', 'nick', 'avatar']);
  285. if ($fromUser) {
  286. $fromUser = $fromUser->toArray();
  287. $fromUser['avatar'] = M3u8CacheRepository::getImageUrl($fromUser['avatar']);
  288. $fromUser['date'] = $v['created_at'];
  289. $fromUser['module_info'] = $moduleInfo;
  290. unset($fromUser['id']);
  291. } else {
  292. $fromUser = null;
  293. }
  294. $result['data'][$k] = $fromUser;
  295. }
  296. }
  297. return json_success($result);
  298. }
  299. /**
  300. * 私聊用户列表
  301. *
  302. * @param ValidatorFactoryInterface $validatorFactory
  303. * @return mixed
  304. */
  305. public function privateChatLists(ValidatorFactoryInterface $validatorFactory)
  306. {
  307. $inputData = $this->getJsonData();
  308. $rules = ['page' => 'required|integer', 'page_size' => 'required|integer'];
  309. $validator = $validatorFactory->make($inputData, $rules);
  310. if ($validator->fails()) {
  311. // 如果有错误(可能是多个信息),这里只取第一个错误信息返回.
  312. return json_fail($validator->errors()->first());
  313. }
  314. $pageSize = $inputData['page_size'] ?? CommonConstant::PAGE_SIZE;
  315. if ($pageSize > 500) {
  316. $pageSize = CommonConstant::PAGE_SIZE;
  317. }
  318. $page = format_page($inputData['page'] ?? 1);
  319. $result = make(MessageModel::class)->db()->aggregate([['$match' => ['receive_uid' => $this->getUserId(), 'from_type' => 'user']], ['$group' => ["_id" => ['from_uid' => '$from_uid'], 'struct_type' => ['$last' => '$struct_type'], 'from_uid' => ['$last' => '$from_uid'], 'from_nick' => ['$last' => '$from_nick'], 'from_avatar' => ['$last' => '$from_avatar'], 'content' => ['$last' => '$content'], 'created_at' => ['$last' => '$created_at']]], ['$sort' => ["created_at" => -1]], ['$limit' => $pageSize * $page], ['$skip' => ($page - 1) * $pageSize]]);
  320. $res = $result->toArray();
  321. if (!empty($res)) {
  322. foreach ($res as &$val) {
  323. $content = json_decode($val['content'], true);
  324. $message = structureHandle($content['message'], $val['struct_type']);
  325. $val['message'] = json_encode($message);
  326. $val['created_at'] = mongoIsoDateToCarbonTime($val['created_at'])->toDateTimeString();
  327. $val['from_avatar'] = M3u8CacheRepository::getImageUrl($val['from_avatar']);
  328. $val['msg_type'] = $val['struct_type'];
  329. unset($val['_id'], $val['content'], $val['struct_type']);
  330. }
  331. }
  332. return json_success($res);
  333. }
  334. /**
  335. * 我的页面红点数量
  336. * @return mixed
  337. */
  338. public function myRed()
  339. {
  340. $result = [];
  341. $userCode = $this->getUserId();
  342. // 系统消息的第一条,包含统计
  343. $sysMsg = make(MessageRepository::class)->firstSys($userCode);
  344. $result['count_sys_unread'] = $sysMsg['count_unread'];
  345. // 私聊消息
  346. $shopsMsg = make(MessageRepository::class)->firstSys($userCode, 'user');
  347. $result['count_p2p_unread'] = $shopsMsg['count_unread'];
  348. return json_success($result);
  349. }
  350. }