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 @@
使用手机号码注册您的账户
+使用手机号或邮箱注册您的账户
总提现
=$withdrawl_total?>
-