Chat.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. <?php
  2. declare (strict_types = 1);
  3. namespace app\system\controller;
  4. use app\model\api\ChatBalanceLog;
  5. use app\model\api\ChatOrder;
  6. use app\model\api\ChatRecord;
  7. use app\model\api\ChatUserRelation;
  8. use app\model\api\User;
  9. use app\services\chat\ChatBalanceService;
  10. use library\basic\BaseController;
  11. use think\Request;
  12. use think\Response;
  13. /**
  14. * 聊天管理控制器
  15. */
  16. class Chat extends BaseController
  17. {
  18. /**
  19. * 获取购买订单列表
  20. * @param Request $request
  21. * @return Response
  22. */
  23. public function orderList(Request $request): Response
  24. {
  25. $data = $request->get();
  26. $page = (int)($data['page'] ?? 1);
  27. $limit = (int)($data['limit'] ?? 15);
  28. $status = isset($data['status']) ? (int)$data['status'] : null;
  29. $orderNo = trim($data['order_no'] ?? '');
  30. $userId = isset($data['user_id']) ? (int)$data['user_id'] : 0;
  31. $where = [];
  32. if ($status !== null) {
  33. $where[] = ['status', '=', $status];
  34. }
  35. if (!empty($orderNo)) {
  36. $where[] = ['order_no', '=', $orderNo];
  37. }
  38. if ($userId > 0) {
  39. $where[] = ['user_id', '=', $userId];
  40. }
  41. $query = ChatOrder::where($where);
  42. $total = $query->count();
  43. $list = $query->order('id desc')
  44. ->page($page, $limit)
  45. ->select();
  46. // 处理数据
  47. $dataList = [];
  48. foreach ($list ?: [] as $item) {
  49. $itemArr = $item->toArray();
  50. // 获取用户信息
  51. $user = User::find($item->user_id);
  52. $itemArr['user_nickname'] = $user ? ($user->nickname ?? '') : '';
  53. $itemArr['user_phone'] = $user ? ($user->phone ?? '') : '';
  54. $itemArr['status_text'] = ChatOrder::getStatusText($item->status);
  55. $itemArr['create_time_text'] = date('Y-m-d H:i:s', $item->create_time);
  56. $itemArr['pay_time_text'] = $item->pay_time ? date('Y-m-d H:i:s', $item->pay_time) : '-';
  57. $dataList[] = $itemArr;
  58. }
  59. return $this->success('获取成功', [
  60. 'list' => $dataList,
  61. 'total' => $total,
  62. 'page' => $page,
  63. 'limit' => $limit,
  64. ]);
  65. }
  66. /**
  67. * 获取聊天次数变动明细列表
  68. * @param Request $request
  69. * @return Response
  70. */
  71. public function balanceLogList(Request $request): Response
  72. {
  73. $data = $request->get();
  74. $page = (int)($data['page'] ?? 1);
  75. $limit = (int)($data['limit'] ?? 15);
  76. $type = isset($data['type']) ? (int)$data['type'] : null;
  77. $userId = isset($data['user_id']) ? (int)$data['user_id'] : 0;
  78. $where = [];
  79. if ($type !== null) {
  80. $where[] = ['type', '=', $type];
  81. }
  82. if ($userId > 0) {
  83. $where[] = ['user_id', '=', $userId];
  84. }
  85. $query = ChatBalanceLog::where($where);
  86. $total = $query->count();
  87. $list = $query->order('id desc')
  88. ->page($page, $limit)
  89. ->select();
  90. // 处理数据
  91. $dataList = [];
  92. foreach ($list ?: [] as $item) {
  93. $itemArr = $item->toArray();
  94. // 获取用户信息
  95. $user = User::find($item->user_id);
  96. $itemArr['user_nickname'] = $user ? ($user->nickname ?? '') : '';
  97. $itemArr['user_phone'] = $user ? ($user->phone ?? '') : '';
  98. $itemArr['type_text'] = ChatBalanceLog::getTypeText($item->type);
  99. $itemArr['num_text'] = $item->num > 0 ? '+' . $item->num : $item->num;
  100. $itemArr['create_time_text'] = date('Y-m-d H:i:s', $item->create_time);
  101. $dataList[] = $itemArr;
  102. }
  103. return $this->success('获取成功', [
  104. 'list' => $dataList,
  105. 'total' => $total,
  106. 'page' => $page,
  107. 'limit' => $limit,
  108. ]);
  109. }
  110. /**
  111. * 获取聊天记录列表
  112. * @param Request $request
  113. * @return Response
  114. */
  115. public function recordList(Request $request): Response
  116. {
  117. $data = $request->get();
  118. $page = (int)($data['page'] ?? 1);
  119. $limit = (int)($data['limit'] ?? 15);
  120. $userId = isset($data['user_id']) ? (int)$data['user_id'] : 0;
  121. $toUserId = isset($data['to_user_id']) ? (int)$data['to_user_id'] : 0;
  122. $where = [];
  123. if ($userId > 0) {
  124. $where[] = ['user_id', '=', $userId];
  125. }
  126. if ($toUserId > 0) {
  127. $where[] = ['to_user_id', '=', $toUserId];
  128. }
  129. $query = ChatRecord::where($where);
  130. $total = $query->count();
  131. $list = $query->order('id desc')
  132. ->page($page, $limit)
  133. ->select();
  134. // 处理数据
  135. $dataList = [];
  136. foreach ($list ?: [] as $item) {
  137. $itemArr = $item->toArray();
  138. // 获取发送者信息
  139. $user = User::find($item->user_id);
  140. $itemArr['user_nickname'] = $user ? ($user->nickname ?? '') : '';
  141. // 获取接收者信息
  142. $toUser = User::find($item->to_user_id);
  143. $itemArr['to_user_nickname'] = $toUser ? ($toUser->nickname ?? '') : '';
  144. $itemArr['type_text'] = ChatRecord::getTypeText($item->type);
  145. $itemArr['is_read_text'] = $item->is_read == 1 ? '已读' : '未读';
  146. $itemArr['create_time_text'] = date('Y-m-d H:i:s', $item->create_time);
  147. $dataList[] = $itemArr;
  148. }
  149. return $this->success('获取成功', [
  150. 'list' => $dataList,
  151. 'total' => $total,
  152. 'page' => $page,
  153. 'limit' => $limit,
  154. ]);
  155. }
  156. /**
  157. * 获取用户聊天会话列表
  158. * @param Request $request
  159. * @return Response
  160. */
  161. public function sessionList(Request $request): Response
  162. {
  163. $data = $request->get();
  164. $page = (int)($data['page'] ?? 1);
  165. $limit = (int)($data['limit'] ?? 15);
  166. $userId = isset($data['user_id']) ? (int)$data['user_id'] : 0;
  167. if ($userId <= 0) {
  168. return $this->fail('用户ID不能为空');
  169. }
  170. $relations = ChatUserRelation::where('user_id', $userId)
  171. ->whereOr('to_user_id', $userId)
  172. ->order('update_time desc')
  173. ->page($page, $limit)
  174. ->select();
  175. $total = ChatUserRelation::where('user_id', $userId)
  176. ->whereOr('to_user_id', $userId)
  177. ->count();
  178. $dataList = [];
  179. foreach ($relations ?: [] as $relation) {
  180. $otherUserId = $relation->user_id == $userId ? $relation->to_user_id : $relation->user_id;
  181. $user = User::find($otherUserId);
  182. $dataList[] = [
  183. 'id' => $relation->id,
  184. 'user_id' => $otherUserId,
  185. 'nickname' => $user ? ($user->nickname ?? '') : '',
  186. 'phone' => $user ? ($user->phone ?? '') : '',
  187. 'is_deduct' => $relation->is_deduct,
  188. 'is_deduct_text' => $relation->is_deduct == 1 ? '已扣次数' : '未扣次数',
  189. 'create_time' => date('Y-m-d H:i:s', $relation->create_time),
  190. 'update_time' => date('Y-m-d H:i:s', $relation->update_time),
  191. ];
  192. }
  193. return $this->success('获取成功', [
  194. 'list' => $dataList,
  195. 'total' => $total,
  196. 'page' => $page,
  197. 'limit' => $limit,
  198. ]);
  199. }
  200. /**
  201. * 获取用户聊天次数余额列表
  202. * @param Request $request
  203. * @return Response
  204. */
  205. public function userBalanceList(Request $request): Response
  206. {
  207. $data = $request->get();
  208. $page = (int)($data['page'] ?? 1);
  209. $limit = (int)($data['limit'] ?? 15);
  210. $keyword = trim($data['keyword'] ?? '');
  211. $query = User::where('chat_num', '>', 0);
  212. if (!empty($keyword)) {
  213. $query->where(function ($q) use ($keyword) {
  214. $q->whereOr([
  215. ['nickname', 'like', '%' . $keyword . '%'],
  216. ['phone', 'like', '%' . $keyword . '%'],
  217. ]);
  218. });
  219. }
  220. $total = $query->count();
  221. $list = $query->order('chat_num desc')
  222. ->page($page, $limit)
  223. ->select();
  224. $dataList = [];
  225. foreach ($list ?: [] as $item) {
  226. $dataList[] = [
  227. 'id' => $item->id,
  228. 'user_id' => $item->id,
  229. 'nickname' => $item->nickname ?? '',
  230. 'phone' => $item->phone ?? '',
  231. 'chat_num' => $item->chat_num ?? 0,
  232. 'avatar' => $item->avatar ?? '',
  233. ];
  234. }
  235. return $this->success('获取成功', [
  236. 'list' => $dataList,
  237. 'total' => $total,
  238. 'page' => $page,
  239. 'limit' => $limit,
  240. ]);
  241. }
  242. /**
  243. * 管理员给用户添加聊天次数
  244. * @param Request $request
  245. * @return Response
  246. */
  247. public function addBalance(Request $request): Response
  248. {
  249. $data = $request->post();
  250. $userId = (int)($data['user_id'] ?? 0);
  251. $num = (int)($data['num'] ?? 0);
  252. $remark = trim($data['remark'] ?? '管理员操作');
  253. if ($userId <= 0) {
  254. return $this->fail('用户ID错误');
  255. }
  256. if ($num <= 0) {
  257. return $this->fail('添加数量必须大于0');
  258. }
  259. $user = User::find($userId);
  260. if (!$user) {
  261. return $this->fail('用户不存在');
  262. }
  263. $result = ChatBalanceService::add($userId, $num, ChatBalanceLog::TYPE_ADMIN_ADD, $remark);
  264. if ($result) {
  265. return $this->success('添加成功');
  266. }
  267. return $this->fail('添加失败');
  268. }
  269. /**
  270. * 管理员扣除用户聊天次数
  271. * @param Request $request
  272. * @return Response
  273. */
  274. public function subBalance(Request $request): Response
  275. {
  276. $data = $request->post();
  277. $userId = (int)($data['user_id'] ?? 0);
  278. $num = (int)($data['num'] ?? 0);
  279. $remark = trim($data['remark'] ?? '管理员操作');
  280. if ($userId <= 0) {
  281. return $this->fail('用户ID错误');
  282. }
  283. if ($num <= 0) {
  284. return $this->fail('扣除数量必须大于0');
  285. }
  286. $user = User::find($userId);
  287. if (!$user) {
  288. return $this->fail('用户不存在');
  289. }
  290. $currentBalance = (int)($user->chat_num ?? 0);
  291. if ($currentBalance < $num) {
  292. return $this->fail('用户聊天次数不足,当前余额:' . $currentBalance);
  293. }
  294. $result = ChatBalanceService::sub($userId, $num, ChatBalanceLog::TYPE_ADMIN_SUB, $remark);
  295. if ($result) {
  296. return $this->success('扣除成功');
  297. }
  298. return $this->fail('扣除失败');
  299. }
  300. /**
  301. * 获取聊天统计数据
  302. * @return Response
  303. */
  304. public function statistics(): Response
  305. {
  306. // 总订单数
  307. $totalOrders = ChatOrder::count();
  308. // 已支付订单数
  309. $paidOrders = ChatOrder::where('status', ChatOrder::STATUS_PAID)->count();
  310. // 总聊天次数消耗
  311. $totalConsume = ChatBalanceLog::where('type', ChatBalanceLog::TYPE_FIRST_CHAT)->sum('num');
  312. // 购买次数总额
  313. $totalBuy = ChatBalanceLog::where('type', ChatBalanceLog::TYPE_BUY)->sum('num');
  314. // 有聊天次数的用户数
  315. $usersWithBalance = User::where('chat_num', '>', 0)->count();
  316. // 总会话数
  317. $totalSessions = ChatUserRelation::count();
  318. return $this->success('获取成功', [
  319. 'total_orders' => $totalOrders,
  320. 'paid_orders' => $paidOrders,
  321. 'total_consume' => abs((int)$totalConsume),
  322. 'total_buy' => (int)$totalBuy,
  323. 'users_with_balance' => $usersWithBalance,
  324. 'total_sessions' => $totalSessions,
  325. ]);
  326. }
  327. /**
  328. * 删除聊天会话记录
  329. * @param Request $request
  330. * @return Response
  331. */
  332. public function deleteSession(Request $request): Response
  333. {
  334. $data = $request->post();
  335. $relationId = (int)($data['id'] ?? 0);
  336. if ($relationId <= 0) {
  337. return $this->fail('会话ID错误');
  338. }
  339. $relation = ChatUserRelation::find($relationId);
  340. if (!$relation) {
  341. return $this->fail('会话不存在');
  342. }
  343. // 删除会话关系
  344. $relation->delete();
  345. return $this->success('删除成功');
  346. }
  347. /**
  348. * 删除聊天记录
  349. * @param Request $request
  350. * @return Response
  351. */
  352. public function deleteRecord(Request $request): Response
  353. {
  354. $data = $request->post();
  355. $id = (int)($data['id'] ?? 0);
  356. if ($id <= 0) {
  357. return $this->fail('记录ID错误');
  358. }
  359. $record = ChatRecord::find($id);
  360. if (!$record) {
  361. return $this->fail('记录不存在');
  362. }
  363. $record->delete();
  364. return $this->success('删除成功');
  365. }
  366. /**
  367. * 设置聊天价格配置
  368. * @param Request $request
  369. * @return Response
  370. */
  371. public function setConfig(Request $request): Response
  372. {
  373. $data = $request->post();
  374. $chatPrice = (int)($data['chat_price'] ?? 0);
  375. if ($chatPrice <= 0) {
  376. return $this->fail('价格必须大于0');
  377. }
  378. $sys = \app\model\api\Sys::find(1);
  379. if (!$sys) {
  380. return $this->fail('系统配置不存在');
  381. }
  382. $sys->chat_price = $chatPrice;
  383. if ($sys->save()) {
  384. return $this->success('设置成功');
  385. }
  386. return $this->fail('设置失败');
  387. }
  388. /**
  389. * 获取聊天价格配置
  390. * @return Response
  391. */
  392. public function getConfig(): Response
  393. {
  394. $sys = \app\model\api\Sys::find(1);
  395. $price = $sys ? (int)($sys->chat_price ?? 0) : 0;
  396. return $this->success('获取成功', [
  397. 'chat_price' => $price,
  398. ]);
  399. }
  400. }