添加限制

This commit is contained in:
youda 2025-04-12 06:27:11 +08:00
parent 04c6b70377
commit 2761218f2a
16 changed files with 940 additions and 371 deletions

View File

@ -212,6 +212,11 @@ class Config extends Base
//清除排行榜设置缓存
\app\common\helper\ConfigHelper::clearRankSettingsCache();
}
if ($data['key'] == 'app_setting') {
//清除redis缓存app_setting
$redis = new RedisHelper();
($redis->getRedis())->del('config:app_setting');
}
$result = setConfig($data['key'], $data);
if ($result) {

View File

@ -538,7 +538,7 @@ class User extends Base
$profit_loss_total = 0;
$money = 0;
foreach ($data['list'] as $k => &$v) {
#公式 (充值余额 + 吧唧币 + 微信支付 - 余额 - 背包赏品
#公式 (充值余额 + 币 + 微信支付 - 余额 - 背包赏品
$cz_money = ProfitMoney::field('change_money')->where('user_id', '=', $v['id'])->where('type', '=', 1)->where('change_money', '>', 0)->where($where)->sum('change_money');
$wx_money = ProfitMoney::field('change_money')->where('user_id', '=', $v['id'])->where('type', '=', 2)->where('change_money', '>', 0)->where($where)->sum('change_money');
$cz_yue = $cz_money + $wx_money;

View File

@ -0,0 +1,81 @@
<?php
namespace app\admin\controller;
use app\admin\controller\Base;
use \think\Request;
use think\facade\View;
use app\common\model\User;
use app\common\service\RankService;
class UserRank extends Base
{
/**
* 用户排行榜页面
*/
public function index()
{
// 当前选中的排行榜类型,默认为邀请新人排行榜
$type = request()->param('type', 'invite');
// 页码和每页显示条数
$page = request()->param('page/d', 1);
$limit = request()->param('limit/d', 15);
// 排序字段,主要用于亏损排行榜可按亏损金额或亏损率排序
$sortField = request()->param('sort_field', 'loss_money');
// 获取排行榜服务类
$rankService = new RankService();
// 获取排行榜数据
try {
// 亏损排行榜需要额外传入排序字段
if ($sortField != 'loss_money') {
$data = $rankService->getRankList('loss_desc', $page, $limit);
} else {
$data = $rankService->getRankList($type, $page, $limit);
}
// 向模板传递变量
View::assign('list', $data);
View::assign('type', $type);
View::assign('page', $page);
View::assign('limit', $limit);
View::assign('sort_field', $sortField);
return View::fetch('user_rank/index');
} catch (\Exception $e) {
// 异常处理
return $this->renderError($e->getMessage());
}
}
/**
* 异步加载排行榜数据接口
*/
public function getRankData()
{
// 获取参数
$type = request()->param('type', 'invite');
$page = request()->param('page/d', 1);
$limit = request()->param('limit/d', 15);
$sortField = request()->param('sort_field', 'loss_money');
// 获取排行榜服务类
$rankService = new RankService();
try {
// 亏损排行榜需要额外传入排序字段
if ($type == 'loss') {
$data = $rankService->getLossRank(0, 0, $page, $limit, $sortField);
} else {
$data = $rankService->getRankList($type, $page, $limit);
}
return $this->renderSuccess('获取成功', $data);
} catch (\Exception $e) {
return $this->renderError($e->getMessage());
}
}
}

View File

@ -397,3 +397,9 @@ Route::post('sign_config_delete', 'SignConfig/delete');
Route::post('sign_config_sort', 'SignConfig/sort');
Route::post('sign_config_status', 'SignConfig/status');
Route::get('sign_config_coupons', 'SignConfig/getCoupons');
#============================
#UserRank.php用户排行榜
#============================
Route::rule('user_rank', 'UserRank/index', 'GET');
Route::rule('user_rank_data', 'UserRank/getRankData', 'GET');

View File

@ -29,7 +29,7 @@
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">商城兑换次数</label>
<label class="layui-form-label">商城购买次数</label>
<div class="layui-input-block">
<input type="number" name="exchange_times"
value="{$app_setting.exchange_times|default=0}" autocomplete="off"
@ -168,6 +168,24 @@
<div class="layui-form-mid layui-word-aux">每日免费送抽奖的ID设置为0表示不启用</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">盒柜兑换次数限制</label>
<div class="layui-input-block">
<input type="number" name="cabinet_exchange_limit"
value="{$app_setting.cabinet_exchange_limit|default=0}" autocomplete="off"
class="layui-input" min="0">
<div class="layui-form-mid layui-word-aux">每天允许盒柜兑换的次数0表示不限制次数</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">每天优惠券次数</label>
<div class="layui-input-block">
<input type="number" name="daily_coupon_limit"
value="{$app_setting.daily_coupon_limit|default=0}" autocomplete="off"
class="layui-input" min="0">
<div class="layui-form-mid layui-word-aux">每天允许使用优惠券的次数0表示不限制次数</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="app-setting-form">保存</button>
@ -396,6 +414,40 @@
</div>
</div>
<!-- 亏损补贴排行榜 -->
<fieldset class="layui-elem-field layui-field-title">
<legend>亏损补贴排行榜</legend>
</fieldset>
<div class="layui-form-item">
<label class="layui-form-label">统计方式</label>
<div class="layui-input-block">
<input type="radio" name="loss_stat_type" value="daily" title="每天统计" lay-filter="loss_stat_type"
{if !isset($rank_setting.loss_stat_type) || $rank_setting.loss_stat_type=='daily'}checked{/if}>
<input type="radio" name="loss_stat_type" value="weekly" title="每周统计" lay-filter="loss_stat_type"
{if isset($rank_setting.loss_stat_type) && $rank_setting.loss_stat_type=='weekly'}checked{/if}>
<input type="radio" name="loss_stat_type" value="monthly" title="每月统计" lay-filter="loss_stat_type"
{if isset($rank_setting.loss_stat_type) && $rank_setting.loss_stat_type=='monthly'}checked{/if}>
<input type="radio" name="loss_stat_type" value="yearly" title="每年统计" lay-filter="loss_stat_type"
{if isset($rank_setting.loss_stat_type) && $rank_setting.loss_stat_type=='yearly'}checked{/if}>
<input type="radio" name="loss_stat_type" value="custom" title="自定义时间范围" lay-filter="loss_stat_type"
{if isset($rank_setting.loss_stat_type) && $rank_setting.loss_stat_type=='custom'}checked{/if}>
</div>
</div>
<div class="layui-form-item loss-time-range" {if !isset($rank_setting.loss_stat_type) || $rank_setting.loss_stat_type!='custom'}style="display:none"{/if}>
<label class="layui-form-label">开始时间</label>
<div class="layui-input-inline">
<input type="text" name="loss_start_time" id="loss_start_time"
value="{$rank_setting.loss_start_time|default=''}" autocomplete="off"
class="layui-input" placeholder="不填则不限制开始时间">
</div>
<label class="layui-form-label">结束时间</label>
<div class="layui-input-inline">
<input type="text" name="loss_end_time" id="loss_end_time"
value="{$rank_setting.loss_end_time|default=''}" autocomplete="off"
class="layui-input" placeholder="不填则不限制结束时间">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="rank-setting-form">保存</button>
@ -788,6 +840,16 @@
type: 'date'
});
laydate.render({
elem: '#loss_start_time',
type: 'date'
});
laydate.render({
elem: '#loss_end_time',
type: 'date'
});
// 监听排行榜统计方式的选择变化
form.on('radio(dadajuan_stat_type)', function(data){
if(data.value === 'custom'){
@ -821,6 +883,14 @@
}
});
form.on('radio(loss_stat_type)', function(data){
if(data.value === 'custom'){
$('.loss-time-range').show();
} else {
$('.loss-time-range').hide();
}
});
// 复制并下载JSON格式按钮点击事件
$('#copy-download-json').on('click', function () {
// 获取app-setting-form表单的所有值

View File

@ -40,7 +40,7 @@
<th>总金额</th>
<th>微信支付</th>
<th>消费余额</th>
<th>吧唧</th>
<th>UU</th>
</tr>
</thead>
<tbody>

View File

@ -62,13 +62,12 @@
{{# if(item.reward_type == 1){ }}
<span class="layui-badge layui-bg-blue">钻石: {{item.reward_value}}</span>
{{# } else if(item.reward_type == 2){ }}
<span class="layui-badge layui-bg-green">货币1: {{item.reward_value}}</span>
<span class="layui-badge layui-bg-green">UU币: {{item.reward_value}}</span>
{{# } else if(item.reward_type == 3){ }}
<span class="layui-badge layui-bg-orange">货币2: {{item.reward_value}}</span>
<span class="layui-badge layui-bg-orange">达达卷: {{item.reward_value}}</span>
{{# } else if(item.reward_type == 4){ }}
<span class="layui-badge layui-bg-red">优惠券</span>
{{# } }}
{{# }); }}
{{# } else { }}
<span class="layui-text">无奖励</span>

View File

@ -13,7 +13,6 @@
<input type="hidden" name="reward_id" value="{$reward_id}">
<div class="layui-form" wid100 lay-filter="editForm">
<div class="layui-form-item">
<label class="layui-form-label">奖励信息</label>
<div class="layui-input-inline" style="width:600px">

View File

@ -0,0 +1,141 @@
{include file="Public:header2"/}
<body>
<div class="layui-fluid">
<div class="layui-row layui-col-space15">
<div class="layui-col-md12">
<div class="layui-card">
<div class="layui-card-header">用户排行榜</div>
<div class="layui-card-body">
<!-- 排行榜类型选择 -->
<div class="layui-form">
<div class="layui-form-item">
<div class="layui-input-block" style="margin-left: 0;">
<input type="radio" name="rank_type" value="invite" title="邀请新人排行榜" {if $type=='invite'}checked{/if} lay-filter="rank_type">
<input type="radio" name="rank_type" value="loss" title="亏损补贴排行榜" {if $type=='loss'}checked{/if} lay-filter="rank_type">
<input type="radio" name="rank_type" value="dadajuan" title="达达卷排行榜" {if $type=='dadajuan'}checked{/if} lay-filter="rank_type">
<input type="radio" name="rank_type" value="diamond" title="钻石排行榜" {if $type=='diamond'}checked{/if} lay-filter="rank_type">
<input type="radio" name="rank_type" value="integral" title="UU币排行榜" {if $type=='integral'}checked{/if} lay-filter="rank_type">
</div>
</div>
</div>
<!-- 亏损排行榜排序选项 -->
<div class="layui-form loss-sort-option" {if $type!='loss'}style="display:none;"{/if}>
<div class="layui-form-item">
<label class="layui-form-label">排序方式:</label>
<div class="layui-input-inline">
<select name="sort_field" lay-filter="sort_field">
<option value="loss_money" {if $sort_field=='loss_money'}selected{/if}>亏损金额</option>
<option value="loss_rate" {if $sort_field=='loss_rate'}selected{/if}>亏损率</option>
</select>
</div>
</div>
</div>
<!-- 数据表格 -->
<table class="layui-table">
<thead>
<tr>
<th>排名</th>
<th>用户ID</th>
<th>用户昵称</th>
<th>头像</th>
<th class="value-title">
{if $type=='invite'}邀请人数
{elseif $type=='loss'}亏损金额
{elseif $type=='dadajuan'}达达卷数量
{elseif $type=='diamond'}钻石数量
{elseif $type=='integral'}UU币数量
{/if}
</th>
<!-- 亏损排行榜特有的列 -->
{if $type=='loss'}
<th>消耗金额</th>
<th>出货金额</th>
<th>亏损率</th>
{/if}
</tr>
</thead>
<tbody>
{volist name="list" id="vo"}
<tr>
<td>{$vo.rank}</td>
<td>{$vo.user_id}</td>
<td>{$vo.nickname}</td>
<td>
<img src="{$vo.headimg}" style="width: 40px; height: 40px; border-radius: 50%;">
</td>
<td class="value-content">{$vo.value} {$vo.unit}</td>
<!-- 亏损排行榜特有的列 -->
{if $type=='loss'}
<td>{$vo.consume_money} 元</td>
<td>{$vo.output_money} 元</td>
<td>{$vo.loss_rate}%</td>
{/if}
</tr>
{/volist}
</tbody>
</table>
<!-- 分页 -->
<div id="page"></div>
</div>
</div>
</div>
</div>
</div>
{include file="Public:footer"/}
<script>
layui.use(['form', 'laypage'], function() {
var form = layui.form;
var laypage = layui.laypage;
// 排行榜类型切换
form.on('radio(rank_type)', function(data) {
var type = data.value;
// 亏损补贴排行榜时显示排序选项
if (type === 'loss') {
$('.loss-sort-option').show();
} else {
$('.loss-sort-option').hide();
}
// 跳转到对应类型的排行榜页面
window.location.href = '{:url("/admin/user_rank")}?type=' + type +
'&sort_field=' + (type === 'loss' ? $('select[name="sort_field"]').val() : 'loss_money');
});
// 排序方式切换
form.on('select(sort_field)', function(data) {
var sortField = data.value;
window.location.href = '{:url("/admin/user_rank")}?type=loss&sort_field=' + sortField;
});
// 初始化分页
laypage.render({
elem: 'page',
count: {$list|count},
limit: {$limit},
curr: {$page},
layout: ['count', 'prev', 'page', 'next', 'limit', 'skip'],
jump: function(obj, first) {
if (!first) {
// 页码或每页显示条数变更时,跳转到对应页
var url = '{:url("/admin/user_rank")}?type={$type}';
url += '&page=' + obj.curr;
url += '&limit=' + obj.limit;
if ('{$type}' === 'loss') {
url += '&sort_field={$sort_field}';
}
window.location.href = url;
}
}
});
});
</script>
</body>
</html>

View File

@ -228,7 +228,7 @@ class Index extends Base
/**
* 获取排行榜数据
* 支持diamond(钻石排行榜)、integral(UU币排行榜)、dadajuan(达达卷排行榜)、invite(邀请新人排行榜)
* 支持diamond(钻石排行榜)、integral(UU币排行榜)、dadajuan(达达卷排行榜)、invite(邀请新人排行榜)、loss(亏损补贴排行榜)
*
* @return \think\response\Json
*/
@ -238,280 +238,18 @@ class Index extends Base
$type = request()->param('type', '');
// 验证排行榜类型是否有效
$validTypes = ['diamond', 'integral', 'dadajuan', 'invite'];
$validTypes = ['diamond', 'integral', 'dadajuan', 'invite', 'loss'];
if (!in_array($type, $validTypes)) {
return $this->renderError('无效的排行榜类型');
}
// 从配置助手获取排行榜时间设置
$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();
// 设置分页参数
$page = request()->param('page/d', 1);
$limit = request()->param('limit/d', 10);
// 初始化返回数据
$data = [];
// 根据不同排行榜类型查询数据
switch ($type) {
case 'diamond': // 钻石排行榜
$data = $this->getDiamondRank($startTime, $endTime, $page, $limit);
break;
case 'integral': // UU币排行榜
$data = $this->getIntegralRank($startTime, $endTime, $page, $limit);
break;
case 'dadajuan': // 达达卷排行榜
$data = $this->getDadajuanRank($startTime, $endTime, $page, $limit);
break;
case 'invite': // 邀请新人排行榜
$data = $this->getInviteRank($startTime, $endTime, $page, $limit);
break;
}
// 初始化排行榜服务类
$rankService = new \app\common\service\RankService();
$data = $rankService->getRankList($type, $page, $limit);
// 返回数据
return $this->renderSuccess('请求成功', $data);
}
/**
* 获取钻石排行榜数据
*
* @param int $startTime 开始时间戳
* @param int $endTime 结束时间戳
* @param int $page 页码
* @param int $limit 每页数量
* @return array 排行榜数据
*/
private 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 排行榜数据
*/
private 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 排行榜数据
*/
private function getDadajuanRank($startTime, $endTime, $page, $limit)
{
// 构建查询条件
$where = [
['status', '=', 1],
['use_money2', '>', 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_money2) 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;
}
/**
* 获取邀请新人排行榜数据
*
* @param int $startTime 开始时间戳
* @param int $endTime 结束时间戳
* @param int $page 页码
* @param int $limit 每页数量
* @return array 排行榜数据
*/
private 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];
}
// 查询数据
$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;
}
}

View File

@ -582,6 +582,18 @@ class Warehouse extends Base
if (empty($recovery_info)) {
return $this->renderError("请选择兑换的赏品");
}
$cabinet_exchange_limit = \app\common\helper\ConfigHelper::getAppSettingKey("cabinet_exchange_limit");
if($cabinet_exchange_limit>0){
$today_start = strtotime(date('Y-m-d 00:00:00', time()));
$today_end = strtotime(date('Y-m-d 23:59:59', time()));
$today_count = OrderListRecovery::where('user_id', '=', $user_id)
->where('addtime', '>=', $today_start)
->where('addtime', '<=', $today_end)
->count();
if($today_count>=$cabinet_exchange_limit){
return $this->renderError("今日兑换次数已达上限");
}
}
#装换结构
$recovery_info = json_decode($recovery_info, true);
$order_list_id = [];

View File

@ -26,6 +26,46 @@ class ConfigHelper
*/
private static $rankSettings = null;
private static $appSetting = null;
/**
* 获取应用设置
*
* @return array 应用设置
*/
public static function getAppSetting()
{
if (self::$appSetting !== null) {
return self::$appSetting;
}
$redis = new RedisHelper();
$cachedValue = $redis->get('config:app_setting');
if ($cachedValue !== false) {
self::$appSetting = json_decode($cachedValue, true);
return self::$appSetting;
}
$app_setting = getConfig('app_setting');
if ($app_setting) {
self::$appSetting = $app_setting;
$redis->set('config:app_setting', json_encode($app_setting), 86400);
return self::$appSetting;
}
return [];
}
/**
* 获取应用设置的key值
*
* @param string $key 配置键名
* @return mixed 配置值
*/
public static function getAppSettingKey($key)
{
$appSetting = self::getAppSetting();
return $appSetting[$key] ?? null;
}
/**
* 获取无限赏抽奖倍数
* 从数据库中查询key为infinite_multiple的配置获取multiple字段
@ -33,8 +73,8 @@ class ConfigHelper
*
* @return int 抽奖倍数默认为1000
*/
public static function getInfiniteMultiple()
{
public static function getInfiniteMultiple(
) {
// 如果静态属性已有值,直接返回
if (self::$infiniteMultiple !== null) {
return self::$infiniteMultiple;
@ -155,6 +195,16 @@ class ConfigHelper
$startKey = 'invite_start_time';
$endKey = 'invite_end_time';
break;
case 'loss':
$statTypeKey = 'loss_stat_type';
$startKey = 'loss_start_time';
$endKey = 'loss_end_time';
break;
case 'loss_desc':
$statTypeKey = 'loss_stat_type';
$startKey = 'loss_start_time';
$endKey = 'loss_end_time';
break;
default:
return [
'stat_type' => 'daily',

View File

@ -85,9 +85,24 @@ class PaymentCalculator
$use_integral = 0; // 货币1抵扣
$use_money2 = 0; // 货币2抵扣
$zhe = 0; // 会员折扣
$daily_coupon_limit = \app\common\helper\ConfigHelper::getAppSettingKey("daily_coupon_limit");
// 优惠券处理
if ($shou_zhe_price <= 0 && !empty($coupon_id) && $goodsExtend['pay_coupon'] == 1) {
//是否限制每日优惠券次数
$is_daily_coupon = true;
if ($daily_coupon_limit > 0) {
$today_start = strtotime(date('Y-m-d 00:00:00', time()));
$today_end = strtotime(date('Y-m-d 23:59:59', time()));
$today_count = CouponReceiveModel::where('user_id', '=', $user['id'])
->where('addtime', '>=', $today_start)
->where('addtime', '<=', $today_end)
->count();
if ($today_count >= $daily_coupon_limit) {
// return ['status' => 0, 'msg' => '今日优惠券次数已达上限'];
$is_daily_coupon = false;
}
}
if ($is_daily_coupon) {
// 获取优惠券信息
$coupon = CouponReceiveModel::where([
'id' => $coupon_id,
@ -105,6 +120,9 @@ class PaymentCalculator
}else{
$coupon_id = 0;
}
} else {
$coupon_id = 0;
}
$price = bcsub("$price", "$coupon_price", 2);
if ($price <= 0) {
@ -220,7 +238,8 @@ class PaymentCalculator
'coupon_id' => $coupon_id,
'coupon_price' => round($coupon_price, 2),
'goods_extend' => $goodsExtend,
'use_money2' => $use_money2
'use_money2' => $use_money2,
'daily_coupon_limit' => $daily_coupon_limit
];
// 添加首抽五折状态

View File

@ -0,0 +1,445 @@
<?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;
/**
* 排行榜服务类
*/
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 = [
['status', '=', 1],
['use_money2', '>', 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_money2) 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;
}
/**
* 获取邀请新人排行榜数据
*
* @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];
}
// 查询数据
$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 每页数量
* @param string $sortField 排序字段loss_money(亏损金额)或loss_rate(亏损率)
* @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)->where('status', '=', 1)->field('id');
}
]
];
// 添加订单时间范围条件
if ($startTime > 0) {
$orderWhere[] = ['pay_time', '>=', $startTime];
}
if ($endTime > 0) {
$orderWhere[] = ['pay_time', '<=', $endTime];
}
// 构建订单详情查询条件
$orderListWhere = [];
if ($startTime > 0) {
$orderListWhere[] = ['addtime', '>=', $startTime];
}
if ($endTime > 0) {
$orderListWhere[] = ['addtime', '<=', $endTime];
}
// 查询用户订单总金额(消耗金额)
$orderSubQuery = Order::where($orderWhere)
->field('user_id, SUM(price) + SUM(use_money) as money')
->group('user_id')
->buildSql();
// 查询用户出货金额
$usersWithOutputMoney = [];
$users = Order::where($orderWhere)->field('DISTINCT user_id')->select()->toArray();
foreach ($users as $user) {
$userId = $user['user_id'];
// 构建特定用户的查询条件
$userOrderListWhere = $orderListWhere;
$userOrderListWhere[] = ['user_id', '=', $userId];
// 查询用户出货金额
$outputMoney = \app\common\model\OrderList::where($userOrderListWhere)
->sum('goodslist_money');
if ($outputMoney > 0) {
$usersWithOutputMoney[$userId] = $outputMoney;
}
}
// 计算亏损数据
$rankList = [];
$index = 0;
// 从订单总金额查询结果中获取数据
$moneyResult = Db::table($orderSubQuery . ' as t')->where('money', '>', 0)->select()->toArray();
foreach ($moneyResult as $item) {
$userId = $item['user_id'];
$consumeMoney = $item['money']; // 消耗金额
// 如果有出货金额数据
if (isset($usersWithOutputMoney[$userId])) {
$outputMoney = $usersWithOutputMoney[$userId]; // 出货金额
// 计算亏损金额和亏损率
$lossMoney = $consumeMoney - $outputMoney;
$lossRate = $consumeMoney > 0 ? round(($lossMoney / $consumeMoney) * 100, 2) : 0;
// 只有亏损的才纳入排行
if ($lossMoney > 0) {
$rankList[] = [
'user_id' => $userId,
'consume_money' => $consumeMoney, // 消耗金额
'output_money' => $outputMoney, // 出货金额
'loss_money' => $lossMoney, // 亏损金额
'loss_rate' => $lossRate // 亏损率(%)
];
}
}
}
// 根据排序字段对结果进行排序
if ($sortField == 'loss_rate') {
// 按亏损率降序排序
usort($rankList, function($a, $b) {
return $b['loss_rate'] <=> $a['loss_rate'];
});
} else {
// 默认按亏损金额降序排序
usort($rankList, function($a, $b) {
return $b['loss_money'] <=> $a['loss_money'];
});
}
// 分页处理
$offset = ($page - 1) * $limit;
$rankList = array_slice($rankList, $offset, $limit);
// 处理用户信息和排名
$result = [];
foreach ($rankList as $index => $item) {
$userInfo = User::field('nickname, headimg, mobile')->where('id', $item['user_id'])->find();
if ($userInfo) {
$result[] = [
'rank' => $offset + $index + 1,
'user_id' => $item['user_id'],
'nickname' => $userInfo['nickname'],
'headimg' => imageUrl($userInfo['headimg']),
'consume_money' => $item['consume_money'],
'output_money' => $item['output_money'],
'value' => $item['loss_money'], // 主要展示值为亏损金额
'loss_rate' => $item['loss_rate'], // 亏损率
'unit' => '元'
];
}
}
return $result;
}
}

View File

@ -16,6 +16,10 @@ return [
'url' => '/admin/record',
'name' => '流水排行',
],
[
'url' => '/admin/user_rank',
'name' => '用户排行榜',
],
// [
// 'url' => '/admin/vip',
// 'name' => 'VIP管理',

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB