ShareService.php 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. <?php
  2. namespace app\common\Service\Share;
  3. use think\Model;
  4. use app\common\model\user\Share as ShareModel;
  5. use app\common\model\User as UserModel;
  6. use app\common\model\Goods as GoodsModel;
  7. use app\common\Enum\ShareEnum;
  8. use app\common\Enum\PageTypeEnum;
  9. class ShareService
  10. {
  11. /**
  12. * 添加分享记录
  13. * @param int $userId 当前用户ID
  14. * @param array $params 分享参数
  15. * @return mixed
  16. */
  17. public static function addShareLog($userId, $params)
  18. {
  19. // 错误的分享参数
  20. if (empty($params['spm'])) {
  21. return false;
  22. }
  23. $shareId = $params['shareId'];
  24. // 分享用户为空
  25. if ($shareId <= 0) {
  26. return false;
  27. }
  28. // 不能分享给本人
  29. if ($shareId == $userId) {
  30. return false;
  31. }
  32. // 新用户不能分享给老用户 按需打开
  33. // if($user->id < $shareId) {
  34. // return false;
  35. // }
  36. $shareUser = UserModel::where('id', $shareId)->find();
  37. // 分享人不存在
  38. if (!$shareUser) {
  39. return false;
  40. }
  41. // 5分钟内相同的分享信息不保存,防止冗余数据
  42. $lastShareLog = ShareModel::where([
  43. 'user_id' => $userId
  44. ])->where('createtime', '>', time() - 300)->order('id desc')->find();
  45. if ($lastShareLog && $lastShareLog->spm === $params['spm']) {
  46. return $lastShareLog;
  47. }
  48. // 根据页面类型构造页面路径和描述
  49. $pageInfo = self::getPageInfo($params['page'], $params['query'], $shareUser);
  50. $memoText = '通过' . ShareEnum::getFromText($params['from']) . '访问了' . $pageInfo['description'];
  51. $ext = [
  52. 'image' => $pageInfo['image'] ?? "",
  53. 'memo' => $memoText
  54. ];
  55. $shareInfo = ShareModel::create([
  56. 'user_id' => $userId,
  57. 'share_id' => $shareId,
  58. 'spm' => $params['spm'],
  59. 'page' => $pageInfo['path'],
  60. 'query' => $params['query'],
  61. 'platform' => $params['platform'],
  62. 'from' => $params['from'],
  63. 'ext' => $ext
  64. ]);
  65. $data = ['shareInfo' => $shareInfo];
  66. \think\Hook::listen('user_share_after', $data);
  67. return $shareInfo;
  68. }
  69. /**
  70. * 根据页面类型获取页面信息
  71. * @param int $pageType 页面类型
  72. * @param string $query 查询参数
  73. * @param object $shareUser 分享者用户对象(可选)
  74. * @return array
  75. */
  76. private static function getPageInfo($pageType, $query, $shareUser = null)
  77. {
  78. $pageInfo = [
  79. 'path' => '',
  80. 'description' => '',
  81. 'image' => ''
  82. ];
  83. switch ($pageType) {
  84. case PageTypeEnum::HOME:
  85. $pageInfo['path'] = '/pages/index/index';
  86. $pageInfo['description'] = '首页';
  87. break;
  88. case PageTypeEnum::GOODS:
  89. $pageInfo['path'] = '/pages/goods/index';
  90. $pageInfo['description'] = '商品';
  91. $pageInfo = self::appendGoodsInfo($pageInfo, $query);
  92. break;
  93. case PageTypeEnum::GROUP_GOODS:
  94. $pageInfo['path'] = '/pages/goods/groupon';
  95. $pageInfo['description'] = '拼团商品';
  96. $pageInfo = self::appendGoodsInfo($pageInfo, $query);
  97. break;
  98. case PageTypeEnum::SECKILL_GOODS:
  99. $pageInfo['path'] = '/pages/goods/seckill';
  100. $pageInfo['description'] = '秒杀商品';
  101. $pageInfo = self::appendGoodsInfo($pageInfo, $query);
  102. break;
  103. case PageTypeEnum::INVITE_GROUP:
  104. $pageInfo['path'] = '/pages/activity/groupon/detail';
  105. $pageInfo['description'] = '拼团活动';
  106. break;
  107. case PageTypeEnum::AGENT_POSTER:
  108. $pageInfo['path'] = '/pages/agent/poster';
  109. if ($shareUser) {
  110. $pageInfo['description'] = $shareUser->nickname . '的分销海报页';
  111. } else {
  112. $pageInfo['description'] = '分销海报页';
  113. }
  114. break;
  115. default:
  116. $pageInfo['path'] = '/pages/index/index';
  117. $pageInfo['description'] = '未知页面';
  118. break;
  119. }
  120. return $pageInfo;
  121. }
  122. /**
  123. * 为商品页面添加商品信息
  124. * @param array $pageInfo 页面信息
  125. * @param string $goodsId 商品ID
  126. * @return array
  127. */
  128. private static function appendGoodsInfo($pageInfo, $goodsId)
  129. {
  130. if (!empty($goodsId)) {
  131. $goods = GoodsModel::find($goodsId);
  132. if ($goods) {
  133. $pageInfo['description'] .= "[{$goods->title}]";
  134. $pageInfo['image'] = $goods->image;
  135. }
  136. }
  137. return $pageInfo;
  138. }
  139. /**
  140. * 解析spm参数
  141. * @param string $spm smp参数
  142. * @return array|false
  143. */
  144. public static function parseSpm($spm)
  145. {
  146. if (empty($spm)) {
  147. return false;
  148. }
  149. $spmParts = explode('.', $spm);
  150. if (count($spmParts) < 5) {
  151. return false;
  152. }
  153. list($shareId, $pageType, $query, $platform, $from) = $spmParts;
  154. return [
  155. 'shareId' => intval($shareId),
  156. 'pageType' => intval($pageType),
  157. 'query' => $query,
  158. 'platform' => intval($platform),
  159. 'from' => intval($from)
  160. ];
  161. }
  162. /**
  163. * 获取用户的分享记录列表
  164. * @param int $userId 用户ID
  165. * @param int $pageSize 每页数量
  166. * @param string $type 记录类型:shared(我分享的) | received(我收到的分享)
  167. * @return mixed
  168. */
  169. public static function getUserShareLogs($userId, $pageSize = 8, $type = 'received')
  170. {
  171. $query = ShareModel::with(['user' => function ($query) {
  172. return $query->field(['id', 'nickname', 'avatar']);
  173. }]);
  174. // 根据类型设置查询条件
  175. if ($type === 'shared') {
  176. // 查看我分享的记录(我作为分享者)
  177. $query->where('share_id', $userId);
  178. } else {
  179. // 查看我收到的分享记录(我作为被分享者)
  180. $query->where('user_id', $userId);
  181. }
  182. $logs = $query->order('createtime desc')
  183. ->paginate($pageSize);
  184. return $logs;
  185. }
  186. /**
  187. * 获取用户分享统计数据
  188. * @param int $userId 用户ID
  189. * @return array
  190. */
  191. public static function getUserShareStats($userId)
  192. {
  193. return [
  194. 'shared_count' => ShareModel::where('share_id', $userId)->count(), // 我分享的次数
  195. 'received_count' => ShareModel::where('user_id', $userId)->count(), // 收到的分享次数
  196. 'today_shared' => ShareModel::where('share_id', $userId)
  197. ->whereTime('createtime', 'today')
  198. ->count(), // 今日分享次数
  199. 'today_received' => ShareModel::where('user_id', $userId)
  200. ->whereTime('createtime', 'today')
  201. ->count(), // 今日收到分享次数
  202. ];
  203. }
  204. /**
  205. * 获取分享记录详情
  206. * @param int $shareLogId 分享记录ID
  207. * @param int $userId 当前用户ID(用于权限验证)
  208. * @return mixed
  209. */
  210. public static function getShareLogDetail($shareLogId, $userId = 0)
  211. {
  212. $query = ShareModel::with(['user']);
  213. // 如果指定了用户ID,则验证权限(只能查看自己相关的记录)
  214. if ($userId > 0) {
  215. $query->where(function($query) use ($userId) {
  216. $query->whereOr('user_id', $userId)
  217. ->whereOr('share_id', $userId);
  218. });
  219. }
  220. $shareLog = $query->where('id', $shareLogId)->find();
  221. if ($shareLog) {
  222. // 解析SPM参数
  223. $spmInfo = self::parseSpm($shareLog->spm);
  224. if ($spmInfo) {
  225. $shareLog->spm_info = $spmInfo;
  226. $shareLog->page_type_text = PageTypeEnum::getPageTypeText($spmInfo['pageType']);
  227. }
  228. }
  229. return $shareLog;
  230. }
  231. }