| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641 |
- <?php
- namespace app\api\controller;
- use Exception;
- use think\Cache;
- use think\Controller;
- use think\Db;
- use think\Env;
- use think\Request;
- /**
- * 聚合平台对接
- */
- class JhApi extends Controller
- {
- protected $api_sign_key;
- public function __construct(Request $request = null)
- {
- parent::__construct($request);
- $this->api_sign_key = Env::get("qmjh.api_sign_key");
- log_message('__construct.input:' . json_encode(input()), 'log', LOG_PATH . 'jh_log/');
- }
- /**
- * sign
- *
- * @param $data
- *
- * @return string
- */
- private function sign($data)
- {
- unset($data['sign']);
- $data['key'] = $this->api_sign_key;
- ksort($data);
- $string = '';
- foreach ($data as $k => $v) {
- if ($string) {
- $string .= '&' . $k . "=" . $v;
- } else {
- $string = $k . "=" . $v;
- }
- }
- return md5($string);
- }
- public function getRole()
- {
- $data = input();
- $type = input('type', 0); // 类型:0=总数;1=列表
- $params = input('params');
- if (!isset($type) || !isset($params)) {
- return json(["code" => -100, "msg" => '缺少必要参数!', "data" => []]);
- }
- $signRes = $this->sign($data);
- // dump($signRes);
- if ($signRes != $data['sign']) {
- return json(["code" => -110, "msg" => '签名有误!', "data" => []]);
- }
- if (!is_json($params)) {
- return json(["code" => -110, "msg" => '查询数据格式有误!', "data" => []]);
- }
- $listBy = json_decode($params, true);
- if(count($listBy) > 2000){
- return json(["code" => -120, "msg" => '查询数据条数限制超 2000条', "data" => []]);
- }
- try {
- // 数据标识处理
- $markByList = [];
- array_walk($listBy, function ($v) use (&$markByList) {
- // $markByList[$v['id']] = $v['aid'] . '_' . $v['gid'].'_'.$v['id'];
- $markByList[$v['id']] = $v['aid'] . '_' . $v['gid'];
- });
- $markByFlip = array_flip($markByList);
- $modelHandle = Db::table('nw_member_game_server');
- $modelHandle->where(function ($query) use ($listBy) {
- foreach ($listBy as $v) {
- $query->whereOr(function ($query) use ($v) {
- $query->where(['member_id' => $v['aid'], 'game_id' => $v['gid']]);
- });
- }
- });
- $result = [];
- if ($type == 1) {
- $list = $modelHandle->field("mgs_id,roleid,rolename,serverid,servername,FROM_UNIXTIME(create_time, '%Y-%m-%d %H:%i:%s') as create_time,CONCAT(`member_id`,'_',`game_id`) as mark")
- ->chunk(500, function($items) use ($markByFlip, &$result) {
- foreach ($items as $item) {
- if (empty($markByFlip[$item['mark']])) {
- break;
- }
- $key = $markByFlip[$item['mark']];
- $result[$key][] = ['role_id' => $item['roleid'], 'rolename' => $item['rolename'], 'server_id' => $item['serverid'], 'server_name' => $item['servername'], 'create_time' => $item['create_time']];
- }
- });
- } else {
- $list = $modelHandle->field("CONCAT(`member_id`,'_',`game_id`) as mark, count(*) as count")->group('mark')->select();
- foreach ($list as $v) {
- if (empty($markByFlip[$v['mark']])) {
- break;
- }
- $key = $markByFlip[$v['mark']];
- $result[$key][] = $v['count'];
- }
- }
- if (!$list) {
- return json(["code" => 200, "msg" => '没有相关数据!', "data" => []]);
- }
- } catch (\Exception $e) {
- // dump($e->getMessage(), $e->getFile() . ' : ' . $e->getLine());
- return json(["code" => -120, "msg" => '程序异常:' . $e->getMessage() . ' - ' . $e->getFile() . ' : ' . $e->getLine(), "data" => []]);
- }
- return json(["code" => 200, "msg" => '成功', "data" => $result]);
- }
- /**
- * 获取游戏账户列表
- *
- * @return \think\response\Json
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\ModelNotFoundException
- * @throws \think\exception\DbException
- */
- public function getSubList()
- {
- $input = input();
- $signRes = $this->sign($input);
- if ($signRes != $input['sign']) {
- return json(["code" => -110, "msg" => '签名有误!', "data" => []]);
- }
- $date = $input['date'] ?? '';
- if ($date) {
- $where['cl.login_time'] = ['between', [strtotime($date . ' 00:00:00'), strtotime($date . ' 23:59:59')]];
- } else {
- // 三个月时间
- $where['cl.login_time'] = ['between', [strtotime('-3 months'), strtotime($date . ' 23:59:59')]];
- }
- if (!empty($input['game_id'])) {
- $where['cl.gameid'] = ['in', explode(',', $input['game_id'])];
- }
- $list = Db::table('cy_logininfo')->alias('cl')
- ->join('cy_members cm', 'cl.userid=cm.id', 'left')
- ->join('cy_game cg', 'cl.gameid=cg.id', 'left')
- ->join('nw_channel nc', 'cl.channel_id=nc.id', 'left')
- ->where(['nc.gh_status' => 1])->where($where)
- ->field('cm.username as user_name,cl.gameid as game_id,max(cl.login_time) as update_time')
- ->group('cl.gameid,cl.sub_id')
- ->page($input['page'] ?? 1, $input['limit'] ?? 100)
- ->select();
- $total = Db::table('cy_logininfo')->alias('cl')
- ->join('cy_members cm', 'cl.userid=cm.id', 'left')
- ->join('cy_game cg', 'cl.gameid=cg.id', 'left')
- ->join('nw_channel nc', 'cl.channel_id=nc.id', 'left')
- ->field('cm.username as user_name,cl.gameid as game_id,max(cl.login_time) as update_time')
- ->where(['nc.gh_status' => 1])->where($where)
- ->group('cl.gameid,cl.sub_id')
- ->count();
- return json(["code" => 200, "msg" => 'success', "data" => $list, 'count' => $total]);
- }
- /**
- * 获取渠道数据汇总
- *
- * @return \think\response\Json
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\ModelNotFoundException
- * @throws \think\exception\DbException
- */
- public function getChannelDataSummary()
- {
- $input = input();
- $signRes = $this->sign($input);
- if ($signRes != $input['sign']) {
- return json(["code" => -110, "msg" => '签名有误!', "data" => []]);
- }
- $date = $input['date'] ?? '';
- if (!$date) {
- return json(["code" => -120, "msg" => '参数错误,缺少date参数!', "data" => []]);
- }
- $where = [
- 'crg.day' => $date,
- 'crg.type_id' => 2,
- 'crg.channel_id' => ['>', 0],
- ];
- $list = Db::table('cy_retaine_game')->alias('crg')
- ->join('cy_game cg', 'cg.id=crg.game_id AND cg.cooperation_status=1', 'left')
- ->join('nw_channel nc', 'nc.id=crg.channel_id AND nc.gh_status=1', 'left')
- ->field("crg.type_id, crg.game_id, cg.name as game_name, crg.channel_id, nc.name as channel_name, crg.reg_num, crg.role_num, crg.act_num, crg.recharge_num, crg.pay_num")
- ->where($where)
- ->where(function ($query) {
- // 非空条件:至少有一个字段不为空
- $query->whereOr('crg.reg_num', '>', 0)
- ->whereOr('crg.role_num', '>', 0)
- ->whereOr('crg.act_num', '>', 0)
- ->whereOr('crg.recharge_num', '>', 0)
- ->whereOr('crg.pay_num', '>', 0);
- })
- ->order("crg.day desc, crg.reg_num desc, crg.game_id desc")
- ->select();
- return json(["code" => 200, "msg" => 'success', "data" => $list]);
- }
- public function getChannelDataSummaryV2()
- {
- $input = input();
- $signRes = $this->sign($input);
- if (empty($input['sign']) || $signRes != $input['sign']) {
- return json(["code" => -110, "msg" => '签名有误!', "data" => []]);
- }
- if (empty($input['date'])) {
- return json(["code" => -120, "msg" => '参数错误,缺少date参数!', "data" => []]);
- }
- $type = input('type', 1); // 类型: 1=汇总, 2=详情
- $where = [
- 'crg.day' => $input['date'],
- 'crg.type_id' => 2,
- 'crg.game_id' => ['>', 0],
- 'crg.channel_id' => ['>', 0],
- ];
- // , crg.old_act_num, crg.old_pay_num, crg.old_recharge_num
- $filed = "crg.id, crg.day, crg.game_id, cg.name as game_name, crg.channel_id, nc.name as channel_name, crg.reg_num, crg.role_num, crg.act_num, crg.recharge_num, crg.pay_num, crg.new_act_num, crg.new_pay_num, crg.new_recharge_num";
- if ($type == 2) {
- $filed = "crg.id, crg.day, crg.game_id, cg.name as game_name, crg.channel_id, nc.name as channel_name, crg.reg_total, crg.reg_num, crg.one_stay, crg.three_stay, crg.four_stay, crg.five_stay, crg.six_stay, crg.seven_stay, crg.fifteen_stay, crg.thirty_stay";
- }
- $listRows = intval(input('list_rows', 50));
- $pageNum = intval(input('page', 1));
- $retaineList = Db::table('cy_retaine_game')->alias('crg')
- ->join('cy_game cg', 'cg.id=crg.game_id AND cg.cooperation_status=1', 'left')
- ->join('nw_channel nc', 'nc.id=crg.channel_id AND nc.gh_status=1')
- ->field($filed)
- ->where($where)
- ->where(function ($query) use ($type) {
- // 非空条件:至少有一个字段不为空
- if ($type == 1) {
- $query->whereOr('crg.reg_num', '>', 0)
- ->whereOr('crg.role_num', '>', 0)
- ->whereOr('crg.act_num', '>', 0)
- ->whereOr('crg.recharge_num', '>', 0)
- ->whereOr('crg.pay_num', '>', 0)
- ->whereOr('crg.new_act_num', '>', 0)
- ->whereOr('crg.new_pay_num', '>', 0)
- ->whereOr('crg.new_recharge_num', '>', 0);
- } else {
- $query->whereOr('crg.reg_num', '>', 0)
- ->whereOr('crg.one_stay', '>', 0)
- ->whereOr('crg.three_stay', '>', 0)
- ->whereOr('crg.four_stay', '>', 0)
- ->whereOr('crg.five_stay', '>', 0)
- ->whereOr('crg.six_stay', '>', 0)
- ->whereOr('crg.seven_stay', '>', 0)
- ->whereOr('crg.fifteen_stay', '>', 0)
- ->whereOr('crg.thirty_stay', '>', 0);
- }
- })
- ->order("crg.id asc")
- ->paginate($listRows, false, ['page' => $pageNum]);
- $pageArr = $retaineList->toArray(); // 包含 data, total, per_page, current_page, last_page 等
- if ($type == 1) {
- $list = $pageArr['data'] ?? [];
- foreach ($list as &$v) {
- $old_recharge_num = $v['recharge_num'] - $v['new_recharge_num'];
- if ($old_recharge_num <= 0) {
- $old_recharge_num = "0.00";
- }
- $v['old_act_num'] = $v['old_pay_num'] = $v['old_recharge_num'] = 0;
- if($v['act_num'] > 0 && ($v['act_num'] - $v['new_act_num']) > 0){
- $v['old_act_num'] = $v['act_num'] - $v['new_act_num'];
- }
- if($v['pay_num'] > 0 && ($v['pay_num'] - $v['new_pay_num']) > 0){
- $v['old_pay_num'] = $v['pay_num'] - $v['new_pay_num'];
- }
- $v['old_recharge_num'] = sprintf("%.2f", $old_recharge_num);
- }
- $pageArr['data'] = $list;
- }
- return json(["code" => 200, "msg" => 'success', "data" => $pageArr]);
- }
- // 获取注册归属数据列表
- public function getSubUserList()
- {
- $input = input();
- // 请求限流:一分钟三次(使用ThinkPHP5的Cache方式)
- $limitKey = 'jh_api_getSubUserList_limit:' . md5(json_encode($input));
- try {
- $redis = Cache::store('redis');
- $requestCount = $redis->get($limitKey);
- if ($requestCount === false || $requestCount === null) {
- // 首次请求,设置为1并设置过期时间
- $redis->set($limitKey, 1, 60);
- $requestCount = 1;
- } else {
- // 增加计数
- $requestCount = $redis->inc($limitKey);
- }
- if ($requestCount > 3) {
- return json(["code" => -130, "msg" => '请求过于频繁,请稍后再试(每分钟限制3次)!', "data" => []]);
- }
- } catch (\Exception $e) {
- // log_message('Redis连接失败: ' . $e->getMessage(), 'error', LOG_PATH . 'jh_log/');
- return json(["code" => -130, "msg" => '当前脚本程序执行异常,请联系开发!', "data" => []]);
- }
- $signRes = $this->sign($input);
- // dump($signRes);
- if (empty($input['sign']) || $signRes != $input['sign']) {
- return json(["code" => -110, "msg" => '签名有误!', "data" => []]);
- }
- if (empty($input['date'])) {
- return json(["code" => -120, "msg" => '参数错误,缺少date参数!', "data" => []]);
- }
- $where = [
- 'nc.gh_status' => 1
- ];
- if (!empty($input['date']) && empty($input['uid'])) {
- $where['ns.create_time'] = ['between', [strtotime($input['date'] . ' 00:00:00'), strtotime($input['date'] . ' 23:59:59')]];
- }
- if (!empty($input['uid'])) {
- $where['ns.id'] = ['>', $input['uid']];
- }
- $list = Db::table('nw_subaccount')->alias('ns')
- ->join('cy_members cm', 'ns.member_id = cm.id', 'left')
- ->join('cy_game cg', 'ns.game_id = cg.id', 'left')
- ->join('nw_channel nc', 'ns.channel_id = nc.id', 'left') // 推广员 (level 3)
- ->join('nw_channel p1', 'nc.parent_id = p1.id', 'left') // 子会长
- ->join('nw_channel p2', 'p1.parent_id = p2.id', 'left') // 会长
- ->where($where)
- ->order('ns.id asc')
- ->field([
- 'ns.id', // 子账户ID
- 'ns.member_id as mid', // 账户ID - 2
- 'cm.username', // 账号 - 3
- 'cm.nickname', // 昵称 - 4
- 'cg.id as game_id', // 游戏ID - 5
- 'cg.name as game_name', // 游戏名 - 6
- 'nc.id as channel_id', // 推广员ID - 10
- 'nc.name as channel_name', // 推广员名称
- 'p1.id as business_id', // 子会长ID - 11
- 'p1.name as business_name', // 子会长名称
- 'p2.id as sub_president_id', // 会长ID - 12
- 'p2.name as sub_president_name', // 会长名称
- 'FROM_UNIXTIME(ns.create_time, "%Y-%m-%d %H:%i:%s") as reg_time', // 注册时间 - 14
- 'FROM_UNIXTIME(ns.update_time, "%Y-%m-%d %H:%i:%s") as login_time', // 登录时间 - 15
- ])
- ->paginate(null, false, ['page' => $input['page'] ?? 1, 'list_rows' => $input['limit'] ?? 100]);
- return json(["code" => 200, "msg" => 'success', "data" => $list ?? []]);
- }
- // 获取订单数据列表
- public function getPayList()
- {
- $input = input();
- $signRes = $this->sign($input);
- // dump($signRes);
- if (empty($input['sign']) || $signRes != $input['sign']) {
- return json(["code" => -110, "msg" => '签名有误!', "data" => []]);
- }
- if (empty($input['time_type'])) {
- return json(["code" => -111, "msg" => '参数错误,缺少 time_type 参数!', "data" => []]);
- }
- if (empty($input['start_time'])) {
- return json(["code" => -112, "msg" => '参数错误,缺少 start_time 参数!', "data" => []]);
- }
- if (empty($input['end_time'])) {
- return json(["code" => -113, "msg" => '参数错误,缺少 end_time 参数!', "data" => []]);
- }
- if(empty($input['limit']) && intval($input['limit']) > 1000){
- return json(["code" => -114, "msg" => '参数错误,limit参数不能大于1000!', "data" => []]);
- }
- // // 请求限流:一分钟三次(使用ThinkPHP5的Cache方式)
- // $limitKey = 'jh_api_getPayList_limit:' . md5(json_encode($input));
- // try {
- // $redis = Cache::store('redis')->handler();
- // $requestCount = $redis->incr($limitKey); // 原子递增
- // if ($requestCount === 1) {
- // $redis->expire($limitKey, 60);
- // }
- // if ($requestCount > 10) {
- // return json(["code" => -130, "msg" => '请求过于频繁!', "data" => []]);
- // }
- // } catch (\Exception $e) {
- // return json(["code" => -130, "msg" => '系统异常!', "data" => []]);
- // }
- // 处理日期:支持 '2026-02-13' 或 '2026-02-13 13:55:55' 两种格式
- $startTime = strtotime($input['start_time']);
- $endTime = strtotime($input['end_time']);
- $timeField = 'cp.create_time';
- if($input['time_type'] == 2){
- // 按照支付时间查询
- $timeField = 'cp.pay_time';
- }
- $where = [
- 'cp.status' => 1,
- 'nc.gh_status' => 1,
- $timeField => ['between', [$startTime, $endTime]],
- ];
- $payTypeList = config('paytype')??[];
- if(!$payTypeList){
- return json(["code" => -115, "msg" => '缺少支付配置,请联系开发处理!', "data" => []]);
- }
- // 查询测试账户ID列表(约10个,变化不频繁)
- $testMemberIds = Db::table('cy_members')
- ->where('test_status', 1)
- ->column('id');
- // 如果有测试账户,加入查询条件
- if (!empty($testMemberIds)) {
- $where['cp.userid'] = ['not in', $testMemberIds];
- }
- // 查询内容=账号/昵称/游戏ID/游戏名/推广员/子会长/公会/注册时间/登录时间/支付方式/支付金额/代金券金额/订单号/充值金额/发货状态/角色ID/角色名/区服名
- $list = Db::table('cy_pay')->alias('cp')
- ->join('nw_subaccount ns', 'cp.userid = ns.member_id AND cp.gameid=ns.game_id', 'left')
- ->join('cy_game cg', 'cp.gameid = cg.id', 'left')
- ->join('nw_channel nc', 'cp.channel_id = nc.id', 'left') // 推广员 (level 3)
- // ->join('nw_channel p1', 'nc.parent_id = p1.id', 'left') // 子会长
- // ->join('nw_channel p2', 'p1.parent_id = p2.id', 'left') // 会长
- ->where($where)
- ->field([
- 'cp.id',
- 'cp.orderid as order_id', // 订单号 - 0
- 'cp.username as account', // 账号 - 2
- // 'cm.nickname', // 昵称
- 'cp.gameid as game_id', // 游戏ID - 1
- 'cg.name as game_name', // 游戏名
- 'nc.id as channel_id', // 推广员ID - 13
- 'nc.name as channel_name', // 推广员名称
- // 'p1.id as business_id', // 子会长ID
- // 'p1.name as business_name', // 子会长名称
- // 'p2.id as sub_president_id', // 会长ID
- // 'p2.name as sub_president_name', // 会长名称
- // 'ns.create_time reg_time', // 注册时间
- // 'ns.update_time as login_time', // 登录时间
- 'cp.paytype as pay_method', // 支付方式 - 10
- // 'cp.real_amount as pay_amount', // 支付金额(人民币部分) - 9 - 删掉
- 'cp.real_amount', // 第三方支付金额(可能为空,因为有平台币支付)
- 'cp.pay_amount', // 实付金额(不会有空,订单支付价格,处理过折扣、代金卷)
- // ## 代金卷 ##
- 'cp.coupon_member_id', // 代金券ID
- 'cp.coupon_amount', // 代金券金额
- // ## 折扣 ##
- 'cp.discount', // 游戏折扣
- 'cp.amount as recharge_amount', // 充值金额(订单总金额) - 5
- 'cp.real_coin as real_ptb', // 平台币 - 6
- // 'cp.status as delivery_status', // 发货状态:0=未支付、1=已支付发货
- 'cp.roleid as role_id', // 角色ID - 21
- 'cp.rolename as role_name', // 角色名 - 17
- 'cp.servername as server_name', // 区服名 - 19
- 'FROM_UNIXTIME(cp.create_time, "%Y-%m-%d %H:%i:%s") as create_time', // 下单时间
- 'FROM_UNIXTIME(cp.pay_time, "%Y-%m-%d %H:%i:%s") as pay_time', // 支付时间 - 26
- 'paytype', // 支付方式
- 'client_type', // 客户端类型(1=祈盟sdk, 2=巨量, 3=快手磁力包)
- ])
- ->order('cp.id desc')
- ->paginate(null, false, ['page' => intval($input['page'] ?? 1), 'list_rows' => intval($input['limit'] ?? 100)])
- ->each(function($item, $key) use ($payTypeList){
- $item['pay_method'] = $payTypeList[$item['pay_method']] ?? $item['pay_method'];
- // ## 订单类型: 1=普通单、2=平台币、3=代金卷、4=折扣
- $pay_type = 1;
- if($item['real_ptb'] > 0){
- $pay_type = 2;
- } elseif ($item['coupon_member_id'] > 0 && $item['coupon_amount'] > 0){
- $pay_type = 3;
- } elseif ($item['discount'] > 0){
- $pay_type = 4;
- }
- $item['pay_form'] = $pay_type;
- $item['real_amount'] = $item['real_amount'];
- return $item;
- });
- // 统计当天的订单总数和订单总金额
- $total_amount = Db::table('cy_pay')->alias('cp')
- ->join('nw_channel nc', 'cp.channel_id = nc.id AND nc.gh_status=1')
- ->where($where)
- ->sum('cp.pay_amount');
- $total_amount = sprintf("%.2f", $total_amount ?? 0.00);
- $resultList = $list->toArray();
- $resultList['total_amount'] = (float)$total_amount; // 订单总金额
- return json(["code" => 200, "msg" => 'success', "data" => $resultList ?? []]);
- }
- /**
- * 获取玩家活跃数据列表。
- *
- * active_start_hour、active_end_hour 均按小时传入,结束小时包含在查询范围内。
- * 单次最多查询 24 个小时,并过滤测试账号和非聚合渠道。
- */
- public function getPlayerActive()
- {
- $input = input();
- $signRes = $this->sign($input);
- if (empty($input['sign']) || $signRes != $input['sign']) {
- return json(["code" => -110, "msg" => '签名有误!', "data" => []]);
- }
- $activeStartHour = trim($input['active_start_hour'] ?? '');
- $activeEndHour = trim($input['active_end_hour'] ?? '');
- if ($activeStartHour === '') {
- return json(["code" => -120, "msg" => '参数错误,缺少 active_start_hour 参数!', "data" => []]);
- }
- if ($activeEndHour === '') {
- return json(["code" => -120, "msg" => '参数错误,缺少 active_end_hour 参数!', "data" => []]);
- }
- // 支持 YYYY-MM-DD HH 和 YYYY-MM-DD HH:00:00 两种整点格式。
- if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}$/', $activeStartHour)) {
- $activeStartHour .= ':00:00';
- }
- if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}$/', $activeEndHour)) {
- $activeEndHour .= ':00:00';
- }
- $hourPattern = '/^\d{4}-\d{2}-\d{2} \d{2}:00:00$/';
- $startTimestamp = preg_match($hourPattern, $activeStartHour) ? strtotime($activeStartHour) : false;
- $endTimestamp = preg_match($hourPattern, $activeEndHour) ? strtotime($activeEndHour) : false;
- if (
- $startTimestamp === false
- || date('Y-m-d H:00:00', $startTimestamp) !== $activeStartHour
- || $endTimestamp === false
- || date('Y-m-d H:00:00', $endTimestamp) !== $activeEndHour
- ) {
- return json(["code" => -120, "msg" => '参数错误,活跃时间格式应为 YYYY-MM-DD HH 或 YYYY-MM-DD HH:00:00!', "data" => []]);
- }
- if ($startTimestamp > $endTimestamp) {
- return json(["code" => -120, "msg" => '参数错误,active_start_hour 不能晚于 active_end_hour!', "data" => []]);
- }
- // 结束小时包含在查询范围内,所以 SQL 上界取结束小时的下一整点(不包含)。
- $endExclusiveTimestamp = $endTimestamp + 3600;
- if (($endExclusiveTimestamp - $startTimestamp) > 24 * 3600) {
- return json(["code" => -120, "msg" => '参数错误,单次活跃时间范围不能超过 24 小时!', "data" => []]);
- }
- $page = intval($input['page'] ?? 1);
- $limit = intval($input['limit'] ?? 100);
- if ($page < 1) {
- return json(["code" => -120, "msg" => '参数错误,page 必须大于等于 1!', "data" => []]);
- }
- if ($limit < 1 || $limit > 1000) {
- return json(["code" => -120, "msg" => '参数错误,limit 必须在 1 到 1000 之间!', "data" => []]);
- }
- $gameId = intval($input['game_id'] ?? 0);
- $channelId = intval($input['channel_id'] ?? 0);
- if ($gameId < 0 || $channelId < 0) {
- return json(["code" => -120, "msg" => '参数错误,game_id 和 channel_id 不能为负数!', "data" => []]);
- }
- $where = [
- 'a.active_hour' => [
- ['>=', date('Y-m-d H:00:00', $startTimestamp)],
- ['<', date('Y-m-d H:00:00', $endExclusiveTimestamp)],
- ],
- ];
- if ($gameId > 0) {
- $where['a.game_id'] = $gameId;
- }
- if ($channelId > 0) {
- $where['a.channel_id'] = $channelId;
- }
- try {
- $list = Db::table('cy_player_active_log')->alias('a')
- ->join('cy_members m', 'm.id=a.member_id AND m.test_status=0')
- ->join('nw_channel channel', 'channel.id=a.channel_id AND channel.gh_status=1')
- // ->join('nw_channel channel', 'channel.id=a.channel_id')
- ->join('nw_game_server game_server', 'game_server.id=a.server_id AND game_server.game_id=a.game_id', 'left')
- ->field([
- 'a.id',
- 'a.member_id',
- 'a.subaccount_id',
- 'm.username',
- 'a.game_id',
- 'a.channel_id',
- 'channel.name as channel_name',
- 'a.server_id as server_pk',
- 'COALESCE(game_server.serverid, a.server_id) as server_id',
- 'COALESCE(game_server.servername, "") as server_name',
- 'a.role_id',
- 'a.role_name',
- 'a.role_level',
- 'a.active_hour',
- 'a.created_at',
- ])
- ->where($where)
- ->order('a.active_hour asc,a.id asc')
- ->paginate($limit, false, ['page' => $page]);
- return json(["code" => 200, "msg" => 'success', "data" => $list->toArray()]);
- } catch (\Exception $e) {
- log_message('getPlayerActive exception: ' . $e->getMessage(), 'error', LOG_PATH . 'jh_log/');
- return json(["code" => -500, "msg" => '系统异常,请联系开发处理!', "data" => []]);
- }
- }
- }
|