diff --git a/zyplayer-doc-data/src/main/java/com/zyplayer/doc/data/service/manage/impl/SwaggerDocServiceImpl.java b/zyplayer-doc-data/src/main/java/com/zyplayer/doc/data/service/manage/impl/SwaggerDocServiceImpl.java index 9ec49346..428471f8 100644 --- a/zyplayer-doc-data/src/main/java/com/zyplayer/doc/data/service/manage/impl/SwaggerDocServiceImpl.java +++ b/zyplayer-doc-data/src/main/java/com/zyplayer/doc/data/service/manage/impl/SwaggerDocServiceImpl.java @@ -27,6 +27,7 @@ public class SwaggerDocServiceImpl extends ServiceImpl swaggerResources() { - Set resourceList = new HashSet<>(); + List resourceList = new LinkedList<>(); List docList = swaggerDocService.getSwaggerDocList(new SwaggerDoc()); for (SwaggerDoc swaggerDoc : docList) { SwaggerResource resource = new SwaggerResource(); - resource.setUrl("/doc-swagger/doc/content?id=" + swaggerDoc.getId()); + resource.setUrl("/v2/api-docs?id=" + swaggerDoc.getId()); resource.setName(swaggerDoc.getName()); resource.setSwaggerVersion("2.0"); resourceList.add(resource); } - return new LinkedList<>(resourceList); + return resourceList; + } + + @ResponseBody + @RequestMapping(value = "/v2/api-docs", produces = {MimeTypeUtils.APPLICATION_JSON_VALUE, HAL_MEDIA_TYPE}) + public ResponseEntity content(HttpServletRequest request, Long id) { + SwaggerDoc swaggerDoc = swaggerDocService.getById(id); + if (swaggerDoc == null) { + throw new ConfirmException("文档不存在"); + } + if (Objects.equals(swaggerDoc.getDocType(), 1)) { + String contentStr = swaggerHttpRequestService.requestUrl(request, swaggerDoc.getDocUrl()); + return new ResponseEntity<>(new Json(contentStr), HttpStatus.OK); + } + return new ResponseEntity<>(new Json(swaggerDoc.getJsonContent()), HttpStatus.OK); } @ResponseBody diff --git a/zyplayer-doc-swagger-plus/src/main/java/com/zyplayer/doc/swaggerplus/framework/utils/SwaggerDocUtil.java b/zyplayer-doc-swagger-plus/src/main/java/com/zyplayer/doc/swaggerplus/framework/utils/SwaggerDocUtil.java index eddb17fc..b21b4214 100644 --- a/zyplayer-doc-swagger-plus/src/main/java/com/zyplayer/doc/swaggerplus/framework/utils/SwaggerDocUtil.java +++ b/zyplayer-doc-swagger-plus/src/main/java/com/zyplayer/doc/swaggerplus/framework/utils/SwaggerDocUtil.java @@ -14,6 +14,14 @@ public class SwaggerDocUtil { return docUrl.contains("/swagger-resources"); } + public static String getSwaggerResourceDomain(String docUrl) { + int index = docUrl.indexOf("/swagger-resources"); + if (index >= 0) { + return docUrl.substring(0, index); + } + return ""; + } + public static boolean isSwaggerLocation(String docUrl) { return docUrl.contains("/v2/api-docs"); } diff --git a/zyplayer-doc-ui/swagger-ui/src/api/custom.js b/zyplayer-doc-ui/swagger-ui/src/api/custom.js index b8915b4d..06ef27ed 100644 --- a/zyplayer-doc-ui/swagger-ui/src/api/custom.js +++ b/zyplayer-doc-ui/swagger-ui/src/api/custom.js @@ -1,6 +1,7 @@ import apiClient from './request/custom.js' export const customApi = { + get: (url, data) => apiClient({url: url, method: 'get', data: data}), post: (url, data) => apiClient({url: url, method: 'post', data: data}), }; diff --git a/zyplayer-doc-ui/swagger-ui/src/api/request/custom.js b/zyplayer-doc-ui/swagger-ui/src/api/request/custom.js index 0110608e..e8f8d262 100644 --- a/zyplayer-doc-ui/swagger-ui/src/api/request/custom.js +++ b/zyplayer-doc-ui/swagger-ui/src/api/request/custom.js @@ -1,5 +1,5 @@ import Axios from 'axios' -import interceptors from './interceptors' +import interceptors from './interceptorsCustom' import {getCustomApiBaseUrl} from "./utils"; const apiClient = Axios.create({ diff --git a/zyplayer-doc-ui/swagger-ui/src/api/request/interceptors.js b/zyplayer-doc-ui/swagger-ui/src/api/request/interceptors.js index a6055359..7e18c7bf 100644 --- a/zyplayer-doc-ui/swagger-ui/src/api/request/interceptors.js +++ b/zyplayer-doc-ui/swagger-ui/src/api/request/interceptors.js @@ -5,7 +5,7 @@ import {getZyplayerApiBaseUrl} from "./utils"; // 增加不需要验证结果的标记 const noValidate = { "./swagger-resources": true, - "/zyplayer-doc-db/datasource/test": true, + "/v2/api-docs": true, }; export default function (axios) { diff --git a/zyplayer-doc-ui/swagger-ui/src/api/request/interceptorsCustom.js b/zyplayer-doc-ui/swagger-ui/src/api/request/interceptorsCustom.js new file mode 100644 index 00000000..197f2165 --- /dev/null +++ b/zyplayer-doc-ui/swagger-ui/src/api/request/interceptorsCustom.js @@ -0,0 +1,41 @@ +import qs from 'qs' +import { message } from 'ant-design-vue'; + +export default function (axios) { + axios.interceptors.request.use( + config => { + if (config.method === 'get') { + config.params = config.params || {}; + config.params = {...config.params, _: (new Date()).getTime()} + } else if (config.method === 'post') { + config.data = config.data || {}; + if (config.data instanceof FormData) { + // 表单,无需特殊处理 + } else if (config.data instanceof Object) { + config.data = qs.stringify(config.data); + } + } + return config; + }, + error => { + console.log(error); + return Promise.reject(error); + } + ); + axios.interceptors.response.use( + response => { + if (!!response.message) { + vue.$message.error('请求错误:' + response.message); + } else { + return response.data; + } + return Promise.reject('请求错误'); + }, + error => { + console.log('err' + error); + message.error('请求错误:' + error.message); + return Promise.reject(error) + } + ); +} + diff --git a/zyplayer-doc-ui/swagger-ui/src/components/layouts/GlobalLayout.vue b/zyplayer-doc-ui/swagger-ui/src/components/layouts/GlobalLayout.vue index 9268c4cc..a4b3e235 100644 --- a/zyplayer-doc-ui/swagger-ui/src/components/layouts/GlobalLayout.vue +++ b/zyplayer-doc-ui/swagger-ui/src/components/layouts/GlobalLayout.vue @@ -3,7 +3,7 @@ @@ -13,13 +13,10 @@ - + - - 当前环境:灰度 - @@ -46,14 +43,10 @@ return { minHeight: minHeight + 'px', appMenuCollapsed: false, - rightAsideWidth: 250 - } - }, - computed: { - initialEnv () { - return this.$store.state.initialEnv; + rightAsideWidth: 300 } }, + computed: {}, mounted() { this.dragChangeRightAsideWidth(); }, diff --git a/zyplayer-doc-ui/swagger-ui/src/components/layouts/MenuChildrenLayout.vue b/zyplayer-doc-ui/swagger-ui/src/components/layouts/MenuChildrenLayout.vue index b30d7fc0..6150b928 100644 --- a/zyplayer-doc-ui/swagger-ui/src/components/layouts/MenuChildrenLayout.vue +++ b/zyplayer-doc-ui/swagger-ui/src/components/layouts/MenuChildrenLayout.vue @@ -17,6 +17,7 @@ {{menuItem.name}} @@ -30,7 +31,8 @@ SettingOutlined, CarryOutOutlined, FileTextOutlined, - DashboardOutlined + DashboardOutlined, + InfoCircleOutlined, } from '@ant-design/icons-vue'; export default { @@ -43,7 +45,7 @@ }, components: { StarOutlined, SettingOutlined, CarryOutOutlined, FileTextOutlined, - DashboardOutlined + DashboardOutlined, InfoCircleOutlined }, methods: { haveShowChildren(children) { 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 45c460ca..f94eb9a1 100644 --- a/zyplayer-doc-ui/swagger-ui/src/components/layouts/MenuLayout.vue +++ b/zyplayer-doc-ui/swagger-ui/src/components/layouts/MenuLayout.vue @@ -4,13 +4,27 @@ -
+
- + {{item.name}}
- + + +
@@ -18,6 +32,7 @@ + diff --git a/zyplayer-doc-ui/swagger-ui/src/routes.js b/zyplayer-doc-ui/swagger-ui/src/routes.js index d25c7514..c92b50a1 100644 --- a/zyplayer-doc-ui/swagger-ui/src/routes.js +++ b/zyplayer-doc-ui/swagger-ui/src/routes.js @@ -21,6 +21,14 @@ let routers = [ }, component: () => import('./views/common/Console.vue') }, + { + path: '/doc/info', + name: '文档信息', + meta: { + icon: 'InfoCircleOutlined', + }, + component: () => import('./views/doc/DocInfo.vue') + }, { path: '/doc/manage', name: '文档管理', diff --git a/zyplayer-doc-ui/swagger-ui/src/store/SwaggerDocUtil.js b/zyplayer-doc-ui/swagger-ui/src/store/SwaggerDocUtil.js new file mode 100644 index 00000000..6ef08f49 --- /dev/null +++ b/zyplayer-doc-ui/swagger-ui/src/store/SwaggerDocUtil.js @@ -0,0 +1,144 @@ +export function getDefinitions(definitions) { + if (!definitions) { + return {}; + } + let swaggerDefinitions = {}; + Object.keys(definitions).forEach((key) => { + swaggerDefinitions["#/definitions/" + key] = definitions[key]; + }); + return swaggerDefinitions; +} + +export function createTreeViewByTag(swagger, keywords) { + let pathIndex = {}, treePathDataMap = {}; + let paths = swagger.paths; + let domain = swagger.domainUrl;// 服务器代理会返回此属性 + let rewriteDomainUrl = swagger.rewriteDomainUrl;// 服务器代理会返回此属性 + if (!paths) { + return; + } + if (!domain) { + domain = "http://" + swagger.host + swagger.basePath; + } + if (domain.substring(domain.length - 1) === "/") { + domain = domain.substring(0, domain.length - 1); + } + //console.log(paths); + Object.keys(paths).forEach(key => { + //console.log(key, paths[key]); + setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "get", treePathDataMap); + setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "head", treePathDataMap); + setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "post", treePathDataMap); + setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "put", treePathDataMap); + setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "patch", treePathDataMap); + setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "delete", treePathDataMap); + setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "options", treePathDataMap); + setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "trace", treePathDataMap); + }); + // console.log(pathIndex); + // console.log(treePathDataMap); + // console.log(treeData); + return {pathIndex: pathIndex, treePathDataMap: treePathDataMap}; +} + +/** + * 设置对象的各种请求方式,存在则复制 + * @param source 资源,原始json的paths的指定对象 + * @param pathObj 当前的待赋值对象 + * @param url url绝对路径 + * @param method 请求方式,post、get... + * @returns + */ +function setRequestMethodForTag(rewriteDomainUrl, domain, source, pathObj, url, method, treePathDataMap) { + if (!source[method] || !source[method].tags) { + return; + } + source[method].tags.forEach(function(val, index) { + let tempObj = pathObj[val]; + if(!tempObj) { + tempObj = pathObj[val] = {}; + } + let tempUrlObj = tempObj[url]; + if(!tempUrlObj) { + tempUrlObj = tempObj[url] = {}; + } + let tempPath = url + "." + method; + tempUrlObj[method] = source[method]; + tempUrlObj[method].path = tempPath; + tempUrlObj[method].url = url; + tempUrlObj[method].method = method; + tempUrlObj[method].domain = domain; + tempUrlObj[method].rewriteDomainUrl = rewriteDomainUrl; + treePathDataMap[tempPath] = source[method]; + }); +} + +export function getTreeDataForTag(swagger, pathData, metaInfo) { + return [ + { + title: swagger.title || 'Swagger接口文档', + key: '0-0', + children: getTreeHtmlForTag(pathData, 0, metaInfo) + } + ]; +} + +function getTreeHtmlForTag(pathData, treeId, metaInfo) { + let treeData = []; + let indexNow = 1; + // get, head, post, put, patch, delete, options, trace + let actionArrays = ["get", "head", "post", "put", "patch", "delete", "options", "trace"]; + Object.keys(pathData).forEach(key => { + let tempNode = pathData[key]; + let tempTreeId = treeId + "_" + indexNow; + // 只有一个子元素,而且有method元素,说明是只有一个节点 + let nodeSub = getObjectFirstAttributeIfOnly(tempNode); + if (nodeSub && nodeSub.method) { + nodeSub.treeId = tempTreeId; + let title = nodeSub.summary || nodeSub.path; + treeData.push({ + title: title, + key: tempTreeId, + isLeaf: true, + method: nodeSub.method, + query: { + path: nodeSub.path, + ...metaInfo + } + }); + } else if (actionArrays.indexOf(key) >= 0) { + tempNode.treeId = tempTreeId; + let title = tempNode.summary || tempNode.path; + treeData.push({ + title: title, + key: tempTreeId, + isLeaf: true, + method: tempNode.method, + query: { + path: tempNode.path, + ...metaInfo + } + }); + } else { + treeData.push({title: key, key: key, children: getTreeHtmlForTag(tempNode, tempTreeId, metaInfo)}); + } + indexNow++; + }); + return treeData; +} + +/** + * 如果对象只有一个属性则返回第一个属性,否则返回null + * @param data + * @returns + */ +function getObjectFirstAttributeIfOnly(data) { + let len = 0, value = ""; + for (let key in data) { + if (++len > 1) { + return undefined; + } + value = data[key]; + } + return value; +} diff --git a/zyplayer-doc-ui/swagger-ui/src/store/index.js b/zyplayer-doc-ui/swagger-ui/src/store/index.js index 9ab2ac94..59058d47 100644 --- a/zyplayer-doc-ui/swagger-ui/src/store/index.js +++ b/zyplayer-doc-ui/swagger-ui/src/store/index.js @@ -1,4 +1,5 @@ import {createStore} from 'vuex' +import {getDefinitions, createTreeViewByTag} from './SwaggerDocUtil' export default createStore({ state() { @@ -16,12 +17,22 @@ export default createStore({ name: '修改用户信息' }, }, + swaggerDoc: {}, + swaggerDefinitions: {}, + swaggerTreePathMap: [], } }, mutations: { setUserInfo(state, userInfo) { state.userInfo = userInfo; }, + setSwaggerDoc(state, swaggerDoc) { + state.swaggerDoc = swaggerDoc; + state.swaggerDefinitions = getDefinitions(swaggerDoc.definitions); + }, + setSwaggerTreePathMap(state, swaggerTreePathMap) { + state.swaggerTreePathMap = swaggerTreePathMap; + }, addTableName(state, item) { let sameObj = Object.assign({}, state.pageTabNameMap); sameObj[item.key] = item.val; diff --git a/zyplayer-doc-ui/swagger-ui/src/views/common/Console.vue b/zyplayer-doc-ui/swagger-ui/src/views/common/Console.vue index bb681402..e44fc938 100644 --- a/zyplayer-doc-ui/swagger-ui/src/views/common/Console.vue +++ b/zyplayer-doc-ui/swagger-ui/src/views/common/Console.vue @@ -1,6 +1,6 @@ @@ -11,7 +11,11 @@ data() { return {} }, - computed: {}, + computed: { + swaggerDoc () { + return this.$store.state.swaggerDoc; + } + }, mounted() { }, methods: {} diff --git a/zyplayer-doc-ui/swagger-ui/src/views/doc/DocInfo.vue b/zyplayer-doc-ui/swagger-ui/src/views/doc/DocInfo.vue new file mode 100644 index 00000000..6ed49b5d --- /dev/null +++ b/zyplayer-doc-ui/swagger-ui/src/views/doc/DocInfo.vue @@ -0,0 +1,40 @@ + + + diff --git a/zyplayer-doc-ui/swagger-ui/src/views/doc/DocManage.vue b/zyplayer-doc-ui/swagger-ui/src/views/doc/DocManage.vue index b8cedd5f..2606c4d9 100644 --- a/zyplayer-doc-ui/swagger-ui/src/views/doc/DocManage.vue +++ b/zyplayer-doc-ui/swagger-ui/src/views/doc/DocManage.vue @@ -29,11 +29,13 @@ + :scroll="{ x: 1400, y: 'calc(100vh - 340px)' }">