From caa7619b31f3c17ce8bf0564a7699052861a1338 Mon Sep 17 00:00:00 2001 From: lingling <1077478963@qq.com> Date: Thu, 13 Mar 2025 08:40:57 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E5=92=8C=E5=88=B7=E6=96=B0token=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=8C=E4=BC=98=E5=8C=96JWT=E8=AE=A4=E8=AF=81?= =?UTF-8?q?=E4=B8=AD=E9=97=B4=E4=BB=B6=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Utils/API/Facebook.php | 16 +++ .../api/v1/AccountController.php | 82 +++++++++++ .../api/v1/PromotionController.php | 132 ++++++++++++++++++ app/dao/SignDao.php | 71 +++++++--- app/dao/UserPhoneLogDao.php | 2 +- app/dao/UserRewardDao.php | 2 +- app/middleware/JwtAuthMiddleware.php | 57 +++++--- process/Task.php | 2 +- process/Task2.php | 27 ++-- 9 files changed, 333 insertions(+), 58 deletions(-) create mode 100644 app/controller/generalization/api/v1/AccountController.php create mode 100644 app/controller/generalization/api/v1/PromotionController.php diff --git a/app/Utils/API/Facebook.php b/app/Utils/API/Facebook.php index af8417d..c106626 100644 --- a/app/Utils/API/Facebook.php +++ b/app/Utils/API/Facebook.php @@ -47,6 +47,7 @@ class Facebook $event = (new Event()) ->setEventName($event_name) ->setEventTime(time()) + ->setEventId(self::create_uuid()) ->setUserData($user_data) ->setCustomData(new CustomData()) // 可扩展更多数据 ->setActionSource("website"); @@ -118,4 +119,19 @@ class Facebook } } } + /** + * uuid生成器 + * + * @param string $prefix + * @return void + */ + public static function create_uuid($prefix=""){ + $chars = md5(uniqid(mt_rand(), true)); + $uuid = substr ( $chars, 0, 8 ) . '-' + . substr ( $chars, 8, 4 ) . '-' + . substr ( $chars, 12, 4 ) . '-' + . substr ( $chars, 16, 4 ) . '-' + . substr ( $chars, 20, 12 ); + return $prefix.$uuid ; + } } diff --git a/app/controller/generalization/api/v1/AccountController.php b/app/controller/generalization/api/v1/AccountController.php new file mode 100644 index 0000000..550bb45 --- /dev/null +++ b/app/controller/generalization/api/v1/AccountController.php @@ -0,0 +1,82 @@ +post(); + + // 根据手机号查询用户 + $db = Admin::where('username', '=', $data['username'])->first(); + + // 如果未找到用户,返回错误 + if (!$db) { + return ApiResponse::error(402, [], '用户未注册'); + } + + // 获取用户输入的密码 + $password = $data['password']; + + // 验证密码是否正确 + if (password_verify($password, $db->password)) { + $user = [ + 'id' => $db->id, + 'nickname' => $db->nickname, + 'username' => $db->username, + 'access_exp' => 2592000, + 'user_type' => 'generalization' + ]; + // 如果密码正确,生成 JWT 令牌 + $token = JwtToken::generateToken($user); + Log::info('生成的token:' . json_encode($token)); + // 返回成功响应和用户信息(可以将 token 添加到响应中) + return ApiResponse::success(200, [ + 'user' => $user, // 返回用户信息 + 'token' => $token // 返回生成的 token + ]); + } else { + // 密码错误,返回错误响应 + return ApiResponse::error(402, [], '密码错误'); + } + } + /** + * @Apidoc\Title("1.0 刷新token") + * @Apidoc\Url("generalization/api/v1/account/refresh") + * @Apidoc\Method("POST") + * @Apidoc\Param("refresh_token", type="string",require=true, desc="令牌") + * @Apidoc\Returned("token", type="object", desc="令牌") + */ + public function refresh(Request $request) { + $token = JwtToken::refreshToken(); + return ApiResponse::success(200, [ + 'token' => $token // 返回生成的 token + ]); + } +} diff --git a/app/controller/generalization/api/v1/PromotionController.php b/app/controller/generalization/api/v1/PromotionController.php new file mode 100644 index 0000000..b76c680 --- /dev/null +++ b/app/controller/generalization/api/v1/PromotionController.php @@ -0,0 +1,132 @@ +post(); + + // 构建查询构造器 + $query = User::query(); + + // 根据 key 进行模糊查询 + if (!empty($data['key'])) { + $key = $data['key']; + $query->where(function ($query) use ($key) { + $query->where('users.invite_code', 'like', '%' . $key . '%') + ->orWhere('users.remark', 'like', '%' . $key . '%'); + }); + } + + // 根据 status 过滤,假设 status 字段存在并且不是 -1 + if (isset($data['status']) && $data['status'] != -1) { + $status = (int)$data['status']; // 强制转换为整数 + // 使用 users 表的别名明确指定 status 字段 + $query->where('users.status', $status); + } + + // 使用 join 进行关联查询 f_id 对应的用户名称 + $users = $query->leftJoin('users as u', 'users.f_id', '=', 'u.id') // 假设 users 表有 id 字段,f_id 关联到父用户 + ->select( + 'users.id', + 'users.username', + 'users.updated_at', + 'users.invite_code', + 'users.login_time', + 'users.money', + 'users.remark', + 'users.status', + 'users.vip_id', + 'users.created_at', + 'u.username as parent_username' // 选择所需字段,并为父用户用户名起别名 + )->where('users.isrobot', 1) + ->orderBy('users.id', 'desc')->get(); // 确保按 users 表的 id 排序 + return ApiResponse::success(200, $users); + } + + /** + * @Apidoc\Title(" 获取推广链接详细注册名单") + * @Apidoc\Url("admin/api/v1/Promotion/detailed") + * @Apidoc\Param("invite_code", type="string", require=true, desc="机器人的邀请码") + * @Apidoc\Param("start_date", type="string", require=false, desc="开始时间,格式:YYYY-MM-DD") + * @Apidoc\Param("end_date", type="string", require=false, desc="结束时间,格式:YYYY-MM-DD") + * @Apidoc\Method("POST") + */ + public function detailed(Request $request) + { + $data = $request->post(); + + // 获取机器人邀请码对应的用户 ID + $users = User::where('robot_invite_code', $data['invite_code'])->pluck('id')->toArray(); + + // 获取时间段参数,默认使用今天 + $startDate = isset($data['start_date']) ? $data['start_date'] : date('Y-m-d'); + $endDate = isset($data['end_date']) ? $data['end_date'] : date('Y-m-d'); + + // 获取用户手机号(按 user_id 分组)并根据时间范围筛选 + $UserPhone = UserPhone::whereIn('user_id', $users) + ->whereBetween('created_at', [$startDate . ' 00:00:00', $endDate . ' 23:59:59']) // 时间范围筛选 + ->select('user_id', DB::raw('count(*) as phone_count')) // 聚合查询,按 user_id 分组,计算每个 user_id 的手机数量 + ->groupBy('user_id') + ->get(); + + // 获取注册的用户数量,按时间筛选 + $res['register'] = User::whereIn('id', $users) + ->whereBetween('created_at', [$startDate . ' 00:00:00', $endDate . ' 23:59:59']) // 时间范围筛选 + ->count(); + + // 获取绑定手机号的用户数量 + $res['binding'] = count($UserPhone); + + // 获取注册的用户详细信息(筛选注册时间段) + $res['register_user'] = User::whereIn('id', $users) + ->whereBetween('created_at', [$startDate . ' 00:00:00', $endDate . ' 23:59:59']) // 时间范围筛选 + ->orderBy('id', 'desc') + ->get(); + + // 获取绑定手机号的用户详细信息 + $userIdsWithPhones = $UserPhone->pluck('user_id')->toArray(); // 获取绑定手机号的用户 ID 列表 + $res['binding_user'] = User::whereIn('id', $userIdsWithPhones) + ->whereBetween('created_at', [$startDate . ' 00:00:00', $endDate . ' 23:59:59']) // 时间范围筛选 + ->orderBy('id', 'desc') + ->get(); + + return ApiResponse::success(200, $res); + } +} diff --git a/app/dao/SignDao.php b/app/dao/SignDao.php index a3ce868..f4019e8 100644 --- a/app/dao/SignDao.php +++ b/app/dao/SignDao.php @@ -40,7 +40,7 @@ class SignDao { $startTime = date('Y-m-01', time()); //获取该月份的第一天 $endTime = date('Y-m-t', time()); //获取该月份的最后一天 - $mon_data = Signlog::where('userid',$user_id)->whereBetween('created_at', [$startTime . " 00:00:00", $endTime . " 23:59:59"])->orderBy('created_at', 'ASC')->get(); + $mon_data = Signlog::where('userid', $user_id)->whereBetween('created_at', [$startTime . " 00:00:00", $endTime . " 23:59:59"])->orderBy('created_at', 'ASC')->get(); $days = []; foreach ($mon_data as $sign) { // 将签到日期提取出来 @@ -59,46 +59,77 @@ class SignDao return $res; } /** - * 查询连续签到天数 + * 查询连续签到天数,并按 7 天一个周期计算 * + * @param int $user_id 用户ID + * @return int 连续签到的天数 */ public static function search_Sign_tolong($user_id) { + // 获取该月份的第一天和最后一天 $startTime = date('Y-m-01', time()); // 获取该月份的第一天 $endTime = date('Y-m-t', time()); // 获取该月份的最后一天 - $mon_data = Signlog::where('userid',$user_id)->whereBetween('created_at', [$startTime . " 00:00:00", $endTime . " 23:59:59"]) + + // 查询该用户在当前月份的所有签到记录,筛选出有效签到(未兑换奖励的签到) + $mon_data = Signlog::where('userid', $user_id) + ->whereBetween('created_at', [$startTime . " 00:00:00", $endTime . " 23:59:59"]) ->orderBy('created_at', 'ASC') ->get(); - // 签到的日期数组 + // 签到的日期数组,用于判断哪些天有签到 $signed_days = []; - $today = date('d'); + $today = date('d'); // 获取今天的日期(用于判断是否是连续签到) + + // 遍历签到记录,记录没有兑换奖励的签到日期 foreach ($mon_data as $sign) { - // 获取签到的日期并保存 - // 只有没有兑换奖励的才算签到有效 - if ($sign->isexchange == 0) { - $signed_days[] = $sign->created_at->format('d'); + if ($sign->isexchange == 0) { // 判断是否没有兑换奖励 + $signed_days[] = $sign->created_at->format('d'); // 保存签到日期的“日”部分 } } - // 获取当前月份的天数 + // 获取当前月份的总天数 $days_in_month = date('t'); - $sign_days = 0; // 连续签到天数 + $sign_days = 0; // 初始化连续签到天数 + $full_cycles = 0; // 完整周期的数量(每7天为一个周期) - // 检查每从今天开始往后是否连续签到 - for ($day = $today; $day >= 0; $day--) { - // 检查当前日期是否有签到 + // 检查从今天开始,是否连续签到 + for ($day = $today; $day >= 1; $day--) { + // 检查当前日期是否在签到日期数组中 if (in_array($day, $signed_days)) { - $sign_days++; // 连续签到天数加 1 + $sign_days++; // 连续签到天数加 1 } else { - break; + break; // 一旦发现没有签到,跳出循环 + } + + // 如果连续签到达到 7 天,发放奖励并重置 + if ($sign_days == 7) { + $today = date('Y-m-d'); // 获取今天的日期 + $todaySign = Signlog::where('userid', $user_id) + ->whereDate('created_at', $today) // 查找今天的签到记录 + ->where('isexchange', 0) // 确认没有兑换奖励 + ->first(); // 如果今天没有兑换奖励,则返回记录 + + // 如果今天没有兑换奖励,则进行奖励 + if ($todaySign) { + // 赠送奖励 + UserRewardDao::sing($user_id, 500); // 给用户奖励 500 + + // 标记为已兑换奖励 + $todaySign->isexchange = 1; // 假设 isexchange 是控制是否已兑换奖励的字段 + $todaySign->save(); // 保存更新后的签到记录 + } + $sign_days = 0; // 重置连续签到天数,开始新的一周期 + $full_cycles++; // 增加完整周期数 } } - if($sign_days==7){ - UserRewardDao::sing($user_id,500); + + // 如果在最后的连续签到周期内还不足 7 天,不发放奖励 + if ($sign_days == 0 && $full_cycles > 0) { + // 返回已经完成的周期数 + return $full_cycles * 7; } - // 返回连续签到天数 - return $sign_days; + // 返回连续签到的天数 + return $full_cycles * 7 + $sign_days; } } diff --git a/app/dao/UserPhoneLogDao.php b/app/dao/UserPhoneLogDao.php index cd7e3d9..b301e23 100644 --- a/app/dao/UserPhoneLogDao.php +++ b/app/dao/UserPhoneLogDao.php @@ -29,7 +29,7 @@ class UserPhoneLogDao public static function setOnlineTimeByPhone($phone, $status, $currentTimestamp) { //这里因为和api的返回是反的所以需要这样 - $status = $status == 0 ? 1 : 0; + // $status = $status == 0 ? 1 : 0; $today = date('Y-m-d'); // $UserPhoneLog=UserPhoneLog::where('phone',$phone)->where('created_at', '>=', $today." 00:00:00")->limit(2)->orderByDesc('id')->get(); $UserPhoneLog = UserPhoneLog::where('phone', $phone)->where('created_at', '>=', $today . " 00:00:00")->orderBy('id', 'desc')->first(); diff --git a/app/dao/UserRewardDao.php b/app/dao/UserRewardDao.php index fdd762e..bde568d 100644 --- a/app/dao/UserRewardDao.php +++ b/app/dao/UserRewardDao.php @@ -131,7 +131,7 @@ class UserRewardDao self::base_phone($ff->id, 5, $ff_dividend, '加粉赏金',$phone); } } - self::base($userid, $status, $money, $memo); + self::base_phone($userid, $status, $money, $memo,$phone); } /** * 搜索函数 diff --git a/app/middleware/JwtAuthMiddleware.php b/app/middleware/JwtAuthMiddleware.php index 11497b2..e76e104 100644 --- a/app/middleware/JwtAuthMiddleware.php +++ b/app/middleware/JwtAuthMiddleware.php @@ -1,4 +1,5 @@ name=='hg\apidoc\Controller'){ + if ($controller->name == 'hg\apidoc\Controller') { return $handler($request); } // var_dump($controller->name); @@ -41,18 +42,18 @@ class JwtAuthMiddleware implements MiddlewareInterface // 获取 Authorization 头部中的 token,通常格式为 "Bearer " $token1 = $request->header('Authorization'); - $token2 =$request->header('Token'); + $token2 = $request->header('Token'); $token_tmp = !empty($token1) ? $token1 : $token2; - - if (strpos($token_tmp,"Bearer ") === false) { - $token= 'Bearer '.$token_tmp; - }else{ - $token= $token_tmp; + + if (strpos($token_tmp, "Bearer ") === false) { + $token = 'Bearer ' . $token_tmp; + } else { + $token = $token_tmp; } // 检查 token 是否为空 if (empty($token)) { // return ApiResponse::error(401, ['error' => '缺少令牌'], '未授权'); - return response('',401,['error' => '缺少令牌']); + return response('', 401, ['error' => '缺少令牌']); } // var_dump($token); @@ -64,25 +65,39 @@ class JwtAuthMiddleware implements MiddlewareInterface try { // 解码 token,返回用户信息 $decoded = JwtToken::getExtend($token); - if(!empty($decoded['user_type'])&&$decoded['user_type']=='user'){ - if (false !== strstr($controller->name, 'admin')) { - return response('',401,['error' => '无权限']); - } - $user=User::find($decoded['id']); - if($user->status==0){ - return response('',401,['error' => '用户封禁']); + if (!empty($decoded['user_type'])) { + $user_type = $decoded['user_type']; + // 权限校验 + switch ($user_type) { + case 'user': + // 如果是普通用户,禁止访问 admin 或 generalization 控制器 + if (false !== strstr($controller->name, 'admin') || false !== strstr($controller->name, 'generalization')) { + return response('', 401, ['error' => '无权限']); + } + break; + + case 'generalization': + // 如果是推广员,禁止访问 admin 控制器 + if (false !== strstr($controller->name, 'admin')) { + return response('', 401, ['error' => '无权限']); + } + break; + + case 'admin': + // 如果是管理员,不做限制(可以访问所有控制器) + break; + + default: + // 其他类型的用户,如果有的话 + return response('', 401, ['error' => '未知的用户类型']); } } - $user=User::find($decoded['id']); - // if($user->status==0){ - // return response('',401,['error' => '用户封禁']); - // } - // var_dump($decoded); + } catch (\Exception $e) { // var_dump($e); // 解码失败,返回无效令牌错误 // return ApiResponse::error(401, ['error' => '无效的令牌'], '无效的令牌'); - return response('',401,['error' => '无效的令牌']); + return response('', 401, ['error' => '无效的令牌']); } // 将解码后的用户信息存储到请求对象的 user 属性中 diff --git a/process/Task.php b/process/Task.php index c1858b5..f30e8f3 100644 --- a/process/Task.php +++ b/process/Task.php @@ -10,7 +10,7 @@ use app\model\GetLodeLog; use support\Log; /** - * 查询用户是否在线类 + * 收取验证码 */ class Task { diff --git a/process/Task2.php b/process/Task2.php index 2c40273..ca12cf8 100644 --- a/process/Task2.php +++ b/process/Task2.php @@ -57,7 +57,7 @@ class Task2 } - + //在线 if ($phone->time > 3600 && $v['logged'] == 1) { // 计算超过 1 小时的积分 $hours = intdiv($phone->time, 3600); @@ -71,20 +71,19 @@ class Task2 // 保存用户收益到 UserReward 表 UserRewardDao::Onhookincome($phone->user_id, $score, $phone->phone); - - + // 保存在线时长记录 + UserPhoneLogDao::setOnlineTimeByPhone($phone->phone, 1, $currentTimestamp); + $phone->status = 1; + $phone->time += $currentTimestamp - $phone->last_time; + $phone->last_time = $currentTimestamp; + $updateData[] = $phone; } - // 保存在线时长记录 这里需要反转状态 - UserPhoneLogDao::setOnlineTimeByPhone($phone->phone, 0, $currentTimestamp); - $phone->status = 1; - $phone->time += $currentTimestamp - $phone->last_time; - $phone->last_time = $currentTimestamp; - $updateData[] = $phone; - - + //不在线 if ($v['logged'] == 0) { $phone->status = 0; $phone->last_time = $currentTimestamp; + // 保存在线时长记录 + UserPhoneLogDao::setOnlineTimeByPhone($phone->phone, 0, $currentTimestamp); $updateData[] = $phone; } } @@ -103,7 +102,7 @@ class Task2 $all_usernames = array_merge($usernames2, $usernames); UserPhone::whereNotIn('phone', $all_usernames) ->where('status', '!=', 2) - ->update(['status' => 2]); + ->update(['status' => 2,'last_time'=>$currentTimestamp]); // 批量查询用户信息 $phones2 = UserPhone::whereIn('phone', $usernames2)->get(); @@ -139,8 +138,8 @@ class Task2 } - // 保存在线时长记录 这里需要反转状态 - UserPhoneLogDao::setOnlineTimeByPhone($phone->phone, 0, $currentTimestamp); + // 保存在线时长记录 + UserPhoneLogDao::setOnlineTimeByPhone($phone->phone, 1, $currentTimestamp); $phone->status = 1; $phone->time += $currentTimestamp - $phone->last_time; $phone->last_time = $currentTimestamp;