vue学习记录 8

问了一下大佬侧边栏内容在哪设置的,他说项目里写了一个自动生成接口的脚本,这些接口构成目录。ಠ_ಠ

不在src,在src同级目录generate下。generate>index.js,自动生成后的各个js文件会显示在generate>config.js内。如果要另外多加接口,除了改脚本配置外,还需要 npm run swagger 。各种run指令部署在src同级目录下的package.json下“scripts”:

1 "scripts": {
2   "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
3   "start": "npm run dev",
4   "build": "node build/build.js",
5   "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
6   "swagger": "node generate/index.js"
7 },


generate>index.js
  1 const fs = require("fs");
  2 const path = require("path");
  3 const http = require("http");
  4 const srcFolder = "/src";
  5 const config = require("./config");
  6 
  7 // 自动生成接口
  8 config.urls.forEach(url => {
  9   main(url);
 10 });
 11 
 12 function mkdirsSync(dirname) {
 13   if (fs.existsSync(dirname)) {
 14     return true;
 15   } else {
 16     if (mkdirsSync(path.dirname(dirname))) {
 17       fs.mkdirSync(dirname);
 18       return true;
 19     }
 20   }
 21 }
 22 function getPath(pathUrl) {
 23   return path.resolve(__dirname, pathUrl);
 24 }
 25 function generateTemplate(arr) {
 26   return 'import httpReq from "@/utils/request";\n';
 27 }
 28 
 29 function generateFunc(name, summary, type = "post") {
 30   const arr = name.slice(1).split("/");
 31   const fun = arr[arr.length - 1];
 32   return `
 33 // ${summary || ""}
 34 export function ${fun}(params){
 35   let url = "${name}";
 36   return httpReq(url, "${type}", params)
 37 }\n`;
 38 }
 39 
 40 function httpgetJson(url) {
 41   return new Promise((resolve, reject) => {
 42     http
 43       .get(url, res => {
 44         console.log("res", res);
 45         const { statusCode } = res;
 46         const contentType = res.headers["content-type"];
 47 
 48         let error;
 49         if (statusCode !== 200) {
 50           error = new Error("请求失败。\n" + `状态码: ${statusCode}`);
 51         } else if (!/^application\/json/.test(contentType)) {
 52           error = new Error(
 53             "无效的 content-type.\n" +
 54               `期望 application/json 但获取的是 ${contentType}`
 55           );
 56         }
 57         if (error) {
 58           console.error(error.message);
 59           // 消耗响应数据以释放内存
 60           res.resume();
 61           return;
 62         }
 63 
 64         res.setEncoding("utf8");
 65         let rawData = "";
 66         res.on("data", chunk => {
 67           rawData += chunk;
 68         });
 69         res.on("end", () => {
 70           try {
 71             const parsedData = JSON.parse(rawData);
 72             resolve(parsedData);
 73           } catch (e) {
 74             reject(`错误: ${e.message}`);
 75           }
 76         });
 77       })
 78       .on("error", e => {
 79         reject(`错误: ${e.message}`);
 80       });
 81   });
 82 }
 83 
 84 async function main(url) {
 85   let mfolder = url.split("/")[3];
 86   console.log("获取远程json文件中...");
 87   const { paths } = await httpgetJson(url);
 88   console.log("获取成功正在生成api文件");
 89   const obj = {};
 90   for (const name in paths) {
 91     const path = paths[name];
 92 
 93     let folder = "";
 94     if (path.post) {
 95       const tag = path.post.tags[0];
 96       if (!tag) continue;
 97       const urlArray = name.slice(1).split("/");
 98       if (name.slice(1).split("/").length === 4) {
 99         folder = urlArray[1];
100       } else {
101         if (name.slice(1).split("/")[0] !== tag) continue;
102       }
103       if (obj[path.post.tags[0]]) {
104         obj[path.post.tags[0]].push({
105           summary: path.post.summary,
106           tag,
107           name,
108           type: "post",
109           folder: folder + "/" + mfolder
110         });
111       } else {
112         obj[path.post.tags[0]] = [
113           {
114             summary: path.post.summary,
115             tag,
116             name,
117             type: "post",
118             folder: folder + "/" + mfolder
119           }
120         ];
121       }
122     } else if (path.get) {
123       const tag = path.get.tags[0];
124       console.log(tag);
125       if (!tag) continue;
126       const urlArray = name.slice(1).split("/");
127       if (name.slice(1).split("/").length === 4) {
128         folder = urlArray[1];
129       } else {
130         if (name.slice(1).split("/")[0] !== tag) continue;
131       }
132       if (obj[path.get.tags[0]]) {
133         obj[path.get.tags[0]].push({
134           summary: path.get.summary,
135           tag,
136           name,
137           type: "get",
138           folder: folder + "/" + mfolder
139         });
140       } else {
141         obj[path.get.tags[0]] = [
142           {
143             summary: path.get.summary,
144             tag,
145             name,
146             type: "get",
147             folder: folder + "/" + mfolder
148           }
149         ];
150       }
151     }
152   }
153   for (const tagName in obj) {
154     let jsString = "";
155     const requestTypes = [];
156     let folder = "";
157     for (const item of obj[tagName]) {
158       const requestType = requestTypes.filter(o => o === item.type);
159       if (requestType.length === 0) requestTypes.push(item.type);
160       jsString += generateFunc(item.name, item.summary, item.type);
161       folder = item.folder;
162     }
163     jsString = generateTemplate(requestTypes) + jsString;
164     mkdirsSync(getPath(`..${srcFolder}/api/${folder}`));
165     fs.writeFileSync(
166       getPath(`..${srcFolder}/api/${folder}/${tagName}.js`),
167       jsString
168     );
169   }
170   console.log("生成完毕");
171 }
generate/index.js
index.js前五行:
1
const fs = require("fs"); 2 const path = require("path"); 3 const http = require("http"); 4 const srcFolder = "/src"; 5 const config = require("./config");

