docs: function CheckParams(data, query)
  {
      for (let key in data) {
          let par = data[key];
          if(par.constructor!=Object)continue;//非
          let errkey = par.lbl?par.lbl:(par.rem?par.rem:key);//发生错误时的key的称呼方式
          if(par.constructor != Object){return `${errkey}接口文档定义错误。`}
          if (null==par.rem && null==par.lbl) {//这里则认为是两层及以上对象嵌套,递归
              if(par.need && null==query[key]){query[key]={};delete par.need;delete par.rem;delete par.lbl;}//如果需要的传外层的话,且为空时,默认给空对象
              let msg =CheckParams(data[key],query[key]);
              if(msg){return msg;}
          }else {
              //参数是否缺少
              if(!query){return 0;}
              let val = query[key];
              //检验必要的请求参数,非必要参数则不验证
              if (par.need&&null==val) {return`缺少${par.lbl?par.lbl:(par.rem?par.rem:key)}参数。`;}
              //若未传,且有默认值,则设置默认值,然后继续向下检验默认值
              if(null!=par.default&&null==val){query[key]=par.default;val = par.default;CTX.usedefault = true;}
              if(null!=par.def&&null==val){query[key]=par.def;val = par.def;CTX.usedefault = true;}
              if(null==val){continue;}//未传的非必须参数不需要校验
              //参数类型
              if(par.type) {
                  let isObj=true;
                  try{
                      switch(par.type.toLowerCase()){
                          case 'number':
                          case 'int':
                              if((par.type == 'number'||par.type =='int')&& parseInt(val)!=val)throw Error('类型错误');
                              query[key] = parseInt(val);
                              val = query[key];
                              break;
                          case 'float':
                              if(par.type == 'float' && parseFloat(val)!=val)throw Error('类型错误');
                              query[key] = parseFloat(val);
                              val = query[key];
                              break;
                          case 'string':if(val.constructor.name != 'String')throw Error('类型错误');break;
                          case 'boolean':
                              if(par.type == 'boolean'&&val.constructor!=Boolean&&(val.trim()!="false"&&val.trim()!="true"))throw Error('类型错误');
                              if(val.constructor!=Boolean)query[key]=(val.trim()==="false"?false:true);
                              val = query[key];
                              break;
                          case 'object':
                              if(val.constructor != Object){
                                  try{
                                      val=JSON.parse(val);
                                  }catch(err){isObj=false;}
                              }
                              if(!isObj)throw Error('类型错误');break;
                          case 'array':
                              if(val.constructor != Array){
                                  try{
                                      val=JSON.parse(val);
                                  }catch(err){isObj=false}
                              }
                              if(!isObj)throw Error('类型错误');break;
                          case 'array':if(val.constructor.name != 'Array')throw Error('类型错误');break;
                          case 'file':if(val.path && !isExist(val.path)) throw Error('类型错误');break;
                          case 'json':
                              try{
                                  let t=JSON.parse(val);
                                  query[key]=t;
                                  val=t;
                              }catch(err){
                                  throw Error('json格式错误');
                              }
                              break;
                          default :
                              if(val.constructor.name != 'String')throw Error('类型错误');
                      }
                  }catch(err){return `${errkey}参数类型错误。`;}
              }
              let msg;
              //参数长度控制
              if(par.len){
                  //接口文档在定义的时候定义为一个对象
                  var ol = 0;
                  let name = "长度";
                  switch (par.type.toLowerCase()){
                      case 'array':
                          ol =  val.length;
                          name = "数组长度";
                          break;
                      case 'object'://数组或者对象
                          ol =  Object.keys(val).length;
                          name = "对象长度";
                          break;
                      case 'string':
                          ol = val.length;
                          name = "字符串长度";
                          break;
                      case 'file':
                          ol = val.size;//文件大小
                          name = "文件大小";
                          break;
                      default:
                          ol = val.length;
                          name = "字符串长度";
                          break;
                  }
                  if((msg=getRange(ol,par.len))){
                      return `${errkey}${name}${msg}${'file'==par.type?'字节':''}`;
                  }
              }
              //范围控制
              if(par.range && (msg=getRange(val,par.range))){return `${errkey}${'string'==par.type?"字符内容":""}${msg}`;}
              //枚举型判断参数是否在设置范围内
              if (par.enum && par.enum.indexOf(val)<0) {return `${errkey}参数只能是${par.enum}。`;}
              //正则验证参数是否合法
              if(par.reg && !eval(par.reg).test((par.type == 'file' ? val.name:par.type=='json'?JSON.stringify(val):val))){return `${errkey}格式错误`;}
              // RES.usedefault = null;
          }
      }
      return 0;
  }