用Rust生成Ant-Design Table Columns | 京东云技术团队

这篇具有很好参考价值的文章主要介绍了用Rust生成Ant-Design Table Columns | 京东云技术团队。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

经常开发表格,是不是已经被手写Ant-Design Table的Columns整烦了?

尤其是ToB项目,表格经常动不动就几十列。每次照着后端给的接口文档一个个配置,太头疼了,主要是有时还会粘错就尴尬了。

那有没有办法能自动生成columns配置呢?

当然可以。

目前后端的接口文档一般是使用Swagger来生成的,Swagger是基于OpenAPI规范的一种实现。(OpenAPI规范是一种描述RESTful API的语言无关的格式,它允许开发者定义API的操作、输入和输出参数、错误响应等信息,并提供了一种规范的方式来描述和交互API。)

那么我们只需要解析Swagger的配置就可以反向生成前端代码。

接下来我们就写个CLI工具来生成Table Columns。

平常我们实现一个CLI工具一般都是用Node,今天我们搞点不一样的,用Rust。

开始咯

swagger.json

打开后端用swagger生成的接口文档中的一个接口,一般是下面这样的,可以看到其json配置文件,如下图:
用Rust生成Ant-Design Table Columns | 京东云技术团队,硬核干货,rust,京东云,开发语言,Columns

swagger: 2.0表明了这个文档使用的swagger版本,不同版本json配置结构会不同。

paths这里key是接口地址。

可以看到当前接口是“/api/operations/cate/rhythmTableList”。
顺着往下看,“post.responses.200.schema.originalRef”,这就是我们要找的,这个接口对应的返回值定义。

definitions拿到上面的返回值定义,就可以在“definitions”里找到对应的值。
这里是“definitions.ResponseResult«List«CateInsightRhythmListVO»».properties.data.items.originalRef”
通过他就可找到返回的实体类定义CateInsightRhythmListVO

CateInsightRhythmListVO这里就是我们生成Table Columns需要的字段定义了。

CLI

接下来制作命令行工具

起初我使用的是commander-rust,感觉用起来更符合直觉,全程采用macros定义即可。
但到发布的时候才发现,Rust依赖必须有一个确定的版本,commander-rust目前使用的是分支解析。。。
最后还是换了clap

clap的定义就要繁琐些,如下:

#[derive(Parser)]
#[command(author, version)]
#[command(about = "swagger_to - Generate code based on swagger.json")]
struct Cli {
    #[command(subcommand)]
    command: Option,
}

#[derive(Subcommand)]
enum Commands {
    /// Generate table columns for ant-design
    Columns(JSON),
}

#[derive(Args)]
struct JSON {
    /// path/to/swagger.json
    path: Option,
}


这里使用#[command(subcommand)]#[derive(Subcommand)]来定义columns子命令
使用#[derive(Args)]定义了path参数,用来让用户输入swagger.json的路径

实现columns子命令

columns命令实现的工作主要是下面几步:

  1. 读取用户输入的swagger.json

  2. 解析swager.json

  3. 生成ant-design table columns

  4. 生成对应Typescript类型定义

读取用户输入的swagger.json

这里用到了一个crate,serde_json, 他可以将swagger.json转换为对象。

let file = File::open(json).expect("File should open");
let swagger_json: Value = serde_json::from_reader(file).expect("File should be proper JSON");


解析swager.json

有了swagger_json对象,我们就可以按照OpenAPI的结构来解析它。

/// openapi.rs

pub fn parse_openapi(swagger_json: Value) -> Vec {
    let paths = swagger_json["paths"].as_object().unwrap();
    let apis = paths
        .iter()
        .map(|(path, path_value)| {
            let post = path_value["post"].as_object().unwrap();
            let responses = post["responses"].as_object().unwrap();
            let response = responses["200"].as_object().unwrap();
            let schema = response["schema"].as_object().unwrap();
            let original_ref = schema["originalRef"].as_str().unwrap();
            let data = swagger_json["definitions"][original_ref]["properties"]["data"]
                .as_object()
                .unwrap();
            let items = data["items"].as_object().unwrap();
            let original_ref = items["originalRef"].as_str().unwrap();
            let properties = swagger_json["definitions"][original_ref]["properties"]
                .as_object()
                .unwrap();
            let response = properties
                .iter()
                .map(|(key, value)| {
                    let data_type = value["type"].as_str().unwrap();
                    let description = value["description"].as_str().unwrap();
                    ResponseDataItem {
                        key: key.to_string(),
                        data_type: data_type.to_string(),
                        description: description.to_string(),
                    }
                })
                .collect();
            Api {
                path: path.to_string(),
                model_name: original_ref.to_string(),
                response: response,
            }
        })
        .collect();
    return apis;
}


