将Knife4j所展示请求参数和响应参数转化为TS类型声明

ArticleaboutconvertingHTMLdatatoTypeScripttypedeclarationsinbrowserconsoleusingJavaScript.FocusesonKnife4j,request/responseparams,andelementtraversal.
摘要由CSDN通过智能技术生成

目标:在浏览器控制台输入js代码,将读取页面所展示的请求参数和响应参数,将他们转化为TS的类型声明,并在控制台中输出出来。

1 找到所需要的元素节点

根据图1、图2所示,分析页面结构找到对应的参数行节点
响应参数页面截图
图1 响应参数页面截图
在这里插入图片描述
图2 页面元素结构

let elements = null;
// 获取所有class为"api-title"的元素
document.getElementsByClassName("api-title").forEach((item) => {
  // 如果找到与传入参数title相匹配的元素
  if (item.innerText === title)
    // 将elements设置为该元素的下一个兄弟元素,这些元素包含"ant-table-row"类
    elements = item.nextSibling.getElementsByClassName("ant-table-row");
});

2 转化元素节点

现有的元素节点结构使用起来较为费劲,并且浪费性能,需要将其转化为我们需要的数据格式

先转化为列表

// 初始化一些变量,用于后续的数据结构构建
let minLevel = 0, // 初始化最小级别为100
  maxLevel = 0, // 初始化最大级别为0
  objectArray = [], // 创建一个空数组,用于存储对象
  load = { datas: [] }, // 创建一个对象,用于临时存储数据
  continuity = false, // 初始化连续性标志为false
  textLoad = ""; // 初始化文本承载字符串为空
// 根据传入的title参数,创建一个基础对象,并将其添加到objectArray数组中
objectArray.push({
  class: "-1",
  key: title === "请求参数" ? "request" : "response",
  title: title === "请求参数" ? "request" : "response",
  type: title === "请求参数" ? "request" : "response",
});
// 遍历elements数组中的每个元素
elements.forEach((item) => {
  // 获取当前元素的级别,并更新minLevel和maxLevel
  if (item.className.split("").at(-1) > maxLevel)
    maxLevel = item.className.split("").at(-1);
  if (item.className.split("").at(-1) < minLevel)
    minLevel = item.className.split("").at(-1);
  // 创建一个对象,包含当前元素的相关信息,并添加到objectArray数组中
  objectArray.push({
    class: item.className.split("").at(-1),
    key: item.children[0].innerText, // 参数名称
    title: item.children[1].innerText, // 参数说明
    type: item.children[title === "请求参数" ? 4 : 2].innerText, // 类型
    require: title === "请求参数" ? item.children[3].innerText : "", // 是否必须
  });
});

再定义两个函数便于将数据转换为字符串

// 定义generate函数,用于生成TypeScript接口代码
function generate(item, load) {
  // 构建接口的开始部分
  let temp = `export interface ${format(item.key)} { \n`;
  // 遍历load.datas数组中的每个数据项
  load.datas.forEach((value) => {
    // 获取数据项的类型,并根据类型构建TypeScript类型字符串
    let type = value.type;
    let tempType = "";
    if (type.indexOf("integer") >= 0) tempType = "number";
    else if (type.indexOf("number") >= 0) tempType = "number";
    else if (type.indexOf("string") >= 0) tempType = "string";
    else if (type.indexOf("boolean") >= 0) tempType = "boolean";
    else if (type.indexOf("分页返回") >= 0) tempType = `${format(value.key)}`;
    else if (type.indexOf("array") >= 0) tempType = `${format(value.key)}[]`;
    else tempType = "any";
    // 构建接口的属性定义,并添加到temp字符串中
    temp += `\t${value.key}${
      value.require === "false" ? "?" : ""
    }: ${tempType}; // ${value.title} \n`;
  });
  // 构建接口的结束部分,并将其添加到textLoad字符串中
  return temp += "}\n";
}
// 定义format函数,用于将字符串的首字母大写
function format(string) {
  return string.charAt(0).toUpperCase() + string.slice(1);
  }

最后将列表数据转化为树形结构,同时拼接字符串

