first commit

This commit is contained in:
2026-03-30 09:39:59 +08:00
parent 6c52425fca
commit 5ac73d3c6d
4484 changed files with 1144395 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "e939f63c-c853-403c-aed7-b8f0925106f0",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

View File

@@ -0,0 +1,40 @@
import { DEBUG, DEV } from 'cc/env';
function jsGetSet(obj: unknown, prop: string, getter: Function, setter?: Function) {
Object.defineProperty(obj, prop, {
get: getter as any,
set: setter as any,
enumerable: false,
configurable: false
});
}
function clear(object: Record<string | number, any>) {
if (!object) return;
for (const key of Object.keys(object)) {
delete object[key];
}
}
/**
* 将某个变量设置为不可观测(不可在浏览器中打印)
* @param owner object | string | number | boolean | Array | Function | ...
* @param callback 被观测时触发回调
* @returns
*/
export function unobservable(owner: unknown, callback?: Function) {
if (DEV || DEBUG) return;
if (!owner) return;
function define() {
function accessor() {
if (callback) {
callback();
} else {
clear(owner);
}
}
try {
jsGetSet(owner, 'unobservable', accessor.bind(null, 'de' + 'bu' + 'gg' + 'er'));
}
catch (e) { !0; }
}
define();
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "c0d5da3b-23f0-400e-85bb-6c754b9c08eb",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "140d98c1-6885-4e37-bf16-2ee67ffe087e",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,77 @@
import { DEV } from 'cc/env';
interface ILog {
(title: string, ...args: any[]): void
}
function empty() { }
/**
* 日志管理类,用于统一日志输出格式
*/
export class Logger {
static setting: {
filter: Array<'log' | 'warn' | 'error'>
} = {
filter: ['error', 'log', 'warn']
};
/**
* 创建日志输出函数
*/
static create(level: 'log' | 'warn' | 'error', styleColor: string, title: string, titleColor = '#fff') {
if (this.setting.filter.indexOf(level) == -1) {
return empty;
}
if (DEV) {
return window.console[level].bind(window.console,
'%c %s %c %s ',
`background:${styleColor}; padding: 2px; border-radius: 5px 0 0 5px; border: 1px solid ${styleColor}; color: ${titleColor}; font-weight: normal;`,
`${title} ${new Date().toLocaleString()}`,
`background:#ffffff ; padding: 2px; border-radius: 0 5px 5px 0; border: 1px solid ${styleColor}; color: ${styleColor}; font-weight: normal;`
);
}
return window.console[level].bind(window.console,
`${title} [${new Date().toLocaleString()}]`
);
}
/**
* 用于输出一般信息
*/
get log() {
return Logger.create('log', '#6495ed', '[LOG]', '#000') as ILog;
}
/**
* 用于输出警告信息
*/
get warn() {
return Logger.create('warn', '#ff7f50', '[WARN]', '#000') as ILog;
}
/**
* 用于输出错误信息
*/
get error() {
return Logger.create('error', '#ff4757', '[ERROR]', '#000') as ILog;
}
/**
* 用于输出调试信息
*/
get debug() {
return Logger.create('log', '#ff6347', '[DEBUG]', '#000') as ILog;
}
/**
* 用于输出成功信息
*/
get success() {
return Logger.create('log', '#00ae9d', '[SUCC]', '#000') as ILog;
}
}
export default new Logger();

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "0b5812e8-b67d-4ba9-83d8-12ca1e46cfd0",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,12 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "0c157f59-fd16-449c-b42c-d0efa2dc1401",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

View File

@@ -0,0 +1,236 @@
import { error, js, log, sys } from 'cc';
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
function encode(text: string, key: string) {
key = key || chars;
let encrypted = '';
for (let i = 0; i < text.length; i++) {
const charCode = text.charCodeAt(i) ^ key.charCodeAt(i % key.length);
encrypted += String.fromCharCode(charCode);
}
return encrypted;
}
function decode(encryptedText: string, key: string) {
key = key || chars;
let decrypted = '';
for (let i = 0; i < encryptedText.length; i++) {
const charCode = encryptedText.charCodeAt(i) ^ key.charCodeAt(i % key.length);
decrypted += String.fromCharCode(charCode);
}
return decrypted;
}
const weekOfYear = function (curDate?: Date) {
/*
date1是当前日期
date2是当年第一天
d是当前日期是今年第多少天
用d + 当前年的第一天的周差距的和在除以7就是本年第几周
*/
curDate = curDate || new Date();
let a = curDate.getFullYear();
let b = curDate.getMonth() + 1;
let c = curDate.getDate();
let date1 = new Date(a, b - 1, c), date2 = new Date(a, 0, 1),
d = Math.round((date1.valueOf() - date2.valueOf()) / 86400000);
return Math.ceil(
(d + ((date2.getDay() + 1) - 1)) / 7
);
};
const getWeekUpdateTime = function () {
const date = new Date();
const year = date.getFullYear();
const week = weekOfYear(date);
return year + '' + week;
};
const getDayUpdateTime = function (curDate?: Date) {
curDate = curDate || new Date();
return curDate.toLocaleDateString();
};
export class Storage {
static setting: {
/**
* 加密密钥
* - 如果需要加密内容,请设置密钥的值
*/
secretKey: string
} = {
secretKey: ''
};
private _cache = {};
/**
* 返回值为false代表调用失败
*/
set(key: string, value: unknown) {
if (typeof key === 'string' && typeof value !== 'undefined') {
try {
const data = JSON.stringify(value);
if (Storage.setting.secretKey) {
sys.localStorage.setItem(key, encode(data, Storage.setting.secretKey));
} else {
sys.localStorage.setItem(key, data);
}
// 设置缓存
this._cache[key] = data;
return true;
} catch (err) { log(err); }
} else {
error('storage set error');
}
return false;
}
/**
* 返回值为undefined代表调用失败
*/
get(key: string) {
// 先读取缓存
if (typeof this._cache[key] !== 'undefined') {
return JSON.parse(this._cache[key]);
}
let result = null;
try {
let data = sys.localStorage.getItem(key);
if (data && typeof data === 'string') {
if (Storage.setting.secretKey) data = decode(data, Storage.setting.secretKey);
// 设置缓存
this._cache[key] = data;
result = JSON.parse(data);
} else if (data !== '' && data !== null) {
result = undefined;
}
} catch (e) {
result = undefined;
}
return result;
}
/**
* 返回值为false代表调用失败
*/
add(key: string, value: number = 1) {
let result = this.get(key);
if (result !== undefined) {
result = result || 0;
result += value;
if (this.set(key, result)) {
return result;
}
}
return false;
}
/**
* 返回值为false代表调用失败
*/
remove(key: string) {
try {
sys.localStorage.removeItem(key);
delete this._cache[key];
return true;
} catch (err) {
return false;
}
}
/**
* 返回值为false代表调用失败
*/
clear() {
try {
sys.localStorage.clear();
js.clear(this._cache);
return true;
} catch (err) {
return false;
}
}
/**
* 设置本周数据 [返回值为false代表调用失败]
* @param {Function} cb 当已存在本周的数据时会根据cb的返回决定是否存储true代表存储
*/
setWeek(key: string, value: unknown, cb?: (oldValue: unknown, newValue: unknown) => boolean) {
const updateTime = getWeekUpdateTime();
if (cb) {
const data = this.getWeek(key);
if (data !== undefined) {
if (data === null || cb(data, value)) {
return this.set(key, {
data: value,
updateTime: updateTime
});
}
}
} else {
return this.set(key, {
data: value,
updateTime: updateTime
});
}
return false;
}
/**
* 获取本周数据 [返回值为undefined代表调用失败]
*/
getWeek(key: string) {
const data = this.get(key);
if (data && data.updateTime == getWeekUpdateTime()) {
return data.data;
}
return data && null;
}
/**
* 设置本天数据 [返回值为false代表调用失败]
* @param {Function} cb 当已存在本天的数据时会根据cb的返回决定是否存储true代表存储
*/
setDay(key: string, value: unknown, cb?: (oldValue: unknown, newValue: unknown) => boolean) {
const updateTime = getDayUpdateTime();
if (cb) {
const data = this.getDay(key);
if (data !== undefined) {
if (data === null || cb(data, value)) {
return this.set(key, {
data: value,
updateTime: updateTime
});
}
}
} else {
return this.set(key, {
data: value,
updateTime: updateTime
});
}
return false;
}
/**
* 获取本天数据 [返回值为undefined代表调用失败]
* @param {*} key
*/
getDay(key: string) {
const data = this.get(key);
if (data && data.updateTime == getDayUpdateTime()) {
return data.data;
}
return data && null;
}
}
export default new Storage();

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "be3da7ca-1bb5-4a41-894b-f82751c78ef2",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,12 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "54e30e53-aef2-4e16-8969-e38bea0ea336",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

View File

@@ -0,0 +1,440 @@
interface IHandle {
(next: (data?: any) => boolean, retry: (timeout?: number) => Promise<boolean>, end: (data?: any) => boolean): void
}
interface IFinish<T> {
(results?: T, success?: boolean): any
}
export interface ITask<T extends Array<any> = any[]> {
readonly results: Readonly<T>;
size(): number;
add(handle: IHandle): this;
start(finish?: IFinish<T> | Function): this;
stop(): boolean;
isRunning(): boolean;
}
/**
* 顺序执行
*/
export class Sync<T extends Array<any>> implements ITask<T> {
private running = false;
private index: number = -1;
private list: IHandle[] = [];
private finish: IFinish<T> | Function = null;
/**
* 每个handle的返回值通过next或end存储
*/
public results: T = [] as T;
/**
* 任务数量
* @returns
*/
public size(): number {
return this.list.length;
}
/**
* 添加一个任务
* @param handle
* @returns
*/
public add(handle: IHandle) {
this.list.push(handle);
this.results.push(undefined);
return this;
}
/**
* 开始执行所有任务
* @param finish 执行完毕回调
* @returns
*/
public start(finish?: IFinish<T> | Function) {
if (this.running) {
return this;
}
this.running = true;
this.index = -1;
this.finish = finish;
this.next(this.index);
return this;
}
/**
* 停止所有任务
* @returns
*/
public stop(): boolean {
if (!this.running) {
return false;
}
this.running = false;
if (this.finish) {
this.finish(this.results, false);
}
return true;
}
/**
* 是否正在执行
* @returns
*/
public isRunning() {
return this.running;
}
/**
* @deprecated
* @returns
*/
public isStop() {
return !this.running;
}
private end(data?: any): boolean {
if (!this.running) {
return false;
}
if (typeof data !== 'undefined') {
this.results[this.index] = data;
}
this.running = false;
if (this.finish) {
this.finish(this.results, true);
}
return true;
}
private next(index: number, data?: any): boolean {
if (!this.running) {
return false;
}
if (index !== this.index) return false;
if (typeof data !== 'undefined') {
this.results[this.index] = data;
}
if (++this.index < this.list.length) {
this.retry(this.index);
} else {
this.end();
}
return true;
}
private retry(index: number): boolean {
if (!this.running) {
return false;
}
if (index !== this.index) return false;
const handle = this.list[index];
handle && handle(
(data?: any) => this.next(index, data),
(timeout = 0) => {
return new Promise(resolve => {
if (timeout > 0) {
setTimeout(() => {
resolve(this.retry(index));
}, timeout * 1000);
} else {
resolve(this.retry(index));
}
});
},
(data?: any) => this.end(data)
);
return true;
}
}
/**
* 同时执行
*/
export class ASync<T extends Array<any>> implements ITask<T> {
private running = false;
private count: number = 0;
private list: IHandle[] = [];
private finish: IFinish<T> | Function = null;
/**
* 每个handle的返回值通过next或end存储
*/
public results: T = [] as T;
/**
* 任务数量
* @returns
*/
public size(): number {
return this.list.length;
}
/**
* 添加一个任务
* @param handle
* @returns
*/
public add(handle: IHandle) {
this.list.push(handle);
this.results.push(undefined);
if (this.running) {
this.retry(this.list.length - 1);
}
return this;
}
/**
* 开始执行所有任务
* @param finish 执行完毕回调
* @returns
*/
public start(finish?: IFinish<T> | Function) {
if (this.running) {
return this;
}
this.running = true;
this.count = 0;
this.finish = finish;
if (this.list.length) {
for (let index = 0; index < this.list.length; index++) {
this.retry(index);
}
} else {
this.end && this.end(this.count);
}
return this;
}
/**
* 停止所有任务
* @returns
*/
public stop(): boolean {
if (!this.running) {
return false;
}
this.running = false;
if (this.finish) {
this.finish(this.results, false);
}
return true;
}
/**
* 是否正在执行
* @returns
*/
public isRunning() {
return this.running;
}
/**
* @deprecated
* @returns
*/
public isStop() {
return !this.running;
}
private end(index: number, data?: any): boolean {
if (!this.running) {
return false;
}
if (index >= 0 && index < this.results.length) {
if (this.results[index] || this.results[index] === null) return false;
this.results[index] = typeof data !== 'undefined' ? data : null;
}
this.running = false;
if (this.finish) {
this.finish(this.results, true);
}
return true;
}
private next(index: number, data?: any): boolean {
if (!this.running) {
return false;
}
if (index >= 0 && index < this.results.length) {
if (this.results[index] || this.results[index] === null) return false;
this.results[index] = typeof data !== 'undefined' ? data : null;
}
if (++this.count === this.list.length) {
this.end && this.end(this.count);
}
return true;
}
private retry(index: number): boolean {
if (!this.running) {
return false;
}
const handle = this.list[index];
handle && handle(
(data?: any) => this.next(index, data),
(timeout = 0) => {
return new Promise(resolve => {
if (timeout > 0) {
setTimeout(() => {
resolve(this.retry(index));
}, timeout * 1000);
} else {
resolve(this.retry(index));
}
});
},
(data?: any) => this.end(index, data)
);
return true;
}
}
export class Any<T extends Array<any>> implements ITask<T> {
private task = new Sync();
/**
* 每个handle的返回值通过next或end存储
*/
public get results(): T {
return this.task.results as T;
}
/**
* 任务数量
* @returns
*/
public size() {
return this.task.size();
}
/**
* 添加一个任务
* @param handle
* @returns
*/
public add(handles: IHandle | IHandle[]) {
if (handles instanceof Array) {
const async = new ASync();
handles.forEach(handle => async.add(handle));
this.task.add(async.start.bind(async));
} else {
this.task.add(handles);
}
return this;
}
/**
* 开始执行所有任务
* @param finish 执行完毕回调
* @returns
*/
public start(finish?: IFinish<T> | Function) {
this.task.start(finish);
return this;
}
/**
* 停止所有任务
* @returns
*/
public stop() {
return this.task.stop();
}
/**
* 是否正在执行
* @returns
*/
public isRunning() {
return this.task.isRunning();
}
/**
* @deprecated
* @returns
*/
public isStop() {
return this.task.isStop();
}
}
interface IExecuteCallBack {
(retry: (timeout?: number) => void): void
}
const task = {
/**
* 任务顺序执行
*/
createSync<T extends Array<any>>(): Sync<T> {
return new Sync<T>();
},
/**
* 任务同时执行
*/
createASync<T extends Array<any>>(): ASync<T> {
return new ASync<T>();
},
/**
* 根据参数指定执行顺序
* @example
* createAny()
* .add(1).add(2).add(3).add(4)
* .add([5,6,7])
* .add(8)
* 执行顺序1234依次执行然后同时执行567最后执行8
*/
createAny<T extends Array<any>>() {
return new Any<T>();
},
/**
* 执行单个任务
*/
execute(fun: IExecuteCallBack, retryMax = -1, retryFinish?: Function) {
fun(function retry(timeout = 0) {
if (retryMax === 0) return retryFinish && retryFinish();
retryMax = retryMax > 0 ? retryMax - 1 : retryMax;
if (timeout > 0) {
setTimeout(() => task.execute(fun, retryMax, retryFinish), timeout * 1000);
} else {
task.execute(fun, retryMax, retryFinish);
}
});
}
};
export default task;

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "721e6dcc-aab3-48d6-aa4e-e1baf821263b",
"files": [],
"subMetas": {},
"userData": {}
}