This commit is contained in:
2025-08-13 18:31:52 +08:00
parent 17ad88608b
commit 275713f893
77 changed files with 10658 additions and 178 deletions

230
app/utils/RedisUtils.php Normal file
View File

@@ -0,0 +1,230 @@
<?php
namespace app\utils;
use app\exception\SysException;
use support\think\Cache;
class RedisUtils
{
const CAN_CREATE_ORDER = 'can_create_order:';
const CREATE_ORDER_LIMIT = 'createOrder:';
const CAN_CASH = 'cash:canCash:';
public static function checkCanCreateOrder($userId)
{
$val = cache(self::CAN_CREATE_ORDER . $userId);
return empty($val);
}
public static function setUserCanCreateOrder($userId, $seconds)
{
cache(self::CAN_CREATE_ORDER . $userId, 1, $seconds);
}
public static function setCreateOrderFlagAndCheckLimit($userId, $orderId): bool
{
// 构造 key
$key = "createOrder:{$userId}:{$orderId}";
// 设置 Redis key值为 orderId过期时间 60 秒
Cache::store('redis')->set($key, (string)$orderId, 60);
// 获取 Redis 原生实例
$redis = Cache::store('redis')->handler();
// 使用 scan 非阻塞统计 key 数量
$pattern = "createOrder:{$userId}:*";
$iterator = null;
$count = 0;
while ($keys = $redis->scan($iterator, $pattern, 100)) {
$count += count($keys);
}
// 超过 22 返回 true
return $count > 22;
}
/**
* 通用的“按周统计”计数器(自动按课程 ID、业务类型区分
*
* @param string $prefix 前缀标识,如 'course:week_play:'
* @param int|string $id 主体 ID如课程 ID
* @param int $expireSeconds 默认过期时间(秒),默认 7 天
* @return int 返回当前统计值
*/
public static function incrWeekCounter(string $prefix, $id, int $expireSeconds = 604800): int
{
$key = $prefix . date('oW') . ':' . $id; // oW 为当前“ISO 年 + 周数”,确保每周一个 key
$count = Cache::store('redis')->inc($key);
// 第一次设置时设定过期时间
if ($count === 1) {
Cache::store('redis')->expire($key, $expireSeconds);
}
return $count;
}
public static function getconfig()
{
return Cache::getConfig();
}
/**
* 获取指定“周统计”计数值
*
* @param string $prefix 前缀
* @param int|string $id 主体 ID
* @return int
*/
public static function getWeekCounter(string $prefix, $id): int
{
$key = $prefix . date('oW') . ':' . $id;
return (int)Cache::store('redis')->get($key, 0);
}
public static function isCanCash($userId)
{
$val = cache(self::CAN_CASH . $userId);
return !empty($val);
}
public static function checkRealCount(int $userId)
{
$key = 'updateAuthCertInfo:' . $userId;
$val = cache($key);
if (!empty($val)) {
throw new SysException("实名修改失败: 每月可修改次数已用完,请联系管理员");
}
}
public static function setRealCount(int $userId)
{
$key = 'updateAuthCertInfo:' . $userId;
cache($key, 2628000);
}
private static function getFreeWatchKey($userId, $permanently = false)
{
if ($permanently) {
return "free:watch:" . $userId;
}
return "free:watch:" . date('Y-m-d') . ':' . $userId;
}
public static function isExpiredSet($key)
{
$redis = Cache::store('redis')->handler();
// 获取 key 的剩余过期时间(单位:秒)
$ttl = $redis->ttl($key);
if ($ttl == -1) {
return false;
}
return $ttl !== -2;
}
public static function getFreeWatchTimeIsExpire($userId)
{
$freeWatchKey = self::getFreeWatchKey($userId, true);
$permanentlyFreeWatch = cache($freeWatchKey);
$watchKey = self::getFreeWatchKey($userId, false);
$payFreeWatchInfo = cache($watchKey);
$expireTime = -1;
$jsonObject = null;
if (!empty($payFreeWatchInfo)) {
$jsonObject = json_decode($payFreeWatchInfo, true);
$expireTime = isset($jsonObject['expireTime']) ? $jsonObject['expireTime'] : -1;
}
$now = time(); // 当前时间戳
if ((!empty($permanentlyFreeWatch) && RedisUtils::isExpiredSet($freeWatchKey)) ||
(!empty($permanentlyFreeWatch) && $now >= $expireTime)) {
if (empty($permanentlyFreeWatch)) {
return null;
}
if (!RedisUtils::isExpiredSet($freeWatchKey)) {
cache($freeWatchKey, intval($permanentlyFreeWatch));
}
return false;
} else {
if (empty($payFreeWatchInfo)) {
return null;
}
$second = isset($jsonObject['second']) ? intval($jsonObject['second']) : 0;
if ($expireTime == -1) {
$jsonObject['expireTime'] = $now + $second;
$tomorrowZero = strtotime(date('Y-m-d', strtotime('+1 day')));
$expire = $tomorrowZero - $now;
cache($watchKey, json_encode($jsonObject), $expire);
return false;
} else {
return $now > $expireTime;
}
}
}
public static function setFreeWatchTime($userId, $second, $isPermanently = false)
{
$now = time();
$tomorrow = strtotime(date('Y-m-d', strtotime('+1 day')));
$freeWatchKey = self::getFreeWatchKey($userId, $isPermanently);
if ($isPermanently) {
$data = cache($freeWatchKey);
if (empty($data)) {
// 永久的,但不设置过期时间(-1
cache($freeWatchKey, $second);
} else {
$expire = Cache::store('redis')->handler()->ttl($freeWatchKey);
if ($expire === -1 || $expire === false || $expire === null) {
$expire = -1;
} else {
$expire += intval($second);
}
$newValue = intval($data) + intval($second);
if ($expire > 0) {
cache($freeWatchKey, $newValue, $expire);
} else {
cache($freeWatchKey, $newValue);
}
}
} else {
// 非永久,临时有效期到明天零点
$expire = $tomorrow - $now;
$jsonObject = [
'expireTime' => -1,
'second' => intval($second)
];
// 如果不存在才设置
if (!Cache::store('redis')->has($freeWatchKey)) {
cache($freeWatchKey, json_encode($jsonObject), $expire);
}
}
}
public static function setCanCashFlag(mixed $userId, int $param)
{
cache("cash:canCash:".$userId, $param,300);
}
}