From 18b167266d62708d0f7066fe335bf58d45f30f76 Mon Sep 17 00:00:00 2001 From: MrKBear Date: Sun, 28 Nov 2021 15:03:37 +0800 Subject: [PATCH 1/3] Add test module --- miniprogram/app.ts | 3 +- miniprogram/logger/InternalLogLabel.ts | 8 +- miniprogram/logger/Logger.ts | 8 +- miniprogram/logger/StackInfo.ts | 43 +++++- miniprogram/logger/index.ts | 11 -- miniprogram/{ => utils}/Config.ts | 0 miniprogram/utils/TestCase.ts | 206 +++++++++++++++++++++++++ 7 files changed, 254 insertions(+), 25 deletions(-) delete mode 100644 miniprogram/logger/index.ts rename miniprogram/{ => utils}/Config.ts (100%) create mode 100644 miniprogram/utils/TestCase.ts diff --git a/miniprogram/app.ts b/miniprogram/app.ts index 06eab41..02194b4 100644 --- a/miniprogram/app.ts +++ b/miniprogram/app.ts @@ -1,4 +1,5 @@ -import { Logger, LevelLogLabel } from "./logger/index"; +import { Logger } from "./logger/Logger"; +import { LevelLogLabel } from "./logger/LevelLogLabel"; App({ diff --git a/miniprogram/logger/InternalLogLabel.ts b/miniprogram/logger/InternalLogLabel.ts index 82c690a..f17cbc8 100644 --- a/miniprogram/logger/InternalLogLabel.ts +++ b/miniprogram/logger/InternalLogLabel.ts @@ -11,7 +11,7 @@ class InternalLogLabel { * 堆栈路径样式 */ public static readonly normalStyle:LogStyle = new LogStyle() - .setColor("#CCCCCC").setBorder("4px", "1px solid #979797").setBlank("0 5px"); + .setColor("#979797").setBorder("4px", "1px solid #979797").setBlank("0 5px"); /** * 一个回车 @@ -27,7 +27,7 @@ class InternalLogLabel { // 获得调用堆栈 let stack = StackInfo.getFirstStack(); - return new LogLabel(stack?.fileName ?? "Unknown file name", + return new LogLabel(stack?.calcFileName() ?? "Unknown file name", InternalLogLabel.normalStyle, false, true, true); } @@ -39,7 +39,7 @@ class InternalLogLabel { // 获得调用堆栈 let stack = StackInfo.getFirstStack(); - return new LogLabel(stack?.url ?? "Unknown url", + return new LogLabel(stack?.calcPathName() ?? "Unknown url", InternalLogLabel.normalStyle, false, true, true); } @@ -51,7 +51,7 @@ class InternalLogLabel { // 获得调用堆栈 let stack = StackInfo.getFirstStack(); - return new LogLabel(stack?.url ?? "Unknown url", + return new LogLabel(stack?.calcPathName() ?? "Unknown url", InternalLogLabel.normalStyle, true, false, true); } diff --git a/miniprogram/logger/Logger.ts b/miniprogram/logger/Logger.ts index 2a5a482..a2d8506 100644 --- a/miniprogram/logger/Logger.ts +++ b/miniprogram/logger/Logger.ts @@ -1,4 +1,4 @@ -import {LOGGER_CONSOLE, LOGGER_FILTER} from "../Config"; +import { LOGGER_FILTER, LOGGER_CONSOLE } from "../utils/Config"; import { InternalLogLabel } from "./InternalLogLabel"; import { LogLabel } from "./LogLabel"; import { MultipleLogContent } from "./MultipleLogContent"; @@ -147,12 +147,12 @@ class Logger { public static logLine(content:T, ...labels:LogLabel[]):T { return Logger.logBase>( new MultipleLogContent>(content), labels, - [InternalLogLabel.urlLabel, InternalLogLabel.blankLabel] + [InternalLogLabel.fileNameLabel, InternalLogLabel.blankLabel] )[0]; } /** - * 函数 Logger.logMultiple 的别名 + * 函数 Logger.logLine 的别名 */ public static ll:typeof Logger.logLine = Logger.logLine; @@ -164,7 +164,7 @@ class Logger { public static logLineMultiple>(labels:LogLabel[], ...content:T):T { return Logger.logBase( new MultipleLogContent(...content), labels, - [InternalLogLabel.urlLabel, InternalLogLabel.blankLabel] + [InternalLogLabel.fileNameLabel, InternalLogLabel.blankLabel] ); } diff --git a/miniprogram/logger/StackInfo.ts b/miniprogram/logger/StackInfo.ts index 4b6d06d..1793b8a 100644 --- a/miniprogram/logger/StackInfo.ts +++ b/miniprogram/logger/StackInfo.ts @@ -19,13 +19,46 @@ class StackInfo { */ public url:string | undefined; - public setInfo(functionName:string, fileName:string, url:string):StackInfo { + /** + * 文件名和行号 + */ + public fileNameLine: string | undefined; + + /** + * 设置信息 + * @param functionName 函数名 + * @param fileName 文件名 + * @param url 文件路径 + */ + public setInfo(functionName:string, fileNameLine:string, url:string):StackInfo { this.functionName = functionName; - this.fileName = fileName; + 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; + } + /** * 获取函数调用栈列表 */ @@ -65,7 +98,7 @@ class StackInfo { /** * 排除的 */ - public static readonly excludeFile:RegExp = /^Logger\.js:\d+:\d+/; + public static readonly excludeFile:RegExp = /^.*(\\|\/)logger(\\|\/).+\.js:\d+:\d+/; /** * 获取第一个调用栈 @@ -76,9 +109,9 @@ class StackInfo { for(let i = 0; i < callStack.length; i++) { - if(!callStack[i].fileName) continue; + if(!callStack[i].url) continue; - if(!StackInfo.excludeFile.test(callStack[i].fileName ?? "")) { + if(!StackInfo.excludeFile.test(callStack[i].url ?? "")) { return callStack[i]; } } diff --git a/miniprogram/logger/index.ts b/miniprogram/logger/index.ts deleted file mode 100644 index 6c169a9..0000000 --- a/miniprogram/logger/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -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"; \ No newline at end of file diff --git a/miniprogram/Config.ts b/miniprogram/utils/Config.ts similarity index 100% rename from miniprogram/Config.ts rename to miniprogram/utils/Config.ts diff --git a/miniprogram/utils/TestCase.ts b/miniprogram/utils/TestCase.ts new file mode 100644 index 0000000..b1cc94d --- /dev/null +++ b/miniprogram/utils/TestCase.ts @@ -0,0 +1,206 @@ +// import { Logger } from "../logger/Logger"; +import { LogStyle } from "../logger/LogStyle"; +import { LogLabel } from "../logger/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; + +/** + * 收集测试函数结构 + */ +class CaseCollect { + + /** + * 用例键名 + */ + public key:string; + + /** + * 用例测试函数 + */ + public caseFunction:TestFunction; + + /** + * 测试结果 + */ + result: Promise | undefined; + + /** + * @param key 测试用例键名 + * @param caseFunction 测试函数 + */ + public constructor(key:string, caseFunction:TestFunction) { + this.key = key; + this.caseFunction = caseFunction; + } + + /** + * 运行测试用例 + */ + public async runTestCase():Promise { + + 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 { + + let running:Promise[] = []; + + 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 }; \ No newline at end of file -- 2.45.2 From cea68f5145aec86392a6bb74d96cefbe3b2e00de Mon Sep 17 00:00:00 2001 From: MrKBear Date: Sun, 28 Nov 2021 16:25:48 +0800 Subject: [PATCH 2/3] Add LifeCycleLogLabel --- miniprogram/logger/LifeCycleLogLabel.ts | 83 +++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 miniprogram/logger/LifeCycleLogLabel.ts diff --git a/miniprogram/logger/LifeCycleLogLabel.ts b/miniprogram/logger/LifeCycleLogLabel.ts new file mode 100644 index 0000000..d83d606 --- /dev/null +++ b/miniprogram/logger/LifeCycleLogLabel.ts @@ -0,0 +1,83 @@ +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 }; \ No newline at end of file -- 2.45.2 From 7fa3a215cf18b551e06418d61bf9f895e518c118 Mon Sep 17 00:00:00 2001 From: MrKBear Date: Wed, 1 Dec 2021 10:52:38 +0800 Subject: [PATCH 3/3] Add Modular and Manager, merge Logger to core --- miniprogram/app.scss | 17 + miniprogram/app.ts | 23 +- miniprogram/{utils => core}/Config.ts | 0 .../{logger/LogStyle.ts => core/LogLabel.ts} | 93 ++++- miniprogram/{logger => core}/Logger.ts | 42 ++- miniprogram/core/Module.ts | 356 ++++++++++++++++++ miniprogram/core/PresetLogLabel.ts | 313 +++++++++++++++ miniprogram/{utils => core}/TestCase.ts | 3 +- miniprogram/logger/InternalLogLabel.ts | 61 --- miniprogram/logger/LevelLogLabel.ts | 61 --- miniprogram/logger/LifeCycleLogLabel.ts | 83 ---- miniprogram/logger/LogLabel.ts | 93 ----- miniprogram/logger/MultipleLogContent.ts | 29 -- miniprogram/logger/StackInfo.ts | 124 ------ miniprogram/pages/Timetable/Timetable.json | 3 +- miniprogram/pages/Timetable/Timetable.scss | 3 + miniprogram/pages/Timetable/Timetable.ts | 104 ++--- miniprogram/pages/Timetable/Timetable.wxml | 2 + 18 files changed, 875 insertions(+), 535 deletions(-) rename miniprogram/{utils => core}/Config.ts (100%) rename miniprogram/{logger/LogStyle.ts => core/LogLabel.ts} (66%) rename miniprogram/{logger => core}/Logger.ts (84%) create mode 100644 miniprogram/core/Module.ts create mode 100644 miniprogram/core/PresetLogLabel.ts rename miniprogram/{utils => core}/TestCase.ts (98%) delete mode 100644 miniprogram/logger/InternalLogLabel.ts delete mode 100644 miniprogram/logger/LevelLogLabel.ts delete mode 100644 miniprogram/logger/LifeCycleLogLabel.ts delete mode 100644 miniprogram/logger/LogLabel.ts delete mode 100644 miniprogram/logger/MultipleLogContent.ts delete mode 100644 miniprogram/logger/StackInfo.ts diff --git a/miniprogram/app.scss b/miniprogram/app.scss index e69de29..a622558 100644 --- a/miniprogram/app.scss +++ b/miniprogram/app.scss @@ -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); + } +} \ No newline at end of file diff --git a/miniprogram/app.ts b/miniprogram/app.ts index 02194b4..a769922 100644 --- a/miniprogram/app.ts +++ b/miniprogram/app.ts @@ -1,5 +1,6 @@ import { Logger } from "./logger/Logger"; import { LevelLogLabel } from "./logger/LevelLogLabel"; +import { LifeCycleLogLabel } from "./logger/LifeCycleLogLabel"; App({ @@ -13,25 +14,7 @@ App({ * 小程序加载时 */ 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); } }) \ No newline at end of file diff --git a/miniprogram/utils/Config.ts b/miniprogram/core/Config.ts similarity index 100% rename from miniprogram/utils/Config.ts rename to miniprogram/core/Config.ts diff --git a/miniprogram/logger/LogStyle.ts b/miniprogram/core/LogLabel.ts similarity index 66% rename from miniprogram/logger/LogStyle.ts rename to miniprogram/core/LogLabel.ts index 30990ee..a4d3424 100644 --- a/miniprogram/logger/LogStyle.ts +++ b/miniprogram/core/LogLabel.ts @@ -134,5 +134,94 @@ class LogStyle { } } -export default LogStyle; -export {LogStyle}; \ No newline at end of file +/** + * 日志标签 + */ +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} \ No newline at end of file diff --git a/miniprogram/logger/Logger.ts b/miniprogram/core/Logger.ts similarity index 84% rename from miniprogram/logger/Logger.ts rename to miniprogram/core/Logger.ts index a2d8506..de64257 100644 --- a/miniprogram/logger/Logger.ts +++ b/miniprogram/core/Logger.ts @@ -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> { + + /** + * 输出内容 + */ + 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(content:T, ...labels:LogLabel[]):T { return Logger.logBase>( new MultipleLogContent>(content), labels, - [InternalLogLabel.fileNameLabel] + [StackLogLabel.fileNameLabel] )[0]; } @@ -130,7 +156,7 @@ class Logger { public static logMultiple>(labels:LogLabel[], ...content:T):T { return Logger.logBase( new MultipleLogContent(...content), labels, - [InternalLogLabel.fileNameLabel] + [StackLogLabel.fileNameLabel] ); } @@ -147,7 +173,7 @@ class Logger { public static logLine(content:T, ...labels:LogLabel[]):T { return Logger.logBase>( new MultipleLogContent>(content), labels, - [InternalLogLabel.fileNameLabel, InternalLogLabel.blankLabel] + [StackLogLabel.fileNameLabel, StackLogLabel.blankLabel] )[0]; } @@ -164,7 +190,7 @@ class Logger { public static logLineMultiple>(labels:LogLabel[], ...content:T):T { return Logger.logBase( new MultipleLogContent(...content), labels, - [InternalLogLabel.fileNameLabel, InternalLogLabel.blankLabel] + [StackLogLabel.fileNameLabel, StackLogLabel.blankLabel] ); } diff --git a/miniprogram/core/Module.ts b/miniprogram/core/Module.ts new file mode 100644 index 0000000..9f84597 --- /dev/null +++ b/miniprogram/core/Module.ts @@ -0,0 +1,356 @@ + +/** + * 自定义对象类型 + */ +type IAnyTypeObject = { + [x:string]: T; +}; + +// 微信 Data 类型 +type Data = WechatMiniprogram.Page.Data; + +// 微信生命周期类型 +type ILifetime = WechatMiniprogram.Page.ILifetime; + +// 继承的方法 +type InstanceMethods = WechatMiniprogram.Page.InstanceMethods; + +// 继承的属性 +type InstanceProperties = WechatMiniprogram.Page.InstanceProperties; + +/** + * 定义微信微信上下文类型 + * + * @template TD data 结构类型 + * @template TC 用户 MinIn 类型 + * + * Partial 可选的微信生命周期 + * Partial> 可选的 data 结构 + * InstanceMethods 必选的微信继承方法 + * InstanceProperties 必选的微信继承属性 + */ +type WXContext = Partial & Partial> +& InstanceMethods & InstanceProperties & TC; + +/** + * 任意的微信上下文 + * 当我们不关心具体是哪个上下文时 + * 使用这个类型 + */ +type AnyWXContext = WXContext; + +/** + * 依赖关系图谱 + * 注意: 这是一个递给类型 + * @template M 限制了所有依赖必须使用同一个 manager + */ +type Depends> = { + [x:string]: Modular>; +}; + +/** + * 页面模组 + * @template M 所属 Manager + * @template DEP 模组依赖 + * @template TD 模组 Data 类型 + */ +class Modular< + M extends Manager = Manager, + DEP extends Depends = Depends, + TD extends IAnyTypeObject = IAnyTypeObject> +implements WXContext { + + // [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; + + /** + * 函数使用的参数列表 + */ + private paramList:Set; + + /** + * 命名空间 + */ + private nameSpace:string; + + // 映射主上下文属性 + public get is():string { return this.context.is }; + public get route():string { return this.context.route }; + public get options():Record { + 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(); + this.paramList = new Set(); + this.nameSpace = nameSpace; + } + + public setData(data:Partial, 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(name: string, detail?: DetailType, + options?: WechatMiniprogram.Component.TriggerEventOption): void { + return this.context.triggerEvent(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 { + + /** + * 微信生命周期 + */ + 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, M extends Modular> + (mode: new (manager:Manager, 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[] = []; + let simple:any; + + for(let i = 0; i < this.modules.length; i++) { + + let res: Promise | 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) { + this.creatAllHooks(); + let res = this.creatHooks("onLoad")(query as any); + return res; + } + +} + +export { Manager, Modular, AnyWXContext, WXContext, ILifetime} \ No newline at end of file diff --git a/miniprogram/core/PresetLogLabel.ts b/miniprogram/core/PresetLogLabel.ts new file mode 100644 index 0000000..f456418 --- /dev/null +++ b/miniprogram/core/PresetLogLabel.ts @@ -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 }; \ No newline at end of file diff --git a/miniprogram/utils/TestCase.ts b/miniprogram/core/TestCase.ts similarity index 98% rename from miniprogram/utils/TestCase.ts rename to miniprogram/core/TestCase.ts index b1cc94d..499324d 100644 --- a/miniprogram/utils/TestCase.ts +++ b/miniprogram/core/TestCase.ts @@ -1,6 +1,5 @@ // import { Logger } from "../logger/Logger"; -import { LogStyle } from "../logger/LogStyle"; -import { LogLabel } from "../logger/LogLabel"; +import { LogStyle, LogLabel } from "./LogLabel"; /** * 测试结果 diff --git a/miniprogram/logger/InternalLogLabel.ts b/miniprogram/logger/InternalLogLabel.ts deleted file mode 100644 index f17cbc8..0000000 --- a/miniprogram/logger/InternalLogLabel.ts +++ /dev/null @@ -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}; \ No newline at end of file diff --git a/miniprogram/logger/LevelLogLabel.ts b/miniprogram/logger/LevelLogLabel.ts deleted file mode 100644 index 7d8fb68..0000000 --- a/miniprogram/logger/LevelLogLabel.ts +++ /dev/null @@ -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 }; \ No newline at end of file diff --git a/miniprogram/logger/LifeCycleLogLabel.ts b/miniprogram/logger/LifeCycleLogLabel.ts deleted file mode 100644 index d83d606..0000000 --- a/miniprogram/logger/LifeCycleLogLabel.ts +++ /dev/null @@ -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 }; \ No newline at end of file diff --git a/miniprogram/logger/LogLabel.ts b/miniprogram/logger/LogLabel.ts deleted file mode 100644 index 4f3253c..0000000 --- a/miniprogram/logger/LogLabel.ts +++ /dev/null @@ -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} \ No newline at end of file diff --git a/miniprogram/logger/MultipleLogContent.ts b/miniprogram/logger/MultipleLogContent.ts deleted file mode 100644 index 87dd610..0000000 --- a/miniprogram/logger/MultipleLogContent.ts +++ /dev/null @@ -1,29 +0,0 @@ - -/** - * 多重内容捆绑 - * 用于 log 输出 - */ -class MultipleLogContent> { - - /** - * 输出内容 - */ - private readonly content:T; - - /** - * @param content 输出内容 - */ - public constructor(...content:T) { - this.content = content; - } - - /** - * 获取内容 - */ - public getContent():T { - return this.content; - } -} - -export default MultipleLogContent; -export { MultipleLogContent }; \ No newline at end of file diff --git a/miniprogram/logger/StackInfo.ts b/miniprogram/logger/StackInfo.ts deleted file mode 100644 index 1793b8a..0000000 --- a/miniprogram/logger/StackInfo.ts +++ /dev/null @@ -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 }; \ No newline at end of file diff --git a/miniprogram/pages/Timetable/Timetable.json b/miniprogram/pages/Timetable/Timetable.json index 8835af0..965b8e8 100644 --- a/miniprogram/pages/Timetable/Timetable.json +++ b/miniprogram/pages/Timetable/Timetable.json @@ -1,3 +1,4 @@ { - "usingComponents": {} + "usingComponents": {}, + "navigationStyle": "custom" } \ No newline at end of file diff --git a/miniprogram/pages/Timetable/Timetable.scss b/miniprogram/pages/Timetable/Timetable.scss index e69de29..ba845f6 100644 --- a/miniprogram/pages/Timetable/Timetable.scss +++ b/miniprogram/pages/Timetable/Timetable.scss @@ -0,0 +1,3 @@ +// view.status-bar { +// // background-color: antiquewhite; +// } diff --git a/miniprogram/pages/Timetable/Timetable.ts b/miniprogram/pages/Timetable/Timetable.ts index af22870..0cc3a60 100644 --- a/miniprogram/pages/Timetable/Timetable.ts +++ b/miniprogram/pages/Timetable/Timetable.ts @@ -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); + + let menu = wx.getMenuButtonBoundingClientRect() + + //导航栏高度 + let navBarHeight = menu.height + (menu.top - statusBarHeight) * 2 + + //状态栏加导航栏高度 + let navStatusBarHeight = statusBarHeight + menu.height + (menu.top - statusBarHeight) * 2 + + console.log('状态栏高度',statusBarHeight) + + console.log('导航栏高度',navBarHeight) + + console.log('状态栏加导航栏高度',navStatusBarHeight) - }, + this.setData({barh: navStatusBarHeight}); - /** - * 生命周期函数--监听页面隐藏 - */ - onHide() { + } + +}) - }, +class M1 extends Modular { - /** - * 生命周期函数--监听页面卸载 - */ - onUnload() { + public onLoad(){ - }, + } +} - /** - * 页面相关事件处理函数--监听用户下拉动作 - */ - onPullDownRefresh() { +class M2 extends Modular}> { + + public onLoad() { + // this.setData(); + } + // hhh(){ + + // } - }, - - /** - * 页面上拉触底事件的处理函数 - */ - onReachBottom() { - - }, - - /** - * 用户点击右上角分享 - */ - onShareAppMessage() { - - } -}) \ No newline at end of file + hh(){} +} \ No newline at end of file diff --git a/miniprogram/pages/Timetable/Timetable.wxml b/miniprogram/pages/Timetable/Timetable.wxml index e28110a..4720305 100644 --- a/miniprogram/pages/Timetable/Timetable.wxml +++ b/miniprogram/pages/Timetable/Timetable.wxml @@ -1 +1,3 @@ + + pages/Timetable/Timetable.wxml -- 2.45.2