This commit is contained in:
2026-03-04 11:30:40 +08:00
parent 9ff5e028b0
commit 189dad2809
3767 changed files with 1056662 additions and 0 deletions

View File

@@ -0,0 +1,276 @@
import { _decorator } from 'cc';
import BaseManager from '../../base/BaseManager';
const { ccclass } = _decorator;
type ICallback = (...args: any[]) => any;
class DailyTimer {
// 获取当前时间相对于当日零点的毫秒数
private static getDayTimeMs(date: Date): number {
return (
date.getHours() * 3600 +
date.getMinutes() * 60 +
date.getSeconds()
) * 1000 + date.getMilliseconds();
}
// 静态方法解析时间为毫秒数
private static parseTimeToMs(h: number, m: number, s: number): number {
return ((h * 3600 + m * 60 + s) * 1000) % 86400000;
}
private readonly startMs: number; // 起始时间毫秒数(相对于当日零点)
private readonly endMs: number; // 结束时间毫秒数
// 用于检查当前时间是否可触发回调
private checkDay = 0;
constructor(
time: string,
public readonly callback: ICallback,
public readonly target?: unknown,
public readonly once: boolean = false
) {
// 使用解构赋值提高可读性
const [startSegment, endSegment = startSegment] = time.split('-');
// 开始时间
const [startH = 0, startM = 0, startS = 0] = startSegment.split(':').map(
part => Math.max(0, parseInt(part, 10) || 0)
);
this.startMs = DailyTimer.parseTimeToMs(startH, startM, startS);
// 结束时间
const [endH = 0, endM = 0, endS = 0] = endSegment.split(':').map(
part => Math.max(0, parseInt(part, 10) || 0)
);
this.endMs = DailyTimer.parseTimeToMs(endH, endM, endS);
// 结束时间与开始时间不能相同
if (this.endMs === this.startMs) {
if (startM === 0 && startS === 0) {
this.endMs = DailyTimer.parseTimeToMs(startH + 1, startM, startS);
} else if (startS === 0) {
this.endMs = DailyTimer.parseTimeToMs(startH, startM + 1, startS);
} else {
this.endMs = DailyTimer.parseTimeToMs(startH, startM, startS + 1);
}
}
}
// 获取当前时间是否在时间范围内
private isInRange(now: Date): boolean {
const currentMs = DailyTimer.getDayTimeMs(now);
// 处理跨天时间段(如 23:00-01:00
return this.startMs <= this.endMs
? currentMs >= this.startMs && currentMs < this.endMs
: currentMs >= this.startMs || currentMs < this.endMs;
}
update(now: Date): boolean {
const dateDay = now.getDay();
if (this.checkDay === dateDay) return false;
if (!this.isInRange(now)) return false;
this.checkDay = dateDay;
this.callback.call(this.target);
return this.once;
}
}
class IntervalTimer {
private elapsed: number = 0;
constructor(
public readonly interval: number,
public readonly callback: ICallback,
public readonly target?: unknown,
public readonly once: boolean = false
) { }
update(dt: number): boolean {
this.elapsed += dt;
let completed = false;
// 处理可能多次触发的情况当dt > interval时
while (this.elapsed >= this.interval) {
this.callback.call(this.target);
this.elapsed -= this.interval;
if (this.once) {
completed = true;
break;
}
}
return completed;
}
}
class Timer {
static update(timer: Timer, dt: number) {
return timer.update(dt);
}
private intervalTimer: IntervalTimer[] = [];
/**
* 注册定时器
* @param interval
* @param callback
* @param target
* @param once
*/
register(
interval: number,
callback: ICallback,
target?: unknown,
once?: boolean
): void {
const timer = new IntervalTimer(interval, callback, target, once || false);
this.intervalTimer.push(timer);
}
/**
* 取消定时器
* @param callback
* @param target
*/
unregister(callback: ICallback, target?: unknown): void {
if (typeof target === 'undefined') {
this.intervalTimer = this.intervalTimer.filter(
timer => timer.callback !== callback
);
} else {
this.intervalTimer = this.intervalTimer.filter(
timer => !(timer.callback === callback && timer.target === target)
);
}
}
/**
* 取消所有定时器
*/
unregisterAll() {
this.intervalTimer = [];
}
private dailyTimers: DailyTimer[] = [];
/**
* 注册每日触发器
* @param time 24小时制,精确到秒
*
* @example
* registerDailyTrigger('16', ...) 等同于 registerDailyTrigger('16-17', ...)
* registerDailyTrigger('8-9:00', ...) 等同于 registerDailyTrigger('8', ...)
* registerDailyTrigger('8:00:01-24', ...)
*/
registerDailyTrigger(
time: string,
callback: ICallback,
target?: unknown,
once?: boolean
) {
const timer = new DailyTimer(time, callback, target, once || false);
this.dailyTimers.push(timer);
}
/**
* 取消每日触发器
*/
unregisterDailyTrigger(callback: ICallback, target?: unknown) {
if (typeof target === 'undefined') {
this.dailyTimers = this.dailyTimers.filter(
timer => timer.callback !== callback
);
} else {
this.dailyTimers = this.dailyTimers.filter(
timer => !(timer.callback === callback && timer.target === target)
);
}
}
/**
* 取消所有每日触发器
*/
unregisterAllDailyTrigger() {
this.dailyTimers = [];
}
/**
* 清除所有定时器和触发器
*/
clear() {
this.intervalTimer = [];
this.dailyTimers = [];
}
protected update(dt: number): void {
for (let index = 0; index < this.intervalTimer.length; index++) {
const timer = this.intervalTimer[index];
if (timer.update(dt)) {
this.intervalTimer.splice(index, 1);
index--;
}
}
const date = new Date();
for (let index = 0; index < this.dailyTimers.length; index++) {
const timer = this.dailyTimers[index];
if (timer.update(date)) {
this.dailyTimers.splice(index, 1);
index--;
}
}
}
}
@ccclass('TimerManager')
export default class TimerManager extends BaseManager {
private timers: Map<string | number | Symbol, Timer> = new Map();
/**
* 清除所有定时器
*/
clear() {
this.timers.forEach((timer) => {
timer.clear();
});
this.timers.clear();
}
/**
* 删除定时器
* @param key 定时器key
*/
delete(key: string | number | Symbol) {
const timer = this.timers.get(key);
if (!timer) return;
this.timers.delete(key);
timer.clear();
}
/**
* 获取定时器
* @param key 定时器key
*/
get(key: string | number | Symbol): Timer {
if (this.timers.has(key)) {
return this.timers.get(key);
}
const timer = new Timer();
this.timers.set(key, timer);
return timer;
}
protected update(dt: number): void {
this.timers.forEach((timer) => {
Timer.update(timer, dt);
});
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "b5636f8d-3516-4510-aaba-74f9202b8a9f",
"files": [],
"subMetas": {},
"userData": {}
}