swagger controller
This commit is contained in:
		| @@ -1,4 +1,5 @@ | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Microsoft.OpenApi.Models; | ||||
| using Swashbuckle.AspNetCore.SwaggerGen; | ||||
| using System.Text; | ||||
|  | ||||
| @@ -18,7 +19,9 @@ public class SwaggerController : ControllerBase | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     [Route("get/{version}")] | ||||
|     [Produces("text/html")] | ||||
|     [HttpGet] | ||||
|     [ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)] | ||||
|     public ActionResult GetApi(string version) | ||||
|     { | ||||
|         var model = generator.GetSwagger(version); | ||||
| @@ -29,99 +32,150 @@ public class SwaggerController : ControllerBase | ||||
|     <meta charset=""UTF-8""> | ||||
|     <title>Flower Story - API 接口文档</title> | ||||
|     <style type=""text/css""> | ||||
|         body {{ background-color: rgb(243,244,246) }} | ||||
|         pre {{ | ||||
|             padding: 1rem; | ||||
|             background-color: rgb(107 114 128); | ||||
|             color: #fff; | ||||
|         }} | ||||
|         table, | ||||
|         table td, | ||||
|         table th {{ | ||||
|             margin: 0; | ||||
|             padding: 0; | ||||
|             border: 1px solid #000; | ||||
|             border: 1px solid #e5e7eb; | ||||
|             border-collapse: collapse; | ||||
|         }} | ||||
|  | ||||
|         table {{ | ||||
|             table-layout: fixed; | ||||
|             word-break: break-all; | ||||
|         }} | ||||
|  | ||||
|         tr {{ | ||||
|             height: 20px; | ||||
|             font-size: 12px; | ||||
|         }} | ||||
|         td {{ padding: .75rem }} | ||||
|  | ||||
|         .red {{ color: #f00 }} | ||||
|         .box {{ | ||||
|             background-color: #fff; | ||||
|             box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.04) 0px 4px 6px -1px; | ||||
|             padding: .75rem; | ||||
|             border-radius: .375rem; | ||||
|             margin-bottom: 2.5rem; | ||||
|         }} | ||||
|         .method-get {{ color: #61affe }} | ||||
|         .method-delete {{ color: #f93e3e }} | ||||
|         .method-post {{ color: #49cc90 }} | ||||
|         .method-put {{ color: #fca130 }} | ||||
|         .header {{ color: rbg(107 114 128) }} | ||||
|         .wrapper {{ | ||||
|             width: 1000px; | ||||
|             margin: 0 auto; | ||||
|         }} | ||||
|  | ||||
|         .operation {{ | ||||
|             width: 100%; | ||||
|         }} | ||||
|  | ||||
|         .bg {{ | ||||
|             background-color: rgb(84, 127, 177); | ||||
|         }} | ||||
|         .operation {{ width: 100% }} | ||||
|         .bg {{ background-color: rgb(84, 127, 177) }} | ||||
|     </style> | ||||
| </head> | ||||
| <body> | ||||
|     <div class=""wrapper""> | ||||
|         <h1>{model.Info.Title}</h1> | ||||
|         <h3>接口文档 {model.Info.Version}</h3> | ||||
|         <p>{model.Info.Description}</p>"); | ||||
|         <div class=""box""> | ||||
|             <p>{model.Info.Description}</p> | ||||
|         </div>"); | ||||
|         foreach (var tag in model.Tags) | ||||
|         { | ||||
|             if (tag == null) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|             builder.Append($@" | ||||
|         <h3>{tag.Description}</h3> | ||||
|         <div class=""box"">"); | ||||
|             foreach (var item in model.Paths) | ||||
|             { | ||||
|                 if (item.Value.Operations != null) | ||||
|                 { | ||||
|                     foreach (var operation in item.Value.Operations) | ||||
|                     { | ||||
|                     if (string.IsNullOrEmpty(operation.Value.Summary)) | ||||
|                         if (!operation.Value.Tags.Any(t => t.Name == tag.Name)) | ||||
|                         { | ||||
|                             continue; | ||||
|                         } | ||||
|                         var method = operation.Key.ToString(); | ||||
|                         builder.Append($@" | ||||
|         <h3>{operation.Value.Summary}</h3> | ||||
|         <table class=""operation""> | ||||
|             <tr class=""bg""><td colspan=""5""></td></tr> | ||||
|             <tr> | ||||
|                 <td>URL</td> | ||||
|                 <td colspan=""4"">{item.Key}</td> | ||||
|             </tr> | ||||
|             <tr> | ||||
|                 <td>请求方式</td> | ||||
|                 <td colspan=""4"">{operation.Key}</td> | ||||
|             </tr>"); | ||||
|             <h4>{operation.Value.Summary}</h4> | ||||
|             <pre><span class=""method-{method.ToLower()}"">{method.ToUpper()}</span> {item.Key}</pre>"); | ||||
|                         if (operation.Value.Parameters?.Count > 0) | ||||
|                         { | ||||
|                             builder.Append(@" | ||||
|             <tr class=""bg""> | ||||
|                 <td>参数</td> | ||||
|                 <td>参数类型</td> | ||||
|                 <td>是否必须</td> | ||||
|                 <td colspan=""2"">说明</td> | ||||
|             </tr>"); | ||||
|             <p>请求参数</p> | ||||
|             <table class=""operation""> | ||||
|                 <tr class=""header""><td>参数</td><td>位置</td><td>类型</td><td>说明</td></tr>"); | ||||
|                             foreach (var param in operation.Value.Parameters) | ||||
|                             { | ||||
|                                 var required = param.Required ? "<span class=\"red\">*</span>" : string.Empty; | ||||
|                                 builder.Append($@" | ||||
|                 <tr> | ||||
|                 <td>{param.Name}</td> | ||||
|                     <td>{required}{param.Name}</td> | ||||
|                     <td>{param.In}</td> | ||||
|                 <td>{param.Required}</td> | ||||
|                 <td colspan=""2"">{param.Description}</td> | ||||
|                     <td>{param.Schema.Type}</td> | ||||
|                     <td>{param.Description}</td> | ||||
|                 </tr>"); | ||||
|                             } | ||||
|                     } | ||||
|                     if (operation.Value.Responses?.Count > 0) | ||||
|                     { | ||||
|                             builder.Append(@" | ||||
|             <tr class=""bg""> | ||||
|                 <td>状态码</td> | ||||
|                 <td colspan=""4"">说明</td> | ||||
|             </tr>"); | ||||
|                         foreach (var response in operation.Value.Responses) | ||||
|             </table>"); | ||||
|                         } | ||||
|                         if (operation.Value.RequestBody?.Content != null) | ||||
|                         { | ||||
|                             foreach (var content in operation.Value.RequestBody.Content) | ||||
|                             { | ||||
|                                 builder.Append($@" | ||||
|             <p>请求实体 ({content.Key})</p> | ||||
|             <table class=""operation""> | ||||
|                 <tr class=""header""><td>字段</td><td>类型</td><td>说明</td></tr>"); | ||||
|                                 if (content.Value.Schema.Type == "array") | ||||
|                                 { | ||||
|                                     builder.Append($@" | ||||
|                 <tr> | ||||
|                 <td>{response.Key}</td> | ||||
|                 <td colspan=""4"">{response.Value.Description}</td> | ||||
|                     <td>.</td> | ||||
|                     <td>{content.Value.Schema.Items.Type}[]</td> | ||||
|                     <td>{operation.Value.RequestBody.Description}</td> | ||||
|                 </tr>"); | ||||
|                                 } | ||||
|                                 else | ||||
|                                 { | ||||
|                                     IDictionary<string, OpenApiSchema> properties; | ||||
|                                     if (content.Value.Schema.Reference != null && model.Components.Schemas.TryGetValue(content.Value.Schema.Reference.Id, out var schema)) | ||||
|                                     { | ||||
|                                         properties = schema.Properties; | ||||
|                                     } | ||||
|                                     else | ||||
|                                     { | ||||
|                                         properties = content.Value.Schema.Properties; | ||||
|                                     } | ||||
|                                     foreach (var prop in properties) | ||||
|                                     { | ||||
|                                         var required = content.Value.Schema.Required.Contains(prop.Key) ? "<span class=\"red\">*</span>" : string.Empty; | ||||
|                                         var type = prop.Value.Type; | ||||
|                                         if (type == "string" && prop.Value.Format == "binary") | ||||
|                                         { | ||||
|                                             type = "file"; | ||||
|                                         } | ||||
|                                         else if (type == "array") | ||||
|                                         { | ||||
|                                             type = prop.Value.Items.Type; | ||||
|                                             if (type == "string" && prop.Value.Items.Format == "binary") | ||||
|                                             { | ||||
|                                                 type = "file"; | ||||
|                                             } | ||||
|                                             type += "[]"; | ||||
|                                         } | ||||
|                                         builder.Append($@" | ||||
|                 <tr> | ||||
|                     <td>{required}{prop.Key}</td> | ||||
|                     <td>{type}</td> | ||||
|                     <td>{prop.Value.Description}</td> | ||||
|                 </tr>"); | ||||
|                                     } | ||||
|                                 } | ||||
| @@ -129,6 +183,94 @@ public class SwaggerController : ControllerBase | ||||
|             </table>"); | ||||
|                             } | ||||
|                         } | ||||
|                         if (operation.Value.Responses?.Count > 0) | ||||
|                         { | ||||
|                             builder.Append(@" | ||||
|             <p>响应 HTTP 状态</p> | ||||
|             <table class=""operation""> | ||||
|                 <tr class=""header""><td>状态码</td><td>说明</td></tr>"); | ||||
|                             foreach (var response in operation.Value.Responses) | ||||
|                             { | ||||
|                                 builder.Append($@" | ||||
|                 <tr> | ||||
|                     <td>{response.Key}</td> | ||||
|                     <td>{response.Value.Description}</td> | ||||
|                 </tr>"); | ||||
|                                 if (response.Key == "200") | ||||
|                                 { | ||||
|                                     foreach (var content in response.Value.Content) | ||||
|                                     { | ||||
|                                         builder.Append($@" | ||||
|                 <tr> | ||||
|                     <td colspan=""2""> | ||||
|                         <p>{content.Key}</p> | ||||
|                         <table class=""operation""> | ||||
|                             <tr><td>字段</td><td>类型</td><td>说明</td></tr>"); | ||||
|                                         OpenApiSchema schema; | ||||
|                                         if (content.Value.Schema.Type == "array") | ||||
|                                         { | ||||
|                                             schema = content.Value.Schema.Items; | ||||
|                                             builder.Append($@" | ||||
|                             <tr><td>.</td><td>{schema.Reference?.Id ?? schema.Type}[]</td><td></td></tr>"); | ||||
|                                         } | ||||
|                                         else | ||||
|                                         { | ||||
|                                             schema = content.Value.Schema; | ||||
|                                         } | ||||
|                                         if (schema.Reference != null && model.Components.Schemas.TryGetValue(schema.Reference.Id, out var s)) | ||||
|                                         { | ||||
|                                             schema = s; | ||||
|                                         } | ||||
|                                         if (schema.Properties.Count > 0) | ||||
|                                         { | ||||
|                                             foreach (var p in schema.Properties) | ||||
|                                             { | ||||
|                                                 bool isArray = p.Value.Type == "array"; | ||||
|                                                 string type = isArray ? $"{p.Value.Items.Reference?.Id ?? p.Value.Items.Type}[]" : p.Value.Type; | ||||
|                                                 builder.Append($@" | ||||
|                             <tr> | ||||
|                                 <td>{p.Key}</td> | ||||
|                                 <td>{type}</td> | ||||
|                                 <td>{p.Value.Description}</td> | ||||
|                             </tr>"); | ||||
|                                                 if (isArray && p.Value.Items.Reference != null && model.Components.Schemas.TryGetValue(p.Value.Items.Reference.Id, out s)) | ||||
|                                                 { | ||||
|                                                     foreach (var p2 in s.Properties) | ||||
|                                                     { | ||||
|                                                         builder.Append($@" | ||||
|                             <tr> | ||||
|                                 <td>  {p2.Key}</td> | ||||
|                                 <td>{p2.Value.Type}</td> | ||||
|                                 <td>{p2.Value.Description}</td> | ||||
|                             </tr>"); | ||||
|                                                     } | ||||
|                                                 } | ||||
|                                             } | ||||
|                                         } | ||||
|                                         else | ||||
|                                         { | ||||
|                                             builder.Append($@" | ||||
|                             <tr> | ||||
|                                 <td>.</td> | ||||
|                                 <td>{schema.Type}</td> | ||||
|                                 <td></td> | ||||
|                             </tr>"); | ||||
|                                         } | ||||
|                                         builder.Append(@" | ||||
|                         </table> | ||||
|                     </td> | ||||
|                 </tr>"); | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
|                             builder.Append(@" | ||||
|             </table>"); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             builder.Append(@" | ||||
|         </div>"); | ||||
|         } | ||||
|         builder.Append(@" | ||||
|     </div> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user