Add Modular and Manager, merge Logger to core
This commit is contained in:
		
							parent
							
								
									cea68f5145
								
							
						
					
					
						commit
						7fa3a215cf
					
				| @ -0,0 +1,17 @@ | ||||
| 
 | ||||
| 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,5 +1,6 @@ | ||||
| import { Logger } from "./logger/Logger"; | ||||
| import { LevelLogLabel } from "./logger/LevelLogLabel"; | ||||
| import { LifeCycleLogLabel } from "./logger/LifeCycleLogLabel"; | ||||
| 
 | ||||
| 
 | ||||
| App<IAppOption>({ | ||||
| @ -13,25 +14,7 @@ App<IAppOption>({ | ||||
|      * 小程序加载时 | ||||
|      */ | ||||
|     onLaunch() { | ||||
| 
 | ||||
|     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" | ||||
|     )); | ||||
|         Logger.log("小程序启动...",  | ||||
|         LevelLogLabel.TraceLabel, LifeCycleLogLabel.OnLaunchLabel); | ||||
|   } | ||||
| }) | ||||
| @ -134,5 +134,94 @@ 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,7 +1,33 @@ | ||||
| import { LOGGER_FILTER, LOGGER_CONSOLE } from "../utils/Config"; | ||||
| import { InternalLogLabel } from "./InternalLogLabel"; | ||||
| import { LOGGER_FILTER, LOGGER_CONSOLE } from "./Config"; | ||||
| import { StackLogLabel } from "./PresetLogLabel"; | ||||
| 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; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * 格式化日志输出 | ||||
| @ -93,7 +119,7 @@ class Logger { | ||||
|         // TODO: 这里可以添加一些钩子作为中间件处理日志输出
 | ||||
| 
 | ||||
|         // 测试是否输出内容
 | ||||
|         if(!Logger.testLog(...labels, ...attachLabel, InternalLogLabel.filterUrlLabel))  | ||||
|         if(!Logger.testLog(...labels, ...attachLabel, StackLogLabel.filterUrlLabel))  | ||||
|         return content.getContent(); | ||||
| 
 | ||||
|         // 计算收集样式
 | ||||
| @ -113,7 +139,7 @@ class Logger { | ||||
|     public static log<T>(content:T, ...labels:LogLabel[]):T { | ||||
|         return Logger.logBase<Array<T>>( | ||||
|             new MultipleLogContent<Array<T>>(content), labels,  | ||||
|             [InternalLogLabel.fileNameLabel] | ||||
|             [StackLogLabel.fileNameLabel] | ||||
|         )[0]; | ||||
|     } | ||||
| 
 | ||||
| @ -130,7 +156,7 @@ class Logger { | ||||
|     public static logMultiple<T extends Array<any>>(labels:LogLabel[], ...content:T):T { | ||||
|         return Logger.logBase<T>( | ||||
|             new MultipleLogContent<T>(...content), labels,  | ||||
|             [InternalLogLabel.fileNameLabel] | ||||
|             [StackLogLabel.fileNameLabel] | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
| @ -147,7 +173,7 @@ class Logger { | ||||
|     public static logLine<T>(content:T, ...labels:LogLabel[]):T { | ||||
|         return Logger.logBase<Array<T>>( | ||||
|             new MultipleLogContent<Array<T>>(content), labels,  | ||||
|             [InternalLogLabel.fileNameLabel, InternalLogLabel.blankLabel] | ||||
|             [StackLogLabel.fileNameLabel, StackLogLabel.blankLabel] | ||||
|         )[0]; | ||||
|     } | ||||
| 
 | ||||
| @ -164,7 +190,7 @@ class Logger { | ||||
|     public static logLineMultiple<T extends Array<any>>(labels:LogLabel[], ...content:T):T { | ||||
|         return Logger.logBase<T>( | ||||
|             new MultipleLogContent<T>(...content), labels,  | ||||
|             [InternalLogLabel.fileNameLabel, InternalLogLabel.blankLabel] | ||||
|             [StackLogLabel.fileNameLabel, StackLogLabel.blankLabel] | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
							
								
								
									
										356
									
								
								miniprogram/core/Module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										356
									
								
								miniprogram/core/Module.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,356 @@ | ||||
| 
 | ||||
| /** | ||||
|  * 自定义对象类型 | ||||
|  */ | ||||
| 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} | ||||
							
								
								
									
										313
									
								
								miniprogram/core/PresetLogLabel.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										313
									
								
								miniprogram/core/PresetLogLabel.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,313 @@ | ||||
| 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,6 +1,5 @@ | ||||
| // import { Logger } from "../logger/Logger";
 | ||||
| import { LogStyle } from "../logger/LogStyle"; | ||||
| import { LogLabel } from "../logger/LogLabel"; | ||||
| import { LogStyle, LogLabel } from "./LogLabel"; | ||||
| 
 | ||||
| /** | ||||
|  * 测试结果 | ||||
| @ -1,61 +0,0 @@ | ||||
| import { LogStyle } from "./LogStyle"; | ||||
| import { LogLabel } from "./LogLabel"; | ||||
| import { StackInfo } from "./StackInfo"; | ||||
| 
 | ||||
| /** | ||||
|  * 内部预定义的 LogLabel | ||||
|  */ | ||||
| class InternalLogLabel { | ||||
| 
 | ||||
|     /** | ||||
|      * 堆栈路径样式 | ||||
|      */ | ||||
|     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",  | ||||
|         InternalLogLabel.normalStyle, false, true, true); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 包含 URL 链接的 label | ||||
|      */ | ||||
|     public static get urlLabel():LogLabel { | ||||
| 
 | ||||
|         // 获得调用堆栈
 | ||||
|         let stack = StackInfo.getFirstStack(); | ||||
| 
 | ||||
|         return new LogLabel(stack?.calcPathName() ?? "Unknown url",  | ||||
|         InternalLogLabel.normalStyle, false, true, true); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 仅仅用来 filter 的 URL 链接的 label | ||||
|      */ | ||||
|     public static get filterUrlLabel():LogLabel { | ||||
| 
 | ||||
|         // 获得调用堆栈
 | ||||
|         let stack = StackInfo.getFirstStack(); | ||||
| 
 | ||||
|         return new LogLabel(stack?.calcPathName() ?? "Unknown url",  | ||||
|         InternalLogLabel.normalStyle, true, false, true); | ||||
|     } | ||||
|      | ||||
| } | ||||
| 
 | ||||
| export default InternalLogLabel; | ||||
| export {InternalLogLabel}; | ||||
| @ -1,61 +0,0 @@ | ||||
| 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 }; | ||||
| @ -1,83 +0,0 @@ | ||||
| import { LogStyle } from "./LogStyle"; | ||||
| import { LogLabel } from "./LogLabel"; | ||||
| 
 | ||||
| /** | ||||
|  * 生成圆角颜色标签样式 | ||||
|  */ | ||||
| const normalStyleGen = (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", normalStyleGen(160, 32, 240) | ||||
|     ); | ||||
| 
 | ||||
|     /** | ||||
|      * 生命周期函数--监听页面加载 | ||||
|      */ | ||||
|     static readonly OnLoadLabel = new LogLabel( | ||||
|         "onLoad", normalStyleGen(255, 140, 105) | ||||
|     ); | ||||
| 
 | ||||
|     /** | ||||
|      * 生命周期函数--监听页面初次渲染完成 | ||||
|      */ | ||||
|     static readonly OnReadyLabel = new LogLabel( | ||||
|         "onReady", normalStyleGen(255, 127, 36) | ||||
|     ); | ||||
| 
 | ||||
|     /** | ||||
|      * 生命周期函数--监听页面显示 | ||||
|      */ | ||||
|     static readonly OnShowLabel = new LogLabel( | ||||
|         "onShow", normalStyleGen(255, 215, 0) | ||||
|     ) | ||||
| 
 | ||||
|     /** | ||||
|      * 生命周期函数--监听页面隐藏 | ||||
|      */ | ||||
|     static readonly OnHideLabel = new LogLabel( | ||||
|         "onHide", normalStyleGen(173, 255, 47) | ||||
|     ); | ||||
| 
 | ||||
|     /** | ||||
|      * 生命周期函数--监听页面卸载 | ||||
|      */ | ||||
|     static readonly OnUnloadLabel = new LogLabel( | ||||
|         "onUnload", normalStyleGen(127, 255, 212) | ||||
|     ); | ||||
| 
 | ||||
|     /** | ||||
|      * 页面相关事件处理函数--监听用户下拉动作 | ||||
|      */ | ||||
|     static readonly OnPullDownRefreshLabel = new LogLabel( | ||||
|         "onPullDownRefresh", normalStyleGen(0, 191, 255) | ||||
|     ); | ||||
| 
 | ||||
|     /** | ||||
|      * 页面上拉触底事件的处理函数 | ||||
|      */ | ||||
|     static readonly OnReachBottomLabel = new LogLabel( | ||||
|         "onReachBottom", normalStyleGen(84, 255, 159) | ||||
|     ); | ||||
| 
 | ||||
|     /** | ||||
|      * 用户点击右上角分享 | ||||
|      */ | ||||
|     static readonly OnShareAppMessageLabel = new LogLabel( | ||||
|         "onShareAppMessage", normalStyleGen(147, 112, 219) | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| export default LifeCycleLogLabel; | ||||
| export { LifeCycleLogLabel }; | ||||
| @ -1,93 +0,0 @@ | ||||
| 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} | ||||
| @ -1,29 +0,0 @@ | ||||
| 
 | ||||
| /** | ||||
|  * 多重内容捆绑 | ||||
|  * 用于 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 }; | ||||
| @ -1,124 +0,0 @@ | ||||
| 
 | ||||
| /** | ||||
|  * 栈信息 | ||||
|  */ | ||||
| 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; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export default StackInfo; | ||||
| export { StackInfo }; | ||||
| @ -1,3 +1,4 @@ | ||||
| { | ||||
|   "usingComponents": {} | ||||
|   "usingComponents": {}, | ||||
|   "navigationStyle": "custom" | ||||
| } | ||||
| @ -0,0 +1,3 @@ | ||||
| // view.status-bar { | ||||
| //     // background-color: antiquewhite; | ||||
| // } | ||||
| @ -1,66 +1,68 @@ | ||||
| // pages/Timetable/Timetable.ts
 | ||||
| import { Logger } from "../../core/Logger"; | ||||
| import { LevelLogLabel, LifeCycleLogLabel } from "../../core/PresetLogLabel"; | ||||
| import { Manager, Modular, AnyWXContext, ILifetime } from "../../core/Module"; | ||||
| 
 | ||||
| Page({ | ||||
| 
 | ||||
|     /** | ||||
|    * 页面的初始数据 | ||||
|      * 课程表页面加载 | ||||
|      */ | ||||
|   data: { | ||||
|     onLoad: async function () { | ||||
| 
 | ||||
|   }, | ||||
|         this; | ||||
| 
 | ||||
|   /** | ||||
|    * 生命周期函数--监听页面加载 | ||||
|    */ | ||||
|   onLoad() { | ||||
|         let manager = new Manager(this); | ||||
|         let m1 = manager.addModule(M1, "m1"); | ||||
|         let m2 = manager.addModule(M2, "m2", {m1}); | ||||
| 
 | ||||
|   }, | ||||
|         let manager2 = new Manager(this); | ||||
|         let m22 = manager.addModule(M2, "m1", {m1}); | ||||
| 
 | ||||
|   /** | ||||
|    * 生命周期函数--监听页面初次渲染完成 | ||||
|    */ | ||||
|   onReady() { | ||||
|         this.setData; | ||||
| 
 | ||||
|   }, | ||||
|         Logger.log("课程表 (Timetable) 页面加载...",  | ||||
|         LevelLogLabel.TraceLabel, LifeCycleLogLabel.OnLoadLabel); | ||||
| 
 | ||||
|   /** | ||||
|    * 生命周期函数--监听页面显示 | ||||
|    */ | ||||
|   onShow() { | ||||
|         let systemInfo = wx.getSystemInfoSync(); | ||||
|   | ||||
|   }, | ||||
|         //状态栏高度
 | ||||
|         let statusBarHeight = Number(systemInfo.statusBarHeight); | ||||
|          | ||||
|   /** | ||||
|    * 生命周期函数--监听页面隐藏 | ||||
|    */ | ||||
|   onHide() { | ||||
|         let menu = wx.getMenuButtonBoundingClientRect() | ||||
|          | ||||
|   }, | ||||
|         //导航栏高度
 | ||||
|         let navBarHeight = menu.height + (menu.top - statusBarHeight) * 2 | ||||
|          | ||||
|   /** | ||||
|    * 生命周期函数--监听页面卸载 | ||||
|    */ | ||||
|   onUnload() { | ||||
|         //状态栏加导航栏高度
 | ||||
|         let navStatusBarHeight = statusBarHeight + menu.height + (menu.top - statusBarHeight) * 2 | ||||
|          | ||||
|   }, | ||||
|         console.log('状态栏高度',statusBarHeight) | ||||
|          | ||||
|   /** | ||||
|    * 页面相关事件处理函数--监听用户下拉动作 | ||||
|    */ | ||||
|   onPullDownRefresh() { | ||||
|         console.log('导航栏高度',navBarHeight) | ||||
|          | ||||
|   }, | ||||
|         console.log('状态栏加导航栏高度',navStatusBarHeight) | ||||
| 
 | ||||
|   /** | ||||
|    * 页面上拉触底事件的处理函数 | ||||
|    */ | ||||
|   onReachBottom() { | ||||
| 
 | ||||
|   }, | ||||
| 
 | ||||
|   /** | ||||
|    * 用户点击右上角分享 | ||||
|    */ | ||||
|   onShareAppMessage() { | ||||
|         this.setData({barh: navStatusBarHeight}); | ||||
| 
 | ||||
|     } | ||||
|    | ||||
| }) | ||||
| 
 | ||||
| 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 +1,3 @@ | ||||
| <view class="status-bar" style="height:{{barh}}px"></view> | ||||
| 
 | ||||
| <text>pages/Timetable/Timetable.wxml</text> | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user