442 lines
14 KiB
PHP
442 lines
14 KiB
PHP
<?php
|
||
namespace app\common\service;
|
||
|
||
use app\common\model\User;
|
||
use app\common\model\Reward;
|
||
use app\common\model\CouponReceive;
|
||
use app\common\model\Coupon;
|
||
use app\common\model\Order;
|
||
use think\facade\Db;
|
||
use app\common\model\OrderListRecovery;
|
||
|
||
/**
|
||
* 排行榜服务类
|
||
*/
|
||
class RankService
|
||
{
|
||
|
||
/**
|
||
* 获取排行榜数据
|
||
* 支持:diamond(钻石排行榜)、integral(UU币排行榜)、dadajuan(达达卷排行榜)、invite(邀请新人排行榜)、loss(亏损补贴排行榜)
|
||
*
|
||
* @return \think\response\Json
|
||
*/
|
||
public function getRankList($type, $page, $limit)
|
||
{
|
||
|
||
// 验证排行榜类型是否有效
|
||
$validTypes = ['diamond', 'integral', 'dadajuan', 'invite', 'loss', 'loss_desc'];
|
||
if (!in_array($type, $validTypes)) {
|
||
throw new \Exception('无效的排行榜类型');
|
||
}
|
||
|
||
// 从配置助手获取排行榜时间设置
|
||
$timeSettings = \app\common\helper\ConfigHelper::getRankTime($type);
|
||
$startTime = !empty($timeSettings['start_time']) ? strtotime($timeSettings['start_time']) : 0;
|
||
$endTime = !empty($timeSettings['end_time']) ? strtotime($timeSettings['end_time']) : time();
|
||
|
||
|
||
$rankService = new \app\common\service\RankService();
|
||
// 初始化返回数据
|
||
$data = [];
|
||
|
||
// 根据不同排行榜类型查询数据
|
||
switch ($type) {
|
||
case 'diamond': // 钻石排行榜
|
||
$data = $rankService->getDiamondRank($startTime, $endTime, $page, $limit);
|
||
break;
|
||
|
||
case 'integral': // UU币排行榜
|
||
$data = $rankService->getIntegralRank($startTime, $endTime, $page, $limit);
|
||
break;
|
||
|
||
case 'dadajuan': // 达达卷排行榜
|
||
$data = $rankService->getDadajuanRank($startTime, $endTime, $page, $limit);
|
||
break;
|
||
|
||
case 'invite': // 邀请新人排行榜
|
||
$data = $rankService->getInviteRank($startTime, $endTime, $page, $limit);
|
||
break;
|
||
|
||
case 'loss': // 亏损补贴排行榜
|
||
$data = $rankService->getLossRank($startTime, $endTime, $page, $limit);
|
||
break;
|
||
case 'loss_desc'://亏损率排行榜
|
||
$data = $rankService->getLossRank($startTime, $endTime, $page, $limit, 'loss_rate');
|
||
break;
|
||
}
|
||
|
||
// 返回数据
|
||
return $data;
|
||
}
|
||
|
||
/**
|
||
* 获取钻石排行榜数据
|
||
*
|
||
* @param int $startTime 开始时间戳
|
||
* @param int $endTime 结束时间戳
|
||
* @param int $page 页码
|
||
* @param int $limit 每页数量
|
||
* @return array 排行榜数据
|
||
*/
|
||
public function getDiamondRank($startTime, $endTime, $page, $limit)
|
||
{
|
||
// 构建查询条件
|
||
$where = [
|
||
['status', '=', 1],
|
||
['use_money', '>', 0],
|
||
[
|
||
'user_id',
|
||
'not in',
|
||
function ($query) {
|
||
$query->name('user')->where('istest', '>', 0)->where('status', '=', 1)->field('id');
|
||
}
|
||
]
|
||
];
|
||
|
||
// 添加时间范围条件
|
||
if ($startTime > 0) {
|
||
$where[] = ['pay_time', '>=', $startTime];
|
||
}
|
||
if ($endTime > 0) {
|
||
$where[] = ['pay_time', '<=', $endTime];
|
||
}
|
||
|
||
// 查询数据
|
||
$list = Order::where($where)
|
||
->field('user_id, sum(use_money) as use_money')
|
||
->group('user_id')
|
||
->order('use_money desc')
|
||
->page($page, $limit)
|
||
->select()
|
||
->toArray();
|
||
|
||
// 处理用户信息
|
||
$rankList = [];
|
||
foreach ($list as $index => $item) {
|
||
$userInfo = User::field('nickname, headimg, mobile')->where('id', $item['user_id'])->find();
|
||
if ($userInfo) {
|
||
$rankList[] = [
|
||
'rank' => ($page - 1) * $limit + $index + 1,
|
||
'user_id' => $item['user_id'],
|
||
'nickname' => $userInfo['nickname'],
|
||
'headimg' => imageUrl($userInfo['headimg']),
|
||
'value' => $item['use_money'],
|
||
'unit' => '钻石'
|
||
];
|
||
}
|
||
}
|
||
|
||
return $rankList;
|
||
}
|
||
|
||
/**
|
||
* 获取UU币排行榜数据
|
||
*
|
||
* @param int $startTime 开始时间戳
|
||
* @param int $endTime 结束时间戳
|
||
* @param int $page 页码
|
||
* @param int $limit 每页数量
|
||
* @return array 排行榜数据
|
||
*/
|
||
public function getIntegralRank($startTime, $endTime, $page, $limit)
|
||
{
|
||
// 构建查询条件
|
||
$where = [
|
||
['status', '=', 1],
|
||
['use_integral', '>', 0],
|
||
[
|
||
'user_id',
|
||
'not in',
|
||
function ($query) {
|
||
$query->name('user')->where('istest', '>', 0)->where('status', '=', 1)->field('id');
|
||
}
|
||
]
|
||
];
|
||
|
||
// 添加时间范围条件
|
||
if ($startTime > 0) {
|
||
$where[] = ['pay_time', '>=', $startTime];
|
||
}
|
||
if ($endTime > 0) {
|
||
$where[] = ['pay_time', '<=', $endTime];
|
||
}
|
||
|
||
// 查询数据
|
||
$list = Order::where($where)
|
||
->field('user_id, sum(use_integral) as use_money')
|
||
->group('user_id')
|
||
->order('use_money desc')
|
||
->page($page, $limit)
|
||
->select()
|
||
->toArray();
|
||
|
||
// 处理用户信息
|
||
$rankList = [];
|
||
foreach ($list as $index => $item) {
|
||
$userInfo = User::field('nickname, headimg, mobile')->where('id', $item['user_id'])->find();
|
||
if ($userInfo) {
|
||
$rankList[] = [
|
||
'rank' => ($page - 1) * $limit + $index + 1,
|
||
'user_id' => $item['user_id'],
|
||
'nickname' => $userInfo['nickname'],
|
||
'headimg' => imageUrl($userInfo['headimg']),
|
||
'value' => $item['use_money'],
|
||
'unit' => 'UU币'
|
||
];
|
||
}
|
||
}
|
||
|
||
return $rankList;
|
||
}
|
||
|
||
/**
|
||
* 获取达达卷排行榜数据
|
||
*
|
||
* @param int $startTime 开始时间戳
|
||
* @param int $endTime 结束时间戳
|
||
* @param int $page 页码
|
||
* @param int $limit 每页数量
|
||
* @return array 排行榜数据
|
||
*/
|
||
public function getDadajuanRank($startTime, $endTime, $page, $limit)
|
||
{
|
||
// 构建查询条件
|
||
$where = [
|
||
['money', '>', 0],
|
||
[
|
||
'user_id',
|
||
'not in',
|
||
function ($query) {
|
||
$query->name('user')->where('istest', '>', 0)->where('status', '=', 1)->field('id');
|
||
}
|
||
]
|
||
];
|
||
|
||
// 添加时间范围条件
|
||
if ($startTime > 0) {
|
||
$where[] = ['addtime', '>=', $startTime];
|
||
}
|
||
if ($endTime > 0) {
|
||
$where[] = ['addtime', '<=', $endTime];
|
||
}
|
||
if($limit==10){
|
||
$limit=200;
|
||
}
|
||
$list = OrderListRecovery::where($where)
|
||
->field('user_id, sum(money) as use_money')
|
||
->group('user_id')
|
||
->order('use_money desc')
|
||
->page($page, $limit)
|
||
->select()
|
||
->toArray();
|
||
|
||
|
||
// 处理用户信息
|
||
$rankList = [];
|
||
foreach ($list as $index => $item) {
|
||
$userInfo = User::field('nickname, headimg, mobile')->where('id', $item['user_id'])->find();
|
||
if ($userInfo) {
|
||
$rankList[] = [
|
||
'rank' => ($page - 1) * $limit + $index + 1,
|
||
'user_id' => $item['user_id'],
|
||
'nickname' => $userInfo['nickname'],
|
||
'headimg' => imageUrl($userInfo['headimg']),
|
||
'value' => intval($item['use_money'] * 100),
|
||
'unit' => '达达卷'
|
||
];
|
||
}
|
||
}
|
||
|
||
return $rankList;
|
||
}
|
||
|
||
/**
|
||
* 获取邀请新人排行榜数据
|
||
*
|
||
* @param int $startTime 开始时间戳
|
||
* @param int $endTime 结束时间戳
|
||
* @param int $page 页码
|
||
* @param int $limit 每页数量
|
||
* @return array 排行榜数据
|
||
*/
|
||
public function getInviteRank($startTime, $endTime, $page, $limit)
|
||
{
|
||
// 构建查询条件
|
||
$where = [
|
||
['pid', '>', 0],
|
||
['istest', '=', 0], // 排除测试用户
|
||
['status', '=', 1] // 只查询状态正常的用户
|
||
];
|
||
|
||
// 添加时间范围条件
|
||
if ($startTime > 0) {
|
||
$where[] = ['addtime', '>=', $startTime];
|
||
}
|
||
if ($endTime > 0) {
|
||
$where[] = ['addtime', '<=', $endTime];
|
||
}
|
||
if($limit==10){
|
||
$limit=50;
|
||
}
|
||
// 查询数据
|
||
$list = User::where($where)
|
||
->field('pid, COUNT(1) as invite_count')
|
||
->group('pid')
|
||
->having('invite_count > 0')
|
||
->order('invite_count desc')
|
||
->page($page, $limit)
|
||
->select()
|
||
->toArray();
|
||
|
||
// 处理用户信息
|
||
$rankList = [];
|
||
foreach ($list as $index => $item) {
|
||
$userInfo = User::field('nickname, headimg, mobile')->where('id', $item['pid'])->find();
|
||
if ($userInfo) {
|
||
$rankList[] = [
|
||
'rank' => ($page - 1) * $limit + $index + 1,
|
||
'user_id' => $item['pid'],
|
||
'nickname' => $userInfo['nickname'],
|
||
'headimg' => imageUrl($userInfo['headimg']),
|
||
'value' => $item['invite_count'],
|
||
'unit' => '人'
|
||
];
|
||
}
|
||
}
|
||
|
||
return $rankList;
|
||
}
|
||
|
||
/**
|
||
* 获取亏损补贴排行榜数据
|
||
*
|
||
* @param int $startTime 开始时间戳
|
||
* @param int $endTime 结束时间戳
|
||
* @param int $page 页码
|
||
* @param int $limit 每页数量
|
||
* @return array 排行榜数据
|
||
*/
|
||
public function getLossRank($startTime, $endTime, $page, $limit, $sortField = 'loss_money')
|
||
{
|
||
// 构建订单条件
|
||
$orderWhere = [
|
||
['status', '=', 1],
|
||
[
|
||
'user_id',
|
||
'not in',
|
||
function ($query) {
|
||
$query->name('user')->where('istest', '>', 0)->field('id');
|
||
}
|
||
]
|
||
];
|
||
|
||
// 添加订单时间范围条件
|
||
if ($startTime > 0) {
|
||
$orderWhere[] = ['pay_time', '>=', $startTime];
|
||
}
|
||
if ($endTime > 0) {
|
||
$orderWhere[] = ['pay_time', '<=', $endTime];
|
||
}
|
||
|
||
// 查询订单数据,分组计算每个用户的消费金额
|
||
$orderData = Db::name('order')
|
||
->where($orderWhere)
|
||
->field('user_id, COALESCE(sum(price), 0) as money')
|
||
->group('user_id')
|
||
->select()
|
||
->toArray();
|
||
|
||
// 处理查询结果,计算每个用户的出货金额和达达卷金额
|
||
$userLossData = [];
|
||
foreach ($orderData as $order) {
|
||
$userId = $order['user_id'];
|
||
$money = $order['money']; // 微信消费金额
|
||
|
||
// 查询出货金额
|
||
$outputMoneyWhere = [];
|
||
if ($startTime > 0) {
|
||
$outputMoneyWhere[] = ['addtime', '>=', $startTime];
|
||
}
|
||
if ($endTime > 0) {
|
||
$outputMoneyWhere[] = ['addtime', '<=', $endTime];
|
||
}
|
||
$outputMoneyWhere[] = ['user_id', '=', $userId];
|
||
|
||
$outputMoney = Db::name('order_list')
|
||
->where($outputMoneyWhere)
|
||
->sum('goodslist_money');
|
||
|
||
// 查询达达卷金额
|
||
$dadaMoneyWhere = [];
|
||
if ($startTime > 0) {
|
||
$dadaMoneyWhere[] = ['addtime', '>=', $startTime];
|
||
}
|
||
if ($endTime > 0) {
|
||
$dadaMoneyWhere[] = ['addtime', '<=', $endTime];
|
||
}
|
||
$dadaMoneyWhere[] = ['user_id', '=', $userId];
|
||
|
||
$dadaMoney = Db::name('order_list_recovery')
|
||
->where($dadaMoneyWhere)
|
||
->sum('money');
|
||
|
||
// 如果dadaMoney为null,设置为0
|
||
$dadaMoney = $dadaMoney ?: 0;
|
||
|
||
// 计算亏损金额:(出货金额-(微信消费金额+达达卷金额))
|
||
$lossMoney = $outputMoney - ($money + $dadaMoney);
|
||
|
||
// 计算亏损率
|
||
$totalConsume = $money + $dadaMoney;
|
||
$lossRate = $totalConsume > 0 ? round(($lossMoney / $totalConsume) * 100, 2) : 0;
|
||
|
||
// 只有亏损的用户才添加到排行榜
|
||
if ($lossMoney < 0) {
|
||
$userLossData[] = [
|
||
'user_id' => $userId,
|
||
'consume_money' => $money, // 微信消费金额
|
||
'output_money' => $outputMoney, // 出货金额
|
||
'dada_money' => $dadaMoney, // 达达卷金额
|
||
'loss_money' => $lossMoney, // 亏损金额
|
||
'loss_rate' => $lossRate // 亏损率(%)
|
||
];
|
||
}
|
||
}
|
||
|
||
// 按亏损金额从小到大排序(因为亏损是负数,所以越小表示亏损越多)
|
||
usort($userLossData, function ($a, $b) {
|
||
return $a['loss_money'] <=> $b['loss_money'];
|
||
});
|
||
|
||
// 分页处理
|
||
$offset = ($page - 1) * $limit;
|
||
$userLossData = array_slice($userLossData, $offset, $limit);
|
||
|
||
// 处理用户信息和排名
|
||
$result = [];
|
||
foreach ($userLossData as $index => $item) {
|
||
$userInfo = User::field('nickname, headimg, mobile')->where('id', $item['user_id'])->find();
|
||
if ($userInfo) {
|
||
// 取亏损金额的绝对值来显示
|
||
$absoluteLossMoney = abs($item['loss_money']);
|
||
|
||
$result[] = [
|
||
'rank' => $offset + $index + 1,
|
||
'user_id' => $item['user_id'],
|
||
'nickname' => $userInfo['nickname'],
|
||
'headimg' => imageUrl($userInfo['headimg']),
|
||
'consume_money' => $item['consume_money'], // 微信消费金额
|
||
'dada_money' => $item['dada_money'], // 达达卷金额
|
||
'output_money' => $item['output_money'], // 出货金额
|
||
'value' => $absoluteLossMoney, // 主要展示值为亏损金额的绝对值
|
||
'loss_rate' => $item['loss_rate'], // 亏损率
|
||
'unit' => '元'
|
||
];
|
||
}
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
|
||
} |