这里我写了一个parse_openapi()方法,用来将swagger.json解析成下面这种形式:

[
  {
    path: 'xxx',
    model_name: 'xxx',
    response: [
      {
        key: '字段key',
        data_type: 'number',
        description: '字段名'
      }
    ]
  }
]


对应的Rust结构定义是这样的:

pub struct ResponseDataItem {
    pub key: String,
    pub data_type: String,
    pub description: String,
}

pub struct Api {
    pub path: String,
    pub model_name: String,
    pub response: Vec<ResponseDataItem>,
}


生成ant-design table columns

有了OpenAPI对象就可以生成Table Column了,这里写了个generate_columns()方法:

/// generator.rs

pub fn generate_columns(apis: &mut Vec) -> String {
    let mut output_text = String::new();
    output_text.push_str("import type { ColumnsType } from 'antd'\n");
    output_text.push_str("import type * as Types from './types'\n");
    output_text.push_str("import * as utils from './utils'\n\n");

    for api in apis {
        let api_name = api.path.split('/').last().unwrap();
        output_text.push_str(
            &format!(
                "export const {}Columns: ColumnsType = [\n",
                api_name,
                api.model_name
            )
        );
        for data_item in api.response.clone() {
            output_text.push_str(
                &format!(
                    "  {{\n    title: '{}',\n    key: '{}',\n    dataIndex: '{}',\n    {}\n  }},\n",
                    data_item.description,
                    data_item.key,
                    data_item.key,
                    get_column_render(data_item.clone())
                )
            );
        }
        output_text.push_str("]\n");
    }

    return output_text;
}


这里主要就是采用字符串模版的形式,将OpenAPI对象遍历生成ts代码。

生成对应Typescript类型定义

Table Columns的类型使用generate_types()来生成,原理和生成columns一样,采用字符串模版:

/// generator.rs

pub fn generate_types(apis: &mut Vec) -> String {
    let mut output_text = String::new();

    for api in apis {
        let api_name = api.path.split('/').last().unwrap();
        output_text.push_str(
            &format!(
                "export type {} = {{\n",
                Some(api.model_name.clone()).unwrap_or(api_name.to_string())
            )
        );
        for data_item in api.response.clone() {
            output_text.push_str(&format!("  {}: {},\n", data_item.key, data_item.data_type));
        }
        output_text.push_str("}\n\n");
    }

    return output_text;
}


main.rs

然后我们在main.rs中分别调用上面这两个方法即可

/// main.rs

let mut apis = parse_openapi(swagger_json);
    let columns = generator::generate_columns(&mut apis);
    let mut columns_ts = File::create("columns.ts").unwrap();
    write!(columns_ts, "{}", columns).expect("Failed to write to output file");
    let types = generator::generate_types(&mut apis);
    let mut types_ts = File::create("types.ts").unwrap();
    write!(types_ts, "{}", types).expect("Failed to write to output file");


对于columns和types分别生成两个文件,columns.ts和types.ts。

!这里有一点需要注意

当时开发的时候对Rust理解不是很深,起初拿到parse_openapi返回的apis我是直接分别传给generate_columns(apis)和generate_types(apis)的。但编译的时候报错了:

用Rust生成Ant-Design Table Columns | 京东云技术团队,硬核干货,rust,京东云,开发语言,Columns

这对于js很常见的操作竟然在Rust中报错了。原来Rust所谓不依赖运行时垃圾回收而管理变量分配引用的特点就体现在这里。
我就又回去读了遍Rust教程里的“引用和借用”那篇,算是搞懂了。这里实际上是Rust变量所有权、引用和借用的问题。读完了自然你也懂了。

看看效果

安装

cargo install swagger_to


使用

swagger_to columns path/to/swagger.json


会在swagger.json所在同级目录生成三个文件:

columns.tsant-design table columns的定义

types.tscolumns对应的类型定义

utils.tscolumn中render对number类型的字段添加了格式化工具

用Rust生成Ant-Design Table Columns | 京东云技术团队,硬核干货,rust,京东云,开发语言,Columns

Enjoy

作者:京东零售 于弘达

来源:京东云开发者社区文章来源地址https://www.toymoban.com/news/detail-611411.html

