From f9fb9c2f70dec03aa8d4cdf74d7e3310d06ac389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9A=AE=E5=85=89=EF=BC=9A=E5=9F=8E=E4=B8=AD=E5=9F=8E?= <806783409@qq.com> Date: Tue, 23 Nov 2021 22:58:10 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=B4=E6=98=8E=E5=86=85=E5=AE=B9=E6=94=AF?= =?UTF-8?q?=E6=8C=81markdown=E6=A0=BC=E5=BC=8F=EF=BC=8C=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=90=8D=E3=80=81=E6=96=B9=E6=B3=95=E5=90=8D=E3=80=81=E6=B3=A8?= =?UTF-8?q?=E9=87=8A=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zyplayer-doc-ui/swagger-ui/package-lock.json | 15 +- zyplayer-doc-ui/swagger-ui/package.json | 2 +- .../src/assets/core/OpenApiAnalysis.js | 9 ++ .../SwaggerAnalysis.js} | 128 ++++++++++++++---- .../core/SwaggerTreeAnalysis.js} | 61 ++++++--- .../swagger-ui/src/assets/utils/logUtil.js | 23 ++++ .../src/components/layouts/MenuLayout.vue | 12 +- zyplayer-doc-ui/swagger-ui/src/store/index.js | 6 +- .../swagger-ui/src/views/swagger/DocInfo.vue | 17 ++- .../swagger-ui/src/views/swagger/DocView.vue | 8 +- 10 files changed, 209 insertions(+), 72 deletions(-) create mode 100644 zyplayer-doc-ui/swagger-ui/src/assets/core/OpenApiAnalysis.js rename zyplayer-doc-ui/swagger-ui/src/assets/{utils/SwaggerAnalysisV2.js => core/SwaggerAnalysis.js} (75%) rename zyplayer-doc-ui/swagger-ui/src/{store/TreeViewByTag.js => assets/core/SwaggerTreeAnalysis.js} (62%) create mode 100644 zyplayer-doc-ui/swagger-ui/src/assets/utils/logUtil.js diff --git a/zyplayer-doc-ui/swagger-ui/package-lock.json b/zyplayer-doc-ui/swagger-ui/package-lock.json index b25e6624..d9ddc3a4 100644 --- a/zyplayer-doc-ui/swagger-ui/package-lock.json +++ b/zyplayer-doc-ui/swagger-ui/package-lock.json @@ -8,7 +8,7 @@ "version": "0.0.0", "dependencies": { "@ant-design/icons-vue": "^6.0.1", - "ant-design-vue": "^3.0.0-alpha.8", + "ant-design-vue": "^3.0.0-alpha.12", "axios": "^0.19.2", "brace": "^0.11.1", "highlight.js": "^11.3.1", @@ -258,10 +258,9 @@ } }, "node_modules/ant-design-vue": { - "version": "3.0.0-alpha.8", - "resolved": "https://registry.npmmirror.com/ant-design-vue/download/ant-design-vue-3.0.0-alpha.8.tgz", - "integrity": "sha1-ZYFtH0S4PpkntHAQWjDTH56SyRo=", - "license": "MIT", + "version": "3.0.0-alpha.12", + "resolved": "https://r.cnpmjs.org/ant-design-vue/download/ant-design-vue-3.0.0-alpha.12.tgz", + "integrity": "sha512-kwmfnK2hC5NZW5QbkdJ7bzogXWlt9YvKTU3bw53OP4BBUep2OcSbxwR8txWLQ3A9HFeb4O1oeWkSh70LoDvpZg==", "dependencies": { "@ant-design/colors": "^6.0.0", "@ant-design/icons-vue": "^6.0.0", @@ -2494,9 +2493,9 @@ } }, "ant-design-vue": { - "version": "3.0.0-alpha.8", - "resolved": "https://registry.npmmirror.com/ant-design-vue/download/ant-design-vue-3.0.0-alpha.8.tgz", - "integrity": "sha1-ZYFtH0S4PpkntHAQWjDTH56SyRo=", + "version": "3.0.0-alpha.12", + "resolved": "https://r.cnpmjs.org/ant-design-vue/download/ant-design-vue-3.0.0-alpha.12.tgz", + "integrity": "sha512-kwmfnK2hC5NZW5QbkdJ7bzogXWlt9YvKTU3bw53OP4BBUep2OcSbxwR8txWLQ3A9HFeb4O1oeWkSh70LoDvpZg==", "requires": { "@ant-design/colors": "^6.0.0", "@ant-design/icons-vue": "^6.0.0", diff --git a/zyplayer-doc-ui/swagger-ui/package.json b/zyplayer-doc-ui/swagger-ui/package.json index 6c4c867b..ab696fc4 100644 --- a/zyplayer-doc-ui/swagger-ui/package.json +++ b/zyplayer-doc-ui/swagger-ui/package.json @@ -8,7 +8,7 @@ }, "dependencies": { "@ant-design/icons-vue": "^6.0.1", - "ant-design-vue": "^3.0.0-alpha.8", + "ant-design-vue": "^3.0.0-alpha.12", "axios": "^0.19.2", "brace": "^0.11.1", "highlight.js": "^11.3.1", diff --git a/zyplayer-doc-ui/swagger-ui/src/assets/core/OpenApiAnalysis.js b/zyplayer-doc-ui/swagger-ui/src/assets/core/OpenApiAnalysis.js new file mode 100644 index 00000000..114897fa --- /dev/null +++ b/zyplayer-doc-ui/swagger-ui/src/assets/core/OpenApiAnalysis.js @@ -0,0 +1,9 @@ +import logUtil from '../utils/logUtil.js'; + +/** + * openApi格式的参数解析 + * @author 暮光:城中城 + * @since 2017年5月7日 + */ +export default {} + diff --git a/zyplayer-doc-ui/swagger-ui/src/assets/utils/SwaggerAnalysisV2.js b/zyplayer-doc-ui/swagger-ui/src/assets/core/SwaggerAnalysis.js similarity index 75% rename from zyplayer-doc-ui/swagger-ui/src/assets/utils/SwaggerAnalysisV2.js rename to zyplayer-doc-ui/swagger-ui/src/assets/core/SwaggerAnalysis.js index 6ab116bf..f4dc3077 100644 --- a/zyplayer-doc-ui/swagger-ui/src/assets/utils/SwaggerAnalysisV2.js +++ b/zyplayer-doc-ui/swagger-ui/src/assets/core/SwaggerAnalysis.js @@ -1,12 +1,33 @@ -import {message} from 'ant-design-vue'; +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 []; @@ -23,7 +44,7 @@ export default { let children = undefined; let additional = undefined; if (type === 'array') { - // 解析parameter.items.$ref 或 parameter.items.originalRef {$ref: "#/definitions/Model", originalRef: "Model"} + // 解析parameter.items.$ref 或 parameter.items.$ref {$ref: "#/definitions/Model"} // 解析parameter.items.type {type: 'file'} if (this.isSchemaRef(parameter.items)) { subType = this.getSchemaRef(parameter.items); @@ -38,12 +59,12 @@ export default { } else if (parameter.items && parameter.items.type) { subType = parameter.items.type; } else { - this.logMessage('001', type, parameter); + logUtil.logMessage('001', type, parameter); } } else if (!type) { if (parameter.schema) { if (this.isSchemaRef(parameter.schema)) { - // 解析parameter.schema {originalRef: "Model", $ref: "#/definitions/Model"} + // 解析parameter.schema {$ref: "#/definitions/Model"} type = this.getSchemaRef(parameter.schema); children = this.getParamDefinitions(type, definitionsDataMap, indexKey, {}, 0); } else if (parameter.schema.type) { @@ -59,13 +80,13 @@ export default { } else if (parameter.schema.items.type) { subType = parameter.schema.items.type; } else { - this.log('0014', type, parameter); + logUtil.log('0014', type, parameter); } } else { - this.log('0011', type, parameter); + logUtil.log('0011', type, parameter); } } else { - this.logMessage('0013', type, parameter); + logUtil.logMessage('0013', type, parameter); } } else if (parameter.items && parameter.items.type) { // 解析parameter.items {type: "object", $ref: "#/definitions/Model"} @@ -75,16 +96,16 @@ export default { children = this.getAdditionalProperties(parameter.items.additionalProperties, additional, definitionsDataMap, indexKey, {}, 0); format = additional.type; } else { - this.logMessage('0012', type, parameter); + logUtil.logMessage('0012', type, parameter); } } else { - this.logMessage('002', type, parameter); + logUtil.logMessage('002', type, parameter); } } else { if (notNeedHandleTypeArr.indexOf(type) >= 0) { // 无需特殊处理的类型 } else { - this.logMessage('003', type, parameter); + logUtil.logMessage('003', type, parameter); } } if (example) { @@ -114,6 +135,18 @@ export default { } 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; @@ -136,15 +169,46 @@ export default { }); return responsesList; }, + /** + * 判断是否包含$ref属性 + * @param schema + * @returns {boolean} + */ isSchemaRef(schema) { - return !!(schema && (schema.originalRef || schema['$ref'])); + return !!(schema && schema['$ref']); }, + /** + * 获取对象的$ref属性 + * @param schema + * @returns {string} + */ getSchemaRef(schema) { - if (schema.originalRef) return schema.originalRef; if (schema['$ref'] && schema['$ref'].indexOf('#/definitions/') === 0) return schema['$ref'].replace('#/definitions/', ''); - this.logMessage('9467', '', schema); + 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层 或者 没有类型定义 @@ -178,14 +242,14 @@ export default { parentRef[currentLevelType] = undefined; }); if (type === 'array') { - // 解析parameter.items {originalRef: "Model", $ref: "#/definitions/Model"} + // 解析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 { - this.logMessage('004', type, parameter); + logUtil.logMessage('004', type, parameter); } } else if (type === 'object') { if (parameter.additionalProperties) { @@ -193,20 +257,20 @@ export default { children = this.getAdditionalProperties(parameter.additionalProperties, additional, definitionsDataMap, keySub, parentRef, deep + 1); format = additional.type; } else { - this.log('0041', type, parameter); + 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 { - this.logMessage('005', type, parameter); + logUtil.logMessage('005', type, parameter); } } else { if (notNeedHandleTypeArr.indexOf(type) >= 0) { // 无需特殊处理的类型 } else { - this.logMessage('006', type, parameter); + logUtil.logMessage('006', type, parameter); } } if (example) { @@ -236,6 +300,21 @@ export default { } 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); @@ -256,24 +335,17 @@ export default { }; return children; } else { - this.logMessage('007', '', additionalProperties); + logUtil.logMessage('007', '', additionalProperties); } } else { additional.type = additionalProperties.type; if (notNeedHandleTypeArr.indexOf(additional.type) >= 0) { // 无需特殊处理的类型 } else { - this.logMessage('008', '', additionalProperties); + logUtil.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); - } } diff --git a/zyplayer-doc-ui/swagger-ui/src/store/TreeViewByTag.js b/zyplayer-doc-ui/swagger-ui/src/assets/core/SwaggerTreeAnalysis.js similarity index 62% rename from zyplayer-doc-ui/swagger-ui/src/store/TreeViewByTag.js rename to zyplayer-doc-ui/swagger-ui/src/assets/core/SwaggerTreeAnalysis.js index 6e671431..7155ac4d 100644 --- a/zyplayer-doc-ui/swagger-ui/src/store/TreeViewByTag.js +++ b/zyplayer-doc-ui/swagger-ui/src/assets/core/SwaggerTreeAnalysis.js @@ -1,15 +1,28 @@ const methodArray = ["get", "head", "post", "put", "patch", "delete", "options", "trace"]; /** - * 通过tag创建文档树 + * 解析swagger文档paths信息,生成后续需要的关键信息 * @param swagger 文档内容 - * @returns {{pathDataMap: {}, pathData: {}}} + * @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 createTreeViewByTag(swagger) { - let pathData = {}, pathDataMap = {}, methodStatistic = {}; +export function analysisSwaggerData(swagger) { + let tagPathMap = {}, urlMethodMap = {}, methodStatistic = {}; let swaggerPaths = swagger.paths; if (!swaggerPaths) { - return {pathDataMap, pathData, methodStatistic}; + return {urlMethodMap, tagPathMap, methodStatistic}; } //console.log(swaggerPaths); Object.keys(swaggerPaths).forEach(url => { @@ -19,13 +32,13 @@ export function createTreeViewByTag(swagger) { if (!pathMethods[method] || !pathMethods[method].tags) { continue; } - let methodUp = method.toUpperCase(); - methodStatistic[methodUp] = (methodStatistic[methodUp] || 0) + 1; - methodStatistic['TOTAL'] = (methodStatistic['TOTAL'] || 0) + 1; + let methodLower = method.toLowerCase(); + methodStatistic[methodLower] = (methodStatistic[methodLower] || 0) + 1; + methodStatistic['total'] = (methodStatistic['total'] || 0) + 1; pathMethods[method].tags.forEach(tag => { - let pathTag = pathData[tag]; + let pathTag = tagPathMap[tag]; if (!pathTag) { - pathTag = pathData[tag] = {}; + pathTag = tagPathMap[tag] = {}; } let pathTagUrl = pathTag[url]; if (!pathTagUrl) { @@ -37,21 +50,30 @@ export function createTreeViewByTag(swagger) { pathTagUrl[method].url = url; pathTagUrl[method].method = method; // url对应文档的映射 - pathDataMap[tempPath] = pathMethods[method]; + urlMethodMap[tempPath] = pathMethods[method]; }); } }); - return {pathData, pathDataMap, methodStatistic}; + return {urlMethodMap, tagPathMap, methodStatistic}; } -export function getTreeDataForTag(swagger, pathData, keywords, metaInfo) { +/** + * 按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; // 遍历分组 - swagger.tags.forEach(tag => { + let swaggerTags = swagger.tags || []; + swaggerTags.forEach(tag => { let indexUrl = 1; let urlTree = []; - let pathTagNode = pathData[tag.name]; + let pathTagNode = tagPathMap[tag.name]; if (!pathTagNode) { return; } @@ -91,12 +113,19 @@ export function getTreeDataForTag(swagger, pathData, keywords, metaInfo) { return [ { key: 'main', - title: swagger.title || 'Swagger接口文档', + 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; diff --git a/zyplayer-doc-ui/swagger-ui/src/assets/utils/logUtil.js b/zyplayer-doc-ui/swagger-ui/src/assets/utils/logUtil.js new file mode 100644 index 00000000..091ae0bb --- /dev/null +++ b/zyplayer-doc-ui/swagger-ui/src/assets/utils/logUtil.js @@ -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); + } +} diff --git a/zyplayer-doc-ui/swagger-ui/src/components/layouts/MenuLayout.vue b/zyplayer-doc-ui/swagger-ui/src/components/layouts/MenuLayout.vue index e24cb9a5..91fe641d 100644 --- a/zyplayer-doc-ui/swagger-ui/src/components/layouts/MenuLayout.vue +++ b/zyplayer-doc-ui/swagger-ui/src/components/layouts/MenuLayout.vue @@ -36,7 +36,7 @@