vue 自動(dòng)生成swagger接口請(qǐng)求文件的方法
前端: vue-element-admin
后端: .net core (6.0)
找了很多自動(dòng)生成的代碼的,感覺不太行,可能是我不太懂。所以自己根據(jù)swagger.json去生成了js請(qǐng)求文件。
后端很簡(jiǎn)單,就不說(shuō)了,只要能訪問到swagger的地址就可以,主要是前端。這個(gè)生成的比較簡(jiǎn)單,你們可以根據(jù)自己的需求修改生成文件js里的代碼。前端代碼也參考了網(wǎng)上的一些內(nèi)容。
1.在項(xiàng)目目錄下新建genSwagger文件夾,然后新建autoGen.js文件

2.autoGen.js文件內(nèi)容如下,里面的內(nèi)容大部分有注釋,可以根據(jù)自己的項(xiàng)目情況做些修改
const fs = require('fs')
const path = require('path')
let apiData = {} // 訪問swagger.json的數(shù)據(jù)
const http = require('http')
const apiUrl = 'http://localhost:5227/swagger/v1/swagger.json' // swagger.json的地址,這里是本地的,可以替換成你的地址,有個(gè)問題是目前只能是http,https的不行,https會(huì)報(bào)一個(gè)證書錯(cuò)誤
// 生成api文件的目錄
function mkdirsSync(dirname) {
if (fs.existsSync(dirname)) {
return true
} else {
if (mkdirsSync(path.dirname(dirname))) {
fs.mkdirSync(dirname)
return true
}
}
}
function getPath(pathUrl) {
return path.resolve(__dirname, pathUrl)
}
let dataList = [] // 真正要處理的數(shù)據(jù)
// 將swagger.json中的數(shù)據(jù)轉(zhuǎn)換成我們需要的數(shù)據(jù)
function getDataList() {
// 遍歷apiData.paths
for (const key in apiData.paths) {
let routeData = {}
routeData.api = key
console.log('path================ ' + key)
// 遍歷apiData.paths[key]
for (let key2 in apiData.paths[key]) {
routeData.method = key2
console.log('methods============== ' + key2)
let tag = apiData.paths[key][key2].tags[0]
console.log('tag=====' + tag)
routeData.controller = tag
let params = apiData.paths[key][key2].parameters
if (params) {
routeData.bodyType = 'query'
routeData.params = apiData.paths[key][key2].parameters
} else {
routeData.params = []
if (key2 === 'post' && key2 !== 'get') {
routeData.bodyType = 'body'
let requestBody = apiData.paths[key][key2].requestBody
if (requestBody) {
let content = requestBody.content
if (content) {
let applicationJson = content['application/json']
if (applicationJson) {
let schema = applicationJson.schema
if (schema) {
let properties = schema.$ref
if (properties) {
let ref = properties.split('/')
let refName = ref[ref.length - 1]
let refData = apiData.components.schemas[refName]
if (refData) {
let refProperties = refData.properties
if (refProperties) {
for (let key3 in refProperties) {
let param = {}
param.name = key3
param.in = 'body'
param.required = true
param.schema = refProperties[key3]
routeData.params.push(param)
}
}
}
}
}
}
}
}
}
}
//遍歷apiData.paths[key][key2]
for (let key3 in apiData.paths[key][key2]) {
// console.log('tags===========' + key3)
if (key2 === 'get') {
//routeData.params = apiData.paths[key][key2][key3].parameters
}
//routeData.other = apiData.paths[key][key2][key3]
console.log(apiData.paths[key][key2][key3])
}
console.log('xxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
}
dataList.push(routeData)
}
console.log(dataList)
}
// 獲取遠(yuǎn)程swagger.json的數(shù)據(jù)
function httpGetJson(url) {
return new Promise((resolve, reject) => {
http.get(url, (res) => {
const { statusCode } = res
const contentType = res.headers['content-type']
let error
if (statusCode !== 200) {
error = new Error('請(qǐng)求失敗。\n' + `狀態(tài)碼: ${statusCode}`)
} else if (!/^application\/json/.test(contentType)) {
error = new Error('無(wú)效的 content-type.\n' + `期望 application/json 但獲取的是 ${contentType}`)
}
if (error) {
console.log('error')
// 消耗響應(yīng)數(shù)據(jù)以釋放內(nèi)存
console.error(error.message)
res.resume()
return
}
res.setEncoding('utf8')
let rawData = ''
res.on('data', (chunk) => {
rawData += chunk
})
res.on('end', () => {
try {
const parsedData = JSON.parse(rawData)
resolve(parsedData)
} catch (e) {
reject(`錯(cuò)誤: ${e.message}`)
}
})
}).on('error', (e) => {
reject(`錯(cuò)誤: ${e.message}`)
})
})
}
// 生成http請(qǐng)求js文件
async function createHttpJsFile() {
console.log('start')
apiData = await httpGetJson(apiUrl)
getDataList()
console.log(dataList)
if (dataList.length === 0) {
console.log('請(qǐng)先點(diǎn)擊getUsers按鈕')
return
}
let httpJs = ''
if (dataList.length > 0) {
const dirPath = '/src/api-service'
// dataList根據(jù)controller去重
const controllerList = []
for (let i = 0; i < dataList.length; i++) {
const routeData = dataList[i]
const controller = routeData.controller
if (controllerList.indexOf(controller) === -1) {
controllerList.push(controller)
}
}
// 生成http請(qǐng)求js文件
for (let i = 0; i < controllerList.length; i++) {
httpJs += `import { httpGet, httpPost } from '@/utils/http'\n`
const fileName = controllerList[i]
// 查找dataList里與 controllerList[i]相同的數(shù)據(jù) (同一個(gè)controller的api放在一起)
const controllerDataList = dataList.filter(item => item.controller === controllerList[i])
console.log(controllerDataList)
for (const data of controllerDataList) {
const api = data.api // /api/user/getUserList
// 取出api中最后一個(gè)斜杠后面的內(nèi)容
const apiName = api.substring(api.lastIndexOf('/') + 1)
if (data.method === 'get') {
httpJs += `export async function ${apiName}(`
if (data.params && data.params.length > 0) {
for (let i = 0; i < data.params.length; i++) {
const param = data.params[i]
if (i === 0) {
httpJs += `${param.name}`
} else {
httpJs += `,${param.name}`
}
}
}
httpJs += `) {\n`
httpJs += ` return await httpGet('${data.api}'`
if (data.params && data.params.length > 0) {
httpJs += `,{\n`
for (let i = 0; i < data.params.length; i++) {
const param = data.params[i]
if (i === 0) {
httpJs += ` ${param.name}:${param.name}`
} else {
httpJs += ` ,${param.name}:${param.name}`
}
}
httpJs += ` })\n`
httpJs += `}\n`
} else {
httpJs += `)}\n`
}
} else if (data.method === 'post') {
// post后面帶參數(shù)
if (data.params.length > 0 && data.bodyType === 'query') {
httpJs += 'export async function ' + apiName + '('
for (let i = 0; i < data.params.length; i++) {
const param = data.params[i]
if (i === 0) {
httpJs += `${param.name}`
} else {
httpJs += `,${param.name}`
}
}
httpJs += `) {\n`
httpJs += ` return await httpPost('${data.api}`
if (data.params && data.params.length > 0) {
for (let i = 0; i < data.params.length; i++) {
const param = data.params[i]
if (i === 0) {
httpJs += `?${param.name}='+${param.name}`
} else {
httpJs += `+'&${param.name}='+${param.name}`
}
}
httpJs += `)}\n`
} else {
httpJs += `)}\n`
}
} else {
httpJs += 'export async function ' + apiName + '(data) {\n'
httpJs += ' return await httpPost(\'' + data.api + '\',data)\n'
httpJs += '}\n'
}
}
}
// 生成js文件
mkdirsSync(getPath(`..${dirPath}/`))
fs.writeFileSync(getPath(`..${dirPath}/${fileName}.js`), httpJs)
httpJs = ''
}
console.log(httpJs)
}
}
// 調(diào)用一下
createHttpJsFile()
3.在package.json下面的scripts節(jié)點(diǎn)下新增內(nèi)容:"swagger": "node genSwagger/autoGen.js"

4.在控制臺(tái)運(yùn)行 npm run swagger

5.運(yùn)行完成后,會(huì)在目錄下面看到你生成的文件

這里我只是做測(cè)試,接口較少。

上面圖片里的import其實(shí)就是很簡(jiǎn)單的axios封裝
代碼如下:
// axios get方法
import axios from 'axios'
import notification from 'element-ui/packages/notification'
const baseUrl = 'https://localhost:7221'
axios.defaults.timeout = 5000
axios.defaults.xsrfHeaderName = ''
axios.defaults.xsrfCookieName = ''
export function httpGet(url, params) {
return new Promise((resolve, reject) => {
axios.get(baseUrl + url, {
params: params
}).then(res => {
resolve(res.data)
}).catch(err => {
reject(err.data)
})
})
}
// axios post方法
export function httpPost(url, params) {
return new Promise((resolve, reject) => {
axios.post(baseUrl + url, params).then(res => {
// 攔截不是200的狀態(tài)碼
if (res.status !== 200) {
notification.error('請(qǐng)求失敗,狀態(tài)碼:' + res.status)
return
}
resolve(res.data)
}).catch(err => {
console.log(err)
notification.error({ title: '錯(cuò)誤', message: '請(qǐng)求出錯(cuò)' })
reject(err.data)
})
})
}這邊完成后,就可以在頁(yè)面上調(diào)用了

目前封裝的方法可能還有點(diǎn)簡(jiǎn)單,但對(duì)我來(lái)說(shuō)暫時(shí)夠用了。
最后再附上swagger.json的數(shù)據(jù),就是解析這些數(shù)據(jù)生成的文件。
{
"openapi": "3.0.1",
"info": {
"title": "WebApplication1",
"version": "1.0"
},
"paths": {
"/api/test/getusers": {
"get": {
"tags": [
"Test"
],
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/api/test/add": {
"post": {
"tags": [
"Test"
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
},
"application/*+json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
},
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/api/user/getUserList": {
"get": {
"tags": [
"User"
],
"parameters": [
{
"name": "keyWord",
"in": "query",
"schema": {
"type": "string"
}
},
{
"name": "pageIndex",
"in": "query",
"schema": {
"type": "integer",
"format": "int32"
}
},
{
"name": "limit",
"in": "query",
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/api/user/add": {
"post": {
"tags": [
"User"
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
},
"application/*+json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
},
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/api/user/detail": {
"get": {
"tags": [
"User"
],
"parameters": [
{
"name": "id",
"in": "query",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/api/user/remove": {
"post": {
"tags": [
"User"
],
"parameters": [
{
"name": "id",
"in": "query",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/WeatherForecast": {
"get": {
"tags": [
"WeatherForecast"
],
"operationId": "GetWeatherForecast",
"responses": {
"200": {
"description": "Success",
"content": {
"text/plain": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/WeatherForecast"
}
}
},
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/WeatherForecast"
}
}
},
"text/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/WeatherForecast"
}
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"User": {
"type": "object",
"properties": {
"id": {
"maxLength": 36,
"minLength": 0,
"type": "string",
"nullable": true
},
"name": {
"maxLength": 50,
"minLength": 0,
"type": "string",
"nullable": true
},
"createTime": {
"type": "string",
"format": "date-time"
}
},
"additionalProperties": false
},
"WeatherForecast": {
"type": "object",
"properties": {
"date": {
"type": "string",
"format": "date-time"
},
"temperatureC": {
"type": "integer",
"format": "int32"
},
"temperatureF": {
"type": "integer",
"format": "int32",
"readOnly": true
},
"summary": {
"type": "string",
"nullable": true
}
},
"additionalProperties": false
}
}
}
}
到此這篇關(guān)于vue 自動(dòng)生成swagger接口請(qǐng)求文件的文章就介紹到這了,更多相關(guān)vue swagger接口內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue-meta實(shí)現(xiàn)router動(dòng)態(tài)設(shè)置meta標(biāo)簽的方法
這篇文章主要介紹了vue-meta實(shí)現(xiàn)router動(dòng)態(tài)設(shè)置meta標(biāo)簽,實(shí)現(xiàn)思路非常簡(jiǎn)單內(nèi)容包括mata標(biāo)簽的特點(diǎn)和mata標(biāo)簽共有兩個(gè)屬性,分別是http-equiv屬性和name屬性,本文通過實(shí)例代碼給大家詳細(xì)講解需要的朋友可以參考下2022-11-11
在線使用iconfont字體圖標(biāo)的簡(jiǎn)單實(shí)現(xiàn)
這篇文章主要介紹了在線使用iconfont字體圖標(biāo)的簡(jiǎn)單實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
vue.js中for循環(huán)如何實(shí)現(xiàn)異步方法同步執(zhí)行
這篇文章主要介紹了vue.js中for循環(huán)如何實(shí)現(xiàn)異步方法同步執(zhí)行問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02
解決Vue2?axios發(fā)請(qǐng)求報(bào)400錯(cuò)誤"Error:?Request?failed?with?s
這篇文章主要給大家介紹了關(guān)于如何解決Vue2?axios發(fā)請(qǐng)求報(bào)400錯(cuò)誤"Error:?Request?failed?with?status?code?400"的相關(guān)資料,在Vue應(yīng)用程序中我們通常會(huì)使用axios作為網(wǎng)絡(luò)請(qǐng)求庫(kù),需要的朋友可以參考下2023-07-07
Vue入門之?dāng)?shù)量加減運(yùn)算操作示例
這篇文章主要介紹了Vue入門之?dāng)?shù)量加減運(yùn)算操作,結(jié)合實(shí)例形式分析了vue.js基本數(shù)值運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2018-12-12
Vue2和Vue3在v-for遍歷時(shí)ref獲取dom節(jié)點(diǎn)的區(qū)別及說(shuō)明
這篇文章主要介紹了Vue2和Vue3在v-for遍歷時(shí)ref獲取dom節(jié)點(diǎn)的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03

