Compare commits
2 Commits
6fea7b1099
...
7c7f838082
| Author | SHA1 | Date |
|---|---|---|
|
|
7c7f838082 | |
|
|
0ed30a1c65 |
|
|
@ -1,192 +0,0 @@
|
|||
package com.syjiaer.clinic.server;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.*;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
|
||||
public class BulidApi {
|
||||
public static void main(String[] args) {
|
||||
List<ApiInfo> apiPaths = scanControllersWithDocs("com.syjiaer.clinic.server");
|
||||
Map<String, Object> nestedJson = convertToNestedJson(apiPaths);
|
||||
generateAPITsFile(apiPaths, "D:\\API.ts");
|
||||
}
|
||||
|
||||
private static String cleanPath(String originalPath) {
|
||||
// 1. 移除路径参数
|
||||
String pathWithoutParams = originalPath.replaceAll("/\\{[^/]+}", "");
|
||||
|
||||
// 2. 分割路径并只保留前三级
|
||||
String[] parts = pathWithoutParams.replaceAll("^/|/$", "").split("/");
|
||||
if (parts.length > 3) {
|
||||
return String.join("/", Arrays.copyOfRange(parts, 0, 3));
|
||||
}
|
||||
|
||||
return pathWithoutParams;
|
||||
}
|
||||
|
||||
private static void generateNamespace(StringBuilder builder, Map<String, Object> map, int indentLevel) {
|
||||
String indent = " ".repeat(indentLevel);
|
||||
|
||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
|
||||
if (value instanceof Map) {
|
||||
// 处理嵌套命名空间
|
||||
builder.append(indent).append("export namespace ").append(capitalize(key)).append(" {\n");
|
||||
generateNamespace(builder, (Map<String, Object>) value, indentLevel + 1);
|
||||
builder.append(indent).append("}\n\n");
|
||||
} else if (value instanceof ApiInfo) {
|
||||
// 处理API端点
|
||||
ApiInfo apiInfo = (ApiInfo) value;
|
||||
String path = apiInfo.getPath().replaceAll("^/|/$", "");
|
||||
String comment = apiInfo.getComment().isEmpty() ? "" : "//" + apiInfo.getComment();
|
||||
|
||||
builder.append(indent).append("export const ")
|
||||
.append(capitalize(key)).append(" = '")
|
||||
.append(path).append("'")
|
||||
.append(comment).append(";\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String capitalize(String str) {
|
||||
if (str == null || str.isEmpty()) {
|
||||
return str;
|
||||
}
|
||||
return str.substring(0, 1).toUpperCase() + str.substring(1);
|
||||
}
|
||||
public static void generateAPITsFile(List<ApiInfo> apiPaths, String outputPath) {
|
||||
Map<String, Object> nestedJson = convertToNestedJson(apiPaths);
|
||||
StringBuilder tsBuilder = new StringBuilder();
|
||||
tsBuilder.append("export namespace API {\n");
|
||||
|
||||
generateNamespace(tsBuilder, nestedJson, 1);
|
||||
|
||||
tsBuilder.append("}\n");
|
||||
|
||||
try (FileWriter fileWriter = new FileWriter(outputPath)) {
|
||||
fileWriter.write(tsBuilder.toString());
|
||||
System.out.println("成功写入 " + outputPath);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("文件写入失败", e);
|
||||
}
|
||||
}
|
||||
public static Map<String, Object> convertToNestedJson(List<ApiInfo> apiPaths) {
|
||||
Map<String, Object> root = new LinkedHashMap<>();
|
||||
|
||||
for (ApiInfo apiInfo : apiPaths) {
|
||||
String path = apiInfo.getPath();
|
||||
// 去除开头和结尾的斜杠,并按斜杠分割
|
||||
String[] parts = path.replaceAll("^/|/$", "").split("/");
|
||||
|
||||
Map<String, Object> currentLevel = root;
|
||||
// 处理路径的每一部分(除最后一部分)
|
||||
for (int i = 0; i < parts.length - 1; i++) {
|
||||
String part = parts[i];
|
||||
// 如果当前节点不是Map,说明是叶子节点,需要转换为Map
|
||||
if (!(currentLevel.get(part) instanceof Map)) {
|
||||
// 如果已有数据是ApiInfo,先保存到临时变量
|
||||
Object existingValue = currentLevel.get(part);
|
||||
currentLevel.put(part, new LinkedHashMap<String, Object>());
|
||||
if (existingValue != null) {
|
||||
// 将原有值放到特殊键下(如"_data")
|
||||
((Map<String, Object>) currentLevel.get(part)).put("_data", existingValue);
|
||||
}
|
||||
}
|
||||
currentLevel = (Map<String, Object>) currentLevel.get(part);
|
||||
}
|
||||
|
||||
// 最后一部分作为叶子节点
|
||||
String lastPart = parts[parts.length - 1];
|
||||
// 检查是否已经存在路径节点
|
||||
if (currentLevel.containsKey(lastPart) && currentLevel.get(lastPart) instanceof Map) {
|
||||
// 如果已经存在Map节点,将API信息放入特殊键
|
||||
((Map<String, Object>) currentLevel.get(lastPart)).put("_data", apiInfo);
|
||||
} else {
|
||||
currentLevel.put(lastPart, apiInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
public static List<ApiInfo> scanControllersWithDocs(String basePackage) {
|
||||
List<ApiInfo> apiInfos = new ArrayList<>();
|
||||
|
||||
ClassPathScanningCandidateComponentProvider scanner =
|
||||
new ClassPathScanningCandidateComponentProvider(false);
|
||||
scanner.addIncludeFilter(new AnnotationTypeFilter(Controller.class));
|
||||
scanner.addIncludeFilter(new AnnotationTypeFilter(RestController.class));
|
||||
|
||||
Set<BeanDefinition> beans = scanner.findCandidateComponents(basePackage);
|
||||
|
||||
try {
|
||||
for (BeanDefinition bean : beans) {
|
||||
Class<?> clazz = Class.forName(bean.getBeanClassName());
|
||||
|
||||
// 获取类注解
|
||||
RequestMapping classMapping = AnnotationUtils.findAnnotation(clazz, RequestMapping.class);
|
||||
String classPath = classMapping != null && classMapping.value().length > 0 ?
|
||||
classMapping.value()[0] : "";
|
||||
|
||||
// 扫描方法
|
||||
for (Method method : clazz.getMethods()) {
|
||||
RequestMapping methodMapping = AnnotationUtils.findAnnotation(method, RequestMapping.class);
|
||||
if (methodMapping != null) {
|
||||
String methodPath = methodMapping.value().length > 0 ?
|
||||
methodMapping.value()[0] : "";
|
||||
String fullPath = (classPath + "/" + methodPath).replaceAll("/+", "/");
|
||||
fullPath = cleanPath(fullPath);
|
||||
|
||||
// 获取方法注释
|
||||
String comment = getMethodComment(method);
|
||||
|
||||
apiInfos.add(new ApiInfo(fullPath, comment));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Controller扫描失败", e);
|
||||
}
|
||||
|
||||
return apiInfos;
|
||||
}
|
||||
|
||||
// 新增方法注释解析方法
|
||||
private static String getMethodComment(Method method) {
|
||||
// 1. 优先获取Swagger的ApiOperation注解
|
||||
ApiOperation apiOperation = AnnotationUtils.findAnnotation(method, ApiOperation.class);
|
||||
if (apiOperation != null) {
|
||||
return apiOperation.value();
|
||||
}
|
||||
|
||||
// 2. 次选JavaDoc注释(需额外实现)
|
||||
return ""; // 暂留空
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
// 新增返回数据结构
|
||||
public static class ApiInfo {
|
||||
private String path;
|
||||
private String comment;
|
||||
|
||||
|
||||
// 构造方法/getter/setter省略
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package com.syjiaer.clinic.server.common.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface ApiParam {
|
||||
String name();
|
||||
String value() default "";
|
||||
boolean required() default false;
|
||||
String comment() default "";
|
||||
Class<?> type() default Object.class;
|
||||
String typeName() default "";
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.syjiaer.clinic.server.common.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD})
|
||||
public @interface ApiParams {
|
||||
ApiParam[] value() default {} ;
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package com.syjiaer.clinic.server.common.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD})
|
||||
public @interface ApiReturn {
|
||||
boolean isArray() default false;
|
||||
boolean isPage() default false;
|
||||
Class<?> type() default Object.class;
|
||||
String name() default "";
|
||||
boolean isNull() default false;
|
||||
String typeName() default "";
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.syjiaer.clinic.server.common.doc;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.syjiaer.clinic.server.common.doc.entity.ApiInfo;
|
||||
import com.syjiaer.clinic.server.common.doc.util.ScanUtil;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
|
||||
public class BulidApi {
|
||||
public static void main(String[] args) {
|
||||
List<ApiInfo> apiPaths = ScanUtil.scanPackageToList("com.syjiaer.clinic.server.controller.charge");
|
||||
System.out.println(JSON.toJSONString(apiPaths));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package com.syjiaer.clinic.server.common.doc.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ApiInfo {
|
||||
private String path;
|
||||
private String comment;
|
||||
private List<Request> requests;
|
||||
private Response response;
|
||||
|
||||
@Data
|
||||
public static class BaseProperty {
|
||||
private String name;
|
||||
private String comment;
|
||||
private String type;
|
||||
private List<BaseProperty> children;
|
||||
}
|
||||
@Data
|
||||
public static class Request extends BaseProperty {
|
||||
// 原有结构保持不变
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Response extends BaseProperty {
|
||||
private Boolean isNull;
|
||||
private Boolean isArray;
|
||||
private Boolean isPage;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,287 @@
|
|||
package com.syjiaer.clinic.server.common.doc.util;
|
||||
|
||||
import com.syjiaer.clinic.server.common.doc.entity.ApiInfo;
|
||||
import com.syjiaer.clinic.server.common.annotations.ApiParam;
|
||||
import com.syjiaer.clinic.server.common.annotations.ApiParams;
|
||||
import com.syjiaer.clinic.server.common.annotations.ApiReturn;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
public class ScanUtil {
|
||||
public static ApiInfo scanApiInfo(String path) {
|
||||
// 1. 获取基础包路径(可配置或使用默认值)
|
||||
String basePackage = "com.syjiaer.clinic.server.controller"; // 示例包路径
|
||||
|
||||
// 2. 获取所有API信息列表
|
||||
List<ApiInfo> apiInfos = scanPackageToList(basePackage);
|
||||
|
||||
// 3. 标准化输入路径(移除前后斜杠,统一格式)
|
||||
String normalizedPath = path.replaceAll("/+", "/")
|
||||
.replaceAll("^/|/$", "");
|
||||
|
||||
// 4. 遍历查找匹配项
|
||||
for (ApiInfo apiInfo : apiInfos) {
|
||||
String apiPath = apiInfo.getPath().replaceAll("^/|/$", "");
|
||||
if (apiPath.equals(normalizedPath)) {
|
||||
return apiInfo;
|
||||
}
|
||||
}
|
||||
|
||||
return null; // 未找到匹配项
|
||||
}
|
||||
|
||||
public static Map<String, Object> scanPackageToCatalog( String basePackage ) {
|
||||
// 使用默认基础包路径,或根据需要修改
|
||||
List<ApiInfo> apiInfos = scanPackageToList(basePackage);
|
||||
Map<String, Object> catalog = new LinkedHashMap<>();
|
||||
|
||||
for (ApiInfo apiInfo : apiInfos) {
|
||||
String path = apiInfo.getPath();
|
||||
String[] parts = path.replaceAll("^/|/$", "").split("/");
|
||||
|
||||
Map<String, Object> currentLevel = catalog;
|
||||
// 构建路径树结构
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
String part = parts[i];
|
||||
if (!currentLevel.containsKey(part)) {
|
||||
// 如果是最后一部分,添加完整API信息
|
||||
if (i == parts.length - 1) {
|
||||
Map<String, Object> leafNode = new LinkedHashMap<>();
|
||||
leafNode.put("path", path);
|
||||
leafNode.put("comment", apiInfo.getComment());
|
||||
currentLevel.put(part, leafNode);
|
||||
} else {
|
||||
currentLevel.put(part, new LinkedHashMap<String, Object>());
|
||||
}
|
||||
}
|
||||
currentLevel = (Map<String, Object>) currentLevel.get(part);
|
||||
}
|
||||
}
|
||||
return catalog;
|
||||
}
|
||||
|
||||
|
||||
public static List<ApiInfo> scanPackageToList(String basePackage) {
|
||||
List<ApiInfo> apiInfos = new ArrayList<>();
|
||||
|
||||
|
||||
ClassPathScanningCandidateComponentProvider scanner =
|
||||
new ClassPathScanningCandidateComponentProvider(false);
|
||||
scanner.addIncludeFilter(new AnnotationTypeFilter(Controller.class));
|
||||
scanner.addIncludeFilter(new AnnotationTypeFilter(RestController.class));
|
||||
|
||||
Set<BeanDefinition> beans = scanner.findCandidateComponents(basePackage);
|
||||
|
||||
try {
|
||||
for (BeanDefinition bean : beans) {
|
||||
String beanClassName = bean.getBeanClassName();
|
||||
|
||||
// 排除包含dev的包
|
||||
if (beanClassName != null && beanClassName.contains(".doc.")) {
|
||||
continue;
|
||||
}
|
||||
Class<?> clazz = Class.forName(bean.getBeanClassName());
|
||||
|
||||
// 获取类注解
|
||||
RequestMapping classMapping = AnnotationUtils.findAnnotation(clazz, RequestMapping.class);
|
||||
String classPath = classMapping != null && classMapping.value().length > 0 ?
|
||||
classMapping.value()[0] : "";
|
||||
|
||||
// 扫描方法
|
||||
for (Method method : clazz.getMethods()) {
|
||||
RequestMapping methodMapping = AnnotationUtils.findAnnotation(method, RequestMapping.class);
|
||||
if (methodMapping != null) {
|
||||
String methodPath = methodMapping.value().length > 0 ?
|
||||
methodMapping.value()[0] : "";
|
||||
String fullPath = (classPath + "/" + methodPath).replaceAll("/+", "/");
|
||||
fullPath = cleanPath(fullPath);
|
||||
|
||||
// 获取方法注释
|
||||
ApiInfo apiInfo = new ApiInfo();
|
||||
apiInfo.setPath(fullPath);
|
||||
apiInfo.setComment(getMethodComment(method));
|
||||
apiInfo.setRequests(scanApiParams(method));
|
||||
apiInfo.setResponse(scanApiReturn(method));
|
||||
apiInfos.add(apiInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Controller扫描失败", e);
|
||||
}
|
||||
|
||||
return apiInfos;
|
||||
}
|
||||
private static String getMethodComment(Method method) {
|
||||
// 1. 优先获取Swagger的ApiOperation注解
|
||||
ApiOperation apiOperation = AnnotationUtils.findAnnotation(method, ApiOperation.class);
|
||||
if (apiOperation != null) {
|
||||
return apiOperation.value();
|
||||
}
|
||||
|
||||
// 2. 次选JavaDoc注释(需额外实现)
|
||||
return ""; // 暂留空
|
||||
}
|
||||
|
||||
private static List<ApiInfo.Request> scanApiParams(Method method) {
|
||||
List<ApiInfo.Request> params = new ArrayList<>();
|
||||
|
||||
ApiParams implicitParams = AnnotationUtils.findAnnotation(method, ApiParams.class);
|
||||
if (implicitParams != null) {
|
||||
for (ApiParam param : implicitParams.value()) {
|
||||
ApiInfo.Request apiParam = new ApiInfo.Request();
|
||||
apiParam.setComment(param.value());
|
||||
apiParam.setName(param.name());
|
||||
|
||||
// 设置参数类型
|
||||
if (!param.typeName().isEmpty()) {
|
||||
apiParam.setType(param.typeName());
|
||||
} else if (!param.type().equals(Object.class)) {
|
||||
apiParam.setType(param.type().getSimpleName());
|
||||
// 递归处理复杂类型属性
|
||||
if (isComplexType(param.type())) {
|
||||
apiParam.setChildren(scanClassProperties(param.type()));
|
||||
}
|
||||
}
|
||||
params.add(apiParam);
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
// 判断是否为需要递归解析的复杂类型
|
||||
private static boolean isComplexType(Class<?> clazz) {
|
||||
return !clazz.isPrimitive()
|
||||
&& !clazz.getName().startsWith("java.")
|
||||
&& !clazz.isEnum();
|
||||
}
|
||||
private static ApiInfo.Response scanApiReturn(Method method) {
|
||||
ApiInfo.Response response = new ApiInfo.Response();
|
||||
|
||||
// 1. 处理ApiReturn注解
|
||||
ApiReturn apiReturn = AnnotationUtils.findAnnotation(method, ApiReturn.class);
|
||||
if (apiReturn != null) {
|
||||
response.setIsArray(apiReturn.isArray());
|
||||
response.setName(apiReturn.name());
|
||||
response.setIsPage(apiReturn.isPage());
|
||||
response.setIsNull(apiReturn.isNull());
|
||||
|
||||
// 设置返回类型
|
||||
if (!apiReturn.typeName().isEmpty()) {
|
||||
response.setType(apiReturn.typeName());
|
||||
} else if (!apiReturn.type().equals(Object.class)) {
|
||||
Class<?> returnType = apiReturn.type();
|
||||
response.setType(returnType.getSimpleName());
|
||||
|
||||
// 递归处理复杂类型
|
||||
if (isComplexType(returnType)) {
|
||||
response.setChildren(scanClassProperties(returnType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
// 递归扫描类的属性
|
||||
private static List<ApiInfo.BaseProperty> scanClassProperties(Class<?> clazz) {
|
||||
List<ApiInfo.BaseProperty> properties = new ArrayList<>();
|
||||
|
||||
// 处理父类属性
|
||||
if (clazz.getSuperclass() != null && isComplexType(clazz.getSuperclass())) {
|
||||
properties.addAll(scanClassProperties(clazz.getSuperclass()));
|
||||
}
|
||||
|
||||
// 处理当前类属性
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
ApiInfo.BaseProperty fieldParam = new ApiInfo.BaseProperty();
|
||||
fieldParam.setName(field.getName());
|
||||
|
||||
// 处理字段注解
|
||||
ApiModelProperty modelProperty = field.getAnnotation(ApiModelProperty.class);
|
||||
if (modelProperty != null) {
|
||||
fieldParam.setComment(modelProperty.value());
|
||||
}
|
||||
|
||||
Class<?> fieldType = field.getType();
|
||||
fieldParam.setType(fieldType.getSimpleName());
|
||||
|
||||
// 递归处理复杂类型
|
||||
if (isComplexType(fieldType)) {
|
||||
fieldParam.setChildren(scanClassProperties(fieldType));
|
||||
}
|
||||
|
||||
properties.add(fieldParam);
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static String cleanPath(String originalPath) {
|
||||
// 1. 移除路径参数
|
||||
String pathWithoutParams = originalPath.replaceAll("/\\{[^/]+}", "");
|
||||
|
||||
// 2. 分割路径并只保留前三级
|
||||
String[] parts = pathWithoutParams.replaceAll("^/|/$", "").split("/");
|
||||
if (parts.length > 3) {
|
||||
return String.join("/", Arrays.copyOfRange(parts, 0, 3));
|
||||
}
|
||||
|
||||
return pathWithoutParams;
|
||||
}
|
||||
|
||||
public static Map<String, Object> scanPackageToMap(String basePackage) {
|
||||
List<ApiInfo> apiPaths = scanPackageToList(basePackage);
|
||||
Map<String, Object> root = new LinkedHashMap<>();
|
||||
|
||||
for (ApiInfo apiInfo : apiPaths) {
|
||||
String path = apiInfo.getPath();
|
||||
// 去除开头和结尾的斜杠,并按斜杠分割
|
||||
String[] parts = path.replaceAll("^/|/$", "").split("/");
|
||||
|
||||
Map<String, Object> currentLevel = root;
|
||||
// 处理路径的每一部分(除最后一部分)
|
||||
for (int i = 0; i < parts.length - 1; i++) {
|
||||
String part = parts[i];
|
||||
// 如果当前节点不是Map,说明是叶子节点,需要转换为Map
|
||||
if (!(currentLevel.get(part) instanceof Map)) {
|
||||
// 如果已有数据是ApiInfo,先保存到临时变量
|
||||
Object existingValue = currentLevel.get(part);
|
||||
currentLevel.put(part, new LinkedHashMap<String, Object>());
|
||||
if (existingValue != null) {
|
||||
// 将原有值放到特殊键下(如"_data")
|
||||
((Map<String, Object>) currentLevel.get(part)).put("_data", existingValue);
|
||||
}
|
||||
}
|
||||
currentLevel = (Map<String, Object>) currentLevel.get(part);
|
||||
}
|
||||
|
||||
// 最后一部分作为叶子节点
|
||||
String lastPart = parts[parts.length - 1];
|
||||
// 检查是否已经存在路径节点
|
||||
if (currentLevel.containsKey(lastPart) && currentLevel.get(lastPart) instanceof Map) {
|
||||
// 如果已经存在Map节点,将API信息放入特殊键
|
||||
((Map<String, Object>) currentLevel.get(lastPart)).put("_data", apiInfo);
|
||||
} else {
|
||||
currentLevel.put(lastPart, apiInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package com.syjiaer.clinic.server.common.doc.util;
|
||||
|
||||
import com.syjiaer.clinic.server.common.doc.entity.ApiInfo;
|
||||
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
public class TsUtil {
|
||||
|
||||
public static void generateNamespace(StringBuilder builder, Map<String, Object> map, int indentLevel) {
|
||||
String indent = " ".repeat(indentLevel);
|
||||
|
||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
|
||||
if (value instanceof Map) {
|
||||
// 处理嵌套命名空间
|
||||
builder.append(indent).append("export namespace ").append(capitalize(key)).append(" {\n");
|
||||
generateNamespace(builder, (Map<String, Object>) value, indentLevel + 1);
|
||||
builder.append(indent).append("}\n\n");
|
||||
} else if (value instanceof ApiInfo) {
|
||||
// 处理API端点
|
||||
ApiInfo apiInfo = (ApiInfo) value;
|
||||
String path = apiInfo.getPath().replaceAll("^/|/$", "");
|
||||
String comment = apiInfo.getComment().isEmpty() ? "" : "//" + apiInfo.getComment();
|
||||
|
||||
builder.append(indent).append("export const ")
|
||||
.append(capitalize(key)).append(" = '")
|
||||
.append(path).append("'")
|
||||
.append(comment).append(";\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String capitalize(String str) {
|
||||
if (str == null || str.isEmpty()) {
|
||||
return str;
|
||||
}
|
||||
return str.substring(0, 1).toUpperCase() + str.substring(1);
|
||||
}
|
||||
public static void generateAPITsFile(Map<String, Object> map, String outputPath) {
|
||||
StringBuilder tsBuilder = new StringBuilder();
|
||||
tsBuilder.append("export namespace API {\n");
|
||||
|
||||
generateNamespace(tsBuilder, map, 1);
|
||||
|
||||
tsBuilder.append("}\n");
|
||||
|
||||
try (FileWriter fileWriter = new FileWriter(outputPath)) {
|
||||
fileWriter.write(tsBuilder.toString());
|
||||
System.out.println("成功写入 " + outputPath);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("文件写入失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,8 @@
|
|||
package com.syjiaer.clinic.server.controller.charge;
|
||||
|
||||
import com.syjiaer.clinic.server.common.annotations.ApiParam;
|
||||
import com.syjiaer.clinic.server.common.annotations.ApiParams;
|
||||
import com.syjiaer.clinic.server.common.annotations.ApiReturn;
|
||||
import com.syjiaer.clinic.server.common.util.DateUtil;
|
||||
import com.syjiaer.clinic.server.common.vo.Page;
|
||||
import com.syjiaer.clinic.server.common.vo.Result;
|
||||
|
|
@ -8,6 +11,8 @@ import com.syjiaer.clinic.server.entity.charge.ChargeLog;
|
|||
import com.syjiaer.clinic.server.entity.charge.ChargeOrder;
|
||||
import com.syjiaer.clinic.server.service.charge.ChargeService;
|
||||
import com.syjiaer.clinic.server.service.charge.vo.RetailOrderDailyChargingReportVo;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
|
@ -22,10 +27,14 @@ public class ChargeLogController extends BaseController {
|
|||
@Autowired
|
||||
private ChargeService chargeService;
|
||||
|
||||
/**
|
||||
* 每日收费报表
|
||||
*/
|
||||
|
||||
@ApiOperation("每日收费报表")
|
||||
@ApiParams({
|
||||
@ApiParam(name = "startDate", value = "开始时间", required = true,typeName = "String"),
|
||||
@ApiParam(name = "endTime", value = "结束时间", required = true, typeName = "String"),
|
||||
@ApiParam(name = "userId", value = "用户ID", required = true, typeName = "Integer")
|
||||
})
|
||||
@ApiReturn(type = RetailOrderDailyChargingReportVo.class,isArray = true)
|
||||
@RequestMapping("/reportWithDays")
|
||||
public Result<List<RetailOrderDailyChargingReportVo>> dailyChargingReport() {
|
||||
String startDateStr = parmsUtil.getString("startDate", "请选择开始时间");
|
||||
|
|
@ -38,34 +47,37 @@ public class ChargeLogController extends BaseController {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* 病人付费记录
|
||||
* @return
|
||||
*/
|
||||
|
||||
@ApiOperation("病人付费记录")
|
||||
@RequestMapping("/listByPatientId")
|
||||
@ApiParams({
|
||||
@ApiParam(name = "patientId", value = "病人ID", required = true, typeName = "Integer")
|
||||
})
|
||||
@ApiReturn(type = ChargeOrder.class,isArray = true)
|
||||
public Result<List<ChargeOrder>> listByPatientId() {
|
||||
|
||||
Integer patientId = parmsUtil.getInteger("patientId");
|
||||
return success(chargeService.getListByPatientId(patientId));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 收费记录
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation("收费记录")
|
||||
@RequestMapping("/list")
|
||||
@ApiReturn(type = ChargeLog.class,isPage = true)
|
||||
public Result<Page<ChargeLog>> list() {
|
||||
return success(chargeService.getChargeRecordPageList());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取收退费记录
|
||||
*/
|
||||
|
||||
@ApiOperation("获取收退费记录")
|
||||
@RequestMapping("listByDatetime")
|
||||
@ApiParams({
|
||||
@ApiParam(name = "beginTime", value = "开始时间", required = true,typeName = "String"),
|
||||
@ApiParam(name = "endTime", value = "结束时间", required = true, typeName = "String"),
|
||||
@ApiParam(name = "userId", value = "用户ID", required = true, typeName = "Integer")
|
||||
})
|
||||
@ApiReturn(type = ChargeLog.class,isArray = true)
|
||||
public Result<List<ChargeLog>> listByDatetime(){
|
||||
String begin = parmsUtil.getString("beginTime","开始时间为空");
|
||||
String end= parmsUtil.getString("endTime","结束时间为空");
|
||||
|
|
@ -73,8 +85,6 @@ public class ChargeLogController extends BaseController {
|
|||
LocalDateTime beginTime = DateUtil.getDateTime(begin);
|
||||
LocalDateTime endTime = DateUtil.getDateTime(end);
|
||||
List<ChargeLog> chargeLogs = chargeService.listChargeLog(beginTime,endTime,userId);
|
||||
|
||||
|
||||
return success(chargeLogs);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
package com.syjiaer.clinic.server.controller.charge;
|
||||
|
||||
import com.syjiaer.clinic.server.common.annotations.ApiParam;
|
||||
import com.syjiaer.clinic.server.common.annotations.ApiParams;
|
||||
import com.syjiaer.clinic.server.common.annotations.ApiReturn;
|
||||
import com.syjiaer.clinic.server.common.annotations.RecordCommonLog;
|
||||
import com.syjiaer.clinic.server.common.api.output.OM2206A;
|
||||
import com.syjiaer.clinic.server.common.api.output.OM2207A;
|
||||
|
|
@ -15,6 +18,8 @@ import com.syjiaer.clinic.server.entity.charge.vo.ChargeDetailVo;
|
|||
import com.syjiaer.clinic.server.entity.charge.vo.ChargeOrderPrintVo;
|
||||
import com.syjiaer.clinic.server.service.charge.ChargeService;
|
||||
import com.syjiaer.clinic.server.service.charge.vo.RetailOrderDailyChargingReportVo;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
|
@ -35,6 +40,10 @@ public class ChargeOrderController extends BaseController {
|
|||
@RecordCommonLog(operation = "生成订单")
|
||||
@ApiOperation("保存收费订单")
|
||||
@RequestMapping("/save")
|
||||
@ApiParams({
|
||||
@ApiParam(name = "data",value = "收费订单信息", required = true, type = ChargeSaveDto.class)
|
||||
})
|
||||
@ApiReturn(name = "订单编号",typeName = "String")
|
||||
public Result<Object> save() {
|
||||
ChargeSaveDto dto = parmsUtil.getObject("data", ChargeSaveDto.class);
|
||||
ChargeOrder chargeOrder = chargeService.save(dto);
|
||||
|
|
@ -45,6 +54,10 @@ public class ChargeOrderController extends BaseController {
|
|||
*/
|
||||
@ApiOperation("根据诊断code和状态获取诊断信息")
|
||||
@RequestMapping("/getByDiagnosisCode")
|
||||
@ApiReturn(isArray = true, type = ChargeOrder.class, name = "订单列表")
|
||||
@ApiParams({
|
||||
@ApiParam(name = "diagnosisCode",value = "诊断code", required = true)
|
||||
})
|
||||
public Result<ChargeOrder> getByDiagnosisCode() {
|
||||
String diagnosisCode = parmsUtil.getString("diagnosisCode","诊断code不能为空");
|
||||
ChargeOrder chargeOrder = chargeService.getOrderByDiagnosisCode(diagnosisCode);
|
||||
|
|
@ -58,6 +71,10 @@ public class ChargeOrderController extends BaseController {
|
|||
*/
|
||||
@ApiOperation("根据code查询订单详情")
|
||||
@RequestMapping("/getByCode")
|
||||
@ApiReturn(type = ChargeDetailVo.class, name = "订单详情")
|
||||
@ApiParams({
|
||||
@ApiParam(name = "code",value = "订单号", required = true)
|
||||
})
|
||||
public Result<ChargeDetailVo> getByCode() {
|
||||
String code = parmsUtil.getString("code");
|
||||
return success(chargeService.getDetail(code));
|
||||
|
|
@ -68,6 +85,10 @@ public class ChargeOrderController extends BaseController {
|
|||
*/
|
||||
@ApiOperation("根据订单号获取订单详情,小票打印用")
|
||||
@RequestMapping("getPrintInfoByCode")
|
||||
@ApiReturn(type = ChargeOrderPrintVo.class, name = "打印订单详情")
|
||||
@ApiParams({
|
||||
@ApiParam(name = "code",value = "订单号", required = true)
|
||||
})
|
||||
public Result<ChargeOrderPrintVo> getPrintInfoByCode() {
|
||||
String code = parmsUtil.getString("code", "订单号不能为空");
|
||||
return success(chargeService.getPrintInfoByCode(code));
|
||||
|
|
@ -78,6 +99,10 @@ public class ChargeOrderController extends BaseController {
|
|||
*/
|
||||
@ApiOperation("查询list 只有订单信息")
|
||||
@RequestMapping("/list")
|
||||
@ApiReturn(isPage = true, type = ChargeOrder.class, name = "订单列表")
|
||||
@ApiParams({
|
||||
@ApiParam(name = "query",value = "查询参数", required = true, type = ChargeQuery.class)
|
||||
})
|
||||
public Result<Page<ChargeOrder>> list() {
|
||||
ChargeQuery chargeQuery = parmsUtil.getObject("query", ChargeQuery.class);
|
||||
return success(chargeService.pageList(chargeQuery));
|
||||
|
|
@ -88,6 +113,10 @@ public class ChargeOrderController extends BaseController {
|
|||
*/
|
||||
@ApiOperation("查询list 带详情")
|
||||
@RequestMapping("/listWithDetail")
|
||||
@ApiParams({
|
||||
@ApiParam(name = "query",value = "查询参数", required = true, type = ChargeQuery.class)
|
||||
})
|
||||
@ApiReturn(isPage = true, type = ChargeDetailVo.class, name = "订单列表")
|
||||
public Result<Page<ChargeDetailVo>> listWithDetail() {
|
||||
ChargeQuery chargeQuery = parmsUtil.getObject("query", ChargeQuery.class);
|
||||
return success(chargeService.pageDetailList(chargeQuery));
|
||||
|
|
@ -99,6 +128,11 @@ public class ChargeOrderController extends BaseController {
|
|||
@ApiOperation("完成订单")
|
||||
@RecordCommonLog(operation = "完成订单")
|
||||
@RequestMapping("/complete")
|
||||
@ApiParams({
|
||||
@ApiParam(name = "id",value = "订单id", required = true),
|
||||
@ApiParam(name = "payType",value = "支付方式", required = true)
|
||||
})
|
||||
@ApiReturn(isNull = true)
|
||||
public Result<Object> complete() {
|
||||
Integer id = parmsUtil.getInteger("id");
|
||||
Integer payType = parmsUtil.getInteger("payType");
|
||||
|
|
@ -113,6 +147,11 @@ public class ChargeOrderController extends BaseController {
|
|||
*/
|
||||
@RecordCommonLog(operation = "订单退款")
|
||||
@RequestMapping("/refund")
|
||||
@ApiParams({
|
||||
@ApiParam(name = "changeOrderCode",value = "订单号", required = true)
|
||||
})
|
||||
@ApiOperation("订单退款")
|
||||
@ApiReturn(isNull = true)
|
||||
public Result<Object> refund() {
|
||||
String changeOrderCode = parmsUtil.getString("changeOrderCode","订单号为空");
|
||||
chargeService.refund(changeOrderCode);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
package com.syjiaer.clinic.server.controller.charge;
|
||||
|
||||
import com.syjiaer.clinic.server.common.annotations.ApiParam;
|
||||
import com.syjiaer.clinic.server.common.annotations.ApiParams;
|
||||
import com.syjiaer.clinic.server.common.annotations.ApiReturn;
|
||||
import com.syjiaer.clinic.server.common.annotations.RecordCommonLog;
|
||||
import com.syjiaer.clinic.server.common.api.output.OM2206A;
|
||||
import com.syjiaer.clinic.server.common.api.output.OM2207A;
|
||||
|
|
@ -22,6 +25,13 @@ public class SocialController extends BaseController {
|
|||
*/
|
||||
@ApiOperation("医保预支付")
|
||||
@RequestMapping("/prePay")
|
||||
@ApiParams({
|
||||
@ApiParam(name = "changeOrderCode",value = "订单号"),
|
||||
@ApiParam(name = "mdtrtCertType",value = "证件类型"),
|
||||
@ApiParam(name = "mdtrtCertNo",value = "证件号码"),
|
||||
@ApiParam(name = "insutype",value = "险种类型")
|
||||
})
|
||||
@ApiReturn(type = OM2206A.class)
|
||||
public Result<OM2206A> prePay(){
|
||||
String changeOrderCode = parmsUtil.getString("changeOrderCode");
|
||||
String mdtrtCertType = parmsUtil.getString("mdtrtCertType");
|
||||
|
|
@ -37,6 +47,15 @@ public class SocialController extends BaseController {
|
|||
@ApiOperation("医保真实支付")
|
||||
@RecordCommonLog(operation = "医保收费")
|
||||
@RequestMapping("/realPay")
|
||||
@ApiParams({
|
||||
@ApiParam(name = "changeOrderCode",value = "订单号"),
|
||||
@ApiParam(name = "mdtrtCertType",value = "证件类型"),
|
||||
@ApiParam(name = "mdtrtCertNo",value = "证件号码"),
|
||||
@ApiParam(name = "insutype",value = "险种类型"),
|
||||
@ApiParam(name = "payType",value = "支付方式"),
|
||||
@ApiParam(name = "curBalc",value = "当前余额")
|
||||
})
|
||||
@ApiReturn(type = OM2207A.class)
|
||||
public Result<OM2207A> realPay(){
|
||||
String changeOrderCode = parmsUtil.getString("changeOrderCode");
|
||||
String mdtrtCertType = parmsUtil.getString("mdtrtCertType");
|
||||
|
|
@ -55,6 +74,10 @@ public class SocialController extends BaseController {
|
|||
@ApiOperation("医保上传支付明细")
|
||||
@RecordCommonLog(operation = "上传医保费用明细")
|
||||
@RequestMapping("/upload")
|
||||
@ApiParams({
|
||||
@ApiParam(name = "changeOrderCode",value = "订单号")
|
||||
})
|
||||
@ApiReturn(isNull = true)
|
||||
public Result<Object> upload() {
|
||||
String changeOrderCode = parmsUtil.getString("changeOrderCode");
|
||||
chargeService.uploadCostDetails(changeOrderCode);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
package com.syjiaer.clinic.server.controller.doc;
|
||||
|
||||
import com.syjiaer.clinic.server.common.annotations.NoAuthCheck;
|
||||
import com.syjiaer.clinic.server.common.doc.entity.ApiInfo;
|
||||
import com.syjiaer.clinic.server.common.doc.util.ScanUtil;
|
||||
import com.syjiaer.clinic.server.common.vo.Result;
|
||||
import com.syjiaer.clinic.server.controller.BaseController;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/doc/base")
|
||||
public class ApiController extends BaseController {
|
||||
@RequestMapping("/getCatalog")
|
||||
@NoAuthCheck
|
||||
public Result<Map<String, Object>> getCatalog(){
|
||||
Map<String, Object> map = ScanUtil.scanPackageToCatalog("com.syjiaer.clinic.server.controller.charge");
|
||||
return success(map);
|
||||
}
|
||||
|
||||
@RequestMapping("/getApiInfo")
|
||||
@NoAuthCheck
|
||||
public Result<ApiInfo> getApiInfo(){
|
||||
String path = parmsUtil.getString("path", "请输入path");
|
||||
ApiInfo apiInfo = ScanUtil.scanApiInfo(path);
|
||||
return success(apiInfo);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue