From 6affaba5c3a1b88ec8935cb10486b6ddf5137da0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com>
Date: Wed, 17 Dec 2025 14:48:13 +0800
Subject: [PATCH] =?UTF-8?q?feat(credit):=20=E6=96=B0=E5=A2=9E=E4=BC=81?=
=?UTF-8?q?=E4=B8=9A=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD=E6=A8=A1=E5=9D=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 新增企业实体类CreditCompany,包含企业基本信息字段
- 新增企业控制器CreditCompanyController,提供CRUD接口
- 新增企业导入参数类CreditCompanyImportParam,支持Excel导入
- 新增企业查询参数类CreditCompanyParam,支持条件查询
- 新增企业Mapper接口及XML映射文件,实现关联查询
- 实现企业分页查询、列表查询、详情查询接口
- 实现企业新增、修改、删除接口
- 实现企业批量导入功能,支持Excel模板下载
- 实现企业数据校验和重复数据处理逻辑
- 添加企业导入模板下载接口
- 支持企业信息的完整字段映射和转换逻辑
- 添加企业查询条件注解,支持动态SQL查询
- 实现企业关联查询SQL,支持多字段模糊匹配
- 添加企业操作日志记录和权限控制注解
- 完善企业导入异常处理和错误信息收集机制
---
.../credit/mapper/xml/CreditUserMapper.xml | 2 +
.../led/config/BmeApiProperties.java | 49 +++
.../led/controller/LedApiController.java | 37 +++
.../com/gxwebsoft/led/model/BmeToken.java | 28 ++
.../led/param/BmeNumberSourcesParam.java | 48 +++
.../led/param/BmeStopReplaceParam.java | 35 +++
.../led/service/LedScheduleService.java | 288 ++++++++++++++++++
src/main/resources/application.yml | 11 +
8 files changed, 498 insertions(+)
create mode 100644 src/main/java/com/gxwebsoft/led/config/BmeApiProperties.java
create mode 100644 src/main/java/com/gxwebsoft/led/controller/LedApiController.java
create mode 100644 src/main/java/com/gxwebsoft/led/model/BmeToken.java
create mode 100644 src/main/java/com/gxwebsoft/led/param/BmeNumberSourcesParam.java
create mode 100644 src/main/java/com/gxwebsoft/led/param/BmeStopReplaceParam.java
create mode 100644 src/main/java/com/gxwebsoft/led/service/LedScheduleService.java
diff --git a/src/main/java/com/gxwebsoft/credit/mapper/xml/CreditUserMapper.xml b/src/main/java/com/gxwebsoft/credit/mapper/xml/CreditUserMapper.xml
index 7e00d8a..0e522b2 100644
--- a/src/main/java/com/gxwebsoft/credit/mapper/xml/CreditUserMapper.xml
+++ b/src/main/java/com/gxwebsoft/credit/mapper/xml/CreditUserMapper.xml
@@ -84,6 +84,8 @@
AND (a.name LIKE CONCAT('%', #{param.keywords}, '%')
+ OR a.procurement_name LIKE CONCAT('%', #{param.keywords}, '%')
+ OR a.winning_name LIKE CONCAT('%', #{param.keywords}, '%')
)
diff --git a/src/main/java/com/gxwebsoft/led/config/BmeApiProperties.java b/src/main/java/com/gxwebsoft/led/config/BmeApiProperties.java
new file mode 100644
index 0000000..f0221d6
--- /dev/null
+++ b/src/main/java/com/gxwebsoft/led/config/BmeApiProperties.java
@@ -0,0 +1,49 @@
+package com.gxwebsoft.led.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 业务中台(排班接口)调用配置。
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "led.bme")
+public class BmeApiProperties {
+
+ /**
+ * 中台基础地址,例如:http://16.1.4.201:7979
+ */
+ private String baseUrl;
+
+ /**
+ * 授权应用ID(文档中的 APPID)。
+ */
+ private String appid;
+
+ /**
+ * 应用密钥(文档中的 secret_key)。
+ */
+ private String secretKey;
+
+ /**
+ * 机构ID,默认按文档要求传 10001。
+ */
+ private String mechanismId = "10001";
+
+ /**
+ * 默认操作员代码。
+ */
+ private String defaultExtUserId;
+
+ /**
+ * 默认医院代码,可留空。
+ */
+ private String defaultHospitalId;
+
+ /**
+ * 连接/读取超时时间(毫秒)。
+ */
+ private int timeoutMs = 10000;
+}
diff --git a/src/main/java/com/gxwebsoft/led/controller/LedApiController.java b/src/main/java/com/gxwebsoft/led/controller/LedApiController.java
new file mode 100644
index 0000000..0335e5e
--- /dev/null
+++ b/src/main/java/com/gxwebsoft/led/controller/LedApiController.java
@@ -0,0 +1,37 @@
+package com.gxwebsoft.led.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.gxwebsoft.common.core.web.ApiResult;
+import com.gxwebsoft.common.core.web.BaseController;
+import com.gxwebsoft.led.param.BmeNumberSourcesParam;
+import com.gxwebsoft.led.param.BmeStopReplaceParam;
+import com.gxwebsoft.led.service.LedScheduleService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+@Tag(name = "LED-排班接口")
+@RestController
+@RequestMapping("/api/led/bme")
+public class LedApiController extends BaseController {
+
+ @Resource
+ private LedScheduleService ledScheduleService;
+
+ @Operation(summary = "查询一周内停替诊医生排班信息(10017)")
+ @PostMapping("/stop-replace")
+ public ApiResult searchStopAndReplace(@RequestBody BmeStopReplaceParam param) {
+ return success(ledScheduleService.searchStopAndReplace(param));
+ }
+
+ @Operation(summary = "查询医生排班信息当日剩余号源(10018)")
+ @PostMapping("/number-sources")
+ public ApiResult searchNumberSources(@RequestBody BmeNumberSourcesParam param) {
+ return success(ledScheduleService.searchNumberSources(param));
+ }
+}
diff --git a/src/main/java/com/gxwebsoft/led/model/BmeToken.java b/src/main/java/com/gxwebsoft/led/model/BmeToken.java
new file mode 100644
index 0000000..9ac429d
--- /dev/null
+++ b/src/main/java/com/gxwebsoft/led/model/BmeToken.java
@@ -0,0 +1,28 @@
+package com.gxwebsoft.led.model;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 业务中台授权令牌缓存实体。
+ */
+@Data
+public class BmeToken implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 接口调用凭证 access_token。
+ */
+ private String accessToken;
+
+ /**
+ * 刷新 access_token 的 refresh_token。
+ */
+ private String refreshToken;
+
+ /**
+ * access_token 过期时间戳(秒级)。
+ */
+ private long expireAt;
+}
diff --git a/src/main/java/com/gxwebsoft/led/param/BmeNumberSourcesParam.java b/src/main/java/com/gxwebsoft/led/param/BmeNumberSourcesParam.java
new file mode 100644
index 0000000..9391be3
--- /dev/null
+++ b/src/main/java/com/gxwebsoft/led/param/BmeNumberSourcesParam.java
@@ -0,0 +1,48 @@
+package com.gxwebsoft.led.param;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * 查询医生排班信息当日剩余号源(10018)入参。
+ */
+@Data
+public class BmeNumberSourcesParam {
+
+ @Schema(description = "开始日期,yyyy-MM-dd")
+ private String startDate;
+
+ @Schema(description = "结束日期,yyyy-MM-dd")
+ private String endDate;
+
+ @Schema(description = "科室代码,可选")
+ private String deptCode;
+
+ @Schema(description = "医生工号,可选")
+ private String userCode;
+
+ @Schema(description = "时段,可选:01上午 02下午 03全天 04中午")
+ @JsonProperty("aSTimeRange")
+ private String aSTimeRange;
+
+ @Schema(description = "医院代码,可选")
+ private String hospitalId;
+
+ @Schema(description = "机构ID,默认10001")
+ private String mechanismId;
+
+ @Schema(description = "操作员代码")
+ private String extUserID;
+
+ @Schema(description = "交易代码,默认10018")
+ private String tradeCode;
+
+ public String getASTimeRange() {
+ return aSTimeRange;
+ }
+
+ public void setASTimeRange(String aSTimeRange) {
+ this.aSTimeRange = aSTimeRange;
+ }
+}
diff --git a/src/main/java/com/gxwebsoft/led/param/BmeStopReplaceParam.java b/src/main/java/com/gxwebsoft/led/param/BmeStopReplaceParam.java
new file mode 100644
index 0000000..27a53c1
--- /dev/null
+++ b/src/main/java/com/gxwebsoft/led/param/BmeStopReplaceParam.java
@@ -0,0 +1,35 @@
+package com.gxwebsoft.led.param;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * 查询一周内停替诊排班(10017)入参。
+ */
+@Data
+public class BmeStopReplaceParam {
+
+ @Schema(description = "开始日期,yyyy-MM-dd")
+ private String startDate;
+
+ @Schema(description = "结束日期,yyyy-MM-dd")
+ private String endDate;
+
+ @Schema(description = "科室代码,可选")
+ private String deptCode;
+
+ @Schema(description = "医生工号,可选")
+ private String userCode;
+
+ @Schema(description = "医院代码,可选")
+ private String hospitalId;
+
+ @Schema(description = "机构ID,默认10001")
+ private String mechanismId;
+
+ @Schema(description = "操作员代码")
+ private String extUserID;
+
+ @Schema(description = "交易代码,默认10017")
+ private String tradeCode;
+}
diff --git a/src/main/java/com/gxwebsoft/led/service/LedScheduleService.java b/src/main/java/com/gxwebsoft/led/service/LedScheduleService.java
new file mode 100644
index 0000000..c00bc48
--- /dev/null
+++ b/src/main/java/com/gxwebsoft/led/service/LedScheduleService.java
@@ -0,0 +1,288 @@
+package com.gxwebsoft.led.service;
+
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.crypto.digest.DigestUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.gxwebsoft.common.core.exception.BusinessException;
+import com.gxwebsoft.common.core.utils.JSONUtil;
+import com.gxwebsoft.common.core.utils.RedisUtil;
+import com.gxwebsoft.led.config.BmeApiProperties;
+import com.gxwebsoft.led.model.BmeToken;
+import com.gxwebsoft.led.param.BmeNumberSourcesParam;
+import com.gxwebsoft.led.param.BmeStopReplaceParam;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 排班接口对接服务。
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class LedScheduleService {
+
+ private static final String TOKEN_CACHE_KEY = "led:bme:auth";
+ private static final long TOKEN_EXPIRE_MARGIN_SECONDS = 60L;
+
+ private final BmeApiProperties properties;
+ private final RedisUtil redisUtil;
+
+ public JSONObject searchStopAndReplace(BmeStopReplaceParam param) {
+ BmeStopReplaceParam requestParam = fillStopReplaceDefaults(param);
+ BmeToken token = ensureToken();
+ System.out.println("token = " + token);
+ String body = buildStopReplaceBody(requestParam);
+ return doSignedPost("/cgi-bin/bme-app-register/outpatient/registered/searchDoctorsStopAndReplaceInfo", body, token);
+ }
+
+ public JSONObject searchNumberSources(BmeNumberSourcesParam param) {
+ BmeNumberSourcesParam requestParam = fillNumberSourcesDefaults(param);
+ BmeToken token = ensureToken();
+ String body = buildNumberSourcesBody(requestParam);
+ return doSignedPost("/cgi-bin/bme-app-register/outpatient/registered/searchDoctorsNumberSources", body, token);
+ }
+
+ private JSONObject doSignedPost(String path, String body, BmeToken token) {
+ if (StrUtil.isBlank(body)) {
+ throw new BusinessException("请求体为空");
+ }
+ ensureConfig();
+ long timestamp = System.currentTimeMillis() / 1000;
+ String nonce = RandomUtil.randomString(16);
+ String signStr = body + "|" + token.getAccessToken() + "|" + token.getRefreshToken() + "|" + timestamp + "|" + nonce;
+ String sig = DigestUtil.md5Hex(signStr);
+ HttpResponse response = HttpRequest.post(buildUrl(path))
+ .header("sig", sig)
+ .header("timestamp", String.valueOf(timestamp))
+ .header("nonce", nonce)
+ .header("access-token", token.getAccessToken())
+ .contentType("application/json")
+ .body(body)
+ .timeout(properties.getTimeoutMs())
+ .execute();
+ if (response.getStatus() != 200) {
+ throw new BusinessException("调用中台接口失败,HTTP状态码:" + response.getStatus());
+ }
+ String respBody = response.body();
+ JSONObject respJson;
+ try {
+ respJson = JSON.parseObject(respBody);
+ } catch (Exception e) {
+ throw new BusinessException("解析中台响应失败");
+ }
+ if (respJson == null || !"0".equals(respJson.getString("code"))) {
+ String message = respJson != null ? respJson.getString("msg") : "未知错误";
+ throw new BusinessException("中台接口调用失败:" + message);
+ }
+ return respJson;
+ }
+
+ private BmeStopReplaceParam fillStopReplaceDefaults(BmeStopReplaceParam param) {
+ if (param == null) {
+ throw new BusinessException("请求参数不能为空");
+ }
+ if (StrUtil.isBlank(param.getStartDate()) || StrUtil.isBlank(param.getEndDate())) {
+ throw new BusinessException("开始日期和结束日期必填");
+ }
+ if (StrUtil.isBlank(param.getMechanismId())) {
+ param.setMechanismId(properties.getMechanismId());
+ }
+ if (StrUtil.isBlank(param.getExtUserID())) {
+ param.setExtUserID(properties.getDefaultExtUserId());
+ }
+ if (StrUtil.isBlank(param.getHospitalId())) {
+ param.setHospitalId(properties.getDefaultHospitalId());
+ }
+ if (StrUtil.isBlank(param.getTradeCode())) {
+ param.setTradeCode("10017");
+ }
+ if (StrUtil.hasBlank(param.getMechanismId(), param.getExtUserID(), param.getTradeCode())) {
+ throw new BusinessException("机构ID、操作员代码、交易代码必填");
+ }
+ return param;
+ }
+
+ private BmeNumberSourcesParam fillNumberSourcesDefaults(BmeNumberSourcesParam param) {
+ if (param == null) {
+ throw new BusinessException("请求参数不能为空");
+ }
+ if (StrUtil.isBlank(param.getStartDate()) || StrUtil.isBlank(param.getEndDate())) {
+ throw new BusinessException("开始日期和结束日期必填");
+ }
+ if (StrUtil.isBlank(param.getMechanismId())) {
+ param.setMechanismId(properties.getMechanismId());
+ }
+ if (StrUtil.isBlank(param.getExtUserID())) {
+ param.setExtUserID(properties.getDefaultExtUserId());
+ }
+ if (StrUtil.isBlank(param.getHospitalId())) {
+ param.setHospitalId(properties.getDefaultHospitalId());
+ }
+ if (StrUtil.isBlank(param.getTradeCode())) {
+ param.setTradeCode("10018");
+ }
+ if (StrUtil.hasBlank(param.getMechanismId(), param.getExtUserID(), param.getTradeCode())) {
+ throw new BusinessException("机构ID、操作员代码、交易代码必填");
+ }
+ return param;
+ }
+
+ private String buildStopReplaceBody(BmeStopReplaceParam param) {
+ Map body = new LinkedHashMap<>();
+ body.put("mechanismId", param.getMechanismId());
+ body.put("tradeCode", param.getTradeCode());
+ body.put("startDate", param.getStartDate());
+ body.put("endDate", param.getEndDate());
+ putIfNotBlank(body, "deptCode", param.getDeptCode());
+ putIfNotBlank(body, "userCode", param.getUserCode());
+ putIfNotBlank(body, "hospitalId", param.getHospitalId());
+ body.put("extUserID", param.getExtUserID());
+ return JSONUtil.toJSONString(body);
+ }
+
+ private String buildNumberSourcesBody(BmeNumberSourcesParam param) {
+ Map body = new LinkedHashMap<>();
+ body.put("mechanismId", param.getMechanismId());
+ body.put("tradeCode", param.getTradeCode());
+ body.put("startDate", param.getStartDate());
+ body.put("endDate", param.getEndDate());
+ putIfNotBlank(body, "deptCode", param.getDeptCode());
+ putIfNotBlank(body, "userCode", param.getUserCode());
+ putIfNotBlank(body, "aSTimeRange", param.getASTimeRange());
+ putIfNotBlank(body, "hospitalId", param.getHospitalId());
+ body.put("extUserID", param.getExtUserID());
+ return JSONUtil.toJSONString(body);
+ }
+
+ private void putIfNotBlank(Map body, String key, String value) {
+ if (StrUtil.isNotBlank(value)) {
+ body.put(key, value);
+ }
+ }
+
+ private BmeToken ensureToken() {
+ ensureConfig();
+ long now = System.currentTimeMillis() / 1000;
+ BmeToken cached = redisUtil.get(TOKEN_CACHE_KEY, BmeToken.class);
+ if (cached != null && cached.getExpireAt() > now + TOKEN_EXPIRE_MARGIN_SECONDS) {
+ return cached;
+ }
+ if (cached != null && StrUtil.isNotBlank(cached.getRefreshToken())) {
+ try {
+ return refreshToken(cached.getRefreshToken());
+ } catch (Exception e) {
+ log.warn("刷新 access_token 失败,尝试重新申请: {}", e.getMessage());
+ }
+ }
+ return fetchToken();
+ }
+
+ private BmeToken fetchToken() {
+ long timestamp = System.currentTimeMillis() / 1000;
+ String nonce = IdUtil.fastSimpleUUID();
+ String grantType = "secret";
+ Map form = new HashMap<>();
+ form.put("appid", properties.getAppid());
+ form.put("grant_type", grantType);
+ form.put("secret_key", properties.getSecretKey());
+ form.put("timestamp", timestamp);
+ form.put("nonce", nonce);
+ String signStr = properties.getAppid() + "|" + properties.getSecretKey() + "|" + grantType + "|" + timestamp + "|" + nonce;
+ form.put("sign", DigestUtil.md5Hex(signStr));
+
+ HttpResponse response = HttpRequest.get(buildUrl("/cgi-bin/bme-auth/auth/access_token"))
+ .form(form)
+ .timeout(properties.getTimeoutMs())
+ .execute();
+ return handleTokenResponse(response);
+ }
+
+ private BmeToken refreshToken(String refreshToken) {
+ long timestamp = System.currentTimeMillis() / 1000;
+ String nonce = IdUtil.fastSimpleUUID();
+ String grantType = "refresh_token";
+ Map form = new HashMap<>();
+ form.put("appid", properties.getAppid());
+ form.put("grant_type", grantType);
+ form.put("refresh_token", refreshToken);
+ form.put("timestamp", timestamp);
+ form.put("nonce", nonce);
+ String signStr = properties.getAppid() + "|" + properties.getSecretKey() + "|" + refreshToken + "|" + grantType + "|" + timestamp + "|" + nonce;
+ form.put("sign", DigestUtil.md5Hex(signStr));
+ HttpResponse response = HttpRequest.get(buildUrl("/cgi-bin/bme-auth/auth/refresh_token"))
+ .form(form)
+ .timeout(properties.getTimeoutMs())
+ .execute();
+ return handleTokenResponse(response);
+ }
+
+ private BmeToken handleTokenResponse(HttpResponse response) {
+ if (response.getStatus() != 200) {
+ throw new BusinessException("获取中台token失败,HTTP状态码:" + response.getStatus());
+ }
+ JSONObject resp;
+ try {
+ resp = JSON.parseObject(response.body());
+ } catch (Exception e) {
+ throw new BusinessException("解析中台token响应失败");
+ }
+ if (resp == null || !"0".equals(resp.getString("code"))) {
+ String message = resp != null ? resp.getString("msg") : "未知错误";
+ throw new BusinessException("获取中台token失败:" + message);
+ }
+ JSONObject data = resp.getJSONObject("data");
+ if (data == null) {
+ throw new BusinessException("中台token响应缺少数据");
+ }
+ String accessToken = data.getString("access_token");
+ String refreshToken = data.getString("refresh_token");
+ int expiresIn = data.getIntValue("expires_in");
+ if (StrUtil.hasBlank(accessToken, refreshToken) || expiresIn <= 0) {
+ throw new BusinessException("中台token响应不完整");
+ }
+ long expireAt = System.currentTimeMillis() / 1000 + expiresIn - TOKEN_EXPIRE_MARGIN_SECONDS;
+ BmeToken token = new BmeToken();
+ token.setAccessToken(accessToken);
+ token.setRefreshToken(refreshToken);
+ token.setExpireAt(expireAt);
+ // refresh_token有效期5天,这里缓存5天
+ redisUtil.set(TOKEN_CACHE_KEY, token, Duration.ofDays(5).getSeconds(), TimeUnit.SECONDS);
+ return token;
+ }
+
+ private void ensureConfig() {
+ if (StrUtil.hasBlank(properties.getBaseUrl(), properties.getAppid(), properties.getSecretKey())) {
+ throw new BusinessException("排班接口配置缺失,请检查 led.bme 配置");
+ }
+ }
+
+ private String buildUrl(String path) {
+ String base = properties.getBaseUrl();
+ if (StrUtil.isBlank(base)) {
+ throw new BusinessException("排班接口基础地址未配置");
+ }
+ if (base.endsWith("/")) {
+ base = base.substring(0, base.length() - 1);
+ }
+ if (!path.startsWith("/")) {
+ path = "/" + path;
+ }
+ // 兼容 baseUrl 已包含 /cgi-bin 的场景,避免拼接成 /cgi-bin/cgi-bin
+ if (base.endsWith("/cgi-bin") && path.startsWith("/cgi-bin/")) {
+ path = path.substring("/cgi-bin".length());
+ }
+ return base + path;
+ }
+}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 751eff3..368b20f 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -198,6 +198,17 @@ springdoc:
swagger-ui:
enabled: true
+# LED - 排班接口(业务中台)对接配置
+led:
+ bme:
+ base-url: ${LED_BME_BASE_URL:http://16.1.4.201:7979}
+ appid: ${LED_BME_APPID:BQ73n58Lf}
+ secret-key: ${LED_BME_SECRET_KEY:jk720-DCPnGq@5t8}
+ mechanism-id: ${LED_BME_MECHANISM_ID:10001}
+ default-ext-user-id: ${LED_BME_DEFAULT_EXT_USER_ID:txzhyy}
+ default-hospital-id: ${LED_BME_DEFAULT_HOSPITAL_ID:}
+ timeout-ms: ${LED_BME_TIMEOUT_MS:10000}
+
# 启用 Knife4j
knife4j:
enable: true