* @version : HUOUNION 8.5 */ namespace huo\logic\data; use huo\logic\agent\AgentLogic; use huo\logic\member\MemberLogic; use huo\model\common\CommonModel; use huo\model\game\GameModel; use huo\model\log\MemLoginLogModel; use huo\model\member\MemberModel; use huo\model\member\MemoauthModel; use huo\model\member\MgRoleModel; use huo\model\order\OrderModel; use huo\model\user\UserModel; use huolib\constant\CacheConst; use huolib\constant\CommonConst; use huolib\constant\OrderConst; use huolib\tool\StrUtils; use huolib\tool\Time; use think\Cache; class StatisticsLogic extends CommonModel { protected $cache_key_prefix = CacheConst::CACHE_STATISTICS_DATA_PREFIX; protected $expire_time = 1; /** * @param array $param * * @return array */ protected function getWhere($param = []) { $_map = []; /* 时间搜索 */ list($_start_time, $_end_time) = $this->getTime($param); $_map['create_time'] = ['between', [$_start_time, $_end_time]]; if (!empty($param['agent_id'])) { if (is_array($param['agent_id'])) { if (in_array('in', $param['agent_id'])) { $_map['agent_id'] = $param['agent_id']; } else { $_map['agent_id'] = ['in', $param['agent_id']]; } } else { $_map['agent_id'] = $param['agent_id']; } // 官方渠道筛选 if ($param['agent_id'] == '-1') { $_map['agent_id'] = ['in', [0]]; } } if (!empty($param['app_id'])) { if (is_array($param['app_id'])) { if (in_array('in', $param['app_id'])) { $_map['app_id'] = $param['app_id']; } else { $_map['app_id'] = ['in', $param['app_id']]; } } else { $_map['app_id'] = $param['app_id']; } } return $_map; } public function getTime($param) { list($_start_time, $_end_time) = time::today(); $_start_time = 0; if (!empty($param['start_time'])) { $_start_time = strtotime($param['start_time']); } if (!empty($param['end_time'])) { $_end_time = strtotime($param['end_time']) + CommonConst::CONST_DAY_SECONDS; } return [$_start_time, $_end_time]; } public function getTodayData($where) { $where['start_time'] = $where['start_time'] = date('Y-m-d'); $_data = $this->getStatisticsData($where); $_data['date'] = $where['start_time']; return $_data; } /** * 获取聚合今日数据 * * @param $where * * @return array */ public function getStatisticsData($where) { list($_start_time, $_end_time) = $this->getTime($where); $_map = $this->getWhere($where); $_data_by_login = $this->getDataByLoginData($_map, $_start_time, $_end_time); $_data_by_member = $this->getDataByMember($_map, $_start_time, $_end_time); $_data_by_order = $this->getDataByOrder($_map, $_start_time, $_end_time); $_data = array_merge($_data_by_login, $_data_by_member, $_data_by_order); if ($_data['user_cnt'] < $_data['reg_cnt']) { $_data['user_cnt'] = $_data['reg_cnt']; } if ($_data['ip_cnt'] < $_data['reg_ip_cnt']) { $_data['ip_cnt'] = $_data['reg_ip_cnt']; } if ($_data['device_cnt'] < $_data['reg_device_cnt']) { $_data['device_cnt'] = $_data['reg_device_cnt']; } /* 新增付费率 */ if (isset($_data['reg_pay_cnt'])) { $_data['reg_pay_rate'] = StrUtils::getRate($_data['reg_pay_cnt'], $_data['reg_cnt']); /* 活跃付费率 */ $_data['user_pay_rate'] = StrUtils::getRate($_data['pay_user_cnt'], $_data['user_cnt']); /* 新增ARPU */ $_data['reg_arpu'] = StrUtils::getArpu($_data['reg_sum_money'], $_data['reg_cnt']); /* ARPU */ $_data['arppu'] = StrUtils::getArpu($_data['sum_money'], $_data['pay_user_cnt']); /* ARPPU */ $_data['arpu'] = StrUtils::getArpu($_data['sum_money'], $_data['user_cnt']); } if (!empty($where['app_id'])) { $_game_data = (new GameModel())->getInfoById($where['app_id']); $_data['game_name'] = get_val($_game_data, 'name', ''); $_data['game_icon'] = get_val($_game_data, 'icon', ''); $_data['classify'] = get_val($_game_data, 'classify', ''); } if (!empty($where['agent_id'])) { $_agent_info = (new UserModel())->getInfoById($where['agent_id']); $_data['agent_name'] = get_val($_agent_info, 'user_login', ''); $_data['agent_nickname'] = get_val($_agent_info, 'user_nicename', ''); } $_data['cpa_cnt'] = 0; /* cpa有效用户 */ $_role_map = [ 'start_time' => $_start_time, 'end_time' => $_end_time, 'app_id' => get_val($where, 'app_id', 0), 'agent_id' => get_val($where, 'agent_id', 0) ]; $_data['role_cnt'] = $this->getDayRole($_role_map); /* 创角数 */ $_data['openid_cnt'] = $this->getOpenidCnt($_role_map); /* 第三方注册用户 */ return $_data; } /** * 获取创角数 * * @param $param * * @return int|string */ public function getDayRole($param) { list($_start_time, $_end_time) = Time::today(); $_start_time = get_val($param, 'start_time', $_start_time); $_end_time = get_val($param, 'end_time', $_end_time); $_role_model = new MgRoleModel(); $_map = [ 'mg_role_model.create_time' => ['between', [$_start_time, $_end_time]], ]; $_app_id = get_val($param, 'app_id', 0); if (!empty($_app_id)) { $_map['mg_role_model.app_id'] = $_app_id; } $_agent_id = get_val($param, 'agent_id', 0); $_mem_ids = []; if (!empty($_agent_id)) { if (-1 == $_agent_id) { $_mem_ids = (new MemberLogic())->getIdsByAgentId(0); //$_map['mg.mem_id'] = ['in', $_mem_ids]; } else { if (is_array($_agent_id)) { $_agent_mem_ids = (new MemberLogic())->getIdsByAgentId($_agent_id); } else { $_agent_ids = (new AgentLogic())->getAgentIds($_agent_id, true); $_agent_mem_ids = (new MemberLogic())->getIdsByAgentId(['in', $_agent_ids]); } $_mem_ids = $_agent_mem_ids; } if (empty($_mem_ids)) { return 0; } } if ($_start_time != strtotime(date('Y-m-d'))) { $_role_mem_ids = $_role_model->with('mg')->where($_map)->cache(CommonConst::CONST_MONTH_SECONDS) ->column('mem_id'); } else { $_role_mem_ids = $_role_model->with('mg')->where($_map)->column('mem_id'); } if (!empty($_mem_ids)) { $_role_mem_ids = array_intersect($_role_mem_ids, $_mem_ids); } return count($_role_mem_ids); } /** * 获取单条记录缓存key * * @param array $where 条件 * * @return string */ protected function getCacheKeyByLoginData($where) { return $this->cache_key_prefix.'ld_'.md5(json_encode($where)); } /** * 获取单条记录缓存key * * @param array $where 条件 * * @return string */ protected function getCacheKeyByMember($where) { return $this->cache_key_prefix.'m_'.md5(json_encode($where)); } /** * 获取单条记录缓存key * * @param array $where 条件 * * @return string */ protected function getCacheKeyByMemberRetain($where) { return $this->cache_key_prefix.'mr_'.md5(json_encode($where)); } /** * 获取单条记录缓存key * * @param array $where 条件 * * @return string */ protected function getCacheKeyByOpenidCnt($where) { return $this->cache_key_prefix.'oc_'.md5(json_encode($where)); } /** * 获取第三方注册数 * * @param $param * * @return mixed */ public function getOpenidCnt($param) { /* 缓存操作 */ $_cache_key = $this->getCacheKeyByOpenidCnt($param); $_data = Cache::get($_cache_key); if (!empty($_data)) { return $_data; } list($_start_time, $_end_time) = Time::today(); $_start_time = get_val($param, 'start_time', $_start_time); $_end_time = get_val($param, 'end_time', $_end_time); $_map = [ 'ljmem.create_time' => ['between', [$_start_time, $_end_time]], ]; $_app_id = get_val($param, 'app_id', 0); if (!empty($_app_id)) { $_map['app_id'] = $_app_id; } $_agent_id = get_val($param, 'agent_id', 0); if (!empty($_agent_id)) { if (-1 == $_agent_id) { $_map['agent_id'] = 0; } else { $_map['agent_id'] = $_agent_id; } } $_cnt = (new MemoauthModel())->with('ljmem')->where($_map)->count('DISTINCT mem_id'); if (!empty($_cnt)) { Cache::set($_cache_key, $_cnt, $this->expire_time); } return $_cnt; } /** * 'user_cnt' 活跃玩家数量 * 'ip_cnt' IP数量 * 'device_cnt' 设备数量 * * @param array $where * * @param string $start_time 开始时间 * @param string $end_time 结束时间 * * @return array */ public function getDataByLoginData($where, $start_time, $end_time) { $_date = date('Y-m', $start_time); $_date_end = date('Y-m', $end_time); $_cache_where = $where; $_map = $where; /* 缓存操作 */ $_cache_key = $this->getCacheKeyByLoginData($_cache_where); $_data = Cache::get($_cache_key); if (!empty($_data)) { return $_data; } $_field = [ 'count(distinct(`mem_id`))' => 'user_cnt', 'count(distinct(`device_id`))' => 'device_cnt', 'count(distinct(`ip`))' => 'ip_cnt', ]; $_model = new MemLoginLogModel(); $_data = $_model->computeTable($_date)->field($_field)->where($_map)->find(); if (is_object($_data)) { $_data = $_data->toArray(); } if (empty($_data)) { $_data = [ 'user_cnt' => 0, 'device_cnt' => 0, 'ip_cnt' => 0, ]; } if ($_date_end != $_date) { $_data2 = $_model->computeTable($_date_end)->field($_field)->where($_map)->find(); if (is_object($_data2)) { $_data2 = $_data2->toArray(); } if (!empty($_data2)) { $_data['user_cnt'] += $_data2['user_cnt']; $_data['device_cnt'] += $_data2['device_cnt']; $_data['ip_cnt'] += $_data2['ip_cnt']; } } if (empty($_data)) { return []; } Cache::set($_cache_key, $_data, $this->expire_time); return $_data; } /** * 'history_user_cnt' 注册玩家数 * 'reg_cnt' 注册玩家数 * 'reg_device_cnt' 新增设备 * 'reg_ip_cnt' 新增IP * * @param array $where 条件 * @param string $start_time 开始时间 * @param string $end_time 结束时间 * * @return array */ public function getDataByMember($where = [], $start_time = 0, $end_time = 0) { $_cache_where = $where; $_map = $where; /* 缓存操作 */ $_cache_key = $this->getCacheKeyByMember($_cache_where); $_data = Cache::get($_cache_key); if (!empty($_data)) { return $_data; } $_model = (new MemberModel()); $_field = [ 'count(distinct(`id`))' => 'reg_cnt', 'count(distinct(`device_id`))' => 'reg_device_cnt', 'count(distinct(`reg_ip`))' => 'reg_ip_cnt', ]; $_data = $_model->field($_field)->where($_map)->find(); if (is_object($_data)) { $_data = $_data->toArray(); } if (empty($_data)) { $_data = [ 'reg_cnt' => 0, 'reg_device_cnt' => 0, 'reg_ip_cnt' => 0, ]; } $_data['history_user_cnt'] = $_model->getRegisterCount(0, $end_time, $_map); Cache::set($_cache_key, $_data, $this->expire_time); return $_data; } /** * 通过订单获取今日数据 * 'pay_user_cnt' 付费玩家数 * 'order_cnt' 成功订单数 * 'fail_order_cnt' 失败订单数 * 'un_order_cnt' 待支付订单数 * 'reg_order_cnt' 新增订单 * 'reg_pay_cnt' 新增即付费人数 * 'sum_money' 充值金额 * 'sum_real_money' 充值流水 * 'first_pay_cnt' 首次付费人数 * 'first_pay_money' 首付金额 * 'reg_sum_money' 新增即付总额 * 'reg_real_sum_money' 自然流水金额 * * @param array $where * * @param int $start_time 开始时间 * @param int $end_time 结束时间 * * @return array */ public function getDataByOrder($where = [], $start_time = 0, $end_time = 0) { $_cache_where = $where; $_map = $where; /* 缓存操作 */ $_cache_key = $this->getCacheKeyByMemberRetain($_cache_where); $_data = Cache::get($_cache_key); if (!empty($_data)) { return $_data; } $_model = (new OrderModel()); $_map_order_cnt = $_map; $_map_pay_user_cnt = $_map; $_map_pay_user_cnt['status'] = OrderConst::PAY_STATUS_SUC; $_map_order_cnt['status'] = OrderConst::PAY_STATUS_SUC; $_map_fail_order_cnt['status'] = OrderConst::PAY_STATUS_FAIL; $_map_un_order_cnt['status'] = OrderConst::PAY_STATUS_NOT; $_data = [ 'pay_user_cnt' => $_model->where($_map_pay_user_cnt)->count('distinct mem_id'), 'order_cnt' => $_model->where($_map_order_cnt)->count('id'), 'fail_order_cnt' => $_model->where($_map_fail_order_cnt)->count('id'), 'un_order_cnt' => $_model->where($_map_un_order_cnt)->count('id'), 'sum_money' => $_model->where($_map_order_cnt)->sum('amount'), 'sum_real_money' => $_model->where($_map_order_cnt)->sum('real_amount'), ]; $_where_str = 'uo.`status` =2 and uo.create_time between '.$start_time.' AND '.$end_time .' and m.create_time between '.$start_time.' AND '.$end_time; if (!empty($_map['agent_id'])) { if (is_array($_map['agent_id'])) { $_where_str .= ' and uo.agent_id in ('.implode(',', $_map['agent_id'][1]).')'; } else { $_where_str .= ' and uo.agent_id='.$_map['agent_id']; } } if (!empty($_map['app_id'])) { if (is_array($_map['app_id'])) { $_where_str .= ' and uo.app_id in ('.implode(',', $_map['app_id'][1]).')'; } else { $_where_str .= ' and uo.app_id='.$_map['app_id']; } } $_sql = 'SELECT count(DISTINCT(uo.id)) AS reg_order_cnt, count(DISTINCT(uo.mem_id)) AS reg_pay_cnt, sum(uo.amount) AS reg_sum_money, sum(uo.real_amount) AS reg_real_sum_money FROM h_pay uo INNER JOIN h_member m ON m.id=uo.mem_id WHERE '.$_where_str; $_sql_data = db()->query($_sql); $_reg_data = $_sql_data[0]; $_data = array_merge($_data, $_reg_data); if (empty($_data)) { $_data = [ 'pay_user_cnt' => 0, 'order_cnt' => 0, 'fail_order_cnt' => 0, 'un_order_cnt' => 0, 'sum_money' => 0, 'sum_real_money' => 0, 'reg_order_cnt' => 0, 'reg_pay_cnt' => 0, 'reg_sum_money' => 0, 'reg_real_sum_money' => 0 ]; } if (empty($_data['reg_sum_money'])) { $_data['reg_sum_money'] = 0; } Cache::set($_cache_key, $_data, $this->expire_time); return $_data; } }