|
|
package main
|
|
|
|
|
|
import (
|
|
|
"bytes"
|
|
|
"dsSzxy/Utils/CommonUtil"
|
|
|
"dsSzxy/Utils/DbUtil"
|
|
|
"dsSzxy/Utils/FileUtil"
|
|
|
"encoding/json"
|
|
|
"fmt"
|
|
|
"github.com/ghodss/yaml"
|
|
|
"github.com/iancoleman/orderedmap"
|
|
|
"log"
|
|
|
"sort"
|
|
|
"strings"
|
|
|
"text/template"
|
|
|
)
|
|
|
|
|
|
var db = DbUtil.Engine
|
|
|
|
|
|
type Item struct {
|
|
|
Description interface{} `json:"description,omitempty"`
|
|
|
Type string `json:"type"`
|
|
|
Example interface{} `json:"example,omitempty"`
|
|
|
Items interface{} `json:"items,omitempty"`
|
|
|
}
|
|
|
|
|
|
type Properties struct {
|
|
|
Success Item `json:"success"`
|
|
|
Count Item `json:"count"`
|
|
|
List Item `json:"list"`
|
|
|
Message Item `json:"message"`
|
|
|
}
|
|
|
|
|
|
type RootDefinition struct {
|
|
|
Type string `json:"type"`
|
|
|
Properties Properties `json:"properties"`
|
|
|
}
|
|
|
|
|
|
type BigStruct struct {
|
|
|
Definitions interface{} `json:"definitions"`
|
|
|
Host string `json:"host"`
|
|
|
Info interface{} `json:"info"`
|
|
|
Paths interface{} `json:"paths"`
|
|
|
Swagger string `json:"swagger"`
|
|
|
}
|
|
|
|
|
|
type SortStruct struct {
|
|
|
InterfaceName string `json:"interfacename"`
|
|
|
Tags string `json:"tags"`
|
|
|
SortId float64 `json:"sort_id"`
|
|
|
Body interface{} `json:"body"`
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
功能:结构体排序通用办法 按标签排序
|
|
|
*/
|
|
|
type SortTagsStructSlice []SortStruct
|
|
|
|
|
|
func (a SortTagsStructSlice) Len() int {
|
|
|
return len(a)
|
|
|
}
|
|
|
|
|
|
func (a SortTagsStructSlice) Swap(i, j int) {
|
|
|
a[i], a[j] = a[j], a[i]
|
|
|
}
|
|
|
|
|
|
func (a SortTagsStructSlice) Less(i, j int) bool {
|
|
|
if a[i].Tags == a[j].Tags {
|
|
|
return a[i].SortId < a[j].SortId
|
|
|
}
|
|
|
return a[i].Tags < a[j].Tags
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
功能:处理排序字段
|
|
|
作者:黄海
|
|
|
时间:2020-05-28
|
|
|
*/
|
|
|
func DoSort(jsonStr string) string {
|
|
|
//原始map数据,后期修改的依据
|
|
|
var d0 map[string]interface{}
|
|
|
json.Unmarshal([]byte(jsonStr), &d0)
|
|
|
var bigStruct BigStruct
|
|
|
bigStruct.Swagger = d0["swagger"].(string)
|
|
|
bigStruct.Info = d0["info"]
|
|
|
bigStruct.Host = d0["host"].(string)
|
|
|
bigStruct.Definitions = d0["definitions"]
|
|
|
|
|
|
//2、我们关心paths
|
|
|
d1 := d0["paths"].(map[string]interface{})
|
|
|
var arr = make([]SortStruct, 0)
|
|
|
for k, v := range d1 {
|
|
|
//k:接口名称,d2:接口名称后面的内容
|
|
|
d2 := v.(map[string]interface{})
|
|
|
//正确判断方法
|
|
|
_, ok := d2["post"]
|
|
|
var httpType map[string]interface{}
|
|
|
if ok { //post接口
|
|
|
httpType = d2["post"].(map[string]interface{})
|
|
|
} else { //get接口
|
|
|
httpType = d2["get"].(map[string]interface{})
|
|
|
}
|
|
|
//按httpType["Tags"]进行一次排序,然后输出
|
|
|
c1 := httpType["tags"].([]interface{})
|
|
|
|
|
|
var s SortStruct
|
|
|
s.InterfaceName = k
|
|
|
s.Tags = c1[0].(string)
|
|
|
//排序号
|
|
|
if httpType["x-sort"] != nil {
|
|
|
s.SortId = httpType["x-sort"].([]interface{})[0].(float64)
|
|
|
} else {
|
|
|
s.SortId = 9999
|
|
|
}
|
|
|
s.Body = d2
|
|
|
//增加到数组中
|
|
|
arr = append(arr, s)
|
|
|
}
|
|
|
sort.Sort(SortTagsStructSlice(arr))
|
|
|
//有序map集合
|
|
|
o := orderedmap.New()
|
|
|
for i := range arr {
|
|
|
o.Set(arr[i].InterfaceName, arr[i].Body)
|
|
|
}
|
|
|
//进行结构体赋值
|
|
|
bigStruct.Paths = o
|
|
|
//转为json字符串
|
|
|
jsonBytes, _ := json.Marshal(bigStruct)
|
|
|
//美化
|
|
|
var str bytes.Buffer
|
|
|
_ = json.Indent(&str, jsonBytes, "", " ")
|
|
|
return str.String()
|
|
|
}
|
|
|
|
|
|
func Xswagger() {
|
|
|
//1、手动执行一次swag init
|
|
|
CommonUtil.Exec("swag", "init")
|
|
|
//3、解析json文件,找到需要本程序代码扩展的配置接口
|
|
|
jsonBody := CommonUtil.ReadSwaggerJson()
|
|
|
//读取doc目录下的swagger.json
|
|
|
m := jsonBody.(map[string]interface{})
|
|
|
n := m["paths"].(map[string]interface{})
|
|
|
for k, v := range n {
|
|
|
//遍历所有接口
|
|
|
t := v.(map[string]interface{})
|
|
|
httpType := "post"
|
|
|
//非空检查器
|
|
|
if t["get"] != nil {
|
|
|
httpType = "get"
|
|
|
}
|
|
|
//接口
|
|
|
r1 := t[httpType].(map[string]interface{})
|
|
|
//var extendList []interface{}
|
|
|
//if r1["x-extendswaggerfield"] != nil {
|
|
|
// extendList = r1["x-extendswaggerfield"].([]interface{})
|
|
|
//}
|
|
|
//var removeList []interface{}
|
|
|
//if r1["x-removeswaggerfield"] != nil {
|
|
|
// removeList = r1["x-removeswaggerfield"].([]interface{})
|
|
|
//}
|
|
|
//result结构体的名称
|
|
|
k2 := strings.Replace(k[1:], "/", ".", -1)
|
|
|
|
|
|
//对应的表
|
|
|
tableName := r1["x-tablename"]
|
|
|
if tableName == nil {
|
|
|
continue
|
|
|
}
|
|
|
//准备替换
|
|
|
replaceContent := "#/definitions/" + k2
|
|
|
//找到此接口的schema-->ref
|
|
|
c := r1["responses"].(map[string]interface{})
|
|
|
d := c["200"].(map[string]interface{})
|
|
|
d = d["schema"].(map[string]interface{})
|
|
|
d["$ref"] = replaceContent
|
|
|
|
|
|
//添加返回结构体
|
|
|
var prop Properties
|
|
|
var item Item
|
|
|
|
|
|
item.Type = "integer"
|
|
|
item.Description = "一共有多少条"
|
|
|
item.Example = "1"
|
|
|
item.Items = nil
|
|
|
prop.Count = item
|
|
|
|
|
|
item.Type = "boolean"
|
|
|
item.Description = "是否成功"
|
|
|
item.Example = "true"
|
|
|
item.Items = nil
|
|
|
prop.Success = item
|
|
|
|
|
|
/***************************************************************************/
|
|
|
//table := tableName.([]interface{})[0].(string)
|
|
|
|
|
|
////(1)根据数据表表名,获取示例数据
|
|
|
//sql := "select * from " + table + " limit 1"
|
|
|
//sampleDataList, _ := db.SQL(sql).Query().List()
|
|
|
//if len(sampleDataList) == 0 {
|
|
|
// log.Fatalln("数据表" + table + "中手动添些数据吧,要不没法提供示例数据~~~")
|
|
|
//}
|
|
|
//
|
|
|
////(2)添加数据库字段描述
|
|
|
//sql = "select column_name,column_comment,data_type from information_schema.columns where table_name=? and table_schema=?"
|
|
|
//commentList, _ := db.SQL(sql, table, ConfigUtil.MysqlDbName).Query().List()
|
|
|
|
|
|
//item.Type = "array"
|
|
|
//item.Description = "数据列表"
|
|
|
//item.Example = nil
|
|
|
//// 终级[]map
|
|
|
//mProperties := make(map[string]interface{}, 1)
|
|
|
////移除指定的字段
|
|
|
//var arr []string
|
|
|
//for t := 0; t < len(removeList); t++ {
|
|
|
// arr = append(arr, removeList[t].(string))
|
|
|
//}
|
|
|
////手工添加
|
|
|
//arr = append(arr, "last_updated_time")
|
|
|
//
|
|
|
////组装
|
|
|
//for p := 0; p < len(commentList); p++ {
|
|
|
// columnName := commentList[p]["column_name"].(string)
|
|
|
// if CommonUtil.IsContain(arr, columnName) {
|
|
|
// continue
|
|
|
// }
|
|
|
// columnComment := commentList[p]["column_comment"].(string)
|
|
|
// dataType := commentList[p]["data_type"].(string)
|
|
|
// _m2 := make(map[string]interface{}, 1)
|
|
|
// _m2["description"] = columnComment
|
|
|
// if strings.Index(dataType, "char") >= 0 {
|
|
|
// _m2["type"] = "string"
|
|
|
// } else if strings.Index(dataType, "int") >= 0 {
|
|
|
// _m2["type"] = "integer"
|
|
|
// } else if strings.Index(dataType, "float") >= 0 {
|
|
|
// _m2["type"] = "number"
|
|
|
// } else {
|
|
|
// _m2["type"] = dataType
|
|
|
// }
|
|
|
// if len(sampleDataList) == 0 {
|
|
|
// fmt.Println(len(sampleDataList))
|
|
|
// }
|
|
|
// _m2["example"] = sampleDataList[0][columnName]
|
|
|
// mProperties[columnName] = _m2
|
|
|
//}
|
|
|
////添加一些扩展的字段类型说明
|
|
|
//for i := 0; i < len(extendList); i++ {
|
|
|
// var b = extendList[i].(map[string]interface{})
|
|
|
// columnComment := b["column_comment"].(string)
|
|
|
// columnName := b["column_name"].(string)
|
|
|
// sampleData := b["sample_data"].(string)
|
|
|
// _m2 := make(map[string]interface{}, 1)
|
|
|
// _m2["description"] = columnComment
|
|
|
// _m2["example"] = sampleData
|
|
|
// _m2["type"] = "string"
|
|
|
// mProperties[columnName] = _m2
|
|
|
//}
|
|
|
//resultProperties := make(map[string]interface{}, 1)
|
|
|
//resultProperties["properties"] = mProperties
|
|
|
////如果是Get,那么实例的对象而不是数组
|
|
|
//item.Items = resultProperties
|
|
|
//item.Example = nil
|
|
|
//item.Description = nil
|
|
|
//prop.List = item
|
|
|
/***************************************************************************/
|
|
|
////(2)根据手动扩展的列名,获取字段的名称和默认值
|
|
|
//for i := 0; i < len(extendList); i++ {
|
|
|
// var b = extendList[i].(map[string]interface{})
|
|
|
// extendField := b["column_name"].(string)
|
|
|
// extendSample := b["sample_data"].(string)
|
|
|
// for j := 0; j < len(sampleDataList); j++ {
|
|
|
// sampleDataList[j][extendField] = extendSample
|
|
|
// }
|
|
|
//}
|
|
|
//item.Type = "string"
|
|
|
//item.Description = "返回的消息"
|
|
|
//item.Example = "操作成功"
|
|
|
//item.Items = nil
|
|
|
//prop.Message = item
|
|
|
|
|
|
var rootDefinition RootDefinition
|
|
|
rootDefinition.Properties = prop
|
|
|
rootDefinition.Type = "object"
|
|
|
m["definitions"].(map[string]interface{})[k2] = rootDefinition
|
|
|
}
|
|
|
|
|
|
//修改Model.Res为固定值
|
|
|
// c := m["definitions"].(map[string]interface{})
|
|
|
//d := c["Model.Res"].(map[string]interface{})
|
|
|
// j := `{
|
|
|
// "success": {
|
|
|
// "description": "是否成功",
|
|
|
// "type": "boolean",
|
|
|
// "example": "true"
|
|
|
// },
|
|
|
// "message": {
|
|
|
// "description": "返回的消息",
|
|
|
// "type": "string",
|
|
|
// "example": "操作成功"
|
|
|
// }
|
|
|
//}`
|
|
|
//var dat map[string]interface{}
|
|
|
//if err := json.Unmarshal([]byte(j), &dat); err == nil {
|
|
|
// d["properties"] = dat
|
|
|
//}
|
|
|
byteValue, _ := json.Marshal(m)
|
|
|
var str bytes.Buffer
|
|
|
_ = json.Indent(&str, byteValue, "", " ")
|
|
|
//处理排序字段
|
|
|
afterJson := DoSort(str.String())
|
|
|
//回写json文件
|
|
|
FileUtil.WriteFileContent("./docs/swagger.json", afterJson)
|
|
|
//转为yaml
|
|
|
y, err := yaml.JSONToYAML([]byte(afterJson))
|
|
|
if err != nil {
|
|
|
fmt.Printf("err: %v\n", err)
|
|
|
return
|
|
|
}
|
|
|
//回写swagger.yaml文件
|
|
|
FileUtil.WriteFileContent("./docs/swagger.yaml", string(y))
|
|
|
//生成docs.go
|
|
|
//调用模板
|
|
|
filesName := "./docs/docs.go.template"
|
|
|
t, err := template.ParseFiles(filesName)
|
|
|
if err != nil {
|
|
|
log.Fatalln("parse file err:", err)
|
|
|
return
|
|
|
}
|
|
|
buf := new(bytes.Buffer)
|
|
|
var p = map[string]interface{}{
|
|
|
"json": afterJson,
|
|
|
}
|
|
|
if err := t.Execute(buf, p); err != nil {
|
|
|
log.Fatal("There was an error:", err.Error())
|
|
|
}
|
|
|
var content = buf.String()
|
|
|
//写入文件
|
|
|
FileUtil.WriteFileContent("./docs/docs.go", content)
|
|
|
fmt.Println("恭喜,所有文件成功生成!")
|
|
|
}
|
|
|
|
|
|
func main() {
|
|
|
Xswagger()
|
|
|
}
|