使用vitejs+vue3+antdv重构swagger文档展示

This commit is contained in:
暮光:城中城
2021-10-17 19:50:22 +08:00
parent 28bcbfd379
commit 9267aed477
72 changed files with 4236 additions and 3 deletions

View File

@@ -0,0 +1,129 @@
package com.zyplayer.doc.swaggerplus.controller;
import com.alibaba.fastjson.JSON;
import com.zyplayer.doc.core.annotation.AuthMan;
import com.zyplayer.doc.core.json.DocResponseJson;
import com.zyplayer.doc.core.json.ResponseJson;
import com.zyplayer.doc.data.config.security.DocUserDetails;
import com.zyplayer.doc.data.config.security.DocUserUtil;
import com.zyplayer.doc.data.repository.manage.entity.SwaggerDoc;
import com.zyplayer.doc.data.service.manage.SwaggerDocService;
import com.zyplayer.doc.swaggerplus.framework.utils.SwaggerDocUtil;
import com.zyplayer.doc.swaggerplus.service.SwaggerHttpRequestService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.swagger.web.SwaggerResource;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.Objects;
/**
* 文档控制器
*
* @author 暮光:城中城
* @since 2021年10月16日
*/
@AuthMan
@RestController
@RequestMapping("/doc-swagger/doc")
public class SwaggerDocumentController {
private static Logger logger = LoggerFactory.getLogger(SwaggerDocumentController.class);
@Resource
private SwaggerDocService swaggerDocService;
@Resource
private SwaggerHttpRequestService swaggerHttpRequestService;
/**
* 获取所有的文档地址
*
* @return 文档内容
* @author 暮光:城中城
* @since 2021年10月16日
*/
@ResponseBody
@PostMapping(value = "/list")
public ResponseJson<List<SwaggerDoc>> list() {
List<SwaggerDoc> docList = swaggerDocService.getSwaggerDocList();
return DocResponseJson.ok(docList);
}
/**
* 添加文档
*
* @return 文档内容
* @author 暮光:城中城
* @since 2021年10月16日
*/
@ResponseBody
@PostMapping(value = "/add")
public ResponseJson<List<SwaggerDoc>> add(HttpServletRequest request, SwaggerDoc swaggerDoc) {
DocUserDetails currentUser = DocUserUtil.getCurrentUser();
swaggerDoc.setYn(1);
swaggerDoc.setCreateTime(new Date());
swaggerDoc.setCreateUserId(currentUser.getUserId());
swaggerDoc.setCreateUserName(currentUser.getUsername());
// url类型
if (Objects.equals(swaggerDoc.getDocType(), 1)) {
// UI地址替换为文档json地址
String docUrl = SwaggerDocUtil.replaceSwaggerResources(swaggerDoc.getDocUrl());
if (SwaggerDocUtil.isSwaggerResources(docUrl)) {
String resourcesStr = swaggerHttpRequestService.requestUrl(request, docUrl);
List<SwaggerResource> resourceList = JSON.parseArray(resourcesStr, SwaggerResource.class);
if (resourceList == null || resourceList.isEmpty()) {
return DocResponseJson.warn("该地址未找到文档");
}
// 存明细地址
for (SwaggerResource resource : resourceList) {
swaggerDoc.setId(null);
swaggerDoc.setDocUrl(resource.getUrl());
swaggerDoc.setName(resource.getName());
swaggerDocService.save(swaggerDoc);
}
} else if (SwaggerDocUtil.isSwaggerLocation(docUrl)) {
swaggerDocService.save(swaggerDoc);
} else {
return DocResponseJson.warn("不支持的地址:" + docUrl);
}
} else {
swaggerDocService.saveOrUpdate(swaggerDoc);
}
return DocResponseJson.ok();
}
/**
* 修改文档信息
*
* @return 无
* @author 暮光:城中城
* @since 2021年10月16日
*/
@ResponseBody
@PostMapping(value = "/update")
public ResponseJson<List<SwaggerDoc>> update(SwaggerDoc swaggerDoc) {
swaggerDocService.saveOrUpdate(swaggerDoc);
return DocResponseJson.ok();
}
/**
* 获取文档内容
*
* @return 文档内容
* @author 暮光:城中城
* @since 2021年10月16日
*/
@ResponseBody
@PostMapping(value = "/content")
public ResponseJson<List<SwaggerDoc>> content(HttpServletRequest request, String docUrl) {
String contentStr = swaggerHttpRequestService.requestUrl(request, docUrl);
return DocResponseJson.ok(contentStr);
}
}

View File

