From d98ac8f1468789e4c796602bca146939e5c13d6f Mon Sep 17 00:00:00 2001 From: commie Date: Sat, 4 Apr 2026 08:52:59 +0800 Subject: [PATCH] 20 --- .gitignore | 1 + .user.ini | 2 +- app/api/controller/AlbumController.php | 96 ++ app/api/controller/CollectionController.php | 13 + app/api/controller/CommonController.php | 74 +- app/api/controller/GalleryController.php | 120 ++ app/api/controller/GroupController.php | 4 +- app/api/controller/MomentsController.php | 9 +- app/api/controller/PassportController.php | 189 +++ app/api/controller/TeamController.php | 3 +- app/api/controller/UserController.php | 36 +- app/command/User.php | 37 +- app/event/User.php | 48 +- app/functions.php | 6 +- app/model/Album.php | 36 +- app/model/BalanceLog.php | 2 +- app/model/Gallery.php | 63 + app/view/common/register.html | 624 ++++++++- app/view/common/register.html.bak | 1182 +++++++++++++++++ imconfig | 1 - .../app/controller/AccountController.php | 42 +- plugin/admin/app/controller/Crud.php | 25 +- .../admin/app/controller/IndexController.php | 51 +- plugin/admin/app/middleware/Config.php | 1 + plugin/admin/app/view/account/login.html | 24 +- plugin/admin/app/view/index/dashboard.html | 84 +- plugin/admin/public/js/index.js | 96 +- plugin/admin/public/js/user.js | 6 +- readme.md | 8 + support/Jwt.php | 2 +- support/OpenImSdk/Api/Auth.php | 3 +- support/OpenImSdk/Api/Friend.php | 2 +- support/OpenImSdk/Core/Utils.php | 3 + 33 files changed, 2565 insertions(+), 328 deletions(-) create mode 100644 app/api/controller/AlbumController.php create mode 100644 app/api/controller/GalleryController.php create mode 100644 app/api/controller/PassportController.php create mode 100644 app/model/Gallery.php create mode 100644 app/view/common/register.html.bak delete mode 120000 imconfig diff --git a/.gitignore b/.gitignore index 7e13f14..a1e21c3 100755 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ app/command/Test.php runtime vendor public/shunliao.apk +.user.ini diff --git a/.user.ini b/.user.ini index fe396d1..74e64bd 100644 --- a/.user.ini +++ b/.user.ini @@ -1 +1 @@ -open_basedir=/www/wwwroot/admin/:/tmp/ \ No newline at end of file +open_basedir=/www/wwwroot/im/admin/:/tmp/ \ No newline at end of file diff --git a/app/api/controller/AlbumController.php b/app/api/controller/AlbumController.php new file mode 100644 index 0000000..d9789d4 --- /dev/null +++ b/app/api/controller/AlbumController.php @@ -0,0 +1,96 @@ +post('limit',10); + $offset = $request->post('offset',0); + $group_id = $request->post('groupID') ?:$request->post('group_id'); + //$ls = $this->get_user_in_group($group_id); + $query = AlbumModel::where('group_id',$group_id) + ->order('id','desc'); + if($offset){ + $list = $query->where('id','<',$offset)->limit($offset,$limit); + }else{ + $list = $query->paginate($limit); + } + return $this->success('ok',$list); + } + /** + * @Apidoc\Title("创建相册") + * @Apidoc\Method("POST") + * @Apidoc\Param("groupID", type="string", require=true, desc="群ID") + * @Apidoc\Param("title", type="string", require=true, desc="标题") + * @Apidoc\Param("image", type="int", require=false, desc="封面ID") + */ + function create(Request $request): Response + { + $user_id = \support\Jwt\JwtToken::getCurrentId(); + $data = [ + 'user_id' => $user_id, + 'group_id' => $request->post('groupID'), + 'title' => input('title'), + 'image' => input('image'), + ]; + $result = AlbumModel::create($data); + return $this->success('ok',$result); + } + /** + * @Apidoc\Title("更新") + * @Apidoc\Method("POST") + * @Apidoc\Param("id", type="string", require=true, desc="ID") + * @Apidoc\Param("title", type="string", require=true, desc="标题") + * @Apidoc\Param("image", type="int", require=false, desc="封面ID") + */ + function update(Request $request): Response + { + $id = $request->input('id'); + $image = $request->input('image'); + $title = $request->input('title'); + $album = AlbumModel::find($id); + if($title){ + $album->title = $title; + } + if($image){ + $album->image = $image; + } + $album->save(); + return $this->success('ok',$album); + } + /** + * @Apidoc\Title("删除") + * @Apidoc\Method("POST") + * @Apidoc\Param("id", type="string", require=true, desc="ID") + */ + function delete(Request $request): Response + { + $id = Input('id'); + $album = AlbumModel::whereIn('id',condition: $id)->find(); + $album->delete(); + + return $this->success('ok'); + } +} diff --git a/app/api/controller/CollectionController.php b/app/api/controller/CollectionController.php index 46c827a..540e7bd 100644 --- a/app/api/controller/CollectionController.php +++ b/app/api/controller/CollectionController.php @@ -90,4 +90,17 @@ class CollectionController extends BaseController{ return $this->success('发布成功', ['collection' => $collection]); } + /** + * 删除收藏 + * @Apidoc\Param("id", type="int",require=true, desc="收藏id") + * @param Request $request + * @return Response + */ + function delete(Request $request): Response + { + $user = \support\Jwt::getUser(); + $id = $request->post('id'); + CollectionModel::where('id',$id)->where('user_id',$user->id)->delete(); + return $this->success('删除成功'); + } } \ No newline at end of file diff --git a/app/api/controller/CommonController.php b/app/api/controller/CommonController.php index 3a84c4e..08269cc 100755 --- a/app/api/controller/CommonController.php +++ b/app/api/controller/CommonController.php @@ -56,6 +56,33 @@ class CommonController extends BaseController{ $config['recharge_status_list'] = \app\enum\RechargeStatus::toArray(); $config['withdrawl_status_list'] = \app\enum\WithdrawlStatus::toArray(); $config['server_status_list'] = \app\enum\ServerStatus::toArray(); + $config['see_point_awards'] = [ + [ + 'name'=>'S1', + 'award'=>0.05, + 'total'=>50, + ], + [ + 'name'=>'S2', + 'award'=>0.1, + 'total'=>100, + ], + [ + 'name'=>'S3', + 'award'=>0.15, + 'total'=>1000, + ], + [ + 'name'=>'S4', + 'award'=>0.2, + 'total'=>5000, + ], + [ + 'name'=>'S5', + 'award'=>0.25, + 'total'=>20000, + ] + ]; //$config['getFriendList'] = $request->IM->friend->getFriendList('100006'); return $this->success(__('successful'), $config); } @@ -97,7 +124,9 @@ class CommonController extends BaseController{ * 注册会员 * * @Apidoc\Method ("POST") + * @Apidoc\Param("type", type="string",require=true, desc="注册方式:email,mobile") * @Apidoc\Param("email", type="string",require=true, desc="邮箱") + * @Apidoc\Param("mobile", type="string",require=true, desc="手机号码") * @Apidoc\Param("password", type="string",require=true, desc="密码") * @Apidoc\Param("trade_password", type="string",require=true, desc="交易密码") * @Apidoc\Param("invite_code", type="string",require=true, desc="推荐码") @@ -121,7 +150,7 @@ class CommonController extends BaseController{ } $username = $email; unset($mobile); - //captcha_verfiy('email','register',$email,false); + captcha_verfiy('email','register',$email,false); } if ($type == 'mobile') { if(!$mobile || !Validate::regex($mobile, "^1\d{10}$")){ @@ -129,10 +158,10 @@ class CommonController extends BaseController{ } $username = $mobile; unset($email); - //captcha_verfiy('mobile','register',$mobile,false); + captcha_verfiy('mobile','register',$mobile,false); } if ($type == 'username') { - if(!$email || !Validate::is($email, "email")){ + if(!$username){ return $this->error(__('Username is incorrect')); } } @@ -151,9 +180,18 @@ class CommonController extends BaseController{ 'role_id' => 1, 'group_id' => 0, 'region' => '86', - 'nickname' => input('nickname','用户_'.substr($username,7)), + 'nickname' => input('nickname'), 'avatar' => '/static/avatar/'.rand(0,17).'.png', ]; + if(empty($extends['nickname'])){ + if($type == 'mobile'){ + $extends['nickname'] = '用户_'.substr($username,7); + }else if($type == 'email'){ + $extends['nickname'] = '用户_'.substr(explode('@',$username)[0],7); + }else{ + $extends['nickname'] = $username; + } + } if ($invite_code) { if(strlen($invite_code) == 12){ //系统生产的一次性推荐吗 @@ -203,10 +241,12 @@ class CommonController extends BaseController{ * 登录 * @Apidoc\Method("POST") * @Apidoc\Param("username", type="string",require=false, desc="用户名登录必填") + * @Apidoc\Param("email", type="string",require=false, desc="邮箱登录必填") * @Apidoc\Param("mobile", type="string",require=false, desc="手机号登录必填") * @Apidoc\Param("type", type="string",require=true,default="mobile",desc="登录方式,username,mobile,email") * @Apidoc\Param("password", type="string",require=false, desc="密码的登录必填") * @Apidoc\Param("code", type="string",require=false, desc="验证码登录必填") + * @Apidoc\Param("platform", type="string",require=false, desc="平台",default="web") * @Apidoc\Param("region", type="string",require=false,default="86", desc="区域,手机号登录必填") */ public function login(Request $request){ @@ -321,11 +361,13 @@ class CommonController extends BaseController{ * @Apidoc\Param("email", type="string",require=true, desc="邮箱") * @Apidoc\Param("newpassword", type="string",require=true, desc="新密码") * @Apidoc\Param("code", type="string",require=true, desc="邮箱验证码,event=reset_trade_pwd") + * @Apidoc\Param("verify_type", type="string",require=true, desc="验证方式,email,mobile") */ public function reset_trade_pwd() { $email = input("email"); $mobile = input("mobile"); + $verify_type = input("verify_type"); $newpassword = input("newpassword"); if (!$newpassword) { return $this->error(__('Invalid parameters')); @@ -334,7 +376,6 @@ class CommonController extends BaseController{ if (!Validate::check(['newpassword' => $newpassword], ['newpassword' => 'require|regex:\S{6,32}'])) { return $this->error(__('Trade password must be 6-32 characters')); } - if (!$mobile && !$email){ try{ $user = \support\Jwt::getUser(); @@ -342,7 +383,14 @@ class CommonController extends BaseController{ $user = false; } if($user){ - captcha_verfiy('mobile','reset_trade_pwd',$user->mobile); + + if($verify_type == 'email'){ + captcha_verfiy('email','reset_trade_pwd',$user->email); + }else if($verify_type == 'mobile'){ + captcha_verfiy('mobile','reset_trade_pwd',$user->mobile); + }else{ + return $this->error(__('Unknown verify type')); + } } }else{ if ($mobile && Validate::regex($mobile, "^1\d{10}$")) { @@ -402,12 +450,13 @@ class CommonController extends BaseController{ $list[$code] = time(); cache($key,$list); cache('exp_'.$key,time()); - // addJob([ - // 'email' => $email, - // 'title' => __("Mt email code"), - // 'event' => $event, - // 'code' => $code - // ],'Email'); + addJob([ + 'email' => $email, + 'title' => __(Config('site.name').' 验证码'), + 'event' => $event, + 'code' => $code + ],'Email'); + \support\Log::channel('mail')->alert("邮件验证码:".$code.',邮箱:'.$email); return $this->success(__('Email sent successfully'),[ 'code'=> $debug ? $code : '' ]); @@ -443,6 +492,7 @@ class CommonController extends BaseController{ 'event' => $event, 'code' => $code ],'Sms'); + \support\Log::channel('mail')->alert("短信验证码:".$code.',手机号:'.$mobile); return $this->success(__('SMS sent successfully'),[ 'code'=> $debug ? $code : '' ]); diff --git a/app/api/controller/GalleryController.php b/app/api/controller/GalleryController.php new file mode 100644 index 0000000..d1ffaed --- /dev/null +++ b/app/api/controller/GalleryController.php @@ -0,0 +1,120 @@ +post('limit',10); + $offset = $request->post('offset',0); + $album_id = $request->post('album_id') ?: 0; + //$ls = $this->get_user_in_group($group_id); + $query = GalleryModel::where('album_id',$album_id)->order('id','desc'); + if($offset){ + $list = $query->where('id','<',$offset)->limit(0,$limit); + }else{ + $list = $query->paginate($limit); + } + return $this->success('ok',$list); + } + /** + * @Apidoc\Title("上传") + * @Apidoc\Method("POST") + * @Apidoc\Param("album_id", type="string", require=true, desc="相册ID",default=0) + * @Apidoc\Param("title", type="string", require=true, desc="标题") + * @Apidoc\Param("url", type="string", require=true, desc="图片") + * @Apidoc\Param("file", type="file", require=true, desc="图片,没有url得时候必传") + */ + function create(Request $request): Response + { + $user_id = \support\Jwt\JwtToken::getCurrentId(); + $res = $this->_upload($request); + if(is_string($res)){ + return $this->fail( $res); + } + $album_id = $request->post('album_id') ?: 0; + $album = AlbumModel::find($album_id); + if(!$album){ + return $this->fail('相册不存在'); + } + $insert_data = []; + foreach($res as $item){ + $insert_data[] = [ + 'user_id' => $user_id, + 'group_id' => $album->group_id, + 'album_id' => $album_id, + 'title' => $item['origin_name'], + 'url' => $item['file_name'], + ]; + } + $result = GalleryModel::saveAll($insert_data); + return $this->success('ok',$result[0]); + } + /** + * @Apidoc\Title("更新") + * @Apidoc\Method("POST") + * @Apidoc\Param("id", type="string", require=true, desc="ID") + * @Apidoc\Param("title", type="string", require=true, desc="标题") + * @Apidoc\Param("url", type="string", require=true, desc="图片") + */ + function update(Request $request): Response + { + $id = $request->input('id'); + $title = $request->input('title'); + $url = $request->input('url'); + $album = GalleryModel::find($id); + if($album){ + if($title){ + $album->title = $title; + } + if($url){ + $album->url = $url; + } + $album->save(); + } + return $this->success('ok',$album); + } + /** + * @Apidoc\Title("删除") + * @Apidoc\Method("POST") + * @Apidoc\Param("id", type="string", require=true, desc="ID") + */ + function delete(Request $request): Response + { + $ids = Input('ids'); + GalleryModel::whereIn('id',condition: $ids)->delete(); + return $this->success('ok'); + } + /** + * 获取在群里的角色 + * @Apidoc\NotParse() + * @Apidoc\NotDebug() + */ + private function get_user_in_group($group_id='',$user_id='') + { + $list = request()->IM->group->getGroupMemberList($group_id,$user_id); + return $list; + } +} diff --git a/app/api/controller/GroupController.php b/app/api/controller/GroupController.php index 81e1b26..0f4e58a 100755 --- a/app/api/controller/GroupController.php +++ b/app/api/controller/GroupController.php @@ -6,7 +6,7 @@ use support\Request; use support\Response; use hg\apidoc\annotation as Apidoc; use app\model\User; -use app\model\Album as AlbumModel; +use app\model\Gallery as AlbumModel; /** * 群组管理 @@ -19,7 +19,7 @@ class GroupController extends BaseController * @Apidoc\Title("群相片列表") * @Apidoc\Method("POST") * @Apidoc\Param("group_id", type="string", require=true, desc="群ID") - * @Apidoc\Param("page", type="int", require=true, desc="页码",default=1) + * @Apidoc\Param("offset", type="int", require=true, desc="偏移量",default=99999999999999) * @Apidoc\Param("limit", type="int", require=true, desc="分页大小",default=10) */ function album_list(Request $request): Response diff --git a/app/api/controller/MomentsController.php b/app/api/controller/MomentsController.php index 6bc7243..fc7a5f5 100644 --- a/app/api/controller/MomentsController.php +++ b/app/api/controller/MomentsController.php @@ -401,6 +401,12 @@ class MomentsController extends BaseController{ $result[] = \support\Encrypt::userIDDecode($userID); return $result; } + /** + * 删除朋友圈 + * @Apidoc\Method("POST") + * @Apidoc\Param("id", type="int",require=true, desc="朋友圈动态ID") + * @return Response + */ function delete(Request $request): Response{ $id = $request->post('id'); $user = \support\Jwt::getUser(); @@ -422,7 +428,8 @@ class MomentsController extends BaseController{ } /** * 设置朋友圈背景 - * @param Request $request + * @Apidoc\Method("POST") + * @Apidoc\Param("file", type="File",require=true, desc="文件") * @return Response */ function setBanner(Request $request){ diff --git a/app/api/controller/PassportController.php b/app/api/controller/PassportController.php new file mode 100644 index 0000000..52ee3ef --- /dev/null +++ b/app/api/controller/PassportController.php @@ -0,0 +1,189 @@ +mobile); + }else if($verify_type == 'email'){ + captcha_verfiy('email', 'verify', $user->email); + }else{ + return $this->error(__('Invalid verify type')); + } + return $this->success(__('Security verify successfully')); + } + /** + * 绑定手机号 + * @Apidoc\Method("POST") + * @Apidoc\Param("region", type="string", require=true, desc="区域代码") + * @Apidoc\Param("mobile", type="string", require=true, desc="手机号") + * @Apidoc\Param("code", type="string", require=true, desc="验证码,event=bind_mobile") + */ + public function bind_mobile() + { + $user = \support\Jwt::getUser(); + $mobile = input('mobile'); + $region = input('region'); + + // 验证手机号格式 + if (!$mobile || !Validate::regex($mobile, "^1\d{10}$")) { + return $this->error(__('Incorrect mobile number format')); + } + + // 验证手机号唯一性 + if (UserModel::where('mobile', $mobile)->where('region',$region)->where('id', '<>', $user->id)->find()) { + return $this->error(__('Mobile number already exists')); + } + + // 验证验证码 + captcha_verfiy('mobile', 'bind_mobile', $mobile); + + // 更新用户信息 + $user->mobile = $mobile; + $user->region = $region; + //$user->mobile_verify = 1; + $user->save(); + + return $this->success(__('Mobile number bound successfully')); + } + + /** + * 绑定邮箱 + * @Apidoc\Method("POST") + * @Apidoc\Param("email", type="string", require=true, desc="邮箱") + * @Apidoc\Param("code", type="string", require=true, desc="验证码,event=bind_email") + */ + public function bind_email() + { + $user = \support\Jwt::getUser(); + $email = input('email'); + // 验证邮箱格式 + if (!$email || !Validate::email($email)) { + return $this->error(__('Incorrect email format')); + } + + // 验证邮箱唯一性 + if (UserModel::where('email', $email)->where('id', '<>', $user->id)->find()) { + return $this->error(__('Email already exists')); + } + captcha_verfiy('email', 'bind_email', $email); + + + // 更新用户信息 + $user->email = $email; + //$user->email_verify = 1; + $user->save(); + + return $this->success(__('Email bound successfully')); + } + + /** + * 绑定用户名 + * @Apidoc\Method("POST") + * @Apidoc\Param("username", type="string", require=true, desc="用户名") + * @Apidoc\Param("verify_type", type="string", require=true, desc="验证类型,email或mobile") + * @Apidoc\Param("code", type="string", require=true, desc="验证码,event=bind_username") + */ + public function bind_username() + { + $user = \support\Jwt::getUser(); + $username = input('username'); + $verify_type = input('verify_type'); + + // 验证用户名格式 + if (!$username || strlen($username) < 3 || strlen($username) > 20) { + return $this->error(__('Username length must be between 3 and 20 characters')); + } + + // 验证用户名唯一性 + if (UserModel::where('username', $username)->where('id', '<>', $user->id)->find()) { + return $this->error(__('Username already exists')); + } + + if($verify_type == 'mobile'){ + captcha_verfiy('mobile', 'bind_username', $user->mobile); + }else if($verify_type == 'email'){ + captcha_verfiy('email', 'bind_username', $user->email); + } + + // 更新用户信息 + $user->username = $username; + $user->save(); + + return $this->success(__('Username bound successfully')); + } + + /** + * 解绑手机号 + * @Apidoc\Method("POST") + * @Apidoc\Param("code", type="string", require=true, desc="验证码,event=unbind_mobile") + */ + public function unbind_mobile() + { + $user = \support\Jwt::getUser(); + + if (!$user->mobile) { + return $this->error(__('Mobile number not bound')); + } + + // 验证验证码 + captcha_verfiy('mobile', 'unbind_mobile', $user->mobile); + + // 更新用户信息 + $user->mobile = ''; + $user->mobile_verify = 0; + $user->save(); + + return $this->success(__('Mobile number unbound successfully')); + } + + /** + * 解绑邮箱 + * @Apidoc\Method("POST") + * @Apidoc\Param("code", type="string", require=true, desc="验证码,event=unbind_email") + */ + public function unbind_email() + { + $user = \support\Jwt::getUser(); + + if (!$user->email) { + return $this->error(__('Email not bound')); + } + + // 验证验证码 + captcha_verfiy('email', 'unbind_email', $user->email); + + // 更新用户信息 + $user->email = ''; + $user->email_verify = 0; + $user->save(); + + return $this->success(__('Email unbound successfully')); + } + +} \ No newline at end of file diff --git a/app/api/controller/TeamController.php b/app/api/controller/TeamController.php index 17fb15d..3f41dfd 100755 --- a/app/api/controller/TeamController.php +++ b/app/api/controller/TeamController.php @@ -47,8 +47,7 @@ class TeamController extends BaseController{ // 'user_sales_reward' => cache('user_sales_reward_'.$user_id)??0,//销售奖 // 'user_output_reward' => cache('user_output_reward_'.$user_id)??0,//产值奖 // 'user_withdrawl_reward' => cache('user_withdrawl_reward'.$user_id)??0,//提现奖 - 'user' => $user[0], - + 'user' => $user[0] ]; return $this->success(__('successful'),$result); diff --git a/app/api/controller/UserController.php b/app/api/controller/UserController.php index a38566c..2c9a1b7 100755 --- a/app/api/controller/UserController.php +++ b/app/api/controller/UserController.php @@ -95,20 +95,46 @@ class UserController extends BaseController{ * @Apidoc\Param("password", type="string",require=true, desc="旧密码(新设时可用为空)") * @Apidoc\Param("newpassword", type="string",require=true, desc="新密码") * @Apidoc\Param("renewpassword", type="string",require=true, desc="新密码") + * @Apidoc\Param("code", type="string",require=true, desc="验证码") + * @Apidoc\Param("verify_type", type="string",require=true, desc="验证方式,email,mobile,password") */ public function change_trade_password(){ + $user = \support\Jwt::getUser(); $password = input('password'); $newpassword = input('newpassword'); $renewpassword = input('renewpassword'); + $verify_type = input('verify_type'); if (!$newpassword || !$renewpassword || $newpassword !== $renewpassword) { return $this->error(__('Invalid parameters')); } - try{ - \support\Jwt::change_trade_pwd($newpassword,$password); - return $this->success(__('Reset trade password successful')); - } catch (\Throwable $e) { - return $this->error($e->getMessage()); + if($verify_type == 'email'){ + captcha_verfiy('email','reset_trade_pwd',$user->email); + try{ + \support\Jwt::change_trade_pwd($newpassword,'',true); + return $this->success(__('Reset trade password successful')); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + }else if($verify_type == 'mobile'){ + captcha_verfiy('mobile','reset_trade_pwd',$user->mobile); + try{ + \support\Jwt::change_trade_pwd($newpassword,'',true); + return $this->success(__('Reset trade password successful')); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + }else if($verify_type == 'password'){ + if (!$password) { + return $this->error(__('Invalid parameters')); + } + try{ + \support\Jwt::change_trade_pwd($newpassword,$password); + return $this->success(__('Reset trade password successful')); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } } + } /** * 根据关键字查询用户列表 diff --git a/app/command/User.php b/app/command/User.php index 1ab792a..bc63f77 100755 --- a/app/command/User.php +++ b/app/command/User.php @@ -21,8 +21,8 @@ class User extends Command */ protected function configure() { - $this->addOption('user_id','u', InputArgument::OPTIONAL, 'user_id'); - $this->addOption('action','a', InputArgument::OPTIONAL, '操作类型'); + $this->addOption('user_id','u', InputOption::VALUE_OPTIONAL, 'user_id'); + $this->addOption('action','a', InputOption::VALUE_OPTIONAL, '操作类型','test'); } /** @@ -38,7 +38,28 @@ class User extends Command } cp('操作不存在:'.$action); return 0; + } + function test(InputInterface $input, OutputInterface $output) + { + $user_id = 104864; + $_user = Db::name('user')->where('id',$user_id)->find(); + Db::query('delete FROM `wa_user_team` WHERE descendant_id='.$user_id.' or ancestor_id='.$user_id.';'); + Hook('user.register_successed',$_user); + //管理团队人数 + // $team_user_ids = Db::name('user_team')->where('descendant_id',$_user['id']) + // ->where('depth','>',0) + // ->order('depth','ASC') + // ->column('ancestor_id'); + // Db::name('user_extend')->whereIn('user_id',$team_user_ids)->data([ + // 'team_total'=> Db::raw('team_total+1') + // ])->save(); + // $list = Db::name('user_extend')->whereIn('user_id',$team_user_ids)->field('user_id,team_total')->select(); + // foreach($list as $v){ + // cache('team_user_count_'.$v['user_id'],$v['team_total']); + // } + // cp($team_user_ids); + return 0; } function login(InputInterface $input, OutputInterface $output){ // $IM = new \support\OpenImSdk\Client([ @@ -59,19 +80,20 @@ class User extends Command } function build_team(InputInterface $input, OutputInterface $output){ $list = Db::name('user')->field('id')->order('id','asc')->select(); + //$list = [['id'=>100006]]; foreach($list as $k=>$user){ //team_total - $team_user_ids = Db::name('user_team')->where('descendant_id',$user['id']) + $team_user_ids = Db::name('user_team')->where('ancestor_id',$user['id']) ->where('depth','>',0) ->order('depth','ASC') - ->column('ancestor_id'); + ->column('descendant_id'); Db::name('user_extend')->where('user_id',$user['id'])->data([ 'team_total'=> count($team_user_ids) ])->save(); cache('team_user_count_'.$user['id'],count($team_user_ids)); $direct_use_count = Db::name('user')->where('parent_id',$user['id'])->count('id'); - $vip_user_count = Db::name('user')->whereIn('id',$team_user_ids)->where('role_id','>',0)->count('id'); + $vip_user_count = Db::name('user')->whereIn('id',$team_user_ids)->where('role_id','>',1)->count('id'); Db::name('user_extend')->where('user_id',$user['id'])->data([ 'direct_total'=> $direct_use_count, @@ -80,6 +102,7 @@ class User extends Command cache('team_direct_total_'.$user['id'],$direct_use_count); cache('team_vip_total_'.$user['id'],$vip_user_count); $this->level_up($user['id'],$vip_user_count); + cp($user['id'].'完成'); } return 0; @@ -87,10 +110,10 @@ class User extends Command protected function level_up($user_id,$count=0){ $levels = [ 0, - 500, + 50, + 100, 1000, 5000, - 10000, 20000, ]; $level = 0; diff --git a/app/event/User.php b/app/event/User.php index f49fe92..ff36e3a 100755 --- a/app/event/User.php +++ b/app/event/User.php @@ -17,12 +17,23 @@ class User{ 'invite_code' => \support\Encrypt::userIDencode($_user['id']), 'userID' => \support\Encrypt::userIDencode($_user['id']) ]; + + \app\model\User::where('id',$_user['id'])->update($saveData); + //创建扩展数据 + Db::name('user_extend')->replace()->insert([ + 'user_id' => $_user['id'], + 'consume' => 0, + // 'profile_banner' => '', + // 'moments_banner' => '', + // 'moments_allow_view_days'=>0, + ]); //管理直推人数和团队人数 if($_user['parent_id']){ parent_info( $_user['id'],[ 'id' => $_user['parent_id'], 'username' => Db::name('user')->where('id',$_user['parent_id'])->value('username') ]); + $this->buildTeam($_user); //直属团队人数 Db::name('user_extend')->where('user_id',$_user['parent_id']) ->data([ @@ -31,7 +42,7 @@ class User{ cache_add('team_direct_total_'.$_user['parent_id'],1); //管理团队人数 - $team_user_ids = Db::name('user_team')->where('descendant_id',$user['id']) + $team_user_ids = Db::name('user_team')->where('descendant_id',$_user['id']) ->where('depth','>',0) ->order('depth','ASC') ->column('ancestor_id'); @@ -44,19 +55,6 @@ class User{ cache('team_user_count_'.$v['user_id'],$v['team_total']); } } - - \app\model\User::where('id',$_user['id'])->update($saveData); - //创建扩展数据 - Db::name('user_extend')->replace()->insert([ - 'user_id' => $_user['id'], - 'consume' => 0, - // 'profile_banner' => '', - // 'moments_banner' => '', - // 'moments_allow_view_days'=>0, - ]); - - - $this->buildTeam($user); } function login_successed($data=[]){ $data = $this->profile($data); @@ -71,10 +69,10 @@ class User{ protected function level_up($user_id,$count=0){ $levels = [ 0, - 500, + 50, + 100, 1000, 5000, - 10000, 20000, ]; $level = 0; @@ -100,7 +98,7 @@ class User{ 'userHeadImg' => null, ]; try { - $ff = Db::name('user_extend')->where('user_id',$user->id)->field('moments_allow_view_days,profile_banner,moments_banner')->find(); + $ff = Db::name('user_extend')->where('user_id',$user['id'])->field('moments_allow_view_days,profile_banner,moments_banner')->find(); $data['moments_allow_view_days'] = $ff['moments_allow_view_days']; $data['moments_banner'] = $ff['moments_banner']; $data['profile_banner'] = $ff['profile_banner']; @@ -170,29 +168,29 @@ class User{ // 插入自己的团队关系 (自己是自己的后代) $teamData = [ [ - 'ancestor_id' => $user->id, - 'descendant_id' => $user->id, + 'ancestor_id' => $user['id'], + 'descendant_id' => $user['id'], 'depth' => 0, 'status' => 0, ] ]; // 2. 处理团队关系(如果有推荐人) - if ($user->parent_id) { + if ($user['parent_id']) { - parent_info( $user->id,[ - 'id' => $user->parent_id, - 'username' => Db::name('user')->where('id',$user->parent_id)->value('username') + parent_info( $user['id'],[ + 'id' => $user['parent_id'], + 'username' => Db::name('user')->where('id',$user['parent_id'])->value('username') ]); // 获取推荐人所有的上级关系,生成新用户的团队关系 $ancestors = Db::name('user_team') - ->where('descendant_id', $user->parent_id) + ->where('descendant_id', $user['parent_id']) ->select(); /** @var \app\model\UserTeam $ancestor */ // 插入新用户与祖先的关系 foreach ($ancestors as $ancestor) { $teamData[] = [ 'ancestor_id' => $ancestor['ancestor_id'], - 'descendant_id' => $user->id, + 'descendant_id' => $user['id'], 'depth' => $ancestor['depth'] + 1, 'status' => 1, // 默认状态为 0,表示无效 ]; diff --git a/app/functions.php b/app/functions.php index b1a06fb..3c2bbc8 100755 --- a/app/functions.php +++ b/app/functions.php @@ -499,13 +499,13 @@ if(!function_exists('cache_get')){ if(!$ret || $force){ if (str_starts_with($key, 'team_user_total_')) { $user_id = substr($key,strlen('team_user_total_')); - $ret = \support\think\Db::name('user_extend')->where('user_id',$user_id)->column('team_total'); + $ret = \support\think\Db::name('user_extend')->where('user_id',$user_id)->value('team_total'); }else if (str_starts_with($key, 'team_direct_total_')) { $user_id = substr($key,strlen('team_direct_total_')); - $ret = \support\think\Db::name('user_extend')->where('user_id',$user_id)->column('direct_total'); + $ret = \support\think\Db::name('user_extend')->where('user_id',$user_id)->value('direct_total'); }else if (str_starts_with($key, 'team_vip_total_')) { $user_id = substr($key,strlen('team_vip_total_')); - $ret = \support\think\Db::name('user_extend')->where('user_id',$user_id)->column('vip_total'); + $ret = \support\think\Db::name('user_extend')->where('user_id',$user_id)->value('vip_total'); } cache($key,$ret); } diff --git a/app/model/Album.php b/app/model/Album.php index 5fe9be6..119d06b 100755 --- a/app/model/Album.php +++ b/app/model/Album.php @@ -5,9 +5,12 @@ namespace app\model; * 相册模型 * @property integer $id 主键(ID) * @property integer $user_id 用户ID - * @property integer $group_id 内容 - * @property string $url 图片 + * @property integer $group_id 群组ID + * @property integer $userID 用户ID + * @property integer $groupID 群组ID * @property string $title 标题 + * @property int $image 封面图片ID + * @property int $weigh 排序权重,越小越靠前 * @property integer $created_at 创建时间 * @property integer $updated_at 更新时间 * @property integer $status 状态(0:隐藏 1:正常) @@ -22,30 +25,45 @@ class Album extends Base 'insert' => [ 'status' => 1, ], + 'append'=>[ + 'userID', + 'groupID' + ] ]); } public static function onAfterInsert($row){ $changeData = $row->getChangedData(); - if(isset($changeData['url'])) { - Files::where('path',$changeData['url'])->inc('use_count'); + if(isset($changeData['image'])) { + Files::where('path',$changeData['image'])->inc('use_count'); }; } public static function onAfterUpdate($row){ $OrgData = $row->getOrigin(); $changeData = $row->getChangedData(); - if(isset($OrgData['url']) && $OrgData['url']) { + if(isset($OrgData['image']) && $OrgData['image']) { \support\Log::info('OrgData string'); - Files::where('path',$OrgData['url'])->dec('use_count'); + Files::where('path',$OrgData['image'])->dec('use_count'); }; - if(isset($changeData['url']) && $changeData['url']) { + if(isset($changeData['image']) && $changeData['image']) { \support\Log::info('changeData string'); - Files::where('path',$changeData['url'])->inc('use_count'); + Files::where('path',$changeData['image'])->inc('use_count'); }; } + public static function onBeforeDelete($row){ + if($row->total>0){ + return false; + } + } public static function onAfterDelete($row){ - Files::where('path',$row->url)->dec('use_count'); + Files::where('path',$row->image)->dec('use_count'); + } + function getGroupIDAttr($v,$row){ + return $v?:$row['group_id']; + } + function getUserIDAttr($v,$row){ + return $v?:$row['user_id']; } } diff --git a/app/model/BalanceLog.php b/app/model/BalanceLog.php index fcfc3a3..973d5e2 100755 --- a/app/model/BalanceLog.php +++ b/app/model/BalanceLog.php @@ -33,7 +33,7 @@ class BalanceLog extends Base // ], ]); } - public static function create(array|object $data, array $allowField = [], bool $replace = false):\think\model\contract\Modelable + public static function create(array|object $data, array $allowField = [], bool $replace = false, string $suffix = ''):\think\model\contract\Modelable { $model = new static(); if(isset($data['currency'])){ diff --git a/app/model/Gallery.php b/app/model/Gallery.php new file mode 100644 index 0000000..4ebbdfe --- /dev/null +++ b/app/model/Gallery.php @@ -0,0 +1,63 @@ + [ + 'status' => 1, + ], + 'append'=>[ + 'userID', + 'groupID' + ] + ]); + } + function getGroupIDAttr($v,$row){ + return $v?:$row['group_id']; + } + function getUserIDAttr($v,$row){ + return $v?:$row['user_id']; + } + public static function onAfterInsert($row){ + $changeData = $row->getChangedData(); + if(isset($changeData['url'])) { + Files::where('path',$changeData['url'])->inc('use_count'); + }; + } + + public static function onAfterUpdate($row){ + $OrgData = $row->getOrigin(); + $changeData = $row->getChangedData(); + if(isset($OrgData['url']) && $OrgData['url']) { + \support\Log::info('OrgData string'); + Files::where('path',$OrgData['url'])->dec('use_count'); + }; + if(isset($changeData['url']) && $changeData['url']) { + \support\Log::info('changeData string'); + Files::where('path',$changeData['url'])->inc('use_count'); + }; + } + + public static function onAfterDelete($row){ + Files::where('path',$row->url)->dec('use_count'); + } + +} + diff --git a/app/view/common/register.html b/app/view/common/register.html index d060180..27ecad9 100644 --- a/app/view/common/register.html +++ b/app/view/common/register.html @@ -39,7 +39,7 @@ min-height: 100vh; line-height: 1.6; padding: 20px; - _background-image: radial-gradient(at 0 0,rgba(var(--primary-rgb),0.05) 0,transparent 50%),radial-gradient(at 100% 100%,rgba(var(--secondary-rgb),0.05) 0,transparent 50%) + background-image: radial-gradient(at 0 0,rgba(39, 186, 87, 0.05) 0,transparent 50%),radial-gradient(at 100% 100%,rgba(39, 186, 87, 0.05) 0,transparent 50%) } .container { @@ -50,13 +50,17 @@ box-shadow: var(--shadow); overflow: hidden; position: relative; - z-index: 1 + z-index: 1; + transition: var(--transition); + } + + .container:hover { + box-shadow: 0 8px 32px rgba(0,0,0,0.12); } .container::before { content: ''; position: absolute; - display: none; top: 0; left: 0; width: 100%; @@ -68,7 +72,9 @@ .header { padding: 40px 40px 30px; - text-align: center + text-align: center; + position: relative; + z-index: 1; } .logo { @@ -80,7 +86,13 @@ align-items: center; justify-content: center; box-shadow: var(--shadow); - margin-bottom: 20px + margin-bottom: 20px; + transition: var(--transition); + } + + .logo:hover { + transform: scale(1.05); + box-shadow: 0 6px 20px rgba(0,0,0,0.12); } .logo svg { @@ -99,7 +111,8 @@ } .header p { - font-size: 14pt + font-size: 14pt; + color: var(--text-light); } .card { @@ -161,10 +174,29 @@ .form-control:focus { border-color: var(--primary); - box-shadow: 0 0 0 3px rgba(67,97,238,0.15); + box-shadow: 0 0 0 3px rgba(39, 186, 87, 0.15); outline: 0 } + .form-control.error { + border-color: #f56c6c; + } + + .form-control.success { + border-color: var(--primary); + } + + .error-message { + color: #f56c6c; + font-size: 12px; + margin-top: 4px; + display: none; + } + + .error-message.show { + display: block; + } + .captcha-group { display: flex; gap: 12px @@ -184,11 +216,15 @@ font-weight: 600; cursor: pointer; transition: var(--transition); - padding: 0 16px + padding: 0 16px; + display: flex; + align-items: center; + justify-content: center; } - .captcha-btn:hover { - background-color: rgba(67,97,238,0.1) + .captcha-btn:hover:not(:disabled) { + background-color: rgba(39, 186, 87, 0.1); + transform: translateY(-1px); } .captcha-btn:disabled { @@ -209,18 +245,26 @@ cursor: pointer; transition: var(--transition); margin-top: 10px; - box-shadow: 0 4px 12px rgba(67,97,238,0.2) + box-shadow: 0 4px 12px rgba(39, 186, 87, 0.2); + position: relative; + overflow: hidden; } .btn:hover { transform: translateY(-2px); - box-shadow: 0 6px 16px rgba(67,97,238,0.3) + box-shadow: 0 6px 16px rgba(39, 186, 87, 0.3) } .btn:active { transform: translateY(0) } + .btn:disabled { + opacity: 0.7; + cursor: not-allowed; + transform: none; + } + .footer { margin-top: 30px; text-align: center; @@ -239,7 +283,6 @@ text-decoration: underline } - .other-options { margin-top: 20px; text-align: center; @@ -282,6 +325,14 @@ height: 60px; border-radius: 15px; } + + .header h1 { + font-size: 20px; + } + + .header p { + font-size: 12pt; + } } /*成功卡片*/ .success-card { @@ -447,6 +498,184 @@ } } + .region .layui-select-title .layui-input{ + height: 51px; + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; + } + + /* 密码强度指示器 */ + .password-strength { + display: flex; + gap: 4px; + margin-top: 8px; + } + + .strength-bar { + flex: 1; + height: 4px; + border-radius: 2px; + background-color: var(--border); + transition: var(--transition); + } + + .strength-bar.weak { + background-color: #f56c6c; + } + + .strength-bar.medium { + background-color: #e6a23c; + } + + .strength-bar.strong { + background-color: var(--primary); + } + + .strength-text { + font-size: 12px; + color: var(--text-light); + margin-top: 4px; + } + + .strength-text.weak { + color: #f56c6c; + } + + .strength-text.medium { + color: #e6a23c; + } + + .strength-text.strong { + color: var(--primary); + } + + /* 加载动画 */ + .loading { + display: inline-block; + width: 20px; + height: 20px; + border: 2px solid rgba(255,255,255,0.3); + border-radius: 50%; + border-top-color: #fff; + animation: spin 1s ease-in-out infinite; + } + + @keyframes spin { + to { transform: rotate(360deg); } + } + + /* 输入框图标 */ + .input-icon { + position: absolute; + left: 16px; + top: 50%; + transform: translateY(-50%); + color: var(--text-light); + } + + .form-control.has-icon { + padding-left: 40px; + } + + /* 验证码按钮加载状态 */ + .captcha-btn.loading { + position: relative; + pointer-events: none; + } + + .captcha-btn.loading::after { + content: ''; + position: absolute; + width: 16px; + height: 16px; + border: 2px solid rgba(39, 186, 87, 0.3); + border-radius: 50%; + border-top-color: var(--primary); + animation: spin 1s ease-in-out infinite; + } + + /* 响应式优化 */ + @media (max-width: 768px) { + .container { + padding: 16px; + max-width: 95%; + } + + .card { + padding: 0 24px 32px; + } + + .form-group { + margin-bottom: 16px; + } + + .btn { + height: 48px; + font-size: 16px; + } + + .captcha-btn { + min-width: 100px; + font-size: 13px; + } + } + + /* 动画效果 */ + @keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } + } + + .form-container { + animation: fadeInUp 0.3s ease-out; + } + + /* 错误消息优化 */ + .error-message { + font-size: 12px; + color: #f56c6c; + margin-top: 4px; + opacity: 0; + height: 0; + overflow: hidden; + transition: var(--transition); + } + + .error-message.show { + opacity: 1; + height: auto; + min-height: 16px; + } + + /* 星星装饰优化 */ + .star { + position: absolute; + background-color: #fff; + border-radius: 50%; + animation: twinkle 3s infinite; + } + + @keyframes twinkle { + 0%, 100% { + opacity: 0.3; + } + 50% { + opacity: 1; + } + } + + /* 庆祝效果 */ + .confetti { + position: absolute; + border-radius: 2px; + } + {/literal} @@ -819,52 +1048,77 @@

