简介
因为后端会把接口用swagger去生成一个可视化接口页面,前端每次去调用的时候都要去手写接口的api文件,所以本文将介绍如何使用nodejs去通过swagger生成的可视化页面自动创建接口api文件
1、首先使用Koa和koa-router去创建一个服务
createApi-server.js
// 因为我们需要去创建文件所以引入fs
const fs = require('fs')
const Koa = require('koa')
const Router = require('koa-router')
// 因为会需要调用接口 所以引入axios
const axios = require('axios')
const app = new Koa()
const router = new Router()
const port = 369
app.use(router.routes()).use(router.allowenMethods())
app.listen(port, async () => {
console.log(`http://localhost:${port}/ is running server`)
})
2、创建一个文件夹用来展示调用swagger接口之后的结果 element-plus和axios、vue3。这3个是我直接拿的框架源码
createApi
│
└───page
│ │ index.html
│ │ axios.min.js
│ │ element-plus.css
│ │ element-plus.js
│ │ index.js
│ │ vue3.js
│
└───util
│ index.js
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="./vue3.js"></script>
<link rel="stylesheet" href="./element-plus.css" />
<script src="./element-plus.js"></script>
<script src="./axios.min.js"></script>
<title>一键创建api文件</title>
<style>
html,
body {
position: relative;
overflow: hidden;
margin: 0;
width: 100vw;
height: 100vh;
}
body {
display: flex;
justify-content: center;
align-items: center;
font-family: 'Helvetica';
color: hsla(0, 0%, 0%, 0.618);
}
#app {
display: flex;
flex-direction: column;
width: 520px;
height: 520px;
/* background: #eee; */
}
.header {
margin-bottom: 30px;
}
.header .select {
margin-right: 20px;
width: 250px;
}
#app .content {
position: relative;
box-sizing: border-box;
flex: 1;
padding-bottom: 30px;
}
.group {
padding: 0 12px;
}
</style>
</head>
<body>
<div id="app">
<div class="header">
<el-select
class="select"
placeholder="请选择你需要创建的接口名称"
filterable
v-model="checkTag"
>
<el-option
v-for="item in tags"
:label="item.name"
:value="item.name"
></el-option>
</el-select>
<el-button type="primary" size="mini" @click="creatFile"
>创建文件</el-button
>
</div>
<div class="content">
<el-checkbox
v-for="item in pathList"
:key="item.path"
v-model="checkPaths"
:label="item.path"
>{{
`${item.method} ${item.path} ${item.summary}`
}}</el-checkbox
>
</div>
</div>
<script type="module">
import './index.js'
</script>
</body>
</html>
index.js
;(async ({ Vue, ElementPlus, axios }) => {
// console.log(window);
const App = {
setup() {
const { toRefs, shallowReactive, onMounted, watch } = Vue
const { ElLoading, ElMessage } = ElementPlus
const state = shallowReactive({
// 接口属性
paths: {},
// 下拉框
tags: [],
// 选中的tag
checkTag: '',
})
// 获取api-doc文档
const getApiDocs = async () => {
const loadingInstance = ElLoading.service({
fullscreen: true,
text: '正在获取数据...',
background: 'rgba(255, 255, 255, .1)',
})
const url = '/api'
try {
const { data } = await axios.get(url)
state.tags = data.tags
state.paths = data.paths
} catch (e) {
ElMessage.error({
message: '服务中断或发生异常!',
})
}
loadingInstance.close()
}
// 获取Path
watch(
() => state.checkTag,
async (v) => {
state.pathList = await getCheckTag()
}
)
const creatFile = () => {
// 创建文件方法
}
onMounted(async () => {
getApiDocs()
})
return {
...toRefs(state),
creatFile
}
},
}
const app = Vue.createApp(App)
app.use(ElementPlus)
app.mount('#app')
window.App = App
})(window)
3、使用koa-static配置静态目录为刚刚写好的index.html,并且创建api接口
createApi-server.js
const KoaStatic = require('koa-static')
...
const port = 369
app.use(koaStatic(`${process.cwd()}/createApi/page`))
router.get('/api', async (ctx, next) => {
// api文档地址
const url = 'swagger的api-docs的url'
const res = await axios(url)
ctx.body = res.data
await next()
})
...
4、接下来起一下服务先看看页面效果
由于我是直接在vuecli项目写的这个功能,所以我直接在package.json里面加了一个命令 "createApi": "nodemon createApi-server.js"
至于为什么要用多选框,我是为了以后加功能便捷而创建的,这个可以忽视
5、页面 接口都联调好了,现在就是开始创建文件了,首先打开createApi/util/index.js里面写创建文件的方法
/util/index.js
const fs = require('fs')
const path = require('path')
// 创建文件之前 首先需要判断 该路径是否存在此文件
/**
* @desc 判断该路径是否存在此文件
* @param {string} dirname 路径
* @author deng
*/
function hasFile(dirname) {
return new Promise(function (resolve, reject) {
fs.access(dirname, (err) => {
if (err) {
// 没有文件
resolve(false)
} else {
// 有该文件
resolve(true)
}
})
})
}
// 我这边使用了比较暴力的手法,如果有该文件,直接替换掉
/**
* @desc 创建文件
* @param {string} dirname 文件名
* @param {*} data 文件内容
* @author deng
*/
async function creatFile(dirname, data) {
// 先删除同名文件
if (await hasFile(dirname)) {
console.log('删除原文件')
await fs.rmSync(dirname)
}
fs.writeFile(dirname, data, (err) => {
if (err) {
console.error('创建失败', err)
}
console.log(`创建成功-${dirname}`)
})
}
/**
* @desc 写入api文件
* @param {Array} pathList 接口API的集合
* @author deng
*/
function createApiFile(pathList) {
// 路径名
const dirname = `./src/api/${pathList[0].path.split('/')[1]}.js`
// 这是我自己在项目封装的axios方法
let file = `import request from '@/utils/request'
`
pathList.forEach((v) => {
const { path, method, summary } = v
// 方法名
const name = path.split('/').join('')
fucList.push(name)
// 只有get请求才会使用params参数
const data = method === 'get' ? 'params' : 'data'
file += `
export function ${name}(${data}){
return request({
url: '${path}',
method: '${method}',
desc: '${summary}',
${data}
})
}
`
})
creatFile(dirname, file)
}
module.exports = {
creatFile,
createApiFile
}
创建文件的方法已经封装好了, 那就直接在createApi-server.js去写接口吧
使用koa-bodyparser插件来接收参数
createApi-server.js
const bodyParser = require('koa-bodyparser')
const { createApiFile } = require('./createApi/util')
app.use(bodyParser())
// 创建api
router.post('/writeAPIFile', async (ctx, next) => {
const { pathList } = ctx.request.body
await createApiFile(pathList)
ctx.body = { code: 0, msg: '创建成功!' }
await next()
})
再去page/index.js里面调用创建文件的api
/page/index.js
// 之前创建的createFile方法里面调用接口
const creatFile = async () => {
const { pathList } = state
try {
const res = await axios.post('/writeAPIFile', {
pathList,
})
if (res.code === 0) {
ElMessage.success({
message: '创建成功!',
})
}
} catch (e) {
ElMessage.error({
message: '文件异常!',
})
}
}
启动服务 试一下创建是否成功