Compare commits
No commits in common. "ce7d6c74f0e589605fe4427d9cfb339a8a9a1986" and "84b927a71b9160b277cc74d815569308ba9aad3c" have entirely different histories.
ce7d6c74f0
...
84b927a71b
@ -1,17 +0,0 @@
|
|||||||
|
|
||||||
page {
|
|
||||||
background-color: #f4f0f1;
|
|
||||||
color: rgba(0, 0, 0, .55);
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: .9em;
|
|
||||||
font-family: 'Lucida Sans',
|
|
||||||
'Lucida Sans Regular', 'Lucida Grande',
|
|
||||||
'Lucida Sans Unicode', 'Geneva', 'Verdana', 'sans-serif';
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark){
|
|
||||||
page {
|
|
||||||
background-color: #1f1f1f;
|
|
||||||
color: rgba(255, 255, 255, .55);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,4 @@
|
|||||||
import { Logger } from "./logger/Logger";
|
import { Logger, LevelLogLabel } from "./logger/index";
|
||||||
import { LevelLogLabel } from "./logger/LevelLogLabel";
|
|
||||||
import { LifeCycleLogLabel } from "./logger/LifeCycleLogLabel";
|
|
||||||
|
|
||||||
|
|
||||||
App<IAppOption>({
|
App<IAppOption>({
|
||||||
@ -14,7 +12,25 @@ App<IAppOption>({
|
|||||||
* 小程序加载时
|
* 小程序加载时
|
||||||
*/
|
*/
|
||||||
onLaunch() {
|
onLaunch() {
|
||||||
Logger.log("小程序启动...",
|
|
||||||
LevelLogLabel.TraceLabel, LifeCycleLogLabel.OnLaunchLabel);
|
console.log(Logger.l({val:"hh"},
|
||||||
|
LevelLogLabel.FatalLabel,LevelLogLabel.ErrorLabel,LevelLogLabel.WarnLabel,
|
||||||
|
LevelLogLabel.InfoLabel,LevelLogLabel.DebugLabel,LevelLogLabel.TraceLabel
|
||||||
|
));
|
||||||
|
|
||||||
|
console.log(Logger.m(
|
||||||
|
[LevelLogLabel.FatalLabel,LevelLogLabel.ErrorLabel,LevelLogLabel.WarnLabel,
|
||||||
|
LevelLogLabel.InfoLabel,LevelLogLabel.DebugLabel,LevelLogLabel.TraceLabel], {val:"hh"}, "hh"
|
||||||
|
));
|
||||||
|
|
||||||
|
console.log(Logger.ll({val:"hh"},
|
||||||
|
LevelLogLabel.FatalLabel,LevelLogLabel.ErrorLabel,LevelLogLabel.WarnLabel,
|
||||||
|
LevelLogLabel.InfoLabel,LevelLogLabel.DebugLabel,LevelLogLabel.TraceLabel
|
||||||
|
));
|
||||||
|
|
||||||
|
console.log(Logger.lm(
|
||||||
|
[LevelLogLabel.FatalLabel,LevelLogLabel.ErrorLabel,LevelLogLabel.WarnLabel,
|
||||||
|
LevelLogLabel.InfoLabel,LevelLogLabel.DebugLabel,LevelLogLabel.TraceLabel], {val:"hh"}, "hh"
|
||||||
|
));
|
||||||
}
|
}
|
||||||
})
|
})
|
@ -1,356 +0,0 @@
|
|||||||
|
|
||||||
/**
|
|
||||||
* 自定义对象类型
|
|
||||||
*/
|
|
||||||
type IAnyTypeObject<T = any> = {
|
|
||||||
[x:string]: T;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 微信 Data 类型
|
|
||||||
type Data<D> = WechatMiniprogram.Page.Data<D>;
|
|
||||||
|
|
||||||
// 微信生命周期类型
|
|
||||||
type ILifetime = WechatMiniprogram.Page.ILifetime;
|
|
||||||
|
|
||||||
// 继承的方法
|
|
||||||
type InstanceMethods<D> = WechatMiniprogram.Page.InstanceMethods<D>;
|
|
||||||
|
|
||||||
// 继承的属性
|
|
||||||
type InstanceProperties = WechatMiniprogram.Page.InstanceProperties;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 定义微信微信上下文类型
|
|
||||||
*
|
|
||||||
* @template TD data 结构类型
|
|
||||||
* @template TC 用户 MinIn 类型
|
|
||||||
*
|
|
||||||
* Partial<ILifetime> 可选的微信生命周期
|
|
||||||
* Partial<Data<TD>> 可选的 data 结构
|
|
||||||
* InstanceMethods<TD> 必选的微信继承方法
|
|
||||||
* InstanceProperties 必选的微信继承属性
|
|
||||||
*/
|
|
||||||
type WXContext<TD, TC> = Partial<ILifetime> & Partial<Data<TD>>
|
|
||||||
& InstanceMethods<TD> & InstanceProperties & TC;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 任意的微信上下文
|
|
||||||
* 当我们不关心具体是哪个上下文时
|
|
||||||
* 使用这个类型
|
|
||||||
*/
|
|
||||||
type AnyWXContext = WXContext<IAnyTypeObject, IAnyTypeObject>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 依赖关系图谱
|
|
||||||
* 注意: 这是一个递给类型
|
|
||||||
* @template M 限制了所有依赖必须使用同一个 manager
|
|
||||||
*/
|
|
||||||
type Depends<M extends Manager<AnyWXContext>> = {
|
|
||||||
[x:string]: Modular<M, Depends<M>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 页面模组
|
|
||||||
* @template M 所属 Manager
|
|
||||||
* @template DEP 模组依赖
|
|
||||||
* @template TD 模组 Data 类型
|
|
||||||
*/
|
|
||||||
class Modular<
|
|
||||||
M extends Manager<AnyWXContext> = Manager<AnyWXContext>,
|
|
||||||
DEP extends Depends<M> = Depends<M>,
|
|
||||||
TD extends IAnyTypeObject = IAnyTypeObject>
|
|
||||||
implements WXContext<TD, IAnyTypeObject> {
|
|
||||||
|
|
||||||
// [x:string]: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存页面上下文
|
|
||||||
*/
|
|
||||||
private manager:M;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 映射 Manager 上下文
|
|
||||||
*/
|
|
||||||
private get context():M["context"] {
|
|
||||||
return this.manager.context;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 模组依赖
|
|
||||||
*/
|
|
||||||
protected depends?:DEP
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 模组数据
|
|
||||||
*/
|
|
||||||
public data?:TD;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 模组使用的函数列表
|
|
||||||
*/
|
|
||||||
private functionList:Set<string>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 函数使用的参数列表
|
|
||||||
*/
|
|
||||||
private paramList:Set<string>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 命名空间
|
|
||||||
*/
|
|
||||||
private nameSpace:string;
|
|
||||||
|
|
||||||
// 映射主上下文属性
|
|
||||||
public get is():string { return this.context.is };
|
|
||||||
public get route():string { return this.context.route };
|
|
||||||
public get options():Record<string, string | undefined> {
|
|
||||||
return this.context.options;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 一旦被类被构造,整个页面的全部申明周期将
|
|
||||||
* 由该类实例控制,此后请勿修改任何生命周期函数
|
|
||||||
* @param manager 页面上下文
|
|
||||||
* @param nameSpace 模组命名空间
|
|
||||||
* @param depend 模组依赖
|
|
||||||
*/
|
|
||||||
public constructor(manager:M, nameSpace:string, depend?: DEP) {
|
|
||||||
|
|
||||||
// 保存微信上下文
|
|
||||||
this.manager = manager;
|
|
||||||
|
|
||||||
// 保存模块依赖
|
|
||||||
this.depends = depend;
|
|
||||||
|
|
||||||
// 初始化内部属性
|
|
||||||
this.functionList = new Set<string>();
|
|
||||||
this.paramList = new Set<string>();
|
|
||||||
this.nameSpace = nameSpace;
|
|
||||||
}
|
|
||||||
|
|
||||||
public setData(data:Partial<TD>, callback?: () => void):void {
|
|
||||||
|
|
||||||
if(this.data === void 0) {
|
|
||||||
this.data = {} as TD;
|
|
||||||
}
|
|
||||||
|
|
||||||
let reportData:IAnyTypeObject = {};
|
|
||||||
|
|
||||||
for(let key in data) {
|
|
||||||
(this.data as IAnyTypeObject)[key] = data[key];
|
|
||||||
reportData[`${ this.nameSpace }$${ key }`] = data[key];
|
|
||||||
this.paramList.add(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.context.setData(reportData, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 向上层上下文传递函数
|
|
||||||
* @param fn 传递的函数
|
|
||||||
* @param name 函数名字
|
|
||||||
*/
|
|
||||||
public setFunc(fn:Function, name:string):void {
|
|
||||||
|
|
||||||
this.functionList.add(name);
|
|
||||||
(this.context as IAnyTypeObject)
|
|
||||||
[`${ this.nameSpace }$${ name }`] = fn.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//#region 映射微信的继承函数
|
|
||||||
|
|
||||||
public hasBehavior(behavior: string): void {
|
|
||||||
return this.context.hasBehavior(behavior);
|
|
||||||
}
|
|
||||||
|
|
||||||
public triggerEvent<DetailType>(name: string, detail?: DetailType,
|
|
||||||
options?: WechatMiniprogram.Component.TriggerEventOption): void {
|
|
||||||
return this.context.triggerEvent<DetailType>(name, detail, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
public createSelectorQuery(): WechatMiniprogram.SelectorQuery {
|
|
||||||
return this.context.createSelectorQuery();
|
|
||||||
}
|
|
||||||
|
|
||||||
public createIntersectionObserver(options: WechatMiniprogram.CreateIntersectionObserverOption):
|
|
||||||
WechatMiniprogram.IntersectionObserver {
|
|
||||||
return this.context.createIntersectionObserver(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
public selectComponent(selector: string): WechatMiniprogram.Component.TrivialInstance {
|
|
||||||
return this.context.selectComponent(selector);
|
|
||||||
}
|
|
||||||
|
|
||||||
public selectAllComponents(selector: string): WechatMiniprogram.Component.TrivialInstance[] {
|
|
||||||
return this.context.selectAllComponents(selector);
|
|
||||||
}
|
|
||||||
|
|
||||||
public selectOwnerComponent(): WechatMiniprogram.Component.TrivialInstance {
|
|
||||||
return this.context.selectOwnerComponent();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getRelationNodes(relationKey: string): WechatMiniprogram.Component.TrivialInstance[] {
|
|
||||||
return this.context.getRelationNodes(relationKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
public groupSetData(callback?: () => void): void {
|
|
||||||
return this.context.groupSetData(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getTabBar(): WechatMiniprogram.Component.TrivialInstance {
|
|
||||||
return this.context.getTabBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getPageId(): string {
|
|
||||||
return this.context.getPageId();
|
|
||||||
}
|
|
||||||
|
|
||||||
public animate(selector: string, keyFrames: WechatMiniprogram.Component.KeyFrame[],
|
|
||||||
duration: number, callback?: () => void): void;
|
|
||||||
public animate(selector: string, keyFrames: WechatMiniprogram.Component.ScrollTimelineKeyframe[],
|
|
||||||
duration: number, scrollTimeline: WechatMiniprogram.Component.ScrollTimelineOption): void;
|
|
||||||
public animate(selector: any, keyFrames: any, duration: any, scrollTimeline?: any): void {
|
|
||||||
return this.context.animate(selector, keyFrames, duration, scrollTimeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
public clearAnimation(selector: string, callback: () => void): void;
|
|
||||||
public clearAnimation(selector: string, options?: WechatMiniprogram.Component.ClearAnimationOptions,
|
|
||||||
callback?: () => void): void;
|
|
||||||
public clearAnimation(selector: any, options?: any, callback?: any): void {
|
|
||||||
return this.context.clearAnimation(selector, options, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getOpenerEventChannel(): WechatMiniprogram.EventChannel {
|
|
||||||
return this.context.getOpenerEventChannel();
|
|
||||||
}
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 页面控件
|
|
||||||
* 用于管理页面的所有模组
|
|
||||||
*/
|
|
||||||
class Manager<WXC extends AnyWXContext = AnyWXContext> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 微信生命周期
|
|
||||||
*/
|
|
||||||
static readonly WxLifeCycle:(keyof ILifetime)[] = [
|
|
||||||
"onShow",
|
|
||||||
"onReady",
|
|
||||||
"onHide",
|
|
||||||
"onUnload",
|
|
||||||
"onPullDownRefresh",
|
|
||||||
"onReachBottom",
|
|
||||||
"onShareAppMessage",
|
|
||||||
"onShareTimeline",
|
|
||||||
"onAddToFavorites",
|
|
||||||
"onPageScroll",
|
|
||||||
"onResize",
|
|
||||||
"onTabItemTap"
|
|
||||||
]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存页面上下文
|
|
||||||
*/
|
|
||||||
public context:WXC;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 一旦被类被构造,整个页面的全部申明周期将
|
|
||||||
* 由该类实例控制,此后请勿修改任何生命周期函数
|
|
||||||
*/
|
|
||||||
public constructor(context:WXC) {
|
|
||||||
|
|
||||||
// 保存微信上下文
|
|
||||||
this.context = context;
|
|
||||||
|
|
||||||
// 初始化模组列表
|
|
||||||
this.modules = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 模组列表
|
|
||||||
*/
|
|
||||||
public modules:Modular[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 添加一个模块
|
|
||||||
* @param mode 模块类
|
|
||||||
* @param nameSpace 命名空间
|
|
||||||
* @param depend 模块依赖
|
|
||||||
* @returns 模块实例
|
|
||||||
*/
|
|
||||||
public addModule<DEP extends Depends<this>, M extends Modular<this, DEP>>
|
|
||||||
(mode: new (manager:Manager<WXC>, nameSpace:string, depend?:DEP) => M,
|
|
||||||
nameSpace:string, depend?:DEP):M {
|
|
||||||
let mod = new mode(this, nameSpace, depend);
|
|
||||||
this.modules.push(mod);
|
|
||||||
return mod;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建指定生命周期的钩子
|
|
||||||
* @param key 生命周期键值
|
|
||||||
*/
|
|
||||||
public creatHooks(key:keyof ILifetime):ILifetime[keyof ILifetime] {
|
|
||||||
return (...arg: any[]) => {
|
|
||||||
|
|
||||||
let hooks:Promise<any>[] = [];
|
|
||||||
let simple:any;
|
|
||||||
|
|
||||||
for(let i = 0; i < this.modules.length; i++) {
|
|
||||||
|
|
||||||
let res: Promise<any> | any =
|
|
||||||
(this.modules[i] as IAnyTypeObject)[key](...arg);
|
|
||||||
|
|
||||||
if (res instanceof Promise) {
|
|
||||||
hooks.push(res);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
hooks.push(Promise.resolve(res));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
key === "onShareAppMessage" ||
|
|
||||||
key === "onShareTimeline" ||
|
|
||||||
key === "onAddToFavorites"
|
|
||||||
) {
|
|
||||||
|
|
||||||
// 如果返回值有特殊含义在处理时进行 MinIn
|
|
||||||
simple = Object.assign({}, simple, res);
|
|
||||||
} else {
|
|
||||||
simple = res;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if(hooks.length === 0) return;
|
|
||||||
if(hooks.length === 1) return simple;
|
|
||||||
|
|
||||||
return Promise.all(hooks);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建全部生命周期钩子
|
|
||||||
*/
|
|
||||||
public creatAllHooks() {
|
|
||||||
for(let i = 0; i < Manager.WxLifeCycle.length; i++) {
|
|
||||||
(this.context as IAnyTypeObject)[Manager.WxLifeCycle[i]] =
|
|
||||||
this.creatHooks(Manager.WxLifeCycle[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加载全部的模块
|
|
||||||
*/
|
|
||||||
public loadAllModule(query:Record<string, string | undefined>) {
|
|
||||||
this.creatAllHooks();
|
|
||||||
let res = this.creatHooks("onLoad")(query as any);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export { Manager, Modular, AnyWXContext, WXContext, ILifetime}
|
|
@ -1,313 +0,0 @@
|
|||||||
import { LogLabel, LogStyle } from "./LogLabel";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 栈信息
|
|
||||||
*/
|
|
||||||
class StackInfo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 函数名
|
|
||||||
*/
|
|
||||||
public functionName:string | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件名
|
|
||||||
*/
|
|
||||||
public fileName:string | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件路径
|
|
||||||
*/
|
|
||||||
public url:string | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件名和行号
|
|
||||||
*/
|
|
||||||
public fileNameLine: string | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置信息
|
|
||||||
* @param functionName 函数名
|
|
||||||
* @param fileName 文件名
|
|
||||||
* @param url 文件路径
|
|
||||||
*/
|
|
||||||
public setInfo(functionName:string, fileNameLine:string, url:string):StackInfo {
|
|
||||||
this.functionName = functionName;
|
|
||||||
this.fileNameLine = fileNameLine;
|
|
||||||
this.url = url;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 计算文件名
|
|
||||||
*/
|
|
||||||
public calcFileName():string | undefined {
|
|
||||||
|
|
||||||
let replaceToTs = this.fileNameLine?.replace(".js", ".ts");
|
|
||||||
let matched = replaceToTs?.match(/^(.+\.(js|ts)):\d+:\d+$/);
|
|
||||||
|
|
||||||
return matched ? matched[1] : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 计算路径名
|
|
||||||
*/
|
|
||||||
public calcPathName():string | undefined {
|
|
||||||
|
|
||||||
let replaceToTs = this.url?.replace(".js", ".ts");
|
|
||||||
let matched = replaceToTs?.match(/^https?:\/\/(\d+\.){3}\d+:\d+\/(.+):\d+:\d+$/);
|
|
||||||
|
|
||||||
return matched ? matched[2] : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取函数调用栈列表
|
|
||||||
*/
|
|
||||||
public static getCallStack():StackInfo[] {
|
|
||||||
|
|
||||||
// 获取堆栈信息
|
|
||||||
let stack:string | undefined = new Error().stack;
|
|
||||||
|
|
||||||
if (stack === void 0) return [];
|
|
||||||
|
|
||||||
// 去除 Error
|
|
||||||
stack = stack.replace(/^(Error)\s/, "");
|
|
||||||
|
|
||||||
// 获取堆栈信息
|
|
||||||
let stackList:string[] = stack.split(/\n/);
|
|
||||||
|
|
||||||
let callStack:StackInfo[] = [];
|
|
||||||
|
|
||||||
for(let i = 0; i < stackList.length; i++) {
|
|
||||||
|
|
||||||
let matcher = stackList[i].match(/^\s+at\s+(.+)\s(\(.+\))/);
|
|
||||||
if (matcher === null || matcher.length < 3) continue;
|
|
||||||
|
|
||||||
let fileName = matcher[2].match(/.+\/(.+\..+:\d+:\d+)\)/);
|
|
||||||
if (fileName === null || matcher.length < 2) continue;
|
|
||||||
|
|
||||||
callStack.push(new StackInfo().setInfo(
|
|
||||||
matcher[1], fileName[1], matcher[2]?.replace(/(\(|\))/g, "")
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
// console.log(callStack);
|
|
||||||
|
|
||||||
return callStack;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 排除的
|
|
||||||
*/
|
|
||||||
public static readonly excludeFile:RegExp = /^.*(\\|\/)logger(\\|\/).+\.js:\d+:\d+/;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取第一个调用栈
|
|
||||||
*/
|
|
||||||
public static getFirstStack():StackInfo | undefined {
|
|
||||||
|
|
||||||
let callStack = this.getCallStack();
|
|
||||||
|
|
||||||
for(let i = 0; i < callStack.length; i++) {
|
|
||||||
|
|
||||||
if(!callStack[i].url) continue;
|
|
||||||
|
|
||||||
if(!StackInfo.excludeFile.test(callStack[i].url ?? "")) {
|
|
||||||
return callStack[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 内部预定义的 LogLabel
|
|
||||||
*/
|
|
||||||
class StackLogLabel {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 堆栈路径样式
|
|
||||||
*/
|
|
||||||
public static readonly normalStyle:LogStyle = new LogStyle()
|
|
||||||
.setColor("#979797").setBorder("4px", "1px solid #979797").setBlank("0 5px");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 一个回车
|
|
||||||
*/
|
|
||||||
public static readonly blankLabel = new LogLabel("\n\r",
|
|
||||||
new LogStyle(), false, true, true);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 包含文件名和行号的 label
|
|
||||||
*/
|
|
||||||
public static get fileNameLabel():LogLabel {
|
|
||||||
|
|
||||||
// 获得调用堆栈
|
|
||||||
let stack = StackInfo.getFirstStack();
|
|
||||||
|
|
||||||
return new LogLabel(stack?.calcFileName() ?? "Unknown file name",
|
|
||||||
StackLogLabel.normalStyle, false, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 包含 URL 链接的 label
|
|
||||||
*/
|
|
||||||
public static get urlLabel():LogLabel {
|
|
||||||
|
|
||||||
// 获得调用堆栈
|
|
||||||
let stack = StackInfo.getFirstStack();
|
|
||||||
|
|
||||||
return new LogLabel(stack?.calcPathName() ?? "Unknown url",
|
|
||||||
StackLogLabel.normalStyle, false, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 仅仅用来 filter 的 URL 链接的 label
|
|
||||||
*/
|
|
||||||
public static get filterUrlLabel():LogLabel {
|
|
||||||
|
|
||||||
// 获得调用堆栈
|
|
||||||
let stack = StackInfo.getFirstStack();
|
|
||||||
|
|
||||||
return new LogLabel(stack?.calcPathName() ?? "Unknown url",
|
|
||||||
StackLogLabel.normalStyle, true, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成圆角颜色标签样式
|
|
||||||
*/
|
|
||||||
const normalLevelStyleGen = (color:string):LogStyle => {
|
|
||||||
return new LogStyle().setBorder("4px", `1px solid ${color}`)
|
|
||||||
.setColor(color).setBlank("0 5px");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 调试等级标签
|
|
||||||
*/
|
|
||||||
class LevelLogLabel {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 致命
|
|
||||||
*/
|
|
||||||
static readonly FatalLabel = new LogLabel(
|
|
||||||
"FATAL", normalLevelStyleGen("#FF00CC")
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 错误
|
|
||||||
*/
|
|
||||||
static readonly ErrorLabel = new LogLabel(
|
|
||||||
"ERROR", normalLevelStyleGen("#FF0000")
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 警告
|
|
||||||
*/
|
|
||||||
static readonly WarnLabel = new LogLabel(
|
|
||||||
"WARN", normalLevelStyleGen("#FF9900")
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 消息
|
|
||||||
*/
|
|
||||||
static readonly InfoLabel = new LogLabel(
|
|
||||||
"INFO", normalLevelStyleGen("#99FF00")
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 调试
|
|
||||||
*/
|
|
||||||
static readonly DebugLabel = new LogLabel(
|
|
||||||
"DEBUG", normalLevelStyleGen("#00FF99")
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 追踪
|
|
||||||
*/
|
|
||||||
static readonly TraceLabel = new LogLabel(
|
|
||||||
"TRACE", normalLevelStyleGen("#00CCFF")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成圆角颜色标签样式
|
|
||||||
*/
|
|
||||||
const normalLifeStyleGen = (r:number, g:number, b:number):LogStyle => {
|
|
||||||
return new LogStyle().setBorder("4px", `1px solid rgb(${ r }, ${ g }, ${ b })`)
|
|
||||||
.setColor(`rgb(${ r }, ${ g }, ${ b })`, `rgba(${ r }, ${ g }, ${ b }, .1)`)
|
|
||||||
.setBlank("0 5px");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期标签
|
|
||||||
*/
|
|
||||||
class LifeCycleLogLabel {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 小程序加载时
|
|
||||||
*/
|
|
||||||
static readonly OnLaunchLabel = new LogLabel(
|
|
||||||
"onLaunch", normalLifeStyleGen(160, 32, 240)
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面加载
|
|
||||||
*/
|
|
||||||
static readonly OnLoadLabel = new LogLabel(
|
|
||||||
"onLoad", normalLifeStyleGen(255, 140, 105)
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面初次渲染完成
|
|
||||||
*/
|
|
||||||
static readonly OnReadyLabel = new LogLabel(
|
|
||||||
"onReady", normalLifeStyleGen(255, 127, 36)
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面显示
|
|
||||||
*/
|
|
||||||
static readonly OnShowLabel = new LogLabel(
|
|
||||||
"onShow", normalLifeStyleGen(255, 215, 0)
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面隐藏
|
|
||||||
*/
|
|
||||||
static readonly OnHideLabel = new LogLabel(
|
|
||||||
"onHide", normalLifeStyleGen(173, 255, 47)
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面卸载
|
|
||||||
*/
|
|
||||||
static readonly OnUnloadLabel = new LogLabel(
|
|
||||||
"onUnload", normalLifeStyleGen(127, 255, 212)
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 页面相关事件处理函数--监听用户下拉动作
|
|
||||||
*/
|
|
||||||
static readonly OnPullDownRefreshLabel = new LogLabel(
|
|
||||||
"onPullDownRefresh", normalLifeStyleGen(0, 191, 255)
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 页面上拉触底事件的处理函数
|
|
||||||
*/
|
|
||||||
static readonly OnReachBottomLabel = new LogLabel(
|
|
||||||
"onReachBottom", normalLifeStyleGen(84, 255, 159)
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户点击右上角分享
|
|
||||||
*/
|
|
||||||
static readonly OnShareAppMessageLabel = new LogLabel(
|
|
||||||
"onShareAppMessage", normalLifeStyleGen(147, 112, 219)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export { StackInfo, StackLogLabel, LevelLogLabel, LifeCycleLogLabel };
|
|
@ -1,205 +0,0 @@
|
|||||||
// import { Logger } from "../logger/Logger";
|
|
||||||
import { LogStyle, LogLabel } from "./LogLabel";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测试结果
|
|
||||||
*/
|
|
||||||
class TestResult {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用例名称
|
|
||||||
*/
|
|
||||||
public caseName:string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测试结果
|
|
||||||
*/
|
|
||||||
public result:boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 消息
|
|
||||||
*/
|
|
||||||
public message:string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 附加消息
|
|
||||||
*/
|
|
||||||
public attach:string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化
|
|
||||||
* @param caseName 用例名称
|
|
||||||
*/
|
|
||||||
constructor(caseName:string) {
|
|
||||||
this.caseName = caseName;
|
|
||||||
this.result = false;
|
|
||||||
this.message = "";
|
|
||||||
this.attach = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置结果
|
|
||||||
*/
|
|
||||||
public setResult(result:boolean, message?:string, attach?:string) {
|
|
||||||
this.result = result;
|
|
||||||
this.message = message ?? (result ? "success!" : "failed!");
|
|
||||||
this.attach = attach ?? this.attach;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测试函数结构
|
|
||||||
*/
|
|
||||||
type TestFunction = () => TestResult | Promise<TestResult>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 收集测试函数结构
|
|
||||||
*/
|
|
||||||
class CaseCollect {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用例键名
|
|
||||||
*/
|
|
||||||
public key:string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用例测试函数
|
|
||||||
*/
|
|
||||||
public caseFunction:TestFunction;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测试结果
|
|
||||||
*/
|
|
||||||
result: Promise<TestResult> | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param key 测试用例键名
|
|
||||||
* @param caseFunction 测试函数
|
|
||||||
*/
|
|
||||||
public constructor(key:string, caseFunction:TestFunction) {
|
|
||||||
this.key = key;
|
|
||||||
this.caseFunction = caseFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 运行测试用例
|
|
||||||
*/
|
|
||||||
public async runTestCase():Promise<CaseCollect> {
|
|
||||||
|
|
||||||
let result = this.caseFunction();
|
|
||||||
|
|
||||||
if(result instanceof Promise) {
|
|
||||||
this.result = result;
|
|
||||||
} else {
|
|
||||||
this.result = Promise.resolve(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly baseStyle = new LogStyle().setBlank();
|
|
||||||
|
|
||||||
public static readonly successLabel:LogLabel = new LogLabel("√",
|
|
||||||
new LogStyle().setBlank("0 4px").setBorder("1000px", "1px solid green")
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打印结果
|
|
||||||
* @param current 当前进度
|
|
||||||
* @param total 总进度
|
|
||||||
*/
|
|
||||||
public printResult(current?:number, total?:number) {
|
|
||||||
|
|
||||||
// 如果测试没有运行,先运行它
|
|
||||||
if(this.result === void 0) this.runTestCase();
|
|
||||||
|
|
||||||
this.result?.then((res) => {
|
|
||||||
|
|
||||||
if(res.result) {
|
|
||||||
console.log(
|
|
||||||
`%c√%c %c1/1%c %c${ this.key }%c ` + res.message,
|
|
||||||
"padding:0 4px; border-radius:1000px; border:1px solid green; color:green",
|
|
||||||
"", "padding:0 4px; border-radius:4px; border:1px solid green; color:green",
|
|
||||||
"", "padding:0 4px; border-radius:4px; border:1px solid #979797; color:#979797",
|
|
||||||
""
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
console.log(
|
|
||||||
`%c√%c %c1/1%c %c${ this.key }%c ` + res.message,
|
|
||||||
"padding:0 4px; border-radius:1000px; border:1px solid red; color:red",
|
|
||||||
"", "padding:0 4px; border-radius:4px; border:1px solid red; color:red",
|
|
||||||
"", "padding:0 4px; border-radius:4px; border:1px solid #979797; color:#979797",
|
|
||||||
""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
console.log(res)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 收集测试用例
|
|
||||||
* @param testCaseClass 测试用例表
|
|
||||||
*/
|
|
||||||
public static collectCase(testCaseClass:ITestCase):CaseCollect[] {
|
|
||||||
|
|
||||||
// 获取静态方法 key
|
|
||||||
let key = Object.getOwnPropertyNames(testCaseClass);
|
|
||||||
|
|
||||||
// 过滤掉通用的方法和属性
|
|
||||||
key = key.filter((key) => !/(length|name|prototype)/.test(key) );
|
|
||||||
|
|
||||||
// 生成 CaseCollect
|
|
||||||
let caseCollect = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < key.length; i++) {
|
|
||||||
caseCollect.push(new CaseCollect(key[i], testCaseClass[key[i]]))
|
|
||||||
}
|
|
||||||
|
|
||||||
return caseCollect;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 运行测试样例
|
|
||||||
*/
|
|
||||||
public static async runCollectCase(cases:CaseCollect[]):Promise<CaseCollect[]> {
|
|
||||||
|
|
||||||
let running:Promise<CaseCollect>[] = [];
|
|
||||||
|
|
||||||
for(let i = 0; i < cases.length; i++) {
|
|
||||||
running.push(cases[i].runTestCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.all(running);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 启动单元测试
|
|
||||||
*/
|
|
||||||
public static runUnitTest(testCaseClass:ITestCase) {
|
|
||||||
|
|
||||||
let caseCollect = this.collectCase(testCaseClass);
|
|
||||||
|
|
||||||
CaseCollect.runCollectCase(caseCollect).then((caseCollect:CaseCollect[]) => {
|
|
||||||
|
|
||||||
for(let i = 0; i < caseCollect.length; i++) {
|
|
||||||
caseCollect[i].printResult()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测试用例接口
|
|
||||||
*/
|
|
||||||
interface ITestCase {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测试用例函数
|
|
||||||
*/
|
|
||||||
[key:string]:TestFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ITestCase;
|
|
||||||
export { ITestCase, TestResult, TestFunction, CaseCollect };
|
|
61
miniprogram/logger/InternalLogLabel.ts
Normal file
61
miniprogram/logger/InternalLogLabel.ts
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import { LogStyle } from "./LogStyle";
|
||||||
|
import { LogLabel } from "./LogLabel";
|
||||||
|
import { StackInfo } from "./StackInfo";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内部预定义的 LogLabel
|
||||||
|
*/
|
||||||
|
class InternalLogLabel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 堆栈路径样式
|
||||||
|
*/
|
||||||
|
public static readonly normalStyle:LogStyle = new LogStyle()
|
||||||
|
.setColor("#CCCCCC").setBorder("4px", "1px solid #979797").setBlank("0 5px");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一个回车
|
||||||
|
*/
|
||||||
|
public static readonly blankLabel = new LogLabel("\n\r",
|
||||||
|
new LogStyle(), false, true, true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 包含文件名和行号的 label
|
||||||
|
*/
|
||||||
|
public static get fileNameLabel():LogLabel {
|
||||||
|
|
||||||
|
// 获得调用堆栈
|
||||||
|
let stack = StackInfo.getFirstStack();
|
||||||
|
|
||||||
|
return new LogLabel(stack?.fileName ?? "Unknown file name",
|
||||||
|
InternalLogLabel.normalStyle, false, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 包含 URL 链接的 label
|
||||||
|
*/
|
||||||
|
public static get urlLabel():LogLabel {
|
||||||
|
|
||||||
|
// 获得调用堆栈
|
||||||
|
let stack = StackInfo.getFirstStack();
|
||||||
|
|
||||||
|
return new LogLabel(stack?.url ?? "Unknown url",
|
||||||
|
InternalLogLabel.normalStyle, false, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 仅仅用来 filter 的 URL 链接的 label
|
||||||
|
*/
|
||||||
|
public static get filterUrlLabel():LogLabel {
|
||||||
|
|
||||||
|
// 获得调用堆栈
|
||||||
|
let stack = StackInfo.getFirstStack();
|
||||||
|
|
||||||
|
return new LogLabel(stack?.url ?? "Unknown url",
|
||||||
|
InternalLogLabel.normalStyle, true, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default InternalLogLabel;
|
||||||
|
export {InternalLogLabel};
|
61
miniprogram/logger/LevelLogLabel.ts
Normal file
61
miniprogram/logger/LevelLogLabel.ts
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import { LogStyle } from "./LogStyle";
|
||||||
|
import { LogLabel } from "./LogLabel";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成圆角颜色标签样式
|
||||||
|
*/
|
||||||
|
const normalStyleGen = (color:string):LogStyle => {
|
||||||
|
return new LogStyle().setBorder("4px", `1px solid ${color}`)
|
||||||
|
.setColor(color).setBlank("0 5px");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调试等级标签
|
||||||
|
*/
|
||||||
|
class LevelLogLabel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 致命
|
||||||
|
*/
|
||||||
|
static readonly FatalLabel = new LogLabel(
|
||||||
|
"FATAL", normalStyleGen("#FF00CC")
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误
|
||||||
|
*/
|
||||||
|
static readonly ErrorLabel = new LogLabel(
|
||||||
|
"ERROR", normalStyleGen("#FF0000")
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 警告
|
||||||
|
*/
|
||||||
|
static readonly WarnLabel = new LogLabel(
|
||||||
|
"WARN", normalStyleGen("#FF9900")
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息
|
||||||
|
*/
|
||||||
|
static readonly InfoLabel = new LogLabel(
|
||||||
|
"INFO", normalStyleGen("#99FF00")
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调试
|
||||||
|
*/
|
||||||
|
static readonly DebugLabel = new LogLabel(
|
||||||
|
"DEBUG", normalStyleGen("#00FF99")
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 追踪
|
||||||
|
*/
|
||||||
|
static readonly TraceLabel = new LogLabel(
|
||||||
|
"TRACE", normalStyleGen("#00CCFF")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LevelLogLabel;
|
||||||
|
export { LevelLogLabel };
|
93
miniprogram/logger/LogLabel.ts
Normal file
93
miniprogram/logger/LogLabel.ts
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import { LogStyle } from "./LogStyle";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志标签
|
||||||
|
*/
|
||||||
|
class LogLabel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关键字
|
||||||
|
* 用于标识这个类别
|
||||||
|
*/
|
||||||
|
public key:string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文字样式
|
||||||
|
*/
|
||||||
|
public style:LogStyle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否受到过滤器影响
|
||||||
|
*/
|
||||||
|
public checked:boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否输出
|
||||||
|
*/
|
||||||
|
public display:boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为附件标签
|
||||||
|
* 例如回车、时间、代码位置
|
||||||
|
*/
|
||||||
|
public attach:boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param key 关键字
|
||||||
|
* @param style 文字样式
|
||||||
|
*/
|
||||||
|
constructor(key:string, style:LogStyle,
|
||||||
|
checked?:boolean, display?:boolean, attach?:boolean) {
|
||||||
|
this.key = key;
|
||||||
|
this.style = style;
|
||||||
|
this.checked = checked ?? true;
|
||||||
|
this.display = display ?? true;
|
||||||
|
this.attach = attach ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得 Logger 输出使用的内容
|
||||||
|
*/
|
||||||
|
public getLoggerOutput():string {
|
||||||
|
if(!this.display) return "";
|
||||||
|
return `%c${ this.key }`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得 Text 输出内容
|
||||||
|
*/
|
||||||
|
public getTextOutput():string {
|
||||||
|
if(!this.display) return "";
|
||||||
|
return `[${ this.key }]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得 style 格式化
|
||||||
|
*/
|
||||||
|
public getStyleOutput():string {
|
||||||
|
if(!this.display) return "";
|
||||||
|
return this.style.stringify();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验
|
||||||
|
*/
|
||||||
|
public checking(src:RegExp | string):boolean {
|
||||||
|
|
||||||
|
let pass = false;
|
||||||
|
|
||||||
|
// 关闭校验
|
||||||
|
if(!this.checked) return pass;
|
||||||
|
|
||||||
|
if(src instanceof RegExp) {
|
||||||
|
pass = (src as RegExp).test(this.key)
|
||||||
|
} else {
|
||||||
|
pass = (src as string) === this.key;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LogLabel;
|
||||||
|
export {LogLabel}
|
@ -134,94 +134,5 @@ class LogStyle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export default LogStyle;
|
||||||
* 日志标签
|
export {LogStyle};
|
||||||
*/
|
|
||||||
class LogLabel {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 关键字
|
|
||||||
* 用于标识这个类别
|
|
||||||
*/
|
|
||||||
public key:string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文字样式
|
|
||||||
*/
|
|
||||||
public style:LogStyle;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否受到过滤器影响
|
|
||||||
*/
|
|
||||||
public checked:boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否输出
|
|
||||||
*/
|
|
||||||
public display:boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否为附件标签
|
|
||||||
* 例如回车、时间、代码位置
|
|
||||||
*/
|
|
||||||
public attach:boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param key 关键字
|
|
||||||
* @param style 文字样式
|
|
||||||
*/
|
|
||||||
constructor(key:string, style:LogStyle,
|
|
||||||
checked?:boolean, display?:boolean, attach?:boolean) {
|
|
||||||
this.key = key;
|
|
||||||
this.style = style;
|
|
||||||
this.checked = checked ?? true;
|
|
||||||
this.display = display ?? true;
|
|
||||||
this.attach = attach ?? false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得 Logger 输出使用的内容
|
|
||||||
*/
|
|
||||||
public getLoggerOutput():string {
|
|
||||||
if(!this.display) return "";
|
|
||||||
return `%c${ this.key }`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得 Text 输出内容
|
|
||||||
*/
|
|
||||||
public getTextOutput():string {
|
|
||||||
if(!this.display) return "";
|
|
||||||
return `[${ this.key }]`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得 style 格式化
|
|
||||||
*/
|
|
||||||
public getStyleOutput():string {
|
|
||||||
if(!this.display) return "";
|
|
||||||
return this.style.stringify();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 校验
|
|
||||||
*/
|
|
||||||
public checking(src:RegExp | string):boolean {
|
|
||||||
|
|
||||||
let pass = false;
|
|
||||||
|
|
||||||
// 关闭校验
|
|
||||||
if(!this.checked) return pass;
|
|
||||||
|
|
||||||
if(src instanceof RegExp) {
|
|
||||||
pass = (src as RegExp).test(this.key)
|
|
||||||
} else {
|
|
||||||
pass = (src as string) === this.key;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pass;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LogLabel;
|
|
||||||
export {LogLabel, LogStyle}
|
|
@ -1,33 +1,7 @@
|
|||||||
import { LOGGER_FILTER, LOGGER_CONSOLE } from "./Config";
|
import {LOGGER_CONSOLE, LOGGER_FILTER} from "../Config";
|
||||||
import { StackLogLabel } from "./PresetLogLabel";
|
import { InternalLogLabel } from "./InternalLogLabel";
|
||||||
import { LogLabel } from "./LogLabel";
|
import { LogLabel } from "./LogLabel";
|
||||||
|
import { MultipleLogContent } from "./MultipleLogContent";
|
||||||
|
|
||||||
/**
|
|
||||||
* 多重内容捆绑
|
|
||||||
* 用于 log 输出
|
|
||||||
*/
|
|
||||||
class MultipleLogContent<T extends Array<any>> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 输出内容
|
|
||||||
*/
|
|
||||||
private readonly content:T;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param content 输出内容
|
|
||||||
*/
|
|
||||||
public constructor(...content:T) {
|
|
||||||
this.content = content;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取内容
|
|
||||||
*/
|
|
||||||
public getContent():T {
|
|
||||||
return this.content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 格式化日志输出
|
* 格式化日志输出
|
||||||
@ -119,7 +93,7 @@ class Logger {
|
|||||||
// TODO: 这里可以添加一些钩子作为中间件处理日志输出
|
// TODO: 这里可以添加一些钩子作为中间件处理日志输出
|
||||||
|
|
||||||
// 测试是否输出内容
|
// 测试是否输出内容
|
||||||
if(!Logger.testLog(...labels, ...attachLabel, StackLogLabel.filterUrlLabel))
|
if(!Logger.testLog(...labels, ...attachLabel, InternalLogLabel.filterUrlLabel))
|
||||||
return content.getContent();
|
return content.getContent();
|
||||||
|
|
||||||
// 计算收集样式
|
// 计算收集样式
|
||||||
@ -139,7 +113,7 @@ class Logger {
|
|||||||
public static log<T>(content:T, ...labels:LogLabel[]):T {
|
public static log<T>(content:T, ...labels:LogLabel[]):T {
|
||||||
return Logger.logBase<Array<T>>(
|
return Logger.logBase<Array<T>>(
|
||||||
new MultipleLogContent<Array<T>>(content), labels,
|
new MultipleLogContent<Array<T>>(content), labels,
|
||||||
[StackLogLabel.fileNameLabel]
|
[InternalLogLabel.fileNameLabel]
|
||||||
)[0];
|
)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +130,7 @@ class Logger {
|
|||||||
public static logMultiple<T extends Array<any>>(labels:LogLabel[], ...content:T):T {
|
public static logMultiple<T extends Array<any>>(labels:LogLabel[], ...content:T):T {
|
||||||
return Logger.logBase<T>(
|
return Logger.logBase<T>(
|
||||||
new MultipleLogContent<T>(...content), labels,
|
new MultipleLogContent<T>(...content), labels,
|
||||||
[StackLogLabel.fileNameLabel]
|
[InternalLogLabel.fileNameLabel]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,12 +147,12 @@ class Logger {
|
|||||||
public static logLine<T>(content:T, ...labels:LogLabel[]):T {
|
public static logLine<T>(content:T, ...labels:LogLabel[]):T {
|
||||||
return Logger.logBase<Array<T>>(
|
return Logger.logBase<Array<T>>(
|
||||||
new MultipleLogContent<Array<T>>(content), labels,
|
new MultipleLogContent<Array<T>>(content), labels,
|
||||||
[StackLogLabel.fileNameLabel, StackLogLabel.blankLabel]
|
[InternalLogLabel.urlLabel, InternalLogLabel.blankLabel]
|
||||||
)[0];
|
)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 函数 Logger.logLine 的别名
|
* 函数 Logger.logMultiple 的别名
|
||||||
*/
|
*/
|
||||||
public static ll:typeof Logger.logLine = Logger.logLine;
|
public static ll:typeof Logger.logLine = Logger.logLine;
|
||||||
|
|
||||||
@ -190,7 +164,7 @@ class Logger {
|
|||||||
public static logLineMultiple<T extends Array<any>>(labels:LogLabel[], ...content:T):T {
|
public static logLineMultiple<T extends Array<any>>(labels:LogLabel[], ...content:T):T {
|
||||||
return Logger.logBase<T>(
|
return Logger.logBase<T>(
|
||||||
new MultipleLogContent<T>(...content), labels,
|
new MultipleLogContent<T>(...content), labels,
|
||||||
[StackLogLabel.fileNameLabel, StackLogLabel.blankLabel]
|
[InternalLogLabel.urlLabel, InternalLogLabel.blankLabel]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
29
miniprogram/logger/MultipleLogContent.ts
Normal file
29
miniprogram/logger/MultipleLogContent.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* 多重内容捆绑
|
||||||
|
* 用于 log 输出
|
||||||
|
*/
|
||||||
|
class MultipleLogContent<T extends Array<any>> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输出内容
|
||||||
|
*/
|
||||||
|
private readonly content:T;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param content 输出内容
|
||||||
|
*/
|
||||||
|
public constructor(...content:T) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取内容
|
||||||
|
*/
|
||||||
|
public getContent():T {
|
||||||
|
return this.content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MultipleLogContent;
|
||||||
|
export { MultipleLogContent };
|
91
miniprogram/logger/StackInfo.ts
Normal file
91
miniprogram/logger/StackInfo.ts
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* 栈信息
|
||||||
|
*/
|
||||||
|
class StackInfo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 函数名
|
||||||
|
*/
|
||||||
|
public functionName:string | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件名
|
||||||
|
*/
|
||||||
|
public fileName:string | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件路径
|
||||||
|
*/
|
||||||
|
public url:string | undefined;
|
||||||
|
|
||||||
|
public setInfo(functionName:string, fileName:string, url:string):StackInfo {
|
||||||
|
this.functionName = functionName;
|
||||||
|
this.fileName = fileName;
|
||||||
|
this.url = url;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取函数调用栈列表
|
||||||
|
*/
|
||||||
|
public static getCallStack():StackInfo[] {
|
||||||
|
|
||||||
|
// 获取堆栈信息
|
||||||
|
let stack:string | undefined = new Error().stack;
|
||||||
|
|
||||||
|
if (stack === void 0) return [];
|
||||||
|
|
||||||
|
// 去除 Error
|
||||||
|
stack = stack.replace(/^(Error)\s/, "");
|
||||||
|
|
||||||
|
// 获取堆栈信息
|
||||||
|
let stackList:string[] = stack.split(/\n/);
|
||||||
|
|
||||||
|
let callStack:StackInfo[] = [];
|
||||||
|
|
||||||
|
for(let i = 0; i < stackList.length; i++) {
|
||||||
|
|
||||||
|
let matcher = stackList[i].match(/^\s+at\s+(.+)\s(\(.+\))/);
|
||||||
|
if (matcher === null || matcher.length < 3) continue;
|
||||||
|
|
||||||
|
let fileName = matcher[2].match(/.+\/(.+\..+:\d+:\d+)\)/);
|
||||||
|
if (fileName === null || matcher.length < 2) continue;
|
||||||
|
|
||||||
|
callStack.push(new StackInfo().setInfo(
|
||||||
|
matcher[1], fileName[1], matcher[2]?.replace(/(\(|\))/g, "")
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log(callStack);
|
||||||
|
|
||||||
|
return callStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排除的
|
||||||
|
*/
|
||||||
|
public static readonly excludeFile:RegExp = /^Logger\.js:\d+:\d+/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取第一个调用栈
|
||||||
|
*/
|
||||||
|
public static getFirstStack():StackInfo | undefined {
|
||||||
|
|
||||||
|
let callStack = this.getCallStack();
|
||||||
|
|
||||||
|
for(let i = 0; i < callStack.length; i++) {
|
||||||
|
|
||||||
|
if(!callStack[i].fileName) continue;
|
||||||
|
|
||||||
|
if(!StackInfo.excludeFile.test(callStack[i].fileName ?? "")) {
|
||||||
|
return callStack[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default StackInfo;
|
||||||
|
export { StackInfo };
|
11
miniprogram/logger/index.ts
Normal file
11
miniprogram/logger/index.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import Logger from "./Logger";
|
||||||
|
|
||||||
|
export default Logger;
|
||||||
|
export { Logger };
|
||||||
|
|
||||||
|
export { InternalLogLabel } from "./InternalLogLabel";
|
||||||
|
export { MultipleLogContent } from "./MultipleLogContent";
|
||||||
|
export { LevelLogLabel } from "./LevelLogLabel";
|
||||||
|
export { LogLabel } from "./LogLabel";
|
||||||
|
export { LogStyle } from "./LogStyle";
|
||||||
|
export { StackInfo } from "./StackInfo";
|
@ -1,4 +1,3 @@
|
|||||||
{
|
{
|
||||||
"usingComponents": {},
|
"usingComponents": {}
|
||||||
"navigationStyle": "custom"
|
|
||||||
}
|
}
|
@ -1,3 +0,0 @@
|
|||||||
// view.status-bar {
|
|
||||||
// // background-color: antiquewhite;
|
|
||||||
// }
|
|
@ -1,68 +1,66 @@
|
|||||||
import { Logger } from "../../core/Logger";
|
// pages/Timetable/Timetable.ts
|
||||||
import { LevelLogLabel, LifeCycleLogLabel } from "../../core/PresetLogLabel";
|
|
||||||
import { Manager, Modular, AnyWXContext, ILifetime } from "../../core/Module";
|
|
||||||
|
|
||||||
Page({
|
Page({
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 课程表页面加载
|
* 页面的初始数据
|
||||||
*/
|
*/
|
||||||
onLoad: async function () {
|
data: {
|
||||||
|
|
||||||
this;
|
},
|
||||||
|
|
||||||
let manager = new Manager(this);
|
/**
|
||||||
let m1 = manager.addModule(M1, "m1");
|
* 生命周期函数--监听页面加载
|
||||||
let m2 = manager.addModule(M2, "m2", {m1});
|
*/
|
||||||
|
onLoad() {
|
||||||
|
|
||||||
let manager2 = new Manager(this);
|
},
|
||||||
let m22 = manager.addModule(M2, "m1", {m1});
|
|
||||||
|
|
||||||
this.setData;
|
/**
|
||||||
|
* 生命周期函数--监听页面初次渲染完成
|
||||||
|
*/
|
||||||
|
onReady() {
|
||||||
|
|
||||||
Logger.log("课程表 (Timetable) 页面加载...",
|
},
|
||||||
LevelLogLabel.TraceLabel, LifeCycleLogLabel.OnLoadLabel);
|
|
||||||
|
|
||||||
let systemInfo = wx.getSystemInfoSync();
|
/**
|
||||||
|
* 生命周期函数--监听页面显示
|
||||||
|
*/
|
||||||
|
onShow() {
|
||||||
|
|
||||||
//状态栏高度
|
},
|
||||||
let statusBarHeight = Number(systemInfo.statusBarHeight);
|
|
||||||
|
|
||||||
let menu = wx.getMenuButtonBoundingClientRect()
|
/**
|
||||||
|
* 生命周期函数--监听页面隐藏
|
||||||
|
*/
|
||||||
|
onHide() {
|
||||||
|
|
||||||
//导航栏高度
|
},
|
||||||
let navBarHeight = menu.height + (menu.top - statusBarHeight) * 2
|
|
||||||
|
|
||||||
//状态栏加导航栏高度
|
/**
|
||||||
let navStatusBarHeight = statusBarHeight + menu.height + (menu.top - statusBarHeight) * 2
|
* 生命周期函数--监听页面卸载
|
||||||
|
*/
|
||||||
|
onUnload() {
|
||||||
|
|
||||||
console.log('状态栏高度',statusBarHeight)
|
},
|
||||||
|
|
||||||
console.log('导航栏高度',navBarHeight)
|
/**
|
||||||
|
* 页面相关事件处理函数--监听用户下拉动作
|
||||||
|
*/
|
||||||
|
onPullDownRefresh() {
|
||||||
|
|
||||||
console.log('状态栏加导航栏高度',navStatusBarHeight)
|
},
|
||||||
|
|
||||||
this.setData({barh: navStatusBarHeight});
|
/**
|
||||||
|
* 页面上拉触底事件的处理函数
|
||||||
|
*/
|
||||||
|
onReachBottom() {
|
||||||
|
|
||||||
}
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户点击右上角分享
|
||||||
|
*/
|
||||||
|
onShareAppMessage() {
|
||||||
|
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class M1<M extends Manager> extends Modular<M, {}> {
|
|
||||||
|
|
||||||
public onLoad(){
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class M2<M extends Manager> extends Modular<M, {m1:M1<M>}> {
|
|
||||||
|
|
||||||
public onLoad() {
|
|
||||||
// this.setData();
|
|
||||||
}
|
|
||||||
// hhh(){
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
hh(){}
|
|
||||||
}
|
|
@ -1,3 +1 @@
|
|||||||
<view class="status-bar" style="height:{{barh}}px"></view>
|
|
||||||
|
|
||||||
<text>pages/Timetable/Timetable.wxml</text>
|
<text>pages/Timetable/Timetable.wxml</text>
|
||||||
|
Loading…
Reference in New Issue
Block a user