参考网址 https://blog.csdn.net/qq_30258495/article/details/125938589 

require用于引入模块,前三行是向服务器请求页面的必要模块引入

readFile(path[,option],callback(err,data));  //fs模块:读取文件
writeFile(path,data[,option],callback(err)); //fs模块:写入覆盖文件
__dirname                                  //path模块,文件当前所处目录
path.join(__dirname , 'xx/x/x' , 'x/x/x');//path模块:拼接路径
path.basename(url);                       //path模块:获取路径中的文件名
path.extname();                           //path模块:获取路径的扩展名
http.createServer();                          //http模块:创建服务器实例
server.on('事件名',callback(request,response));//http模块:为服务器绑定事件
server.listen(端口号,callback());              //http模块:监听端口

第五行引入的是utils.js模块,参考网址 https://blog.csdn.net/baidu_36611723/article/details/82252658 


 

1 config.urls.forEach(url => {
2   main(url);
3 });

这个要和函数main(url)一起看,main内另外嵌自建函数httpgetJson(url)。搜索

1 const requestType = requestTypes.filter(o => o === item.type);
2 if (requestType.length === 0) requestTypes.push(item.type);
3 jsString += generateFunc(item.name, item.summary, item.type);
4 folder = item.folder;

的时候发现swagger脚本教程:

参考网址 https://blog.csdn.net/weixin_39695241/article/details/111534917 

内容有点简略,可能是搬运?另外搜了一下

参考网址 https://blog.csdn.net/jsrgckf/article/details/128803251 这个给了详细的样例,不过和当前项目的有出入,可以作为学习参考。

参考网址 https://www.cnblogs.com/hmit/p/11363412.html 个人推荐看这个,有更详细的swagger使用指导。

和swagger教程有点出入,大佬设定swagger管道的位置在项目XXX.Swagger > SwaggerCollectionExtensions;而网上的教程有点老,基本部署在startup.cs。


 

项目后端SwaggerCollectionExtensions:

1 using Microsoft.AspNetCore.Builder;
2 using Microsoft.Extensions.DependencyInjection;
3 using Microsoft.Extensions.PlatformAbstractions;
4 using Microsoft.OpenApi.Models;
5 using Swashbuckle.AspNetCore.SwaggerUI;
using

namespace XXX.Swagger{

    public static class SwaggerCollectionExtensions{