到了这里,关于用Rust生成Ant-Design Table Columns | 京东云技术团队的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue2安装ant-design UI报错 ERR! peer vue@“>=3.2.0“ from ant-design-vue@3.2.15

    npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! npm ERR! While resolving: default@0.1.0 npm ERR! Found: vue@2.7.14 npm ERR!   vue@\\\"^2.6.10\\\" from the root project npm ERR! npm ERR! Could not resolve dependency: npm ERR! peer vue@\\\"=3.2.0\\\" from ant-design-vue@3.2.15 npm ERR! node_modules/ant-design-vue npm ERR!   ant-design

    2024年02月01日
    浏览(55)
  • Ant-Design 官方网站总是打不开,那么我们则需要使用以下该官网的镜像地址来打开;

      1、 Ant-Design 官网原地址: https://ant.design/index-cn Ant-Design 官网镜像地址:http://ant-design.gitee.io/index-cn 或者  Ant Design - 一套企业级 UI 设计语言和 React 组件库   2、 Ant-Design-Pro 原地址: https://pro.ant.design/index-cn Ant-Design-Pro 镜像地址:http://ant-design-pro.gitee.io/index-cn   3、

    2024年02月12日
    浏览(48)
  • Ant Design Vue表格(Table)及分页(Pagination )使用

    最近在写一个新项目,UI框架用的是 Ant Design Vue ,因为之前一直用的 Element UI ,没有用过这个组件库,没想到二者区别这么大,因此踩了不少坑,其中就有 Table 和 Pagination ,花了一会时间才弄明白,在此记录并分享一下此次经历。 注意:是 Vue3 项目。 Table 的使用相对比较简

    2024年02月10日
    浏览(43)
  • Ant Design Vue的table组件高度自适应问题

    今天在编写公司项目的时候碰到ant design vue的table组件高度没办法自适应的问题,会出现如下页面情况。  最终尝试的解决方案只能通过监听浏览器窗口变化实现自适应 (1)给表格的srcoll定义一个动态接收参数,方便后面数据增加动态改变滚动高度。  (2)vue3项目中就直接

    2024年02月16日
    浏览(47)
  • Ant Design Vue Table 嵌套子表格的数据刷新方法

    父子组件各自负责,在table中嵌套了子表格后,首次加载表格时,父组件会实例化子组件并传递参数,折叠后再次展开时,只会传递参数,子组件的数据刷新就属于子表格了。如 @@@code template #expandedRowRender=\\\"{ record }\\\" originIndex style= \\\"margin-left: 55px; margin-right: 50px; background-color:

    2024年02月09日
    浏览(36)
  • ant-design-vue表格Table行内新增、编辑、删除

    ant-design-vue表格Table进行单元格内新增、编辑、删除等操作 如图所示:

    2024年02月14日
    浏览(43)
  • [ant-design-vue] table组件列宽拖拽功能

    原有的样式文件没有使用的必要,个人添加的部分样式内容就符合需求了 vue3.x对应的ant-design-vue中的table组件本身支持列宽的拖动了,不需求额外的包的支持,根据Api说明设置resizeColumn即可

    2024年01月23日
    浏览(49)
  • ant-design-vue的table表格行合并和列合并

    场景说明: 1、列合并:需要在表格最后一列进行合并,如图: 思路:相当于是第二列的最后一栏(colSpan )占比5列,第2列后面的4列最后一行(colSpan )占比0。 代码示例 行合并需求如图:将指定列的多行合并成一行 思路:和合并列差不多;第一列的第一行和第二行要合并

    2024年02月16日
    浏览(40)
  • 保姆级教程:Ant Design Vue中 a-table 嵌套子表格

    前端为Ant Design Vue 版本为1.6.2,使用的是vue2 Ant Design Vue中 a-table 嵌套子表格,说的可能稍微墨迹了点,不过重点内容都说的比较详细,利于新人理解,高手可以自取完整代码 下图为官网图,会在每行最前面多一个加号,点击后会展开,看到子表格的数据 子格嵌套从代码层简

    2024年02月01日
    浏览(60)
  • Vue 3 中 Ant Design Vue 如何自定义表格 Table 的表头(列头)内容?

    项目用到的是 Ant Design Vue (2.2.8) 组件库,开发中遇到一个如下图的表格,有些表头文本后面会有一些自定义图标,鼠标移入图标时显示对应的审批时间提示。当前列如果没有审批时间就会隐藏图标,只展示列头文本。 使用 Ant Design Vue 基础的 Table 组件是无法满足这个场景的

    2024年02月16日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包