// 从最大级别开始向下遍历,构建最终的数据结构
while (minLevel <= maxLevel) {
  for (let i = objectArray.length - 1; i >= 0; i--) {
    // 如果当前对象的级别不等于最大级别,设置连续性为false
    if (objectArray[i].class != maxLevel) continuity = false;
    // 如果当前对象的级别等于最大级别
    if (objectArray[i].class == maxLevel) {
      // 如果load.datas数组为空,设置load.end为当前索引
      if (load.datas.length == 0) load.end = i;
      // 设置连续性为true
      continuity = true;
      // 将当前对象添加到load.datas数组中
      load.datas.unshift(objectArray[i]);
    }
    // 如果load.datas数组不为空且连续性为false,执行数据处理
    if (load?.datas.length > 0 && !continuity) {
      // 设置load.start为当前索引+1
      load.start = i + 1;
      // 将load.datas数组中的数据作为当前对象的children属性
      objectArray[i].children = load.datas;
      // 调用generate函数,生成TypeScript接口代码
      textLoad = generate(objectArray[i], load) + textLoad;
      // 从objectArray数组中移除已处理的数据
      objectArray.splice(load.start, load.end - load.start + 1);
      // 重置load对象
      load = { datas: [] };
    }
  }
  // 减小最大级别,继续下一轮循环
  maxLevel--;
}

3 封装成函数

封装成函数便于调用

// 定义getText函数,接受一个参数title,表示要查找的标题
function getText(title) {
	// 上方的所有代码
	// 返回生成的TypeScript接口代码
  	return textLoad;
}
// 调用getText函数,打印生成的TypeScript接口代码
console.log(getText("请求参数") + "\n" + getText("响应参数"));

4 全部代码

// 这段代码的主要功能是将HTML中的表格数据转换为TypeScript接口定义,以便在TypeScript项目中使用。代码中使用了递归和循环来处理嵌套的数据结构,并且通过生成TypeScript代码的方式,使得数据结构更加清晰和易于维护。
// 定义getText函数,接受一个参数title,表示要查找的标题
function getText(title) {
  let elements = null;
  // 获取所有class为"api-title"的元素
  document.getElementsByClassName("api-title").forEach((item) => {
    // 如果找到与传入参数title相匹配的元素
    if (item.innerText === title)
      // 将elements设置为该元素的下一个兄弟元素,这些元素包含"ant-table-row"类
      elements = item.nextSibling.getElementsByClassName("ant-table-row");
  });
  // 初始化一些变量,用于后续的数据结构构建
  let minLevel = 0, // 初始化最小级别为100
    maxLevel = 0, // 初始化最大级别为0
    objectArray = [], // 创建一个空数组,用于存储对象
    load = { datas: [] }, // 创建一个对象,用于临时存储数据
    continuity = false, // 初始化连续性标志为false
    textLoad = ""; // 初始化文本承载字符串为空
  // 根据传入的title参数,创建一个基础对象,并将其添加到objectArray数组中
  objectArray.push({
    class: "-1",
    key: title === "请求参数" ? "request" : "response",
    title: title === "请求参数" ? "request" : "response",
    type: title === "请求参数" ? "request" : "response",
  });
  // 遍历elements数组中的每个元素
  elements.forEach((item) => {
    // 获取当前元素的级别,并更新minLevel和maxLevel
    if (item.className.split("").at(-1) > maxLevel)
      maxLevel = item.className.split("").at(-1);
    if (item.className.split("").at(-1) < minLevel)
      minLevel = item.className.split("").at(-1);
    // 创建一个对象,包含当前元素的相关信息,并添加到objectArray数组中
    objectArray.push({
      class: item.className.split("").at(-1),
      key: item.children[0].innerText, // 参数名称
      title: item.children[1].innerText, // 参数说明
      type: item.children[title === "请求参数" ? 4 : 2].innerText, // 类型
      require: title === "请求参数" ? item.children[3].innerText : "", // 是否必须
    });
  });
  // 从最大级别开始向下遍历,构建最终的数据结构
  while (minLevel <= maxLevel) {
    for (let i = objectArray.length - 1; i >= 0; i--) {
      // 如果当前对象的级别不等于最大级别,设置连续性为false
      if (objectArray[i].class != maxLevel) continuity = false;
      // 如果当前对象的级别等于最大级别
      if (objectArray[i].class == maxLevel) {
        // 如果load.datas数组为空,设置load.end为当前索引
        if (load.datas.length == 0) load.end = i;
        // 设置连续性为true
        continuity = true;
        // 将当前对象添加到load.datas数组中
        load.datas.unshift(objectArray[i]);
      }
      // 如果load.datas数组不为空且连续性为false,执行数据处理
      if (load?.datas.length > 0 && !continuity) {
        // 设置load.start为当前索引+1
        load.start = i + 1;
        // 将load.datas数组中的数据作为当前对象的children属性
        objectArray[i].children = load.datas;
        // 调用generate函数,生成TypeScript接口代码
        textLoad = generate(objectArray[i], load) + textLoad;
        // 从objectArray数组中移除已处理的数据
        objectArray.splice(load.start, load.end - load.start + 1);
        // 重置load对象
        load = { datas: [] };
      }
    }
    // 减小最大级别,继续下一轮循环
    maxLevel--;
  }
  // 定义generate函数,用于生成TypeScript接口代码
  function generate(item, load) {
    // 构建接口的开始部分
    let temp = `export interface ${format(item.key)} { \n`;
    // 遍历load.datas数组中的每个数据项
    load.datas.forEach((value) => {
      // 获取数据项的类型,并根据类型构建TypeScript类型字符串
      let type = value.type;
      let tempType = "";
      if (type.indexOf("integer") >= 0) tempType = "number";
      else if (type.indexOf("number") >= 0) tempType = "number";
      else if (type.indexOf("string") >= 0) tempType = "string";
      else if (type.indexOf("boolean") >= 0) tempType = "boolean";
      else if (type.indexOf("分页返回") >= 0) tempType = `${format(value.key)}`;
      else if (type.indexOf("array") >= 0) tempType = `${format(value.key)}[]`;
      else tempType = "any";
      // 构建接口的属性定义,并添加到temp字符串中
      temp += `\t${value.key}${
        value.require === "false" ? "?" : ""
      }: ${tempType}; // ${value.title} \n`;
    });
    // 构建接口的结束部分,并将其添加到textLoad字符串中
    return temp += "}\n";
  }
  // 定义format函数,用于将字符串的首字母大写
  function format(string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
  }
  // 返回生成的TypeScript接口代码
  return textLoad;
}
// 调用getText函数,打印生成的TypeScript接口代码
console.log(getText("请求参数") + "\n" + getText("响应参数"));