@@ -0,0 +1,76 @@
package com.zyplayer.doc.swaggerplus.controller;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zyplayer.doc.core.annotation.AuthMan;
import com.zyplayer.doc.core.json.DocResponseJson;
import com.zyplayer.doc.core.json.ResponseJson;
import com.zyplayer.doc.data.repository.manage.entity.SwaggerDoc;
import com.zyplayer.doc.data.repository.manage.entity.SwaggerGlobalParam;
import com.zyplayer.doc.data.service.manage.SwaggerGlobalParamService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 全局参数控制器
*
* @author 暮光:城中城
* @since 2021年10月16日
*/
@AuthMan
@RestController
@RequestMapping("/doc-swagger/global-param")
public class SwaggerGlobalParamController {
private static Logger logger = LoggerFactory.getLogger(SwaggerGlobalParamController.class);
@Resource
private SwaggerGlobalParamService swaggerGlobalParamService;
/**
* 获取所有的全局参数
*
* @return 全局参数列表
* @author 暮光:城中城
* @since 2021年10月16日
*/
@ResponseBody
@PostMapping(value = "/list")
public ResponseJson<List<SwaggerGlobalParam>> list() {
QueryWrapper<SwaggerGlobalParam> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("yn", 1);
List<SwaggerGlobalParam> globalParamList = swaggerGlobalParamService.list(queryWrapper);
return DocResponseJson.ok(globalParamList);
}
/**
* 修改全局参数
*
* @return 无
* @author 暮光:城中城
* @since 2021年10月16日
*/
@ResponseBody
@PostMapping(value = "/update")
public ResponseJson<List<SwaggerDoc>> update(String globalParam) {
List<SwaggerGlobalParam> newParamList = JSON.parseArray(globalParam, SwaggerGlobalParam.class);
QueryWrapper<SwaggerGlobalParam> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("yn", 1);
List<SwaggerGlobalParam> queryParamList = swaggerGlobalParamService.list(queryWrapper);
List<Long> newIdList = newParamList.stream().map(SwaggerGlobalParam::getId).filter(Objects::nonNull).collect(Collectors.toList());
List<Long> deletedList = queryParamList.stream().map(SwaggerGlobalParam::getId).filter(id -> !newIdList.contains(id)).collect(Collectors.toList());
// 删除不存在的
swaggerGlobalParamService.removeByIds(deletedList);
// 保存或更新的
swaggerGlobalParamService.saveOrUpdateBatch(newParamList);
return DocResponseJson.ok();
}
}

View File

@@ -0,0 +1,63 @@
package com.zyplayer.doc.swaggerplus.controller;
import com.zyplayer.doc.core.annotation.AuthMan;
import com.zyplayer.doc.data.repository.manage.entity.SwaggerDoc;
import com.zyplayer.doc.data.service.manage.SwaggerDocService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.swagger.web.ApiKeyVehicle;
import springfox.documentation.swagger.web.SecurityConfiguration;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.UiConfiguration;
import javax.annotation.Resource;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
* 承接了所有的ApiResourceController的接口
*
* @author 暮光:城中城
* @since 2021年10月16日
*/
@AuthMan
@RestController
public class SwaggerProxyController {
@Resource
private SwaggerDocService swaggerDocService;
@RequestMapping("/swagger-resources")
public List<SwaggerResource> swaggerResources() {
Set<SwaggerResource> resourceList = new HashSet<>();
List<SwaggerDoc> docList = swaggerDocService.getSwaggerDocList();
for (SwaggerDoc swaggerDoc : docList) {
SwaggerResource resource = new SwaggerResource();
resource.setLocation(swaggerDoc.getDocUrl());
resource.setName(swaggerDoc.getName());
resource.setSwaggerVersion("2.0");
resourceList.add(resource);
}
return new LinkedList<>(resourceList);
}
@ResponseBody
@RequestMapping(value = "/swagger-resources/configuration/security")
public ResponseEntity<SecurityConfiguration> securityConfiguration() {
SecurityConfiguration securityConfiguration = new SecurityConfiguration(null, null, null, null, null, ApiKeyVehicle.HEADER, "api_key", ",");
return new ResponseEntity<>(securityConfiguration, HttpStatus.OK);
}
@ResponseBody
@RequestMapping(value = "/swagger-resources/configuration/ui")
public ResponseEntity<UiConfiguration> uiConfiguration() {
UiConfiguration uiConfiguration = new UiConfiguration(null);
return new ResponseEntity<>(uiConfiguration, HttpStatus.OK);
}
}

View File

