You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

344 lines
9.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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()
}