User.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. <?php
  2. /**
  3. *
  4. * @author: xaboy<365615158@qq.com>
  5. * @day: 2017/11/11
  6. */
  7. namespace app\admin\controller\user;
  8. use app\admin\controller\AuthController;
  9. use service\FormBuilder as Form;
  10. use traits\CurdControllerTrait;
  11. use service\UtilService as Util;
  12. use service\JsonService as Json;
  13. use think\Request;
  14. use think\Url;
  15. use app\admin\model\user\User as UserModel;
  16. use app\admin\model\user\UserBill AS UserBillAdmin;
  17. use basic\ModelBasic;
  18. use service\HookService;
  19. use behavior\user\UserBehavior;
  20. use app\admin\model\store\StoreVisit;
  21. use app\admin\model\wechat\WechatMessage;
  22. use app\admin\model\order\StoreOrder;
  23. use app\admin\model\store\StoreCouponUser;
  24. /**
  25. * 用户管理控制器
  26. * Class User
  27. * @package app\admin\controller\user
  28. */
  29. class User extends AuthController
  30. {
  31. use CurdControllerTrait;
  32. /**
  33. * 显示资源列表
  34. *
  35. * @return \think\Response
  36. */
  37. public function index(){
  38. $this->assign('count_user',UserModel::getcount());
  39. return $this->fetch();
  40. }
  41. /**
  42. * 修改user表状态
  43. *
  44. * @return json
  45. */
  46. public function set_status($status='',$uid=0,$is_echo=0){
  47. if($is_echo==0) {
  48. if ($status == '' || $uid == 0) return Json::fail('参数错误');
  49. UserModel::where(['uid' => $uid])->update(['status' => $status]);
  50. }else{
  51. $uids=Util::postMore([
  52. ['uids',[]]
  53. ]);
  54. UserModel::destrSyatus($uids['uids'],$status);
  55. }
  56. return Json::successful($status==0 ? '禁用成功':'解禁成功');
  57. }
  58. /**
  59. * 获取user表
  60. *
  61. * @return json
  62. */
  63. public function get_user_list(){
  64. $where=Util::getMore([
  65. ['page',1],
  66. ['limit',20],
  67. ['nickname',''],
  68. ['status',''],
  69. ['pay_count',''],
  70. ['is_promoter',''],
  71. ['order',''],
  72. ['data',''],
  73. ['user_type',''],
  74. ['country',''],
  75. ['province',''],
  76. ['city',''],
  77. ['user_time_type',''],
  78. ['user_time',''],
  79. ['sex',''],
  80. ]);
  81. return Json::successlayui(UserModel::getUserList($where));
  82. }
  83. /**
  84. * 编辑模板消息
  85. * @param $id
  86. * @return mixed|\think\response\Json|void
  87. */
  88. public function edit($uid)
  89. {
  90. if(!$uid) return $this->failed('数据不存在');
  91. $user = UserModel::get($uid);
  92. if(!$user) return Json::fail('数据不存在!');
  93. $f = array();
  94. $f[] = Form::input('uid','用户编号',$user->getData('uid'))->disabled(1);
  95. $f[] = Form::input('nickname','用户姓名',$user->getData('nickname'));
  96. $f[] = Form::radio('money_status','修改余额',1)->options([['value'=>1,'label'=>'增加'],['value'=>2,'label'=>'减少']]);
  97. $f[] = Form::number('money','余额')->min(0);
  98. $f[] = Form::radio('integration_status','修改积分',1)->options([['value'=>1,'label'=>'增加'],['value'=>2,'label'=>'减少']]);
  99. $f[] = Form::number('integration','积分')->min(0);
  100. $f[] = Form::radio('status','状态',$user->getData('status'))->options([['value'=>1,'label'=>'开启'],['value'=>0,'label'=>'锁定']]);
  101. $f[] = Form::radio('is_promoter','推广员',$user->getData('is_promoter'))->options([['value'=>1,'label'=>'开启'],['value'=>0,'label'=>'关闭']]);
  102. $form = Form::make_post_form('添加用户通知',$f,Url::build('update',array('id'=>$uid)),5);
  103. $this->assign(compact('form'));
  104. return $this->fetch('public/form-builder');
  105. }
  106. public function update(Request $request, $uid)
  107. {
  108. $data = Util::postMore([
  109. ['money_status',0],
  110. ['is_promoter',1],
  111. ['money',0],
  112. ['integration_status',0],
  113. ['integration',0],
  114. ['status',0],
  115. ],$request);
  116. if(!$uid) return $this->failed('数据不存在');
  117. $user = UserModel::get($uid);
  118. if(!$user) return Json::fail('数据不存在!');
  119. ModelBasic::beginTrans();
  120. $res1 = false;
  121. $res2 = false;
  122. $edit = array();
  123. if($data['money_status'] && $data['money']){//余额增加或者减少
  124. if($data['money_status'] == 1){//增加
  125. $edit['now_money'] = bcadd($user['now_money'],$data['money'],2);
  126. $res1 = UserBillAdmin::income('系统增加余额',$user['uid'],'now_money','system_add',$data['money'],$this->adminId,$edit['now_money'],'系统增加了'.floatval($data['money']).'余额');
  127. try{
  128. HookService::listen('admin_add_money',$user,$data['money'],false,UserBehavior::class);
  129. }catch (\Exception $e){
  130. ModelBasic::rollbackTrans();
  131. return Json::fail($e->getMessage());
  132. }
  133. }else if($data['money_status'] == 2){//减少
  134. $edit['now_money'] = bcsub($user['now_money'],$data['money'],2);
  135. $res1 = UserBillAdmin::expend('系统减少余额',$user['uid'],'now_money','system_sub',$data['money'],$this->adminId,$edit['now_money'],'系统扣除了'.floatval($data['money']).'余额');
  136. try{
  137. HookService::listen('admin_sub_money',$user,$data['money'],false,UserBehavior::class);
  138. }catch (\Exception $e){
  139. ModelBasic::rollbackTrans();
  140. return Json::fail($e->getMessage());
  141. }
  142. }
  143. }else{
  144. $res1 = true;
  145. }
  146. if($data['integration_status'] && $data['integration']){//积分增加或者减少
  147. if($data['integration_status'] == 1){//增加
  148. $edit['integral'] = bcadd($user['integral'],$data['integration'],2);
  149. $res2 = UserBillAdmin::income('系统增加积分',$user['uid'],'integral','system_add',$data['integration'],$this->adminId,$edit['integral'],'系统增加了'.floatval($data['integration']).'积分');
  150. try{
  151. HookService::listen('admin_add_integral',$user,$data['integration'],false,UserBehavior::class);
  152. }catch (\Exception $e){
  153. ModelBasic::rollbackTrans();
  154. return Json::fail($e->getMessage());
  155. }
  156. }else if($data['integration_status'] == 2){//减少
  157. $edit['integral'] = bcsub($user['integral'],$data['integration'],2);
  158. $res2 = UserBillAdmin::expend('系统减少积分',$user['uid'],'integral','system_sub',$data['integration'],$this->adminId,$edit['integral'],'系统扣除了'.floatval($data['integration']).'积分');
  159. try{
  160. HookService::listen('admin_sub_integral',$user,$data['integration'],false,UserBehavior::class);
  161. }catch (\Exception $e){
  162. ModelBasic::rollbackTrans();
  163. return Json::fail($e->getMessage());
  164. }
  165. }
  166. }else{
  167. $res2 = true;
  168. }
  169. $edit['status'] = $data['status'];
  170. $edit['is_promoter'] = $data['is_promoter'];
  171. if($edit) $res3 = UserModel::edit($edit,$uid);
  172. else $res3 = true;
  173. if($res1 && $res2 && $res3) $res =true;
  174. else $res = false;
  175. ModelBasic::checkTrans($res);
  176. if($res) return Json::successful('修改成功!');
  177. else return Json::fail('修改失败');
  178. }
  179. /**
  180. * 用户图表
  181. * @return mixed
  182. */
  183. public function user_analysis(){
  184. $where = Util::getMore([
  185. ['nickname',''],
  186. ['status',''],
  187. ['is_promoter',''],
  188. ['date',''],
  189. ['user_type',''],
  190. ['export',0]
  191. ],$this->request);
  192. $user_count=UserModel::consume($where,'',true);
  193. //头部信息
  194. $header=[
  195. [
  196. 'name'=>'新增用户',
  197. 'class'=>'fa-line-chart',
  198. 'value'=>$user_count,
  199. 'color'=>'red'
  200. ],
  201. [
  202. 'name'=>'用户留存',
  203. 'class'=>'fa-area-chart',
  204. 'value'=>$this->gethreaderValue(UserModel::consume($where,'',true),$where).'%',
  205. 'color'=>'lazur'
  206. ],
  207. [
  208. 'name'=>'新增用户总消费',
  209. 'class'=>'fa-bar-chart',
  210. 'value'=>'¥'.UserModel::consume($where),
  211. 'color'=>'navy'
  212. ],
  213. [
  214. 'name'=>'用户活跃度',
  215. 'class'=>'fa-pie-chart',
  216. 'value'=>$this->gethreaderValue(UserModel::consume($where,'',true)).'%',
  217. 'color'=>'yellow'
  218. ],
  219. ];
  220. $name=['新增用户','用户消费'];
  221. $dates=$this->get_user_index($where,$name);
  222. $user_index=['name'=>json_encode($name), 'date'=>json_encode($dates['time']), 'series'=>json_encode($dates['series'])];
  223. //用户浏览分析
  224. $view=StoreVisit::getVisit($where['date'],['','warning','info','danger']);
  225. $view_v1=WechatMessage::getViweList($where['date'],['','warning','info','danger']);
  226. $view=array_merge($view,$view_v1);
  227. $view_v2=[];
  228. foreach ($view as $val){
  229. $view_v2['color'][]='#'.rand(100000,339899);
  230. $view_v2['name'][]=$val['name'];
  231. $view_v2['value'][]=$val['value'];
  232. }
  233. $view=$view_v2;
  234. //消费会员排行用户分析
  235. $user_null=UserModel::getUserSpend($where['date']);
  236. //消费数据
  237. $now_number=UserModel::getUserSpend($where['date'],true);
  238. list($paren_number,$title)=UserModel::getPostNumber($where['date']);
  239. if($paren_number==0) {
  240. $rightTitle=[
  241. 'number'=>$now_number>0?$now_number:0,
  242. 'icon'=>'fa-level-up',
  243. 'title'=>$title
  244. ];
  245. }else{
  246. $number=(float)bcsub($now_number,$paren_number,4);
  247. if($now_number==0){
  248. $icon='fa-level-down';
  249. }else{
  250. $icon=$now_number>$paren_number?'fa-level-up':'fa-level-down';
  251. }
  252. $rightTitle=['number'=>$number, 'icon'=>$icon, 'title'=>$title];
  253. }
  254. unset($title,$paren_number,$now_number);
  255. list($paren_user_count,$title)=UserModel::getPostNumber($where['date'],true,'add_time','');
  256. if($paren_user_count==0){
  257. $count=$user_count==0?0:$user_count;
  258. $icon=$user_count==0?'fa-level-down':'fa-level-up';
  259. }else{
  260. $count=(float)bcsub($user_count,$paren_user_count,4);
  261. $icon=$user_count<$paren_user_count?'fa-level-down':'fa-level-up';
  262. }
  263. $leftTitle=[
  264. 'count'=>$count,
  265. 'icon'=>$icon,
  266. 'title'=>$title
  267. ];
  268. unset($count,$icon,$title);
  269. $consume=[
  270. 'title'=>'消费金额为¥'.UserModel::consume($where),
  271. 'series'=>UserModel::consume($where,'xiaofei'),
  272. 'rightTitle'=>$rightTitle,
  273. 'leftTitle'=>$leftTitle,
  274. ];
  275. $form=UserModel::consume($where,'form');
  276. $grouping=UserModel::consume($where,'grouping');
  277. $this->assign(compact('header','user_index','view','user_null','consume','form','grouping','where'));
  278. return $this->fetch();
  279. }
  280. public function gethreaderValue($chart,$where=[]){
  281. if($where){
  282. switch($where['date']){
  283. case null:case 'today':case 'week':case 'year':
  284. if($where['date']==null){
  285. $where['date']='month';
  286. }
  287. $sum_user=UserModel::whereTime('add_time',$where['date'])->count();
  288. if($sum_user==0) return 0;
  289. $counts=bcdiv($chart,$sum_user,4)*100;
  290. return $counts;
  291. break;
  292. case 'quarter':
  293. $quarter=UserModel::getMonth('n');
  294. $quarter[0]=strtotime($quarter[0]);
  295. $quarter[1]=strtotime($quarter[1]);
  296. $sum_user=UserModel::where('add_time','between',$quarter)->count();
  297. if($sum_user==0) return 0;
  298. $counts=bcdiv($chart,$sum_user,4)*100;
  299. return $counts;
  300. default:
  301. //自定义时间
  302. $quarter=explode('-',$where['date']);
  303. $quarter[0]=strtotime($quarter[0]);
  304. $quarter[1]=strtotime($quarter[1]);
  305. $sum_user=UserModel::where('add_time','between',$quarter)->count();
  306. if($sum_user==0) return 0;
  307. $counts=bcdiv($chart,$sum_user,4)*100;
  308. return $counts;
  309. break;
  310. }
  311. }else{
  312. $num=UserModel::count();
  313. $chart=$num!=0?bcdiv($chart,$num,5)*100:0;
  314. return $chart;
  315. }
  316. }
  317. public function get_user_index($where,$name){
  318. switch ($where['date']){
  319. case null:
  320. $days = date("t",strtotime(date('Y-m',time())));
  321. $dates=[];
  322. $series=[];
  323. $times_list=[];
  324. foreach ($name as $key=>$val){
  325. for($i=1;$i<=$days;$i++){
  326. if(!in_array($i.'号',$times_list)){
  327. array_push($times_list,$i.'号');
  328. }
  329. $time=$this->gettime(date("Y-m",time()).'-'.$i);
  330. if($key==0){
  331. $dates['data'][]=UserModel::where('add_time','between',$time)->count();
  332. }else if($key==1){
  333. $dates['data'][]=UserModel::consume(true,$time);
  334. }
  335. }
  336. $dates['name']=$val;
  337. $dates['type']='line';
  338. $series[]=$dates;
  339. unset($dates);
  340. }
  341. return ['time'=>$times_list,'series'=>$series];
  342. case 'today':
  343. $dates=[];
  344. $series=[];
  345. $times_list=[];
  346. foreach ($name as $key=>$val){
  347. for($i=0;$i<=24;$i++){
  348. $strtitle=$i.'点';
  349. if(!in_array($strtitle,$times_list)){
  350. array_push($times_list,$strtitle);
  351. }
  352. $time=$this->gettime(date("Y-m-d ",time()).$i);
  353. if($key==0){
  354. $dates['data'][]=UserModel::where('add_time','between',$time)->count();
  355. }else if($key==1){
  356. $dates['data'][]=UserModel::consume(true,$time);
  357. }
  358. }
  359. $dates['name']=$val;
  360. $dates['type']='line';
  361. $series[]=$dates;
  362. unset($dates);
  363. }
  364. return ['time'=>$times_list,'series'=>$series];
  365. case "week":
  366. $dates=[];
  367. $series=[];
  368. $times_list=[];
  369. foreach ($name as $key=>$val){
  370. for($i=0;$i<=6;$i++){
  371. if(!in_array('星期'.($i+1),$times_list)){
  372. array_push($times_list,'星期'.($i+1));
  373. }
  374. $time=UserModel::getMonth('h',$i);
  375. if($key==0){
  376. $dates['data'][]=UserModel::where('add_time','between',[strtotime($time[0]),strtotime($time[1])])->count();
  377. }else if($key==1){
  378. $dates['data'][]=UserModel::consume(true,[strtotime($time[0]),strtotime($time[1])]);
  379. }
  380. }
  381. $dates['name']=$val;
  382. $dates['type']='line';
  383. $series[]=$dates;
  384. unset($dates);
  385. }
  386. return ['time'=>$times_list,'series'=>$series];
  387. case 'year':
  388. $dates=[];
  389. $series=[];
  390. $times_list=[];
  391. $year=date('Y');
  392. foreach ($name as $key=>$val){
  393. for($i=1;$i<=12;$i++){
  394. if(!in_array($i.'月',$times_list)){
  395. array_push($times_list,$i.'月');
  396. }
  397. $t = strtotime($year.'-'.$i.'-01');
  398. $arr= explode('/',date('Y-m-01',$t).'/'.date('Y-m-',$t).date('t',$t));
  399. if($key==0){
  400. $dates['data'][]=UserModel::where('add_time','between',[strtotime($arr[0]),strtotime($arr[1])])->count();
  401. }else if($key==1){
  402. $dates['data'][]=UserModel::consume(true,[strtotime($arr[0]),strtotime($arr[1])]);
  403. }
  404. }
  405. $dates['name']=$val;
  406. $dates['type']='line';
  407. $series[]=$dates;
  408. unset($dates);
  409. }
  410. return ['time'=>$times_list,'series'=>$series];
  411. case 'quarter':
  412. $dates=[];
  413. $series=[];
  414. $times_list=[];
  415. foreach ($name as $key=>$val){
  416. for($i=1;$i<=4;$i++){
  417. $arr=$this->gettime('quarter',$i);
  418. if(!in_array(implode('--',$arr).'季度',$times_list)){
  419. array_push($times_list,implode('--',$arr).'季度');
  420. }
  421. if($key==0){
  422. $dates['data'][]=UserModel::where('add_time','between',[strtotime($arr[0]),strtotime($arr[1])])->count();
  423. }else if($key==1){
  424. $dates['data'][]=UserModel::consume(true,[strtotime($arr[0]),strtotime($arr[1])]);
  425. }
  426. }
  427. $dates['name']=$val;
  428. $dates['type']='line';
  429. $series[]=$dates;
  430. unset($dates);
  431. }
  432. return ['time'=>$times_list,'series'=>$series];
  433. default:
  434. $list=UserModel::consume($where,'default');
  435. $dates=[];
  436. $series=[];
  437. $times_list=[];
  438. foreach ($name as $k=>$v){
  439. foreach ($list as $val){
  440. $date=$val['add_time'];
  441. if(!in_array($date,$times_list)){
  442. array_push($times_list,$date);
  443. }
  444. if($k==0){
  445. $dates['data'][]=$val['num'];
  446. }else if($k==1){
  447. $dates['data'][]=UserBillAdmin::where(['uid'=>$val['uid'],'type'=>'pay_product'])->sum('number');
  448. }
  449. }
  450. $dates['name']=$v;
  451. $dates['type']='line';
  452. $series[]=$dates;
  453. unset($dates);
  454. }
  455. return ['time'=>$times_list,'series'=>$series];
  456. }
  457. }
  458. public function gettime($time='',$season=''){
  459. if(!empty($time) && empty($season)){
  460. $timestamp0 = strtotime($time);
  461. $timestamp24 =strtotime($time)+86400;
  462. return [$timestamp0,$timestamp24];
  463. }else if(!empty($time) && !empty($season)){
  464. $firstday=date('Y-m-01',mktime(0,0,0,($season - 1) *3 +1,1,date('Y')));
  465. $lastday=date('Y-m-t',mktime(0,0,0,$season * 3,1,date('Y')));
  466. return [$firstday,$lastday];
  467. }
  468. }
  469. /**
  470. * 会员等级首页
  471. */
  472. public function group(){
  473. return $this->fetch();
  474. }
  475. /**
  476. * 会员详情
  477. */
  478. public function see($uid=''){
  479. $this->assign([
  480. 'uid'=>$uid,
  481. 'userinfo'=>UserModel::getUserDetailed($uid),
  482. 'is_layui'=>true,
  483. 'headerList'=>UserModel::getHeaderList($uid),
  484. 'count'=>UserModel::getCountInfo($uid),
  485. ]);
  486. return $this->fetch();
  487. }
  488. /*
  489. * 获取某个用户的推广下线
  490. * */
  491. public function getSpreadList($uid,$page=1,$limit=20){
  492. return Json::successful(UserModel::getSpreadList($uid,(int)$page,(int)$limit));
  493. }
  494. /**
  495. * 获取某用户的订单列表
  496. */
  497. public function getOneorderList($uid,$page=1,$limit=20){
  498. return Json::successful(StoreOrder::getOneorderList(compact('uid','page','limit')));
  499. }
  500. /**
  501. * 获取某用户的积分列表
  502. */
  503. public function getOneIntegralList($uid,$page=1,$limit=20){
  504. return Json::successful(UserBillAdmin::getOneIntegralList(compact('uid','page','limit')));
  505. }
  506. /**
  507. * 获取某用户的积分列表
  508. */
  509. public function getOneSignList($uid,$page=1,$limit=20){
  510. return Json::successful(UserBillAdmin::getOneSignList(compact('uid','page','limit')));
  511. }
  512. /**
  513. * 获取某用户的持有优惠劵
  514. */
  515. public function getOneCouponsList($uid,$page=1,$limit=20){
  516. return Json::successful(StoreCouponUser::getOneCouponsList(compact('uid','page','limit')));
  517. }
  518. /**
  519. * 获取某用户的余额变动记录
  520. */
  521. public function getOneBalanceChangList($uid,$page=1,$limit=20){
  522. return Json::successful(UserBillAdmin::getOneBalanceChangList(compact('uid','page','limit')));
  523. }
  524. }