swagger文档增加文档搜索和录入示例,修改编辑问题

This commit is contained in:
暮光:城中城
2021-10-30 22:33:48 +08:00
parent c8f570fa6a
commit 9fcdfb7758
23 changed files with 133 additions and 80 deletions

View File

@@ -35,8 +35,7 @@ export default {
} else if (parameter.items && parameter.items.type) {
subType = parameter.items.type;
} else {
console.log('001-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
message.error('001-遇到未处理的类型,请联系开发人员修改:' + type);
this.logMessage('001', type, parameter);
}
} else if (!type) {
if (parameter.schema) {
@@ -56,14 +55,13 @@ export default {
} else if (parameter.schema.items.type) {
subType = parameter.schema.items.type;
} else {
console.log('0014-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
this.log('0014', type, parameter);
}
} else {
console.log('0011-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
this.log('0011', type, parameter);
}
} else {
console.log('0013-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
message.error('0013-遇到未处理的类型,请联系开发人员修改:' + type);
this.logMessage('0013', type, parameter);
}
} else if (parameter.items && parameter.items.type) {
// 解析parameter.items {type: "object", $ref: "#/definitions/Model"}
@@ -73,19 +71,16 @@ export default {
children = this.getAdditionalProperties(parameter.items.additionalProperties, additional, definitionsDataMap, indexKey, {}, 0);
format = additional.type;
} else {
console.log('0012-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
message.error('0012-遇到未处理的类型,请联系开发人员修改:' + type);
this.logMessage('0012', type, parameter);
}
} else {
console.log('002-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
message.error('002-遇到未处理的类型,请联系开发人员修改:' + type);
this.logMessage('002', type, parameter);
}
} else {
if (notNeedHandleTypeArr.indexOf(type) >= 0) {
// 无需特殊处理的类型
} else {
console.log('003-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
message.error('003-遇到未处理的类型,请联系开发人员修改:' + type);
this.logMessage('003', type, parameter);
}
}
if (parameter.enum && parameter.enum.length > 0) {
@@ -171,8 +166,7 @@ export default {
} else if (parameter.items && parameter.items.type) {
subType = parameter.items.type;
} else {
console.log('004-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
message.error('004-遇到未处理的类型,请联系开发人员修改:' + type);
this.logMessage('004', type, parameter);
}
} else if (type === 'object') {
if (parameter.additionalProperties) {
@@ -180,22 +174,20 @@ export default {
children = this.getAdditionalProperties(parameter.additionalProperties, additional, definitionsDataMap, keySub, parentRef, deep + 1);
format = additional.type;
} else {
console.log('0041-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
this.log('0041', type, parameter);
}
} else if (!type) {
if (parameter.originalRef) {
type = parameter.originalRef;
children = this.getParamDefinitions(parameter.originalRef, definitionsDataMap, keySub, parentRef, deep + 1);
} else {
console.log('005-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
message.error('005-遇到未处理的类型,请联系开发人员修改:' + type);
this.logMessage('005', type, parameter);
}
} else {
if (notNeedHandleTypeArr.indexOf(type) >= 0) {
// 无需特殊处理的类型
} else {
console.log('006-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
message.error('006-遇到未处理的类型,请联系开发人员修改:' + type);
this.logMessage('006', type, parameter);
}
}
if (parameter.items && parameter.items.enum && parameter.items.enum.length > 0) {
@@ -239,19 +231,24 @@ export default {
};
return children;
} else {
console.log('007-遇到未处理的类型,请联系开发人员修改:', additionalProperties);
message.error('007-遇到未处理的类型,请联系开发人员修改');
this.logMessage('007', '', additionalProperties);
}
} else {
additional.type = additionalProperties.type;
if (notNeedHandleTypeArr.indexOf(additional.type) >= 0) {
// 无需特殊处理的类型
} else {
console.log('008-遇到未处理的类型,请联系开发人员修改:', additionalProperties);
message.error('008-遇到未处理的类型,请联系开发人员修改');
this.logMessage('008', '', additionalProperties);
}
}
return undefined;
},
log(code, type, parameter) {
console.log(code + '-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
},
logMessage(code, type, parameter) {
console.log(code + '-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
message.error(code + '-遇到未处理的类型,请联系开发人员修改:' + type);
}
}

View File

@@ -10,6 +10,7 @@
<a-select placeholder="请选择分组" v-model:value="swaggerDocChoice" @change="swaggerDocChoiceChange" style="width: 100%;">
<a-select-option :value="item.url" v-for="item in swaggerResourceList">{{item.name}}</a-select-option>
</a-select>
<a-input-search v-model:value="searchKeywords" placeholder="搜索文档内容" style="width: 100%;margin-top: 10px;" @search="loadTreeData"/>
</div>
<a-directory-tree :showIcon="false" :tree-data="treeData" v-model:expandedKeys="expandedKeys" @select="docChecked">
<template #title="{ title, isLeaf, method, children, key }">
@@ -35,7 +36,7 @@
<script>
import MenuChildrenLayout from './MenuChildrenLayout.vue'
import {customApi} from '../../api'
import {createTreeViewByTag, getTreeDataForTag} from '../../store/SwaggerDocUtil'
import {createTreeViewByTag, getTreeDataForTag} from '../../store/TreeViewByTag'
export default {
name: 'MenuLayout',
@@ -52,10 +53,13 @@
openKeys: [],
// 文档树
treeDataLoading: false,
pathData: {},
swaggerDoc: {},
treeData: [],
expandedKeys: [],
swaggerResourceList: [],
swaggerDocChoice: undefined,
searchKeywords: '',
}
},
watch:{
@@ -104,27 +108,32 @@
});
},
swaggerDocChoiceChange() {
this.loadV2Doc(this.swaggerDocChoice);
this.loadV2Doc();
},
loadV2Doc(url) {
this.expandedKeys = [];
loadV2Doc() {
this.treeDataLoading = true;
customApi.get(url).then(res => {
customApi.get(this.swaggerDocChoice).then(res => {
let v2Doc = this.toJsonObj(res);
if (typeof v2Doc !== 'object' || !v2Doc.swagger) {
this.$message.error('获取文档数据请求失败');
this.treeDataLoading = false;
return;
}
this.$store.commit('setSwaggerDoc', v2Doc);
let metaInfo = {url};
let treeData = createTreeViewByTag(v2Doc, '');
this.treeData = getTreeDataForTag(v2Doc, treeData.pathData, metaInfo);
this.swaggerDoc = v2Doc;
this.$store.commit('setSwaggerDoc', this.swaggerDoc);
let treeData = createTreeViewByTag(this.swaggerDoc);
this.$store.commit('setSwaggerTreePathMap', treeData.pathDataMap);
this.$store.commit('setMethodStatistic', treeData.methodStatistic);
this.pathData = treeData.pathData;
this.loadTreeData();
setTimeout(() => this.treeDataLoading = false, 100);
});
},
loadTreeData() {
this.expandedKeys = ['main'];
let metaInfo = {url: this.swaggerDocChoice};
this.treeData = getTreeDataForTag(this.swaggerDoc, this.pathData, this.searchKeywords, metaInfo);
},
toJsonObj(value) {
if (typeof value !== 'string') {
return value;

View File

@@ -3,10 +3,9 @@ const methodArray = ["get", "head", "post", "put", "patch", "delete", "options",
/**
* 通过tag创建文档树
* @param swagger 文档内容
* @param keywords 搜索内容
* @returns {{pathDataMap: {}, pathData: {}}}
*/
export function createTreeViewByTag(swagger, keywords) {
export function createTreeViewByTag(swagger) {
let pathData = {}, pathDataMap = {}, methodStatistic = {};
let swaggerPaths = swagger.paths;
if (!swaggerPaths) {
@@ -45,21 +44,11 @@ export function createTreeViewByTag(swagger, keywords) {
return {pathData, pathDataMap, methodStatistic};
}
export function getTreeDataForTag(swagger, pathData, metaInfo) {
return [
{
key: 'main',
title: swagger.title || 'Swagger接口文档',
children: getTreeHtmlForTag(swagger.tags, pathData, metaInfo)
}
];
}
function getTreeHtmlForTag(swaggerTags, pathData, metaInfo) {
export function getTreeDataForTag(swagger, pathData, keywords, metaInfo) {
let treeData = [];
let indexTag = 1;
// 遍历分组
swaggerTags.forEach(tag => {
swagger.tags.forEach(tag => {
let indexUrl = 1;
let urlTree = [];
let pathTagNode = pathData[tag.name];
@@ -74,6 +63,9 @@ function getTreeHtmlForTag(swaggerTags, pathData, metaInfo) {
Object.keys(pathUrlNode).forEach(method => {
let tempTreeId = indexTag + "_" + indexUrl + "_" + indexMethod;
let methodNode = pathUrlNode[method];
if (!searchInPathMethods(url, methodNode, keywords)) {
return;
}
methodNode.treeId = tempTreeId;
let title = methodNode.summary || methodNode.path;
urlTree.push({
@@ -94,5 +86,25 @@ function getTreeHtmlForTag(swaggerTags, pathData, metaInfo) {
treeData.push({title: tag.name, key: indexTag, children: urlTree});
indexTag++;
});
return treeData;
return [
{
key: 'main',
title: swagger.title || 'Swagger接口文档',
children: treeData
}
];
}
function searchInPathMethods(url, methodNode, keywords) {
if (!keywords || !url) {
return true;
}
url = url.toLowerCase();
keywords = keywords.toLowerCase();
// 路径中有就不用再去找了
if (url.indexOf(keywords) >= 0) {
return true;
}
let searchData = methodNode.path + methodNode.summary + methodNode.description + methodNode.tags;
return (searchData && searchData.toLowerCase().indexOf(keywords) >= 0);
}

View File

@@ -1,5 +1,4 @@
import {createStore} from 'vuex'
import {createTreeViewByTag} from './SwaggerDocUtil'
export default createStore({
state() {

View File

@@ -31,25 +31,20 @@
</template>
<script>
import { toRefs, ref, reactive, onMounted, computed } from 'vue';
import {useStore} from 'vuex';
export default {
name: 'docInfo',
components: {},
data() {
return {}
setup() {
const store = useStore()
const swaggerDoc = computed(() => store.state.swaggerDoc);
const swaggerDocInfo = computed(() => store.state.swaggerDoc.info);
const methodStatistic = computed(() => store.state.methodStatistic);
return {
swaggerDoc,
swaggerDocInfo,
methodStatistic
};
},
computed: {
swaggerDoc () {
return this.$store.state.swaggerDoc || {};
},
swaggerDocInfo () {
return this.$store.state.swaggerDoc.info;
},
methodStatistic () {
return this.$store.state.methodStatistic;
},
},
mounted() {
},
methods: {}
}
};
</script>

View File

@@ -65,9 +65,32 @@
</a-form-item>
<a-form-item label="文档地址" required name="docUrl" v-if="docEdit.docType === 1">
<a-input placeholder="请输入文档地址URL" v-model:value="docEdit.docUrl"></a-input>
<template #extra>
查看文档地址
<a-popover title="文档地址支持以下任一格式">
<template #content>
<p>格式一http://doc.zyplayer.com/v2/api-docs</p>
<p>格式二http://doc.zyplayer.com/swagger-resources</p>
<p>格式三http://doc.zyplayer.com/swagger-ui.html</p>
</template>
<a>示例</a>
</a-popover>
</template>
</a-form-item>
<a-form-item label="文档内容" required name="jsonContent" v-else-if="docEdit.docType === 2">
<a-textarea placeholder="请输入JSON格式的swagger文档内容" v-model:value="docEdit.jsonContent"></a-textarea>
<template #extra>
查看文档内容
<a-popover title="文档内容说明">
<template #content>
<div>支持以下格式的Swagger文档内容输入其中 {"swagger": "2.0"} 为必要属性</div>
<div v-highlight>
<pre><code class="lang-json">{{swaggerDocDemo}}</code></pre>
</div>
</template>
<a>说明</a>
</a-popover>
</template>
</a-form-item>
<a-form-item label="开放访问" required name="openVisit">
<a-radio-group v-model:value="docEdit.openVisit">
@@ -167,6 +190,16 @@
{title: '目标域名', dataIndex: 'rewriteDomain', width: 250},
{title: '操作', dataIndex: 'operation', fixed: 'right', width: 170},
],
swaggerDocDemo:
'{\n'
+ ' "swagger": "2.0",\n'
+ ' "info": {},\n'
+ ' "host": "doc.zyplayer.com",\n'
+ ' "basePath":"/",\n'
+ ' "tags": [],\n'
+ ' "paths": {},\n'
+ ' "definitions": {}\n'
+ '}'
};
},
};

View File

@@ -57,6 +57,7 @@
let docList = ref([]);
let docListLoading = ref(false);
const searchDocList = async () => {
docEdit.value = {};
docListLoading.value = true;
zyplayerApi.docSwaggerGlobalParamList().then(res => {
setTimeout(() => docListLoading.value = false, 500);
@@ -66,13 +67,16 @@
let docEdit = ref({});
const addDocLine = () => {
if (docEdit.value.isEdit) {
return;
cancelEditDoc(docEdit.value);
}
let newLine = {isEdit: true};
docList.value.push(newLine);
docEdit.value = newLine;
};
const editDoc = (record) => {
if (docEdit.value.isEdit) {
cancelEditDoc(docEdit.value);
}
record.isEdit = true;
docEdit.value = {...record};
};
@@ -80,6 +84,8 @@
record.isEdit = false;
if (!record.id) {
docList.value = docList.value.filter(item => item !== record);
} else {
docList.value.forEach(item => item.isEdit = false);
}
docEdit.value = {};
};