Files
midi-php/application/api/model/BlindBoxTurntableGift.php
2025-09-25 19:36:32 +08:00

1186 lines
52 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\api\model;
use app\common\controller\Push;
use think\Cache;
use think\Model;
use think\Db;
use think\Session;
/*
* 盲盒转盘
* 2025-08-16
*/
class BlindBoxTurntableGift extends Model
{
// 开启自动写入时间戳字段
protected $autoWriteTimestamp = true;
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
protected $table = 'fa_vs_gift';
//获取奖池礼物列表
public function get_gift_list($gift_bag_id,$room_id)
{
$box = db::name('vs_gift_bag')->where('id',$gift_bag_id)->find();
$gifts = db::name('vs_gift_bag_detail')->where('gift_bag_id',$gift_bag_id)->order("id desc")->select();
$gift_list = [];
foreach ($gifts as $key => $value) {
$gift_data = db::name('vs_gift')->where('gid',$value['foreign_id'])->where('delete_time',0)->find();
if($gift_data){
$gift_list[$key]['number'] = $key;
$gift_list[$key]['gift_id'] = $gift_data['gid'];
$gift_list[$key]['gift_name'] = $gift_data['gift_name'];
$gift_list[$key]['base_image'] = $gift_data['base_image'];
$gift_list[$key]['play_image'] = $gift_data['play_image'];
$gift_list[$key]['gift_price'] = $gift_data['gift_price'];
}
}
$ext = json_decode($box['ext'],true);
$box_gift = Db::name('vs_gift')->where('gid',$ext['gift_id'])->find();
//巡乐会
$is_xlh = 0;
$xlh_box = db::name('vs_gift_bag')->where('id',13)->find();
$xlh_ext = json_decode($xlh_box['ext'],true);
$xlh = [];
if($xlh_ext['inlet_bag_id'] == $box['id']){
$room = db::name('vs_room')->field('id,xlh_periods,xlh_periods_num')->where(['id'=>$room_id])->find();
$is_xlh = 1;
$xlh['waiting_start_num'] = $xlh_ext['open_condition']['waiting_start_num'];//等待开奖次数
$xlh['start_num'] = $xlh_ext['open_condition']['start_num'];//开始开奖次数
//当前抽奖次数
$xlh['current_num'] = $room['xlh_periods_num'];
//状态
if($xlh['current_num'] >= $xlh_ext['open_condition']['start_num']){
$xlh['status'] = 1;//状态 1:巡乐会开始 2:即将开始开始 0:等待开始
} elseif($xlh['current_num'] >= $xlh_ext['open_condition']['waiting_start_num'] && $xlh['current_num'] < $xlh_ext['open_condition']['start_num']){
$xlh['status'] = 2;//状态 1:巡乐会开始 2:即将开始开始 0:等待开始
}else{
$xlh['status'] = 0;
}
}
$result_data = [
'title' => $box['name'],
'rule_url' => get_system_config_value('web_site')."/api/Page/get_gift_box_rule?box_id=".$box["id"],
'box_price' => $box_gift['gift_price'],
'is_xlh' => $is_xlh,
'xlh_data' => $xlh,
'gift_list' => $gift_list,
];
return ['code' => 1, 'msg' => '获取成功', 'data' => $result_data];
}
/*
* 抽奖
*/
public function draw_gift($gift_bag_id, $user_id, $gift_user_ids,$num=1,$room_id=0,$heart_id=0)
{
// 合并配置查询
$bag_data = db::name("vs_gift_bag")
->field('id,name,ext')
->where('id',$gift_bag_id)
->find();
if (!$bag_data) {
return ['code' => 0, 'msg' => '盲盒配置不存在', 'data' => null];
}
$ext = json_decode($bag_data['ext'],true);
// 合并盲盒和礼物信息查询
$bag_gift = db::name("vs_gift")
->where(['gid'=>$ext['gift_id']])
->find();
if (!$bag_gift) {
return ['code' => 0, 'msg' => '盲盒礼物不存在', 'data' => null];
}
// 合并巡乐会配置查询
$xlh_box = db::name('vs_gift_bag')
->where('id',13)
->find();
$xlh_ext = $xlh_box ? json_decode($xlh_box['ext'],true) : [];
$xlh_is_piao_ping = 0;
// 处理收礼用户数组(多个)
$toarray = explode(',',$gift_user_ids);
// 合并房间信息查询
$room = db::name('vs_room')
->field('id,room_name,xlh_periods,xlh_periods_num,is_open_blind_box_turntable')
->where(['id'=>$room_id])
->find();
if (!$room) {
return ['code' => 0, 'msg' => '房间不存在', 'data' => null];
}
$this_xlh_periods_num = $room['xlh_periods_num'];//本期当前抽奖次数(巡乐会出发条件)
// 判断是否有足够的金币
$user_waller = db::name('user_wallet')
->where(['user_id'=>$user_id])
->find();
if (!$user_waller) {
return ['code' => 0, 'msg' => '用户钱包不存在', 'data' => null];
}
// 抽奖总消耗金币
$bag_gift_price = $bag_gift['gift_price'] * $num;
if ($user_waller['coin'] < $bag_gift_price) {
return ['code' => 0, 'msg' => '用户金币不足', 'data' => null];
}
if ($room['is_open_blind_box_turntable'] != 1) {
return ['code' => 0, 'msg' => '该房间未开启盲盒转盘', 'data' => null];
}
// 预计算抽奖结果,减少数据库事务中的查询
// 计算期数和抽奖次数
// 合并奖池总抽奖次数和房间奖池信息查询
$room_pan_info = db::name("vs_gift_bag_detail")
->alias('a')
->join('vs_room_pan b', 'b.gift_bag_detail_id = a.id AND b.room_id = ' . $room_id)
->where(['a.gift_bag_id' => $gift_bag_id])
->field('SUM(a.quantity) as total_quantity, SUM(b.remaining_number) as total_remaining, MAX(b.periods) as periods')
->find();
$total_quantity = $room_pan_info['total_quantity'] ?: 0;
$total_remaining = $room_pan_info['total_remaining'] ?: 0;
$periods = $room_pan_info['periods'] ?: 0;
// 本期当前第多少次后抽奖 总的抽奖次数- 剩余数量
$total_draw_times = $total_quantity - $total_remaining;
if($total_draw_times<0){
$total_draw_times = 0;
}
// 预计算所有抽奖结果
$precomputed_results = [];
$current_draw_times = $total_draw_times;
$current_periods = $periods;
$current_xlh_periods_num = $this_xlh_periods_num;
// 生成缓存键
$available_cache_key = 'blindbox_available_gifts_' . $gift_bag_id . '_' . $room_id;
$last_remaining_cache_key = 'blindbox_last_remaining_' . $gift_bag_id . '_' . $room_id;
// 获取所有可用礼物用于预计算
$available_gifts = $this->get_available_gifts_for_precompute($gift_bag_id, $room_id, $current_draw_times);
if (empty($available_gifts)) {
return ['code' => 0, 'msg' => '当前盲盒无可用礼物', 'data' => null];
}
$should_reset_all_gifts = false; // 标记是否需要重置所有礼物
//如果本期奖池数量小于抽奖次数,则重置奖池,并把上期剩余数量加到本期奖池中
//接收礼物人数
$receive_num = count($toarray);
//需要的礼物数量
$need_gift_num = $receive_num * $num;
$last_periods_remaining = [];
if ($total_remaining - $need_gift_num <= 0 ) {
//上期剩余礼物
$last_periods_remaining = $available_gifts;
//加入缓存
cache($last_remaining_cache_key, $last_periods_remaining);
// 重置奖池
$current_periods++;
$this->reset_gift_pool($room_id, $gift_bag_id, $current_periods);
//补充上期剩余数量
foreach ($available_gifts as $gift_data) {
db::name("vs_room_pan")
->where(['room_id'=>$room_id,'gift_bag_id'=>$gift_bag_id,'gift_bag_detail_id'=>$gift_data['id']])
->setInc('remaining_number', $gift_data['remaining_number']);
}
// 重新获取可用礼物
$current_draw_times = 0;
$available_gifts = $this->get_available_gifts_for_precompute($gift_bag_id, $room_id, $current_draw_times);
$should_reset_all_gifts = false; // 重置标记
}
//加入缓存
cache($available_cache_key, $available_gifts);
// 预计算所有抽奖结果
foreach ($toarray as $gift_user_id) {
if($user_id == $gift_user_id){
return ['code' => 0, 'msg' => "收礼人不能包含自己", 'data' => null];
}
for($i = 0; $i < $num; $i++){
// 使用加权随机算法预计算单次抽奖结果
//从缓存中取出可用礼物
if(cache($available_cache_key)){
$available_gifts = cache($available_cache_key);
}
if(cache($last_remaining_cache_key)){
$last_periods_remaining = cache($last_remaining_cache_key);
}
$draw_result = $this->precompute_single_draw($gift_bag_id,$room_id,$available_gifts,$last_periods_remaining);
if (!$draw_result) {
return ['code' => 0, 'msg' => '预计算抽奖失败', 'data' => null];
}
$precomputed_results[] = [
'gift_user_id' => $gift_user_id,
'gift_bag_detail' => $draw_result['gift_bag_detail'],
'gift' => $draw_result['gift'],
'draw_times' => $current_draw_times,
'periods' => $current_periods
];
$current_draw_times++;
// 判断巡乐会飘屏判断
$current_xlh_periods_num++;
if(!empty($xlh_ext) && $xlh_ext['inlet_bag_id'] == $gift_bag_id && $current_xlh_periods_num == $xlh_ext['open_condition']['waiting_start_num']){
$xlh_is_piao_ping = 1;
}
if(!empty($xlh_ext) && $xlh_ext['inlet_bag_id'] == $gift_bag_id && $current_xlh_periods_num == $xlh_ext['open_condition']['start_num']){
$xlh_is_piao_ping = 2;
}
// 更新可用礼物数量(模拟数据库更新)
$total_remaining_after_update = 0;
foreach ($available_gifts as &$gift) {
if ($gift['id'] == $draw_result['gift_bag_detail']['id']) {
$gift['remaining_number']--;
}
// 计算更新后的总剩余数量
$total_remaining_after_update += $gift['remaining_number'];
}
// 检查是否需要重置所有礼物
if ($total_remaining_after_update <= 0) {
$should_reset_all_gifts = true;
$current_periods++; // 增加期数
}
}
}
// 清除相关缓存
cache($available_cache_key, null);
cache($last_remaining_cache_key, null);
// 开始数据库事务处理
db::startTrans();
try{
// 盲盒转盘抽奖记录
$box_turntable_log = db::name('vs_blind_box_turntable_log')->insertGetId([
'user_id' => $user_id,
'gift_bag_id' => $gift_bag_id,
'num' => $num,
'room_id' => $room_id,
'bag_price' => $bag_gift['gift_price'],
'createtime' => time()
]);
if (!$box_turntable_log) {
db::rollback();
return ['code' => 0, 'msg' => '添加盲盒转盘记录失败', 'data' => null];
}
// 处理预计算的抽奖结果
$result_draw_gift = [];
$gift_counts = []; // 统计每个礼物的数量
$gift_user_counts = []; // 统计每个用户每个礼物的数量
foreach ($precomputed_results as $result) {
$gift_user_id = $result['gift_user_id'];
$gift_bag_detail = $result['gift_bag_detail'];
$gift = $result['gift'];
$pan_data = db::name("vs_room_pan")
->where(['room_id'=>$room_id,'gift_bag_detail_id'=>$gift_bag_detail['id']])->value("remaining_number");
if($pan_data < 1){
db::rollback();
return ['code' => 0, 'msg' => '礼物数量不足', 'data' => null];
}
// 构造返回数据
$result_data = [
'user_id' => $user_id,
'gift_user_id' => $gift_user_id,
'gift_id' => $gift_bag_detail['foreign_id'],
'gift_price' => $gift['gift_price'],
'is_public_screen' => $gift['is_public_screen'],
'periods' => $result['periods'],
];
$result_draw_gift[] = $result_data;
// 统计礼物数量
$gift_id = $gift_bag_detail['foreign_id'];
if (!isset($gift_counts[$gift_id])) {
$gift_counts[$gift_id] = [
'gift_id' => $gift_id,
'count' => 0,
'gift_price' => $gift['gift_price']
];
}
$gift_counts[$gift_id]['count']++;
// 统计用户礼物数量
$user_gift_key = $gift_user_id . '_' . $gift_id;
if (!isset($gift_user_counts[$user_gift_key])) {
$gift_user_counts[$user_gift_key] = [
'gift_user_id' => $gift_user_id,
'gift_id' => $gift_id,
'count' => 0,
'gift_price' => $gift['gift_price']
];
}
$gift_user_counts[$user_gift_key]['count']++;
// 处理礼包发放记录表
$data = [];
$data['user_id'] = $user_id;
$data['gift_user_id'] = $gift_user_id;
$data['parent_id'] = $box_turntable_log;
$data['gift_bag_id'] = $gift_bag_id;
$data['gift_id'] = $gift_bag_detail['foreign_id'];
$data['periods'] = $result['periods'];
$data['room_id'] = $room_id;
$data['gift_price'] = $gift['gift_price'];
$data['bag_price'] = $bag_gift['gift_price'];
$data['createtime'] = time();
$insert_result = db::name("vs_gift_bag_receive_log")->insert($data);
if(!$insert_result){
db::rollback();
return ['code' => 0, 'msg' => '插入礼包发放记录失败', 'data' => []];
}
// 减去盲盒包礼物数量
$ret = db::name("vs_room_pan")
->where(['room_id'=>$room_id,'gift_bag_detail_id'=>$gift_bag_detail['id'],"remaining_number"=>["<>",0]])
->setDec('remaining_number',1);
if(!$ret){
db::rollback();
return ['code' => 0, 'msg' => '更新礼物剩余数量失败', 'data' => []];
}
}
// 扣除抽奖消耗的金币
// 扣除用户金币并记录日志
$wallet_update = model('GiveGift')->change_user_cion_or_earnings_log($user_id,$bag_gift_price,$room_id,1,10,'盲盒转盘抽奖消耗');
if(!$wallet_update){
Db::rollback();
return ['code' => 0, 'msg' => '扣除用户金币失败', 'data' => null];
}
// 用户财富等级更新
$user_level = model('Level')->user_level_data_update($user_id,$bag_gift_price,1,$room_id);
if(!$user_level){
Db::rollback();
return ['code' => 0, 'msg' => '用户等级更新失败', 'data' => null];
}
db::commit();
} catch(\Exception $e) {
db::rollback();
return V(0,$e->getMessage());
}
// 批量插入盲盒转盘结果记录
foreach ($gift_user_counts as $user_gift) {
$ret = db::name('vs_blind_box_turntable_results_log')->insert([
'tid' => $box_turntable_log,
'gift_user_id' => $user_gift['gift_user_id'],
'gift_id' => $user_gift['gift_id'],
'count' => $user_gift['count'],
'gift_price' => $user_gift['gift_price'],
'all_gift_price' => $user_gift['gift_price'] * $user_gift['count'],
'createtime' => time(),
'heart_id' => $heart_id
]);
if (!$ret) {
return ['code' => 0, 'msg' => '添加盲盒转盘结果记录失败', 'data' => null];
}
//给接收礼物的人送礼物
$give_gift_ext['gift_id'] = $user_gift['gift_id'];
$give_gift_ext['count'] = $user_gift['count'];
$give_gift_ext['gift_price'] = $user_gift['gift_price'];
$give_gift_ext['all_gift_price'] = $user_gift['gift_price'] * $user_gift['count'];
$give_gift_ext['is_draw_gift'] = 1;
$res = model('Room')->room_gift($user_id, $user_gift['gift_user_id'], $user_gift['gift_id'], $user_gift['count'], 1, $room_id, 0,$heart_id,$give_gift_ext);
if (isset($res) && $res['code'] != 1) {
db::rollback();
return ['code' => 0, 'msg' => $res['msg'], 'data' => null];
}
}
// 巡乐会
$xlh = [];
if(!empty($xlh_ext) && $xlh_ext['inlet_bag_id'] == $gift_bag_id){
// 巡乐会飘屏
db::name("vs_room")->where('id',$room_id)->update([
'xlh_periods_num' => $current_xlh_periods_num
]);//加巡乐会条件次数
if($xlh_is_piao_ping == 1){
// 即将开始推送飘屏
$text = $room['room_name']."的巡乐会即将开始,请大家尽快参与哦!";
// 推送礼物横幅
$push = new Push(UID, $room_id);
$text_list_new = [
'text' => $text,
'room_id' => $room_id,
'from_type' => 1
];
$push->xunlehui($text_list_new);
}
if($xlh_is_piao_ping == 2){
// 正式开始推送飘屏
$text = $room['room_name']."的巡乐会正式开始,请大家尽快参与哦!";
// 推送礼物横幅
$push = new Push(UID, $room_id);
$text_list_new = [
'text' => $text,
'room_id' => $room_id,
'from_type' => 2
];
$push->xunlehui($text_list_new);
// 巡乐会正式开始
$this_xlh_periods = db::name('vs_room')->where('id',$room_id)->value('xlh_periods');
$pan_xlh_id = db::name('vs_room_pan_xlh')->insertGetId([
'room_id' => $room_id,
'gift_id' => $xlh_ext['locking_condition']['locking_gift_id'],
'homeowner_gift_id' => $xlh_ext['locking_condition']['give_homeowner_gift_id'],
'periods' => $this_xlh_periods+1,
'num' => 0,
'end_time' => time() + $xlh_ext['locking_time']['end_time'] * 60,
'createtime' => time()
]);
if(!$pan_xlh_id){
return ['code' => 0, 'msg' => '创建巡乐会失败!', 'data' => []];
}
db::name("vs_room")->where('id',$room_id)->setInc('xlh_periods');//修改巡乐会期数
}
$xlh['waiting_start_num'] = $xlh_ext['open_condition']['waiting_start_num'];//等待开奖次数
$xlh['start_num'] = $xlh_ext['open_condition']['start_num'];//开始开奖次数
// 当前抽奖次数
$xlh['current_num'] = $current_xlh_periods_num;
// 状态
if($xlh['current_num'] >= $xlh_ext['open_condition']['start_num']){
$xlh['status'] = 1;//状态 1:巡乐会开始 2:即将开始开始 0:等待开始
} elseif($xlh['current_num'] >= $xlh_ext['open_condition']['waiting_start_num'] && $xlh['current_num'] < $xlh_ext['open_condition']['start_num']){
$xlh['status'] = 2;//状态 1:巡乐会开始 2:即将开始开始 0:等待开始
}else{
$xlh['status'] = 0;
}
// 推送
$text = [
'xlh_data' => $xlh,
'text' => ""
];
// 聊天室推送系统消息
model('Chat')->sendMsg(1056,$room_id,$text);
}
// 整理返回结果
$result_list = [];
foreach ($gift_counts as $gift) {
$result_list[] = [
'gift_id' => $gift['gift_id'],
'count' => $gift['count']
];
}
$reslut = [];
$reslut['blind_box_turntable_id'] = $box_turntable_log;
$reslut['reslut_list'] = $result_list;
return V(1,"成功", $reslut);
}
/**
* 重置奖池
* @param int $room_id 房间ID
* @param int $gift_bag_id 礼物包ID
* @param int $periods 期数
*/
private function reset_gift_pool($room_id, $gift_bag_id, $periods) {
// 重置奖池中所有礼物数量
db::name("vs_room_pan")
->where(['room_id'=>$room_id,'gift_bag_id'=>$gift_bag_id])
->update([
'remaining_number' => db::raw('(SELECT quantity FROM fa_vs_gift_bag_detail WHERE id = fa_vs_room_pan.gift_bag_detail_id)'),
'periods' => $periods
]);
// 更新总期数
db::name("vs_gift_bag")
->where('id', $gift_bag_id)
->setInc('periods');
}
/*
* 获取可用礼物用于预计算
*/
private function get_available_gifts_for_precompute($gift_bag_id, $room_id, $total_draw_times) {
$where = [
'a.gift_bag_id' => $gift_bag_id,
'a.quantity' => ['>',0],
'b.remaining_number' => ['>',0],
'b.room_id' => $room_id,
'a.weight' => ['<=', $total_draw_times],
];
return db::name("vs_gift_bag_detail")
->field('a.id,a.quantity,b.remaining_number,a.weight,a.foreign_id')
->alias('a')
->join('vs_room_pan b','b.gift_bag_detail_id = a.id','left')
->where($where)
->select();
}
/*
* 预计算单次抽奖结果
*/
private function precompute_single_draw($gift_bag_id, $room_id, $available_gifts, $last_periods_remaining = []) {
// 生成缓存键
$available_cache_key = 'blindbox_available_gifts_' . $gift_bag_id . '_' . $room_id;
$last_remaining_cache_key = 'blindbox_last_remaining_' . $gift_bag_id . '_' . $room_id;
// 保证有可用礼物
if (empty($available_gifts)) {
return false;
}
$last_remaining_all = array_sum(array_column($last_periods_remaining, 'remaining_number'));
if ($last_remaining_all == 0) {
$last_periods_remaining = [];
cache($last_remaining_cache_key, null);
}
$last_periods_remaining_flag = 0;
if (!empty($last_periods_remaining)) {
$available_gifts = $last_periods_remaining;
$last_periods_remaining_flag = 1;
}
// 循环尝试直到抽中有效礼物
$max_attempts = 5; // 最大尝试次数,防止无限循环
$attempt = 0;
$selected_gift = null;
while ($attempt < $max_attempts && !$selected_gift) {
// 实现加权随机算法:剩余数量越多,被抽中的概率越大
$remaining = 0;
foreach ($available_gifts as $gift) {
$remaining += $gift['remaining_number'];
}
if ($remaining <= 0) {
break; // 如果没有剩余数量,跳出循环
}
$rand_value = mt_rand(1, $remaining);
$current_sum = 0;
foreach ($available_gifts as $gift) {
if ($gift['remaining_number'] <= 0) {
continue;
}
$current_sum += $gift['remaining_number'];
if ($rand_value <= $current_sum) {
$selected_gift = $gift;
break;
}
}
$attempt++;
}
if (!$selected_gift) {
return false;
}
// 获取开出礼物的信息
$gift = db::name("vs_gift")
->where(['gid' => $selected_gift['foreign_id']])
->find();
if (!$gift) {
return false;
}
// 操作缓存,减去缓存中对应数据数量
foreach ($available_gifts as &$available_gifts_gift) {
if ($selected_gift['id'] == $available_gifts_gift['id']) {
$available_gifts_gift['remaining_number'] -= 1;
}
}
if ($available_gifts_gift['remaining_number'] == 0) {
unset($available_gifts_gift);
}
if ($last_periods_remaining_flag == 1) {
// 操作上一轮奖池
cache($last_remaining_cache_key, $available_gifts);
} else {
cache($available_cache_key, $available_gifts);
}
return [
'gift_bag_detail' => $selected_gift,
'gift' => $gift
];
}
/*
* 礼物特效播放
*/
public function gift_send($send_id){
try{
$blind_box_turntable = db('vs_blind_box_turntable_log')->where(['id'=>$send_id,'is_sued'=>0])->find();
if(!$blind_box_turntable){
return ['code' => 1, 'msg' => '成功', 'data' => null];
}
$room_id = $blind_box_turntable['room_id'];
$blind_box_turntable_log = db('vs_blind_box_turntable_results_log')->where(['tid'=>$send_id])->select();
if(!$blind_box_turntable_log){
return ['code' => 0, 'msg' => '数据不存在','data' => null];
}
$room_name = Db::name('vs_room')->where(['id' => $room_id, 'apply_status' => 2])->value('room_name');
$FromUserInfo = Db::name('user')->where(['id'=>$blind_box_turntable['user_id']])->find();
$FromUserInfo['icon'][0] = model('UserData')->user_wealth_icon($blind_box_turntable['user_id']);//财富图标
$FromUserInfo['icon'][1] = model('UserData')->user_charm_icon($blind_box_turntable['user_id']);//魅力图标
$user_nickname = $FromUserInfo['nickname'];
$textMessage = $user_nickname;
$text_message = [];
foreach ($blind_box_turntable_log as $key => $value) {
$ToUserInfo = Db::name('user')->where(['id' => $value['gift_user_id']])->field('id as user_id,nickname,avatar,sex')->find();
$draw_gift = Db::name('vs_gift')->where(['gid'=>$value['gift_id']])->find();
$textMessage = $textMessage . ' 送给 ' . $ToUserInfo['nickname']. ' 盲盒转盘礼物 ' . $draw_gift['gift_name'].' x ' .$value['count']."\n";
$play_image[] = $draw_gift['play_image'];
$gift_names[] = $draw_gift['gift_name'];
$text_message = $user_nickname . '在' . $room_name . '房间送给了' . $ToUserInfo['nickname'] . $draw_gift['gift_name'] . 'X' . $value['count']."\n";
if($draw_gift['is_public_server'] == 1) {
$text_list_new[] = [
'text' => $text_message,
'gift_picture' => $draw_gift['base_image'],
'room_id' => $room_id,
'fromUserName' => $FromUserInfo['nickname'],
'toUserName' => $ToUserInfo['nickname'],
'giftName' => $draw_gift['gift_name'],
'roomId' => $room_id,
'number' => $value['count'],
];
}
$ToUserInfosList[$value['gift_user_id']] = $ToUserInfo;
}
foreach($ToUserInfosList as &$userInfo) {
$userInfo['icon'][0] = model('UserData')->user_wealth_icon($userInfo['user_id']);//财富图标
$userInfo['icon'][1] = model('UserData')->user_charm_icon($userInfo['user_id']);//魅力图标
$userInfo['charm'] = db::name('vs_room_user_charm')->where(['user_id' => $userInfo['user_id'],'room_id' => $room_id])->value('charm');//魅力
$ToUserInfos[] = $userInfo;
}
$text = [
'FromUserInfo' => $FromUserInfo,
'ToUserInfos' => $ToUserInfos,
'GiftInfo' => [
'play_image' => implode(',',$play_image),
'gift_name' => implode(',',$gift_names),
],
'text' => rtrim($textMessage, "\n")
];
//聊天室推送系统消息
model('Chat')->sendMsg(1005,$room_id,$text);
$roomtype = Db::name('vs_room')->where(['id' => $room_id])->value('type_id');
if($roomtype == 6){
//推送消息
$hot_value = db::name('vs_give_gift')->where('from_id', $room_id)->where('from',6)
->sum('total_price');
$text1 = [
'room_id' => $room_id,
'hot_value' => $hot_value * 10,
'text' => '房间心动值变化'
];
//聊天室推送系统消息
model('Chat')->sendMsg(1028,$room_id,$text1);
}else{
if(!empty($text_list_new)){
//推送礼物横幅
$push = new Push($blind_box_turntable['user_id'], $room_id);
$push->giftBanner($text_list_new);
}
}
db::name('vs_blind_box_turntable_log')->where('id', $send_id)->update(['is_sued' => 1, 'updatetime' => time()]);
return ['code' => 1, 'msg' => '成功', 'data' => null];
} catch (\Exception $e) {
return ['code' => 0, 'msg' => "网络请求错误,请重试!", 'data' => null];
}
}
/*
* 获取用户抽奖记录
*/
public function get_user_record($gift_bag_id,$user_id=0,$page=1,$page_size=12){
$where = [];
$where['b.gift_bag_id'] = $gift_bag_id;
if($user_id > 0){
$where['b.user_id'] = $user_id;
}
$list = db('vs_blind_box_turntable_results_log')
->alias('a')
->join('vs_blind_box_turntable_log b','b.id = a.tid','left')
->join('user c','a.gift_user_id = c.id','left')
->join('vs_gift d','d.gid = a.gift_id','left')
->field('a.gift_id,a.count,a.gift_user_id,a.createtime,c.nickname,d.gift_name as gift_name,d.base_image')
->where($where)
->order('a.createtime desc')
->page($page,$page_size)
->select();
foreach ($list as &$v){
$v['createtime'] = date('Y-m-d H:i:s',$v['createtime']);
}
return ['code' => 1, 'msg' => '成功', 'data' => $list];
}
/*
* 获取全服抽奖记录
*/
public function get_all_record($gift_bag_id,$page=1,$page_size=12){
$where = [];
$where['b.gift_bag_id'] = $gift_bag_id;
$where['d.gift_bag_id'] = $gift_bag_id;
$where['d.is_world_show'] = 1;
$list = db('vs_blind_box_turntable_results_log')
->alias('a')
->join('vs_blind_box_turntable_log b','b.id = a.tid','left')
->join('user c','b.user_id = c.id','left')
->join('vs_gift_bag_detail d','d.foreign_id = a.gift_id','left')
->join('vs_gift e','e.gid = a.gift_id','left')
->field('a.gift_id,a.count,b.user_id,a.createtime,c.nickname,d.name as gift_name,e.base_image')
->where($where)
->order('a.createtime desc')
->page($page,$page_size)
->select();
foreach ($list as &$v){
$v['createtime'] = date('Y-m-d H:i:s',$v['createtime']);
}
return ['code' => 1, 'msg' => '成功', 'data' => $list];
}
/*
* 巡乐会
*/
public function xlh_gift_list($room_id){
$room_data = db::name('vs_room')->field('xlh_periods,xlh_periods_num,user_id')-> where('id',$room_id)->find();
if(empty($room_data)){
return ['code' => 0, 'msg' => '房间不存在!', 'data' => null];
}
$gift_bag_id = 13;
$xlh_box = db::name('vs_gift_bag')->where('id',$gift_bag_id)->find();
$xlh_ext = json_decode($xlh_box['ext'],true);
$gifts = db::name('vs_gift_bag_detail')->where('gift_bag_id',$gift_bag_id)->order("id desc")->select();
$gift_list = [];
foreach ($gifts as $key => $value) {
$gift_data = db::name('vs_gift')->where('gid',$value['foreign_id'])->where('delete_time',0)->find();
if($gift_data){
$gift_list[$key]['number'] = $key;
$gift_list[$key]['gift_id'] = $gift_data['gid'];
$gift_list[$key]['gift_name'] = $gift_data['gift_name'];
$gift_list[$key]['base_image'] = $gift_data['base_image'];
$gift_list[$key]['play_image'] = $gift_data['play_image'];
$gift_list[$key]['gift_price'] = $gift_data['gift_price'];
}
}
//房主信息
$room_user = db::name('user')->where('id',$room_data['user_id'])->find();
//房主礼物
$room_user_gift = db::name('vs_gift')->where('gid',$xlh_ext['locking_condition']['give_homeowner_gift_id'])->find();
//巡乐会主礼物
$xlh_main_gift = db::name('vs_gift')->where('gid',$xlh_ext['locking_condition']['locking_gift_id'])->find();
//中奖用户
$xlh_periods = $room_data['xlh_periods']??0;
$pan_xlh = db::name('vs_room_pan_xlh')->where(['room_id'=>$room_id,'periods'=>$xlh_periods,'send_time'=>0])->find();
if(empty($pan_xlh)){
if($room_data['xlh_periods_num'] >= $xlh_ext['open_condition']['start_num']){
$pan_xlh_id = db::name('vs_room_pan_xlh')->insertGetId([
'room_id' => $room_id,
'gift_id' => $xlh_ext['locking_condition']['locking_gift_id'],
'homeowner_gift_id' => $xlh_ext['locking_condition']['give_homeowner_gift_id'],
'periods' => $xlh_periods+1,
'num' => 0,
'end_time' => time() + $xlh_ext['locking_time']['end_time'] * 60,
'createtime' => time()
]);
db::name("vs_room")->where('id',$room_id)->setInc('xlh_periods');//修改巡乐会期数
$pan_xlh = db::name('vs_room_pan_xlh')->where(['id'=>$pan_xlh_id])->find();
}else{
return ['code' => 0, 'msg' => '未开始', 'data' => null];
}
}
$xlh_user_data= null;
if($pan_xlh && $pan_xlh['user_id']){
$xlh_user = db::name('user')->where('id',$pan_xlh['user_id'])->find();
$xlh_user_data = [
'user_id' => $xlh_user['id'],
'nickname' => $xlh_user['nickname'],
'avatar' => $xlh_user['avatar'],
];
}
//$gift_list 按gift_price 升序排序
usort($gift_list, function($a, $b) {
return $a['gift_price'] - $b['gift_price'];
});
$result_data = [
'title' => $xlh_box['name'],
'rule_url' => get_system_config_value('web_site')."/api/Page/get_gift_box_rule?box_id=".$xlh_box["id"],
'box_price' => $xlh_ext['xlh_box_price'],
'xlh_end_time' =>$pan_xlh['end_time']??0,
'give_homeowner_gift' => [
'gift_id' => $room_user_gift['gid'],
'gift_name' => $room_user_gift['gift_name'],
'gift_price' => $room_user_gift['gift_price'],
'base_image' => $room_user_gift['base_image'],
],
'homeowner_user' => [
'user_id' => $room_user['id'],
'nickname' => $room_user['nickname'],
'avatar' => $room_user['avatar'],
],
'locking_gift' => [
'gift_id' => $xlh_main_gift['gid'],
'gift_name' => $xlh_main_gift['gift_name'],
'gift_price' => $xlh_main_gift['gift_price'],
'base_image' => $xlh_main_gift['base_image'],
'gift_num' => $pan_xlh['num']??0
],
'xlh_user' => $xlh_user_data,
'gift_list' => $gift_list,
];
return ['code' => 1, 'msg' => '获取成功', 'data' => $result_data];
}
/*
* 巡乐会抽奖
*/
public function xlh_draw_gift($user_id,$num,$room_id){
$gift_bag_id = 13;
//获取盲盒配置
$bag_data = db::name("vs_gift_bag")->field('id,name,ext,periods')->where('id',$gift_bag_id)->find();
$ext = json_decode($bag_data['ext'],true);
//判断是否有足够的金币
$bag_gift_price = $ext['xlh_box_price'] * $num;
$user_waller = db::name('user_wallet')->where(['user_id'=>$user_id])->find();
if ($user_waller['coin'] < $bag_gift_price) {
return ['code' => 0, 'msg' => '用户金币不足', 'data' => null];
}
$room = db::name('vs_room')->where(['id'=>$room_id])->find();
if ($room['is_open_blind_box_turntable'] != 1) {
return ['code' => 0, 'msg' => '该房间未开启盲盒转盘', 'data' => null];
}
//开始抽奖
$pan_xlh = db::name('vs_room_pan_xlh')->where(['room_id'=>$room_id,'periods'=>$room['xlh_periods']])->find();
if(empty($pan_xlh)){
return ['code' => 0, 'msg' => '未开始', 'data' => null];
}
if($pan_xlh['end_time']<=time()){
return ['code' => 0, 'msg' => '本轮已结束', 'data' => null];
}
if($pan_xlh['send_time']!=0){
return ['code' => 0, 'msg' => '本轮已结束,礼物已发放', 'data' => null];
}
$is_zhong_jiang = 0;
$pan_xlh_num = $pan_xlh['num'];
//奖池总的抽奖次数
$total_quantity = db::name("vs_gift_bag_detail")->where(['gift_bag_id' => $gift_bag_id])->sum('quantity');
db::startTrans();
try{
//扣除抽奖消耗的金币
//扣除用户金币并记录日志
$wallet_update = model('GiveGift')->change_user_cion_or_earnings_log($user_id,$bag_gift_price,$room_id,1,10,'巡乐会抽奖消耗');
if(!$wallet_update){
Db::rollback();
return ['code' => 0, 'msg' => '扣除用户金币失败', 'data' => null];
}
//用户财富等级更新
$user_level = model('Level')->user_level_data_update($user_id,$bag_gift_price,1,$room_id);
if(!$user_level){
Db::rollback();
return ['code' => 0, 'msg' => '用户等级更新失败', 'data' => null];
}
//开始抽奖
for($i = 0; $i < $num; $i++){
//本期当前第多少次后抽奖 总的抽奖次数- 剩余数量
$room_pan = db::name("vs_room_pan")->where(['room_id'=>$room_id,'gift_bag_id'=>$gift_bag_id])->field('remaining_number,periods')->find();
if(empty($room_pan)){
return ['code' => 0, 'msg' => '当前房间未配置抽奖礼物,请联系管理员', 'data' => []];
}
$total_remaining = db::name("vs_room_pan")->where(['room_id'=>$room_id,'gift_bag_id'=>$gift_bag_id])->sum('remaining_number');
$total_draw_times = $total_quantity - $total_remaining;
//随机获取一个礼物
$where = [
'a.gift_bag_id' => $gift_bag_id,
'b.room_id' => $room_id,
'a.quantity' => ['>',0],
'b.remaining_number' => ['>',0],
'a.weight' => ['<=', $total_draw_times],
];
// 使用闭包条件来处理复杂的 weight 逻辑
// $where['a.weight'] = ['exp', Db::raw('= 0 OR a.weight < '.$total_draw_times)];
// 优化:基于剩余数量的加权随机选择
$gift_bag_details = db::name("vs_gift_bag_detail")
->field('a.id,a.quantity,b.remaining_number,a.weight,a.foreign_id')
->alias('a')
->join('vs_room_pan b','b.gift_bag_detail_id = a.id','left')
->where($where)
->select();
if (empty($gift_bag_details)) {
return ['code' => 0, 'msg' => '当前盲盒无可用礼物', 'data' => []];
}
// 实现加权随机算法:剩余数量越多,被抽中的概率越大
$remaining = 0;
foreach ($gift_bag_details as $gift) {
$remaining += $gift['remaining_number'];
}
$rand_value = mt_rand(1, $remaining);
$current_sum = 0;
$gift_bag_detail = null;
foreach ($gift_bag_details as $gift) {
if($gift['remaining_number'] <= 0){
continue;
}
$current_sum += $gift['remaining_number'];
if ($rand_value <= $current_sum) {
$gift_bag_detail = $gift;
break;
}
}
if($gift_bag_detail){
//获取开出礼物的信息
$gift = db::name("vs_gift")->where(['gid'=>$gift_bag_detail['foreign_id']])->find();
//抽中礼物落包
$res = model('UserGiftPack')->change_user_gift_pack($user_id,$gift_bag_detail['foreign_id'],1,model('UserGiftPack')::XLH_DRAW_GIFT_GET,$bag_data['name']."抽奖所得");
if ($res['code'] != 1) {
db::rollback();
return ['code' => 0, 'msg' => $res['msg'], 'data' => null];
}
//处理抽中礼物命中主奖品逻辑
if($gift_bag_detail['foreign_id'] == $ext['locking_condition']['selected_gift_id']){
//中奖
$pan_xlh_num = $pan_xlh_num+1;
$cache_key = 'selected_gift_id_'.$room_id.$gift_bag_detail['foreign_id'];
if($pan_xlh_num <= 1){
$add_end_time = $ext['locking_time']['tow_no_locking_time'] * 60;
Cache::set($cache_key,$add_end_time,$add_end_time);
}else{
// $add_end_time = ($ext['locking_time']['tow_no_locking_time']-$ext['locking_time']['next_time']) * 60;
if(Cache::get($cache_key)){
$erci_xlh_num = Cache::get($cache_key);
$add_end_time = ($erci_xlh_num-$ext['locking_time']['next_time'] *60);
Cache::set($cache_key,$add_end_time,$add_end_time);
}else{
$add_end_time = ($ext['locking_time']['tow_no_locking_time']-$ext['locking_time']['next_time']) * 60;
}
}
if($add_end_time <= 30){
Cache::set($cache_key,30,30);
$add_end_time = 30;
}
$end_time = time() + $add_end_time;
db::name('vs_room_pan_xlh')->where('id',$pan_xlh['id'])->update([
'user_id' => $user_id,
'pay_price' =>$ext['xlh_box_price'],
'locking_gift_id' =>$gift_bag_detail['foreign_id'],
'num' => $pan_xlh_num,
'end_time' => $end_time,
'updatetime' => time()
]);
db::name('vs_room_pan_xlh_log')->insertGetId([
'xlh_id' => $pan_xlh['id'],
'user_id' => $user_id,
'num' => $pan_xlh_num,
'locking_end_time' => $end_time,
'createtime' => time()
]);
$is_zhong_jiang = 1;
}
//减去盲盒包礼物数量
$ret = db::name("vs_room_pan")->where(['room_id'=>$room_id,'gift_bag_detail_id'=>$gift_bag_detail['id']])->setDec('remaining_number',1);
if(!$ret){
db::rollback();
return ['code' => 0, 'msg' => '失败.', 'data' => []];
}
//判断剩余数量是否为0 为0重置进入下一期
$gift_bag_num = db::name("vs_room_pan")->where(['room_id'=>$room_id,'gift_bag_id'=>$gift_bag_id])->sum('remaining_number');
if($gift_bag_num <= 0){
db::name("vs_room_pan")->where(['room_id'=>$room_id,'gift_bag_id'=>$gift_bag_id])->setInc('periods');
db::name("vs_room_pan")->where(['room_id'=>$room_id,'gift_bag_id'=>$gift_bag_id])->update(
['remaining_number' => db::raw('(SELECT quantity FROM fa_vs_gift_bag_detail WHERE id = fa_vs_room_pan.gift_bag_detail_id)')]);
}
}else{
db::rollback();
return ['code' => 0, 'msg' => '失败!', 'data' => []];
}
$result_data[] = [
'user_id' => $user_id,
'gift_id'=>$gift_bag_detail['foreign_id'],
'gift_price'=>$gift['gift_price'],
'gift_name'=>$gift['gift_name'],
'base_image'=>$gift['base_image'],
];
}
$reslut_data = [];
foreach ($result_data as $key => $value) {
$gift_id = $value['gift_id'];
if (!isset($reslut_data[$gift_id])) {
$reslut_data[$gift_id] = [
'gift_id' => $gift_id,
'gift_price'=>$value['gift_price'],
'gift_name'=>$value['gift_name'],
'base_image'=>$value['base_image'],
'count' => 1
];
}else {
$reslut_data[$gift_id]['count']++;
}
}
$result_list = [];
foreach ($reslut_data as $key => $value) {
//处理礼包发放记录表
$data = [];
$data['user_id'] = $user_id;
$data['parent_id'] = $pan_xlh['id'];
$data['gift_bag_id'] = $gift_bag_id;
$data['gift_id'] = $value['gift_id'];
$data['periods'] = $room_pan['periods'];
$data['room_id'] = $room_id;
$data['num'] = $value['count'];
$data['gift_price'] = $value['gift_price'];
$data['bag_price'] = $ext['xlh_box_price'];
$data['createtime'] = time();
$result = db::name("vs_gift_bag_receive_log")->insert($data);
if(!$result){
db::rollback();
return ['code' => 0, 'msg' => '失败,', 'data' => []];
}
$result_list[]=[
'gift_id'=>$value['gift_id'],
'gift_name'=>$value['gift_name'],
'base_image' =>$value['base_image'],
'gift_price'=>$value['gift_price'],
'count'=>$value['count'],
];
}
// 添加活动记录
$reslut = Db::name('vs_activities_receive')->insert([
'user_id' => $user_id,
'activities_id' => 6,
'room_id' => $room_id,
'createtime' => time(),
'updatetime' => time()
]);
db::commit();
} catch(\Exception $e) {
db::rollback();
return V(0,$e->getMessage());
}
if($is_zhong_jiang == 1){
//推送
$FromUserInfo = db::name('user')->field('nickname,avatar')->where(['id'=>$user_id])->find();
$room_name = db::name('vs_room')->where(['id'=>$room_id])->value('room_name');
$gift_name = db::name('vs_gift')->where(['gid'=>$value['gift_id']])->value('gift_name');
$text = $FromUserInfo['nickname'] . ' 用户在 ' . $room_name.' 房间巡乐会中 ' .$gift_name.'礼物 x ' .$value['count']." 已收入背包";
$text = [
'gift_num' => $pan_xlh_num,
'FromUserInfo' => $FromUserInfo,
'end_time' => $end_time,
'text' => $text
];
//聊天室推送系统消息
model('Chat')->sendMsg(1057,$room_id,$text);
}
//返回结果排序
usort($result_list, function($a, $b) {
return $b['gift_price'] <=> $a['gift_price'];
});
return ['code' => 1, 'msg' => '成功', 'data' => $result_list];
}
/*
* 巡乐会抽奖记录
*/
public function xlh_get_user_record($user_id,$room_id,$page=1,$page_size=12){
$where = [];
$where['a.gift_bag_id'] = 13;
$where['a.user_id'] = $user_id;
$where['a.room_id'] = $room_id;
$list = db('vs_gift_bag_receive_log')
->alias('a')
->join('vs_room_pan_xlh b','b.id = a.parent_id','left')
->join('vs_gift c','c.gid = a.gift_id','left')
->field('a.gift_id,a.num as count,a.createtime,c.gift_name as gift_name,c.base_image')
->where($where)
->order('a.createtime desc')
->page($page,$page_size)
->select();
foreach ($list as &$v){
$v['createtime'] = date('Y-m-d H:i:s',$v['createtime']);
}
return ['code' => 1, 'msg' => '成功', 'data' => $list];
}
/*
* 巡乐会榜单
*/
public function xlh_ranking($room_id,$page=1,$page_size=12){
$where = [];
$where['a.gift_bag_id'] = 13;
$where['a.room_id'] = $room_id;
$where['e.is_world_show'] = 1;
$list = db('vs_gift_bag_receive_log')
->alias('a')
->join('vs_room_pan_xlh b','b.id = a.parent_id','left')
->join('vs_gift c','c.gid = a.gift_id','left')
->join('fa_user d','d.id = a.user_id','left')
->join('vs_gift_bag_detail e','e.foreign_id = a.gift_id','left')
->field('a.gift_id,a.num as count,a.createtime,c.gift_name,c.base_image,d.nickname')
->where($where)
->order('a.createtime desc')
->page($page,$page_size)
->select();
foreach ($list as &$v){
$v['createtime'] = date('Y-m-d H:i:s',$v['createtime']);
}
return ['code' => 1, 'msg' => '成功', 'data' => $list];
}
/*
* 获取用户当前房间的巡乐会信息
*/
public function get_user_xlh_info($room_id){
$gift_bag_id = 13;
$xlh_box = db::name('vs_gift_bag')->where('id',$gift_bag_id)->find();
$xlh_ext = json_decode($xlh_box['ext'],true);
$room_data = db('vs_room')
->where(['id'=>$room_id])
->field('id,room_name,xlh_periods,xlh_periods_num')
->find();
$xlh_data = db('vs_room_pan_xlh')
->where(["room_id"=>$room_id,"periods"=>$room_data['xlh_periods']])
->field('id,room_id,periods,end_time')
->find();
//寻乐会状态
$xlh_status = 0;
// 状态
if($room_data['xlh_periods_num'] >= $xlh_ext['open_condition']['start_num']){
$xlh_status = 1;//状态 1:巡乐会开始 2:即将开始 0:等待开始
} elseif($room_data['xlh_periods_num'] >= $xlh_ext['open_condition']['waiting_start_num'] && $room_data['xlh_periods_num'] < $xlh_ext['open_condition']['start_num']){
$xlh_status = 2;//状态 1:巡乐会开始 2:即将开始开始 0:等待开始
}else{
$xlh_status = 0;//未开始
}
return [
'activities_name' => $xlh_box['name'],
'icon' => null,
'xlh_status'=>$xlh_status,
'end_time'=>$xlh_data['end_time'] ?? 0,
];
}
}