 1 /// <summary>
 2 /// 注入自定义的swagger服务
 3 /// </summary>
 4 /// <param name="services"></param>
 5 /// <param name="apiInfo"></param>
 6 /// <returns></returns>
 7 public static IServiceCollection AddCustomSwagger(this IServiceCollection services, IApiInfo? apiInfo){
 8   if (apiInfo != null){
 9     services.AddSwaggerGen(options =>{
10       options.CustomSchemaIds(c => c.FullName);
11       //遍历GroupVersion所有枚举值生成接口文档
12       //Skip(1)是因为Enum第一个FieldInfo是内置的一个Int值
13       typeof(GroupVersion).GetFields().Skip(1).ToList().ForEach(f =>{
14         //获取枚举值上的特性
15         var info = f.GetCustomAttributes(typeof(GroupInfoAttribute), false).OfType<GroupInfoAttribute>().FirstOrDefault();
16         options.SwaggerDoc(f.Name.ToLower(), new OpenApiInfo{
17           Title = info?.Title,
18           Version = info?.Version ?? apiInfo.Version,
19           Description = info?.Description
20         });
21       });
22       //判断接口归于哪个分组
23       options.DocInclusionPredicate((docName, apiDescription) =>{
24         return docName == apiInfo?.ApiName ? true : apiDescription.GroupName == docName;
25       });
26 
27       var basePath = PlatformServices.Default.Application.ApplicationBasePath;
28       var xmlpath = Path.Combine(basePath, "XXX.Api.xml");
29       if (File.Exists(xmlpath)){
30         options.IncludeXmlComments(xmlpath, includeControllerXmlComments: true);
31       }
32       var modelPath = Path.Combine(basePath, "XXX.DTO.xml");
33       if (File.Exists(modelPath)){
34         options.IncludeXmlComments(modelPath);
35       }
36       var corePath = Path.Combine(basePath, "XXX.Core.xml");
37       if (File.Exists(corePath)){
38         options.IncludeXmlComments(corePath);
39       }
40       //TOKEN
41       options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme {
42         Description = "在下框中输入请求头中需要添加Jwt授权Token:Bearer Token",
43         Name = "Authorization",
44         In = ParameterLocation.Header,
45         Scheme = "Bearer",
46         Type = SecuritySchemeType.ApiKey,
47         BearerFormat = "JWT"
48       });
49       //添加安全要求
50       options.AddSecurityRequirement(new OpenApiSecurityRequirement {
51         new OpenApiSecurityScheme {
52           Reference = new OpenApiReference {
53             Type = ReferenceType.SecurityScheme,
54             Id = "Bearer"
55           }
56         },
57         new List<string>()
58       });
59     });
60   }
61   return services;
62 }
AddCustomSwagger
 1 /// <summary>
 2 /// 使用自定义 Swagger
 3 /// </summary>
 4 /// <param name="app"></param>
 5 /// <param name="apiInfo"></param>
 6 /// <returns></returns>
 7 public static IApplicationBuilder UseCustomSwagger(this IApplicationBuilder app, IApiInfo apiInfo) {
 8   app.UseSwagger(c => {
 9     c.RouteTemplate = "/{documentName}/{version}/swagger.json";
10   });
11   app.UseSwaggerUI(c => {
12   //遍历GroupVersion所有枚举值生成接口文档,Skip(1)是因为Enum第一个FieldInfo是内置的一个Int值
13     typeof(GroupVersion).GetFields().Skip(1).ToList().ForEach(f => {
14       //获取枚举值上的特性
15       var info = f.GetCustomAttributes(typeof(GroupInfoAttribute), false).OfType<GroupInfoAttribute>().FirstOrDefault();
16       if (info != null) {
17 c.SwaggerEndpoint($"/{f.Name.ToLower()}/{info.Version}/swagger.json",  $"{info.Title} {info.Version}");
18      }
19     });
20     c.DocumentTitle = apiInfo.ApiName + "接口文档";
21    //c.SwaggerEndpoint($"/{apiInfo.ApiName}/{apiInfo.Version}/swagger.json", $"{apiInfo.Title} {apiInfo.Version}");
22     //SWAGGER UI折叠
23     c.DocExpansion(DocExpansion.None);
24     //不显示model
25     c.DefaultModelExpandDepth(-1);
26   });
27   return app;
28 }
UseCustomSwagger

    }

}


 

查了一堆资料

好极了,要开始学后端咯(满脸写着开心

 

posted @ 2023-06-26 13:14  yyn工作号  阅读(27)  评论(0)    收藏  举报