欢迎回来

-

使用手机号码注册您的账户

+

使用手机号或邮箱注册您的账户

-
- -
- + +
+
+ +
+ + +
+
- +
+
- +
+
+
+
+
+
+
密码强度:弱
+
- +
+
- + +
@@ -904,15 +1158,162 @@ {literal} diff --git a/app/view/common/register.html.bak b/app/view/common/register.html.bak new file mode 100644 index 0000000..6ebbc7f --- /dev/null +++ b/app/view/common/register.html.bak @@ -0,0 +1,1182 @@ + + + + + + + 用户注册 - {$config.name} + + + {literal} + + {/literal} + + + +
+
+ +

欢迎回来

+

使用手机号或邮箱注册您的账户

+
+
+ +
+ + +
+
    +
  • 手机号注册
  • +
  • 邮箱注册
  • +
+
+
+
+ +
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+ 已有账号?立即下载APP +
+
+ +
+
+
+
+
+
+ +
+

注册成功!

+

注册成功,下载APP,马上开始您的聊天之旅吧

+ + 下载 +
+
+ + + + +{literal} + +{/literal} + \ No newline at end of file diff --git a/imconfig b/imconfig deleted file mode 120000 index cb6c10b..0000000 --- a/imconfig +++ /dev/null @@ -1 +0,0 @@ -/www/wwwroot/im/config \ No newline at end of file diff --git a/plugin/admin/app/controller/AccountController.php b/plugin/admin/app/controller/AccountController.php index 83a7927..b991570 100755 --- a/plugin/admin/app/controller/AccountController.php +++ b/plugin/admin/app/controller/AccountController.php @@ -86,6 +86,7 @@ class AccountController extends Crud $username = $request->post('username', ''); $this->removeLoginLimit($username); $password = $request->post('password', ''); + $code = $request->post('code', ''); if (!$username) { return $this->fail('用户名不能为空'); } @@ -94,26 +95,33 @@ class AccountController extends Crud * @var Admin $admin */ $admin = Admin::where('username', $username)->find(); - // if (!$admin || !Util::passwordVerify($password, $admin->password)) { - // return $this->fail('账户不存在或密码错误'); - // } - //$secret = $admin['totp_secret'] ?:'EJGYB7OZR2W46XRX7VB3PXHSOY4LUAWCA5GTDAVTWKHXNDAAAIIP7AQ3JSO3XZJNX5J5OTIDEQVKLYFYIYNAXSCYF4GNZ2EMA4ORA3Y'; - //\support\Log::alert($admin['totp_secret']); - $totp = \OTPHP\TOTP::create($admin->totp_secret); - //$secret = $totp->getSecret(); - //$totp->setLabel('cansnow'); - //$totp->setIssuer('DVPN'); - //$qrCodeUri =$totp->getProvisioningUri(); - //cp($secret); - //cp($qrCodeUri); - //cp('https://api.qrtool.cn/?text='.urlencode($qrCodeUri)); - //cp($totp->at(time())); - if (!$totp->verify($request->post('code', ''))) { - return $this->fail('当前账户暂时无法登录1'); - } if ($admin->status != 1) { return $this->fail('当前账户暂时无法登录'); } + if(!$code && !$password){ + return $this->fail('请输入验证码或密码'); + } + if($code){ + //$secret = $admin['totp_secret'] ?:'EJGYB7OZR2W46XRX7VB3PXHSOY4LUAWCA5GTDAVTWKHXNDAAAIIP7AQ3JSO3XZJNX5J5OTIDEQVKLYFYIYNAXSCYF4GNZ2EMA4ORA3Y'; + //\support\Log::alert($admin['totp_secret']); + $totp = \OTPHP\TOTP::create($admin->totp_secret); + //$secret = $totp->getSecret(); + //$totp->setLabel('cansnow'); + //$totp->setIssuer('DVPN'); + //$qrCodeUri =$totp->getProvisioningUri(); + //cp($secret); + //cp($qrCodeUri); + //cp('https://api.qrtool.cn/?text='.urlencode($qrCodeUri)); + //cp($totp->at(time())); + if (!$totp->verify($code)) { + return $this->fail('动态密码错误'); + } + } + if($password){ + if (!$admin || !Util::passwordVerify($password, $admin->password)) { + return $this->fail('账户不存在或密码错误'); + } + } $admin->login_at = time(); $admin->save(); $this->removeLoginLimit($username); diff --git a/plugin/admin/app/controller/Crud.php b/plugin/admin/app/controller/Crud.php index a1bdf9f..c3ab3d0 100755 --- a/plugin/admin/app/controller/Crud.php +++ b/plugin/admin/app/controller/Crud.php @@ -374,22 +374,15 @@ class Crud extends Base } } } - $password_filed = 'password'; - if (isset($data[$password_filed])) { - // 密码为空,则不更新密码 - if ($data[$password_filed] === '') { - unset($data[$password_filed]); - } else { - $data[$password_filed] = Util::passwordHash(md5($data[$password_filed])); - } - } - $password_filed = 'trade_password'; - if (isset($data[$password_filed])) { - // 密码为空,则不更新密码 - if ($data[$password_filed] === '') { - unset($data[$password_filed]); - } else { - $data[$password_filed] = Util::passwordHash($data[$password_filed]); + $password_fileds = ['password','trade_password','empty_password']; + foreach($password_fileds as $password_filed){ + if (isset($data[$password_filed])) { + // 密码为空,则不更新密码 + if ($data[$password_filed] === '') { + unset($data[$password_filed]); + } else { + $data[$password_filed] = Util::passwordHash(md5($data[$password_filed])); + } } } unset($data[$primary_key]); diff --git a/plugin/admin/app/controller/IndexController.php b/plugin/admin/app/controller/IndexController.php index 0f6e12b..46c857f 100755 --- a/plugin/admin/app/controller/IndexController.php +++ b/plugin/admin/app/controller/IndexController.php @@ -69,7 +69,6 @@ class IndexController extends Base } //$day7_user_recharge_sum = Recharge::where('status',2)->whereTime('created_at', '-7 days')->sum('amount'); // 总用户数 - $user_count = \app\model\User::where('status',1)->count('id'); $recharge_total = 0;//\app\model\Recharge::where('status',\app\enum\RechargeStatus::COMPLETE->value)->sum('amount'); // mysql版本 $withdrawl_total = \app\model\Withdrawl::where('status',\app\enum\WithdrawlStatus::COMPLETE->value)->sum('recive_amount'); @@ -90,7 +89,6 @@ class IndexController extends Base return view('index/dashboard', [ 'today_user_recharge_sum' => formatAmount(cache('statistics_recharge_amount_'.date('Y-m-d')),0), 'day7_user_recharge_sum' => formatAmount($day7_user_recharge_sum,0), - 'user_count' => $user_count, //'recharge' => $recharge, //'withdrawl' => $withdrawl, 'recharge_total' => formatAmount($recharge_total,0), @@ -122,39 +120,28 @@ class IndexController extends Base } return $this->success('ok',$res); } - function recharge_lines() - { + function lines_data(){ + $days = Input('days',7); + $items = Input('items',''); + $items = explode(',',$items); $res = []; - for ($i=7; $i >= 0; $i--) { + for ($i=$days; $i >= 0; $i--) { $date = date('Y-m-d',strtotime('-'.$i.' days')); - $res[$date] = [ - 'amount' => cache('statistics_recharge_amount_'.$date)?:0, - ]; + $item= []; + foreach($items as $k=>$v){ + if($v == 'withdrawl'){ + $item[$v] = cache('statistics_withdrawl_amount_'.$date)?:0; + } + if($v == 'recharge'){ + $item[$v] = cache('statistics_recharge_amount_'.$date)?:0; + } + if($v == 'register'){ + $item[$v] = cache('statistics_register_'.$date)?:0; + } + } + $res[$date] = $item; } - return $this->success('ok',$res); - } - function withdrawl_lines() - { - $res = []; - for ($i=7; $i >= 0; $i--) { - $date = date('Y-m-d',strtotime('-'.$i.' days')); - $res[$date] = [ - 'amount' => cache('statistics_withdrawl_amount_'.$date)?:0, - ]; - } - return $this->success('ok',$res); - } - function money_lines() - { - $res = []; - for ($i=7; $i >= 0; $i--) { - $date = date('Y-m-d',strtotime('-'.$i.' days')); - $res[$date] = [ - 'withdrawl' => cache('statistics_withdrawl_amount_'.$date)?:0, - 'recharge' => cache('statistics_recharge_amount_'.$date)?:0, - ]; - } - return $this->success('ok',$res); + return $this->success('ok'.$items,$res); } } diff --git a/plugin/admin/app/middleware/Config.php b/plugin/admin/app/middleware/Config.php index ae1168b..8c90781 100755 --- a/plugin/admin/app/middleware/Config.php +++ b/plugin/admin/app/middleware/Config.php @@ -28,6 +28,7 @@ class Config implements MiddlewareInterface $config['action'] = $request->action_name; $config['moduleurl'] = admin_path(); $config['admin_path'] = admin_path(); + $config['development'] = config('site.name') == '瞬聊Test'; $config['domain'] = env_get('server.domain',''); $request->_view_vars = array_merge((array) $request->_view_vars,[ 'user' => session('admin'), diff --git a/plugin/admin/app/view/account/login.html b/plugin/admin/app/view/account/login.html index f125bcc..5f9efa2 100755 --- a/plugin/admin/app/view/account/login.html +++ b/plugin/admin/app/view/account/login.html @@ -54,18 +54,28 @@ +
- -
@@ -32,8 +31,7 @@

