CommentService.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. <?php
  2. namespace app\common\Service\Goods;
  3. use app\common\model\Comment;
  4. use app\common\model\Order;
  5. use app\common\model\OrderAction;
  6. use app\common\Enum\OrderEnum;
  7. use app\common\Enum\CommentEnum;
  8. use think\Db;
  9. use think\Exception;
  10. use app\common\exception\BusinessException;
  11. use app\common\Enum\StatusEnum;
  12. class CommentService
  13. {
  14. /**
  15. * 获取评论列表
  16. * @param array $params 查询参数
  17. * @return \think\Paginator
  18. */
  19. public static function getCommentList($params = [])
  20. {
  21. $goods_id = isset($params['goods_id']) ? (int)$params['goods_id'] : 0;
  22. $pid = isset($params['pid']) ? (int)$params['pid'] : 0;
  23. $has_picture = isset($params['has_picture']) ? (int)$params['has_picture'] : '';
  24. $orderBy = isset($params['order_by']) ? $params['order_by'] : 'id';
  25. $orderWay = isset($params['order_way']) ? strtolower($params['order_way']) : 'desc';
  26. $page = isset($params['page']) ? (int)$params['page'] : 1;
  27. $pageSize = isset($params['page_size']) ? $params['page_size'] : 10;
  28. $orderWay = in_array($orderWay, ['asc', 'desc']) ? $orderWay : 'desc';
  29. $where = [
  30. 'evaluate_status' => CommentEnum::EVALUATE_STATUS_APPROVED,
  31. 'status' => StatusEnum::ENABLED
  32. ];
  33. if ($goods_id > 0) {
  34. $where['goods_id'] = $goods_id;
  35. }
  36. if ($pid !== '') {
  37. $where['pid'] = $pid;
  38. }
  39. // 添加有图评论过滤
  40. if ($has_picture !== '') {
  41. $where['has_picture'] = $has_picture;
  42. }
  43. $order = $orderBy == 'rand' ? 'rand()' : (in_array($orderBy, ['pid', 'id', 'createtime', 'updatetime']) ? "{$orderBy} {$orderWay}" : "id {$orderWay}");
  44. $list = Comment::with(['user', 'reply' => function ($query) {
  45. $query->with(['manage' => function ($user) {
  46. $user->field('id,nickname');
  47. }]);
  48. }])
  49. ->where($where)
  50. ->order($order)
  51. ->paginate($pageSize, false, ['page' => $page]);
  52. return $list;
  53. }
  54. /**
  55. * 获取商品好评度
  56. * @param int $goods_id 商品ID
  57. * @return float
  58. */
  59. public static function degree($goods_id)
  60. {
  61. $total = Comment::where('goods_id', $goods_id)
  62. ->where('pid', 0)
  63. ->where('evaluate_status', CommentEnum::EVALUATE_STATUS_APPROVED)
  64. ->where('status', CommentEnum::STATUS_NORMAL)
  65. ->sum('star');
  66. $favorable = Comment::where('goods_id', $goods_id)
  67. ->where('pid', 0)
  68. ->where('evaluate_status', CommentEnum::EVALUATE_STATUS_APPROVED)
  69. ->where('status', CommentEnum::STATUS_NORMAL)
  70. ->where('star', '>', 3)
  71. ->sum('star');
  72. if (!$total || !$favorable) {
  73. return 100;
  74. }
  75. return bcmul(bcdiv($favorable, $total, 2), 100);
  76. }
  77. // 获取 总计评论数 和 第一个评论数据
  78. public static function getCommentCountAndFirstComment($goods_id = 0)
  79. {
  80. $total = Comment::where('goods_id', $goods_id)
  81. ->where('pid', 0)
  82. ->where('evaluate_status', CommentEnum::EVALUATE_STATUS_APPROVED)
  83. ->where('status', StatusEnum::ENABLED)
  84. ->count();
  85. $comment = Comment::where('goods_id', $goods_id)
  86. ->with(['user' => function ($query) {
  87. $query->field('id,nickname,avatar');
  88. }])
  89. ->where('pid', 0)
  90. ->where('evaluate_status', CommentEnum::EVALUATE_STATUS_APPROVED)
  91. ->where('status', StatusEnum::ENABLED)
  92. ->order('id desc')
  93. ->find();
  94. if (!empty($comment)) {
  95. $comment->user->avatar = cdnurl($comment->user->avatar, true);
  96. }
  97. return [
  98. 'total' => $total,
  99. 'comment' => $comment
  100. ];
  101. }
  102. /**
  103. * 获取用户评论列表
  104. * @param int $user_id 用户ID
  105. * @param int $page 页码
  106. * @param int $pagesize 每页数量
  107. * @return \think\Paginator
  108. */
  109. public static function getUserCommentList($user_id, $page = 1, $pagesize = 10)
  110. {
  111. $list = Comment::with([
  112. 'Goods' => function ($query) {
  113. $query->field('id,title,image');
  114. }
  115. ])
  116. ->where('user_id', $user_id)
  117. ->where('pid', 0)
  118. ->where('evaluate_status', CommentEnum::EVALUATE_STATUS_APPROVED)
  119. ->where('status', CommentEnum::STATUS_NORMAL)
  120. ->order('createtime desc')
  121. ->paginate($pagesize, false, ['page' => $page]);
  122. return $list;
  123. }
  124. /**
  125. * 添加评论
  126. * @param int $user_id 用户ID
  127. * @param int $order_id 订单ID
  128. * @param array $remark 评论内容
  129. * @param int $pid 父评论ID
  130. * @return bool
  131. * @throws Exception
  132. */
  133. public static function addComment($user_id, $order_id, $remark, $pid = 0)
  134. {
  135. // 验证订单
  136. $order = Order::with(['OrderGoods'])
  137. ->where('id', $order_id)
  138. ->where('order_status', OrderEnum::STATUS_CONFIRM)
  139. ->where('user_id', $user_id)
  140. ->find();
  141. if (!$order) {
  142. throw new BusinessException('未找到可评论的订单');
  143. }
  144. // 检查是否已评论
  145. $existComment = Comment::where('user_id', $user_id)
  146. ->where('order_id', $order->id)
  147. ->find();
  148. if ($existComment) {
  149. throw new BusinessException('订单已评论');
  150. }
  151. // 获取可评价的商品
  152. $goods_ids = [];
  153. foreach ($order->order_goods as $item) {
  154. $goods_ids[] = $item['goods_id'];
  155. }
  156. // 验证评论数据并组装
  157. $data = [];
  158. foreach ($remark as $item) {
  159. if (!in_array($item['goods_id'], $goods_ids)) {
  160. throw new BusinessException('存在不可评价的商品');
  161. }
  162. // 处理图片
  163. $images = isset($item['images']) ? $item['images'] : [];
  164. $has_picture = !empty($images) ? CommentEnum::HAS_PICTURE_YES : CommentEnum::HAS_PICTURE_NO;
  165. $data[] = [
  166. 'pid' => $pid,
  167. 'order_id' => $order['id'],
  168. 'user_id' => $user_id,
  169. 'goods_id' => $item['goods_id'],
  170. 'star' => $item['star'],
  171. 'content' => $item['content'],
  172. 'images' => is_array($images) ? implode(',', $images) : $images,
  173. 'has_picture' => $has_picture,
  174. 'ip' => request()->ip(),
  175. 'useragent' => substr(request()->server('HTTP_USER_AGENT'), 0, 255),
  176. 'evaluate_status' => CommentEnum::EVALUATE_STATUS_PENDING,
  177. ];
  178. }
  179. // 事务处理
  180. Db::startTrans();
  181. try {
  182. // 批量添加评论
  183. $comment = new Comment();
  184. $comment->saveAll($data);
  185. // 更新订单状态
  186. $order->order_status = OrderEnum::STATUS_COMMENT;
  187. $order->save();
  188. // 更新订单商品评论状态
  189. foreach ($order->order_goods as $item) {
  190. $item->save(['comment_status' => 1]);
  191. }
  192. // 添加订单日志
  193. OrderAction::push($order->order_sn, '系统', '订单已完成');
  194. Db::commit();
  195. return true;
  196. } catch (\Exception $e) {
  197. Db::rollback();
  198. throw new BusinessException('添加评论失败:' . $e->getMessage());
  199. }
  200. }
  201. /**
  202. * 批量保存评论(原方法保留)
  203. * @param array $data 评论数据
  204. * @return bool
  205. */
  206. public static function saveComments($data)
  207. {
  208. $comment = new Comment();
  209. return $comment->saveAll($data);
  210. }
  211. /**
  212. * 审核评论
  213. * @param int $comment_id 评论ID
  214. * @param int $evaluate_status 评价状态
  215. * @return bool
  216. * @throws Exception
  217. */
  218. public static function auditComment($comment_id, $evaluate_status)
  219. {
  220. if (!CommentEnum::isValidEvaluateStatus($evaluate_status)) {
  221. throw new BusinessException('评价状态参数错误');
  222. }
  223. $comment = Comment::where('id', $comment_id)->find();
  224. if (!$comment) {
  225. throw new BusinessException('评论不存在');
  226. }
  227. $status = $evaluate_status == CommentEnum::EVALUATE_STATUS_APPROVED ?
  228. CommentEnum::STATUS_NORMAL : CommentEnum::STATUS_HIDDEN;
  229. return $comment->save([
  230. 'evaluate_status' => $evaluate_status,
  231. 'status' => $status
  232. ]);
  233. }
  234. /**
  235. * 获取商品评论统计
  236. * @param int $goods_id 商品ID
  237. * @return array
  238. */
  239. public static function getCommentStats($goods_id)
  240. {
  241. $total = Comment::where('goods_id', $goods_id)
  242. ->where('pid', 0)
  243. ->where('evaluate_status', CommentEnum::EVALUATE_STATUS_APPROVED)
  244. ->where('status', CommentEnum::STATUS_NORMAL)
  245. ->count();
  246. $star_counts = [];
  247. for ($i = 1; $i <= 5; $i++) {
  248. $star_counts[$i] = Comment::where('goods_id', $goods_id)
  249. ->where('pid', 0)
  250. ->where('evaluate_status', CommentEnum::EVALUATE_STATUS_APPROVED)
  251. ->where('status', CommentEnum::STATUS_NORMAL)
  252. ->where('star', $i)
  253. ->count();
  254. }
  255. // 有图评论统计
  256. $picture_count = Comment::where('goods_id', $goods_id)
  257. ->where('pid', 0)
  258. ->where('evaluate_status', CommentEnum::EVALUATE_STATUS_APPROVED)
  259. ->where('status', CommentEnum::STATUS_NORMAL)
  260. ->where('has_picture', CommentEnum::HAS_PICTURE_YES)
  261. ->count();
  262. return [
  263. 'total' => $total,
  264. 'star_counts' => $star_counts,
  265. 'picture_count' => $picture_count,
  266. 'degree' => self::degree($goods_id)
  267. ];
  268. }
  269. }