230 lines
6.7 KiB
PHP
230 lines
6.7 KiB
PHP
<?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);
|
||
}
|
||
|
||
} |