5 代码压缩

内容太长了,复制和使用起来都很不便捷,为方便使用rollup将其压缩,压缩后代码如下方所示

function e(e){let t=null;document.getElementsByClassName("api-title").forEach((n=>{n.innerText===e&&(t=n.nextSibling.getElementsByClassName("ant-table-row"))}));let n=0,s=0,a=[],l={datas:[]},r=!1,i="";for(a.push({class:"-1",key:"请求参数"===e?"request":"response",title:"请求参数"===e?"request":"response",type:"请求参数"===e?"request":"response"}),t.forEach((t=>{t.className.split("").at(-1)>s&&(s=t.className.split("").at(-1)),t.className.split("").at(-1)<n&&(n=t.className.split("").at(-1)),a.push({class:t.className.split("").at(-1),key:t.children[0].innerText,title:t.children[1].innerText,type:t.children["请求参数"===e?4:2].innerText,require:"请求参数"===e?t.children[3].innerText:""})}));n<=s;){for(let e=a.length-1;e>=0;e--)a[e].class!=s&&(r=!1),a[e].class==s&&(0==l.datas.length&&(l.end=e),r=!0,l.datas.unshift(a[e])),l?.datas.length>0&&!r&&(l.start=e+1,a[e].children=l.datas,i=c(a[e],l)+i,a.splice(l.start,l.end-l.start+1),l={datas:[]});s--}function c(e,t){let n=`export interface ${o(e.key)} { \n`;return t.datas.forEach((e=>{let t=e.type,s="";s=t.indexOf("integer")>=0||t.indexOf("number")>=0?"number":t.indexOf("string")>=0?"string":t.indexOf("boolean")>=0?"boolean":t.indexOf("分页返回")>=0?`${o(e.key)}`:t.indexOf("array")>=0?`${o(e.key)}[]`:"any",n+=`\t${e.key}${"false"===e.require?"?":""}: ${s}; // ${e.title} \n`})),n+="}\n"}function o(e){return e.charAt(0).toUpperCase()+e.slice(1)}return i}console.log(e("请求参数")+"\n"+e("响应参数"));

6 使用说明及成果

将第五部分的代码复制到控制台,进行回车
成果截图
最后将控制台钟打印出来的TS类型声明复制到代码中就可以直接使用了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值