User.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\controller\api\user;
  12. use app\common\repositories\store\IntegralRepository;
  13. use app\common\repositories\store\service\StoreServiceRepository;
  14. use app\common\repositories\system\CacheRepository;
  15. use app\common\repositories\user\MemberinterestsRepository;
  16. use app\common\repositories\user\UserBillRepository;
  17. use app\common\repositories\user\UserBrokerageRepository;
  18. use app\common\repositories\user\UserRepository;
  19. use app\common\repositories\user\UserVisitRepository;
  20. use app\validate\api\UserBaseInfoValidate;
  21. use crmeb\basic\BaseController;
  22. use crmeb\services\MiniProgramService;
  23. use crmeb\services\SmsService;
  24. use think\App;
  25. use think\db\exception\DataNotFoundException;
  26. use think\db\exception\DbException;
  27. use think\db\exception\ModelNotFoundException;
  28. class User extends BaseController
  29. {
  30. protected $repository;
  31. protected $user;
  32. public function __construct(App $app, UserRepository $repository)
  33. {
  34. parent::__construct($app);
  35. $this->repository = $repository;
  36. $this->user = $this->request->userInfo();
  37. }
  38. /**
  39. * @return mixed
  40. * @author xaboy
  41. * @day 2020/6/22
  42. */
  43. public function spread_image()
  44. {
  45. $type = $this->request->param('type');
  46. $res = $type == 'routine'
  47. ? $this->repository->routineSpreadImage($this->user)
  48. : $this->repository->wxSpreadImage($this->user);
  49. return app('json')->success($res);
  50. }
  51. public function spread_image_v2()
  52. {
  53. $type = $this->request->param('type');
  54. $user = $this->user;
  55. $siteName = systemConfig('site_name');
  56. $qrcode = $type == 'routine'
  57. ? $this->repository->mpQrcode($user)
  58. : $this->repository->wxQrcode($user);
  59. $poster = systemGroupData('spread_banner');
  60. $nickname = $user['nickname'];
  61. $mark = '邀请您加入' . $siteName;
  62. return app('json')->success(compact('qrcode', 'poster', 'nickname', 'mark'));
  63. }
  64. public function spread_info()
  65. {
  66. $user = $this->user;
  67. $make = app()->make(UserBrokerageRepository::class);
  68. $user->append(['one_level_count', 'lock_brokerage', 'two_level_count', 'spread_total', 'yesterday_brokerage', 'total_extract', 'total_brokerage', 'total_brokerage_price']);
  69. $show_brokerage = (bool)$make->search(['type' => 0])->count();
  70. $data = [
  71. 'total_brokerage_price' => $user->total_brokerage_price,
  72. 'lock_brokerage' => $user->lock_brokerage,
  73. 'one_level_count' => $user->one_level_count,
  74. 'two_level_count' => $user->two_level_count,
  75. 'spread_total' => $user->spread_total,
  76. 'yesterday_brokerage' => $user->yesterday_brokerage,
  77. 'total_extract' => $user->total_extract,
  78. 'total_brokerage' => $user->total_brokerage,
  79. 'brokerage_price' => $user->brokerage_price,
  80. 'show_brokerage' => $show_brokerage,
  81. 'brokerage' => $show_brokerage ? ($user->brokerage ?: ['brokerage_level' => 0, 'brokerage_name' => '普通分销员']) : null,
  82. 'now_money' => $user->now_money,
  83. 'broken_day' => (int)systemConfig('lock_brokerage_timer'),
  84. 'user_extract_min' => (int)systemConfig('user_extract_min'),
  85. ];
  86. return app('json')->success($data);
  87. }
  88. public function brokerage_all()
  89. {
  90. return app('json')->success(app()->make(UserBrokerageRepository::class)->all(0));
  91. }
  92. public function brokerage_info()
  93. {
  94. $make = app()->make(UserBrokerageRepository::class);
  95. $user = $this->user;
  96. $brokerage = $user->brokerage;
  97. $next_brokerage = $make->getNextLevel($user->brokerage_level) ?: $brokerage;
  98. $brokerage_rate = null;
  99. if ($next_brokerage || $brokerage) {
  100. $brokerage_rate = $make->getLevelRate($user, $next_brokerage);
  101. }
  102. $down_brokerage = null;
  103. if ($next_brokerage) {
  104. $down_brokerage = $make->getNextLevel($next_brokerage->brokerage_level);
  105. }
  106. $brokerage = $brokerage ?: ['brokerage_level' => 0, 'brokerage_name' => '普通分销员'];
  107. return app('json')->success(compact('brokerage', 'next_brokerage', 'brokerage_rate', 'down_brokerage'));
  108. }
  109. public function brokerage_notice()
  110. {
  111. $user = $this->user;
  112. if (!$user->brokerage_level) {
  113. return app('json')->fail('无需通知');
  114. }
  115. $make = app()->make(CacheRepository::class);
  116. $key = 'notice_' . $user->uid . '_' . $user->brokerage_level;
  117. if ($make->getResult($key)) {
  118. return app('json')->fail('已通知');
  119. }
  120. $make->create(['key' => $key, 'result' => 1, 'expire_time' => 0]);
  121. $userBrokerageRepository = app()->make(UserBrokerageRepository::class);
  122. return app('json')->success(['type' => $userBrokerageRepository->getNextLevel($user->brokerage_level) ? 'level' : 'top']);
  123. }
  124. /**
  125. * @param UserBillRepository $billRepository
  126. * @return mixed
  127. * @author xaboy
  128. * @day 2020/6/22
  129. */
  130. public function bill(UserBillRepository $billRepository)
  131. {
  132. [$page, $limit] = $this->getPage();
  133. return app('json')->success($billRepository->userList([
  134. 'now_money' => $this->request->param('type', 0),
  135. 'status' => 1,
  136. ], $this->request->uid(), $page, $limit));
  137. }
  138. /**
  139. * @param UserBillRepository $billRepository
  140. * @return mixed
  141. * @author xaboy
  142. * @day 2020/6/22
  143. */
  144. public function brokerage_list(UserBillRepository $billRepository)
  145. {
  146. [$page, $limit] = $this->getPage();
  147. return app('json')->success($billRepository->userList([
  148. 'category' => 'brokerage',
  149. ], $this->request->uid(), $page, $limit));
  150. }
  151. /**
  152. * @return mixed
  153. * @throws DataNotFoundException
  154. * @throws DbException
  155. * @throws ModelNotFoundException
  156. * @author xaboy
  157. * @day 2020/6/22
  158. */
  159. public function spread_order()
  160. {
  161. [$page, $limit] = $this->getPage();
  162. return app('json')->success($this->repository->subOrder($this->request->uid(), $page, $limit));
  163. }
  164. /**
  165. * TODO
  166. * @return mixed
  167. * @author Qinii
  168. * @day 2020-06-18
  169. */
  170. public function binding()
  171. {
  172. $data = $this->request->params(['phone', 'sms_code']);
  173. $sms_code = app()->make(SmsService::class)->checkSmsCode($data['phone'], $data['sms_code'], 'binding');
  174. if (!$data['sms_code'] || !$sms_code)
  175. return app('json')->fail('验证码不正确');
  176. $user = $this->repository->accountByUser($data['phone']);
  177. if ($user) {
  178. if (systemConfig('is_phone_login') === '1') {
  179. return app('json')->fail('手机号已被绑定');
  180. }
  181. $data = ['phone' => $data['phone']];
  182. } else {
  183. $data = ['account' => $data['phone'], 'phone' => $data['phone']];
  184. }
  185. $this->repository->update($this->request->uid(), $data);
  186. return app('json')->success('绑定成功');
  187. }
  188. /**
  189. * TODO 小程序获取手机号绑定
  190. * @author Qinii
  191. * @day 10/11/21
  192. */
  193. public function mpPhone()
  194. {
  195. $code = $this->request->param('code');
  196. $iv = $this->request->param('iv');
  197. $encryptedData = $this->request->param('encryptedData');
  198. $miniProgramService = MiniProgramService::create();
  199. $userInfoCong = $miniProgramService->getUserInfo($code);
  200. $session_key = $userInfoCong['session_key'];
  201. $data = $miniProgramService->encryptor($session_key, $iv, $encryptedData);
  202. $user = $this->repository->accountByUser($data['purePhoneNumber']);
  203. if ($user) {
  204. $data = ['phone' => $data['purePhoneNumber']];
  205. } else {
  206. $data = ['account' => $data['purePhoneNumber'], 'phone' => $data['purePhoneNumber']];
  207. }
  208. $this->repository->update($this->request->uid(), $data);
  209. return app('json')->success('绑定成功');
  210. }
  211. /**
  212. * @return mixed
  213. * @throws DataNotFoundException
  214. * @throws DbException
  215. * @throws ModelNotFoundException
  216. * @author xaboy
  217. * @day 2020/6/22
  218. */
  219. public function spread_list()
  220. {
  221. [$level, $sort, $nickname] = $this->request->params(['level', 'sort', 'keyword'], true);
  222. $uid = $this->request->uid();
  223. [$page, $limit] = $this->getPage();
  224. return app('json')->success($level == 2
  225. ? $this->repository->getTwoLevelList($uid, $nickname, $sort, $page, $limit)
  226. : $this->repository->getOneLevelList($uid, $nickname, $sort, $page, $limit));
  227. }
  228. /**
  229. * @return mixed
  230. * @author xaboy
  231. * @day 2020/6/22
  232. */
  233. public function spread_top()
  234. {
  235. [$page, $limit] = $this->getPage();
  236. $type = $this->request->param('type', 0);
  237. $func = $type == 1 ? 'spreadMonthTop' : 'spreadWeekTop';
  238. $data = $this->repository->{$func}($page, $limit);
  239. return app('json')->success($data);
  240. }
  241. /**
  242. * @return mixed
  243. * @author xaboy
  244. * @day 2020/6/22
  245. */
  246. public function brokerage_top()
  247. {
  248. [$page, $limit] = $this->getPage();
  249. $type = $this->request->param('type', 'week');
  250. $uid = $this->request->uid();
  251. $func = $type == 'month' ? 'brokerageMonthTop' : 'brokerageWeekTop';
  252. $data = $this->repository->{$func}($uid, $page, $limit);
  253. return app('json')->success($data);
  254. }
  255. public function history(UserVisitRepository $repository)
  256. {
  257. $uid = $this->request->uid();
  258. [$page, $limit] = $this->getPage();
  259. return app('json')->success($repository->getHistory($uid, $page, $limit));
  260. }
  261. public function deleteHistory($id, UserVisitRepository $repository)
  262. {
  263. $uid = $this->request->uid();
  264. if (!$repository->getWhereCount(['user_visit_id' => $id, 'uid' => $uid]))
  265. return app('json')->fail('数据不存在');
  266. $repository->delete($id);
  267. return app('json')->success('删除成功');
  268. }
  269. public function deleteHistoryBatch(UserVisitRepository $repository)
  270. {
  271. $uid = $this->request->uid();
  272. $data = $this->request->param('ids');
  273. if (!empty($data) && is_array($data)) {
  274. foreach ($data as $id) {
  275. if (!$repository->getWhereCount(['user_visit_id' => $id, 'uid' => $uid]))
  276. return app('json')->fail('数据不存在');
  277. }
  278. $repository->batchDelete($data, null);
  279. }
  280. if ($data == 1)
  281. $repository->batchDelete(null, $uid);
  282. return app('json')->success('删除成功');
  283. }
  284. public function account()
  285. {
  286. $user = $this->user;
  287. if (!$user->phone) return app('json')->fail('请绑定手机号');
  288. return app('json')->success($this->repository->selfUserList($user->phone));
  289. }
  290. public function switchUser()
  291. {
  292. $uid = (int)$this->request->param('uid');
  293. if (!$uid) return app('json')->fail('用户不存在');
  294. $userInfo = $this->user;
  295. if (!$userInfo->phone) return app('json')->fail('请绑定手机号');
  296. $user = $this->repository->switchUser($userInfo, $uid);
  297. $tokenInfo = $this->repository->createToken($user);
  298. $this->repository->loginAfter($user);
  299. return app('json')->success($this->repository->returnToken($user, $tokenInfo));
  300. }
  301. public function edit()
  302. {
  303. $data = $this->request->params(['avatar', 'nickname']);
  304. $uid = (int)$this->request->param('uid');
  305. if (!$uid) return app('json')->fail('用户不存在');
  306. if (empty($data['avatar'])) unset($data['avatar']);
  307. if (empty($data['nickname'])) unset($data['nickname']);
  308. if (empty($data)) return app('json')->fail('参数丢失');
  309. $this->repository->update($this->request->uid(), $data);
  310. return app('json')->success('修改成功');
  311. }
  312. public function changePassword()
  313. {
  314. $data = $this->request->params(['repassword','password', 'sms_code']);
  315. if (!$this->user->phone)
  316. return app('json')->fail('请先绑定手机号');
  317. if (empty($data['repassword']) || empty($data['password']))
  318. return app('json')->fail('请输入密码');
  319. if ($data['repassword'] !== $data['password'])
  320. return app('json')->fail('两次密码不一致');
  321. $sms_code = app()->make(SmsService::class)->checkSmsCode($this->user->phone, $data['sms_code'], 'change_pwd');
  322. if (!$data['sms_code'] || !$sms_code)
  323. return app('json')->fail('验证码不正确');
  324. $password = $this->repository->encodePassword($data['password']);
  325. $this->repository->update($this->request->uid(), ['pwd' => $password]);
  326. return app('json')->success('绑定成功');
  327. }
  328. public function changePhone()
  329. {
  330. $data = $this->request->params(['phone', 'sms_code']);
  331. $sms_code = app()->make(SmsService::class)->checkSmsCode($data['phone'], $data['sms_code'], 'change_phone');
  332. if (!$data['sms_code'] || !$sms_code)
  333. return app('json')->fail('验证码不正确');
  334. $user = $this->repository->accountByUser($data['phone']);
  335. $data['main_uid'] = 0;
  336. if ($user) {
  337. if ($this->request->userInfo()->account !== $data['phone']) {
  338. $data['account'] = $this->request->userInfo()->account.'_'.$this->request->uid();
  339. }
  340. } else {
  341. $data['account'] = $data['phone'];
  342. }
  343. unset($data['sms_code']);
  344. $this->repository->update($this->request->uid(), $data);
  345. return app('json')->success('修改成功');
  346. }
  347. public function getAgree($key)
  348. {
  349. $make = app()->make(CacheRepository::class);
  350. $data = $make->getResult($key);
  351. return app('json')->success($data);
  352. }
  353. public function integralInfo(UserBillRepository $make)
  354. {
  355. if (!systemConfig('integral_status')) {
  356. return app('json')->fail('红包米功能未开启');
  357. }
  358. $integral = $this->user->integral;
  359. $lockIntegral = $make->lockIntegral($this->user->uid);
  360. $deductionIntegral = $make->deductionIntegral($this->user->uid);
  361. $totalGainIntegral = $make->totalGainIntegral($this->user->uid);
  362. $make1 = app()->make(IntegralRepository::class);
  363. $nextClearDay = $make1->getTimeoutDay();
  364. $status = $nextClearDay < strtotime('+20 day');
  365. $invalidDay = $make1->getInvalidDay();
  366. if ($status && $integral > 0 && $invalidDay) {
  367. $validIntegral = $make->validIntegral($this->user->uid, date('Y-m-d H:i:s', $invalidDay), date('Y-m-d H:i:s', $nextClearDay));
  368. if ($integral > $validIntegral) {
  369. $nextClearIntegral = (int)bcsub($integral, $validIntegral, 0);
  370. } else {
  371. $nextClearIntegral = 0;
  372. }
  373. } else {
  374. $nextClearIntegral = 0;
  375. }
  376. $nextClearDay = date('m月d日', $nextClearDay);
  377. $clear = compact('nextClearDay', 'status', 'nextClearIntegral');
  378. return app('json')->success(compact('integral', 'lockIntegral', 'deductionIntegral', 'totalGainIntegral', 'clear'));
  379. }
  380. public function integralList(UserBillRepository $repository)
  381. {
  382. if (!systemConfig('integral_status')) {
  383. return app('json')->fail('红包米功能未开启');
  384. }
  385. [$page, $limit] = $this->getPage();
  386. $data = $repository->userList(['category' => 'integral'], $this->user->uid, $page, $limit);
  387. return app('json')->success($data);
  388. }
  389. public function services()
  390. {
  391. $uid = $this->user->uid;
  392. $where = $this->request->params(['is_verify', 'customer', 'is_goods', 'is_open']);
  393. $is_sys = $this->request->param('is_sys');
  394. return app('json')->success(app()->make(StoreServiceRepository::class)->getServices($uid, $where,$is_sys));
  395. }
  396. public function memberInfo()
  397. {
  398. if (!systemConfig('member_status')) return app('json')->fail('未开启会员功能');
  399. $make = app()->make(UserBrokerageRepository::class);
  400. $data['uid'] = $this->user->uid;
  401. $data['avatar'] = $this->user->avatar;
  402. $data['nickname'] = $this->user->nickname;
  403. $data['member_value'] = $this->user->member_value;
  404. $data['member'] = $this->user->member;
  405. $next_level = $make->getNextLevel($this->user->member_level, 1);
  406. if (!$next_level && $data['member']) {
  407. $next_level = $this->user->member->toArray();
  408. $next_level['brokerage_rule']['value'] = 0;
  409. }
  410. $data['next_level'] = $next_level;
  411. $makeInteres = app()->make(MemberinterestsRepository::class);
  412. $data['interests'] = systemConfig('member_interests_status') ? $makeInteres->getInterestsByLevel($makeInteres::TYPE_FREE,$this->user->member_level) : [] ;
  413. $data['today'] = app()->make(UserBillRepository::class)->search([
  414. 'category' => 'sys_members',
  415. 'uid' => $this->user->uid,
  416. 'day' => date('Y-m-d', time())
  417. ])->sum('number');
  418. $config_key = ['member_pay_num', 'member_sign_num', 'member_reply_num', 'member_share_num'];
  419. if (systemConfig('community_status')) $config_key[] = 'member_community_num';
  420. $config= systemConfig($config_key);
  421. if ($this->user->is_svip > 0) {
  422. foreach ($config as $key => $item) {
  423. $data['config'][$key] = $item .' x' . $makeInteres->getSvipInterestVal($makeInteres::HAS_TYPE_MEMBER).' ';
  424. }
  425. } else {
  426. $data['config'] = $config;
  427. }
  428. return app('json')->success($data);
  429. }
  430. public function notice()
  431. {
  432. $type = $this->request->param('type',0);
  433. $arr = [
  434. '0' => 'brokerage_level',
  435. '1' => 'member_level',
  436. ];
  437. $filed = $arr[$type];
  438. if (!$this->user->$filed) {
  439. return app('json')->fail('无需通知');
  440. }
  441. $make = app()->make(CacheRepository::class);
  442. $key = 'notice_' . $filed . '_' . $this->user->uid;
  443. if ($ret = $make->getWhere(['key' => $key])) {
  444. $userBrokerageRepository = app()->make(UserBrokerageRepository::class);
  445. $level = app()->make(UserBrokerageRepository::class)->getWhere(
  446. ['brokerage_level' => $ret->result, 'type' => $type],
  447. 'brokerage_name,brokerage_icon,brokerage_rule'
  448. );
  449. $next_level = $userBrokerageRepository->getNextLevel($this->user->$filed, $type);
  450. $ret->delete();
  451. $type = $next_level ? 'level' : 'top';
  452. return app('json')->success(compact('type', 'level'));
  453. }
  454. return app('json')->fail('已通知');
  455. }
  456. public function updateBaseInfo(UserBaseInfoValidate $validate)
  457. {
  458. if (systemConfig('open_update_info') != '1') {
  459. return app('json')->fail('不允许修改基本信息');
  460. }
  461. $nickname = $this->request->param('nickname');
  462. $avatar = $this->request->param('avatar');
  463. if (!$nickname && !$avatar)
  464. return app('json')->fail('未做任何修改');
  465. $user = $this->request->userInfo();
  466. if(!empty($nickname)) {
  467. $validate->check(['nickname' => $nickname]);
  468. $data['nickname'] = $nickname;
  469. }
  470. if(!empty($avatar)) {
  471. $data['avatar'] = $avatar;
  472. }
  473. $this->repository->updateBaseInfo($data,$user);
  474. return app('json')->success('修改成功');
  475. }
  476. }