Files
yusheng-php/application/common/library/GiftTableManager.php
2025-12-30 11:37:21 +08:00

221 lines
7.2 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
// application/common/library/GiftTableManager.php
namespace app\common\library;
use think\Db;
use think\Exception;
use think\facade\Log;
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私密房间送礼',
`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);
}
}