@@ -0,0 +1,75 @@
package com.zyplayer.doc.swaggerplus.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zyplayer.doc.core.annotation.AuthMan;
import com.zyplayer.doc.core.json.DocResponseJson;
import com.zyplayer.doc.core.json.ResponseJson;
import com.zyplayer.doc.data.config.security.DocUserDetails;
import com.zyplayer.doc.data.config.security.DocUserUtil;
import com.zyplayer.doc.data.repository.manage.entity.SwaggerDoc;
import com.zyplayer.doc.data.repository.manage.entity.SwaggerRequestParam;
import com.zyplayer.doc.data.service.manage.SwaggerRequestParamService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
/**
* 请求参数控制器
*
* @author 暮光:城中城
* @since 2021年10月16日
*/
@AuthMan
@RestController
@RequestMapping("/doc-swagger/request-param")
public class SwaggerRequestParamController {
private static Logger logger = LoggerFactory.getLogger(SwaggerRequestParamController.class);
@Resource
private SwaggerRequestParamService swaggerRequestParamService;
/**
* 获取所有的请求参数
*
* @return 请求参数
* @author 暮光:城中城
* @since 2021年10月16日
*/
@ResponseBody
@PostMapping(value = "/query")
public ResponseJson<SwaggerRequestParam> query(String docUrl) {
QueryWrapper<SwaggerRequestParam> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("yn", 1);
queryWrapper.eq("doc_url", docUrl);
SwaggerRequestParam requestParam = swaggerRequestParamService.getOne(queryWrapper);
return DocResponseJson.ok(requestParam);
}
/**
* 修改请求参数
*
* @return 无
* @author 暮光:城中城
* @since 2021年10月16日
*/
@ResponseBody
@PostMapping(value = "/update")
public ResponseJson<List<SwaggerDoc>> update(SwaggerRequestParam swaggerRequestParam) {
QueryWrapper<SwaggerRequestParam> updateWrapper = new QueryWrapper<>();
updateWrapper.eq("doc_url", swaggerRequestParam.getDocUrl());
DocUserDetails currentUser = DocUserUtil.getCurrentUser();
swaggerRequestParam.setYn(1);
swaggerRequestParam.setCreateTime(new Date());
swaggerRequestParam.setCreateUserId(currentUser.getUserId());
swaggerRequestParam.setCreateUserName(currentUser.getUsername());
swaggerRequestParamService.update(swaggerRequestParam, updateWrapper);
return DocResponseJson.ok();
}
}

View File

@@ -0,0 +1,17 @@
package com.zyplayer.doc.swaggerplus.framework.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@ComponentScan(basePackages = {
"com.zyplayer.doc.swagger",
})
public @interface EnableDocSwaggerPlus {
}

View File

@@ -0,0 +1,21 @@
package com.zyplayer.doc.swaggerplus.framework.utils;
public class SwaggerDocUtil {
public static String replaceSwaggerResources(String docUrl) {
int htmlIndex = docUrl.indexOf("/swagger-ui.html");
if (htmlIndex > 0) {
docUrl = docUrl.substring(0, htmlIndex) + "/swagger-resources";
}
return docUrl;
}
public static boolean isSwaggerResources(String docUrl) {
return docUrl.contains("/swagger-resources");
}
public static boolean isSwaggerLocation(String docUrl) {
return docUrl.contains("/v2/api-docs");
}
}

View File

@@ -0,0 +1,52 @@
package com.zyplayer.doc.swaggerplus.service;
import cn.hutool.http.HttpRequest;
import com.zyplayer.doc.data.repository.manage.entity.SwaggerGlobalParam;
import com.zyplayer.doc.data.service.manage.SwaggerGlobalParamService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.net.HttpCookie;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
@Service
public class SwaggerHttpRequestService {
@Resource
private SwaggerGlobalParamService swaggerGlobalParamService;
public String requestUrl(HttpServletRequest request, String docUrl) {
List<SwaggerGlobalParam> globalParamList = swaggerGlobalParamService.getGlobalParamList();
Map<String, Object> globalFormParamMap = globalParamList.stream().filter(item -> Objects.equals(item.getParamType(), 1))
.collect(Collectors.toMap(SwaggerGlobalParam::getParamKey, SwaggerGlobalParam::getParamValue));
Map<String, String> globalHeaderParamMap = globalParamList.stream().filter(item -> Objects.equals(item.getParamType(), 2))
.collect(Collectors.toMap(SwaggerGlobalParam::getParamKey, SwaggerGlobalParam::getParamValue));
String resultStr = HttpRequest.get(docUrl)
.form(globalFormParamMap)
.header("Accept", "application/json, text/javascript, */*; q=0.01")
.header("User-Agent", request.getHeader("User-Agent"))
.addHeaders(globalHeaderParamMap)
.cookie(this.getHttpCookie(request))
.timeout(5000).execute().body();
return resultStr;
}
private List<HttpCookie> getHttpCookie(HttpServletRequest request) {
List<HttpCookie> httpCookies = new LinkedList<>();
for (Cookie cookie : request.getCookies()) {
HttpCookie httpCookie = new HttpCookie(cookie.getName(), cookie.getValue());
httpCookie.setDomain(cookie.getDomain());
httpCookie.setPath(cookie.getPath());
httpCookie.setMaxAge(cookie.getMaxAge());
httpCookies.add(httpCookie);
}
return httpCookies;
}
}

