diff --git a/app/admin/controller/Config.php b/app/admin/controller/Config.php index b89d23f..484e9e3 100755 --- a/app/admin/controller/Config.php +++ b/app/admin/controller/Config.php @@ -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) { diff --git a/app/admin/controller/User.php b/app/admin/controller/User.php index 8e5502a..e4d138f 100755 --- a/app/admin/controller/User.php +++ b/app/admin/controller/User.php @@ -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; diff --git a/app/admin/controller/UserRank.php b/app/admin/controller/UserRank.php new file mode 100644 index 0000000..b509466 --- /dev/null +++ b/app/admin/controller/UserRank.php @@ -0,0 +1,81 @@ +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()); + } + } +} \ No newline at end of file diff --git a/app/admin/route/app.php b/app/admin/route/app.php index 54360bb..7310630 100755 --- a/app/admin/route/app.php +++ b/app/admin/route/app.php @@ -396,4 +396,10 @@ Route::post('sign_config_reward_edit', 'SignConfig/rewardEdit'); 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'); \ No newline at end of file +Route::get('sign_config_coupons', 'SignConfig/getCoupons'); + +#============================ +#UserRank.php用户排行榜 +#============================ +Route::rule('user_rank', 'UserRank/index', 'GET'); +Route::rule('user_rank_data', 'UserRank/getRankData', 'GET'); \ No newline at end of file diff --git a/app/admin/view/Config/systemconfig.html b/app/admin/view/Config/systemconfig.html index 48d36b1..1a9a01b 100755 --- a/app/admin/view/Config/systemconfig.html +++ b/app/admin/view/Config/systemconfig.html @@ -29,7 +29,7 @@
- +
每日免费送抽奖的ID,设置为0表示不启用
+
+ +
+ +
每天允许盒柜兑换的次数,0表示不限制次数
+
+
+
+ +
+ +
每天允许使用优惠券的次数,0表示不限制次数
+
+
@@ -395,6 +413,40 @@ class="layui-input" placeholder="不填则不限制结束时间">
+ + +
+ 亏损补贴排行榜 +
+
+ +
+ + + + + +
+
+
+ +
+ +
+ +
+ +
+
@@ -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表单的所有值 diff --git a/app/admin/view/Finance/record.html b/app/admin/view/Finance/record.html index 7b43dc6..19c1d90 100755 --- a/app/admin/view/Finance/record.html +++ b/app/admin/view/Finance/record.html @@ -40,7 +40,7 @@ 总金额 微信支付 消费余额 - 吧唧币 + UU币 diff --git a/app/admin/view/SignConfig/index.html b/app/admin/view/SignConfig/index.html index caaeb42..b6a8225 100755 --- a/app/admin/view/SignConfig/index.html +++ b/app/admin/view/SignConfig/index.html @@ -62,13 +62,12 @@ {{# if(item.reward_type == 1){ }} 钻石: {{item.reward_value}} {{# } else if(item.reward_type == 2){ }} - 货币1: {{item.reward_value}} + UU币: {{item.reward_value}} {{# } else if(item.reward_type == 3){ }} - 货币2: {{item.reward_value}} + 达达卷: {{item.reward_value}} {{# } else if(item.reward_type == 4){ }} 优惠券 {{# } }} - {{# }); }} {{# } else { }} 无奖励 diff --git a/app/admin/view/SignConfig/reward_edit.html b/app/admin/view/SignConfig/reward_edit.html index 0908200..11dfdaa 100755 --- a/app/admin/view/SignConfig/reward_edit.html +++ b/app/admin/view/SignConfig/reward_edit.html @@ -12,8 +12,7 @@
- - +
diff --git a/app/admin/view/user_rank/index.html b/app/admin/view/user_rank/index.html new file mode 100644 index 0000000..2f4852f --- /dev/null +++ b/app/admin/view/user_rank/index.html @@ -0,0 +1,141 @@ +{include file="Public:header2"/} + + +
+
+
+
+
用户排行榜
+
+ +
+
+
+ + + + + +
+
+
+ + +
+
+ +
+ +
+
+
+ + + + + + + + + + + + {if $type=='loss'} + + + + {/if} + + + + {volist name="list" id="vo"} + + + + + + + + {if $type=='loss'} + + + + {/if} + + {/volist} + +
排名用户ID用户昵称头像 + {if $type=='invite'}邀请人数 + {elseif $type=='loss'}亏损金额 + {elseif $type=='dadajuan'}达达卷数量 + {elseif $type=='diamond'}钻石数量 + {elseif $type=='integral'}UU币数量 + {/if} + 消耗金额出货金额亏损率
{$vo.rank}{$vo.user_id}{$vo.nickname} + + {$vo.value} {$vo.unit}{$vo.consume_money} 元{$vo.output_money} 元{$vo.loss_rate}%
+ + +
+
+
+
+
+
+ + {include file="Public:footer"/} + + + + + \ No newline at end of file diff --git a/app/api/controller/Index.php b/app/api/controller/Index.php index 4bd09e1..121a978 100755 --- a/app/api/controller/Index.php +++ b/app/api/controller/Index.php @@ -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; - } - - } diff --git a/app/api/controller/Warehouse.php b/app/api/controller/Warehouse.php index f8b3b5f..a135eb2 100755 --- a/app/api/controller/Warehouse.php +++ b/app/api/controller/Warehouse.php @@ -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 = []; diff --git a/app/common/helper/ConfigHelper.php b/app/common/helper/ConfigHelper.php index b7e2faa..213bf35 100755 --- a/app/common/helper/ConfigHelper.php +++ b/app/common/helper/ConfigHelper.php @@ -18,14 +18,54 @@ class ConfigHelper * @var int|null */ private static $infiniteMultiple = null; - + /** * 静态属性,用于存储排行榜设置 * * @var array|null */ 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,47 +73,47 @@ class ConfigHelper * * @return int 抽奖倍数,默认为1000 */ - public static function getInfiniteMultiple() - { + public static function getInfiniteMultiple( + ) { // 如果静态属性已有值,直接返回 if (self::$infiniteMultiple !== null) { return self::$infiniteMultiple; } - + // 实例化Redis助手 $redis = new RedisHelper(); - + // 设置Redis键名 $redisKey = 'config:infinite_multiple'; - + // 尝试从Redis获取 $cachedValue = $redis->get($redisKey); if ($cachedValue !== false) { // 缓存结果到静态属性 - self::$infiniteMultiple = (int)$cachedValue; + self::$infiniteMultiple = (int) $cachedValue; return self::$infiniteMultiple; } - + // Redis中不存在,从数据库获取 $config = Db::name('config') ->where('key', 'infinite_multiple') ->value('value'); - + // 解析JSON数据 $configArray = json_decode($config, true); - + // 获取倍数值,默认为10000 - $multiple = isset($configArray['multiple']) ? (int)$configArray['multiple'] : 10000; - + $multiple = isset($configArray['multiple']) ? (int) $configArray['multiple'] : 10000; + // 存入Redis,过期时间为1天(86400秒) $redis->set($redisKey, $multiple, 86400); - + // 缓存结果到静态属性 self::$infiniteMultiple = $multiple; - + return self::$infiniteMultiple; } - + /** * 获取排行榜设置 * 从数据库中查询key为rank_setting的配置 @@ -86,13 +126,13 @@ class ConfigHelper if (self::$rankSettings !== null) { return self::$rankSettings; } - + // 实例化Redis助手 $redis = new RedisHelper(); - + // 设置Redis键名 $redisKey = 'config:rank_settings'; - + // 尝试从Redis获取 $cachedValue = $redis->get($redisKey); if ($cachedValue !== false) { @@ -100,24 +140,24 @@ class ConfigHelper self::$rankSettings = json_decode($cachedValue, true); return self::$rankSettings; } - + // Redis中不存在,从数据库获取 $config = Db::name('config') ->where('key', 'rank_setting') ->value('value'); - + // 解析JSON数据 $configArray = json_decode($config, true) ?: []; - + // 存入Redis,过期时间为1小时(3600秒) $redis->set($redisKey, json_encode($configArray), 3600); - + // 缓存结果到静态属性 self::$rankSettings = $configArray; - + return self::$rankSettings; } - + /** * 获取特定排行榜的时间设置 * @@ -128,12 +168,12 @@ class ConfigHelper { // 获取所有排行榜设置 $settings = self::getRankSettings(); - + // 根据类型设置默认的键名 $statTypeKey = ''; $startKey = ''; $endKey = ''; - + switch ($type) { case 'dadajuan': $statTypeKey = 'dadajuan_stat_type'; @@ -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', @@ -162,47 +212,47 @@ class ConfigHelper 'end_time' => '' ]; } - + // 获取统计方式,默认为每天统计 $statType = isset($settings[$statTypeKey]) ? $settings[$statTypeKey] : 'daily'; - + // 根据统计方式计算时间范围 $startTime = ''; $endTime = ''; - + // 当前时间 $now = time(); - + switch ($statType) { case 'daily': // 每天统计:当天0点到第二天0点 $startTime = date('Y-m-d 00:00:00', $now); $endTime = date('Y-m-d 00:00:00', strtotime('+1 day', $now)); break; - + case 'weekly': // 每周统计:本周一0点到下周一0点 $weekStart = strtotime('this week monday', $now); $startTime = date('Y-m-d 00:00:00', $weekStart); $endTime = date('Y-m-d 00:00:00', strtotime('+1 week', $weekStart)); break; - + case 'monthly': // 每月统计:本月1号0点到下月1号0点 $startTime = date('Y-m-01 00:00:00', $now); $endTime = date('Y-m-01 00:00:00', strtotime('+1 month', $now)); break; - + case 'yearly': // 每年统计:本年1月1号0点到下年1月1号0点 $startTime = date('Y-01-01 00:00:00', $now); $endTime = date('Y-01-01 00:00:00', strtotime('+1 year', $now)); break; - + case 'custom': // 自定义时间范围:使用设置的时间 - $startTime = isset($settings[$startKey]) && !empty($settings[$startKey]) ? - $settings[$startKey] : ''; - $endTime = isset($settings[$endKey]) && !empty($settings[$endKey]) ? - $settings[$endKey] : ''; + $startTime = isset($settings[$startKey]) && !empty($settings[$startKey]) ? + $settings[$startKey] : ''; + $endTime = isset($settings[$endKey]) && !empty($settings[$endKey]) ? + $settings[$endKey] : ''; break; } - + // 返回排行榜配置 return [ 'stat_type' => $statType, @@ -210,7 +260,7 @@ class ConfigHelper 'end_time' => $endTime ]; } - + /** * 清除排行榜设置的Redis缓存 * 在排行榜设置更新时调用,确保获取最新数据 @@ -221,12 +271,12 @@ class ConfigHelper { // 重置静态属性 self::$rankSettings = null; - + // 清除Redis缓存 $redis = new RedisHelper(); $redisKey = 'config:rank_settings'; - + // 删除缓存,返回是否成功 return $redis->delete($redisKey); } -} \ No newline at end of file +} \ No newline at end of file diff --git a/app/common/service/PaymentCalculator.php b/app/common/service/PaymentCalculator.php index c035354..f7c0854 100644 --- a/app/common/service/PaymentCalculator.php +++ b/app/common/service/PaymentCalculator.php @@ -34,19 +34,19 @@ class PaymentCalculator $goods = GoodsModel::field('id,title,imgurl_detail,type,price,status,is_shou_zhe,quanju_xiangou,daily_xiangou,choujiang_xianzhi') ->where(['id' => $goods_id]) ->find(); - + if (!$goods) { return ['status' => 0, 'msg' => '盒子不存在']; } - + if ($goods['status'] != 1) { return ['status' => 0, 'msg' => '盒子已下架']; } } - + // 获取盒子类型 $goods_type = $goods['type']; - + // 如果未传入扩展信息,则从数据库获取 if (!$goodsExtend) { $goodsExtend = GoodsExtend::getGoodsExtendByGoodsId($goods_id, $goods_type); @@ -54,13 +54,13 @@ class PaymentCalculator return ['status' => 0, 'msg' => '盒子类型配置不存在']; } } - + // 处理图片URL $goods['imgurl_detail'] = imageUrl($goods['imgurl_detail']); - + // 盒子单价 $box_price = $goods['price']; - + // 首抽五折处理 $shou_zhe_price = 0; if ($goods['type'] != 5 && $goods_type != 10 && $goods_type != 15) { @@ -70,36 +70,54 @@ class PaymentCalculator $shou_zhe_price = bcmul("$box_price", "0.5", 2); } } - + // 计算总价 $goods['shou_zhe_price'] = $shou_zhe_price; $price = bcmul("$box_price", "$prize_num", 2); $price = bcsub("$price", "$shou_zhe_price", 2); - + // 订单金额 $order_total = $order_zhe_total = $price; - + // 初始化变量 $coupon_price = 0; $use_money = 0; // 余额抵扣 $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) { - // 获取优惠券信息 - $coupon = CouponReceiveModel::where([ - 'id' => $coupon_id, - 'status' => 0, - 'user_id' => $user['id'] - ])->where('man_price', '<=', $price) - ->where('end_time', '>', time()) // 确保优惠券未过期 - ->find(); + //是否限制每日优惠券次数 + $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, + 'status' => 0, + 'user_id' => $user['id'] + ])->where('man_price', '<=', $price) + ->where('end_time', '>', time()) // 确保优惠券未过期 + ->find(); - if ($coupon) { - $coupon_price = $coupon['price']; - } else { + if ($coupon) { + $coupon_price = $coupon['price']; + } else { + $coupon_id = 0; + } + }else{ $coupon_id = 0; } } else { @@ -111,11 +129,11 @@ class PaymentCalculator $price = 0; } $order_zhe_total = $price; - + // 如果不是首抽五折,处理各种支付抵扣 if ($shou_zhe_price <= 0) { $iszhifu = 0; - + // 余额抵扣 if ($use_money_is == 1 && $goodsExtend['pay_balance'] == 1) { if ($goodsExtend['is_deduction'] == 1) { @@ -140,7 +158,7 @@ class PaymentCalculator } } } - + // 货币1抵扣 if ($use_integral_is == 1 && $goodsExtend['pay_currency'] == 1) { $price_in_currency = $price * 100; // 1:100比例 @@ -166,7 +184,7 @@ class PaymentCalculator } } } - + // 货币2抵扣 if ($use_money2_is == 1 && $goodsExtend['pay_currency2'] == 1) { $price_in_currency2 = $price * 100; // 1:100比例 @@ -192,16 +210,16 @@ class PaymentCalculator } } } - + // 如果是支付模式但未选择任何支付方式 if ($goodsExtend['is_deduction'] == 0 && $iszhifu == 0 && $goodsExtend['pay_wechat'] == 0) { return ['status' => 0, 'msg' => '请选择支付方式']; } } - + // 设置抽奖数量 $goods['prize_num'] = $prize_num; - + // 组装返回数据 $data = [ 'status' => 1, @@ -220,15 +238,16 @@ 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 ]; - + // 添加首抽五折状态 $data['is_shou_zhe'] = $shou_zhe_price > 0 ? 1 : 0; - + return $data; } - + /** * 验证抽奖限制 * @@ -242,7 +261,7 @@ class PaymentCalculator // 验证抽奖门槛 $user_id = $user['id']; $choujiang_xianzhi = $goods['choujiang_xianzhi']; - + if ($choujiang_xianzhi && $choujiang_xianzhi > 0) { // 验证福利屋活动 if ($goods['type'] == 15) { @@ -252,34 +271,34 @@ class PaymentCalculator $goods['flw_start_time'], $goods['flw_end_time'] ); - + if ($consumptionData['total_consumed'] < $choujiang_xianzhi) { return [ - 'status' => 0, + 'status' => 0, 'msg' => "需在指定时间" . date('Y-m-d H:i:s', $goods['flw_start_time']) . "-" - . date('Y-m-d H:i:s', $goods['flw_end_time']) . "消耗达到" . $choujiang_xianzhi - . "钻石,即可加入房间,还需" . round(($choujiang_xianzhi - $consumptionData['total_consumed']), 2) . "钻石." + . date('Y-m-d H:i:s', $goods['flw_end_time']) . "消耗达到" . $choujiang_xianzhi + . "钻石,即可加入房间,还需" . round(($choujiang_xianzhi - $consumptionData['total_consumed']), 2) . "钻石." ]; } } else { // 常规消费验证 $user_price = Order::where('user_id', '=', $user_id)->where('status', '=', 1)->sum('price'); - + if ($user_price < $choujiang_xianzhi) { if ($user['istest'] > 0) { $user_price = Order::where('user_id', '=', $user_id)->where('status', '=', 1)->sum('order_zhe_total'); } - + if ($user_price < $choujiang_xianzhi) { return [ - 'status' => 0, + 'status' => 0, 'msg' => "消费满" . $choujiang_xianzhi . "元可参与 已消费" . round($user_price, 2) . "元" ]; } } } } - + // 验证全局限购 if ($goods['quanju_xiangou'] > 0) { $user_quanju_count = \app\common\model\OrderList::field('id') @@ -287,20 +306,20 @@ class PaymentCalculator ->where('user_id', '=', $user_id) ->where('parent_goods_list_id', '=', 0) ->count(); - + if ($user_quanju_count >= $goods['quanju_xiangou']) { return ['status' => 0, 'msg' => '当前限购' . $goods['quanju_xiangou'] . '次']; } - + $now_prize_num = $prize_num + $user_quanju_count; if ($now_prize_num > $goods['quanju_xiangou']) { return [ - 'status' => 0, + 'status' => 0, 'msg' => '购买超出限制,还允许购买' . ($goods['quanju_xiangou'] - $user_quanju_count) . '次' ]; } } - + // 验证每日限购 if ($goods['daily_xiangou'] > 0) { $todayMidnight = strtotime('today'); @@ -310,20 +329,20 @@ class PaymentCalculator ->where('parent_goods_list_id', '=', 0) ->where('addtime', '>=', $todayMidnight) ->count(); - + if ($user_toDay_count >= $goods['daily_xiangou']) { return ['status' => 0, 'msg' => '今日限购' . $goods['daily_xiangou'] . '次']; } - + $now_prize_num = $prize_num + $user_toDay_count; if ($now_prize_num > $goods['daily_xiangou']) { return [ - 'status' => 0, + 'status' => 0, 'msg' => '购买超出限制,今日还允许购买' . ($goods['daily_xiangou'] - $user_toDay_count) . '次' ]; } } - + return ['status' => 1, 'msg' => '验证通过']; } -} \ No newline at end of file +} \ No newline at end of file diff --git a/app/common/service/RankService.php b/app/common/service/RankService.php new file mode 100644 index 0000000..9e4e0e5 --- /dev/null +++ b/app/common/service/RankService.php @@ -0,0 +1,445 @@ +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; + } + +} \ No newline at end of file diff --git a/config/menu.php b/config/menu.php index ce479ae..60e2b70 100755 --- a/config/menu.php +++ b/config/menu.php @@ -16,6 +16,10 @@ return [ 'url' => '/admin/record', 'name' => '流水排行', ], + [ + 'url' => '/admin/user_rank', + 'name' => '用户排行榜', + ], // [ // 'url' => '/admin/vip', // 'name' => 'VIP管理', diff --git a/public/storage/poster/share/21546.png b/public/storage/poster/share/21546.png new file mode 100644 index 0000000..0bd3d88 Binary files /dev/null and b/public/storage/poster/share/21546.png differ