总充值

-
+
@@ -45,8 +43,7 @@

总提现

-
+
@@ -90,28 +87,24 @@ - 渠道商数 - - count('id'); - ?> - + 用户总数 + - 用户余额总和 - {$user_money_total} + VIP用户数 + count('id');?> + + + SVIP1用户数 + count('id');?> + + + SVIP2用户数 + count('id');?> 用户积分总和 - {$user_score_total} - - - 调研币总和 - - - - 待分配总和 - + @@ -132,49 +125,24 @@ - 问卷成交个数 - - - + 操作系统 + {$os} - 预计支出泡沫 - - - + workerman + {$workerman_version} - 总沉淀金额 - - - - + webman + {$webman_version} - 实际泡沫 - - 0){ - echo ''.$cha.''; - }else{ - echo ''.$cha.''; - } - ?> - + php + {$php_version} -   - - - -   - + MySQL + {$mysql_version} diff --git a/plugin/admin/public/js/index.js b/plugin/admin/public/js/index.js index 8e15180..c66a954 100755 --- a/plugin/admin/public/js/index.js +++ b/plugin/admin/public/js/index.js @@ -83,7 +83,11 @@ define(['lightyear','multitabs', '../libs/Chart','form','bootstrap'], function ( setTheme = function (input_name, data_name) { $("input[name='" + input_name + "']").click(function () { $('body').attr(data_name, $(this).val()); + localStorage.setItem(data_name,$(this).val()); }); + if(Config.development){ + $('body').attr(data_name, localStorage.getItem(data_name) || 'color_8'); + } } setTheme('logo_bg', 'data-logobg'); setTheme('header_bg', 'data-headerbg'); @@ -167,47 +171,7 @@ define(['lightyear','multitabs', '../libs/Chart','form','bootstrap'], function ( }); }, dashboard: function () { - // new Chart( - // document.getElementsByClassName('js-chartjs-bars'), - // { - // type: 'bar', - // data: { - // labels: recharge_labels, - // datasets: [ - // { - // label: '充值统计', - // data: recharge_values, - // borderColor: '#358ed7', - // backgroundColor: 'rgba(53, 142, 215, 0.175)', - // borderWidth: 1, - // fill: false, - // lineTension: 0.5 - // }, - // ] - // } - // } - // ); - // new Chart( - // document.getElementsByClassName('js-chartjs-lines'), - // { - // type: 'bar',//line - // data: { - // labels: withdrawl_labels, - // datasets: [ - // { - // label: '提现统计', - // data: withdrawl_values, - // borderColor: '#358ed7', - // backgroundColor: 'rgba(53, 142, 215, 0.175)', - // borderWidth: 1, - // fill: false, - // lineTension: 0.5 - // } - // ] - // } - // } - // ); - $.getJSON('index/money_lines',function(res){ + $.getJSON('index/lines_data?items=withdrawl,recharge&days=7',function(res){ res = res.data; var labels=[]; var withdrawl_values=[]; @@ -248,17 +212,13 @@ define(['lightyear','multitabs', '../libs/Chart','form','bootstrap'], function ( } ); }); - $.getJSON('index/role_buy_lines',function(res){ + $.getJSON('index/lines_data?items=register&days=7',function(res){ res = res.data; - var amount=[]; - var reward=[]; - var residual=[]; + var register=[]; var labels=[]; for (let date in res) { labels.push(date); - amount.push(res[date].amount); - reward.push(res[date].reward); - residual.push(res[date].residual); + register.push(res[date].register); } new Chart(document.getElementsByClassName('js-role_buy_lines'),{ type: 'line', @@ -266,32 +226,32 @@ define(['lightyear','multitabs', '../libs/Chart','form','bootstrap'], function ( labels: labels, datasets: [ { - label: '总购买金额', - data: amount, + label: '注册统计', + data: register, borderColor: 'rgba(43, 191, 232, 0.7)', backgroundColor: 'rgba(43, 191, 232, 0.7)', borderWidth: 2, fill: false, lineTension: 0.5 }, - { - label: '奖励统计', - data: reward, - borderColor: 'rgba(166, 53, 215, 0.7)', - backgroundColor: 'rgba(166, 53, 215, 0.7)', - borderWidth: 2, - fill: false, - lineTension: 0.5 - }, - { - label: '沉淀统计', - data: residual, - borderColor: 'rgba(59, 199, 8, 0.7)', - backgroundColor: 'rgba(59, 199, 8, 0.7)', - borderWidth: 2, - fill: false, - lineTension: 0.5 - } + // { + // label: '奖励统计', + // data: reward, + // borderColor: 'rgba(166, 53, 215, 0.7)', + // backgroundColor: 'rgba(166, 53, 215, 0.7)', + // borderWidth: 2, + // fill: false, + // lineTension: 0.5 + // }, + // { + // label: '沉淀统计', + // data: residual, + // borderColor: 'rgba(59, 199, 8, 0.7)', + // backgroundColor: 'rgba(59, 199, 8, 0.7)', + // borderWidth: 2, + // fill: false, + // lineTension: 0.5 + // } ] } }); diff --git a/plugin/admin/public/js/user.js b/plugin/admin/public/js/user.js index ef83118..572d5fd 100755 --- a/plugin/admin/public/js/user.js +++ b/plugin/admin/public/js/user.js @@ -50,11 +50,13 @@ define(['table', 'upload','form','qrcode'], function (Table,Upload,Form) { }, { title: "用户名", - field: "username" + field: "username", + filter: "string" }, { title: "昵称", - field: "nickname" + field: "nickname", + filter: "string" }, { title: "头像", diff --git a/readme.md b/readme.md index 23ab85b..3da4254 100755 --- a/readme.md +++ b/readme.md @@ -79,3 +79,11 @@ bash bootstrap.sh mage mage start docker exec -it mongo mongorestore --uri="mongodb://openIM:n1e5a6s6m7@172.18.0.1:37017/openim_v3" /data/backup/3/openim_v3 +docker exec -it mongo mongorestore --uri="mongodb://openIM:n1e5a6s6m7@localhost:27017/openim_v3" /data/backup/0/openim_v3 + +修复未读<0的问题 +cd /www/wwwroot/im/server +go run tools/fix-conversation-maxseq/main.go --config config --dry-run +清理15天以前的消息 +cd /www/wwwroot/im/server +go run tools/clean-old-messages/main.go --config config --days 15 diff --git a/support/Jwt.php b/support/Jwt.php index 54c22bc..608725e 100755 --- a/support/Jwt.php +++ b/support/Jwt.php @@ -68,7 +68,7 @@ class Jwt 'password' => $password, 'email' => $email, 'mobile' => $mobile, - 'level' => 1, + 'level' => 0, 'score' => 0, 'avatar' => '', ]; diff --git a/support/OpenImSdk/Api/Auth.php b/support/OpenImSdk/Api/Auth.php index 6bf3ada..78ede62 100755 --- a/support/OpenImSdk/Api/Auth.php +++ b/support/OpenImSdk/Api/Auth.php @@ -33,9 +33,8 @@ class Auth public function getUserToken(string $userID, string $platformID = 'android'): array { // 获取管理员token - $adminToken = Utils::getAdminToken(); $platformID = Utils::getPlatformId( $platformID ); - return Utils::send(Url::$getUserToken, ['userID' => $userID, 'platformID' => $platformID], '获取用户token错误', $adminToken); + return Utils::send(Url::$getUserToken, ['userID' => $userID, 'platformID' => $platformID], '获取用户token错误'); } /** diff --git a/support/OpenImSdk/Api/Friend.php b/support/OpenImSdk/Api/Friend.php index 8365bf8..87cb9dc 100755 --- a/support/OpenImSdk/Api/Friend.php +++ b/support/OpenImSdk/Api/Friend.php @@ -63,7 +63,7 @@ class Friend * @param string $friendUserID 好友ID * @return array */ - public function deleteFriend(string $ownerUserID, string $friendUserID): array + public function deleteFriend(string $ownerUserID, string $friendUserID): array|bool { // 获取管理员token $adminToken = Utils::getAdminToken(); diff --git a/support/OpenImSdk/Core/Utils.php b/support/OpenImSdk/Core/Utils.php index 0885562..80d23d3 100755 --- a/support/OpenImSdk/Core/Utils.php +++ b/support/OpenImSdk/Core/Utils.php @@ -192,6 +192,9 @@ class Utils return self::getTokenManager()->clearToken($userID, $isAdmin); } public static function getPlatformId($name=''): int{ + if(ctype_digit($name)){ + return (int)$name; + } $arr = [ 'ios' => 1, 'android' => 2,