User.php 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100
  1. <?php
  2. namespace app\adminapi\controller\v1\user;
  3. use app\adminapi\controller\AuthController;
  4. use Exception;
  5. use FormBuilder\exception\FormBuilderException;
  6. use think\db\exception\DataNotFoundException;
  7. use think\db\exception\DbException;
  8. use think\db\exception\ModelNotFoundException;
  9. use think\Response;
  10. use think\response\Json;
  11. use app\models\user\{
  12. User as UserModel,
  13. UserLabelRelation,
  14. UserLabel,
  15. UserLevel,
  16. UserBill as UserBillAdmin,
  17. UserTaskFinish,
  18. UserGroup
  19. };
  20. use app\models\system\{
  21. SystemUserLevel, SystemUserTask
  22. };
  23. use app\models\store\{
  24. StoreOrder, StoreVisit, StoreCouponUser
  25. };
  26. use app\models\wechat\WechatMessage;
  27. use crmeb\basic\BaseModel;
  28. use crmeb\repositories\UserRepository;
  29. use crmeb\services\{
  30. FormBuilder as Form, UtilService as Util
  31. };
  32. use think\Request;
  33. use think\facade\Route as Url;
  34. class User extends AuthController
  35. {
  36. /**
  37. * 显示资源列表头部
  38. *
  39. * @return Response
  40. */
  41. public function type_header()
  42. {
  43. //全部会员
  44. $all = UserModel::merSet($this->merId)->count();
  45. //小程序会员
  46. $routine = UserModel::merSet($this->merId)->alias('u')->join('WechatUser w', 'u.uid=w.uid')->where('w.routine_openid', '<>', '')->count();
  47. //公众号会员
  48. $wechat = UserModel::merSet($this->merId)->alias('u')->join('WechatUser w', 'u.uid=w.uid')->where('w.openid', '<>', '')->count();
  49. //H5会员
  50. $h5 = UserModel::merSet($this->merId)->alias('u')->join('WechatUser w', 'u.uid=w.uid')->where(['w.routine_openid' => '', 'w.openid' => ''])->where('u.user_type', 'h5')->count();
  51. $list = [
  52. ['user_type' => '', 'name' => '全部会员', 'count' => $all],
  53. ['user_type' => 'routine', 'name' => '小程序会员', 'count' => $routine],
  54. ['user_type' => 'wechat', 'name' => '公众号会员', 'count' => $wechat],
  55. ['user_type' => 'h5', 'name' => 'H5会员', 'count' => $h5],
  56. ];
  57. return $this->success(compact('list'));
  58. }
  59. /**
  60. * 显示资源列表
  61. *
  62. * @return Response
  63. * @throws Exception
  64. */
  65. public function index()
  66. {
  67. $where = Util::getMore([
  68. ['page', 1],
  69. ['limit', 20],
  70. ['nickname', ''],
  71. ['status', ''],
  72. ['pay_count', ''],
  73. ['is_promoter', ''],
  74. ['order', ''],
  75. ['data', ''],
  76. ['user_type', ''],
  77. ['country', ''],
  78. ['province', ''],
  79. ['city', ''],
  80. ['user_time_type', ''],
  81. ['user_time', ''],
  82. ['sex', ''],
  83. [['level', 0], 0],
  84. [['group_id', 'd'], 0],
  85. [['label_id', 'd'], 0]
  86. ]);
  87. $where['mer_id'] = $this->merId;
  88. return $this->success(UserModel::getUserList($where));
  89. }
  90. /**
  91. * 显示创建资源表单页.
  92. *
  93. * @return void
  94. */
  95. public function create()
  96. {
  97. //
  98. }
  99. /**
  100. * 保存新建的资源
  101. *
  102. * @param Request $request
  103. * @return void
  104. */
  105. public function save(Request $request)
  106. {
  107. //
  108. }
  109. /**
  110. * 显示指定的资源
  111. *
  112. * @param int $id
  113. * @return Response
  114. * @throws DataNotFoundException
  115. * @throws DbException
  116. * @throws ModelNotFoundException
  117. */
  118. public function read($id)
  119. {
  120. if (!$id) {
  121. return $this->fail('参数错误');
  122. }
  123. if (!UserModel::be(['uid' => $id, 'mer_id' => $this->merId])) {
  124. return $this->fail('参数错误');
  125. }
  126. $info = [
  127. 'uid' => $id,
  128. 'userinfo' => UserModel::getUserDetailed($id),
  129. 'is_layui' => true,
  130. 'headerList' => UserModel::getHeaderList($id),
  131. 'count' => UserModel::getCountInfo($id),
  132. 'ps_info' => UserModel::where('uid', $id)->find()
  133. ];
  134. return $this->success($info);
  135. }
  136. /**
  137. * 赠送会员等级
  138. * @param $id
  139. * @return mixed
  140. * @throws DataNotFoundException
  141. * @throws DbException
  142. * @throws ModelNotFoundException
  143. */
  144. public function give_level($id)
  145. {
  146. if (!$id) return $this->fail('缺少参数');
  147. $mer_id = $this->merId ?: '';
  148. if (!UserModel::be(['uid' => $id, 'mer_id' => $mer_id])) {
  149. return $this->fail('参数错误');
  150. }
  151. $level = UserLevel::getUserLevel($id);
  152. //获取当前会员等级
  153. if ($level === false)
  154. $grade = 0;
  155. else
  156. $grade = UserLevel::getUserLevelInfo($level, 'grade');
  157. //查询高于当前会员的所有会员等级
  158. $systemLevelList = SystemUserLevel::merSet($this->merId)->where('grade', '>', $grade)->where(['is_show' => 1, 'is_del' => 0])->field(['name', 'id'])->select();
  159. $field[] = Form::select('level_id', '会员等级')->setOptions(function () use ($systemLevelList) {
  160. $menus = [];
  161. foreach ($systemLevelList as $menu) {
  162. $menus[] = ['value' => $menu['id'], 'label' => $menu['name']];
  163. }
  164. return $menus;
  165. })->filterable(1);
  166. return $this->makePostForm('赠送会员', $field, Url::buildUrl('/user/save_give_level/' . $id), 'PUT');
  167. }
  168. /**
  169. * 执行赠送会员等级
  170. * @param $id
  171. * @return mixed
  172. * @throws DataNotFoundException
  173. * @throws DbException
  174. * @throws ModelNotFoundException
  175. * @throws Exception
  176. */
  177. public function save_give_level($id)
  178. {
  179. if (!$id) return $this->fail('缺少参数');
  180. if (!UserModel::be(['uid' => $id, 'mer_id' => $this->merId])) {
  181. return $this->fail('参数错误');
  182. }
  183. list($level_id) = Util::postMore([
  184. ['level_id', 0],
  185. ], $this->request, true);
  186. //查询当前选择的会员等级
  187. $systemLevel = SystemUserLevel::merSet($this->merId)->where(['is_show' => 1, 'is_del' => 0, 'id' => $level_id])->find();
  188. if (!$systemLevel) return $this->fail('您选择赠送的会员等级不存在!');
  189. //检查是否拥有此会员等级
  190. $level = UserLevel::where(['uid' => $id, 'level_id' => $level_id, 'is_del' => 0])->field('valid_time,is_forever')->find();
  191. if ($level) {
  192. if ($level['is_forever']) {
  193. return $this->fail('此用户已有该会员等级,无法再次赠送');
  194. } else {
  195. if (time() < $level['valid_time'])
  196. return $this->fail('此用户已有该会员等级,无法再次赠送');
  197. }
  198. }
  199. //设置会员过期时间
  200. $add_valid_time = (int)$systemLevel->valid_date * 86400;
  201. UserModel::commitTrans();
  202. try {
  203. //保存会员信息
  204. $res = UserLevel::setUserLevel($id, $level_id, $this->merId);
  205. //提取等级任务并记录完成情况
  206. $levelIds = [$level_id];
  207. $lowGradeLevelIds = SystemUserLevel::merSet($this->merId)->where('grade', '<', $systemLevel->grade)->where(['is_show' => 1, 'is_del' => 0])->column('id', 'id');
  208. if (count($lowGradeLevelIds)) $levelIds = array_merge($levelIds, $lowGradeLevelIds);
  209. $taskIds = SystemUserTask::where('level_id', 'in', $levelIds)->column('id', 'id');
  210. $inserValue = [];
  211. foreach ($taskIds as $taskId) {
  212. $inserValue[] = ['uid' => $id, 'task_id' => $taskId, 'status' => 1, 'add_time' => time()];
  213. }
  214. $res = $res && UserTaskFinish::insertAll($inserValue);
  215. if ($res) {
  216. UserModel::commitTrans();
  217. return $this->success('赠送成功');
  218. } else {
  219. UserModel::rollbackTrans();
  220. return $this->success('赠送失败');
  221. }
  222. } catch (Exception $e) {
  223. UserModel::rollbackTrans();
  224. return $this->fail('赠送失败');
  225. }
  226. }
  227. /**
  228. * 清除会员等级
  229. * @param $id
  230. * @return Response
  231. */
  232. public function del_level($id)
  233. {
  234. if (!$id) return $this->fail('缺少参数');
  235. if (!UserModel::be(['uid' => $id, 'mer_id' => $this->merId])) {
  236. return $this->fail('参数错误');
  237. }
  238. if (UserLevel::cleanUpLevel($id))
  239. return $this->success('清除成功');
  240. else
  241. return $this->fail('清除失败');
  242. }
  243. /**
  244. * 设置会员分组
  245. * @return mixed
  246. * @throws DataNotFoundException
  247. * @throws DbException
  248. * @throws ModelNotFoundException
  249. * @throws Exception
  250. */
  251. public function set_group()
  252. {
  253. list($uids) = Util::postMore([
  254. ['uids', []],
  255. ], $this->request, true);
  256. $uid = implode(',', $uids);
  257. if (!$uid) return $this->fail('缺少参数');
  258. if (UserModel::where(['uid' => $uids, 'mer_id' => $this->merId])->count() != count($uids)) {
  259. return $this->fail('参数错误');
  260. }
  261. $userGroup = UserGroup::select();
  262. if (count($uids) == 1) {
  263. $user = UserModel::where('uid', $uids[0])->find();
  264. $field[] = Form::select('group_id', '会员分组', (string)$user->getData('group_id'))->setOptions(function () use ($userGroup) {
  265. $menus = [];
  266. foreach ($userGroup as $menu) {
  267. $menus[] = ['value' => $menu['id'], 'label' => $menu['group_name']];
  268. }
  269. return $menus;
  270. })->filterable(1);
  271. } else {
  272. $field[] = Form::select('group_id', '会员分组')->setOptions(function () use ($userGroup) {
  273. $menus = [];
  274. foreach ($userGroup as $menu) {
  275. $menus[] = ['value' => $menu['id'], 'label' => $menu['group_name']];
  276. }
  277. return $menus;
  278. })->filterable(1);
  279. }
  280. $field[] = Form::hidden('uids', $uid);
  281. return $this->makePostForm('设置会员分组', $field, Url::buildUrl('/user/save_set_group'), 'PUT');
  282. }
  283. /**
  284. * 保存会员分组
  285. * @param $id
  286. * @return mixed
  287. * @throws Exception
  288. */
  289. public function save_set_group()
  290. {
  291. list($group_id, $uids) = Util::postMore([
  292. ['group_id', 0],
  293. ['uids', ''],
  294. ], $this->request, true);
  295. if (!$uids) return $this->fail('缺少参数');
  296. $uids = explode(',', $uids);
  297. if (UserModel::where(['uid' => $uids, 'mer_id' => $this->merId])->count() != count($uids)) {
  298. return $this->fail('参数错误');
  299. }
  300. $res = UserModel::whereIn('uid', $uids)->update(['group_id' => $group_id]);
  301. if ($res) {
  302. return $this->success('设置分组成功');
  303. } else {
  304. return $this->fail('设置分组失败或无改动');
  305. }
  306. }
  307. /**
  308. * 设置用户标签
  309. * @return mixed
  310. * @throws DataNotFoundException
  311. * @throws DbException
  312. * @throws ModelNotFoundException
  313. * @throws Exception
  314. */
  315. public function set_label()
  316. {
  317. list($uids) = Util::postMore([
  318. ['uids', []],
  319. ], $this->request, true);
  320. $uid = implode(',', $uids);
  321. if (!$uid) return $this->fail('缺少参数');
  322. if (UserModel::where(['uid' => $uids, 'mer_id' => $this->merId])->count() != count($uids)) {
  323. return $this->fail('参数错误');
  324. }
  325. $userGroup = UserLabel::select();
  326. if (count($uids) == 1) {
  327. $lids = UserLabelRelation::where('uid', $uids[0])->column('label_id');
  328. $field[] = Form::select('label_id', '会员标签', $lids)->setOptions(function () use ($userGroup) {
  329. $menus = [];
  330. foreach ($userGroup as $menu) {
  331. $menus[] = ['value' => $menu['id'], 'label' => $menu['label_name']];
  332. }
  333. return $menus;
  334. })->filterable(1)->multiple(1);
  335. } else {
  336. $field[] = Form::select('label_id', '会员标签')->setOptions(function () use ($userGroup) {
  337. $menus = [];
  338. foreach ($userGroup as $menu) {
  339. $menus[] = ['value' => $menu['id'], 'label' => $menu['label_name']];
  340. }
  341. return $menus;
  342. })->filterable(1)->multiple(1);
  343. }
  344. $field[] = Form::hidden('uids', $uid);
  345. return $this->makePostForm('设置会员标签', $field, Url::buildUrl('/user/save_set_label'), 'PUT');
  346. }
  347. /**
  348. * 保存用户标签
  349. * @return mixed
  350. * @throws Exception
  351. */
  352. public function save_set_label()
  353. {
  354. list($lables, $uids) = Util::postMore([
  355. ['label_id', ''],
  356. ['uids', ''],
  357. ], $this->request, true);
  358. if (!$uids) return $this->fail('缺少参数');
  359. $uids = explode(',', $uids);
  360. if (UserModel::where([['uid', 'in', $uids], ['mer_id', '=', $this->merId]])->count() != count($uids)) {
  361. return $this->fail('参数错误');
  362. }
  363. $res = UserLabelRelation::saveUserLabel($uids, $lables);
  364. if ($res) {
  365. return $this->success('设置标签成功');
  366. } else {
  367. return $this->fail('设置标签失败');
  368. }
  369. }
  370. /**
  371. * 编辑其他
  372. * @param $id
  373. * @return mixed
  374. * @throws DataNotFoundException
  375. * @throws DbException
  376. * @throws FormBuilderException
  377. * @throws ModelNotFoundException
  378. */
  379. public function edit_other($id)
  380. {
  381. if (!$id) return $this->fail('数据不存在');
  382. $user = UserModel::merSet($this->merId)->where('uid', $id)->find();
  383. if (!$user) return $this->fail('数据不存在!');
  384. $f = array();
  385. $f[] = Form::radio('money_status', '修改余额', 1)->options([['value' => 1, 'label' => '增加'], ['value' => 2, 'label' => '减少']]);
  386. $f[] = Form::number('money', '余额', 0)->min(0);
  387. $f[] = Form::radio('integration_status', '修改积分', 1)->options([['value' => 1, 'label' => '增加'], ['value' => 2, 'label' => '减少']]);
  388. $f[] = Form::number('integration', '积分', 0)->min(0);
  389. return $this->makePostForm('修改其他', $f, Url::buildUrl('/user/update_other/' . $id), 'PUT');
  390. }
  391. /**
  392. * 执行编辑其他
  393. * @param int $id
  394. * @return mixed
  395. * @throws Exception
  396. */
  397. public function update_other($id)
  398. {
  399. $data = Util::postMore([
  400. ['money_status', 0],
  401. ['money', 0],
  402. ['integration_status', 0],
  403. ['integration', 0],
  404. ], $this->request);
  405. if (!$id) return $this->fail('数据不存在');
  406. $user = UserModel::merSet($this->merId)->where('uid', $id)->find();
  407. if (!$user) return $this->fail('数据不存在!');
  408. BaseModel::beginTrans();
  409. $res1 = false;
  410. $res2 = false;
  411. $edit = array();
  412. if ($data['money_status'] && $data['money']) {//余额增加或者减少
  413. if ($data['money_status'] == 1) {//增加
  414. $edit['now_money'] = bcadd($user['now_money'], $data['money'], 2);
  415. $res1 = UserBillAdmin::income('系统增加余额', $user['uid'], 'now_money', 'system_add', $data['money'], $this->adminId, $edit['now_money'], '系统增加了' . floatval($data['money']) . '余额');
  416. try {
  417. UserRepository::adminAddMoney($user, $data['money']);
  418. } catch (Exception $e) {
  419. BaseModel::rollbackTrans();
  420. return $this->fail($e->getMessage());
  421. }
  422. } else if ($data['money_status'] == 2) {//减少
  423. $edit['now_money'] = bcsub($user['now_money'], $data['money'], 2);
  424. $res1 = UserBillAdmin::expend('系统减少余额', $user['uid'], 'now_money', 'system_sub', $data['money'], $this->adminId, $edit['now_money'], '系统扣除了' . floatval($data['money']) . '余额');
  425. try {
  426. UserRepository::adminSubMoney($user, $data['money']);
  427. } catch (Exception $e) {
  428. BaseModel::rollbackTrans();
  429. return $this->fail($e->getMessage());
  430. }
  431. }
  432. } else {
  433. $res1 = true;
  434. }
  435. if ($data['integration_status'] && $data['integration']) {//积分增加或者减少
  436. if ($data['integration_status'] == 1) {//增加
  437. $edit['integral'] = bcadd($user['integral'], $data['integration'], 2);
  438. $res2 = UserBillAdmin::income('系统增加积分', $user['uid'], 'integral', 'system_add', $data['integration'], $this->adminId, $edit['integral'], '系统增加了' . floatval($data['integration']) . '积分');
  439. try {
  440. UserRepository::adminAddIntegral($user, $data['integration']);
  441. } catch (Exception $e) {
  442. BaseModel::rollbackTrans();
  443. return $this->fail($e->getMessage());
  444. }
  445. } else if ($data['integration_status'] == 2) {//减少
  446. $edit['integral'] = bcsub($user['integral'], $data['integration'], 2);
  447. $res2 = UserBillAdmin::expend('系统减少积分', $user['uid'], 'integral', 'system_sub', $data['integration'], $this->adminId, $edit['integral'], '系统扣除了' . floatval($data['integration']) . '积分');
  448. try {
  449. UserRepository::adminSubIntegral($user, $data['integration']);
  450. } catch (Exception $e) {
  451. BaseModel::rollbackTrans();
  452. return $this->fail($e->getMessage());
  453. }
  454. }
  455. } else {
  456. $res2 = true;
  457. }
  458. if ($edit) $res3 = UserModel::edit($edit, $id);
  459. else $res3 = true;
  460. if ($res1 && $res2 && $res3) $res = true;
  461. else $res = false;
  462. BaseModel::checkTrans($res);
  463. if ($res) return $this->success('修改成功!');
  464. else return $this->fail('修改失败');
  465. }
  466. /**
  467. * 修改user表状态
  468. *
  469. * @return array
  470. */
  471. public function set_status($status, $id)
  472. {
  473. if ($status == '' || $id == 0) return $this->fail('参数错误');
  474. UserModel::merSet($this->merId)->where(['uid' => $id])->update(['status' => $status]);
  475. return $this->success($status == 0 ? '禁用成功' : '解禁成功');
  476. }
  477. /**
  478. * 编辑会员信息
  479. * @param $id
  480. * @return mixed|Json|void
  481. * @throws DataNotFoundException
  482. * @throws DbException
  483. * @throws FormBuilderException
  484. * @throws ModelNotFoundException
  485. */
  486. public function edit($id)
  487. {
  488. if (!$id) return $this->fail('数据不存在');
  489. $user = UserModel::merSet($this->merId)->where('uid', $id)->find();
  490. if (!$user) return $this->fail('数据不存在!');
  491. $f = array();
  492. $f[] = Form::input('uid', '用户编号', $user->getData('uid'))->disabled(1);
  493. $f[] = Form::input('real_name', '真实姓名', $user->getData('real_name'));
  494. $f[] = Form::input('phone', '手机号码', $user->getData('phone'));
  495. $f[] = Form::date('birthday', '生日', $user->getData('birthday') ? date('Y-m-d', $user->getData('birthday')) : '');
  496. $f[] = Form::input('card_id', '身份证号', $user->getData('card_id'));
  497. $f[] = Form::input('addres', '用户地址', $user->getData('addres'));
  498. $f[] = Form::textarea('mark', '用户备注', $user->getData('mark'));
  499. $level = UserLevel::getUserLevel($id);
  500. //获取当前会员等级
  501. if ($level === false)
  502. $grade = 0;
  503. else
  504. $grade = UserLevel::getUserLevelInfo($level, 'grade');
  505. //查询高于当前会员的所有会员等级
  506. $systemLevelList = SystemUserLevel::merSet($this->merId)->where('grade', '>', $grade)->where(['is_show' => 1, 'is_del' => 0])->field(['name', 'id'])->select();
  507. $f[] = Form::select('level', '会员等级', (string)$user->getData('level'))->setOptions(function () use ($systemLevelList) {
  508. $menus = [];
  509. foreach ($systemLevelList as $menu) {
  510. $menus[] = ['value' => $menu['id'], 'label' => $menu['name']];
  511. }
  512. return $menus;
  513. })->filterable(1);
  514. $systemGroupList = UserGroup::select();
  515. $f[] = Form::select('group_id', '会员分组', (string)$user->getData('group_id'))->setOptions(function () use ($systemGroupList) {
  516. $menus = [];
  517. foreach ($systemGroupList as $menu) {
  518. $menus[] = ['value' => $menu['id'], 'label' => $menu['group_name']];
  519. }
  520. return $menus;
  521. })->filterable(1);
  522. $systemLabelList = UserLabel::select();
  523. $labels = UserLabelRelation::where('uid', $user->getData('uid'))->column('label_id');
  524. $f[] = Form::select('label_id', '会员标签', $labels)->setOptions(function () use ($systemLabelList) {
  525. $menus = [];
  526. foreach ($systemLabelList as $menu) {
  527. $menus[] = ['value' => $menu['id'], 'label' => $menu['label_name']];
  528. }
  529. return $menus;
  530. })->filterable(1)->multiple(1);
  531. $f[] = Form::radio('is_promoter', '推广员', $user->getData('is_promoter'))->options([['value' => 1, 'label' => '开启'], ['value' => 0, 'label' => '关闭']]);
  532. $f[] = Form::radio('status', '状态', $user->getData('status'))->options([['value' => 1, 'label' => '开启'], ['value' => 0, 'label' => '锁定']]);
  533. return $this->makePostForm('编辑', $f, Url::buildUrl('/user/user/' . $id), 'PUT');
  534. }
  535. /**
  536. * @param $id
  537. * @return mixed
  538. * @throws DataNotFoundException
  539. * @throws DbException
  540. * @throws ModelNotFoundException
  541. * @throws Exception
  542. */
  543. public function update($id)
  544. {
  545. $data = Util::postMore([
  546. ['money_status', 0],
  547. ['is_promoter', 1],
  548. ['real_name', ''],
  549. ['card_id', ''],
  550. ['birthday', ''],
  551. ['mark', ''],
  552. ['money', 0],
  553. ['integration_status', 0],
  554. ['integration', 0],
  555. ['status', 0],
  556. ['level', 0],
  557. ['phone', 0],
  558. ['addres', ''],
  559. ['label_id', ''],
  560. ['group_id', 0]
  561. ]);
  562. if ($data['phone']) {
  563. if (!preg_match("/^1[3456789]\d{9}$/", $data['phone'])) return $this->fail('手机号码格式不正确');
  564. }
  565. if ($data['card_id']) {
  566. if (!preg_match('/^[1-9]{1}\d{5}[1-9]{2}\d{9}[Xx0-9]{1}$/', $data['card_id'])) return $this->fail('请输入正确的身份证');
  567. }
  568. if (!$id) return $this->fail('数据不存在');
  569. $user = UserModel::merSet($this->merId)->where('uid', $id)->find();
  570. if (!$user) return $this->fail('数据不存在!');
  571. BaseModel::beginTrans();
  572. $res1 = false;
  573. $res2 = false;
  574. $edit = array();
  575. if ($data['money_status'] && $data['money']) {//余额增加或者减少
  576. if ($data['money_status'] == 1) {//增加
  577. $edit['now_money'] = bcadd($user['now_money'], $data['money'], 2);
  578. $res1 = UserBillAdmin::income('系统增加余额', $user['uid'], 'now_money', 'system_add', $data['money'], $this->adminId, $edit['now_money'], '系统增加了' . floatval($data['money']) . '余额');
  579. try {
  580. UserRepository::adminAddMoney($user, $data['money']);
  581. } catch (Exception $e) {
  582. BaseModel::rollbackTrans();
  583. return $this->fail($e->getMessage());
  584. }
  585. } else if ($data['money_status'] == 2) {//减少
  586. $edit['now_money'] = bcsub($user['now_money'], $data['money'], 2);
  587. $res1 = UserBillAdmin::expend('系统减少余额', $user['uid'], 'now_money', 'system_sub', $data['money'], $this->adminId, $edit['now_money'], '系统扣除了' . floatval($data['money']) . '余额');
  588. try {
  589. UserRepository::adminSubMoney($user, $data['money']);
  590. } catch (Exception $e) {
  591. BaseModel::rollbackTrans();
  592. return $this->fail($e->getMessage());
  593. }
  594. }
  595. } else {
  596. $res1 = true;
  597. }
  598. if ($data['integration_status'] && $data['integration']) {//积分增加或者减少
  599. if ($data['integration_status'] == 1) {//增加
  600. $edit['integral'] = bcadd($user['integral'], $data['integration'], 2);
  601. $res2 = UserBillAdmin::income('系统增加积分', $user['uid'], 'integral', 'system_add', $data['integration'], $this->adminId, $edit['integral'], '系统增加了' . floatval($data['integration']) . '积分');
  602. try {
  603. UserRepository::adminAddIntegral($user, $data['integration']);
  604. } catch (Exception $e) {
  605. BaseModel::rollbackTrans();
  606. return $this->fail($e->getMessage());
  607. }
  608. } else if ($data['integration_status'] == 2) {//减少
  609. $edit['integral'] = bcsub($user['integral'], $data['integration'], 2);
  610. $res2 = UserBillAdmin::expend('系统减少积分', $user['uid'], 'integral', 'system_sub', $data['integration'], $this->adminId, $edit['integral'], '系统扣除了' . floatval($data['integration']) . '积分');
  611. try {
  612. UserRepository::adminSubIntegral($user, $data['integration']);
  613. } catch (Exception $e) {
  614. BaseModel::rollbackTrans();
  615. return $this->fail($e->getMessage());
  616. }
  617. }
  618. } else {
  619. $res2 = true;
  620. }
  621. UserLabelRelation::saveUserLabel([$id], $data['label_id']);
  622. $edit['status'] = $data['status'];
  623. $edit['real_name'] = $data['real_name'];
  624. $edit['card_id'] = $data['card_id'];
  625. $edit['birthday'] = strtotime($data['birthday']);
  626. $edit['mark'] = $data['mark'];
  627. $edit['is_promoter'] = $data['is_promoter'];
  628. $edit['level'] = $data['level'];
  629. $edit['phone'] = $data['phone'];
  630. $edit['addres'] = $data['addres'];
  631. $edit['group_id'] = $data['group_id'];
  632. if ($edit) $res3 = UserModel::edit($edit, $id);
  633. else $res3 = true;
  634. if ($res1 && $res2 && $res3) $res = true;
  635. else $res = false;
  636. BaseModel::checkTrans($res);
  637. if ($res) return $this->success('修改成功!');
  638. else return $this->fail('修改失败');
  639. }
  640. /**
  641. * TODO:需统一到数据统计模块 start
  642. * 用户图表
  643. * @return mixed
  644. * @throws DataNotFoundException
  645. * @throws DbException
  646. * @throws ModelNotFoundException
  647. * @throws Exception
  648. */
  649. public function user_analysis()
  650. {
  651. $where = Util::getMore([
  652. ['nickname', ''],
  653. ['status', ''],
  654. ['is_promoter', ''],
  655. ['date', ''],
  656. ['user_type', ''],
  657. ['export', 0]
  658. ], $this->request);
  659. $user_count = UserModel::consume($where, '', true, $this->merId);
  660. //头部信息
  661. $header = [
  662. [
  663. 'name' => '新增用户',
  664. 'class' => 'fa-line-chart',
  665. 'value' => $user_count,
  666. 'color' => 'red'
  667. ],
  668. [
  669. 'name' => '用户留存',
  670. 'class' => 'fa-area-chart',
  671. 'value' => $this->gethreaderValue(UserModel::consume($where, '', true, $this->merId), $where) . '%',
  672. 'color' => 'lazur'
  673. ],
  674. [
  675. 'name' => '新增用户总消费',
  676. 'class' => 'fa-bar-chart',
  677. 'value' => '¥' . UserModel::consume($where, '', '', $this->merId),
  678. 'color' => 'navy'
  679. ],
  680. [
  681. 'name' => '用户活跃度',
  682. 'class' => 'fa-pie-chart',
  683. 'value' => $this->gethreaderValue(UserModel::consume($where, '', true, $this->merId)) . '%',
  684. 'color' => 'yellow'
  685. ],
  686. ];
  687. $name = ['新增用户', '用户消费'];
  688. $dates = $this->get_user_index($where, $name);
  689. $user_index = ['name' => json_encode($name), 'date' => json_encode($dates['time']), 'series' => json_encode($dates['series'])];
  690. //用户浏览分析
  691. $view = StoreVisit::getVisit($where['date'], ['', 'warning', 'info', 'danger'], $this->merId);
  692. $view_v1 = WechatMessage::getViweList($where['date'], ['', 'warning', 'info', 'danger'], $this->merId);
  693. $view = array_merge($view, $view_v1);
  694. $view_v2 = [];
  695. foreach ($view as $val) {
  696. $view_v2['color'][] = '#' . rand(100000, 339899);
  697. $view_v2['name'][] = $val['name'];
  698. $view_v2['value'][] = $val['value'];
  699. }
  700. $view = $view_v2;
  701. //消费会员排行用户分析
  702. $user_null = UserModel::getUserSpend($where['date'], '', $this->merId);
  703. //消费数据
  704. $now_number = UserModel::getUserSpend($where['date'], true, $this->merId);
  705. list($paren_number, $title) = UserModel::getPostNumber($where['date'], false, 'A.add_time', '消费', $this->merId);
  706. if ($paren_number == 0) {
  707. $rightTitle = [
  708. 'number' => $now_number > 0 ? $now_number : 0,
  709. 'icon' => 'fa-level-up',
  710. 'title' => $title
  711. ];
  712. } else {
  713. $number = (float)bcsub((string)$now_number, $paren_number, 4);
  714. if ($now_number == 0) {
  715. $icon = 'fa-level-down';
  716. } else {
  717. $icon = $now_number > $paren_number ? 'fa-level-up' : 'fa-level-down';
  718. }
  719. $rightTitle = ['number' => $number, 'icon' => $icon, 'title' => $title];
  720. }
  721. unset($title, $paren_number, $now_number);
  722. list($paren_user_count, $title) = UserModel::getPostNumber($where['date'], true, 'add_time', '', $this->merId);
  723. if ($paren_user_count == 0) {
  724. $count = $user_count == 0 ? 0 : $user_count;
  725. $icon = $user_count == 0 ? 'fa-level-down' : 'fa-level-up';
  726. } else {
  727. $count = (float)bcsub($user_count, $paren_user_count, 4);
  728. $icon = $user_count < $paren_user_count ? 'fa-level-down' : 'fa-level-up';
  729. }
  730. $leftTitle = [
  731. 'count' => $count,
  732. 'icon' => $icon,
  733. 'title' => $title
  734. ];
  735. unset($count, $icon, $title);
  736. $consume = [
  737. 'title' => '消费金额为¥' . UserModel::consume($where, '', '', $this->merId),
  738. 'series' => UserModel::consume($where, 'xiaofei', '', $this->merId),
  739. 'rightTitle' => $rightTitle,
  740. 'leftTitle' => $leftTitle,
  741. ];
  742. $form = UserModel::consume($where, 'form', '', $this->merId);
  743. $grouping = UserModel::consume($where, 'grouping', '', $this->merId);
  744. return $this->success(compact('header', 'user_index', 'view', 'user_null', 'consume', 'form', 'grouping', 'where'));
  745. }
  746. /**
  747. * @param $chart
  748. * @param array $where
  749. * @return float|int
  750. */
  751. public function gethreaderValue($chart, $where = [])
  752. {
  753. if ($where) {
  754. switch ($where['date']) {
  755. case null:
  756. case 'today':
  757. case 'week':
  758. case 'year':
  759. if ($where['date'] == null) {
  760. $where['date'] = 'month';
  761. }
  762. $sum_user = UserModel::merSet($this->merId)->whereTime('add_time', $where['date'])->count();
  763. if ($sum_user == 0) return 0;
  764. $counts = bcdiv($chart, $sum_user, 4) * 100;
  765. return $counts;
  766. break;
  767. case 'quarter':
  768. $quarter = UserModel::getMonth('n');
  769. $quarter[0] = strtotime($quarter[0]);
  770. $quarter[1] = strtotime($quarter[1]);
  771. $sum_user = UserModel::merSet($this->merId)->where('add_time', 'between', $quarter)->count();
  772. if ($sum_user == 0) return 0;
  773. $counts = bcdiv($chart, $sum_user, 4) * 100;
  774. return $counts;
  775. default:
  776. //自定义时间
  777. $quarter = explode('-', $where['date']);
  778. $quarter[0] = strtotime($quarter[0]);
  779. $quarter[1] = strtotime($quarter[1]);
  780. $sum_user = UserModel::merSet($this->merId)->where('add_time', 'between', $quarter)->count();
  781. if ($sum_user == 0) return 0;
  782. $counts = bcdiv($chart, $sum_user, 4) * 100;
  783. return $counts;
  784. break;
  785. }
  786. } else {
  787. $num = UserModel::merSet($this->merId)->count();
  788. $chart = $num != 0 ? bcdiv($chart, $num, 5) * 100 : 0;
  789. return $chart;
  790. }
  791. }
  792. /**
  793. * @param $where
  794. * @param $name
  795. * @return array
  796. * @throws DataNotFoundException
  797. * @throws DbException
  798. * @throws ModelNotFoundException
  799. */
  800. public function get_user_index($where, $name)
  801. {
  802. switch ($where['date']) {
  803. case null:
  804. $days = date("t", strtotime(date('Y-m', time())));
  805. $dates = [];
  806. $series = [];
  807. $times_list = [];
  808. foreach ($name as $key => $val) {
  809. for ($i = 1; $i <= $days; $i++) {
  810. if (!in_array($i . '号', $times_list)) {
  811. array_push($times_list, $i . '号');
  812. }
  813. $time = $this->gettime(date("Y-m", time()) . '-' . $i);
  814. if ($key == 0) {
  815. $dates['data'][] = UserModel::merSet($this->merId)->where('add_time', 'between', $time)->count();
  816. } else if ($key == 1) {
  817. $dates['data'][] = UserModel::consume(true, $time, '', $this->merId);
  818. }
  819. }
  820. $dates['name'] = $val;
  821. $dates['type'] = 'line';
  822. $series[] = $dates;
  823. unset($dates);
  824. }
  825. return ['time' => $times_list, 'series' => $series];
  826. case 'today':
  827. $dates = [];
  828. $series = [];
  829. $times_list = [];
  830. foreach ($name as $key => $val) {
  831. for ($i = 0; $i <= 24; $i++) {
  832. $strtitle = $i . '点';
  833. if (!in_array($strtitle, $times_list)) {
  834. array_push($times_list, $strtitle);
  835. }
  836. $time = $this->gettime(date("Y-m-d ", time()) . $i);
  837. if ($key == 0) {
  838. $dates['data'][] = UserModel::merSet($this->merId)->where('add_time', 'between', $time)->count();
  839. } else if ($key == 1) {
  840. $dates['data'][] = UserModel::consume(true, $time, '', $this->merId);
  841. }
  842. }
  843. $dates['name'] = $val;
  844. $dates['type'] = 'line';
  845. $series[] = $dates;
  846. unset($dates);
  847. }
  848. return ['time' => $times_list, 'series' => $series];
  849. case "week":
  850. $dates = [];
  851. $series = [];
  852. $times_list = [];
  853. foreach ($name as $key => $val) {
  854. for ($i = 0; $i <= 6; $i++) {
  855. if (!in_array('星期' . ($i + 1), $times_list)) {
  856. array_push($times_list, '星期' . ($i + 1));
  857. }
  858. $time = UserModel::getMonth('h', $i);
  859. if ($key == 0) {
  860. $dates['data'][] = UserModel::merSet($this->merId)->where('add_time', 'between', [strtotime($time[0]), strtotime($time[1])])->count();
  861. } else if ($key == 1) {
  862. $dates['data'][] = UserModel::consume(true, [strtotime($time[0]), strtotime($time[1])], '', $this->merId);
  863. }
  864. }
  865. $dates['name'] = $val;
  866. $dates['type'] = 'line';
  867. $series[] = $dates;
  868. unset($dates);
  869. }
  870. return ['time' => $times_list, 'series' => $series];
  871. case 'year':
  872. $dates = [];
  873. $series = [];
  874. $times_list = [];
  875. $year = date('Y');
  876. foreach ($name as $key => $val) {
  877. for ($i = 1; $i <= 12; $i++) {
  878. if (!in_array($i . '月', $times_list)) {
  879. array_push($times_list, $i . '月');
  880. }
  881. $t = strtotime($year . '-' . $i . '-01');
  882. $arr = explode('/', date('Y-m-01', $t) . '/' . date('Y-m-', $t) . date('t', $t));
  883. if ($key == 0) {
  884. $dates['data'][] = UserModel::merSet($this->merId)->where('add_time', 'between', [strtotime($arr[0]), strtotime($arr[1])])->count();
  885. } else if ($key == 1) {
  886. $dates['data'][] = UserModel::consume(true, [strtotime($arr[0]), strtotime($arr[1])], '', $this->merId);
  887. }
  888. }
  889. $dates['name'] = $val;
  890. $dates['type'] = 'line';
  891. $series[] = $dates;
  892. unset($dates);
  893. }
  894. return ['time' => $times_list, 'series' => $series];
  895. case 'quarter':
  896. $dates = [];
  897. $series = [];
  898. $times_list = [];
  899. foreach ($name as $key => $val) {
  900. for ($i = 1; $i <= 4; $i++) {
  901. $arr = $this->gettime('quarter', $i);
  902. if (!in_array(implode('--', $arr) . '季度', $times_list)) {
  903. array_push($times_list, implode('--', $arr) . '季度');
  904. }
  905. if ($key == 0) {
  906. $dates['data'][] = UserModel::merSet($this->merId)->where('add_time', 'between', [strtotime($arr[0]), strtotime($arr[1])])->count();
  907. } else if ($key == 1) {
  908. $dates['data'][] = UserModel::consume(true, [strtotime($arr[0]), strtotime($arr[1])], '', $this->merId);
  909. }
  910. }
  911. $dates['name'] = $val;
  912. $dates['type'] = 'line';
  913. $series[] = $dates;
  914. unset($dates);
  915. }
  916. return ['time' => $times_list, 'series' => $series];
  917. default:
  918. $list = UserModel::consume($where, 'default', '', $this->merId);
  919. $dates = [];
  920. $series = [];
  921. $times_list = [];
  922. foreach ($name as $k => $v) {
  923. foreach ($list as $val) {
  924. $date = $val['add_time'];
  925. if (!in_array($date, $times_list)) {
  926. array_push($times_list, $date);
  927. }
  928. if ($k == 0) {
  929. $dates['data'][] = $val['num'];
  930. } else if ($k == 1) {
  931. $dates['data'][] = UserBillAdmin::where(['uid' => $val['uid'], 'type' => 'pay_product'])->sum('number');
  932. }
  933. }
  934. $dates['name'] = $v;
  935. $dates['type'] = 'line';
  936. $series[] = $dates;
  937. unset($dates);
  938. }
  939. return ['time' => $times_list, 'series' => $series];
  940. }
  941. }
  942. public function gettime($time = '', $season = '')
  943. {
  944. if (!empty($time) && empty($season)) {
  945. $timestamp0 = strtotime($time);
  946. $timestamp24 = strtotime($time) + 86400;
  947. return [$timestamp0, $timestamp24];
  948. } else if (!empty($time) && !empty($season)) {
  949. $firstday = date('Y-m-01', mktime(0, 0, 0, ($season - 1) * 3 + 1, 1, date('Y')));
  950. $lastday = date('Y-m-t', mktime(0, 0, 0, $season * 3, 1, date('Y')));
  951. return [$firstday, $lastday];
  952. }
  953. }
  954. /**
  955. * TODO:需统一到数据统计模块 end
  956. */
  957. /**
  958. * 获取单个用户信息
  959. * @param int $id 用户id
  960. * @return mixed
  961. * @throws Exception
  962. */
  963. public function oneUserInfo($id)
  964. {
  965. $data = Util::getMore([
  966. ['type', ''],
  967. ['page', 1],
  968. ['limit', 20]
  969. ]);
  970. if (!$id || $data['type'] == '') return $this->fail('缺少参数');
  971. if (!UserModel::be(['uid' => $id, 'mer_id' => $this->merId])) {
  972. return $this->fail('参数错误');
  973. }
  974. switch ($data['type']) {
  975. case 'spread':
  976. return $this->getSpreadList($id, $data['page'], $data['limit'], $this->merId);
  977. break;
  978. case 'order':
  979. return $this->getOneOrderList($id, $data['page'], $data['limit']);
  980. break;
  981. case 'integral':
  982. return $this->getOneIntegralList($id, $data['page'], $data['limit']);
  983. break;
  984. case 'sign':
  985. return $this->getOneSignList($id, $data['page'], $data['limit']);
  986. break;
  987. case 'coupon':
  988. return $this->getOneCouponsList($id, $data['page'], $data['limit']);
  989. break;
  990. case 'balance_change':
  991. return $this->getOneBalanceChangList($id, $data['page'], $data['limit']);
  992. break;
  993. default:
  994. return $this->fail('type参数错误');
  995. }
  996. }
  997. /**
  998. * 获取某个用户的推广下线
  999. * @param $id
  1000. * @param $page
  1001. * @param $limit
  1002. * @param string $mer_id
  1003. * @return Response
  1004. */
  1005. public function getSpreadList($id, $page, $limit, $mer_id = '')
  1006. {
  1007. return $this->success(UserModel::getSpreadList($id, (int)$page, (int)$limit, $mer_id));
  1008. }
  1009. /**
  1010. * 获取某用户的订单列表
  1011. * @param $id
  1012. * @param $page
  1013. * @param $limit
  1014. * @param string $mer_id
  1015. * @return Response
  1016. */
  1017. public function getOneOrderList($id, $page, $limit)
  1018. {
  1019. return $this->success(StoreOrder::getOneorderList(compact('id', 'page', 'limit')));
  1020. }
  1021. /**
  1022. * 获取某用户的积分列表
  1023. * @param $id
  1024. * @param int $page
  1025. * @param int $limit
  1026. * @return
  1027. */
  1028. public function getOneIntegralList($id, $page = 1, $limit = 20)
  1029. {
  1030. return $this->success(UserBillAdmin::getOneIntegralList(compact('id', 'page', 'limit')));
  1031. }
  1032. /**
  1033. * 获取某用户的签到明细
  1034. * @param $id
  1035. * @param int $page
  1036. * @param int $limit
  1037. * @return
  1038. */
  1039. public function getOneSignList($id, $page = 1, $limit = 20)
  1040. {
  1041. return $this->success(UserBillAdmin::getOneSignList(compact('id', 'page', 'limit')));
  1042. }
  1043. /**
  1044. * 获取某用户的持有优惠劵
  1045. * @param $id
  1046. * @param int $page
  1047. * @param int $limit
  1048. * @return
  1049. */
  1050. public function getOneCouponsList($id, $page = 1, $limit = 20)
  1051. {
  1052. return $this->success(StoreCouponUser::getOneCouponsList(compact('id', 'page', 'limit')));
  1053. }
  1054. /**
  1055. * 获取某用户的余额变动记录
  1056. * @param $id
  1057. * @param int $page
  1058. * @param int $limit
  1059. * @return
  1060. */
  1061. public function getOneBalanceChangList($id, $page = 1, $limit = 20)
  1062. {
  1063. return $this->success(UserBillAdmin::getOneBalanceChangList(compact('id', 'page', 'limit')));
  1064. }
  1065. }