UserLogic.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | likeshop100%开源免费商用商城系统
  4. // +----------------------------------------------------------------------
  5. // | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
  6. // | 开源版本可自由商用,可去除界面版权logo
  7. // | 商业版本务必购买商业授权,以免引起法律纠纷
  8. // | 禁止对系统程序代码以任何目的,任何形式的再发布
  9. // | gitee下载:https://gitee.com/likeshop_gitee
  10. // | github下载:https://github.com/likeshop-github
  11. // | 访问官网:https://www.likeshop.cn
  12. // | 访问社区:https://home.likeshop.cn
  13. // | 访问手册:http://doc.likeshop.cn
  14. // | 微信公众号:likeshop技术社区
  15. // | likeshop团队 版权所有 拥有最终解释权
  16. // +----------------------------------------------------------------------
  17. // | author: likeshopTeam
  18. // +----------------------------------------------------------------------
  19. namespace app\adminapi\logic\user;
  20. use app\adminapi\logic\distribution\DistributionLogic;
  21. use app\common\{logic\BaseLogic,
  22. model\User,
  23. model\Order,
  24. enum\PayEnum,
  25. model\UserLevel,
  26. model\UserLabel,
  27. enum\CouponEnum,
  28. model\CouponList,
  29. enum\AccountLogEnum,
  30. model\UserLabelIndex,
  31. logic\AccountLogLogic,
  32. enum\UserTerminalEnum};
  33. use think\facade\Db;
  34. use think\Model;
  35. /**
  36. * 用户逻辑层
  37. * Class UserLogic
  38. * @package app\adminapi\logic\user
  39. */
  40. class UserLogic extends BaseLogic
  41. {
  42. /**
  43. * @notes 用户概况页面
  44. * @return array
  45. * @author cjhao
  46. * @date 2021/8/17 14:58
  47. */
  48. public function index():array
  49. {
  50. $today = strtotime(date('Y-m-d'));
  51. //用户数
  52. $userCount = User::count();
  53. //今日新增用户数
  54. $userNewCount = User::where('create_time','>=',$today)->count();
  55. //成交用户数
  56. $repetitionCount = Order::where(['pay_status'=>PayEnum::ISPAID])->count();
  57. //复购用户数
  58. $purchaseCount = Order::where(['pay_status'=>PayEnum::ISPAID])
  59. ->group('user_id')
  60. ->having('count(user_id) >= 2')
  61. ->count();
  62. $dayList = day_time(14,true);
  63. $dayList = array_reverse($dayList);
  64. $echarts_data = [];
  65. //图表数据
  66. foreach ($dayList as $dayKey => $dayVal){
  67. $newUserCount = User::whereTime('create_time','between',[$dayVal,$dayVal+86399])->count();
  68. $echarts_data[] = [
  69. 'day' => date('m-d',$dayVal),
  70. 'user_new_count' => $newUserCount,
  71. ];
  72. }
  73. $data = [
  74. 'user_count' => $userCount,
  75. 'user_new_count' => $userNewCount,
  76. 'repetition_count' => $repetitionCount,
  77. 'purchase_count' => $purchaseCount,
  78. 'echarts_data' => $echarts_data,
  79. ];
  80. return $data;
  81. }
  82. /**
  83. * @notes 用户搜索条件列表
  84. * @return array
  85. * @throws \think\db\exception\DataNotFoundException
  86. * @throws \think\db\exception\DbException
  87. * @throws \think\db\exception\ModelNotFoundException
  88. * @author cjhao
  89. * @date 2021/8/10 16:58
  90. */
  91. public function otherLists(): array
  92. {
  93. $userLevel = UserLevel::order('rank', 'asc')->field('id,name')->select();
  94. $userLabel = UserLabel::field('id,name')->select();
  95. $sourceList = UserTerminalEnum::getTermInalDesc();
  96. return [
  97. 'user_level_list' => $userLevel,
  98. 'user_label_list' => $userLabel,
  99. 'source_list' => $sourceList,
  100. ];
  101. }
  102. /**
  103. * @notes 设置用户标签
  104. * @param array $param
  105. * @return bool
  106. * @throws \Exception
  107. * @author cjhao
  108. * @date 2021/8/17 11:43
  109. */
  110. public function setLabel(array $param): bool
  111. {
  112. $userIds = $param['user_ids'] ?? [];
  113. $labelIds = $param['label_ids'] ?? [];
  114. $labelIds = UserLabel::where(['id' => $labelIds])->column('id');
  115. //当前用户已绑定的标签
  116. $userLabelIndexList = UserLabelIndex::where(['user_id' => $userIds])
  117. ->group('user_id')
  118. ->column('group_concat(label_id Separator \',\') as user_label_id', 'user_id');
  119. $addData = [];
  120. foreach ($userIds as $userId) {
  121. $userLabelIndex = $userLabelIndexList[$userId]['user_label_id'] ?? '';
  122. $userLabelIds = explode(',', $userLabelIndex);
  123. foreach ($labelIds as $labelId) {
  124. //该用户已有该标签,跳过
  125. if (in_array($labelId, $userLabelIds)) {
  126. continue;
  127. }
  128. $addData[] = [
  129. 'user_id' => $userId,
  130. 'label_id' => $labelId,
  131. ];
  132. }
  133. }
  134. //写入数据
  135. if ($addData) {
  136. (new UserLabelIndex)->saveAll($addData);
  137. }
  138. return true;
  139. }
  140. /**
  141. * @notes 用户详情
  142. * @param int $userId
  143. * @return mixed
  144. * @throws \think\db\exception\DataNotFoundException
  145. * @throws \think\db\exception\DbException
  146. * @throws \think\db\exception\ModelNotFoundException
  147. * @author cjhao
  148. * @date 2021/8/18 15:52
  149. */
  150. public function detail(int $userId)
  151. {
  152. $user = User::with('userLevel')
  153. ->field('id,sn,nickname,avatar,real_name,sex,mobile,birthday,code,level,create_time,login_time,total_order_amount,total_order_num,user_money,user_earnings,user_money+user_earnings as total_user_money,user_integral,disable,register_source,inviter_id,first_leader,disable,user_delete,admin_update_leader')
  154. ->find($userId);
  155. $user->userLabelIndex;
  156. $user = $user->toArray();
  157. $labels = array_column($user['userLabelIndex'],'name');
  158. $labels = implode('、',$labels);
  159. //交易信息
  160. $latelyTime = Order::where(['user_id'=>$userId])->order('id desc')->value('create_time');
  161. //分销信息
  162. // $distribution = DistributionLogic::info($user);
  163. //基本信息
  164. $data = [
  165. 'user_info' => [//用户信息
  166. 'id' => $user['id'],
  167. 'sn' => $user['sn'],
  168. 'nickname' => $user['nickname'],
  169. 'real_name' => $user['real_name'],
  170. 'avatar' => $user['avatar'],
  171. 'sex' => $user['sex'],
  172. 'birthday' => $user['birthday'],
  173. 'mobile' => $user['mobile'],
  174. 'code' => $user['code'],
  175. 'level' => $user['level'],
  176. 'level_name' => $user['name'],
  177. 'labels' => $labels,
  178. 'create_time' => $user['create_time'],
  179. 'login_time' => $user['login_time'],
  180. 'register_source' => UserTerminalEnum::getTermInalDesc($user['register_source']),
  181. 'total_user_money' => $user['total_user_money'], //钱包金额
  182. 'user_money' => $user['user_money'], //可用金额
  183. 'user_earnings' => $user['user_earnings'], //可提现金额
  184. 'user_integral' => $user['user_integral'], //积分
  185. 'disable' => $user['disable'], //禁用状态
  186. 'user_delete' => $user['user_delete'],
  187. 'coupon_num' => CouponList::where([
  188. ['user_id','=',$userId],
  189. ['status','=',CouponEnum::USE_STATUS_NOT],
  190. ['invalid_time', '>=', time()]
  191. ])->count(),
  192. 'inviter' => User::getInviterInfo($user['inviter_id'], $user['id']), // 邀请人信息
  193. 'first_leader_info' => User::getFirstLeader($user), // 上级分销商信息
  194. ],
  195. 'transaction' => [//交易信息
  196. 'total_order_amount'=> $user['total_order_amount'],
  197. 'total_order_num' => $user['total_order_num'],
  198. 'customer_price' => $user['total_order_num'] ? round($user['total_order_amount'] / $user['total_order_num'],2) : 0,
  199. 'lately_order_time' => $latelyTime ? date('Y-m-d H:i:s',$latelyTime) : '',
  200. ],
  201. ];
  202. return $data;
  203. }
  204. /**
  205. * @notes 更新用户信息
  206. * @param array $params
  207. * @return bool
  208. * @author cjhao
  209. * @date 2021/8/18 17:21
  210. */
  211. public function setUserInfo(array $params):bool
  212. {
  213. User::where(['id'=>$params['user_id']])->update([$params['field']=>$params['value']]);
  214. return true;
  215. }
  216. /**
  217. * @notes 设置用户标签
  218. * @param array $params
  219. * @return bool
  220. * @throws \Exception
  221. * @author cjhao
  222. * @date 2021/8/19 11:31
  223. */
  224. public function setUserLabel(array $params):bool {
  225. //先删除用户标签,在重新设置用户标签
  226. UserLabelIndex::where(['user_id'=>$params['user_id']])->delete();
  227. $addData = [];
  228. foreach ($params['label_ids'] as $labelId){
  229. $addData[] = [
  230. 'user_id' => $params['user_id'],
  231. 'label_id' => $labelId,
  232. ];
  233. }
  234. if($addData){
  235. (new UserLabelIndex)->saveAll($addData);
  236. }
  237. return true;
  238. }
  239. /**
  240. * @notes 调整用户余额
  241. * @param array $params
  242. * @return string
  243. * @author cjhao
  244. * @date 2021/9/10 18:15
  245. */
  246. public function adjustUserWallet(array $params)
  247. {
  248. Db::startTrans();
  249. try {
  250. $user = User::find($params['user_id']);
  251. switch ($params['type']){
  252. case 1:
  253. //增加
  254. if(1 == $params['action']){
  255. //调整可用余额
  256. $user->user_money = $user->user_money + $params['num'];
  257. $user->save();
  258. //记录日志
  259. AccountLogLogic::add($user->id, AccountLogEnum::BNW_INC_ADMIN, AccountLogEnum::INC, $params['num'], '', $params['remark'] ?? '');
  260. }else{
  261. $user->user_money = $user->user_money - $params['num'];
  262. $user->save();
  263. //记录日志
  264. AccountLogLogic::add($user->id, AccountLogEnum::BNW_DEC_ADMIN,AccountLogEnum::DEC, $params['num'], '', $params['remark'] ?? '');
  265. }
  266. break;
  267. case 2:
  268. //增加
  269. if(1 == $params['action']){
  270. //调整可用余额
  271. $user->user_earnings = $user->user_earnings + $params['num'];
  272. $user->save();
  273. //记录日志
  274. AccountLogLogic::add($user->id, AccountLogEnum::BW_INC_ADMIN, AccountLogEnum::INC, $params['num'], '', $params['remark'] ?? '');
  275. }else{
  276. $user->user_earnings = $user->user_earnings - $params['num'];
  277. $user->save();
  278. //记录日志
  279. AccountLogLogic::add($user->id, AccountLogEnum::BW_DEC_ADMIN,AccountLogEnum::DEC, $params['num'], '', $params['remark'] ?? '');
  280. }
  281. break;
  282. case 3:
  283. //增加
  284. if(1 == $params['action']){
  285. //调整可用余额
  286. $user->user_integral = $user->user_integral + $params['num'];
  287. $user->save();
  288. //记录日志
  289. AccountLogLogic::add($user->id, AccountLogEnum::INTEGRAL_INC_ADMIN, AccountLogEnum::INC, $params['num'], '', $params['remark'] ?? '');
  290. }else{
  291. $user->user_integral = $user->user_integral - $params['num'];
  292. $user->save();
  293. //记录日志
  294. AccountLogLogic::add($user->id, AccountLogEnum::INTEGRAL_DEC_ADMIN,AccountLogEnum::DEC, $params['num'], '', $params['remark'] ?? '');
  295. }
  296. break;
  297. }
  298. Db::commit();
  299. return true;
  300. } catch (\Exception $e) {
  301. Db::rollback();
  302. return $e->getMessage();
  303. }
  304. }
  305. /**
  306. * @notes 用户信息
  307. * @author Tab
  308. * @date 2021/9/13 19:33
  309. */
  310. public static function info($params)
  311. {
  312. $info = User::findOrEmpty($params['user_id'])->toArray();
  313. if (empty($info)) {
  314. $info = '';
  315. } else {
  316. $info = $info['sn'] . '(' . $info['nickname'] . ')';
  317. }
  318. $count = User::where('inviter_id', $params['user_id'])->count();
  319. return [
  320. 'name' => $info,
  321. 'count' => $count
  322. ];
  323. }
  324. /**
  325. * @notes 上级分销商调整信息
  326. * @param $params
  327. * @return array
  328. * @author Tab
  329. * @date 2021/9/14 10:50
  330. */
  331. public static function adjustFirstLeaderInfo($params)
  332. {
  333. $userField = [
  334. 'id',
  335. 'sn',
  336. 'nickname',
  337. 'first_leader'
  338. ];
  339. $user = User::field($userField)->findOrEmpty($params['user_id'])->toArray();
  340. if(empty($user['first_leader'])) {
  341. $firstLeader = '系统';
  342. } else {
  343. $firstLeaderField = [
  344. 'id',
  345. 'sn',
  346. 'nickname',
  347. ];
  348. $firstLeader = User::field($firstLeaderField)->findOrEmpty($user['first_leader'])->toArray();
  349. }
  350. return [
  351. 'user' => $user,
  352. 'first_leader' => $firstLeader
  353. ];
  354. }
  355. /**
  356. * @notes
  357. * @param $params
  358. * @return bool
  359. * @author Tab
  360. * @date 2021/9/14 11:42
  361. */
  362. public static function adjustFirstLeader($params)
  363. {
  364. Db::startTrans();
  365. try {
  366. switch($params['type']) {
  367. // 指定推荐人
  368. case 'assign':
  369. $formatData = self::assignFirstLeader($params);
  370. break;
  371. // 设置推荐人为系统,即清空上级
  372. case 'system':
  373. $formatData = self::clearFirstLeader($params);
  374. break;
  375. }
  376. $user = User::findOrEmpty($params['user_id']);
  377. // 旧关系链
  378. if (!empty($user->ancestor_relation)) {
  379. $old_ancestor_relation = $user->id . ',' .$user->ancestor_relation;
  380. } else {
  381. $old_ancestor_relation = $user->id;
  382. }
  383. // 更新当前用户的分销关系
  384. User::where(['id' => $params['user_id']])->update($formatData);
  385. //更新当前用户下级的分销关系
  386. $data = [
  387. 'second_leader' => $formatData['first_leader'],
  388. 'third_leader' => $formatData['second_leader'],
  389. 'update_time' => time(),
  390. ];
  391. User::where(['first_leader' => $params['user_id']])->update($data);
  392. //更新当前用户下下级的分销关系
  393. $data = [
  394. 'third_leader' => $formatData['first_leader'],
  395. 'update_time' => time()
  396. ];
  397. User::where(['second_leader' => $params['user_id']])->update($data);
  398. //更新当前用户所有后代的关系链
  399. $posterityArr = User::field('id,ancestor_relation')
  400. ->whereFindInSet('ancestor_relation', $params['user_id'])
  401. ->select()
  402. ->toArray();
  403. $updateData = [];
  404. $replace_ancestor_relation = $params['user_id'] . ','. $formatData['ancestor_relation'];
  405. foreach($posterityArr as $item) {
  406. $replace = substr($item['ancestor_relation'], strpos($item['ancestor_relation'], $params['user_id']));
  407. $updateData[] = [
  408. 'id' => $item['id'],
  409. 'ancestor_relation' => trim(str_replace($old_ancestor_relation, $replace_ancestor_relation, $item['ancestor_relation']), ',')
  410. ];
  411. }
  412. // 批量更新
  413. (new User())->saveAll($updateData);
  414. Db::commit();
  415. return true;
  416. } catch(\Exception $e) {
  417. Db::rollback();
  418. self::setError($e->getMessage());
  419. return false;
  420. }
  421. }
  422. /**
  423. * @notes 指定上级分销商
  424. * @param $params
  425. * @return array
  426. * @throws \think\Exception
  427. * @author Tab
  428. * @date 2021/9/14 11:44
  429. */
  430. public static function assignFirstLeader($params)
  431. {
  432. if (empty($params['first_id'])) {
  433. throw new \think\Exception('请选择上级分销商');
  434. }
  435. if ($params['first_id'] == $params['user_id']) {
  436. throw new \think\Exception('上级分销商不可以选择自己');
  437. }
  438. $firstLeader = User::field(['id', 'first_leader', 'second_leader', 'third_leader', 'ancestor_relation'])
  439. ->where('id', $params['first_id'])
  440. ->findOrEmpty()
  441. ->toArray();
  442. if(empty($firstLeader)) {
  443. throw new \think\Exception('分销商不存在');
  444. }
  445. $ancestorRelation =explode(',', $firstLeader['ancestor_relation']);
  446. if(!empty($ancestorRelation) && in_array($params['user_id'], $ancestorRelation)) {
  447. throw new \think\Exception('不允许填写自己任一下级的邀请码');
  448. }
  449. // 上级
  450. $first_leader_id = $firstLeader['id'];
  451. // 上上级
  452. $second_leader_id = $firstLeader['first_leader'];
  453. // 上上上级
  454. $third_leader_id = $firstLeader['second_leader'];
  455. // 拼接关系链
  456. $firstLeader['ancestor_relation'] = $firstLeader['ancestor_relation'] ?: ''; // 清空null值及0
  457. $my_ancestor_relation = $first_leader_id. ',' . $firstLeader['ancestor_relation'];
  458. // 去除两端逗号
  459. $my_ancestor_relation = trim($my_ancestor_relation, ',');
  460. $data = [
  461. 'first_leader' => $first_leader_id,
  462. 'second_leader' => $second_leader_id,
  463. 'third_leader' => $third_leader_id,
  464. 'ancestor_relation' => $my_ancestor_relation,
  465. 'admin_update_leader' => 1,
  466. ];
  467. return $data;
  468. }
  469. /**
  470. * @notes 清空上级
  471. * @param $params
  472. * @return array
  473. * @author Tab
  474. * @date 2021/9/14 11:46
  475. */
  476. public static function clearFirstLeader($params)
  477. {
  478. $data = [
  479. 'first_leader' => 0,
  480. 'second_leader' => 0,
  481. 'third_leader' => 0,
  482. 'ancestor_relation' => '',
  483. 'admin_update_leader' => 1,
  484. ];
  485. return $data;
  486. }
  487. }