7-cloud README
七点一刻低代码插件.
Requirements
1. 添加VScode配置
在VScode的配置文件中,添加以下配置,设置后保存ts代码就会触发插件
"[typescript]": {
"editor.codeActionsOnSave": {
"source.tsSave": true
}
}
2. 本插件前端基于TS,要求TS版本不低于XXX,后端基于Golang的GoFrame框架,要求GoFrame版本最低为V2。
3. 前后端都需要安装qk-library:
前端qk-library的安装方式:
使用的是私有的npm,需要登陆阿里云账号设置权限,具体步骤参考以下链接:
https://packages.aliyun.com/npm/npm-registry/guide
后端qk-library的安装方式:
使用的私有仓库,需要登陆阿里云账号设置权限,具体步骤参考以下链接:
https://help.aliyun.com/document_detail/293638.html
4. 因插件使用了gofmt和goimports命令行,所以需要安装这两个工具
- 到golang中文网下载 https://studygolang.com/dl,下载版本 v1.16.15
- 在环境变量中设置代理的路径 https://goproxy.io/zh/
- 在vscode插件市场中安装go插件,打开任意go文件,按提示下载gotools
- 安装gotools成功后,在终端输入goimports -h, 有帮助文档输出证明安装成功,否则执行 go install golang.org/x/tools/cmd/goimports@lasest
Introduction
该插件是七点一刻内部使用的低代码插件,目前具备根据前端代码,生成后端API,Model和Define文件的基础能力。
本插件基于以下目录结构:
为了方便生成代码,link的目录结构和server基本是保持一致的,文件之间也是一一对应的关系。
```
project
│
│───client
│ │
│ └───link
│ │
│ └───conmon
│ │ │
│ │ └───consts
│ │ │ xxx.const.ts
│ │
│ └───model
│ │ │ xxx.model.ts
│ │
│ └───system
│ │
│ └───x_system
│ │
│ └───define
│ │ │ xxx.define.ts
│ │
│ └───api
│ │ │
│ │ │ xxx.api.ts
│ │
│ └───service
│ │ │
│ │ │ xxx.service.ts
│
└───server
│
└───conmon
│ │
│ └───consts
│ │ xxx.const.go
│
│
└───model
│ │ xxx.model.go
│
└───system
│
└───x_system
│
└───define
│ │ xxx.define.go
│
└───api
│ │
│ │ xxx.api.go
│
└───service
│ │
│ │ xxx.service.go
│
...
...
```
Flow
引入该插件后,前后端的联调流程需要发生改变。
传统的开发流程:
- 后端定义模型,与前端协商好接口
- 后端开发接口,前端开发页面
- 后端生成swagger文档,部署测试服
- 前端根据swagger文档对接接口
- 联调出现问题后,前端反馈给后端修改
基于插件的开发流程:
- 后端在link/model目录中设计好模型
- 后端在link/system目录中划分好系统
- 后端在link/system/xxx/api/xxx.api.ts文件中定义好接口
- 以上几个步骤会同步生成后端代码,后端把服务跑起来,生成swagger文档,检验接口可行性
- 后端把模型和接口设计与前端沟通
- 前端在link/system/xxx/define/xxx.define.ts文件中填充接口字段
- 后端继续负责完成复杂逻辑
Features
1. API:由Ts文件生成Go文件
由于GoFrame框架的API层,目前已经很薄,代码都是大同小异。所以采用声明式代码生成的方式来做。示例代码如下:
import { Api, BaseApi, HttpMethod, ReturnType } from "@base/api";
import { Order } from "@model/order.model";
import { AdminOrderListReq, AdminOrderListRes } from "../define/admin.define";
// @class 父类BaseApi:中包含了默认的配置(后端用)和基础方法(前端用)
// @class AdminOrderApi:的含义是路由分组,约定一个API文件只允许有一个路由分组,也就是只能有一个AdminOrderApi类
// @property tag:接口分组
// @property basePath:路由的路径就设置在属性basePath中,要求/开头
// @property model:代表用到的数据模型,在子类中可以进行重写
// @property method:代表HTTP请求方法,模式是POST
class AdminOrderApi extends BaseApi {
tag = "管理后台订单"
method: HttpMethod = "post"
basePath = "/admin/order"
model?: OrderItem
}
// @class Api:需要实现 Api 抽象类
// @class AdminOrderListApi 的含义是一个具体的API接口,一个路由组可以包含多个接口
// @property tag:接口分组,会覆盖父类的tag
// @property path:前端拼接basePath后作为完整的路由路径,要求/开头,生成的g.Meta后只会包含最后一个路径,且用-分割
// @property summary:接口详细名称
// @properyt mime: 用于生成g.Meta里的mime
// @property return:代表返回值的类型
// RETURN_TYPE_NIL(返回空,默认值)
// RTURN_TYPE_PAGE(分页列表)
// RETURN_TYPE_ARR(数组)
// RETURN_TYPE_OBJ(对象)
// RETURN_TYPE_RAW(不封装code和message)
// RETURN_TYPE_FILE(文件)
// RETURN_TYPE_ZIP(压缩包)
// @property model:重写父类的模型
// @property service:目前只支持 custom, list,get,post,delete,patch 六种,规则说明见下文备注
// @property method:代表HTTP请求方法
// @property req:定义参数的类型
// @property res:定义相应的类型
export class AdminOrderListApi extends AdminOrderApi implements Api {
summary: "列表"
path = "/list"
return: ReturnType = "page"
service: ServiceType = "list"
req!: AdminOrderListReq
res!: AdminOrderListRes
}
特别说明:
api生成后,如需要调用service里的方法,则会自动生成service文件,特别要注意的是,service里方法的命名规范要遵守以下规则
备注:当返回值为NisRes时,不再传递res到service层
var AdminDog = new(adminDog)
type adminDog struct{}
// 规范一:要用指针
// 规范二:以包名的首字母作为自身引用,即s
func (s *adminDog) Get(ctx *qcontext.Context, req *define.DogGetReq, res *define.DogGetRes) error {
return nil
}
path和service会决定后端是否调用service还是直接调用CURD。规则如下:
- 默认情况下,会直接调用service;
- 当path为/list,/get,/post,/delete 或者 /patch 时,默认会调用CURD;
- 如path为/list,/get,/post,/delete 或者 /patch,却想调用自定义service,则设置service = "custom";
- service属性的优先级最高,设置后无视path属性,当设置为list,get,post,delete,patch时会调用CURD,设置为custom时调用自定义service;
编辑好之后,按保存就会自动生成对应的后端API代码
2. Model:由Ts文件生成Go文件;
import { Base } from "./model"
import { Merchant } from "./merchant.model"
import { OrderItem } from "./order_item.model"
import { decimal, uint } from "qk-library/type/base"
import { OrderStatus } from "../common/consts/order.const"
// @type Order 一个类型声明对应一个后端的struct
// @type Base ts中用&号来表示两个类型的联合,相当于golang的组合
export type Order = Base &{
// @gorm comment:定金比例
firstPayPie: decimal // decimal对应golang中的decimal.Decimal,在qk库中引入
// @gorm comment:买家Id
buyerID: uint // uint是golang中的别名,在qk库中引入
// @gorm comment:交货日
deliveryCycle ?:uint // ?代表这是一个指针
// @gorm comment:商家Id
merchantID ?:uint
merchant ?:Merchant // 也可以引用其他模型
// @gorm comment:总价
totalPrice ?:decimal
// @gorm comment:订单状态
orderStatus?: OrderStatus
// @gorm comment:订单项
orderItems: OrderItem[]
}
前端忽略部分类型
对于一些只有前端使用到,或者是比较复杂的类型,难以进行转化的,可以加上@ignore注释,这样就不会生成对应的后端类型
// @ignore
export type SpecialMap = Map<string, Map<uint, string>>
针对类型定义的注释用法
首先从ts类型转成golang类型时,默认是转化为定义,而不是别名。
即 export type Order = Base, 默认是转成 type Order Base,而不是type Order = Base。
如果需要转化为别名,则需要额外加上注释,关于golang中定义和别名的区别,可以参考文章:https://studygolang.com/articles/19144
// @alias
export type Order = Base
针对字段的注释用法,我们主要用注释来表示golang中的tag。
// @gorm comment:定金比例
@gorm 代表了tag中的key,要求// @开头,如果不是以// @开头,则会被认为是普通注释处理
comment:定金比例 代表了tag中的value,要求空格开头
对于多个标签,分开多行写
// @gorm comment:定金比例
// @dc 定金比例
3. Define:由Ts文件生成Go文件;
Define生成的逻辑和Model的逻辑基本一致,只是Define会额外生成一个g.Meta
Define文件保存时,会去对应的api文件中查找路由信息生成。
4. Consts:由Ts文件生成Go文件;
Consts生成的逻辑和Define的逻辑基本一致;
Consts中支持前端的字符串枚举语法,并转化为后端语法:
// 目前只支持字符串枚举
export enum OrderStatus {
created = "待发货",
pendingPickup = "待提货",
pendingDelivery = "待交货",
complete = "已完成",
}
可转化为以下语法:
type OrderStatus string
const (
// ORDER_STATUS_CREATED 待发货
ORDER_STATUS_CREATED OrderStatus = "created"
// ORDER_STATUS_PENDING_PICKUP 待提货
ORDER_STATUS_PENDING_PICKUP OrderStatus = "pendingPickup"
// ORDER_STATUS_PENDING_DELIVERY 待交货
ORDER_STATUS_PENDING_DELIVERY OrderStatus = "pendingDelivery"
// ORDER_STATUS_COMPLETE 已完成
ORDER_STATUS_COMPLETE OrderStatus = "complete"
)
func (c OrderStatus) GetPtr() *OrderStatus {
return &c
}
5. 其他说明:
- 生成的代码最下方会有/* 7-Cloud Separation Line */这一行注释,这行注释下方后端可以写一些自定义的代码而不会被生成的代码覆盖
- 保存link下的api,model和define文件时会生成对应的go代码,如果不成功,在vscode右下角会有提示,请检查代码或者反馈给开发者
- 此插件启动成功后,在ts文件的选项卡栏,会有一个预览的小图标,点击图标可跳转到对应golang文件
- 此插件启动成功后,在golang文件的选项卡栏,会有一个预览的小图标,点击图标可跳转到对应ts源文件
- 一般我们约定,左侧选项组是主编辑区(前端查看ts代码,后端查看go代码),右侧选项组作为预览用,只放一个预览用的文件
Tip: Many popular extensions utilize animations. This is an excellent way to show off your extension! We recommend short, focused animations that are easy to follow.
Snippets列表
- baseApi
- apiClass
插件配置
This extension config the following settings:
7-cloud.path
: 按照项目名配置各项目的前端后端路径
7-cloud.defaultpath
: 当项目名没有匹配到的时候,使用这个默认设置
Known Issues
Calling out known issues can help limit users opening duplicate issues against your extension.
Enjoy!