View File

@@ -0,0 +1,45 @@
CREATE TABLE `swagger_doc` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键自增ID',
`name` varchar(100) DEFAULT NULL COMMENT '文档名称',
`doc_type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '文档类型 1=url 2=swagger文档json',
`doc_url` varchar(250) DEFAULT NULL COMMENT '文档URL地址',
`json_content` text DEFAULT NULL COMMENT 'swagger文档json内容',
`rewrite_domain` varchar(100) DEFAULT NULL COMMENT '重写的域名',
`open_visit` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否开放访问 0=否 1=是',
`doc_status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '状态 1=启用 2=禁用',
`create_user_id` bigint(20) DEFAULT NULL COMMENT '创建人ID',
`create_user_name` varchar(20) DEFAULT NULL COMMENT '创建人名字',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`yn` tinyint(4) DEFAULT NULL COMMENT '是否有效 0=无效 1=有效',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='swagger文档地址';
CREATE TABLE `swagger_request_param` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键自增ID',
`doc_url` varchar(250) DEFAULT NULL COMMENT '文档url',
`form_data` text DEFAULT NULL COMMENT 'form参数',
`body_data` text DEFAULT NULL COMMENT 'body参数',
`header_data` varchar(1024) DEFAULT NULL COMMENT 'header参数',
`cookie_data` varchar(1024) DEFAULT NULL COMMENT 'cookie参数',
`create_user_id` bigint(20) DEFAULT NULL COMMENT '创建人ID',
`create_user_name` varchar(20) DEFAULT NULL COMMENT '创建人名字',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`yn` tinyint(4) DEFAULT NULL COMMENT '是否有效 0=无效 1=有效',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='swagger文档请求参数记录';
CREATE TABLE `swagger_global_param` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键自增ID',
`param_type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '参数类型 1=form 2=header 3=cookie',
`param_key` varchar(100) DEFAULT NULL COMMENT '参数名',
`param_value` varchar(1024) DEFAULT NULL COMMENT '参数值',
`create_user_id` bigint(20) DEFAULT NULL COMMENT '创建人ID',
`create_user_name` varchar(20) DEFAULT NULL COMMENT '创建人名字',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`yn` tinyint(4) DEFAULT NULL COMMENT '是否有效 0=无效 1=有效',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='swagger文档全局参数记录';

View File

@@ -0,0 +1 @@
import{b as o,o as e}from"./vendor.0502eb24.js";const t={name:"About",components:{},data:()=>({}),computed:{},mounted(){},methods:{}};t.render=function(t,n,d,r,a,m){return e(),o("div",null," 控制台 ")};export{t as default};

View File

@@ -0,0 +1 @@
import{r as e,c as a,w as t,o,a as s}from"./vendor.0502eb24.js";const c={name:"About",components:{},data:()=>({activePage:"doc"}),computed:{},mounted(){let e=this.$route.query.path,a=this.$store.state.docMap[e];a?this.$store.commit("addTableName",{key:this.$route.fullPath,val:a.name}):this.$message.error("没有找到对应的文档")},methods:{changePage(){}}};c.render=function(c,n,d,i,r,l){const m=e("a-tab-pane"),u=e("a-tabs");return o(),a(u,{activeKey:r.activePage,"onUpdate:activeKey":n[0]||(n[0]=e=>r.activePage=e),closable:"",onTabClick:l.changePage,style:{padding:"5px 10px 0"}},{default:t((()=>[s(m,{tab:"接口说明",key:"doc"}),s(m,{tab:"在线调试",key:"debug"})])),_:1},8,["activeKey","onTabClick"])};export{c as default};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{b as e,o as t}from"./vendor.0502eb24.js";const n={name:"SettingView",components:{},data:()=>({}),computed:{},mounted(){},methods:{}};n.render=function(n,o,d,r,a,m){return t(),e("div",null," 展示配置页面 ")};export{n as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="logo.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>swagger文档管理</title>
<script type="module" crossorigin src="assets/main.95be7151.js"></script>
<link rel="modulepreload" href="assets/vendor.0502eb24.js">
<link rel="stylesheet" href="assets/style.1a9128b7.css">
</head>
<body>
<div id="app"></div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB