UserLogic.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. <?php
  2. namespace app\admin\logic;
  3. use app\admin\model\dao\MoneyLog;
  4. use app\admin\model\dao\ScoreLog;
  5. use app\admin\model\dao\User;
  6. use app\common\model\UserModel;
  7. use app\common\model\UserMoneyModel;
  8. use think\facade\Cache;
  9. use think\facade\Db;
  10. class UserLogic
  11. {
  12. public static function forbid($id)
  13. {
  14. $user = User::getUserOrEmptyById($id);
  15. if (empty($user)) return [false, '数据不存在'];
  16. if ($user['status'] == 0) return [false, '该用户已被禁用'];
  17. $result = User::updateStatus($id, 0);
  18. return $result ? [true, '禁用成功'] : [false, '禁用失败'];
  19. }
  20. public static function enable($id)
  21. {
  22. $user = User::getUserOrEmptyById($id);
  23. if (empty($user)) return [false, '数据不存在'];
  24. if ($user['status'] == 1) return [false, '该用户已启用'];
  25. $result = User::updateStatus($id, 1);
  26. return $result ? [true, '禁用成功'] : [false, '禁用失败'];
  27. }
  28. public static function getUserDetail($id)
  29. {
  30. $user = new User();
  31. return $user->getUserDetail($id);
  32. }
  33. public static function levelset($post)
  34. {
  35. $level = $post['level'];
  36. if ($level > 4) {
  37. return '最高等级4级';
  38. }
  39. $user = User::getUserOrEmptyById($post['id']);
  40. if (empty($user)) return '用户不存在';
  41. $level_type = 1;
  42. if ($level > $user['level']) {
  43. $level_type = 2;
  44. }
  45. Db::startTrans();
  46. try {
  47. $userData = ['level' => $level, 'level_type' => $level_type];
  48. User::update($post['id'], $userData);
  49. Db::commit();
  50. } catch (\Exception $e) {
  51. Db::rollback();
  52. return '失败' . $e->getMessage();
  53. }
  54. return true;
  55. }
  56. public static function lookpidlevel($id)
  57. {
  58. $path = Db::name('user')->where('id', $id)->value('path');
  59. $arr = explode(',', $path);
  60. $ids = $arr;
  61. $ids = implode(',', $ids);
  62. $order = 'field(id,' . $ids . ')';
  63. $where = array();
  64. $where[] = ['uid', 'in', $arr];
  65. sr_log($where);
  66. $user = new UserModel();
  67. $count = $user
  68. ->withJoin('userData', 'INNER')
  69. ->where($where)
  70. ->count();
  71. $list = $user
  72. ->withJoin('userData', 'INNER')
  73. ->where($where)
  74. ->order(Db::raw($order))
  75. ->select();
  76. return [$count, $list];
  77. }
  78. public static function getExportList($where, $page, $limit)
  79. {
  80. return (new UserModel())
  81. ->where($where)
  82. ->withJoin('userData', 'INNER')
  83. ->where($where)
  84. ->page($page, $limit)
  85. ->order('id', 'desc')
  86. ->select()
  87. ->toArray();
  88. }
  89. public static function recycleCountSet($post)
  90. {
  91. $user = User::getUserById($post['id']);
  92. if (empty($user)) return '用户不存在';
  93. if (empty($post['recycle_count']) || $post['recycle_count'] < 0 || $post['recycle_count'] > 500) {
  94. return '回收卡数量格式有误';
  95. }
  96. try {
  97. $updateData = ['recycle_count' => $post['recycle_count']];
  98. $result = User::update($user['id'], $updateData);
  99. if (!$result) return "更新临时卡数量失败";
  100. } catch (\Exception $e) {
  101. return '失败' . $e->getMessage();
  102. }
  103. return true;
  104. }
  105. public function getList($page, $limit, $where, $sort, $userMap)
  106. {
  107. $where[] = ['status', '<>', 3];
  108. $userDao = new User();
  109. $count = $userDao->getCount($where, $userMap);
  110. $list = $userDao->getPageList($page, $limit, $where, $sort, $userMap);
  111. foreach ($list as &$item) {
  112. //团队会员(包括1、2级和自身)的积分账户合计、余额账户合计
  113. // 计算团队成员(包括1、2级和自身)ID
  114. $teamIds = $this->getTeamMoneyAndScore($item['id']);
  115. // 积分账户合计
  116. $item['score_total'] = $teamIds['score'];
  117. // 余额账户合计
  118. $item['money_total'] = $teamIds['money'];
  119. }
  120. $data = [
  121. 'code' => 0,
  122. 'msg' => Db::getLastSql(),
  123. 'count' => $count,
  124. 'data' => $list,
  125. ];
  126. return json($data);
  127. }
  128. /**
  129. * 获取团队自身,一级、二级自己的余额/积分
  130. * @param $uid
  131. */
  132. private function getTeamMoneyAndScore($uid)
  133. {
  134. $cacheKey = 'userLogicTeamIds_' . $uid;
  135. if (!Cache::has($cacheKey)) {
  136. // 自身
  137. $user = Db::table(User::$table)
  138. ->where('id', $uid)
  139. ->field(['id', 'score', 'money'])
  140. ->find();
  141. $totalScore = $user['score'];
  142. $totalMoney = $user['money'];
  143. // 一级子用户
  144. Db::table(User::$table)
  145. ->where('pid', $uid)
  146. ->field(['id', 'score', 'money'])
  147. ->chunk(100, function ($users) use (&$totalScore, &$totalMoney) {
  148. foreach ($users as $user) {
  149. $uids[] = $user['id'];
  150. $totalScore += $user['score'];
  151. $totalMoney += $user['money'];
  152. }
  153. // 二级子用户
  154. Db::table(User::$table)
  155. ->whereIn('pid', $uids)
  156. ->field(['id', 'score', 'money'])
  157. ->chunk(100, function ($users) use (&$totalScore, &$totalMoney) {
  158. foreach ($users as $user) {
  159. $totalScore += $user['score'];
  160. $totalMoney += $user['money'];
  161. }
  162. });
  163. }, ['score', 'money']);
  164. Cache::set($cacheKey, ['score' => $totalScore, 'money' => sprintf("%.2f", $totalMoney)], 5 * 60);
  165. }
  166. return Cache::get($cacheKey);
  167. }
  168. /**
  169. * 修改用户手机号码
  170. * @param mixed $uid
  171. * @param mixed $phone
  172. */
  173. public function modifyPhone($uid, $phone)
  174. {
  175. // 判断手机号码是否使用过
  176. $user = User::getUserById($uid);
  177. if (empty($user)) return '用户不存在';
  178. if ($user['mobile'] == $phone) return "请输入新的手机号码";
  179. if (User::getUserByMobile($phone)) return "该手机号码已注册";
  180. // 修改用户信息
  181. try {
  182. $updateData = [
  183. 'mobile' => $phone,
  184. ];
  185. // 按照账号原规则,手机号码作为用户名,同时修改新的用户名
  186. if ($user['mobile'] == $user['user_name']) {
  187. $updateData['user_name'] = $phone;
  188. }
  189. $result = User::update($uid, $updateData);
  190. if (!$result) return "更新手机号码失败,请稍后重试";
  191. } catch (\Exception $e) {
  192. return '失败' . $e->getMessage();
  193. }
  194. return true;
  195. }
  196. /**
  197. * 修改用户所属上级
  198. * @param mixed $uid
  199. * @param mixed $pid
  200. */
  201. public function modifypid($uid, $pid)
  202. {
  203. $user = User::getUserById($uid);
  204. if (empty($user)) return '用户不存在';
  205. // 查询pid是否存在用户path中
  206. if ($uid == $pid) {
  207. return "不能修改自己为上级";
  208. }
  209. if ($user['pid'] == $pid) {
  210. return "该用户已所属待变更的上级,不能修改";
  211. }
  212. // 当前用户关系层级链路
  213. $newUserPath = "";
  214. if ($pid == 0) {
  215. $newPathPrefix = $user['id'];
  216. } else {
  217. $pUser = User::getUserById($pid);
  218. if (empty($pUser)) {
  219. return "待变更的上级用户不存在";
  220. }
  221. $userPathArr = explode(',', $user['path']);
  222. if (in_array($pid, $userPathArr)) {
  223. $pidIndex = array_search($pid, $userPathArr);
  224. $userPathArrPrefix = array_slice($userPathArr, 0, $pidIndex + 1);
  225. } else {
  226. $pidIndex = array_search($user['pid'], $userPathArr);
  227. $userPathArrPrefix = array_slice($userPathArr, 0, $pidIndex);
  228. $userPathArrPrefix[] = $pid;
  229. }
  230. $newUserPath = implode(',', $userPathArrPrefix);
  231. // 子级用户Path待替换关系层级前部分链表
  232. $userPathArrPrefix[] = $user['id'];
  233. $newPathPrefix = implode(',', $userPathArrPrefix);
  234. }
  235. // 子级用户Path被替换关系层级前部分链表
  236. $oldPathPrefix = $user['path'] == 0 ? $uid : $user['path'] . ',' . $uid;
  237. Db::startTrans();
  238. try {
  239. // 子级path变更
  240. $result = Db::table(User::$table)
  241. ->where([
  242. ['path', 'like', $oldPathPrefix . '%'],
  243. ['id', '<>', $uid]
  244. ])
  245. ->field(['id', 'path'])
  246. ->chunk(100, function ($users) use ($pid, $oldPathPrefix, $newPathPrefix, $uid) {
  247. foreach ($users as $user) {
  248. $newPath = str_replace($oldPathPrefix, $newPathPrefix, $user['path']);
  249. User::modifyUserPath($user['id'], $newPath);
  250. }
  251. });
  252. if (!$result) {
  253. Db::rollback();
  254. return "修改用户所属上级失败,请确认用户的层级关系";
  255. }
  256. // 更新用户Pid,Path
  257. User::modifyUserPidAndPath($uid, $pid, $newUserPath);
  258. Db::commit();
  259. } catch (\Exception $exception) {
  260. Db::rollback();
  261. return "失败:" . $exception->getMessage();
  262. }
  263. return true;
  264. }
  265. /**
  266. * 修改余额
  267. * @param mixed $post
  268. */
  269. public function ModifyMoney($post)
  270. {
  271. $user = User::getUserById($post['uid']);
  272. if (empty($user)) {
  273. return "用户不存在";
  274. }
  275. Db::startTrans();
  276. try {
  277. if ($post['state'] == 1) {
  278. $afterMoney = $user['money'] + $post['money'];
  279. } else {
  280. $afterMoney = $user['money'] - $post['money'];
  281. if ($afterMoney < 0) {
  282. return "账号余额不足";
  283. }
  284. }
  285. $afterMoney = round($afterMoney, 2);
  286. $moneyLog = [
  287. 'uid' => $post['uid'],
  288. 'type' => $post['type'] ?? 0,
  289. 'money' => $post['money'],
  290. 'create_at' => date('Y-m-d H:i:s'),
  291. 'state' => $post['state'] ?? '0',
  292. 'from_id' => $post['from_id'] ?? '0',
  293. 'before_money' => $user['money'],
  294. 'after_money' => $afterMoney,
  295. 'uid2' => $post['uid2'] ?? 0,
  296. 'free_type' => $post['free_type'] ?? '',
  297. 'remark' => $post['remark'],
  298. ];
  299. // 子级path变更
  300. MoneyLog::AddMoneyLog($moneyLog);
  301. User::UpdateUserMoney($user['id'], $afterMoney);
  302. Db::commit();
  303. } catch (\Exception $exception) {
  304. Db::rollback();
  305. return "失败:" . $exception->getMessage();
  306. }
  307. return true;
  308. }
  309. /**
  310. * 修改积分
  311. * @param mixed $post
  312. */
  313. public function ModifyScore($post)
  314. {
  315. $user = User::getUserById($post['uid']);
  316. if (empty($user)) {
  317. return "用户不存在";
  318. }
  319. Db::startTrans();
  320. try {
  321. if ($post['state'] == 1) {
  322. $afterScore = $user['score'] + $post['score'];
  323. } else {
  324. $afterScore = $user['score'] - $post['score'];
  325. if ($afterScore < 0) {
  326. return "账号积分不足";
  327. }
  328. }
  329. $moneyLog = [
  330. 'uid' => $post['uid'],
  331. 'type' => $post['type'] ?? 0,
  332. 'score' => $post['score'],
  333. 'create_at' => date('Y-m-d H:i:s'),
  334. 'scene' => $post['scene'] ?? 0,
  335. 'from_id' => $post['from_id'] ?? '0',
  336. 'state' => $post['state'] ?? '0',
  337. 'before_score' => $user['score'],
  338. 'after_score' => $afterScore,
  339. 'uid2' => $post['uid2'] ?? 0,
  340. ];
  341. // 子级path变更
  342. ScoreLog::AddScoreLog($moneyLog);
  343. User::UpdateUserScore($user['id'], $afterScore);
  344. Db::commit();
  345. } catch (\Exception $exception) {
  346. Db::rollback();
  347. return "失败:" . $exception->getMessage();
  348. }
  349. return true;
  350. }
  351. /**
  352. * 删除用户
  353. * @param $id
  354. */
  355. public function delUser($id)
  356. {
  357. $user = User::getUserById($id);
  358. if (empty($user)) {
  359. return "用户不存在";
  360. }
  361. if (User::updateStatus($id, 3) !== 1) {
  362. return false;
  363. }
  364. return true;
  365. }
  366. /* 注册用户数量统计
  367. * @param string $time 时间节点如:2023-03-01
  368. * @return mixed
  369. * @throws \think\db\exception\DbException
  370. */
  371. public static function getCountByTime($time = '0')
  372. {
  373. $cacheKey = "caches:user:counts_{$time}";
  374. if (!Cache::has($cacheKey)) {
  375. $data = UserModel::where(['status' => 1])
  376. ->where(function ($query) use ($time) {
  377. if ($time) {
  378. $query->where('reg_time', '>=', $time);
  379. }
  380. })->count('id');
  381. if ($data) {
  382. Cache::set($cacheKey, $data, rand(3, 5));
  383. }
  384. return $data;
  385. }
  386. return Cache::get($cacheKey);
  387. }
  388. }