238 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			238 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { LogLabel } from "./LogLabel";
 | ||
| import { Logger } from "./Logger";
 | ||
| import { LevelLogLabel, colorRadio } from "./PresetLogLabel";
 | ||
| 
 | ||
| interface IAnyData {
 | ||
|     [x:string]: any
 | ||
| }
 | ||
| 
 | ||
| type IWxRequestOption<O> = WechatMiniprogram.RequestOption<O>;
 | ||
| 
 | ||
| type DeepReadonly<T> = {
 | ||
|     readonly [P in keyof T]: DeepReadonly<T[P]>;
 | ||
| };
 | ||
| 
 | ||
| /**
 | ||
|  * 请求参数设置
 | ||
|  */
 | ||
| type IParamSetting<T extends IAnyData> = {
 | ||
|     [P in keyof T]: {
 | ||
|         
 | ||
|         /**
 | ||
|          * 默认值
 | ||
|          */
 | ||
|         defaultValue?: T[P],
 | ||
| 
 | ||
|         /**
 | ||
|          * ### 数据测试
 | ||
|          * 1、支持正则表达式测试 \
 | ||
|          * 2、支持使用 string === string 测试 \
 | ||
|          * 3、支持使用 number === number 测试 \
 | ||
|          * 4、支持使用自定义函数测试 
 | ||
|          */
 | ||
|         tester?: RegExp | ((data:T[P]) => boolean) | string | number,
 | ||
| 
 | ||
|         /**
 | ||
|          * ### 预解析函数
 | ||
|          * 1、此函数用来处理该键值 \
 | ||
|          * 2、当返回 undefined 时此键值被遗弃 \
 | ||
|          * 3、返回值时,此键值被覆盖
 | ||
|          * 
 | ||
|          * @param data 当前给定数据
 | ||
|          * @param key 当前给定数据键值
 | ||
|          * @param all 全部输入数据
 | ||
|          * @returns 解析结果
 | ||
|          */
 | ||
|         parse?: ((data:T[P], key:string, all:DeepReadonly<Partial<T>>) => T[P] | undefined),
 | ||
| 
 | ||
|         /**
 | ||
|          * 是否为请求头数据
 | ||
|          */
 | ||
|         isHeader?: boolean,
 | ||
| 
 | ||
|         /**
 | ||
|          * 是否为模板
 | ||
|          */
 | ||
|         isTemplate?: boolean
 | ||
| 
 | ||
|         /**
 | ||
|          * 是否可选
 | ||
|          */
 | ||
|         Optional?: boolean
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * 接口调用
 | ||
|  */
 | ||
| class API<I extends IAnyData, O extends IAnyData> {
 | ||
| 
 | ||
|     public static get baseUrl():string {
 | ||
|         return "https://xxx.xxx"
 | ||
|     }
 | ||
| 
 | ||
|     public static defaultLogLabel:LogLabel = new LogLabel(
 | ||
|         `API:API`, colorRadio(200, 120, 222)
 | ||
|     );
 | ||
| 
 | ||
|     /**
 | ||
|      * Logger 使用的标签
 | ||
|      */
 | ||
|     private LogLabel:LogLabel = API.defaultLogLabel;
 | ||
| 
 | ||
|     /**
 | ||
|      * Api 唯一 ID
 | ||
|      */
 | ||
|     public key:string = "API";
 | ||
| 
 | ||
|     /**
 | ||
|      * API url
 | ||
|      */
 | ||
|     public url:string = "/";
 | ||
| 
 | ||
|     /**
 | ||
|      * API 需要的参数列表
 | ||
|      */
 | ||
|     public params:IParamSetting<I> = {} as any;
 | ||
| 
 | ||
|     /**
 | ||
|      * API 需要的数据
 | ||
|      */
 | ||
|     public data?:Partial<I>;
 | ||
| 
 | ||
|     /**
 | ||
|      * 请求数据
 | ||
|      */
 | ||
|     public requestData?:IWxRequestOption<O>;
 | ||
| 
 | ||
|     /**
 | ||
|      * 超时时间 (wx.request)
 | ||
|      */
 | ||
|     public timeout?:number;
 | ||
| 
 | ||
|     /**
 | ||
|      * 请求方法 (wx.request)
 | ||
|      */
 | ||
|     public method:HTTPMethod = HTTPMethod.GET;
 | ||
| 
 | ||
|     /**
 | ||
|      * 构造函数
 | ||
|      * 注意:data 是不安全的,请传入数据副本
 | ||
|      * @param data API需要的全部数据
 | ||
|      */
 | ||
|     public constructor(data?: Partial<I>) {
 | ||
|         this.data = data ?? {};
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 初始化标签
 | ||
|      */
 | ||
|     public initLabel() {
 | ||
|         this.LogLabel = new LogLabel(
 | ||
|             `API:${ this.key }`, colorRadio(200, 120, 222)
 | ||
|         );
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 初始化数据
 | ||
|      */
 | ||
|     public initData() {
 | ||
| 
 | ||
|         if (this.data === void 0) {
 | ||
|             Logger.log(`数据初始化异常: 没有输入 [data] 数据!`, 
 | ||
|             LevelLogLabel.FatalLabel, this.LogLabel);
 | ||
|             return;
 | ||
|         }
 | ||
| 
 | ||
|         for (let key in this.params) {
 | ||
| 
 | ||
|             let data = this.data[key];
 | ||
|             let { defaultValue, Optional, tester } = this.params[key];
 | ||
| 
 | ||
|             // 默认值赋予
 | ||
|             if (data === void 0 && defaultValue !== void 0) {
 | ||
|                 this.data[key] = defaultValue;
 | ||
|             }
 | ||
| 
 | ||
|             // 数据存在测试
 | ||
|             if (data === void 0 && !Optional) {
 | ||
|                 Logger.log(`数据校验异常: 数据 [${key}] 是必须的,但是并没有接收到!`, 
 | ||
|                 LevelLogLabel.FatalLabel, this.LogLabel);
 | ||
|             }
 | ||
| 
 | ||
|             // 用户自定义测试
 | ||
|             if (data !== void 0 && tester !== void 0) {
 | ||
|                 let testRes:boolean = false;
 | ||
|                 
 | ||
|                 if (tester instanceof RegExp) {
 | ||
|                     testRes = tester.test(data!);
 | ||
|                 } else if (typeof tester === "string" || typeof tester === "number") {
 | ||
|                     testRes = tester === data;
 | ||
|                 } else if (tester instanceof Function) {
 | ||
|                     testRes = tester(data!);
 | ||
|                 } else {
 | ||
|                     Logger.logMultiple(
 | ||
|                         [LevelLogLabel.FatalLabel, this.LogLabel],
 | ||
|                         `数据校验异常: [${ key }] 参数存在未知类型的 tester:`, tester
 | ||
|                     );
 | ||
|                 }
 | ||
| 
 | ||
|                 if (!testRes) {
 | ||
|                     Logger.logMultiple(
 | ||
|                         [LevelLogLabel.FatalLabel, this.LogLabel],
 | ||
|                         `数据校验异常: [${ key }] 参数数据未通过自定义的 tester:`, data
 | ||
|                     );
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 收集请求数据
 | ||
|      */
 | ||
|     public collectData() {
 | ||
| 
 | ||
|         if (this.data === void 0) {
 | ||
|             Logger.log(`收集请求数据异常: 没有输入 [data] 数据!`, 
 | ||
|             LevelLogLabel.FatalLabel, this.LogLabel);
 | ||
|             return;
 | ||
|         }
 | ||
| 
 | ||
|         // 重置请求数据
 | ||
|         const requestData:IWxRequestOption<O> = this.requestData = {
 | ||
|             url: API.baseUrl + this.url,
 | ||
|         };
 | ||
| 
 | ||
|         for (let key in this.params) {
 | ||
|             
 | ||
|             let data = this.data[key];
 | ||
|             let { isHeader, isTemplate, parse } = this.params[key];
 | ||
|             
 | ||
|             // 数据预解析
 | ||
|             if (parse !== void 0) {
 | ||
|                 data = parse(data!, key, this.data as DeepReadonly<Partial<I>>);
 | ||
|             }
 | ||
| 
 | ||
|             // 加载数据
 | ||
|             if (!isTemplate) {
 | ||
|                 if (isHeader) {
 | ||
|                     wx.request
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| enum HTTPMethod {
 | ||
|     OPTIONS = "OPTIONS", 
 | ||
|     GET = "GET", 
 | ||
|     HEAD = "HEAD", 
 | ||
|     POST = "POST", 
 | ||
|     PUT = "PUT", 
 | ||
|     DELETE = "DELETE", 
 | ||
|     TRACE = "TRACE", 
 | ||
|     CONNECT = "CONNECT"
 | ||
| }
 | ||
| 
 | ||
| export default API;
 | ||
| export { API, IParamSetting } | 
