swagger文档管理改为API接口文档管理
This commit is contained in:
@@ -0,0 +1,209 @@
|
||||
|
||||
import datasourceApi from '../../api/datasource'
|
||||
/**
|
||||
* 编辑框自动提示数据库、表和字段等
|
||||
*/
|
||||
export default {
|
||||
isInit: false,
|
||||
source: {},
|
||||
databaseInfo: {},
|
||||
tableInfo: {},
|
||||
columnInfo: {},
|
||||
lastCallbackArr: [],
|
||||
isAutocomplete: false,
|
||||
change(source) {
|
||||
this.source = source;
|
||||
this.lastCallbackArr = [];
|
||||
console.log("change(sourceId):" + JSON.stringify(this.source));
|
||||
if (!this.isInit) {
|
||||
console.log("change(sourceId),isInit:" + this.isInit);
|
||||
this.isInit = true;
|
||||
let languageTools = ace.acequire("ace/ext/language_tools");
|
||||
languageTools.addCompleter(this);
|
||||
}
|
||||
// 初始加载
|
||||
if (!!this.source.sourceId) {
|
||||
// 加载所有库
|
||||
let databaseList = this.databaseInfo[this.source.sourceId] || [];
|
||||
if (databaseList.length <= 0) {
|
||||
datasourceApi.databaseList({sourceId: this.source.sourceId}).then(json => {
|
||||
this.databaseInfo[this.source.sourceId] = json.data || [];
|
||||
});
|
||||
}
|
||||
// 加载库下所有表
|
||||
if (!!this.source.dbName) {
|
||||
let tableKey = this.source.sourceId + '_' + this.source.dbName;
|
||||
let tableList = this.tableInfo[tableKey] || [];
|
||||
if (tableList.length <= 0) {
|
||||
datasourceApi.tableList({sourceId: this.source.sourceId, dbName: this.source.dbName}).then(json => {
|
||||
this.tableInfo[tableKey] = json.data || [];
|
||||
});
|
||||
}
|
||||
}
|
||||
// 加载表下所有字段
|
||||
if (!!this.source.tableName) {
|
||||
let columnKey = this.source.sourceId + '_' + this.source.dbName + '_' + this.source.tableName;
|
||||
let columnList = this.columnInfo[columnKey] || [];
|
||||
if (columnList.length <= 0) {
|
||||
datasourceApi.tableColumnList({sourceId: this.source.sourceId, dbName: this.source.dbName, tableName: this.source.tableName}).then(json => {
|
||||
this.columnInfo[columnKey] = json.data.columnList || [];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
startAutocomplete(editor) {
|
||||
this.isAutocomplete = true;
|
||||
editor.execCommand("startAutocomplete");
|
||||
},
|
||||
async getCompletions(editor, session, pos, prefix, callback) {
|
||||
let callbackArr = [];
|
||||
let endPos = this.isAutocomplete ? pos.column : pos.column - 1;
|
||||
let lineStr = session.getLine(pos.row).substring(0, endPos);
|
||||
this.isAutocomplete = false;
|
||||
console.log("Executor.vue getCompletions,sourceId:" + JSON.stringify(this.source) + ', lineStr:' + lineStr, pos);
|
||||
if (!!this.source.tableName) {
|
||||
// 如果指定了表名,则只提示字段,其他都不用管,用在表数据查看页面
|
||||
callbackArr = await this.getAssignTableColumns(this.source.dbName, this.source.tableName);
|
||||
callback(null, callbackArr);
|
||||
} else if (lineStr.endsWith("from ") || lineStr.endsWith("join ") || lineStr.endsWith("into ")
|
||||
|| lineStr.endsWith("update ") || lineStr.endsWith("table ")) {
|
||||
// 获取库和表
|
||||
callbackArr = this.getDatabasesAndTables();
|
||||
this.lastCallbackArr = callbackArr;
|
||||
callback(null, callbackArr);
|
||||
} else if (lineStr.endsWith(".")) {
|
||||
// 获取表和字段
|
||||
callbackArr = await this.getTablesAndColumns(lineStr);
|
||||
this.lastCallbackArr = callbackArr;
|
||||
callback(null, callbackArr);
|
||||
} else if (lineStr.endsWith("select ") || lineStr.endsWith("where ") || lineStr.endsWith("and ")
|
||||
|| lineStr.endsWith("or ") || lineStr.endsWith("set ")) {
|
||||
// 获取字段
|
||||
callbackArr = await this.getTableColumns(session, pos);
|
||||
this.lastCallbackArr = callbackArr;
|
||||
callback(null, callbackArr);
|
||||
} else {
|
||||
callback(null, this.lastCallbackArr);
|
||||
}
|
||||
},
|
||||
getDatabasesAndTables() {
|
||||
let callbackArr = [];
|
||||
// 所有表
|
||||
let tableList = this.tableInfo[this.source.sourceId + '_' + this.source.dbName] || [];
|
||||
tableList.forEach(item => callbackArr.push({
|
||||
caption: (!!item.tableComment) ? item.tableName + '-' + item.tableComment : item.tableName,
|
||||
snippet: item.tableName,
|
||||
meta: "表",
|
||||
type: "snippet",
|
||||
score: 1000
|
||||
}));
|
||||
// 所有库
|
||||
let databaseList = this.databaseInfo[this.source.sourceId] || [];
|
||||
databaseList.forEach(item => callbackArr.push({
|
||||
caption: item.dbName,
|
||||
snippet: item.dbName,
|
||||
meta: "库",
|
||||
type: "snippet",
|
||||
score: 1000
|
||||
}));
|
||||
return callbackArr;
|
||||
},
|
||||
async getTablesAndColumns(lineStr) {
|
||||
let isFound = false;
|
||||
let callbackArr = [];
|
||||
// 匹配 库名. 搜索表名
|
||||
let databaseList = this.databaseInfo[this.source.sourceId] || [];
|
||||
for (let i = 0; i < databaseList.length; i++) {
|
||||
let item = databaseList[i];
|
||||
if (lineStr.endsWith(item.dbName + ".")) {
|
||||
let tableList = this.tableInfo[this.source.sourceId + '_' + item.dbName] || [];
|
||||
if (tableList.length <= 0) {
|
||||
let res = await datasourceApi.tableList({sourceId: this.source.sourceId, dbName: item.dbName});
|
||||
tableList = res.data || [];
|
||||
this.tableInfo[this.source.sourceId + '_' + item.dbName] = tableList;
|
||||
}
|
||||
tableList.forEach(item => callbackArr.push({
|
||||
caption: (!!item.tableComment) ? item.tableName + '-' + item.tableComment : item.tableName,
|
||||
snippet: item.tableName,
|
||||
meta: "表",
|
||||
type: "snippet",
|
||||
score: 1000
|
||||
}));
|
||||
isFound = true;
|
||||
}
|
||||
}
|
||||
// 未找到,匹配 表名. 搜索字段名
|
||||
if (!isFound) {
|
||||
let tableList = this.tableInfo[this.source.sourceId + '_' + this.source.dbName] || [];
|
||||
for (let i = 0; i < tableList.length; i++) {
|
||||
let tableName = tableList[i].tableName;
|
||||
if (lineStr.endsWith(tableName + ".")) {
|
||||
callbackArr = await this.getAssignTableColumns(this.source.dbName, tableName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return callbackArr;
|
||||
},
|
||||
async getTableColumns(session, pos) {
|
||||
let queryText = "";
|
||||
// 往前加
|
||||
for (let i = pos.row; i >= 0; i--) {
|
||||
let tempLine = session.getLine(i);
|
||||
queryText = tempLine + " " + queryText;
|
||||
if (tempLine.indexOf(";") >= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 往后加
|
||||
for (let i = pos.row + 1; i < session.getLength(); i++) {
|
||||
let tempLine = session.getLine(i);
|
||||
queryText = queryText + " " + tempLine;
|
||||
if (tempLine.indexOf(";") >= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 所有表,找下面的字段列表
|
||||
let callbackArr = [];
|
||||
let tableList = this.tableInfo[this.source.sourceId + '_' + this.source.dbName] || [];
|
||||
for (let i = 0; i < tableList.length; i++) {
|
||||
let tableName = tableList[i].tableName;
|
||||
if (queryText.indexOf(tableName) >= 0) {
|
||||
let tempArr = await this.getAssignTableColumns(this.source.dbName, tableName);
|
||||
callbackArr = callbackArr.concat(tempArr);
|
||||
}
|
||||
}
|
||||
return callbackArr;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取指定数据表的字段
|
||||
* @param dbName
|
||||
* @param tableName
|
||||
*/
|
||||
async getAssignTableColumns(dbName, tableName) {
|
||||
let columnKey = this.source.sourceId + '_' + dbName + '_' + tableName;
|
||||
let columnList = this.columnInfo[columnKey] || [];
|
||||
if (columnList.length <= 0) {
|
||||
let res = await datasourceApi.tableColumnList({
|
||||
sourceId: this.source.sourceId,
|
||||
dbName: dbName,
|
||||
tableName: tableName
|
||||
});
|
||||
columnList = res.data.columnList || [];
|
||||
this.columnInfo[columnKey] = columnList;
|
||||
}
|
||||
let callbackArr = [];
|
||||
columnList.forEach(item => {
|
||||
let caption = (!!item.description) ? item.name + "-" + item.description : item.name;
|
||||
callbackArr.push({
|
||||
caption: caption,
|
||||
snippet: item.name,
|
||||
meta: "字段",
|
||||
type: "snippet",
|
||||
score: 1000
|
||||
});
|
||||
});
|
||||
return callbackArr;
|
||||
}
|
||||
}
|
||||
3
zyplayer-doc-ui/api-ui/src/assets/ace-editor/index.css
Normal file
3
zyplayer-doc-ui/api-ui/src/assets/ace-editor/index.css
Normal file
@@ -0,0 +1,3 @@
|
||||
.ace_editor.ace_autocomplete{
|
||||
width: 400px;
|
||||
}
|
||||
110
zyplayer-doc-ui/api-ui/src/assets/ace-editor/index.js
Normal file
110
zyplayer-doc-ui/api-ui/src/assets/ace-editor/index.js
Normal file
@@ -0,0 +1,110 @@
|
||||
import ace from 'brace';
|
||||
import 'brace/ext/language_tools';
|
||||
import 'brace/mode/sql';
|
||||
import 'brace/snippets/sql';
|
||||
import 'brace/mode/json';
|
||||
import 'brace/snippets/json';
|
||||
import 'brace/mode/xml';
|
||||
import 'brace/snippets/xml';
|
||||
import 'brace/mode/html';
|
||||
import 'brace/snippets/html';
|
||||
import 'brace/mode/javascript';
|
||||
import 'brace/snippets/javascript';
|
||||
import 'brace/mode/text';
|
||||
import 'brace/snippets/text';
|
||||
import 'brace/theme/monokai';
|
||||
import 'brace/theme/chrome';
|
||||
import './index.css';
|
||||
import { h, reactive } from 'vue'
|
||||
|
||||
export default {
|
||||
render() {
|
||||
let height = this.height ? this.px(this.height) : '100%';
|
||||
let width = this.width ? this.px(this.width) : '100%';
|
||||
return h('div', {
|
||||
attrs: {
|
||||
style: "height: " + height + '; width: ' + width,
|
||||
}
|
||||
});
|
||||
},
|
||||
props: {
|
||||
value: String,
|
||||
lang: String,
|
||||
theme: String,
|
||||
height: String,
|
||||
width: String,
|
||||
options: Object
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editor: null,
|
||||
contentBackup: ""
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: function (val) {
|
||||
if (this.contentBackup !== val) {
|
||||
this.editor.session.setValue(val, 1);
|
||||
this.contentBackup = val;
|
||||
}
|
||||
},
|
||||
theme: function (newTheme) {
|
||||
this.editor.setTheme('ace/theme/' + newTheme);
|
||||
},
|
||||
lang: function (newLang) {
|
||||
this.editor.getSession().setMode(typeof newLang === 'string' ? ('ace/mode/' + newLang) : newLang);
|
||||
},
|
||||
options: function (newOption) {
|
||||
this.editor.setOptions(newOption);
|
||||
},
|
||||
height: function () {
|
||||
this.$nextTick(function () {
|
||||
this.editor.resize()
|
||||
})
|
||||
},
|
||||
width: function () {
|
||||
this.$nextTick(function () {
|
||||
this.editor.resize()
|
||||
})
|
||||
},
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.editor.destroy();
|
||||
this.editor.container.remove();
|
||||
},
|
||||
mounted() {
|
||||
let vm = this;
|
||||
let lang = this.lang || 'text';
|
||||
let theme = this.theme || 'chrome';
|
||||
let editor = vm.editor = ace.edit(this.$el);
|
||||
editor.$blockScrolling = Infinity;
|
||||
this.$emit('init', editor);
|
||||
//editor.setOption("enableEmmet", true);
|
||||
editor.getSession().setMode(typeof lang === 'string' ? ('ace/mode/' + lang) : lang);
|
||||
editor.setTheme('ace/theme/' + theme);
|
||||
if (this.value) {
|
||||
editor.setValue(this.value, 1);
|
||||
}
|
||||
this.contentBackup = this.value;
|
||||
editor.on('change', function () {
|
||||
let content = editor.getValue();
|
||||
vm.$emit('update:value', content);
|
||||
vm.contentBackup = content;
|
||||
// 内容改变就执行输入提示功能,和自动的冲突了,感觉自动的就符合了,但是按空格他不出现提示框
|
||||
// console.log('change content:' + content);
|
||||
// editor.execCommand("startAutocomplete");
|
||||
});
|
||||
if (vm.options) {
|
||||
editor.setOptions(vm.options);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
px: function (n) {
|
||||
if (/^\d*$/.test(n)) {
|
||||
return n + "px";
|
||||
}
|
||||
return n;
|
||||
},
|
||||
},
|
||||
}
|
||||
;
|
||||
@@ -0,0 +1,9 @@
|
||||
import logUtil from '../utils/logUtil.js';
|
||||
|
||||
/**
|
||||
* openApi格式的参数解析
|
||||
* @author 暮光:城中城
|
||||
* @since 2017年5月7日
|
||||
*/
|
||||
export default {}
|
||||
|
||||
351
zyplayer-doc-ui/api-ui/src/assets/core/SwaggerAnalysis.js
Normal file
351
zyplayer-doc-ui/api-ui/src/assets/core/SwaggerAnalysis.js
Normal file
@@ -0,0 +1,351 @@
|
||||
import logUtil from '../utils/logUtil.js';
|
||||
// 无需特殊处理的参数类型
|
||||
let notNeedHandleTypeArr = ['file', 'string', 'integer', 'long', 'double', 'object', 'number', 'boolean', 'ref'];
|
||||
|
||||
/**
|
||||
* swagger格式的参数解析参数解析
|
||||
* @author 暮光:城中城
|
||||
* @since 2017年5月7日
|
||||
*/
|
||||
export default {
|
||||
/**
|
||||
* 解析请求的参数
|
||||
* @param parameters swagger.parameters
|
||||
* @param definitionsDataMap 解析的path里对应的数据map,{url + "." + method: swagger.paths.post}
|
||||
* @returns [] 参数列表:[{
|
||||
* type: '',
|
||||
* key: '',
|
||||
* in: '',
|
||||
* name: '',
|
||||
* subType: '',
|
||||
* required: '否',
|
||||
* format: '',
|
||||
* enum: '',
|
||||
* example: '',
|
||||
* collectionFormat: 'multi',
|
||||
* description: '',
|
||||
* additional: '',
|
||||
* children: [],
|
||||
* }]
|
||||
*/
|
||||
getRequestParamList(parameters, definitionsDataMap) {
|
||||
if (!parameters) {
|
||||
return [];
|
||||
}
|
||||
let indexKey = 1;
|
||||
let requestParamList = [];
|
||||
for (let i = 0; i < parameters.length; i++) {
|
||||
let parameter = parameters[i];
|
||||
let description = parameter.description || '';
|
||||
let type = parameter.type;
|
||||
let format = parameter.format;
|
||||
let example = parameter['x-example'];
|
||||
let subType = undefined;
|
||||
let children = undefined;
|
||||
let additional = undefined;
|
||||
if (type === 'array') {
|
||||
// 解析parameter.items.$ref 或 parameter.items.$ref {$ref: "#/definitions/Model"}
|
||||
// 解析parameter.items.type {type: 'file'}
|
||||
if (this.isSchemaRef(parameter.items)) {
|
||||
subType = this.getSchemaRef(parameter.items);
|
||||
children = this.getParamDefinitions(subType, definitionsDataMap, indexKey, {}, 0);
|
||||
} else if (parameter.schema) {
|
||||
if (this.isSchemaRef(parameter.schema.items)) {
|
||||
subType = this.getSchemaRef(parameter.schema.items);
|
||||
children = this.getParamDefinitions(subType, definitionsDataMap, indexKey, {}, 0);
|
||||
} else if (parameter.schema.type) {
|
||||
subType = parameter.schema.type;
|
||||
}
|
||||
} else if (parameter.items && parameter.items.type) {
|
||||
subType = parameter.items.type;
|
||||
} else {
|
||||
logUtil.logMessage('001', type, parameter);
|
||||
}
|
||||
} else if (!type) {
|
||||
if (parameter.schema) {
|
||||
if (this.isSchemaRef(parameter.schema)) {
|
||||
// 解析parameter.schema {$ref: "#/definitions/Model"}
|
||||
type = this.getSchemaRef(parameter.schema);
|
||||
children = this.getParamDefinitions(type, definitionsDataMap, indexKey, {}, 0);
|
||||
} else if (parameter.schema.type) {
|
||||
type = parameter.schema.type;
|
||||
if (parameter.schema.additionalProperties) {
|
||||
additional = {};
|
||||
children = this.getAdditionalProperties(parameter.schema.additionalProperties, additional, definitionsDataMap, indexKey, {}, 0);
|
||||
format = additional.type;
|
||||
} else if (parameter.schema.items) {
|
||||
if (this.isSchemaRef(parameter.schema.items)) {
|
||||
subType = this.getSchemaRef(parameter.schema.items);
|
||||
children = this.getParamDefinitions(subType, definitionsDataMap, indexKey, {}, 0);
|
||||
} else if (parameter.schema.items.type) {
|
||||
subType = parameter.schema.items.type;
|
||||
} else {
|
||||
logUtil.log('0014', type, parameter);
|
||||
}
|
||||
} else {
|
||||
logUtil.log('0011', type, parameter);
|
||||
}
|
||||
} else {
|
||||
logUtil.logMessage('0013', type, parameter);
|
||||
}
|
||||
} else if (parameter.items && parameter.items.type) {
|
||||
// 解析parameter.items {type: "object", $ref: "#/definitions/Model"}
|
||||
type = parameter.items.type;
|
||||
if (parameter.items.additionalProperties) {
|
||||
additional = {};
|
||||
children = this.getAdditionalProperties(parameter.items.additionalProperties, additional, definitionsDataMap, indexKey, {}, 0);
|
||||
format = additional.type;
|
||||
} else {
|
||||
logUtil.logMessage('0012', type, parameter);
|
||||
}
|
||||
} else {
|
||||
logUtil.logMessage('002', type, parameter);
|
||||
}
|
||||
} else {
|
||||
if (notNeedHandleTypeArr.indexOf(type) >= 0) {
|
||||
// 无需特殊处理的类型
|
||||
} else {
|
||||
logUtil.logMessage('003', type, parameter);
|
||||
}
|
||||
}
|
||||
if (example) {
|
||||
description = description ? (description + ',') : '';
|
||||
description += '例:' + example;
|
||||
}
|
||||
if (parameter.enum && parameter.enum.length > 0) {
|
||||
description = description || '枚举类型';
|
||||
description += ',可选值:' + parameter.enum.join('、');
|
||||
}
|
||||
requestParamList.push({
|
||||
type: type,
|
||||
key: indexKey,
|
||||
in: parameter.in,
|
||||
name: parameter.name,
|
||||
subType: subType,
|
||||
required: parameter.required ? '是' : '否',
|
||||
format: format,
|
||||
enum: parameter.enum,
|
||||
example: example,
|
||||
collectionFormat: parameter.collectionFormat,// 枚举多选时=multi
|
||||
description: description,
|
||||
additional: additional,
|
||||
children: children,
|
||||
});
|
||||
indexKey++;
|
||||
}
|
||||
return requestParamList;
|
||||
},
|
||||
/**
|
||||
* 解析请求返回的结果集
|
||||
* @param responses swagger.parameters
|
||||
* @param definitionsDataMap 解析的path里对应的数据map,{url + "." + method: swagger.paths.post}
|
||||
* @returns [] 参数列表:[{
|
||||
* code: '',
|
||||
* type: '',
|
||||
* key: '',
|
||||
* desc: '',
|
||||
* schemas: [],
|
||||
* }]
|
||||
*/
|
||||
getResponseParamList(responses, definitionsDataMap) {
|
||||
let responsesList = [];
|
||||
let indexKey = 1;
|
||||
Object.keys(responses).forEach(code => {
|
||||
let codeResponses = responses[code];
|
||||
let type = undefined;
|
||||
let children = undefined;
|
||||
if (this.isSchemaRef(codeResponses.schema)) {
|
||||
type = this.getSchemaRef(codeResponses.schema);
|
||||
children = this.getParamDefinitions(type, definitionsDataMap, indexKey, {}, 0);
|
||||
}
|
||||
responsesList.push({
|
||||
code: code,
|
||||
type: type,
|
||||
key: indexKey,
|
||||
desc: codeResponses.description,
|
||||
schemas: children,
|
||||
});
|
||||
indexKey++;
|
||||
});
|
||||
return responsesList;
|
||||
},
|
||||
/**
|
||||
* 判断是否包含$ref属性
|
||||
* @param schema
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isSchemaRef(schema) {
|
||||
return !!(schema && schema['$ref']);
|
||||
},
|
||||
/**
|
||||
* 获取对象的$ref属性
|
||||
* @param schema
|
||||
* @returns {string}
|
||||
*/
|
||||
getSchemaRef(schema) {
|
||||
if (schema['$ref'] && schema['$ref'].indexOf('#/definitions/') === 0) return schema['$ref'].replace('#/definitions/', '');
|
||||
logUtil.logMessage('9467', '', schema);
|
||||
return '';
|
||||
},
|
||||
/**
|
||||
* 获取swagger.definitions里的对象信息
|
||||
* @param ref 对象名
|
||||
* @param definitionsDataMap 解析的path里对应的数据map,{url + "." + method: swagger.paths.post}
|
||||
* @param indexKey 层级key
|
||||
* @param parentRef 父级已用过的ref,防止无限递归
|
||||
* @param deep 层级深度,大于10层则不再解析,防止层级太深或无线递归
|
||||
* @returns {undefined|
|
||||
* {
|
||||
* type: '',
|
||||
* name: '',
|
||||
* key: '',
|
||||
* subType: '',
|
||||
* format: '',
|
||||
* description: '',
|
||||
* enum: '',
|
||||
* additional: '',
|
||||
* example: '',
|
||||
* children: [],
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
getParamDefinitions(ref, definitionsDataMap, indexKey, parentRef, deep) {
|
||||
let definition = definitionsDataMap[ref];
|
||||
// 层级大于5层 或者 没有类型定义
|
||||
if (deep >= 10 || !definition) {
|
||||
return undefined;
|
||||
}
|
||||
// 允许重复递归一次
|
||||
parentRef[ref] = (parentRef[ref] || 0) + 1;
|
||||
if (parentRef[ref] > 2) {
|
||||
return undefined;
|
||||
}
|
||||
let paramList = [];
|
||||
let type = definition.type;
|
||||
let properties = definition.properties;
|
||||
let indexSub = 1;
|
||||
if (type === 'object' && properties) {
|
||||
let currentLevelTypes = {};
|
||||
Object.keys(properties).forEach(key => {
|
||||
let parameter = properties[key];
|
||||
let type = parameter.type;
|
||||
let format = parameter.format;
|
||||
let description = parameter.description || '';
|
||||
let example = parameter['example'] || parameter['x-example'];
|
||||
let subType = undefined;
|
||||
let additional = undefined;
|
||||
let enums = undefined;
|
||||
let keySub = indexKey + '_' + indexSub;
|
||||
let children = undefined;
|
||||
// 把当前层级用过的类型清除,防止多个同类型在一层,后面的不能解析
|
||||
Object.keys(currentLevelTypes).forEach(currentLevelType => {
|
||||
parentRef[currentLevelType] = undefined;
|
||||
});
|
||||
if (type === 'array') {
|
||||
// 解析parameter.items {$ref: "#/definitions/Model"}
|
||||
if (this.isSchemaRef(parameter.items)) {
|
||||
subType = this.getSchemaRef(parameter.items);
|
||||
children = this.getParamDefinitions(subType, definitionsDataMap, keySub, parentRef, deep + 1);
|
||||
} else if (parameter.items && parameter.items.type) {
|
||||
subType = parameter.items.type;
|
||||
} else {
|
||||
logUtil.logMessage('004', type, parameter);
|
||||
}
|
||||
} else if (type === 'object') {
|
||||
if (parameter.additionalProperties) {
|
||||
additional = {};
|
||||
children = this.getAdditionalProperties(parameter.additionalProperties, additional, definitionsDataMap, keySub, parentRef, deep + 1);
|
||||
format = additional.type;
|
||||
} else {
|
||||
logUtil.log('0041', type, parameter);
|
||||
}
|
||||
} else if (!type) {
|
||||
if (this.isSchemaRef(parameter)) {
|
||||
type = this.getSchemaRef(parameter);
|
||||
children = this.getParamDefinitions(type, definitionsDataMap, keySub, parentRef, deep + 1);
|
||||
} else {
|
||||
logUtil.logMessage('005', type, parameter);
|
||||
}
|
||||
} else {
|
||||
if (notNeedHandleTypeArr.indexOf(type) >= 0) {
|
||||
// 无需特殊处理的类型
|
||||
} else {
|
||||
logUtil.logMessage('006', type, parameter);
|
||||
}
|
||||
}
|
||||
if (example) {
|
||||
description = description ? (description + ',') : '';
|
||||
description += '例:' + example;
|
||||
}
|
||||
if (parameter.items && parameter.items.enum && parameter.items.enum.length > 0) {
|
||||
enums = parameter.items.enum;
|
||||
description = description || '枚举类型';
|
||||
description += ',可选值:' + parameter.items.enum.join('、');
|
||||
}
|
||||
paramList.push({
|
||||
type: type,
|
||||
name: key,
|
||||
key: keySub,
|
||||
subType: subType,
|
||||
format: format,
|
||||
description: description,
|
||||
enum: enums,
|
||||
additional: additional,
|
||||
example: example,
|
||||
children: children,
|
||||
});
|
||||
indexSub++;
|
||||
currentLevelTypes[type] = 1;
|
||||
});
|
||||
}
|
||||
return paramList.length > 0 ? paramList : undefined;
|
||||
},
|
||||
/**
|
||||
* parameter.schema.additionalProperties 类型的参数值处理
|
||||
* @param additionalProperties
|
||||
* @param additional
|
||||
* @param definitionsDataMap
|
||||
* @param keySub
|
||||
* @param parentRef
|
||||
* @param deep
|
||||
* @returns {
|
||||
* undefined
|
||||
* |{type: "", name: "", key: "", subType: "", format: "", description: "", enum: "", additional: "", example: "", children: *[]}
|
||||
* |{}
|
||||
* |{children: (undefined|{type: "", name: "", key: "", subType: "", format: "", description: "", enum: "", additional: "", example: "", children: *[]}), type: string}
|
||||
* }
|
||||
*/
|
||||
getAdditionalProperties(additionalProperties, additional, definitionsDataMap, keySub, parentRef, deep) {
|
||||
if (this.isSchemaRef(additionalProperties)) {
|
||||
additional.type = this.getSchemaRef(additionalProperties);
|
||||
additional.children = this.getParamDefinitions(additional.type, definitionsDataMap, keySub, parentRef, deep + 1);
|
||||
return additional.additional;
|
||||
} else if (additionalProperties.additionalProperties) {
|
||||
additional.type = additionalProperties.type;
|
||||
additional.additional = {};
|
||||
return this.getAdditionalProperties(additionalProperties.additionalProperties, additional.additional, definitionsDataMap, keySub, parentRef, deep + 1);
|
||||
} else if (additionalProperties.type === 'array') {
|
||||
additional.type = additionalProperties.type;
|
||||
if (this.isSchemaRef(additionalProperties.items)) {
|
||||
let subType = this.getSchemaRef(additionalProperties.items);
|
||||
let children = this.getParamDefinitions(subType, definitionsDataMap, keySub, parentRef, deep + 1);
|
||||
additional.additional = {
|
||||
type: subType,
|
||||
children: children
|
||||
};
|
||||
return children;
|
||||
} else {
|
||||
logUtil.logMessage('007', '', additionalProperties);
|
||||
}
|
||||
} else {
|
||||
additional.type = additionalProperties.type;
|
||||
if (notNeedHandleTypeArr.indexOf(additional.type) >= 0) {
|
||||
// 无需特殊处理的类型
|
||||
} else {
|
||||
logUtil.logMessage('008', '', additionalProperties);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
}
|
||||
|
||||
141
zyplayer-doc-ui/api-ui/src/assets/core/SwaggerTreeAnalysis.js
Normal file
141
zyplayer-doc-ui/api-ui/src/assets/core/SwaggerTreeAnalysis.js
Normal file
@@ -0,0 +1,141 @@
|
||||
const methodArray = ["get", "head", "post", "put", "patch", "delete", "options", "trace"];
|
||||
|
||||
/**
|
||||
* 解析swagger文档paths信息,生成后续需要的关键信息
|
||||
* @param swagger 文档内容
|
||||
* @returns {{urlMethodMap: {}, tagPathMap: {}, methodStatistic: {}}} 例:
|
||||
* {
|
||||
* urlMethodMap: {
|
||||
* 'url + "." + method': {swagger.paths.url.method对象信息}
|
||||
* },
|
||||
* tagPathMap: {
|
||||
* 分组名: {url: {...接口信息, path: '', url: '', method: ''}}
|
||||
* },
|
||||
* methodStatistic: {
|
||||
* POST: 132,
|
||||
* GET: 146,
|
||||
* TOTAL: 999
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
export function analysisSwaggerData(swagger) {
|
||||
let tagPathMap = {}, urlMethodMap = {}, methodStatistic = {};
|
||||
let swaggerPaths = swagger.paths;
|
||||
if (!swaggerPaths) {
|
||||
return {urlMethodMap, tagPathMap, methodStatistic};
|
||||
}
|
||||
//console.log(swaggerPaths);
|
||||
Object.keys(swaggerPaths).forEach(url => {
|
||||
//console.log(key, swaggerPaths[key]);
|
||||
let pathMethods = swaggerPaths[url];
|
||||
for (let method of methodArray) {
|
||||
if (!pathMethods[method] || !pathMethods[method].tags) {
|
||||
continue;
|
||||
}
|
||||
let methodLower = method.toLowerCase();
|
||||
methodStatistic[methodLower] = (methodStatistic[methodLower] || 0) + 1;
|
||||
methodStatistic['total'] = (methodStatistic['total'] || 0) + 1;
|
||||
pathMethods[method].tags.forEach(tag => {
|
||||
let pathTag = tagPathMap[tag];
|
||||
if (!pathTag) {
|
||||
pathTag = tagPathMap[tag] = {};
|
||||
}
|
||||
let pathTagUrl = pathTag[url];
|
||||
if (!pathTagUrl) {
|
||||
pathTagUrl = pathTag[url] = {};
|
||||
}
|
||||
let tempPath = url + "." + method;
|
||||
pathTagUrl[method] = pathMethods[method];
|
||||
pathTagUrl[method].path = tempPath;
|
||||
pathTagUrl[method].url = url;
|
||||
pathTagUrl[method].method = method;
|
||||
// url对应文档的映射
|
||||
urlMethodMap[tempPath] = pathMethods[method];
|
||||
});
|
||||
}
|
||||
});
|
||||
return {urlMethodMap, tagPathMap, methodStatistic};
|
||||
}
|
||||
|
||||
/**
|
||||
* 按tag分组获取左侧菜单目录树
|
||||
* @param swagger 原始文档信息
|
||||
* @param tagPathMap 分组信息{分组名: {url: {...接口信息, path: '', url: '', method: ''}}}
|
||||
* @param keywords 过滤关键字
|
||||
* @param metaInfo 接口元信息,点击时放入URL的参数
|
||||
* @returns {{children: [], title: (*|string), key: string}[]}
|
||||
*/
|
||||
export function getTreeDataForTag(swagger, tagPathMap, keywords, metaInfo) {
|
||||
let treeData = [];
|
||||
let indexTag = 1;
|
||||
// 遍历分组
|
||||
let swaggerTags = swagger.tags || [];
|
||||
swaggerTags.forEach(tag => {
|
||||
let indexUrl = 1;
|
||||
let urlTree = [];
|
||||
let pathTagNode = tagPathMap[tag.name];
|
||||
if (!pathTagNode) {
|
||||
return;
|
||||
}
|
||||
// 遍历路劲
|
||||
Object.keys(pathTagNode).forEach(url => {
|
||||
let indexMethod = 1;
|
||||
let pathUrlNode = pathTagNode[url];
|
||||
// 遍历方法
|
||||
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({
|
||||
title: title,
|
||||
key: tempTreeId,
|
||||
isLeaf: true,
|
||||
method: methodNode.method,
|
||||
query: {
|
||||
...metaInfo,
|
||||
path: methodNode.url,
|
||||
method: methodNode.method,
|
||||
}
|
||||
});
|
||||
indexMethod++;
|
||||
});
|
||||
indexUrl++;
|
||||
});
|
||||
if (urlTree.length > 0) {
|
||||
treeData.push({title: tag.name, key: indexTag, children: urlTree});
|
||||
}
|
||||
indexTag++;
|
||||
});
|
||||
return [
|
||||
{
|
||||
key: 'main',
|
||||
title: swagger.info.title || 'Swagger接口文档',
|
||||
children: treeData
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索接口是否包含某关键字,将匹配:URL、path、method、summary、description、tags 属性
|
||||
* @param url 接口URL
|
||||
* @param methodNode 接口基本信息
|
||||
* @param keywords 关键字
|
||||
* @returns {*|boolean} 是否包含
|
||||
*/
|
||||
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.method + methodNode.summary + methodNode.description + methodNode.tags;
|
||||
return (searchData && searchData.toLowerCase().indexOf(keywords) >= 0);
|
||||
}
|
||||
BIN
zyplayer-doc-ui/api-ui/src/assets/logo.png
Normal file
BIN
zyplayer-doc-ui/api-ui/src/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.7 KiB |
23
zyplayer-doc-ui/api-ui/src/assets/utils/logUtil.js
Normal file
23
zyplayer-doc-ui/api-ui/src/assets/utils/logUtil.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import {message} from 'ant-design-vue';
|
||||
|
||||
export default {
|
||||
/**
|
||||
* 输出一个log到console
|
||||
* @param code 错误码,用于定位包错行
|
||||
* @param type 参数类型
|
||||
* @param parameter 参数对象
|
||||
*/
|
||||
log(code, type, parameter) {
|
||||
console.log(code + '-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
|
||||
},
|
||||
/**
|
||||
* 输出一个log到console,并且message输出信息,用于比较严重必须要处理的异常使用
|
||||
* @param code 错误码,用于定位包错行
|
||||
* @param type 参数类型
|
||||
* @param parameter 参数对象
|
||||
*/
|
||||
logMessage(code, type, parameter) {
|
||||
console.log(code + '-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
|
||||
message.error(code + '-遇到未处理的类型,请联系开发人员修改:' + type);
|
||||
}
|
||||
}
|
||||
32
zyplayer-doc-ui/api-ui/src/assets/utils/unitConvert.js
Normal file
32
zyplayer-doc-ui/api-ui/src/assets/utils/unitConvert.js
Normal file
@@ -0,0 +1,32 @@
|
||||
export default {
|
||||
formatSeconds(value) {
|
||||
let result = parseInt(value);
|
||||
let second = result / 1000;
|
||||
let s = Math.floor(second % 60);
|
||||
let ms = (result % 1000);
|
||||
if (s > 0) return `${s}.${ms} s`;
|
||||
return `${ms} ms`;
|
||||
},
|
||||
formatFileSize(fileSize) {
|
||||
if (!fileSize) {
|
||||
return '0 B';
|
||||
}
|
||||
let size = "";
|
||||
if (fileSize < 0.1 * 1024) {
|
||||
size = fileSize.toFixed(2) + " B"
|
||||
} else if (fileSize < 0.1 * 1024 * 1024) {
|
||||
size = (fileSize / 1024).toFixed(2) + " KB"
|
||||
} else if (fileSize < 0.1 * 1024 * 1024 * 1024) {
|
||||
size = (fileSize / (1024 * 1024)).toFixed(2) + " MB"
|
||||
} else {
|
||||
size = (fileSize / (1024 * 1024 * 1024)).toFixed(2) + " GB"
|
||||
}
|
||||
let sizeStr = size + "";
|
||||
let index = sizeStr.indexOf(".");
|
||||
let dou = sizeStr.substr(index + 1, 2);
|
||||
if (dou == "00") {
|
||||
return sizeStr.substring(0, index) + sizeStr.substr(index + 3, 2)
|
||||
}
|
||||
return size;
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user