2025-12-30 11:37:21 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
// application/common/library/GiftTableManager.php
|
|
|
|
|
|
|
|
|
|
|
|
namespace app\common\library;
|
|
|
|
|
|
|
|
|
|
|
|
use think\Db;
|
|
|
|
|
|
use think\Exception;
|
2025-12-30 15:25:58 +08:00
|
|
|
|
use think\Log;
|
2025-12-30 11:37:21 +08:00
|
|
|
|
|
|
|
|
|
|
class GiftTableManager
|
|
|
|
|
|
{
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 根据时间戳获取分表名
|
|
|
|
|
|
* @param int $timestamp 时间戳
|
|
|
|
|
|
* @return string 表名
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function getTableName($timestamp = null)
|
|
|
|
|
|
{
|
|
|
|
|
|
$timestamp = $timestamp ?: time();
|
|
|
|
|
|
$month = date('Ym', $timestamp);
|
|
|
|
|
|
return 'fa_vs_give_gift_' . $month;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 创建月份分表(纯PHP实现,不使用存储过程)
|
|
|
|
|
|
* @param string $yearMonth 年月格式:202401
|
|
|
|
|
|
* @return bool
|
|
|
|
|
|
* @throws Exception
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function createMonthTable($yearMonth)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!preg_match('/^\d{6}$/', $yearMonth)) {
|
|
|
|
|
|
throw new Exception('年月格式错误');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$tableName = 'fa_vs_give_gift_' . $yearMonth;
|
|
|
|
|
|
|
|
|
|
|
|
// 检查表是否已存在
|
|
|
|
|
|
try {
|
|
|
|
|
|
$checkSql = "SHOW TABLES LIKE '{$tableName}'";
|
|
|
|
|
|
$exists = Db::query($checkSql);
|
|
|
|
|
|
if ($exists) {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
|
// 表不存在,继续创建
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建分表SQL
|
|
|
|
|
|
$sql = "
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS `{$tableName}` (
|
|
|
|
|
|
`id` bigint NOT NULL COMMENT '雪花ID',
|
|
|
|
|
|
`user_id` int NOT NULL DEFAULT '0' COMMENT '用户id 送礼物的人',
|
|
|
|
|
|
`gift_id` int NOT NULL DEFAULT '0' COMMENT '礼物id',
|
|
|
|
|
|
`gift_type` tinyint(1) NOT NULL DEFAULT '1' COMMENT '礼物类型,1-正常礼物,2-盲盒开出来的,3-签约金币',
|
|
|
|
|
|
`number` int unsigned NOT NULL DEFAULT '0' COMMENT '礼物数量',
|
|
|
|
|
|
`gift_user` int NOT NULL DEFAULT '0' COMMENT '收礼物的人',
|
|
|
|
|
|
`from_id` int NOT NULL DEFAULT '0' COMMENT '来源ID,(房间ID)',
|
|
|
|
|
|
`pit_number` int NOT NULL DEFAULT '0' COMMENT '麦位编号(废弃)',
|
|
|
|
|
|
`total_price` decimal(16,2) NOT NULL COMMENT '礼物总价值',
|
|
|
|
|
|
`type` int NOT NULL DEFAULT '1' COMMENT '1金币购买 2送背包礼物',
|
|
|
|
|
|
`from` int NOT NULL DEFAULT '1' COMMENT '1私聊送礼物 2语聊房送礼 3视频直播房送礼(暂时不用) 4动态打赏 6私密房间送礼',
|
2026-01-07 11:53:15 +08:00
|
|
|
|
`remarks` varchar(255) NULL COMMENT '备注',
|
2025-12-30 11:37:21 +08:00
|
|
|
|
`createtime` bigint NOT NULL COMMENT '创建时间(秒时间戳)',
|
|
|
|
|
|
`updatetime` bigint DEFAULT NULL COMMENT '更新时间(秒时间戳)',
|
|
|
|
|
|
PRIMARY KEY (`id`),
|
|
|
|
|
|
KEY `idx_createtime` (`createtime`) USING BTREE,
|
|
|
|
|
|
KEY `idx_user_id` (`user_id`) USING BTREE,
|
|
|
|
|
|
KEY `idx_gift_user` (`gift_user`) USING BTREE,
|
|
|
|
|
|
KEY `idx_from_id` (`from_id`) USING BTREE,
|
|
|
|
|
|
KEY `idx_room_user_time` (`from_id`, `user_id`, `createtime`) USING BTREE,
|
|
|
|
|
|
KEY `idx_room_receiver_time` (`from_id`, `gift_user`, `createtime`) USING BTREE,
|
|
|
|
|
|
KEY `idx_user_time` (`user_id`, `createtime`) USING BTREE,
|
|
|
|
|
|
KEY `idx_receiver_time` (`gift_user`, `createtime`) USING BTREE,
|
|
|
|
|
|
KEY `idx_combined_search` (`from_id`, `user_id`, `gift_user`, `createtime`) USING BTREE
|
|
|
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户送礼表_{$yearMonth}'
|
|
|
|
|
|
";
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
Db::execute($sql);
|
|
|
|
|
|
|
|
|
|
|
|
// 计算时间范围
|
|
|
|
|
|
$startTime = strtotime($yearMonth . '01 00:00:00');
|
|
|
|
|
|
$endTime = strtotime(date('Y-m-01', strtotime('+1 month', $startTime)));
|
|
|
|
|
|
|
|
|
|
|
|
// 记录分表信息
|
|
|
|
|
|
$tableInfo = Db::name('vs_give_gift_tables')
|
|
|
|
|
|
->where('table_name', $tableName)
|
|
|
|
|
|
->find();
|
|
|
|
|
|
|
|
|
|
|
|
if (!$tableInfo) {
|
|
|
|
|
|
Db::name('vs_give_gift_tables')->insert([
|
|
|
|
|
|
'table_name' => $tableName,
|
|
|
|
|
|
'start_time' => $startTime,
|
|
|
|
|
|
'end_time' => $endTime,
|
|
|
|
|
|
'create_time' => time()
|
|
|
|
|
|
]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Log::info("创建分表成功: {$tableName}");
|
|
|
|
|
|
return true;
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
|
Log::error("创建分表失败 {$tableName}: " . $e->getMessage());
|
|
|
|
|
|
throw new Exception('创建分表失败:' . $e->getMessage());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 批量创建分表
|
|
|
|
|
|
* @param int $months 创建未来几个月
|
|
|
|
|
|
* @return array 创建结果
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function batchCreateTables($months = 12)
|
|
|
|
|
|
{
|
|
|
|
|
|
$results = [];
|
|
|
|
|
|
|
|
|
|
|
|
for ($i = 0; $i < $months; $i++) {
|
|
|
|
|
|
$yearMonth = date('Ym', strtotime("+{$i} month"));
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
$result = self::createMonthTable($yearMonth);
|
|
|
|
|
|
$results[$yearMonth] = [
|
|
|
|
|
|
'success' => $result,
|
|
|
|
|
|
'message' => $result ? '创建成功' : '创建失败'
|
|
|
|
|
|
];
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
|
$results[$yearMonth] = [
|
|
|
|
|
|
'success' => false,
|
|
|
|
|
|
'message' => $e->getMessage()
|
|
|
|
|
|
];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return $results;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取所有分表
|
|
|
|
|
|
* @return array
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function getAllTables()
|
|
|
|
|
|
{
|
|
|
|
|
|
try {
|
|
|
|
|
|
return Db::name('vs_give_gift_tables')
|
|
|
|
|
|
->order('start_time', 'asc')
|
|
|
|
|
|
->select();
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
|
Log::error("获取分表列表失败: " . $e->getMessage());
|
|
|
|
|
|
return [];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 根据时间范围获取需要查询的表
|
|
|
|
|
|
* @param int $startTime 开始时间戳
|
|
|
|
|
|
* @param int $endTime 结束时间戳
|
|
|
|
|
|
* @return array 表名数组
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function getTablesByTimeRange($startTime = null, $endTime = null)
|
|
|
|
|
|
{
|
|
|
|
|
|
try {
|
|
|
|
|
|
$query = Db::name('vs_give_gift_tables');
|
|
|
|
|
|
|
|
|
|
|
|
if ($startTime !== null) {
|
|
|
|
|
|
$query->where('end_time', '>=', $startTime);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ($endTime !== null) {
|
|
|
|
|
|
$query->where('start_time', '<=', $endTime);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$tables = $query->order('start_time', 'asc')
|
|
|
|
|
|
->column('table_name');
|
|
|
|
|
|
|
|
|
|
|
|
return $tables ?: [];
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
|
Log::error("获取时间范围分表失败: " . $e->getMessage());
|
|
|
|
|
|
return [];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 初始化分表系统
|
|
|
|
|
|
* @param string $startMonth 起始年月 202401
|
|
|
|
|
|
* @param int $months 创建几个月
|
|
|
|
|
|
* @return array
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function initTables($startMonth = null, $months = 24)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!$startMonth) {
|
|
|
|
|
|
$startMonth = date('Ym');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$results = [];
|
|
|
|
|
|
$startDate = new \DateTime($startMonth . '01');
|
|
|
|
|
|
|
|
|
|
|
|
for ($i = 0; $i < $months; $i++) {
|
|
|
|
|
|
$currentDate = clone $startDate;
|
|
|
|
|
|
$currentDate->modify("+{$i} month");
|
|
|
|
|
|
$yearMonth = $currentDate->format('Ym');
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
$result = self::createMonthTable($yearMonth);
|
|
|
|
|
|
$results[$yearMonth] = $result;
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
|
$results[$yearMonth] = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return $results;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检查并创建当前月份的表
|
|
|
|
|
|
* @return bool
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function checkAndCreateCurrentMonthTable()
|
|
|
|
|
|
{
|
|
|
|
|
|
$currentMonth = date('Ym');
|
|
|
|
|
|
return self::createMonthTable($currentMonth);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|