Modules_Manage_Controllers_UserController.proxy.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. <?php
  2. /**
  3. * 用户管理
  4. * @author x.b
  5. */
  6. declare (strict_types=1);
  7. namespace Modules\Manage\Controllers;
  8. use App\Constants\ChangeLogConstant;
  9. use App\Exception\ApiException;
  10. use App\Model\Mongo\SendCardHistoryModel;
  11. use App\Model\VipOrderModel;
  12. use App\Repositories\Service\QueueService;
  13. use App\Repositories\UserRepository as UserRepository;
  14. use App\Model\CoinsLogModel;
  15. use App\Model\VipCardModel;
  16. use App\Model\UserModel as Model;
  17. use Carbon\Carbon;
  18. use Hyperf\DbConnection\Db;
  19. use Hyperf\Validation\Contract\ValidatorFactoryInterface;
  20. use App\Repositories\MessageRepository;
  21. class UserController extends BaseController
  22. {
  23. use \Hyperf\Di\Aop\ProxyTrait;
  24. use \Hyperf\Di\Aop\PropertyHandlerTrait;
  25. function __construct()
  26. {
  27. if (method_exists(parent::class, '__construct')) {
  28. parent::__construct(...func_get_args());
  29. }
  30. $this->__handlePropertyHandler(__CLASS__);
  31. }
  32. /**
  33. * 详细
  34. * @param yes id int $id 用户ID 如 100
  35. * @return mixed
  36. * @example param_json_data string: {"handshake":"","data":{"id":14550388}}
  37. */
  38. public function detail(ValidatorFactoryInterface $validatorFactory)
  39. {
  40. $inputData = $this->getJsonData();
  41. $rules = ['id' => 'required|numeric'];
  42. $validator = $validatorFactory->make($inputData, $rules);
  43. if ($validator->fails()) {
  44. return json_fail($validator->errors()->first());
  45. }
  46. $id = $inputData['id'];
  47. $select = ['*'];
  48. $model = Model::query();
  49. $result = $model->select($select)->where('id', $id)->first();
  50. if (!$result) {
  51. return json_fail('用户不存在');
  52. }
  53. // 查他的上级邀请人的名字
  54. $result['parent_nick'] = '';
  55. if ($result['parent_uid']) {
  56. $select = ['nick'];
  57. $r = Model::query()->select($select)->where('code', $result['parent_uid'])->first();
  58. if ($r) {
  59. $result['parent_nick'] = $r['nick'];
  60. }
  61. }
  62. $userRepo = make(UserRepository::class);
  63. $userDataInfo = $userRepo->getUserInfoData($result['code']);
  64. $result['qrcode'] = $userDataInfo['account_qrcode_content'];
  65. $orderCount = VipOrderModel::where(['user_code' => $result['code']])->count();
  66. $payCount = VipOrderModel::where(['user_code' => $result['code']])->where(['status' => 1])->count();
  67. $result['order_count'] = $orderCount;
  68. $result['pay_count'] = $payCount;
  69. return json_success($result);
  70. }
  71. /**
  72. * 列表
  73. * @param ValidatorFactoryInterface $validatorFactory
  74. * @return mixed
  75. * @example param_json_data string: {"handshake":"","data":{"page":1,"page_size":5,"search":{"nick":"用户CH3J30","stime":"","otime":""},"order":"created_at","order_sort":"desc"}}
  76. */
  77. public function list(ValidatorFactoryInterface $validatorFactory)
  78. {
  79. $inputData = $this->getJsonData();
  80. $page = isset($inputData['page']) ? (int) $inputData['page'] : 1;
  81. $page_size = isset($inputData['page_size']) ? (int) $inputData['page_size'] : 20;
  82. $select = ['*'];
  83. $model = Model::query();
  84. $order_key = isset($inputData['order']) ? $inputData['order'] : 'id';
  85. $order_value = isset($inputData['order_sort']) ? $inputData['order_sort'] : 'desc';
  86. if (!$order_key) {
  87. $order_key = 'id';
  88. //不要信任前端,他可能会传个空字符串过来!
  89. }
  90. if (!$order_value) {
  91. $order_value = 'desc';
  92. }
  93. $search = isset($inputData['search']) ? $inputData['search'] : array();
  94. if ($search) {
  95. foreach ($search as $k => $v) {
  96. if (!strlen((string) $v)) {
  97. continue;
  98. }
  99. $operator = '=';
  100. if ($k == 'channel_id' && $v == 'official') {
  101. // 官方代表空
  102. $v = "";
  103. }
  104. if ($k == 'max_view') {
  105. preg_match('/^(=|>|<)(\\d{1,10})$/', $v, $matches);
  106. if (isset($matches[2])) {
  107. $operator = $matches[1];
  108. $v = $matches[2];
  109. }
  110. }
  111. switch ($k) {
  112. case "nick":
  113. // 用户名
  114. case "mobile":
  115. // 手机号
  116. $model->where($k, 'like', "{$v}%");
  117. break;
  118. case "stime":
  119. // 自定义-开始日期
  120. $model->where('created_at', '>=', $v);
  121. break;
  122. case "otime":
  123. // 自定义-结束日期
  124. $model->where('created_at', '<=', Carbon::parse($v)->endOfDay()->toDateTimeString());
  125. break;
  126. default:
  127. $model->where($k, $operator, $v);
  128. }
  129. }
  130. }
  131. $result = $model->select($select)->orderBy((string) $order_key, (string) $order_value)->paginate($page_size, ['*'], 'page', $page);
  132. return json_success($result);
  133. }
  134. /**
  135. * 删除
  136. */
  137. public function delete()
  138. {
  139. }
  140. /**
  141. * 更新
  142. * @return mixed
  143. * @example param_json_data string: {"handshake":"","data":{"id":14550388,"status":"1"}}
  144. */
  145. public function update(ValidatorFactoryInterface $validatorFactory)
  146. {
  147. $inputData = $this->getJsonData();
  148. $rules = ['id' => 'required|numeric'];
  149. $validator = $validatorFactory->make($inputData, $rules);
  150. if ($validator->fails()) {
  151. return json_fail($validator->errors()->first());
  152. }
  153. $id = $inputData['id'];
  154. $status = isset($inputData['status']) ? $inputData['status'] : '';
  155. if ($status) {
  156. if (!in_array($status, array(1, 2, 3))) {
  157. return json_fail('请按文档正确传参,用户的状态值');
  158. }
  159. }
  160. $user_info = Model::query()->where('id', $id)->first();
  161. if (!$user_info) {
  162. return json_fail('用户不存在');
  163. }
  164. $data = array();
  165. if (isset($inputData['nick'])) {
  166. $data['nick'] = trim($inputData['nick']);
  167. }
  168. if (isset($inputData['avatar'])) {
  169. $data['avatar'] = trim($inputData['avatar']);
  170. }
  171. if (isset($inputData['bg_cover'])) {
  172. $data['bg_cover'] = trim($inputData['bg_cover']);
  173. }
  174. if (isset($inputData['intro'])) {
  175. $data['intro'] = rtrim($inputData['intro']);
  176. }
  177. if (isset($inputData['status'])) {
  178. $data['status'] = intval($inputData['status']);
  179. }
  180. if (isset($inputData['mobile'])) {
  181. $data['mobile'] = intval($inputData['mobile']);
  182. }
  183. $data = action_data($data);
  184. if ($data) {
  185. $result = Model::query()->where('id', $id)->update($data);
  186. if (!$result) {
  187. return json_fail('更新失败');
  188. }
  189. }
  190. // 创建管理员日志
  191. $oldItem = clone $user_info;
  192. $newitem = Model::query()->where('id', $id)->first();
  193. $logSubject = '修改一个用户信息,名称:' . $user_info['nick'];
  194. $logSvalue = $oldItem->id;
  195. $logDbData = ['after_items' => [$newitem->toArray()], 'before_items' => [$oldItem->toArray()]];
  196. $this->log($logSubject, $logSvalue, $logDbData);
  197. make(UserRepository::class)->delUserCache($user_info['code']);
  198. return json_success('', '更新成功');
  199. }
  200. /**
  201. * 发放金币
  202. * @param int yes $id 用户ID, 如 14550388
  203. * @param int yes $coins 金币数, 如 50 则是加; 如 -100 则是减少
  204. * @return mixed
  205. * @example param_json_data string: {"handshake":"","data":{"id":14550388,"coins":50}}
  206. */
  207. public function sendCoins(ValidatorFactoryInterface $validatorFactory)
  208. {
  209. $inputData = $this->getJsonData();
  210. $rules = ['id' => 'required|numeric', 'coins' => 'required|numeric'];
  211. $validator = $validatorFactory->make($inputData, $rules);
  212. if ($validator->fails()) {
  213. return json_fail($validator->errors()->first());
  214. }
  215. $id = $inputData['id'];
  216. $coins = $inputData['coins'];
  217. $user_info = Model::query()->where('id', $id)->first();
  218. if (!$user_info) {
  219. return json_fail('用户不存在');
  220. }
  221. if ($coins > 0) {
  222. $result = Model::query()->where('id', $id)->increment('coins', $coins);
  223. } else {
  224. $_coins = abs((int) $coins);
  225. //取绝对值
  226. if ($user_info->coins < $_coins) {
  227. return json_fail('用户金币不够,不能扣减');
  228. }
  229. $result = Model::query()->where('id', $id)->decrement('coins', $_coins);
  230. }
  231. if (!$result) {
  232. return json_fail('处理失败');
  233. }
  234. make(UserRepository::class)->delUserCache($user_info['code']);
  235. //清除用户信息redis缓存
  236. if ($coins < 0) {
  237. $way = ChangeLogConstant::WAY_2;
  238. $type = ChangeLogConstant::TYPE_22;
  239. } else {
  240. $way = ChangeLogConstant::WAY_1;
  241. $type = ChangeLogConstant::TYPE_18;
  242. }
  243. // 记录帐变使用日志
  244. $changeData = ['user_uid' => $user_info['code'], 'currency_type' => ChangeLogConstant::CHANGE_COIN, 'amount' => abs((int) $coins), 'way' => $way, 'type' => $type];
  245. // 帐变记录
  246. make(QueueService::class)->saveChangeLogJob($changeData);
  247. // 创建管理员日志
  248. $oldItem = clone $user_info;
  249. $newitem = Model::query()->where('id', $id)->first();
  250. $logSubject = '对一个用户发放金币,名称:' . $user_info['nick'];
  251. $logSvalue = $oldItem->id;
  252. $logDbData = ['after_items' => [$newitem->toArray()], 'before_items' => [$oldItem->toArray()]];
  253. $this->log($logSubject, $logSvalue, $logDbData);
  254. return json_success('', '处理成功');
  255. }
  256. /**
  257. * bindPhone 绑定老用户
  258. * 业务逻辑:
  259. * 1. 后台对指定新用户 输入 老用户对手机号
  260. * 2。查询出 老用户对设备号,设备类型
  261. * 3。将新/老用户的仅 设备号和设备类型,互换一下。
  262. * 4。调接口,退出新老用户(即 缓存中清理下 )
  263. * @param int yes $id 新用户的ID,如100
  264. * @param int yes $mobile 老用户的手机号
  265. * @return mixed
  266. * @example param_json_data string: {"handshake":"","data":{"id":14550389,"mobile":"13873840000"}}
  267. */
  268. public function bindPhone(ValidatorFactoryInterface $validatorFactory)
  269. {
  270. $inputData = $this->getJsonData();
  271. $rules = ['id' => 'required|numeric', 'mobile' => 'required|numeric'];
  272. $validator = $validatorFactory->make($inputData, $rules);
  273. if ($validator->fails()) {
  274. return json_fail($validator->errors()->first());
  275. }
  276. $id = $inputData['id'];
  277. $mobile = $inputData['mobile'];
  278. $user_info_new = Model::query()->where('id', $id)->first();
  279. if (!$user_info_new) {
  280. return json_fail('新用户不存在');
  281. }
  282. $user_info_old = Model::query()->where('mobile', $mobile)->first();
  283. if (!$user_info_old) {
  284. return json_fail('老用户对应的电话号码不存在');
  285. }
  286. // 交换更新用户设备号,设备类型
  287. Db::beginTransaction();
  288. try {
  289. $data = array('device_no' => $user_info_old['device_no'], 'device_type' => $user_info_old['device_type'], 'finger_hash' => $user_info_old['finger_hash']);
  290. $r = Model::query()->where('id', $id)->update($data);
  291. if (!$r) {
  292. throw new ApiException('更新新用户设备信息失败');
  293. }
  294. $data = array('device_no' => $user_info_new['device_no'], 'device_type' => $user_info_new['device_type'], 'finger_hash' => $user_info_new['finger_hash']);
  295. $r = Model::query()->where('mobile', $mobile)->update($data);
  296. if (!$r) {
  297. throw new ApiException('更新老用户设备信息失败');
  298. }
  299. // 清理新/旧用户缓存数据
  300. $m = make(UserRepository::class);
  301. $m->userLogout($user_info_new['code']);
  302. $m->userLogout($user_info_old['code']);
  303. Db::commit();
  304. } catch (\Exception $e) {
  305. Db::rollBack();
  306. }
  307. // 创建管理员日志
  308. $oldItem = clone $user_info_new;
  309. $oldItem2 = clone $user_info_old;
  310. $newitem = Model::query()->where('id', $id)->first();
  311. $newitem2 = Model::query()->where('id', $user_info_old['id'])->first();
  312. $logSubject = "绑定老用户,用户id:{$user_info_new['id']}->{$user_info_old['id']}";
  313. $logSvalue = $oldItem->id;
  314. $logDbData = ['after_items' => [$newitem->toArray(), $newitem2->toArray()], 'before_items' => [$oldItem->toArray(), $oldItem2->toArray()]];
  315. $this->log($logSubject, $logSvalue, $logDbData);
  316. return json_success('', '处理成功');
  317. }
  318. /**
  319. * 对指定用户发放会员卡
  320. * @param int yes $id 用户id
  321. * @param int yes $card_id 会员卡ID,来源会员卡列表的字段id
  322. * @return mixed
  323. * @example param_json_data string: {"handshake":"","data":{"id":424432,"card_id":1}}
  324. */
  325. public function sendCard(ValidatorFactoryInterface $validatorFactory)
  326. {
  327. $inputData = $this->getJsonData();
  328. $rules = ['id' => 'required', 'card_id' => 'required'];
  329. $validator = $validatorFactory->make($inputData, $rules);
  330. if ($validator->fails()) {
  331. return json_fail($validator->errors()->first());
  332. }
  333. $uid = $inputData['id'];
  334. $card_id = $inputData['card_id'];
  335. $card_info = VipCardModel::query()->where('id', $card_id)->first();
  336. if (!$card_info) {
  337. return json_fail('会员卡不存在');
  338. }
  339. if (!$card_info['status']) {
  340. return json_fail('会员卡未启动');
  341. }
  342. $user_info = Model::query()->where('id', $uid)->first();
  343. if (!$user_info) {
  344. return json_fail('用户不存在');
  345. }
  346. try {
  347. //加会员天数
  348. $userInfo = make(UserRepository::class)->getUserInfoFromCache($user_info['code']);
  349. if ($userInfo['is_vip'] == 'y') {
  350. $vipTime = Carbon::parse($userInfo['vip_expired'])->addDays($card_info['day'])->toDateTimeString();
  351. } else {
  352. $vipTime = Carbon::now()->addDays($card_info['day'])->toDateTimeString();
  353. }
  354. $result = Model::query()->where('id', $user_info['id'])->update(['vip_expired' => $vipTime]);
  355. if (!$result) {
  356. return json_fail('添加用户会员卡时间失败');
  357. }
  358. make(UserRepository::class)->delUserCache($user_info['code']);
  359. //清除用户信息redis缓存
  360. } catch (\Exception $e) {
  361. return json_fail('处理失败');
  362. }
  363. //$managerInfo = $authService->getManagerInfo();
  364. // $roleId = $managerInfo['role_id'];
  365. // $managerId = $managerInfo['manager_id'];
  366. $managerInfo = $this->getCurrentManagerInfo();
  367. make(SendCardHistoryModel::class)->db()->insertOne(['mid_id' => $managerInfo['manager_id'], 'user_code' => $user_info['code'], 'vip_id' => $card_info['id'], 'vip_days' => $card_info['day']]);
  368. // 创建管理员日志
  369. $oldItem = clone $user_info;
  370. $newitem = Model::query()->where('id', $user_info['id'])->first();
  371. $logSubject = "发放{$card_info['day']}天的会员卡,会员卡配置ID:{$card_info['id']},用户id:{$user_info['id']}";
  372. $logSvalue = $oldItem->id;
  373. $logDbData = ['after_items' => [$newitem->toArray()], 'before_items' => [$oldItem->toArray()]];
  374. $this->log($logSubject, $logSvalue, $logDbData);
  375. return json_success('', '处理成功');
  376. }
  377. /**
  378. * 指定用户的邀请详细
  379. * @param yes id int $id 用户ID 如 100
  380. * @return mixed
  381. * @example param_json_data string: {"handshake":"","page":1,"page_size":5,"data":{"id":30}}
  382. */
  383. public function inviteDetail(ValidatorFactoryInterface $validatorFactory)
  384. {
  385. $inputData = $this->getJsonData();
  386. $page = isset($inputData['page']) ? (int) $inputData['page'] : 1;
  387. $page_size = isset($inputData['page_size']) ? (int) $inputData['page_size'] : 20;
  388. $rules = ['id' => 'required|numeric'];
  389. $validator = $validatorFactory->make($inputData, $rules);
  390. if ($validator->fails()) {
  391. return json_fail($validator->errors()->first());
  392. }
  393. $order_key = isset($inputData['order']) ? $inputData['order'] : 'id';
  394. $order_value = isset($inputData['order_sort']) ? $inputData['order_sort'] : 'desc';
  395. if (!$order_key) {
  396. $order_key = 'id';
  397. //不要信任前端,他可能会传个空字符串过来!
  398. }
  399. if (!$order_value) {
  400. $order_value = 'desc';
  401. }
  402. $id = $inputData['id'];
  403. $select = ['*'];
  404. $user_info = Model::query()->select($select)->where('id', $id)->first();
  405. if (!$user_info) {
  406. return json_fail('用户不存在');
  407. }
  408. $select = ['nick', 'id', 'mobile', 'created_at'];
  409. $invite_list = Model::query()->select($select)->where('parent_uid', $user_info['code'])->orderBy((string) $order_key, (string) $order_value)->paginate($page_size, ['*'], 'page', $page);
  410. if (!$invite_list) {
  411. $invite_list = array();
  412. }
  413. $result = array('user_info' => $user_info, 'invite_list' => $invite_list);
  414. return json_success($result);
  415. }
  416. /**
  417. * 邀请列表
  418. * @param ValidatorFactoryInterface $validatorFactory
  419. * @return mixed
  420. * @example param_json_data string: {"handshake":"","data":{"page":1,"page_size":5,"search":{"nick":"用户CH3J30","id":"","mobile":"","code":"","stime":"","otime":""},"order":"invite","order_sort":"desc"}}
  421. */
  422. public function inviteList(ValidatorFactoryInterface $validatorFactory)
  423. {
  424. $inputData = $this->getJsonData();
  425. $page = isset($inputData['page']) ? (int) $inputData['page'] : 1;
  426. $page_size = isset($inputData['page_size']) ? (int) $inputData['page_size'] : 20;
  427. $select = ['id', 'nick', 'mobile', 'mobile', 'device_no', 'device_type', 'channel_id', 'code', 'status', 'invite', 'coins', 'ip'];
  428. $model = Model::query();
  429. $order_key = isset($inputData['order']) ? $inputData['order'] : 'id';
  430. $order_value = isset($inputData['order_sort']) ? $inputData['order_sort'] : 'desc';
  431. if (!$order_key) {
  432. $order_key = 'id';
  433. //不要信任前端,他可能会传个空字符串过来!
  434. }
  435. if (!$order_value) {
  436. $order_value = 'desc';
  437. }
  438. $search = isset($inputData['search']) ? $inputData['search'] : array();
  439. if ($search) {
  440. foreach ($search as $k => $v) {
  441. if (!strlen((string) $v)) {
  442. continue;
  443. }
  444. switch ($k) {
  445. case "nick":
  446. // 用户名
  447. case "mobile":
  448. // 手机号
  449. case "code":
  450. // 邀请码
  451. $model->where($k, 'like', "{$v}%");
  452. break;
  453. case "stime":
  454. // 自定义-开始日期
  455. $model->where('created_at', '>=', $v);
  456. break;
  457. case "otime":
  458. // 自定义-结束日期
  459. $model->where('created_at', '<=', Carbon::parse($v)->endOfDay()->toDateTimeString());
  460. break;
  461. default:
  462. $model->where($k, $v);
  463. }
  464. }
  465. }
  466. $model->where('invite', '>', '0');
  467. //仅查询有邀请人数的
  468. $invite_all_select = [Db::raw('count(*) as id_all'), Db::raw('sum(invite) as invite_all')];
  469. $invite_all = $model->select($invite_all_select)->first();
  470. if ($invite_all) {
  471. if (!$invite_all['id_all']) {
  472. $invite_all['average'] = 0;
  473. } else {
  474. $invite_all['average'] = round($invite_all['invite_all'] / $invite_all['id_all'], 1);
  475. }
  476. } else {
  477. $invite_all = array("id_all" => 0, "invite_all" => 0, 'average' => 0);
  478. }
  479. $invite_list = $model->select($select)->orderBy((string) $order_key, (string) $order_value)->paginate($page_size, ['*'], 'page', $page);
  480. $result = array('invite_all' => $invite_all, 'invite_list' => $invite_list);
  481. return json_success($result);
  482. }
  483. /**
  484. * 发送系统消息给单个用户
  485. */
  486. public function sendMessageToUser(ValidatorFactoryInterface $validatorFactory)
  487. {
  488. $inputData = $this->getJsonData();
  489. $rules = ['subject' => 'required|string|max:255', 'receive_uid' => 'required|max:32', 'content' => 'required|string'];
  490. $validator = $validatorFactory->make($inputData, $rules);
  491. if ($validator->fails()) {
  492. // 如果有错误(可能是多个信息),这里只取第一个错误信息返回.
  493. return json_fail($validator->errors()->first());
  494. }
  495. $receiveUid = data_get($inputData, 'receive_uid', '');
  496. $content = data_get($inputData, 'content', '');
  497. $subject = data_get($inputData, 'subject', '');
  498. $msgRepo = make(MessageRepository::class);
  499. $msgRepo->sendTextFromSys($receiveUid, $content, $subject);
  500. return json_success(['result' => 'success']);
  501. }
  502. }